From 43b22a83964cb22d390292e1869acdfe09f13140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Thu, 18 Apr 2024 23:05:54 -0400 Subject: [PATCH 001/248] [cdac] Implement a JSON contract reader (#100966) Implement a parser for the "compact" JSON contract descriptor format specified in [data_contracts.md](https://github.com/dotnet/runtime/blob/main/docs/design/datacontracts/data_descriptor.md) The data model is a WIP - it's likely we will want something a bit more abstract (and less mutable). This is not wired up to consume a real contract descriptor from target process memory at the moment. It's only exercised by unit tests for now. --- * compact descriptor format json parser * suggestions from reviews; remove FieldDescriptor wrong conversion we incorrectly allowed `[number]` as a field descriptor conversion. that's not allowed. removed it. * Make test project like the nativeoat+linker tests Dont' use libraries test infrastructure. Just normal arcade xunit support. * add tools.cdacreadertests subset; add to CLR_Tools_Tests test leg * no duplicate fields/sizes in types * Make all cdacreader.csproj ProjectReferences use the same AdditionalProperties Since we set Configuration and RuntimeIdentifier, if we don't pass the same AdditionalProperties in all ProjectReferences, we bad project.assets.json files * Don't share the native compilation AdditionalProperties --------- Co-authored-by: Aaron Robinson Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> Co-authored-by: Elinor Fung --- eng/Subsets.props | 6 + .../common/evaluate-default-paths.yml | 4 + eng/pipelines/runtime.yml | 3 +- .../src/ContractDescriptorParser.cs | 327 ++++++++++++++++++ .../tests/ContractDescriptorParserTests.cs | 213 ++++++++++++ ...iagnostics.DataContractReader.Tests.csproj | 15 + src/native/managed/compile-native.proj | 15 +- src/native/managed/subproject.props | 13 + 8 files changed, 584 insertions(+), 12 deletions(-) create mode 100644 src/native/managed/cdacreader/src/ContractDescriptorParser.cs create mode 100644 src/native/managed/cdacreader/tests/ContractDescriptorParserTests.cs create mode 100644 src/native/managed/cdacreader/tests/Microsoft.Diagnostics.DataContractReader.Tests.csproj create mode 100644 src/native/managed/subproject.props diff --git a/eng/Subsets.props b/eng/Subsets.props index 499e9c3cb645fe..9de503dd5002f3 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -173,6 +173,8 @@ + + @@ -369,6 +371,10 @@ Test="true" Category="clr" Condition="'$(DotNetBuildSourceOnly)' != 'true' and '$(NativeAotSupported)' == 'true'"/> + + + + diff --git a/eng/pipelines/common/evaluate-default-paths.yml b/eng/pipelines/common/evaluate-default-paths.yml index d954a1ddacbb57..975c18eb69d464 100644 --- a/eng/pipelines/common/evaluate-default-paths.yml +++ b/eng/pipelines/common/evaluate-default-paths.yml @@ -164,6 +164,10 @@ jobs: - src/tools/illink/* - global.json + - subset: tools_cdacreader + include: + - src/native/managed/cdacreader/* + - subset: installer include: exclude: diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index b4ed2afd252d23..f0591ff810c37a 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -713,7 +713,7 @@ extends: jobParameters: timeoutInMinutes: 120 nameSuffix: CLR_Tools_Tests - buildArgs: -s clr.aot+clr.iltools+libs.sfx+clr.toolstests -c $(_BuildConfig) -test + buildArgs: -s clr.aot+clr.iltools+libs.sfx+clr.toolstests+tools.cdacreadertests -c $(_BuildConfig) -test enablePublishTestResults: true testResultsFormat: 'xunit' # We want to run AOT tests when illink changes because there's share code and tests from illink which are used by AOT @@ -721,6 +721,7 @@ extends: or( eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_tools_illink.containsChange'], true), + eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_tools_cdacreader.containsChange'], true), eq(variables['isRollingBuild'], true)) # # Build CrossDacs diff --git a/src/native/managed/cdacreader/src/ContractDescriptorParser.cs b/src/native/managed/cdacreader/src/ContractDescriptorParser.cs new file mode 100644 index 00000000000000..fbf76cd4e8d439 --- /dev/null +++ b/src/native/managed/cdacreader/src/ContractDescriptorParser.cs @@ -0,0 +1,327 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.Diagnostics.DataContractReader; + +/// +/// A parser for the JSON representation of a contract descriptor. +/// +/// +/// See design doc for the format. +/// +public partial class ContractDescriptorParser +{ + // data_descriptor.md uses a distinguished property name to indicate the size of a type + public const string TypeDescriptorSizeSigil = "!"; + + /// + /// Parses the "compact" representation of a contract descriptor. + /// + public static ContractDescriptor? ParseCompact(ReadOnlySpan json) + { + return JsonSerializer.Deserialize(json, ContractDescriptorContext.Default.ContractDescriptor); + } + + [JsonSerializable(typeof(ContractDescriptor))] + [JsonSerializable(typeof(int))] + [JsonSerializable(typeof(string))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(TypeDescriptor))] + [JsonSerializable(typeof(FieldDescriptor))] + [JsonSerializable(typeof(GlobalDescriptor))] + [JsonSourceGenerationOptions(AllowTrailingCommas = true, + DictionaryKeyPolicy = JsonKnownNamingPolicy.Unspecified, // contracts, types and globals are case sensitive + PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, + NumberHandling = JsonNumberHandling.AllowReadingFromString, + ReadCommentHandling = JsonCommentHandling.Skip)] + internal sealed partial class ContractDescriptorContext : JsonSerializerContext + { + } + + public class ContractDescriptor + { + public int? Version { get; set; } + public string? Baseline { get; set; } + public Dictionary? Contracts { get; set; } + + public Dictionary? Types { get; set; } + + public Dictionary? Globals { get; set; } + + [JsonExtensionData] + public Dictionary? Extras { get; set; } + } + + [JsonConverter(typeof(TypeDescriptorConverter))] + public class TypeDescriptor + { + public uint? Size { get; set; } + public Dictionary? Fields { get; set; } + } + + [JsonConverter(typeof(FieldDescriptorConverter))] + public class FieldDescriptor + { + public string? Type { get; set; } + public int Offset { get; set; } + } + + [JsonConverter(typeof(GlobalDescriptorConverter))] + public class GlobalDescriptor + { + public string? Type { get; set; } + public ulong Value { get; set; } + public bool Indirect { get; set; } + } + + internal sealed class TypeDescriptorConverter : JsonConverter + { + // Almost a normal dictionary converter except: + // 1. looks for a special key "!" to set the Size property + // 2. field names are property names, but treated case-sensitively + public override TypeDescriptor Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType != JsonTokenType.StartObject) + throw new JsonException(); + uint? size = null; + Dictionary? fields = new(); + while (reader.Read()) + { + switch (reader.TokenType) + { + case JsonTokenType.EndObject: + return new TypeDescriptor { Size = size, Fields = fields }; + case JsonTokenType.PropertyName: + string? fieldNameOrSizeSigil = reader.GetString(); + reader.Read(); // read the next value: either a number or a field descriptor + if (fieldNameOrSizeSigil == TypeDescriptorSizeSigil) + { + uint newSize = reader.GetUInt32(); + if (size is not null) + { + throw new JsonException($"Size specified multiple times: {size} and {newSize}"); + } + size = newSize; + } + else + { + string? fieldName = fieldNameOrSizeSigil; + var field = JsonSerializer.Deserialize(ref reader, ContractDescriptorContext.Default.FieldDescriptor); + if (fieldName is null || field is null) + throw new JsonException(); + if (!fields.TryAdd(fieldName, field)) + { + throw new JsonException($"Duplicate field name: {fieldName}"); + } + } + break; + case JsonTokenType.Comment: + // unexpected - we specified to skip comments. but let's ignore anyway + break; + default: + throw new JsonException(); + } + } + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, TypeDescriptor value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + } + + internal sealed class FieldDescriptorConverter : JsonConverter + { + // Compact Field descriptors are either a number or a two element array + // 1. number - no type, offset is given as the number + // 2. [number, string] - offset is given as the number, type name is given as the string + public override FieldDescriptor Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (TryGetInt32FromToken(ref reader, out int offset)) + return new FieldDescriptor { Offset = offset }; + if (reader.TokenType != JsonTokenType.StartArray) + throw new JsonException(); + reader.Read(); + // [number, string] + // ^ we're here + if (!TryGetInt32FromToken(ref reader, out offset)) + throw new JsonException(); + reader.Read(); // string + if (reader.TokenType != JsonTokenType.String) + throw new JsonException(); + string? type = reader.GetString(); + reader.Read(); // end of array + if (reader.TokenType != JsonTokenType.EndArray) + throw new JsonException(); + return new FieldDescriptor { Type = type, Offset = offset }; + } + + public override void Write(Utf8JsonWriter writer, FieldDescriptor value, JsonSerializerOptions options) + { + throw new JsonException(); + } + } + + internal sealed class GlobalDescriptorConverter : JsonConverter + { + public override GlobalDescriptor Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + // four cases: + // 1. number - no type, direct value, given value + // 2. [number] - no type, indirect value, given aux data ptr + // 3. [number, string] - type, direct value, given value + // 4. [[number], string] - type, indirect value, given aux data ptr + + // Case 1: number + if (TryGetUInt64FromToken(ref reader, out ulong valueCase1)) + return new GlobalDescriptor { Value = valueCase1 }; + if (reader.TokenType != JsonTokenType.StartArray) + throw new JsonException(); + reader.Read(); + // we're in case 2 or 3 or 4: + // case 2: [number] + // ^ we're here + // case 3: [number, string] + // ^ we're here + // case 4: [[number], string] + // ^ we're here + if (TryGetUInt64FromToken(ref reader, out ulong valueCase2or3)) + { + // case 2 or 3 + // case 2: [number] + // ^ we're here + // case 3: [number, string] + // ^ we're here + reader.Read(); // end of array (case 2) or string (case 3) + if (reader.TokenType == JsonTokenType.EndArray) // it was case 2 + { + return new GlobalDescriptor { Value = valueCase2or3, Indirect = true }; + } + if (reader.TokenType == JsonTokenType.String) // it was case 3 + { + string? type = reader.GetString(); + reader.Read(); // end of array for case 3 + if (reader.TokenType != JsonTokenType.EndArray) + throw new JsonException(); + return new GlobalDescriptor { Type = type, Value = valueCase2or3 }; + } + throw new JsonException(); + } + if (reader.TokenType == JsonTokenType.StartArray) + { + // case 4: [[number], string] + // ^ we're here + reader.Read(); // number + if (!TryGetUInt64FromToken(ref reader, out ulong value)) + throw new JsonException(); + reader.Read(); // end of inner array + if (reader.TokenType != JsonTokenType.EndArray) + throw new JsonException(); + reader.Read(); // string + if (reader.TokenType != JsonTokenType.String) + throw new JsonException(); + string? type = reader.GetString(); + reader.Read(); // end of outer array + if (reader.TokenType != JsonTokenType.EndArray) + throw new JsonException(); + return new GlobalDescriptor { Type = type, Value = value, Indirect = true }; + } + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, GlobalDescriptor value, JsonSerializerOptions options) + { + throw new JsonException(); + } + } + + // Somewhat flexible parsing of numbers, allowing json number tokens or strings as decimal or hex, possibly negatated. + private static bool TryGetUInt64FromToken(ref Utf8JsonReader reader, out ulong value) + { + if (reader.TokenType == JsonTokenType.Number) + { + if (reader.TryGetUInt64(out value)) + return true; + if (reader.TryGetInt64(out long signedValue)) + { + value = (ulong)signedValue; + return true; + } + } + if (reader.TokenType == JsonTokenType.String) + { + var s = reader.GetString(); + if (s == null) + { + value = 0u; + return false; + } + if (ulong.TryParse(s, out value)) + return true; + if (long.TryParse(s, out long signedValue)) + { + value = (ulong)signedValue; + return true; + } + if (s.StartsWith("0x", StringComparison.OrdinalIgnoreCase) && + ulong.TryParse(s.AsSpan(2), System.Globalization.NumberStyles.HexNumber, null, out value)) + { + return true; + } + if (s.StartsWith("-0x", StringComparison.OrdinalIgnoreCase) && + ulong.TryParse(s.AsSpan(3), System.Globalization.NumberStyles.HexNumber, null, out ulong negValue)) + { + value = ~negValue + 1; // two's complement + return true; + } + } + value = 0; + return false; + } + + // Somewhat flexible parsing of numbers, allowing json number tokens or strings as either decimal or hex, possibly negated + private static bool TryGetInt32FromToken(ref Utf8JsonReader reader, out int value) + { + if (reader.TokenType == JsonTokenType.Number) + { + value = reader.GetInt32(); + return true; + } + if (reader.TokenType == JsonTokenType.String) + { + var s = reader.GetString(); + if (s == null) + { + value = 0; + return false; + } + if (int.TryParse(s, out value)) + { + return true; + } + if (s.StartsWith("0x", StringComparison.OrdinalIgnoreCase) && + int.TryParse(s.AsSpan(2), System.Globalization.NumberStyles.HexNumber, null, out value)) + { + return true; + } + if (s.StartsWith("-0x", StringComparison.OrdinalIgnoreCase) && + int.TryParse(s.AsSpan(3), System.Globalization.NumberStyles.HexNumber, null, out int negValue)) + { + value = -negValue; + return true; + } + } + value = 0; + return false; + } +} diff --git a/src/native/managed/cdacreader/tests/ContractDescriptorParserTests.cs b/src/native/managed/cdacreader/tests/ContractDescriptorParserTests.cs new file mode 100644 index 00000000000000..eca740870727bb --- /dev/null +++ b/src/native/managed/cdacreader/tests/ContractDescriptorParserTests.cs @@ -0,0 +1,213 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Text.Unicode; +using Xunit; + +namespace Microsoft.Diagnostics.DataContractReader.UnitTests; + +public class ContractDescriptorParserTests +{ + [Fact] + public void ParsesEmptyContract() + { + ReadOnlySpan json = "{}"u8; + ContractDescriptorParser.ContractDescriptor descriptor = ContractDescriptorParser.ParseCompact(json); + Assert.Null(descriptor.Version); + Assert.Null(descriptor.Baseline); + Assert.Null(descriptor.Contracts); + Assert.Null(descriptor.Types); + Assert.Null(descriptor.Extras); + } + [Fact] + public void ParsesTrivialContract() + { + ReadOnlySpan json = """ + { + "version": 0, + "baseline": "empty", + "contracts": {}, + "types": {}, + "globals": {} + } + """u8; + ContractDescriptorParser.ContractDescriptor descriptor = ContractDescriptorParser.ParseCompact(json); + Assert.Equal(0, descriptor.Version); + Assert.Equal("empty", descriptor.Baseline); + Assert.Empty(descriptor.Contracts); + Assert.Empty(descriptor.Types); + Assert.Empty(descriptor.Globals); + Assert.Null(descriptor.Extras); + } + + [Fact] + public void ParseSizedTypes() + { + ReadOnlySpan json = """ + { + "version": 0, + "baseline": "empty", + "contracts": {}, + "types": + { + "pointer": { "!" : 8}, + "int": { "!" : 4}, + "Point": { + "x": [ 4, "int"], + "y": 8, + "!": 12 + }, + "Point3D": { // no size + "r": [ 0, "double"], + "phi": 8, + "rho": 16 + } + }, + "globals": {} + } + """u8; + ContractDescriptorParser.ContractDescriptor descriptor = ContractDescriptorParser.ParseCompact(json); + Assert.Equal(0, descriptor.Version); + Assert.Equal("empty", descriptor.Baseline); + Assert.Empty(descriptor.Contracts); + Assert.Empty(descriptor.Globals); + Assert.Equal(4, descriptor.Types.Count); + Assert.Equal(8u, descriptor.Types["pointer"].Size); + Assert.Equal(4u, descriptor.Types["int"].Size); + Assert.Equal(2, descriptor.Types["Point"].Fields.Count); + Assert.Equal(4, descriptor.Types["Point"].Fields["x"].Offset); + Assert.Equal(8, descriptor.Types["Point"].Fields["y"].Offset); + Assert.Equal("int", descriptor.Types["Point"].Fields["x"].Type); + Assert.Null(descriptor.Types["Point"].Fields["y"].Type); + Assert.Equal(12u, descriptor.Types["Point"].Size); + Assert.Equal(3, descriptor.Types["Point3D"].Fields.Count); + Assert.Equal(0, descriptor.Types["Point3D"].Fields["r"].Offset); + Assert.Equal(8, descriptor.Types["Point3D"].Fields["phi"].Offset); + Assert.Equal(16, descriptor.Types["Point3D"].Fields["rho"].Offset); + Assert.Equal("double", descriptor.Types["Point3D"].Fields["r"].Type); + Assert.Null(descriptor.Types["Point3D"].Fields["phi"].Type); + Assert.Null(descriptor.Types["Point3D"].Size); + } + + [Fact] + public void ParseContractsCaseSensitive() + { + ReadOnlySpan json = """ + { + "version": 0, + "baseline": "empty", + "contracts": { + "foo": 1, + "Foo": 2 + }, + "types": {}, + "globals": {} + } + """u8; + ContractDescriptorParser.ContractDescriptor descriptor = ContractDescriptorParser.ParseCompact(json); + Assert.Equal(0, descriptor.Version); + Assert.Equal("empty", descriptor.Baseline); + Assert.Equal(2, descriptor.Contracts.Count); + Assert.Equal(1, descriptor.Contracts["foo"]); + Assert.Equal(2, descriptor.Contracts["Foo"]); + } + + [Fact] + public void ParsesGlobals() + { + ReadOnlySpan json = """ + { + "version": 0, + "baseline": "empty", + "contracts": {}, + "types": {}, + "globals": { + "globalInt": 1, + "globalPtr": [2], + "globalTypedInt": [3, "uint8"], + "globalTypedPtr": [[4], "uintptr"], + "globalHex": "0x1234", + "globalNegative": -2, + "globalStringyInt": "17", + "globalStringyNegative": "-2", + "globalNegativeHex": "-0xff", + "globalBigStringyInt": "0x123456789abcdef", + "globalStringyPtr": ["0x1234"], + "globalTypedStringyInt": ["0x1234", "int"], + "globalTypedStringyPtr": [["0x1234"], "int"] + } + } + """u8; + ContractDescriptorParser.ContractDescriptor descriptor = ContractDescriptorParser.ParseCompact(json); + Assert.Equal(0, descriptor.Version); + Assert.Equal("empty", descriptor.Baseline); + Assert.Empty(descriptor.Contracts); + Assert.Empty(descriptor.Types); + Assert.Equal(13, descriptor.Globals.Count); + Assert.Equal((ulong)1, descriptor.Globals["globalInt"].Value); + Assert.False(descriptor.Globals["globalInt"].Indirect); + Assert.Equal((ulong)2, descriptor.Globals["globalPtr"].Value); + Assert.True(descriptor.Globals["globalPtr"].Indirect); + Assert.Equal((ulong)3, descriptor.Globals["globalTypedInt"].Value); + Assert.False(descriptor.Globals["globalTypedInt"].Indirect); + Assert.Equal("uint8", descriptor.Globals["globalTypedInt"].Type); + Assert.Equal((ulong)4, descriptor.Globals["globalTypedPtr"].Value); + Assert.True(descriptor.Globals["globalTypedPtr"].Indirect); + Assert.Equal("uintptr", descriptor.Globals["globalTypedPtr"].Type); + Assert.Equal((ulong)0x1234, descriptor.Globals["globalHex"].Value); + Assert.False(descriptor.Globals["globalHex"].Indirect); + Assert.Equal((ulong)0xfffffffffffffffe, descriptor.Globals["globalNegative"].Value); + Assert.False(descriptor.Globals["globalNegative"].Indirect); + Assert.Equal((ulong)17, descriptor.Globals["globalStringyInt"].Value); + Assert.False(descriptor.Globals["globalStringyInt"].Indirect); + Assert.Equal((ulong)0xfffffffffffffffe, descriptor.Globals["globalStringyNegative"].Value); + Assert.False(descriptor.Globals["globalStringyNegative"].Indirect); + Assert.Equal((ulong)0xffffffffffffff01, descriptor.Globals["globalNegativeHex"].Value); + Assert.False(descriptor.Globals["globalNegativeHex"].Indirect); + Assert.Equal((ulong)0x123456789abcdef, descriptor.Globals["globalBigStringyInt"].Value); + Assert.False(descriptor.Globals["globalBigStringyInt"].Indirect); + Assert.Equal((ulong)0x1234, descriptor.Globals["globalStringyPtr"].Value); + Assert.True(descriptor.Globals["globalStringyPtr"].Indirect); + Assert.Equal("int", descriptor.Globals["globalTypedStringyInt"].Type); + Assert.Equal((ulong)0x1234, descriptor.Globals["globalTypedStringyInt"].Value); + Assert.False(descriptor.Globals["globalTypedStringyInt"].Indirect); + Assert.Equal("int", descriptor.Globals["globalTypedStringyPtr"].Type); + Assert.Equal((ulong)0x1234, descriptor.Globals["globalTypedStringyPtr"].Value); + Assert.True(descriptor.Globals["globalTypedStringyPtr"].Indirect); + } + + [Fact] + void ParsesExoticOffsets() + { + ReadOnlySpan json = """ + { + "version": 0, + "baseline": "empty", + "contracts": {}, + "types": { + "OddStruct": { + "a": -12, + "b": "0x12", + "c": "-0x12", + "d": ["0x100", "int"] + } + }, + "globals": { + } + } + """u8; + ContractDescriptorParser.ContractDescriptor descriptor = ContractDescriptorParser.ParseCompact(json); + Assert.Equal(0, descriptor.Version); + Assert.Equal("empty", descriptor.Baseline); + Assert.Empty(descriptor.Contracts); + Assert.Empty(descriptor.Globals); + Assert.Equal(1, descriptor.Types.Count); + Assert.Equal(4, descriptor.Types["OddStruct"].Fields.Count); + Assert.Equal(-12, descriptor.Types["OddStruct"].Fields["a"].Offset); + Assert.Equal(0x12, descriptor.Types["OddStruct"].Fields["b"].Offset); + Assert.Equal(-0x12, descriptor.Types["OddStruct"].Fields["c"].Offset); + Assert.Equal(0x100, descriptor.Types["OddStruct"].Fields["d"].Offset); + Assert.Equal("int", descriptor.Types["OddStruct"].Fields["d"].Type); + } +} diff --git a/src/native/managed/cdacreader/tests/Microsoft.Diagnostics.DataContractReader.Tests.csproj b/src/native/managed/cdacreader/tests/Microsoft.Diagnostics.DataContractReader.Tests.csproj new file mode 100644 index 00000000000000..22e8d256e01df1 --- /dev/null +++ b/src/native/managed/cdacreader/tests/Microsoft.Diagnostics.DataContractReader.Tests.csproj @@ -0,0 +1,15 @@ + + + true + $(NetCoreAppToolCurrent) + + + + + + + + + + diff --git a/src/native/managed/compile-native.proj b/src/native/managed/compile-native.proj index d227466bfcebd1..bcda8c5d6b57b5 100644 --- a/src/native/managed/compile-native.proj +++ b/src/native/managed/compile-native.proj @@ -35,24 +35,17 @@ --gcc-toolchain=$(ROOTFS_DIR)/usr - - - - - - - + + - - @(SubprojectProps->'%(Identity)=%(Value)', ';') - - + + + + + + + + + + + + @(SubprojectProps->'%(Identity)=%(Value)', ';') + + From 4abe399e564c5aeabe7ff8899080170d8c037497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Thu, 18 Apr 2024 23:13:22 -0400 Subject: [PATCH 002/248] [cdac] cdac-build-tool (#100650) # cDAC Build Tool ## Summary The purpose of `cdac-build-tool` is to generate a `.c` file that contains a JSON cDAC contract descriptor. It works by processing one or more object files containing data descriptors and zero or more text files that specify contracts. ## Running ```console % cdac-build-tool compose [-v] -o contractdescriptor.c -c contracts.txt datadescriptor.o ``` ## .NET runtime build integration `cdac-build-tool` is meant to run as a CMake custom command. It consumes a target platform object file and emits a C source file that contains a JSON contract descriptor. The C source is the included in the normal build and link steps to create the runtime. The contract descriptor source file depends on `contract-aux-data.c` which is a source file that contains the definitions of the "indirect pointer data" that is referenced by the data descriptor. This is typically the addresses of important global variables in the runtime. Constants and build flags are embedded directly in the JSON payload. Multiple data descriptor source files may be specified (for example if they are produced by different components of the runtime, or by different source languages). The final JSON payload will be a composition of all the data descriptors. Multiple contracts text files may be specified. This may be useful if some contracts are conditionally included (for example if they are platform-specific). The final JSON payload will be a composition of all the contracts files. ```mermaid flowchart TB headers("runtime headers") data_header("datadescriptor.h") data_src("datadescriptor.c") compile_data["clang"] data_obj("datadescriptor.o") contracts("contracts.txt") globals("contractpointerdata.c") build[["cdac-build-tool"]] descriptor_src("contractdescriptor.c") vm("runtime sources") compile_runtime["clang"] runtime_lib(["libcoreclr.so"]) headers -.-> data_src headers ~~~ data_header data_header -.-> data_src headers -.-> globals headers -.-> vm data_src --> compile_data --> data_obj --> build contracts ---> build build --> descriptor_src descriptor_src --> compile_runtime data_header -.-> globals ----> compile_runtime vm ----> compile_runtime --> runtime_lib ``` --- * add implementation note notes * add an emitter * read in the directory header * contract parsing * indirect pointer value support * move sample to tool dir * Take baselines from the docs/design/datacontracts/data dir We don't parse them yet, however * Add README * fix BE Store the magic as a uint64_t so that it will follow the platform endianness. Store endmagic as bytes so that it directly follows the name pool - and fix the endmagic check not to look at the endianness * hook up cdac-build-tool to the coreclr build; export DotNetRuntimeContractDescriptor * cleanup; add contracts.txt * add diagram to README * move implementation notes * better verbose output from ObjectFileScraper * turn off whole program optimizations for data-descriptor.obj On windows /GL creates object files that cdac-build-tool cannot read It's ok to do this because we don't ship data-descriptor.obj as part of the product - it's only used to generate the cDAC descriptor * C++-ify and add real Thread offsets * no C99 designated initializers in C++ until C++20 * build data descriptor after core runtime * fix gcc build * simplify ObjectFileScraper just read the whole file into memory * invoke 'dotnet cmake-build-tool.dll' instead of 'dotnet run --project' * clean up macro boilerplate * platform flags * turn off verbose output * can't use constexpr function in coreclr because debugreturn.h defines a `return` macro that expands to something that is not c++11 constexpr * Rename "aux data" to "pointer data" * rename "data-descriptor" to "datadescriptor" * simplify linking * cdac-build-tool don't build dotnet tool; turn on analyzers * rationalize naming; update docs; add some inline comments * renamce cdac.h to cdacoffsets.h * improve output: hex offsets; improved formatting * don't throw in ParseContracts; add line numbers to errors * change input format for contracts to jsonc * add custom JsonConverter instances for the compact json representation * simplify; bug fix - PointerDataCount include placeholder * one more set of feedback changes: simpler json converters * set _RequiresLiveILLink=false for cdac-build-tool.csproj fixes windows builds: error MSB3026: (NETCORE_ENGINEERING_TELEMETRY=Build) Could not copy "D:\a\_work\1\s\artifacts\obj\ILLink.Tasks\Debug\net9.0\ILLink.Tasks.dll" to "D:\a\_work\1\s\artifacts\bin\ILLink.Tasks\Debug\net9.0\ILLink.Tasks.dll". Beginning retry 1 in 1000ms. The process cannot access the file 'D:\a\_work\1\s\artifacts\bin\ILLink.Tasks\Debug\net9.0\ILLink.Tasks.dll' because it is being used by another process. --------- Co-authored-by: Elinor Fung Co-authored-by: Aaron Robinson --- .../datacontracts/contract-descriptor.md | 4 +- docs/design/datacontracts/data/empty.jsonc | 4 + eng/Subsets.props | 2 + src/coreclr/debug/runtimeinfo/CMakeLists.txt | 43 ++ .../debug/runtimeinfo/contractpointerdata.cpp | 23 + src/coreclr/debug/runtimeinfo/contracts.jsonc | 14 + .../debug/runtimeinfo/datadescriptor.cpp | 297 ++++++++++ .../debug/runtimeinfo/datadescriptor.h | 139 +++++ .../dlls/mscoree/coreclr/CMakeLists.txt | 1 + src/coreclr/dlls/mscoree/mscorwks_ntdef.src | 3 + .../dlls/mscoree/mscorwks_unixexports.src | 3 + src/coreclr/runtime-prereqs.proj | 1 + src/coreclr/runtime.proj | 1 + .../tools/cdac-build-tool/ComposeCommand.cs | 91 +++ .../ContractDescriptorSourceFileEmitter.cs | 81 +++ .../tools/cdac-build-tool/ContractReader.cs | 33 ++ .../cdac-build-tool/DataDescriptorModel.cs | 389 ++++++++++++ .../cdac-build-tool/Directory.Build.props | 7 + .../cdac-build-tool/EmbeddedBaselines.cs | 52 ++ .../JsonConverter/FieldModelJsonConverter.cs | 35 ++ .../JsonConverter/GlobalModelJsonConverter.cs | 32 + .../JsonConverter/GlobalValueJsonConverter.cs | 32 + .../JsonConverter/TypeModelJsonConverter.cs | 32 + .../cdac-build-tool/ObjectFileScraper.cs | 519 ++++++++++++++++ src/coreclr/tools/cdac-build-tool/Program.cs | 20 + src/coreclr/tools/cdac-build-tool/README.md | 134 +++++ .../Resources/contract-descriptor.c.in | 34 ++ .../cdac-build-tool/cdac-build-tool.csproj | 32 + .../cdac-build-tool/data-descriptor-blob.md | 203 +++++++ .../cdac-build-tool/sample/sample.blob.c | 553 ++++++++++++++++++ .../cdac-build-tool/sample/sample.data.h | 24 + src/coreclr/vm/CMakeLists.txt | 1 + src/coreclr/vm/cdacoffsets.h | 24 + src/coreclr/vm/threads.h | 10 + .../apphost/static/singlefilehost.def | 3 + .../static/singlefilehost_freebsdexports.src | 3 + .../static/singlefilehost_unixexports.src | 3 + 37 files changed, 2880 insertions(+), 2 deletions(-) create mode 100644 docs/design/datacontracts/data/empty.jsonc create mode 100644 src/coreclr/debug/runtimeinfo/contractpointerdata.cpp create mode 100644 src/coreclr/debug/runtimeinfo/contracts.jsonc create mode 100644 src/coreclr/debug/runtimeinfo/datadescriptor.cpp create mode 100644 src/coreclr/debug/runtimeinfo/datadescriptor.h create mode 100644 src/coreclr/tools/cdac-build-tool/ComposeCommand.cs create mode 100644 src/coreclr/tools/cdac-build-tool/ContractDescriptorSourceFileEmitter.cs create mode 100644 src/coreclr/tools/cdac-build-tool/ContractReader.cs create mode 100644 src/coreclr/tools/cdac-build-tool/DataDescriptorModel.cs create mode 100644 src/coreclr/tools/cdac-build-tool/Directory.Build.props create mode 100644 src/coreclr/tools/cdac-build-tool/EmbeddedBaselines.cs create mode 100644 src/coreclr/tools/cdac-build-tool/JsonConverter/FieldModelJsonConverter.cs create mode 100644 src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalModelJsonConverter.cs create mode 100644 src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalValueJsonConverter.cs create mode 100644 src/coreclr/tools/cdac-build-tool/JsonConverter/TypeModelJsonConverter.cs create mode 100644 src/coreclr/tools/cdac-build-tool/ObjectFileScraper.cs create mode 100644 src/coreclr/tools/cdac-build-tool/Program.cs create mode 100644 src/coreclr/tools/cdac-build-tool/README.md create mode 100644 src/coreclr/tools/cdac-build-tool/Resources/contract-descriptor.c.in create mode 100644 src/coreclr/tools/cdac-build-tool/cdac-build-tool.csproj create mode 100644 src/coreclr/tools/cdac-build-tool/data-descriptor-blob.md create mode 100644 src/coreclr/tools/cdac-build-tool/sample/sample.blob.c create mode 100644 src/coreclr/tools/cdac-build-tool/sample/sample.data.h create mode 100644 src/coreclr/vm/cdacoffsets.h diff --git a/docs/design/datacontracts/contract-descriptor.md b/docs/design/datacontracts/contract-descriptor.md index 1e3ddabd6dd735..e63ae11b4ae936 100644 --- a/docs/design/datacontracts/contract-descriptor.md +++ b/docs/design/datacontracts/contract-descriptor.md @@ -24,9 +24,9 @@ struct DotNetRuntimeContractDescriptor uint32_t flags; uint32_t descriptor_size; const char *descriptor; - uint32_t aux_data_count; + uint32_t pointer_data_count; uint32_t pad0; - uintptr_t *aux_data; + uintptr_t *pointer_data; }; ``` diff --git a/docs/design/datacontracts/data/empty.jsonc b/docs/design/datacontracts/data/empty.jsonc new file mode 100644 index 00000000000000..29d15882a36b81 --- /dev/null +++ b/docs/design/datacontracts/data/empty.jsonc @@ -0,0 +1,4 @@ +// the empty baseline data descriptor +{ + "version": 0 +} diff --git a/eng/Subsets.props b/eng/Subsets.props index 9de503dd5002f3..0a51b12649d1e8 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -360,6 +360,8 @@ + + diff --git a/src/coreclr/debug/runtimeinfo/CMakeLists.txt b/src/coreclr/debug/runtimeinfo/CMakeLists.txt index e6d45ada120131..2a4cfc2dca3ff5 100644 --- a/src/coreclr/debug/runtimeinfo/CMakeLists.txt +++ b/src/coreclr/debug/runtimeinfo/CMakeLists.txt @@ -37,3 +37,46 @@ endif() # publish runtimeinfo lib install_clr(TARGETS runtimeinfo DESTINATIONS lib COMPONENT runtime) + +add_library(cdac_data_descriptor OBJECT datadescriptor.cpp) +# don't build the data descriptor before the VM (and any of its dependencies' generated headers) +add_dependencies(cdac_data_descriptor cee_wks_core) +if(CLR_CMAKE_TARGET_WIN32) + # turn off whole program optimization: + # 1. it creates object files that cdac-build-tool can't read + # 2. we never link cdac_data_descriptor into the final product - it's only job is to be scraped + target_compile_options(cdac_data_descriptor PRIVATE /GL-) +endif() +target_include_directories(cdac_data_descriptor BEFORE PRIVATE ${VM_DIR}) +target_include_directories(cdac_data_descriptor BEFORE PRIVATE ${VM_DIR}/${ARCH_SOURCES_DIR}) +target_include_directories(cdac_data_descriptor PRIVATE ${CLR_DIR}/interop/inc) + +set(GENERATED_CDAC_DESCRIPTOR_DIR "${CMAKE_CURRENT_BINARY_DIR}/cdac") +set(CONTRACT_DESCRIPTOR_OUTPUT "${GENERATED_CDAC_DESCRIPTOR_DIR}/contract-descriptor.c") +if("${CDAC_BUILD_TOOL_BINARY_PATH}" STREQUAL "" OR NOT EXISTS "${CDAC_BUILD_TOOL_BINARY_PATH}") + message(FATAL_ERROR "No cdac-build-tool set or ${CDAC_BUILD_TOOL_BINARY_PATH} does not exist") +endif() + +set(CONTRACT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/contracts.jsonc") + +# generate the contract descriptor by running cdac-build-tool +# n.b. this just uses `dotnet` from the PATH. InitializeDotNetCli adds the apropropriate directory +add_custom_command( + OUTPUT "${CONTRACT_DESCRIPTOR_OUTPUT}" + VERBATIM + COMMAND dotnet ${CDAC_BUILD_TOOL_BINARY_PATH} compose -o "${CONTRACT_DESCRIPTOR_OUTPUT}" -c "${CONTRACT_FILE}" $ + DEPENDS cdac_data_descriptor cee_wks_core $ "${CONTRACT_FILE}" + USES_TERMINAL +) + +# It is important that cdac_contract_descriptor is an object library; +# if it was static, linking it into the final dll would not export +# DotNetRuntimeContractDescriptor since it is not referenced anywhere. +add_library_clr(cdac_contract_descriptor OBJECT + "${CONTRACT_DESCRIPTOR_OUTPUT}" + contractpointerdata.cpp +) +target_include_directories(cdac_contract_descriptor BEFORE PRIVATE ${VM_DIR}) +target_include_directories(cdac_contract_descriptor BEFORE PRIVATE ${VM_DIR}/${ARCH_SOURCES_DIR}) +target_include_directories(cdac_contract_descriptor PRIVATE ${CLR_DIR}/interop/inc) +add_dependencies(cdac_contract_descriptor cdac_data_descriptor cee_wks_core) diff --git a/src/coreclr/debug/runtimeinfo/contractpointerdata.cpp b/src/coreclr/debug/runtimeinfo/contractpointerdata.cpp new file mode 100644 index 00000000000000..ae1440af4219a2 --- /dev/null +++ b/src/coreclr/debug/runtimeinfo/contractpointerdata.cpp @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "common.h" + +#include +#include + +#include "threads.h" + +extern "C" +{ + +// without an extern declaration, clang does not emit this global into the object file +extern const uintptr_t contractDescriptorPointerData[]; + +const uintptr_t contractDescriptorPointerData[] = { + (uintptr_t)0, // placeholder +#define CDAC_GLOBAL_POINTER(name,value) (uintptr_t)(value), +#include "datadescriptor.h" +}; + +} diff --git a/src/coreclr/debug/runtimeinfo/contracts.jsonc b/src/coreclr/debug/runtimeinfo/contracts.jsonc new file mode 100644 index 00000000000000..186230d5c68d6f --- /dev/null +++ b/src/coreclr/debug/runtimeinfo/contracts.jsonc @@ -0,0 +1,14 @@ +//algorithmic contracts for coreclr +// The format of this file is: JSON with comments +// { +// "CONTRACT NAME": VERSION, +// ... +// } +// CONTRACT NAME is an arbitrary string, VERSION is an integer +// +// cdac-build-tool can take multiple "-c contract_file" arguments +// so to conditionally include contracts, put additional contracts in a separate file +{ + "SOSBreakingChangeVersion": 1 // example contract: "runtime exports an SOS breaking change version global" +} + diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.cpp b/src/coreclr/debug/runtimeinfo/datadescriptor.cpp new file mode 100644 index 00000000000000..99fe1cca7eeca7 --- /dev/null +++ b/src/coreclr/debug/runtimeinfo/datadescriptor.cpp @@ -0,0 +1,297 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "common.h" + +#include +#include + +#include "static_assert.h" + +#include +#include "threads.h" + +// begin blob definition + +extern "C" +{ + +struct TypeSpec +{ + uint32_t Name; + uint32_t Fields; + uint16_t Size; // note: C++ fragile no designated initializers - Size must come after Name and Fields +}; + +struct FieldSpec +{ + uint32_t Name; + uint32_t TypeName; + uint16_t FieldOffset; +}; + +struct GlobalLiteralSpec +{ + uint32_t Name; + uint32_t TypeName; + uint64_t Value; +}; + +struct GlobalPointerSpec +{ + uint32_t Name; + uint32_t PointerDataIndex; +}; + +#define CONCAT(token1,token2) token1 ## token2 +#define CONCAT4(token1, token2, token3, token4) token1 ## token2 ## token3 ## token4 + +#define MAKE_TYPELEN_NAME(tyname) CONCAT(cdac_string_pool_typename__, tyname) +#define MAKE_FIELDLEN_NAME(tyname,membername) CONCAT4(cdac_string_pool_membername__, tyname, __, membername) +#define MAKE_FIELDTYPELEN_NAME(tyname,membername) CONCAT4(cdac_string_pool_membertypename__, tyname, __, membername) +#define MAKE_GLOBALLEN_NAME(globalname) CONCAT(cdac_string_pool_globalname__, globalname) +#define MAKE_GLOBALTYPELEN_NAME(globalname) CONCAT(cdac_string_pool_globaltypename__, globalname) + +// define a struct where the size of each field is the length of some string. we will use offsetof to get +// the offset of each struct element, which will be equal to the offset of the beginning of that string in the +// string pool. +struct CDacStringPoolSizes +{ + char cdac_string_pool_nil; // make the first real string start at offset 1 +#define DECL_LEN(membername,len) char membername[(len)]; +#define CDAC_BASELINE(name) DECL_LEN(cdac_string_pool_baseline_, (sizeof(name))) +#define CDAC_TYPE_BEGIN(name) DECL_LEN(MAKE_TYPELEN_NAME(name), sizeof(#name)) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) DECL_LEN(MAKE_FIELDLEN_NAME(tyname,membername), sizeof(#membername)) \ + DECL_LEN(MAKE_FIELDTYPELEN_NAME(tyname,membername), sizeof(#membertyname)) +#define CDAC_GLOBAL_POINTER(name,value) DECL_LEN(MAKE_GLOBALLEN_NAME(name), sizeof(#name)) +#define CDAC_GLOBAL(name,tyname,value) DECL_LEN(MAKE_GLOBALLEN_NAME(name), sizeof(#name)) \ + DECL_LEN(MAKE_GLOBALTYPELEN_NAME(name), sizeof(#tyname)) +#include "datadescriptor.h" + char cdac_string_pool_trailing_nil; +#undef DECL_LEN +}; + +#define GET_TYPE_NAME(name) offsetof(struct CDacStringPoolSizes, MAKE_TYPELEN_NAME(name)) +#define GET_FIELD_NAME(tyname,membername) offsetof(struct CDacStringPoolSizes, MAKE_FIELDLEN_NAME(tyname,membername)) +#define GET_FIELDTYPE_NAME(tyname,membername) offsetof(struct CDacStringPoolSizes, MAKE_FIELDTYPELEN_NAME(tyname,membername)) +#define GET_GLOBAL_NAME(globalname) offsetof(struct CDacStringPoolSizes, MAKE_GLOBALLEN_NAME(globalname)) +#define GET_GLOBALTYPE_NAME(globalname) offsetof(struct CDacStringPoolSizes, MAKE_GLOBALTYPELEN_NAME(globalname)) + +// count the types +enum +{ + CDacBlobTypesCount = +#define CDAC_TYPES_BEGIN() 0 +#define CDAC_TYPE_BEGIN(name) + 1 +#include "datadescriptor.h" +}; + +// count the field pool size. +// there's 1 placeholder element at the start, and 1 endmarker after each type +enum +{ + CDacBlobFieldsPoolCount = +#define CDAC_TYPES_BEGIN() 1 +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) + 1 +#define CDAC_TYPE_END(name) + 1 +#include "datadescriptor.h" +}; + +// count the literal globals +enum +{ + CDacBlobGlobalLiteralsCount = +#define CDAC_GLOBALS_BEGIN() 0 +#define CDAC_GLOBAL(name,tyname,value) + 1 +#include "datadescriptor.h" +}; + +// count the aux vector globals +enum +{ + CDacBlobGlobalPointersCount = +#define CDAC_GLOBALS_BEGIN() 0 +#define CDAC_GLOBAL_POINTER(name,value) + 1 +#include "datadescriptor.h" +}; + + +#define MAKE_TYPEFIELDS_TYNAME(tyname) CONCAT(CDacFieldsPoolTypeStart__, tyname) + +// index of each run of fields. +// we make a struct containing one 1-byte field for each field in the run, and then take the offset of the +// struct to get the index of the run of fields. +// this looks like +// +// struct CDacFieldsPoolSizes { +// char cdac_fields_pool_start_placeholder__; +// struct CDacFieldsPoolTypeStart__MethodTable { +// char cdac_fields_pool_member__MethodTable__GCHandle; +// char cdac_fields_pool_member__MethodTable_endmarker; +// } CDacFieldsPoolTypeStart__MethodTable; +// ... +// }; +// +// so that offsetof(struct CDacFieldsPoolSizes, CDacFieldsPoolTypeStart__MethodTable) will give the offset of the +// method table field descriptors in the run of fields +struct CDacFieldsPoolSizes +{ +#define DECL_LEN(membername) char membername; +#define CDAC_TYPES_BEGIN() DECL_LEN(cdac_fields_pool_start_placeholder__) +#define CDAC_TYPE_BEGIN(name) struct MAKE_TYPEFIELDS_TYNAME(name) { +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) DECL_LEN(CONCAT4(cdac_fields_pool_member__, tyname, __, membername)) +#define CDAC_TYPE_END(name) DECL_LEN(CONCAT4(cdac_fields_pool_member__, tyname, _, endmarker)) \ + } MAKE_TYPEFIELDS_TYNAME(name); +#include "datadescriptor.h" +#undef DECL_LEN +}; + +#define GET_TYPE_FIELDS(tyname) offsetof(struct CDacFieldsPoolSizes, MAKE_TYPEFIELDS_TYNAME(tyname)) + +// index of each global pointer +// +// struct CDacGlobalPointerIndex +// { +// char placeholder; +// char firstGlobalPointerName; +// char secondGlobalPointerName; +// ... +//} +// +// offsetof (CDACGlobalPointerIndex, NAME) returns the index of the global +struct CDacGlobalPointerIndex +{ +#define DECL_LEN(membername) char membername; +#define CDAC_GLOBALS_BEGIN() DECL_LEN(cdac_global_pointer_index_start_placeholder__) +#define CDAC_GLOBAL_POINTER(name,value) DECL_LEN(CONCAT(cdac_global_pointer_index__, name)) +#include "datadescriptor.h" +#undef DECL_LEN +}; + +#define GET_GLOBAL_POINTER_INDEX(name) offsetof(struct CDacGlobalPointerIndex, CONCAT(cdac_global_pointer_index__, name)) + +struct BinaryBlobDataDescriptor +{ + // The blob begins with a directory that gives the relative offsets of the `Baseline`, `Types`, + // `FieldsPool`, `GlobalLiteralValues`, `GlobalPointerValues` and `Names` fields of the blob. + // The number of elements of each of the arrays is next. This is followed by the sizes of the + // spec structs. Since `BinaryBlobDataDescriptor` is created via macros, we want to embed the + // `offsetof` and `sizeof` of the components of the blob into the blob itself without having to + // account for any padding that the C/C++ compiler may introduce to enforce alignment. + // Additionally the `Directory` tries to follow a common C/C++ alignment rule (we don't want + // padding introduced in the directory itself): N-byte members are aligned to start on N-byte + // boundaries. + struct Directory { + uint32_t FlagsAndBaselineStart; + uint32_t TypesStart; + + uint32_t FieldsPoolStart; + uint32_t GlobalLiteralValuesStart; + + uint32_t GlobalPointersStart; + uint32_t NamesPoolStart; + + uint32_t TypeCount; + uint32_t FieldsPoolCount; + + uint32_t GlobalLiteralValuesCount; + uint32_t GlobalPointerValuesCount; + + uint32_t NamesPoolCount; + + uint8_t TypeSpecSize; + uint8_t FieldSpecSize; + uint8_t GlobalLiteralSpecSize; + uint8_t GlobalPointerSpecSize; + } Directory; + uint32_t PlatformFlags; + uint32_t BaselineName; + struct TypeSpec Types[CDacBlobTypesCount]; + struct FieldSpec FieldsPool[CDacBlobFieldsPoolCount]; + struct GlobalLiteralSpec GlobalLiteralValues[CDacBlobGlobalLiteralsCount]; + struct GlobalPointerSpec GlobalPointerValues[CDacBlobGlobalPointersCount]; + uint8_t NamesPool[sizeof(struct CDacStringPoolSizes)]; + uint8_t EndMagic[4]; +}; + +struct MagicAndBlob { + uint64_t magic; + struct BinaryBlobDataDescriptor Blob; +}; + +// we only support 32-bit and 64-bit right now +static_assert_no_msg(sizeof(void*) == 4 || sizeof(void*) == 8); + +// C-style designated initializers are a C++20 feature. Have to use plain old aggregate initialization instead. + +DLLEXPORT +struct MagicAndBlob BlobDataDescriptor = { + /*.magic = */ 0x00424F4C42434144ull,// "DACBLOB", + /*.Blob =*/ { + /*.Directory =*/ { + /* .FlagsAndBaselineStart = */ offsetof(struct BinaryBlobDataDescriptor, PlatformFlags), + /* .TypesStart = */ offsetof(struct BinaryBlobDataDescriptor, Types), + /* .FieldsPoolStart = */ offsetof(struct BinaryBlobDataDescriptor, FieldsPool), + /* .GlobalLiteralValuesStart = */ offsetof(struct BinaryBlobDataDescriptor, GlobalLiteralValues), + /* .GlobalPointersStart = */ offsetof(struct BinaryBlobDataDescriptor, GlobalPointerValues), + /* .NamesPoolStart = */ offsetof(struct BinaryBlobDataDescriptor, NamesPool), + /* .TypeCount = */ CDacBlobTypesCount, + /* .FieldsPoolCount = */ CDacBlobFieldsPoolCount, + /* .GlobalLiteralValuesCount = */ CDacBlobGlobalLiteralsCount, + /* .GlobalPointerValuesCount = */ CDacBlobGlobalPointersCount, + /* .NamesPoolCount = */ sizeof(struct CDacStringPoolSizes), + /* .TypeSpecSize = */ sizeof(struct TypeSpec), + /* .FieldSpecSize = */ sizeof(struct FieldSpec), + /* .GlobalLiteralSpecSize = */ sizeof(struct GlobalLiteralSpec), + /* .GlobalPointerSpecSize = */ sizeof(struct GlobalPointerSpec), + }, + /* .PlatformFlags = */ (sizeof(void*) == 4 ? 0x02 : 0) | 0x01, + /* .BaselineName = */ offsetof(struct CDacStringPoolSizes, cdac_string_pool_baseline_), + + /* .Types = */ { +#define CDAC_TYPE_BEGIN(name) { \ + /* .Name = */ GET_TYPE_NAME(name), \ + /* .Fields = */ GET_TYPE_FIELDS(name), +#define CDAC_TYPE_INDETERMINATE(name) /*.Size = */ 0, +#define CDAC_TYPE_SIZE(size) /* .Size = */ size, +#define CDAC_TYPE_END(name) }, +#include "datadescriptor.h" + }, + + /* .FieldsPool = */ { +#define CDAC_TYPES_BEGIN() {0,}, +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) { \ + /* .Name = */ GET_FIELD_NAME(tyname,membername), \ + /* .TypeName = */ GET_FIELDTYPE_NAME(tyname,membername), \ + /* .FieldOffset = */ offset, \ +}, +#define CDAC_TYPE_END(name) { 0, }, +#include "datadescriptor.h" + }, + + /* .GlobalLiteralValues = */ { +#define CDAC_GLOBAL(name,tyname,value) { /*.Name = */ GET_GLOBAL_NAME(name), /* .TypeName = */ GET_GLOBALTYPE_NAME(name), /* .Value = */ value }, +#include "datadescriptor.h" + }, + + /* .GlobalPointerValues = */ { +#define CDAC_GLOBAL_POINTER(name,value) { /* .Name = */ GET_GLOBAL_NAME(name), /* .PointerDataIndex = */ GET_GLOBAL_POINTER_INDEX(name) }, +#include "datadescriptor.h" + }, + + /* .NamesPool = */ ("\0" // starts with a nul +#define CDAC_BASELINE(name) name "\0" +#define CDAC_TYPE_BEGIN(name) #name "\0" +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) #membername "\0" #membertyname "\0" +#define CDAC_GLOBAL_POINTER(name,value) #name "\0" +#define CDAC_GLOBAL(name,tyname,value) #name "\0" #tyname "\0" +#include "datadescriptor.h" + ), + + /* .EndMagic = */ { 0x01, 0x02, 0x03, 0x04 }, + } +}; + +// end blob definition + +} // extern "C" diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.h b/src/coreclr/debug/runtimeinfo/datadescriptor.h new file mode 100644 index 00000000000000..b5ab51774e1215 --- /dev/null +++ b/src/coreclr/debug/runtimeinfo/datadescriptor.h @@ -0,0 +1,139 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// No include guards. This file is included multiple times. + +// The format is: +// CDAC_BASELINE("string") baseline data contract that the runtime should follow. "empty" is reasonable +// CDAC_TYPES_BEGIN() +// ... ... +// CDAC_TYPES_END() +// CDAC_GLOBALS_BEGIN() +// ... ... +// CDAC_GLOBALS_END() +// +// In the format is: +// CDAC_TYPE_BEGIN(cdacTypeIdentifier) // defined a new data descriptor named cdacIdentifier +// +// CDAC_TYPE_SIZE(k) -or- CDAC_TYPE_INDETERMINATE(cdacTypeIdentifier) specifies that the type has +// size k (bytes - usually sizeof(SomeNativeType)) or specify that the type's size is not provided +// It is important that CDAC_TYPE_SIZE or CDAC_TYPE_INDETERMINATE immediately follows +// CDAC_TYPE_BEGIN +// +// CDAC_TYPE_FIELD(cdacTypeIdentifier, cdacFieldTypeIdentifier, cdacFieldName, k) specifies the +// field of "cdacTypeIdentifier" that has name cdacFieldName and has the type +// "cdacFieldtypeIdentifier" located at offset k in the type layout. k is usually +// offsetof(SomeClass, m_FieldName) if the field is public +// +// if the field is private, the convention is that SomeClass declares a friend struct +// cdac_offsets and provides a specialization of cdac_offsets with a public constexpr +// size_t member that holds the offset: +// +// class MyClass { +// private: +// void* m_myField; +// friend template cdac_offsets; +// }; +// template<> struct cdac_offsets { +// static constexpr size_t MyField = offsetof(MyClass, m_myField); +// }; +// +// then the field layout can be specified as +// CDAC_TYPE_FIELD(MyClassLayout, pointer, MyField, cdac_offsets::MyField) +// There can be zero or more CDAC_TYPE_FIELD entries per type layout +// +// CDAC_TYPE_END(cdacTypeIdentifier) specifies the end of the type layout for cdacTypeIdentifier +// +// In the format is: +// +// CDAC_GLOBAL(cdacGlobalName, cdacTypeIdentifier, value) +// or +// CDAC_GLOBAL_POINTER(cdacGlobalName, cdacTypeIdentifier, address) +// +// Zero or more globals can be defined +// +// if a global is given with CDAC_GLOBAL(), `value` should be a constexpr uint64_t (or convertible +// to uint64_t) for example, it can be a literal constant or a preprocessor definition +// +// if a global is a CDAC_GLOBAL_POINTER(), address should be a constexpr pointer or a constexpr +// uintptr_t +// +// +// +// This file is compiled using the target architecture. Preprocessor defines for the target +// platform will be available. It is ok to use `#ifdef`. + +#ifndef CDAC_BASELINE +#define CDAC_BASELINE(identifier) +#endif +#ifndef CDAC_TYPES_BEGIN +#define CDAC_TYPES_BEGIN() +#endif +#ifndef CDAC_TYPE_BEGIN +#define CDAC_TYPE_BEGIN(tyname) +#endif +#ifndef CDAC_TYPE_SIZE +#define CDAC_TYPE_SIZE(k) +#endif +#ifndef CDAC_TYPE_INDETERMINATE +#define CDAC_TYPE_INDETERMINATE(tyname) +#endif +#ifndef CDAC_TYPE_FIELD +#define CDAC_TYPE_FIELD(tyname,fieldtyname,fieldname,off) +#endif +#ifndef CDAC_TYPE_END +#define CDAC_TYPE_END(tyname) +#endif +#ifndef CDAC_TYPES_END +#define CDAC_TYPES_END() +#endif +#ifndef CDAC_GLOBALS_BEGIN +#define CDAC_GLOBALS_BEGIN() +#endif +#ifndef CDAC_GLOBAL +#define CDAC_GLOBAL(globalname,tyname,val) +#endif +#ifndef CDAC_GLOBAL_POINTER +#define CDAC_GLOBAL_POINTER(globalname,addr) +#endif +#ifndef CDAC_GLOBALS_END +#define CDAC_GLOBALS_END() +#endif + +CDAC_BASELINE("empty") +CDAC_TYPES_BEGIN() + +CDAC_TYPE_BEGIN(ManagedThread) +CDAC_TYPE_INDETERMINATE(ManagedThread) +CDAC_TYPE_FIELD(ManagedThread, GCHandle, GCHandle, cdac_offsets::ExposedObject) +CDAC_TYPE_FIELD(ManagedThread, pointer, LinkNext, cdac_offsets::Link) +CDAC_TYPE_END(ManagedThread) + +CDAC_TYPE_BEGIN(GCHandle) +CDAC_TYPE_SIZE(sizeof(OBJECTHANDLE)) +CDAC_TYPE_END(GCHandle) + +CDAC_TYPES_END() + +CDAC_GLOBALS_BEGIN() +CDAC_GLOBAL_POINTER(ManagedThreadStore, &ThreadStore::s_pThreadStore) +#if FEATURE_EH_FUNCLETS +CDAC_GLOBAL(FeatureEHFunclets, uint8, 1) +#else +CDAC_GLOBAL(FeatureEHFunclets, uint8, 0) +#endif +CDAC_GLOBAL(SOSBreakingChangeVersion, uint8, SOS_BREAKING_CHANGE_VERSION) +CDAC_GLOBALS_END() + +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef CDAC_TYPES_END +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBALS_END diff --git a/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt b/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt index c600af1fb6aada..7ba58d0297f9a9 100644 --- a/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt +++ b/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt @@ -109,6 +109,7 @@ set(CORECLR_LIBRARIES interop coreclrminipal gc_pal + cdac_contract_descriptor ) if(CLR_CMAKE_TARGET_ARCH_AMD64) diff --git a/src/coreclr/dlls/mscoree/mscorwks_ntdef.src b/src/coreclr/dlls/mscoree/mscorwks_ntdef.src index 0ac421b63e0718..a2076bd62433c9 100644 --- a/src/coreclr/dlls/mscoree/mscorwks_ntdef.src +++ b/src/coreclr/dlls/mscoree/mscorwks_ntdef.src @@ -28,3 +28,6 @@ EXPORTS ; Used by profilers MetaDataGetDispenser + + ; cDAC contract descriptor + DotNetRuntimeContractDescriptor diff --git a/src/coreclr/dlls/mscoree/mscorwks_unixexports.src b/src/coreclr/dlls/mscoree/mscorwks_unixexports.src index a35a59c095604a..3eacb7fa484856 100644 --- a/src/coreclr/dlls/mscoree/mscorwks_unixexports.src +++ b/src/coreclr/dlls/mscoree/mscorwks_unixexports.src @@ -14,3 +14,6 @@ g_dacTable ; Used by profilers MetaDataGetDispenser + +; cDAC contract descriptor +DotNetRuntimeContractDescriptor diff --git a/src/coreclr/runtime-prereqs.proj b/src/coreclr/runtime-prereqs.proj index 6bbe50f7d550a9..91e3f46d59d5fe 100644 --- a/src/coreclr/runtime-prereqs.proj +++ b/src/coreclr/runtime-prereqs.proj @@ -15,6 +15,7 @@ + diff --git a/src/coreclr/runtime.proj b/src/coreclr/runtime.proj index 773b0290d523f9..c231ebd07a80e8 100644 --- a/src/coreclr/runtime.proj +++ b/src/coreclr/runtime.proj @@ -50,6 +50,7 @@ <_CoreClrBuildArg Condition="'$(HostCrossOS)' != ''" Include="-hostos $(HostCrossOS)" /> <_CoreClrBuildArg Include="-outputrid $(OutputRID)" /> <_CoreClrBuildArg Condition="'$(BuildSubdirectory)' != ''" Include="-subdir $(BuildSubdirectory)" /> + <_CoreClrBuildArg Include="-cmakeargs "-DCDAC_BUILD_TOOL_BINARY_PATH=$(RuntimeBinDir)cdac-build-tool\cdac-build-tool.dll"" /> diff --git a/src/coreclr/tools/cdac-build-tool/ComposeCommand.cs b/src/coreclr/tools/cdac-build-tool/ComposeCommand.cs new file mode 100644 index 00000000000000..226244a88872ab --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/ComposeCommand.cs @@ -0,0 +1,91 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.CommandLine; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +internal sealed class ComposeCommand : CliCommand +{ + private readonly CliArgument inputFiles = new("INPUT [INPUTS...]") { Arity = ArgumentArity.OneOrMore, Description = "One or more input files" }; + private readonly CliOption outputFile = new("-o") { Arity = ArgumentArity.ExactlyOne, HelpName = "OUTPUT", Required = true, Description = "Output file" }; + private readonly CliOption contractFile = new("-c") { Arity = ArgumentArity.ZeroOrMore, HelpName = "CONTRACT", Description = "Contract file (may be specified multiple times)" }; + private readonly CliOption _verboseOption; + public ComposeCommand(CliOption verboseOption) : base("compose") + { + _verboseOption = verboseOption; + Add(inputFiles); + Add(outputFile); + Add(contractFile); + SetAction(Run); + } + + private async Task Run(ParseResult parse, CancellationToken token = default) + { + var inputs = parse.GetValue(inputFiles); + if (inputs == null || inputs.Length == 0) + { + Console.Error.WriteLine("No input files specified"); + return 1; + } + var output = parse.GetValue(outputFile); + if (output == null) + { + Console.Error.WriteLine("No output file specified"); + return 1; + } + var contracts = parse.GetValue(contractFile); + var verbose = parse.GetValue(_verboseOption); + var builder = new DataDescriptorModel.Builder(); + var scraper = new ObjectFileScraper(verbose, builder); + foreach (var input in inputs) + { + token.ThrowIfCancellationRequested(); + if (!await scraper.ScrapeInput(input, token).ConfigureAwait(false)) + { + Console.Error.WriteLine($"could not scrape payload in {input}"); + return 1; + } + } + if (contracts != null) + { + var contractReader = new ContractReader(builder); + foreach (var contract in contracts) + { + if (!await contractReader.ParseContracts(contract, token).ConfigureAwait(false)) + { + Console.Error.WriteLine($"could not parse contracts in {contract}"); + return 1; + } + } + } + + var model = builder.Build(); + if (verbose) + { + model.DumpModel(); + } + EnsureDirectoryExists(output); + using var writer = new System.IO.StreamWriter(output); + var emitter = new ContractDescriptorSourceFileEmitter(); + emitter.SetPlatformFlags(model.PlatformFlags); + emitter.SetPointerDataCount(model.PointerDataCount); + emitter.SetJsonDescriptor(model.ToJson()); + emitter.Emit(writer); + await writer.FlushAsync(token).ConfigureAwait(false); + return 0; + } + + private static void EnsureDirectoryExists(string outputPath) + { + var directory = System.IO.Path.GetDirectoryName(outputPath); + if (directory == null) + { + return; + } + System.IO.Directory.CreateDirectory(directory); + } +} diff --git a/src/coreclr/tools/cdac-build-tool/ContractDescriptorSourceFileEmitter.cs b/src/coreclr/tools/cdac-build-tool/ContractDescriptorSourceFileEmitter.cs new file mode 100644 index 00000000000000..dde27a6858c6d0 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/ContractDescriptorSourceFileEmitter.cs @@ -0,0 +1,81 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; + +namespace Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +public partial class ContractDescriptorSourceFileEmitter +{ + public const string TemplateResourceName = "Microsoft.DotNet.Diagnostics.DataContract.Resources.contract-descriptor.c.in"; + private const string JsonDescriptorKey = "jsonDescriptor"; + private const string JsonDescriptorSizeKey = "jsonDescriptorSize"; + private const string PointerDataCount = "pointerDataCount"; + private const string PlatformFlags = "platformFlags"; + + + [GeneratedRegex("%%([a-zA-Z0-9_]+)%%", RegexOptions.CultureInvariant)] + private static partial Regex FindTemplatePlaceholderRegex(); + + internal static Stream GetTemplateStream() + { + return typeof(ContractDescriptorSourceFileEmitter).Assembly.GetManifestResourceStream(TemplateResourceName)!; + } + + internal static string GetTemplateString() + { + using var reader = new StreamReader(GetTemplateStream(), System.Text.Encoding.UTF8); + return reader.ReadToEnd(); + } + + public void SetPointerDataCount(int count) + { + Elements[PointerDataCount] = count.ToString(); + } + + public void SetPlatformFlags(uint platformFlags) + { + Elements[PlatformFlags] = $"0x{platformFlags:x8}"; + } + + /// The jsonDescriptor should not be C escaped + public void SetJsonDescriptor(string jsonDescriptor) + { + var count = jsonDescriptor.Length; // return the length before escaping + var escaped = CStringEscape().Replace(jsonDescriptor, "\\$1"); + Elements[JsonDescriptorKey] = escaped; + Elements[JsonDescriptorSizeKey] = count.ToString(); + } + + [GeneratedRegex("(\")", RegexOptions.CultureInvariant)] + private static partial Regex CStringEscape(); + + public Dictionary Elements { get; } = new(); + + public void Emit(TextWriter dest) + { + var template = GetTemplateString(); + var matches = FindTemplatePlaceholderRegex().Matches(template); + var prevPos = 0; + foreach (Match match in matches) + { + // copy everything from the end of the last match (prevPos) to just before the current match to the output + dest.Write(template.AsSpan(prevPos, match.Index - prevPos)); + + // lookup the capture key and write it out + + var key = match.Groups[1].Captures[0].Value; + if (!Elements.TryGetValue(key, out string? result)) + { + throw new InvalidOperationException ($"no replacement for {key}"); + } + dest.Write(result); + prevPos = match.Index + match.Length; + } + // write everything from the prevPos to the end of the template + dest.Write(template.AsSpan(prevPos)); + } +} diff --git a/src/coreclr/tools/cdac-build-tool/ContractReader.cs b/src/coreclr/tools/cdac-build-tool/ContractReader.cs new file mode 100644 index 00000000000000..3bd8ec0c77e7f5 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/ContractReader.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +public class ContractReader +{ + private readonly DataDescriptorModel.Builder _builder; + + private static readonly JsonSerializerOptions s_jsonSerializerOptions = new() { PropertyNameCaseInsensitive = false, ReadCommentHandling = JsonCommentHandling.Skip }; + + public ContractReader(DataDescriptorModel.Builder builder) + { + _builder = builder; + } + + public async Task ParseContracts(string contractFilePath, CancellationToken token = default) + { + string? contents = await File.ReadAllTextAsync(contractFilePath, token).ConfigureAwait(false); + var contracts = JsonSerializer.Deserialize>(contents, s_jsonSerializerOptions); + if (contracts is null) + return false; + _builder.AddOrupdateContracts(contracts); + return true; + } +} diff --git a/src/coreclr/tools/cdac-build-tool/DataDescriptorModel.cs b/src/coreclr/tools/cdac-build-tool/DataDescriptorModel.cs new file mode 100644 index 00000000000000..3abeb5c56e83ce --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/DataDescriptorModel.cs @@ -0,0 +1,389 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.DotNet.Diagnostics.DataContract.JsonConverter; + +namespace Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +public class DataDescriptorModel +{ + public int Version => 0; + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public string Baseline { get; } + public IReadOnlyDictionary Types { get; } + public IReadOnlyDictionary Globals { get; } + public IReadOnlyDictionary Contracts { get; } + [JsonIgnore] + public uint PlatformFlags { get; } + // The number of indirect globals plus 1 for the placeholder at index 0 + [JsonIgnore] + public int PointerDataCount => 1 + Globals.Values.Count(g => g.Value.Indirect); + + private DataDescriptorModel(string baseline, IReadOnlyDictionary types, IReadOnlyDictionary globals, IReadOnlyDictionary contracts, uint platformFlags) + { + Baseline = baseline; + Types = types; + Globals = globals; + Contracts = contracts; + PlatformFlags = platformFlags; + } + + public const string PointerTypeName = "pointer"; + + internal void DumpModel() + { + Console.WriteLine("\nData Descriptor Model:"); + Console.WriteLine($"Platform Flags: 0x{PlatformFlags:x8}"); + Console.WriteLine($"Baseline: {Baseline}"); + foreach (var (typeName, type) in Types) + { + Console.WriteLine($"Type: {typeName}"); + if (type.Size != null) + { + Console.WriteLine($" Size: 0x{type.Size:x8}"); + } + foreach (var (fieldName, field) in type.Fields) + { + Console.WriteLine($" Field: {fieldName}"); + Console.WriteLine($" Type: {field.Type}"); + Console.WriteLine($" Offset: 0x{field.Offset:x8}"); + } + } + foreach (var (globalName, global) in Globals) + { + Console.WriteLine($"Global: {globalName}"); + Console.WriteLine($" Type: {global.Type}"); + Console.WriteLine($" Value: {global.Value}"); + } + foreach (var (contractName, contract) in Contracts) + { + Console.WriteLine($"Contract: {contractName}"); + Console.WriteLine($" Version: {contract}"); + } + } + + private static JsonSerializerOptions s_jsonSerializerOptions = new JsonSerializerOptions + { + WriteIndented = false, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + DictionaryKeyPolicy = null, // leave unchanged + }; + public string ToJson() + { + // always writes the "compact" format, see data_descriptor.md + return JsonSerializer.Serialize(this, s_jsonSerializerOptions); + } + + public class Builder + { + private string _baseline; + private bool _baselineParsed; + private readonly Dictionary _types = new(); + private readonly Dictionary _globals = new(); + private readonly Dictionary _contracts = new(); + public Builder() + { + _baseline = string.Empty; + _baselineParsed = false; + } + + public uint PlatformFlags {get; set;} + + public TypeModelBuilder AddOrUpdateType(string name, int? size) + { + if (!_baselineParsed) + { + throw new InvalidOperationException("Baseline must be set before adding types"); + } + if (!_types.TryGetValue(name, out var type)) + { + type = new TypeModelBuilder(); + _types[name] = type; + } + type.Size = size; + return type; + } + + public GlobalBuilder AddOrUpdateGlobal(string name, string type, GlobalValue? value) + { + if (!_baselineParsed) + { + throw new InvalidOperationException("Baseline must be set before adding globals"); + } + if (!_globals.TryGetValue(name, out var global)) + { + global = new GlobalBuilder(); + _globals[name] = global; + } + global.Type = type; + global.Value = value; + return global; + } + + public void AddOrUpdateContract(string name, int version) + { + if (!_contracts.TryGetValue(name, out var contract)) + { + contract = new ContractBuilder(); + _contracts[name] = contract; + } + contract.Version = version; + } + + public void AddOrupdateContracts(IEnumerable> contracts) + { + foreach (var (name, version) in contracts) + { + AddOrUpdateContract(name, version); + } + } + + public void SetBaseline(string baseline) + { + if (_baseline != string.Empty && _baseline != baseline) + { + throw new InvalidOperationException($"Baseline already set to {_baseline} cannot set to {baseline}"); + } + if (EmbeddedBaselines.BaselineNames.Contains(baseline)) + { + _baseline = baseline; + } + else + { + throw new InvalidOperationException($"Baseline '{baseline}' not known"); + } + _baseline = baseline; + if (!_baselineParsed) + { + _baselineParsed = true; // kind of a hack - set it before parsing the baseline, so we can call AddOrUpdateType + ParseBaseline(); + } + } + + private void ParseBaseline() + { + if (_baseline != "empty") + { + throw new InvalidOperationException("TODO: [cdac] - implement baseline parsing"); + } + } + + public DataDescriptorModel Build() + { + var types = new Dictionary(); + foreach (var (typeName, typeBuilder) in _types) + { + types[typeName] = typeBuilder.Build(typeName); + } + var globals = new Dictionary(); + foreach (var (globalName, globalBuilder) in _globals) + { + if (globalBuilder.Type == string.Empty) + { + throw new InvalidOperationException($"Type must be set for global {globalName}"); + } + GlobalValue? v = globalBuilder.Value; + if (v == null) + { + throw new InvalidOperationException($"Value must be set for global {globalName}"); + } + globals[globalName] = new GlobalModel { Type = globalBuilder.Type, Value = v.Value }; + } + var contracts = new Dictionary(); + foreach (var (contractName, contractBuilder) in _contracts) + { + contracts[contractName] = contractBuilder.Build(); + } + return new DataDescriptorModel(_baseline, types, globals, contracts, PlatformFlags); + } + } + + public class TypeModelBuilder + { + private readonly Dictionary _fields = new(); + private int? _size; + public TypeModelBuilder() { } + + public int? Size + { + get => _size; + set + { + if (_size != null && (value == null || _size != (int)value)) + { + throw new InvalidOperationException($"Size already set to {_size} cannot set to {value}"); + } + _size = value; + } + } + + public void AddOrUpdateField(string name, string type, int? offset) + { + if (!_fields.TryGetValue(name, out var field)) + { + field = new FieldBuilder(); + _fields[name] = field; + } + field.Type = type; + field.Offset = offset; + } + + public TypeModel Build(string typeName) + { + var fields = new Dictionary(); + foreach (var (fieldName, fieldBuilder) in _fields) + { + fields.Add(fieldName, fieldBuilder.Build(typeName, fieldName)); + } + return new TypeModel { Size = _size, Fields = fields }; + } + } + + public class GlobalBuilder + { + private string _type = string.Empty; + private GlobalValue? _value; + public string Type + { + get => _type; + set + { + if (_type != string.Empty && _type != value) + { + throw new InvalidOperationException($"Type already set to {_type} cannot set to {value}"); + } + _type = value; + } + } + public GlobalValue? Value + { + get => _value; + set + { + if (_value != null && _value != value) + { + throw new InvalidOperationException($"Value already set to {_value} cannot set to {value}"); + } + _value = value; + } + } + } + internal sealed class FieldBuilder + { + private string _type = string.Empty; + private int? _offset; + public string Type + { + get => _type; + set + { + if (_type != string.Empty && _type != value) + { + throw new InvalidOperationException($"Type already set to {_type} cannot set to {value}"); + } + _type = value; + } + } + + public int? Offset + { + get => _offset; + set + { + if (_offset != null && (value == null || _offset != (int)value)) + { + throw new InvalidOperationException($"Offset already set to {_offset} cannot set to {value}"); + } + _offset = value; + } + } + + public FieldModel Build(string typeName, string fieldName) + { + if (_offset == null) + { + throw new InvalidOperationException($"Offset must be set for {typeName}.{fieldName}"); + } + return new FieldModel { Type = _type, Offset = (int)_offset }; + } + } + + [JsonConverter(typeof(FieldModelJsonConverter))] + public readonly struct FieldModel + { + public string Type { get; init; } + public int Offset { get; init; } + } + + [JsonConverter(typeof(TypeModelJsonConverter))] + public readonly struct TypeModel + { + public int? Size { get; init; } + public IReadOnlyDictionary Fields { get; init; } + } + + [JsonConverter(typeof(GlobalValueJsonConverter))] + public readonly struct GlobalValue : IEquatable + { + public bool Indirect { get; private init; } + public ulong Value { get; } + public static GlobalValue MakeDirect(ulong value) => new GlobalValue(value); + public static GlobalValue MakeIndirect(uint auxDataIdx) => new GlobalValue((ulong)auxDataIdx) { Indirect = true }; + private GlobalValue(ulong value) { Value = value; } + + public static bool operator ==(GlobalValue left, GlobalValue right) => left.Value == right.Value && left.Indirect == right.Indirect; + public static bool operator !=(GlobalValue left, GlobalValue right) => !(left == right); + + public bool Equals(GlobalValue other) => this == other; + public override bool Equals(object? obj) => obj is GlobalValue value && this == value; + public override int GetHashCode() => HashCode.Combine(Value, Indirect); + public override string ToString() => Indirect ? $"Indirect({Value})" : $"0x{Value:x}"; + } + + [JsonConverter(typeof(GlobalModelJsonConverter))] + public readonly struct GlobalModel + { + public string Type { get; init; } + public GlobalValue Value { get; init; } + } + + public class ContractBuilder + { + private int? _version; + public ContractBuilder() + { + } + + public int? Version + { + get => _version; + set + { + if (_version != null && _version != value) + { + throw new InvalidOperationException($"Version already set to {_version} cannot set to {value}"); + } + _version = value; + } + } + + // There is no ContractModel right now because the only info we keep is the version. + // As a result it is convenient to use a Dictionary for the contracts since + // the JSON serialization coincides with what we want. + public int Build() + { + if (_version == null) + { + throw new InvalidOperationException("Version must be set for contract"); + } + return _version.Value; + } + } +} diff --git a/src/coreclr/tools/cdac-build-tool/Directory.Build.props b/src/coreclr/tools/cdac-build-tool/Directory.Build.props new file mode 100644 index 00000000000000..465a55954dfea4 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/Directory.Build.props @@ -0,0 +1,7 @@ + + + + <_RequiresLiveILLink>false + + + diff --git a/src/coreclr/tools/cdac-build-tool/EmbeddedBaselines.cs b/src/coreclr/tools/cdac-build-tool/EmbeddedBaselines.cs new file mode 100644 index 00000000000000..ac9cea8b6615ea --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/EmbeddedBaselines.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; + +namespace Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +public partial class EmbeddedBaselines +{ + public const string TemplateResourceNamePrefix = "Microsoft.DotNet.Diagnostics.DataContract.Baseline:"; + public const string TemplateResourceNameEscapePrefix = @"Microsoft\.DotNet\.Diagnostics\.DataContract\.Baseline:"; + public const string TemplateResourceNameExt = ".jsonc"; + public const string TemplateResourceNameEscapeExt = @"\.jsonc"; + + [GeneratedRegex("^" + TemplateResourceNameEscapePrefix + "(.+)" + TemplateResourceNameEscapeExt + "$", RegexOptions.CultureInvariant)] + private static partial Regex BaselineRegex(); + + private static string[] GetBaselineNames() + { + var assembly = typeof(EmbeddedBaselines).Assembly; + var resources = assembly.GetManifestResourceNames(); + var baselineNames = new List(); + foreach (var resource in resources) + { + var match = BaselineRegex().Match(resource); + if (match.Success) + { + baselineNames.Add(match.Groups[1].Value); + } + } + return baselineNames.ToArray(); + } + + private static readonly Lazy> _baselineNames = new(GetBaselineNames); + public static IReadOnlyList BaselineNames => _baselineNames.Value; + + public static string GetBaselineContent(string name) + { + var assembly = typeof(EmbeddedBaselines).Assembly; + var resourceName = TemplateResourceNamePrefix + name + TemplateResourceNameExt; + using var stream = assembly.GetManifestResourceStream(resourceName); + if (stream == null) + { + throw new InvalidOperationException($"Baseline '{name}' not found"); + } + using var reader = new StreamReader(stream); + return reader.ReadToEnd(); + } +} diff --git a/src/coreclr/tools/cdac-build-tool/JsonConverter/FieldModelJsonConverter.cs b/src/coreclr/tools/cdac-build-tool/JsonConverter/FieldModelJsonConverter.cs new file mode 100644 index 00000000000000..5b6631af52a0eb --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/JsonConverter/FieldModelJsonConverter.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +namespace Microsoft.DotNet.Diagnostics.DataContract.JsonConverter; + +/// +/// Writes a FieldModel in the compact form of [offset, type] or just offset if type is null. +/// . +/// +public class FieldModelJsonConverter : JsonConverter +{ + public override DataDescriptorModel.FieldModel Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, DataDescriptorModel.FieldModel value, JsonSerializerOptions options) + { + if (value.Type is null) + { + writer.WriteNumberValue(value.Offset); + } + else + { + writer.WriteStartArray(); + writer.WriteNumberValue(value.Offset); + writer.WriteStringValue(value.Type); + writer.WriteEndArray(); + } + } +} diff --git a/src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalModelJsonConverter.cs b/src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalModelJsonConverter.cs new file mode 100644 index 00000000000000..cae54edb6ff104 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalModelJsonConverter.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +namespace Microsoft.DotNet.Diagnostics.DataContract.JsonConverter; +public class GlobalModelJsonConverter : JsonConverter +{ + public override DataDescriptorModel.GlobalModel Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, DataDescriptorModel.GlobalModel value, JsonSerializerOptions options) + { + if (value.Type is null) + { + // no type: just write 'value' or '[value]' + JsonSerializer.Serialize(writer, value.Value, options); + } + else + { + // there's a type. Write: [value, type] or [[value], type] + writer.WriteStartArray(); + JsonSerializer.Serialize(writer, value.Value, options); + writer.WriteStringValue(value.Type); + writer.WriteEndArray(); + } + } +} diff --git a/src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalValueJsonConverter.cs b/src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalValueJsonConverter.cs new file mode 100644 index 00000000000000..429f6cc6979284 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalValueJsonConverter.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +namespace Microsoft.DotNet.Diagnostics.DataContract.JsonConverter; +public class GlobalValueJsonConverter : JsonConverter +{ + public override DataDescriptorModel.GlobalValue Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, DataDescriptorModel.GlobalValue value, JsonSerializerOptions options) + { + if (!value.Indirect) + { + // no type: just write value as a number. + // we always write as a string containing a hex number + writer.WriteStringValue($"0x{value.Value:x}"); + } + else + { + // pointer data index. write as a 1-element array containing a decimal number + writer.WriteStartArray(); + writer.WriteNumberValue(value.Value); + writer.WriteEndArray(); + } + } +} diff --git a/src/coreclr/tools/cdac-build-tool/JsonConverter/TypeModelJsonConverter.cs b/src/coreclr/tools/cdac-build-tool/JsonConverter/TypeModelJsonConverter.cs new file mode 100644 index 00000000000000..bf400253d5ddfe --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/JsonConverter/TypeModelJsonConverter.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +namespace Microsoft.DotNet.Diagnostics.DataContract.JsonConverter; +public class TypeModelJsonConverter : JsonConverter +{ + public const string SizePropertyname = "!"; + + public override DataDescriptorModel.TypeModel Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, DataDescriptorModel.TypeModel value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + if (value.Size is not null) + { + writer.WriteNumber(SizePropertyname, value.Size.Value); + } + foreach (var (fieldName, field) in value.Fields) + { + writer.WritePropertyName(fieldName); + JsonSerializer.Serialize(writer, field, options); + } + writer.WriteEndObject(); + } +} diff --git a/src/coreclr/tools/cdac-build-tool/ObjectFileScraper.cs b/src/coreclr/tools/cdac-build-tool/ObjectFileScraper.cs new file mode 100644 index 00000000000000..42b0b004c8980a --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/ObjectFileScraper.cs @@ -0,0 +1,519 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +public class ObjectFileScraper +{ + public static readonly ReadOnlyMemory MagicLE = new byte[8] { 0x44, 0x41, 0x43, 0x42, 0x4C, 0x4F, 0x42, 0x00 }; // "DACBLOB\0" + public static readonly ReadOnlyMemory MagicBE = new byte[8] { 0x00, 0x42, 0x4F, 0x4C, 0x42, 0x43, 0x41, 0x44 }; + + private readonly DataDescriptorModel.Builder _builder; + + public bool Verbose {get;} + public ObjectFileScraper(bool verbose, DataDescriptorModel.Builder builder) + { + Verbose = verbose; + _builder = builder; + } + + public async Task ScrapeInput(string inputPath, CancellationToken token) + { + var bytes = await File.ReadAllBytesAsync(inputPath, token).ConfigureAwait(false); + if (!ScraperState.CreateScraperState(bytes, out var state)) + { + return false; + } + if (Verbose) + { + Console.WriteLine($"Magic starts at 0x{state.MagicStart:x8} in {inputPath}"); + } + var header = ReadHeader(state); + if (Verbose) + { + DumpHeaderDirectory(header); + } + var content = ReadContent(state, header); + content.AddToModel(_builder); + if (Verbose) + { + Console.WriteLine($"\nFinished scraping content from {inputPath}"); + } + return true; + } + + private sealed class ScraperState + { + public ReadOnlyMemory Data { get; } + public bool LittleEndian { get; } + private long _position; + + // expect MagicLE and MagicBE to have the same length + public long MagicStart => HeaderStart - MagicLE.Length; + public long HeaderStart { get; } + + private ScraperState(ReadOnlyMemory data, bool isLittleEndian, long headerStart) + { + Data = data; + LittleEndian = isLittleEndian; + HeaderStart = headerStart; + _position = headerStart; + } + + public static bool CreateScraperState(ReadOnlyMemory bytes, [NotNullWhen(true)] out ScraperState? scraperState) + { + if (FindMagic(bytes.Span, out int offset, out bool isLittleEndian)) + { + scraperState = new ScraperState(bytes, isLittleEndian, offset + MagicLE.Length); + return true; + } + scraperState = null; + return false; + } + + private static bool FindMagic(ReadOnlySpan buffer, out int offset, out bool isLittleEndian) + { + int start = buffer.IndexOf(MagicLE.Span); + if (start != -1) + { + offset = start; + isLittleEndian = true; + return true; + } + start = buffer.IndexOf(MagicBE.Span); + if (start != -1) + { + offset = start; + isLittleEndian = false; + return true; + } + offset = 0; + isLittleEndian = false; + return false; + } + + public ulong GetUInt64(long offset) => LittleEndian ? BinaryPrimitives.ReadUInt64LittleEndian(Data.Span.Slice((int)offset)) : BinaryPrimitives.ReadUInt64BigEndian(Data.Span.Slice((int)offset)); + public uint GetUInt32(long offset) => LittleEndian ? BinaryPrimitives.ReadUInt32LittleEndian(Data.Span.Slice((int)offset)) : BinaryPrimitives.ReadUInt32BigEndian(Data.Span.Slice((int)offset)); + public ushort GetUInt16(long offset) => LittleEndian ? BinaryPrimitives.ReadUInt16LittleEndian(Data.Span.Slice((int)offset)) : BinaryPrimitives.ReadUInt16BigEndian(Data.Span.Slice((int)offset)); + public byte GetByte(long offset) => Data.Span[(int)offset]; + + public ReadOnlySpan GetBytes(long offset, int length) => Data.Span.Slice((int)offset, length); + + public void ResetPosition(long position) + { + _position = position; + } + + public ulong ReadUInt64() + { + var value = GetUInt64(_position); + _position += sizeof(ulong); + return value; + } + public uint ReadUInt32() + { + var value = GetUInt32(_position); + _position += sizeof(uint); + return value; + } + public ushort ReadUInt16() + { + var value = GetUInt16(_position); + _position += sizeof(ushort); + return value; + } + + public byte ReadByte() + { + var value = GetByte(_position); + _position += sizeof(byte); + return value; + } + public void ReadBytes(Span buffer) + { + GetBytes(_position, buffer.Length).CopyTo(buffer); + _position += buffer.Length; + } + + public void Skip(int count) + { + _position += count; + } + } + + // see typedef Directory in data-descriptor-blob.md + private struct HeaderDirectory + { + public uint FlagsAndBaselineStart; + public uint TypesStart; + + public uint FieldsPoolStart; + public uint GlobalLiteralValuesStart; + + public uint GlobalPointersStart; + public uint NamesStart; + + public uint TypesCount; + public uint FieldsPoolCount; + + public uint GlobalLiteralValuesCount; + public uint GlobalPointerValuesCount; + + public uint NamesPoolCount; + + public byte TypeSpecSize; + public byte FieldSpecSize; + public byte GlobalLiteralSpecSize; + public byte GlobalPointerSpecSize; + }; + + private static void DumpHeaderDirectory(HeaderDirectory headerDirectory) + { + Console.WriteLine($""" + Scaped Header Directory: + + Baseline Start = 0x{headerDirectory.FlagsAndBaselineStart:x8} + Types Start = 0x{headerDirectory.TypesStart:x8} + Fields Pool Start = 0x{headerDirectory.FieldsPoolStart:x8} + Global Literals Start = 0x{headerDirectory.GlobalLiteralValuesStart:x8} + Global Pointers Start = 0x{headerDirectory.GlobalPointersStart:x8} + Names Pool Start = 0x{headerDirectory.NamesStart:x8} + + Types Count = {headerDirectory.TypesCount} + Fields Pool Count = {headerDirectory.FieldsPoolCount} + Global Literal Values Count = {headerDirectory.GlobalLiteralValuesCount} + Global Pointer Values Count = {headerDirectory.GlobalPointerValuesCount} + Names Pool Count = {headerDirectory.NamesPoolCount} + + """); + } + + private static HeaderDirectory ReadHeader(ScraperState state) + { + state.ResetPosition(state.HeaderStart); + var baselineStart = state.ReadUInt32(); + var typesStart = state.ReadUInt32(); + + var fieldPoolStart = state.ReadUInt32(); + var globalLiteralValuesStart = state.ReadUInt32(); + + var globalPointersStart = state.ReadUInt32(); + var namesStart = state.ReadUInt32(); + + var typeCount = state.ReadUInt32(); + var fieldPoolCount = state.ReadUInt32(); + + var globalLiteralValuesCount = state.ReadUInt32(); + var globalPointerValuesCount = state.ReadUInt32(); + + var namesPoolCount = state.ReadUInt32(); + + var typeSpecSize = state.ReadByte(); + var fieldSpecSize = state.ReadByte(); + var globalLiteralSpecSize = state.ReadByte(); + var globalPointerSpecSize = state.ReadByte(); + + return new HeaderDirectory { + FlagsAndBaselineStart = baselineStart, + TypesStart = typesStart, + FieldsPoolStart = fieldPoolStart, + GlobalLiteralValuesStart = globalLiteralValuesStart, + GlobalPointersStart = globalPointersStart, + NamesStart = namesStart, + + TypesCount = typeCount, + FieldsPoolCount = fieldPoolCount, + + GlobalLiteralValuesCount = globalLiteralValuesCount, + GlobalPointerValuesCount = globalPointerValuesCount, + + NamesPoolCount = namesPoolCount, + + TypeSpecSize = typeSpecSize, + FieldSpecSize = fieldSpecSize, + GlobalLiteralSpecSize = globalLiteralSpecSize, + GlobalPointerSpecSize = globalPointerSpecSize, + }; + } + + private struct TypeSpec + { + public uint NameIdx; + public uint FieldsIdx; + public ushort? Size; + } + + private struct FieldSpec + { + public uint NameIdx; + public uint TypeNameIdx; + public ushort FieldOffset; + } + + // Like a FieldSpec but with names resolved + private struct FieldEntry + { + public string Name; + public string Type; + public ushort Offset; + } + + private struct GlobalLiteralSpec + { + public uint NameIdx; + public uint TypeNameIdx; + public ulong Value; + } + + private struct GlobalPointerSpec + { + public uint NameIdx; + public uint AuxDataIdx; + } + + private sealed class Content + { + public required bool Verbose {get; init; } + public required uint PlatformFlags { get; init; } + public required uint Baseline { get; init; } + public required IReadOnlyList TypeSpecs { get; init; } + public required IReadOnlyList FieldSpecs { get; init; } + public required IReadOnlyList GlobaLiteralSpecs { get; init; } + public required IReadOnlyList GlobalPointerSpecs { get; init; } + public required ReadOnlyMemory NamesPool { get; init; } + + internal string GetPoolString(uint stringIdx) + { + var nameStart = NamesPool.Span.Slice((int)stringIdx); + var end = nameStart.IndexOf((byte)0); // find the first nul after index + if (end == -1) + throw new InvalidOperationException("expected a nul-terminated name"); + var nameBytes = nameStart.Slice(0, end); + return System.Text.Encoding.UTF8.GetString(nameBytes); + } + + public void AddToModel(DataDescriptorModel.Builder builder) + { + WriteVerbose("\nAdding scraped content to model"); + builder.PlatformFlags = PlatformFlags; + string baseline = GetPoolString(Baseline); + WriteVerbose($"Baseline Name = {baseline}"); + builder.SetBaseline(baseline); + + + FieldEntry[] fields = FieldSpecs.Select((fieldSpec) => + (fieldSpec.NameIdx != 0) ? + new FieldEntry + { + Name = GetPoolString(fieldSpec.NameIdx), + Type = GetPoolString(fieldSpec.TypeNameIdx), + Offset = fieldSpec.FieldOffset + } : + default + ).ToArray(); + + foreach (var typeSpec in TypeSpecs) + { + string typeName = GetPoolString(typeSpec.NameIdx); + var typeBuilder = builder.AddOrUpdateType(typeName, typeSpec.Size); + uint j = typeSpec.FieldsIdx; // convert byte offset to index; + WriteVerbose($"Type {typeName} has fields starting at index {j}"); + while (j < fields.Length && !string.IsNullOrEmpty(fields[j].Name)) + { + typeBuilder.AddOrUpdateField(fields[j].Name, fields[j].Type, fields[j].Offset); + WriteVerbose($"Type {typeName} has field {fields[j].Name} with offset {fields[j].Offset}"); + j++; + } + if (typeSpec.Size is not null) + { + WriteVerbose($"Type {typeName} has size {typeSpec.Size}"); + } + else + { + WriteVerbose($"Type {typeName} has indeterminate size"); + } + } + + foreach (var globalSpec in GlobaLiteralSpecs) + { + var globalName = GetPoolString(globalSpec.NameIdx); + var globalType = GetPoolString(globalSpec.TypeNameIdx); + var globalValue = DataDescriptorModel.GlobalValue.MakeDirect(globalSpec.Value); + builder.AddOrUpdateGlobal(globalName, globalType, globalValue); + WriteVerbose($"Global {globalName} has type {globalType} with value {globalValue}"); + } + + foreach (var globalPointer in GlobalPointerSpecs) + { + var globalName = GetPoolString(globalPointer.NameIdx); + var auxDataIdx = globalPointer.AuxDataIdx; + var globalValue = DataDescriptorModel.GlobalValue.MakeIndirect(auxDataIdx); + builder.AddOrUpdateGlobal(globalName, DataDescriptorModel.PointerTypeName, globalValue); + WriteVerbose($"Global pointer {globalName} has index {globalValue}"); + } + } + + private void WriteVerbose(string msg) + { + if (Verbose) + Console.WriteLine(msg); + } + } + + private Content ReadContent(ScraperState state, HeaderDirectory header) + { + WriteVerbose("\nReading scraped content"); + state.ResetPosition(state.HeaderStart + header.FlagsAndBaselineStart); + var platformFlags = state.ReadUInt32(); + var baselineNameIdx = state.ReadUInt32(); + WriteVerbose($"flags = 0x{platformFlags:x8}, baseline Name Idx = {baselineNameIdx}"); + + TypeSpec[] typeSpecs = ReadTypeSpecs(state, header); + FieldSpec[] fieldSpecs = ReadFieldSpecs(state, header); + GlobalLiteralSpec[] globalLiteralSpecs = ReadGlobalLiteralSpecs(state, header); + GlobalPointerSpec[] globalPointerSpecs = ReadGlobalPointerSpecs(state, header); + byte[] namesPool = ReadNamesPool(state, header); + + byte[] endMagic = new byte[4]; + state.ReadBytes(endMagic.AsSpan()); + if (!CheckEndMagic(endMagic)) + { + throw new InvalidOperationException($"expected endMagic, got 0x{endMagic[0]:x} 0x{endMagic[1]:x} 0x{endMagic[2]:x} 0x{endMagic[3]:x}"); + } + else + { + WriteVerbose("\nFound correct endMagic at end of content"); + } + return new Content + { + Verbose = Verbose, + PlatformFlags = platformFlags, + Baseline = baselineNameIdx, + TypeSpecs = typeSpecs, + FieldSpecs = fieldSpecs, + GlobaLiteralSpecs = globalLiteralSpecs, + GlobalPointerSpecs = globalPointerSpecs, + NamesPool = namesPool + }; + } + + private TypeSpec[] ReadTypeSpecs(ScraperState state, HeaderDirectory header) + { + TypeSpec[] typeSpecs = new TypeSpec[header.TypesCount]; + + state.ResetPosition(state.HeaderStart + (long)header.TypesStart); + for (int i = 0; i < header.TypesCount; i++) + { + int bytesRead = 0; + typeSpecs[i].NameIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + typeSpecs[i].FieldsIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + ushort size = state.ReadUInt16(); + bytesRead += sizeof(ushort); + if (size != 0) + { + typeSpecs[i].Size = size; + } + WriteVerbose($"TypeSpec[{i}]: NameIdx = {typeSpecs[i].NameIdx}, FieldsIdx = {typeSpecs[i].FieldsIdx}, Size = {typeSpecs[i].Size}"); + // skip padding + if (bytesRead < header.TypeSpecSize) + { + state.Skip(header.TypeSpecSize - bytesRead); + } + } + return typeSpecs; + } + + private static FieldSpec[] ReadFieldSpecs(ScraperState state, HeaderDirectory header) + { + state.ResetPosition(state.HeaderStart + (long)header.FieldsPoolStart); + FieldSpec[] fieldSpecs = new FieldSpec[header.FieldsPoolCount]; + for (int i = 0; i < header.FieldsPoolCount; i++) + { + int bytesRead = 0; + fieldSpecs[i].NameIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + fieldSpecs[i].TypeNameIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + fieldSpecs[i].FieldOffset = state.ReadUInt16(); + bytesRead += sizeof(ushort); + // skip padding + if (bytesRead < header.FieldSpecSize) + { + state.Skip(header.FieldSpecSize - bytesRead); + } + } + return fieldSpecs; + } + + private static GlobalLiteralSpec[] ReadGlobalLiteralSpecs(ScraperState state, HeaderDirectory header) + { + GlobalLiteralSpec[] globalSpecs = new GlobalLiteralSpec[header.GlobalLiteralValuesCount]; + state.ResetPosition(state.HeaderStart + (long)header.GlobalLiteralValuesStart); + for (int i = 0; i < header.GlobalLiteralValuesCount; i++) + { + int bytesRead = 0; + globalSpecs[i].NameIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + globalSpecs[i].TypeNameIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + globalSpecs[i].Value = state.ReadUInt64(); + bytesRead += sizeof(ulong); + // skip padding + if (bytesRead < header.GlobalLiteralSpecSize) + { + state.Skip(header.GlobalLiteralSpecSize - bytesRead); + } + } + return globalSpecs; + } + + private static GlobalPointerSpec[] ReadGlobalPointerSpecs(ScraperState state, HeaderDirectory header) + { + GlobalPointerSpec[] globalSpecs = new GlobalPointerSpec[header.GlobalPointerValuesCount]; + state.ResetPosition(state.HeaderStart + (long)header.GlobalPointersStart); + for (int i = 0; i < header.GlobalPointerValuesCount; i++) + { + int bytesRead = 0; + globalSpecs[i].NameIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + globalSpecs[i].AuxDataIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + // skip padding + if (bytesRead < header.GlobalPointerSpecSize) + { + state.Skip(header.GlobalPointerSpecSize - bytesRead); + } + } + return globalSpecs; + } + + private static byte[] ReadNamesPool(ScraperState state, HeaderDirectory header) + { + byte[] namesPool = new byte[header.NamesPoolCount]; + state.ResetPosition(state.HeaderStart + (long)header.NamesStart); + state.ReadBytes(namesPool.AsSpan()); + return namesPool; + } + + private static bool CheckEndMagic(ReadOnlySpan bytes) + { + return (bytes[0] == 0x01 && bytes[1] == 0x02 && bytes[2] == 0x03 && bytes[3] == 0x04); + } + + private void WriteVerbose(string msg) + { + if (Verbose) + Console.WriteLine(msg); + } +} diff --git a/src/coreclr/tools/cdac-build-tool/Program.cs b/src/coreclr/tools/cdac-build-tool/Program.cs new file mode 100644 index 00000000000000..132c13d30fa119 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/Program.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.CommandLine; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +public class Program +{ + public static async Task Main(string[] args) + { + CliRootCommand rootCommand = new (); + var verboseOption = new CliOption("-v", "--verbose") {Recursive = true, Description = "Verbose"}; + rootCommand.Add(verboseOption); + rootCommand.Add(new DiagramDirective()); + rootCommand.Add(new ComposeCommand(verboseOption)); + return await rootCommand.Parse(args).InvokeAsync().ConfigureAwait(true); + } +} diff --git a/src/coreclr/tools/cdac-build-tool/README.md b/src/coreclr/tools/cdac-build-tool/README.md new file mode 100644 index 00000000000000..512026a29860b9 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/README.md @@ -0,0 +1,134 @@ +# cDAC Build Tool + +## Summary + +The purpose of `cdac-build-tool` is to generate a `.c` file that contains a JSON cDAC contract descriptor. + +It works by processing one or more object files containing data descriptors and zero or more text +files that specify contracts. + +## Running + +```console +% cdac-build-tool compose [-v] -o contractdescriptor.c -c contracts.txt datadescriptor.o +``` +## .NET runtime build integration + +`cdac-build-tool` is meant to run as a CMake custom command. +It consumes a target platform object file and emits a C source +file that contains a JSON contract descriptor. The C source +is then included in the normal build and link steps to create the runtime. + +The contract descriptor source file depends on `contractpointerdata.c` which is a source file that contains +the definitions of the "indirect pointer data" that is referenced by the data descriptor. This is typically the addresses of important global variables in the runtime. +Constants and build flags are embedded directly in the JSON payload. + +Multiple data descriptor source files may be specified (for example if they are produced by different components of the runtime, or by different source languages). The final JSON payload will be a composition of all the data descriptors. + +Multiple contracts text files may be specified. This may be useful if some contracts are conditionally included (for example if they are platform-specific). The final JSON payload will be a composition of all the contracts files. + +In the C/C++ data descriptor, we use a single header file `datadescriptor.h` together with the C preprocessor to produce `datadescriptor.c` and `contractpointerdata.c`. +This is an implementation detail. For data structures defined in other languages, other tools can be used to produce the object file and indirect pointer data. + +```mermaid +flowchart TB + headers("runtime headers") + data_header("datadescriptor.h") + data_src("datadescriptor.c") + compile_data["clang"] + data_obj("datadescriptor.o") + contracts("contracts.txt") + globals("contractpointerdata.c") + build[["cdac-build-tool"]] + descriptor_src("contractdescriptor.c") + vm("runtime sources") + compile_runtime["clang"] + runtime_lib(["libcoreclr.so"]) + + headers -.-> data_src + headers ~~~ data_header + data_header -.-> data_src + headers -.-> globals + headers -.-> vm + data_src --> compile_data --> data_obj --> build + contracts ---> build + build --> descriptor_src + descriptor_src --> compile_runtime + data_header -.-> globals ----> compile_runtime + vm ----> compile_runtime --> runtime_lib +``` + + +## Specifying data descriptors + +The sample in the `sample` dir uses the following syntax (see [sample/sample.data.h](sample/sample.data.h)) to specify the data descriptor: + +```c +CDAC_BASELINE("empty") +CDAC_TYPES_BEGIN() + +CDAC_TYPE_BEGIN(ManagedThread) +CDAC_TYPE_INDETERMINATE(ManagedThread) +CDAC_TYPE_FIELD(ManagedThread, GCHandle, GCHandle, offsetof(ManagedThread,m_gcHandle)) +CDAC_TYPE_FIELD(ManagedThread, pointer, Next, offsetof(ManagedThread,m_next)) +CDAC_TYPE_END(ManagedThread) + +CDAC_TYPE_BEGIN(GCHandle) +CDAC_TYPE_SIZE(sizeof(intptr_t)) +CDAC_TYPE_END(GCHandle) + +CDAC_TYPES_END() + +CDAC_GLOBALS_BEGIN() +CDAC_GLOBAL_POINTER(ManagedThreadStore, &g_managedThreadStore) +#if FEATURE_EH_FUNCLETS +CDAC_GLOBAL(FeatureEHFunclets, uint8, 1) +#else +CDAC_GLOBAL(FeatureEHFunclets, uint8, 0) +#endif +CDAC_GLOBAL(SomeMagicNumber, uint32, 42) +CDAC_GLOBALS_END() +``` + +The file is included multiple times with the macros variously defined in order to generate the +data descriptor blob. + +## Implementation Details + +See [data-descriptor-blob.md](./data-descriptor-blob.md) + +## Workflow + +### Porting and extending the data blob scraper + +When porting to a new architecture, or extending the blob contents, it is recommended to +first work with the sample blob, rather than the full CoreCLR descriptor. + +For example, if your target platform has a clang toolchain, something like this will provide a suitable +input for `cdac-build-tool`: + +```console +$ clang -target wasm32-unknown-unknown -c -o /tmp/sample.o src/coreclr/tools/cdac-build-tool/sample/sample.blob.c +``` + +If you are modifying the preprocessor macros, using `-E` to emit the preprocessed output is helpful as well. + +```console +$ clang -target x86_64-unknown-linux-gnu -E -o /tmp/sample.i .src/coreclr/tools/cdac-build-tool/sample/sample.blob.c +``` + +Running the `cdac-build-tool` with the `-v` verbose option will show progress + +```console +$ ./dotnet.sh run --project src/coreclr/tools/cdac-build-tool/cdac-build-tool.csproj -- compose -v -o /tmp/contract.c /tmp/sample.o +``` + +It is also helpful to run the `cdac-build-tool` under a debugger with a breakpoint in `ObjectFileScraper.ScrapeInput` + +**Release runtime builds** When building Release builds of the runtime, the build infrastructure +may turn on whole program optimizations. On some toolchains this may produce object files that +are a serialization of the internal compiler state, rather than a native object format. This may break +assumptions of the `cdac-build-tool` about global symbol initialization, for example constants and string literals might not be stored as binary integers or as byte sequences. In such cases, it may be +necessary to turn off global optimizations when compiling `datadescriptor.cpp`. This is okay to do because `datadescriptor.cpp` is not shipped as part of the runtime build - and in fact it has no executable functions at all. It is just used to gather type layout and size information. + +It is conceivable that some future C/C++ compiler with whole program optimizations turned on may remove unused struct fields. (Such that separately compiling `datadescriptor.cpp` would produce incorrect offsets). In that case, `cdac-build-tool` will need to use another technique to collect offsets for a runtime built with such a compiler. As of 2024, no compilers do this, however. diff --git a/src/coreclr/tools/cdac-build-tool/Resources/contract-descriptor.c.in b/src/coreclr/tools/cdac-build-tool/Resources/contract-descriptor.c.in new file mode 100644 index 00000000000000..c1f0edd7a66f9c --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/Resources/contract-descriptor.c.in @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include + +#ifdef _MSC_VER +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT __attribute__((visibility("default"))) +#endif + +struct DotNetRuntimeContractDescriptor +{ + uint64_t magic; + uint32_t flags; + const uint32_t descriptor_size; + const char *descriptor; + const uint32_t pointer_data_count; + uint32_t pad0; + const uintptr_t *pointer_data; +}; + +extern const uintptr_t contractDescriptorPointerData[]; + +DLLEXPORT struct DotNetRuntimeContractDescriptor DotNetRuntimeContractDescriptor; + +DLLEXPORT struct DotNetRuntimeContractDescriptor DotNetRuntimeContractDescriptor = { + .magic = 0x0043414443434e44ull, // "DNCCDAC\0" + .flags = %%platformFlags%%, + .descriptor_size = %%jsonDescriptorSize%%, + .descriptor = "%%jsonDescriptor%%", + .pointer_data_count = %%pointerDataCount%%, + .pointer_data = &contractDescriptorPointerData[0], +}; diff --git a/src/coreclr/tools/cdac-build-tool/cdac-build-tool.csproj b/src/coreclr/tools/cdac-build-tool/cdac-build-tool.csproj new file mode 100644 index 00000000000000..427a1eb4e9c91d --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/cdac-build-tool.csproj @@ -0,0 +1,32 @@ + + + + cdac-build-tool + Exe + enable + AnyCPU + $(NetCoreAppToolCurrent) + true + $(RuntimeBinDir)/cdac-build-tool + true + false + false + false + .NET runtime data contract build tool + Microsoft.DotNet.Diagnostics.DataContract + + + + + + + + Microsoft.DotNet.Diagnostics.DataContract.Baseline: + + + + + + + + diff --git a/src/coreclr/tools/cdac-build-tool/data-descriptor-blob.md b/src/coreclr/tools/cdac-build-tool/data-descriptor-blob.md new file mode 100644 index 00000000000000..b7321edd12c991 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/data-descriptor-blob.md @@ -0,0 +1,203 @@ +## On-disk target object binary blob descriptor + +### Summary + +This is an internal implemetnation detail allowing tooling to read target architecture structure sizes and offsets without understanding target architecture object formats. + +### Design requirements + +The design of the physical binary blob descriptor is constrained by the following requirements: +* The binary blob should be easy to process by examining an object file on disk - even if the object + file is for a foreign architecture/OS. It should be possible to read the binary blob purely by + looking at the bytes. Tooling should be able to analyze the blob without having to understand + relocation entries, dwarf debug info, symbols etc. +* It should be possible to produce the blob using the native C/C++/NativeAOT compiler for a given + target/architecture. In particular for a runtime written in C, the binary blob should be + constructible using C idioms. If the C compiler needs to pad or align the data, the blob format + should provide a way to iterate the blob contents without having to know anything about the target + platform ABI or C compiler conventions. +* It should be possible to create separate subsets of the physical descriptor (in the target runtime + object format) using separate toolchains (for example: in NativeAOT some of the struct layouts may + be described by the NativeAOT compiler, while some might be described by the C/C++ toolchain) and + to run a build host (not target architecture) tool to read and compose them into a single physical + binary blob before embedding it into the final NativeAOT runtime binary. + +This leads to the following overall strategy for the design: +* The physical blob is "self-contained": indirections are encoded as offsets from the beginning of + the blob (or other base offsets), whereas using pointers would mean that the encoding of the blob + would have relocations applied to it, which would preclude reading the blob out of of an object + file without understanding the object file format. +* The physical blob must be "self-describing": If the C compiler adds padding or alignment, the blob + descriptor must contain information for how to skip the padding/alignment data. +* The physical blob must be constructible using "lowest common denominator" target toolchain + tooling - the C preprocessor. That doesn't mean that tooling _must_ use the C preprocessor to + generate the blob, but the format must not exceed the capabilities of the C preprocessor. + + +### Blob + +Multi-byte values are in the target platform endianness. + +The blob's job is to encode descriptions of the .NET runtime's implementation types and their fields, +as well as globals. + +When encoding strings, we create a "string pool" in the data blob: a massive string literal +that concatentates all the names that we might need, separated by `"\0"` nul characters. To encode a name into another data structure, we write the offset of the name from the beginning of the string pool. We reserve the offset 0 to designate empty or invalid names. + +When encoding the fields of a type, we create a "field pool" in the data blob: a collection of field +descriptors delimited by an "empty field descriptor" (a field descriptor of a name index of 0). All +the fields for a single type are encoded as a contiguous run from a given field pool index until the next empty field descriptor. + +We're interested in encoding the following kinds of information: + +```c +// A type: +// We encode a data contract name and a collection of fields, and the size of the type. +struct TypeSpec +{ + uint32_t Name; + uint32_t Fields; + uint16_t Size; +}; + +// A field: +// We encode the field name, the type (or an empty name) and the offset of the field in the native +// struct. The size of the field is not part of the data descriptor. +struct FieldSpec +{ + uint32_t Name; + uint32_t TypeName; + uint16_t FieldOffset; +}; + +// A literal global value such as a constant, some flags bitmap, or the value of a preprocessor define: +// we record the name, an optional type name, and a value as an unsigned 64-bit value +struct GlobalLiteralSpec +{ + uint32_t Name; + uint32_t TypeName; + uint64_t Value; +}; + +// A global pointer value such as the addrress of some important datastructure: +// We record the name and the index of the global in the auxiliarly "pointer data" global which +// is compiled into the .NET runtime and contains the addresses of all the globals that are referenced +// from the data descriptor. +struct GlobalPointerSpec +{ + uint32_t Name; + uint32_t PointerDataIndex; +}; +``` + +The main data we want to emit to the object file is an instance of the following structure: + +```c +// The main payload of the object file. +struct BinaryBlobDataDescriptor +{ + // A directory giving the offsets of all the other content, + // the number of types, fields, global literals and pointers, and + // the sizes of the "Spec" structs, above, in order to account for any padding added + // by the C/C++ compiler. + struct Directory { + uint32_t FlagsAndBaselineStart; + uint32_t TypesStart; + + uint32_t FieldPoolStart; + uint32_t GlobalLiteralValuesStart; + + uint32_t GlobalPointersStart; + uint32_t NamesStart; + + uint32_t TypeCount; + uint32_t FieldPoolCount; + + uint32_t GlobalLiteralValuesCount; + uint32_t GlobalPointerValuesCount; + + uint32_t NamesPoolCount; + + uint8_t TypeSpecSize; + uint8_t FieldSpecSize; + uint8_t GlobalLiteralSpecSize; + uint8_t GlobalPointerSpecSize; + } Directory; + // Platform flags (primarily pointer size) + uint32_t PlatformFlags; + // a well-known name of the baseline data descriptor. the current descriptor + // records changes from this baseline. + uint32_t BaselineName; + // an array of type specs + struct TypeSpec Types[CDacBlobTypesCount]; + // all of the field specs - contiguous runs are all owned by the same type + struct FieldSpec FieldPool[CDacBlobFieldPoolCount]; + // an array of literal globals + struct GlobalLiteralSpec GlobalLiteralValues[CDacBlobGlobalLiteralsCount]; + // an array of pointer globals + struct GlobalPointerSpec GlobalPointerValues[CDacBlobGlobalPointersCount]; + // all of the names that might be referenced from elsewhere in BinaryBlobDataDescriptor, + // delimited by "\0" + uint8_t NamesPool[sizeof(struct CDacStringPoolSizes)]; + // an end magic value to validate that the name pool is of the expected length + uint8_t EndMagic[4]; // the bytes 0x01 0x02 0x03 0x04 +}; +``` + +Finally, the value that we write to the object file has this form: + +```c +struct MagicAndBlob { + // the magic value that we look for in the object file + // 0x00424F4C42434144ull - in little endian this is "DACBLOB\0" + uint64_t magic; + // the blob payload, described above + struct BinaryBlobDataDescriptor Blob; +}; +``` + +The `BinaryBlobDataDescriptor` begins with a directory that gives the relative offsets of the `PlatformFlags`, `Types`, `FieldPool`, +`GlobalLiteralValues`, `GlobalPointerValues` and `Names` fields of the blob. The number of elements of each of the arrays is +next. This is followed by the sizes of the spec structs. + +Rationale: If a `BinaryBlobDataDescriptor` is created via C macros, we want to embed the `offsetof` +and `sizeof` of the components of the blob into the blob itself without having to account for any +padding that the C compiler may introduce to enforce alignment. Additionally the `Directory` tries +to follow a common C alignment rule (we don't want padding introduced in the directory itself): +N-byte members are aligned to start on N-byte boundaries. + +The baseline is specified as an offset into the names pool. + +The types are given as an array of `TypeSpec` elements. Each one contains an offset into the +`NamesPool` giving the name of the type, An offset into the fields pool indicating the first +specified field of the type, and the size of the type in bytes or 0 if it is indeterminate. + +The fields pool is given as a sequence of `FieldSpec` elements. The fields for each type are given +in a contiguous subsequence and are terminated by a marker `FieldSpec` with a `Name` offset of 0. +(Thus if a type has an empty sequence of fields it just points to a marker field spec directly.) +For each field there is a name that gives an offset in the name pool and an offset indicating the +field's offset. + +The global constants are given as a sequence of `GlobalLiteralSpec` elements. Each global has a +name, type and a value. Globals that are the addresses in target memory, are in `GlobalPointerSpec` +elements. Each pointer element has a name and an index in a separately compiled pointer structure +that is linked into runtime . See +[contract-descriptor.md](/docs/design/datacontracts/contract-descriptor.md) + +The `NamesPool` is a single sequence of utf-8 bytes comprising the concatenation of all the type +field and global names including a terminating nul byte for each name. The same name may occur +multiple times. The names could be referenced by multiple type or multiple fields. (That is, a +clever blob emitter may pool strings). The first name in the name pool is the empty string (with +its nul byte). + +Rationale: we want to reserve the offset 0 as a marker. + +Names are referenced by giving their offset from the beginning of the `NamesPool`. Each name +extends until the first nul byte encountered at or past the beginning of the name. + + +## Example + +An example C header describing some data types is given in [sample.data.h](./sample/sample.data.h). And +example series of C macro preprocessor definitions that produces a constant blob `Blob` is given in +[sample.blob.c](./sample/sample.blob.c) diff --git a/src/coreclr/tools/cdac-build-tool/sample/sample.blob.c b/src/coreclr/tools/cdac-build-tool/sample/sample.blob.c new file mode 100644 index 00000000000000..b90b7eca0e932a --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/sample/sample.blob.c @@ -0,0 +1,553 @@ +#include +#include + +// example structures + +typedef struct ManagedThread ManagedThread; + +struct ManagedThread { + uint32_t garbage0; + uint32_t m_gcHandle; + uint32_t garbage1; + ManagedThread *m_next; +}; + +typedef struct ManagedThreadStore { + ManagedThread *threads; +} ManagedThreadStore; + +static ManagedThreadStore g_managedThreadStore; + +// end example structures + +// begin blob definition + +struct TypeSpec +{ + uint32_t Name; + uint32_t Fields; + uint16_t Size; +}; + +struct FieldSpec +{ + uint32_t Name; + uint32_t TypeName; + uint16_t FieldOffset; +}; + +struct GlobalLiteralSpec +{ + uint32_t Name; + uint32_t TypeName; + uint64_t Value; +}; + +struct GlobalPointerSpec +{ + uint32_t Name; + uint32_t AuxIndex; +}; + +#define CONCAT(token1,token2) token1 ## token2 +#define CONCAT4(token1, token2, token3, token4) token1 ## token2 ## token3 ## token4 + +#define MAKE_TYPELEN_NAME(tyname) CONCAT(cdac_string_pool_typename__, tyname) +#define MAKE_FIELDLEN_NAME(tyname,membername) CONCAT4(cdac_string_pool_membername__, tyname, __, membername) +#define MAKE_FIELDTYPELEN_NAME(tyname,membername) CONCAT4(cdac_string_pool_membertypename__, tyname, __, membername) +#define MAKE_GLOBALLEN_NAME(globalname) CONCAT(cdac_string_pool_globalname__, globalname) +#define MAKE_GLOBALTYPELEN_NAME(globalname) CONCAT(cdac_string_pool_globaltypename__, globalname) + +// define a struct where the size of each field is the length of some string. we will use offsetof to get +// the offset of each struct element, which will be equal to the offset of the beginning of that string in the +// string pool. +struct CDacStringPoolSizes +{ + char cdac_string_pool_nil; // make the first real string start at offset 1 +#define DECL_LEN(membername,len) char membername[(len)]; +#define CDAC_BASELINE(name) DECL_LEN(cdac_string_pool_baseline_, (sizeof(name))) +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) DECL_LEN(MAKE_TYPELEN_NAME(name), sizeof(#name)) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) DECL_LEN(MAKE_FIELDLEN_NAME(tyname,membername), sizeof(#membername)) \ + DECL_LEN(MAKE_FIELDTYPELEN_NAME(tyname,membername), sizeof(#membertyname)) +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) DECL_LEN(MAKE_GLOBALLEN_NAME(name), sizeof(#name)) +#define CDAC_GLOBAL(name,tyname,value) DECL_LEN(MAKE_GLOBALLEN_NAME(name), sizeof(#name)) \ + DECL_LEN(MAKE_GLOBALTYPELEN_NAME(name), sizeof(#tyname)) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END +}; + +#define GET_TYPE_NAME(name) offsetof(struct CDacStringPoolSizes, MAKE_TYPELEN_NAME(name)) +#define GET_FIELD_NAME(tyname,membername) offsetof(struct CDacStringPoolSizes, MAKE_FIELDLEN_NAME(tyname,membername)) +#define GET_FIELDTYPE_NAME(tyname,membername) offsetof(struct CDacStringPoolSizes, MAKE_FIELDTYPELEN_NAME(tyname,membername)) +#define GET_GLOBAL_NAME(globalname) offsetof(struct CDacStringPoolSizes, MAKE_GLOBALLEN_NAME(globalname)) +#define GET_GLOBALTYPE_NAME(globalname) offsetof(struct CDacStringPoolSizes, MAKE_GLOBALTYPELEN_NAME(globalname)) + +// count the types +enum +{ + CDacBlobTypesCount = +#define CDAC_BASELINE(name) 0 +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) + 1 +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + , +}; + +// count the field pool size. +// there's 1 placeholder element at the start, and 1 endmarker after each type +enum +{ + CDacBlobFieldsPoolCount = +#define CDAC_BASELINE(name) 1 +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) + 1 +#define CDAC_TYPE_END(name) + 1 +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + , +}; + +// count the literal globals +enum +{ + CDacBlobGlobalLiteralsCount = +#define CDAC_BASELINE(name) 0 +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) +#define CDAC_GLOBAL(name,tyname,value) + 1 +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + , +}; + +// count the aux vector globals +enum +{ + CDacBlobGlobalPointersCount = +#define CDAC_BASELINE(name) 0 +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) + 1 +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + , +}; + + +#define MAKE_TYPEFIELDS_TYNAME(tyname) CONCAT(CDacFieldsPoolTypeStart__, tyname) + +// index of each run of fields. +// we make a struct containing one 1-byte field for each field in the run, and then take the offset of the +// struct to get the index of the run of fields. +// this looks like +// +// struct CDacFieldsPoolSizes { +// char cdac_field_pool_start_placeholder__; +// struct CDacFieldsPoolTypeStart__MethodTable { +// char cdac_fields_pool_member__MethodTable__GCHandle; +// char cdac_fields_pool_member__MethodTable_endmarker; +// } CDacFieldsPoolTypeStart__MethodTable; +// ... +// }; +// +// so that offsetof(struct CDacFieldsPoolSizes, CDacFieldsPoolTypeStart__MethodTable) will give the offset of the +// method table field descriptors in the run of fields +struct CDacFieldsPoolSizes +{ +#define DECL_LEN(membername) char membername; +#define CDAC_BASELINE(name) DECL_LEN(cdac_fields_pool_start_placeholder__) +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) struct MAKE_TYPEFIELDS_TYNAME(name) { +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) DECL_LEN(CONCAT4(cdac_fields_pool_member__, tyname, __, membername)) +#define CDAC_TYPE_END(name) DECL_LEN(CONCAT4(cdac_fields_pool_member__, tyname, _, endmarker)) \ + } MAKE_TYPEFIELDS_TYNAME(name); +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END +#undef DECL_LEN +}; + +#define GET_TYPE_FIELDS(tyname) offsetof(struct CDacFieldsPoolSizes, MAKE_TYPEFIELDS_TYNAME(tyname)) + +// index of each global pointer +// +// struct CDacGlobalPointerIndex +// { +// char placeholder; +// char firstGlobalPointerName; +// char secondGlobalPointerName; +// ... +//} +// +// offsetof (CDACGlobalPointerIndex, NAME) returns the index of the global +struct CDacGlobalPointerIndex +{ +#define DECL_LEN(membername) char membername; +#define CDAC_BASELINE(name) DECL_LEN(cdac_global_pointer_index_start_placeholder__) +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) DECL_LEN(CONCAT(cdac_global_pointer_index__, name)) +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END +}; + +#define GET_GLOBAL_POINTER_INDEX(name) offsetof(struct CDacGlobalPointerIndex, CONCAT(cdac_global_pointer_index__, name)) + +struct BinaryBlobDataDescriptor +{ + // see data-descriptor-blob.md + struct Directory { + uint32_t FlagsAndBaselineStart; + uint32_t TypesStart; + + uint32_t FieldsPoolStart; + uint32_t GlobalLiteralValuesStart; + + uint32_t GlobalPointersStart; + uint32_t NamesPoolStart; + + uint32_t TypeCount; + uint32_t FieldsPoolCount; + + uint32_t GlobalLiteralValuesCount; + uint32_t GlobalPointerValuesCount; + + uint32_t NamesPoolCount; + + uint8_t TypeSpecSize; + uint8_t FieldSpecSize; + uint8_t GlobalLiteralSpecSize; + uint8_t GlobalPointerSpecSize; + } Directory; + uint32_t PlatformFlags; + uint32_t BaselineName; + struct TypeSpec Types[CDacBlobTypesCount]; + struct FieldSpec FieldsPool[CDacBlobFieldsPoolCount]; + struct GlobalLiteralSpec GlobalLiteralValues[CDacBlobGlobalLiteralsCount]; + struct GlobalPointerSpec GlobalPointerValues[CDacBlobGlobalPointersCount]; + uint8_t NamesPool[sizeof(struct CDacStringPoolSizes)]; + uint8_t EndMagic[4]; +}; + +struct MagicAndBlob { + uint64_t magic; + struct BinaryBlobDataDescriptor Blob; +}; + +const struct MagicAndBlob Blob = { + .magic = 0x00424F4C42434144ull,// "DACBLOB", + .Blob = { + .Directory = { + .FlagsAndBaselineStart = offsetof(struct BinaryBlobDataDescriptor, PlatformFlags), + .TypesStart = offsetof(struct BinaryBlobDataDescriptor, Types), + .FieldsPoolStart = offsetof(struct BinaryBlobDataDescriptor, FieldsPool), + .GlobalLiteralValuesStart = offsetof(struct BinaryBlobDataDescriptor, GlobalLiteralValues), + .GlobalPointersStart = offsetof(struct BinaryBlobDataDescriptor, GlobalPointerValues), + .NamesPoolStart = offsetof(struct BinaryBlobDataDescriptor, NamesPool), + .TypeCount = CDacBlobTypesCount, + .FieldsPoolCount = CDacBlobFieldsPoolCount, + .GlobalLiteralValuesCount = CDacBlobGlobalLiteralsCount, + .GlobalPointerValuesCount = CDacBlobGlobalPointersCount, + .NamesPoolCount = sizeof(struct CDacStringPoolSizes), + .TypeSpecSize = sizeof(struct TypeSpec), + .FieldSpecSize = sizeof(struct FieldSpec), + .GlobalLiteralSpecSize = sizeof(struct GlobalLiteralSpec), + .GlobalPointerSpecSize = sizeof(struct GlobalPointerSpec), + }, + .EndMagic = { 0x01, 0x02, 0x03, 0x04 }, + .PlatformFlags = 0x01 | (sizeof(void*) == 4 ? 0x02 : 0), + .BaselineName = offsetof(struct CDacStringPoolSizes, cdac_string_pool_baseline_), + + .NamesPool = ("\0" // starts with a nul +#define CDAC_BASELINE(name) name "\0" +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) #name "\0" +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) #membername "\0" #membertyname "\0" +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) #name "\0" +#define CDAC_GLOBAL(name,tyname,value) #name "\0" #tyname "\0" +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + ), + + .FieldsPool = { +#define CDAC_BASELINE(name) {0,}, +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) { \ + .Name = GET_FIELD_NAME(tyname,membername), \ + .TypeName = GET_FIELDTYPE_NAME(tyname,membername), \ + .FieldOffset = offset, \ +}, +#define CDAC_TYPE_END(name) { 0, }, +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + }, + + .Types = { +#define CDAC_BASELINE(name) +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) { \ + .Name = GET_TYPE_NAME(name), \ + .Fields = GET_TYPE_FIELDS(name), +#define CDAC_TYPE_INDETERMINATE(name) .Size = 0, +#define CDAC_TYPE_SIZE(size) .Size = size, +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) +#define CDAC_TYPE_END(name) }, +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + }, + + .GlobalLiteralValues = { +#define CDAC_BASELINE(name) +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) +#define CDAC_GLOBAL(name,tyname,value) { .Name = GET_GLOBAL_NAME(name), .TypeName = GET_GLOBALTYPE_NAME(name), .Value = value }, +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + }, + + .GlobalPointerValues = { +#define CDAC_BASELINE(name) +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) { .Name = GET_GLOBAL_NAME(name), .AuxIndex = GET_GLOBAL_POINTER_INDEX(name) }, +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + }, + } +}; + +// end blob definition diff --git a/src/coreclr/tools/cdac-build-tool/sample/sample.data.h b/src/coreclr/tools/cdac-build-tool/sample/sample.data.h new file mode 100644 index 00000000000000..e4b8bff98b5e43 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/sample/sample.data.h @@ -0,0 +1,24 @@ +CDAC_BASELINE("empty") +CDAC_TYPES_BEGIN() + +CDAC_TYPE_BEGIN(ManagedThread) +CDAC_TYPE_INDETERMINATE(ManagedThread) +CDAC_TYPE_FIELD(ManagedThread, GCHandle, GCHandle, offsetof(ManagedThread,m_gcHandle)) +CDAC_TYPE_FIELD(ManagedThread, pointer, Next, offsetof(ManagedThread,m_next)) +CDAC_TYPE_END(ManagedThread) + +CDAC_TYPE_BEGIN(GCHandle) +CDAC_TYPE_SIZE(sizeof(intptr_t)) +CDAC_TYPE_END(GCHandle) + +CDAC_TYPES_END() + +CDAC_GLOBALS_BEGIN() +CDAC_GLOBAL_POINTER(ManagedThreadStore, &g_managedThreadStore) +#if FEATURE_EH_FUNCLETS +CDAC_GLOBAL(FeatureEHFunclets, uint8, 1) +#else +CDAC_GLOBAL(FeatureEHFunclets, uint8, 0) +#endif +CDAC_GLOBAL(SomeMagicNumber, uint32, 42) +CDAC_GLOBALS_END() diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 345d5ac35f00e9..220e2684a0d7af 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -391,6 +391,7 @@ set(VM_HEADERS_WKS callhelpers.h callsiteinspect.h callconvbuilder.hpp + cdacoffsets.h ceemain.h clrconfignative.h clrex.h diff --git a/src/coreclr/vm/cdacoffsets.h b/src/coreclr/vm/cdacoffsets.h new file mode 100644 index 00000000000000..317ef41f736037 --- /dev/null +++ b/src/coreclr/vm/cdacoffsets.h @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef CDACOFFSETS_H__ +#define CDACOFFSETS_H__ + +// See data-descriptor.h +// +// If the offset of some field F in class C must be provided to cDAC, but the field is private, the +// class C should declare cdac_offsets as a friend: +// +// friend template struct cdac_offsets; +// +// and provide a specialization cdac_offsets with a constexpr size_t member providing the offset: +// +// template<> struct cdac_offsets { +// static constexpr size_t F_Offset = offsetof(C, F); +// }; +template +struct cdac_offsets +{ +}; + +#endif// CDACOFFSETS_H__ diff --git a/src/coreclr/vm/threads.h b/src/coreclr/vm/threads.h index 4241893ee522bb..67c4b6b83c975b 100644 --- a/src/coreclr/vm/threads.h +++ b/src/coreclr/vm/threads.h @@ -121,6 +121,7 @@ #include "gchandleutilities.h" #include "gcinfotypes.h" #include +#include "cdacoffsets.h" class Thread; class ThreadStore; @@ -4076,8 +4077,17 @@ class Thread private: bool m_hasPendingActivation; + + template friend struct ::cdac_offsets; }; +template<> +struct cdac_offsets +{ + static constexpr size_t ExposedObject = offsetof(Thread, m_ExposedObject); + static constexpr size_t Link = offsetof(Thread, m_Link); +}; + // End of class Thread typedef Thread::ForbidSuspendThreadHolder ForbidSuspendThreadHolder; diff --git a/src/native/corehost/apphost/static/singlefilehost.def b/src/native/corehost/apphost/static/singlefilehost.def index e1208056b83201..9d193783f950e1 100644 --- a/src/native/corehost/apphost/static/singlefilehost.def +++ b/src/native/corehost/apphost/static/singlefilehost.def @@ -18,3 +18,6 @@ g_dacTable = s_dacGlobals ; Used by profilers MetaDataGetDispenser + +; cDAC contract descriptor +DotNetRuntimeContractDescriptor diff --git a/src/native/corehost/apphost/static/singlefilehost_freebsdexports.src b/src/native/corehost/apphost/static/singlefilehost_freebsdexports.src index 1f9c5178218555..da5cab866d93fc 100644 --- a/src/native/corehost/apphost/static/singlefilehost_freebsdexports.src +++ b/src/native/corehost/apphost/static/singlefilehost_freebsdexports.src @@ -10,6 +10,9 @@ g_dacTable ; Used by profilers MetaDataGetDispenser +; cDAC contract descriptor +DotNetRuntimeContractDescriptor + ; FreeBSD needs to reexport these __progname environ diff --git a/src/native/corehost/apphost/static/singlefilehost_unixexports.src b/src/native/corehost/apphost/static/singlefilehost_unixexports.src index 18d5697e84580e..23c60f6b8b162c 100644 --- a/src/native/corehost/apphost/static/singlefilehost_unixexports.src +++ b/src/native/corehost/apphost/static/singlefilehost_unixexports.src @@ -9,3 +9,6 @@ g_dacTable ; Used by profilers MetaDataGetDispenser + +; cDAC contract descriptor +DotNetRuntimeContractDescriptor From 3cea1eeb6c04ebb7e81d47393b96ad51b66b8d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Fri, 19 Apr 2024 13:03:55 +0900 Subject: [PATCH 003/248] Ignore ControlFlowGuard outside Windows (#101268) Don't deoptimize dehydration for this. --- .../nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index 988a02dd8792d8..ce4a3236f58e30 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -229,7 +229,7 @@ The .NET Foundation licenses this file to you under the MIT license. - + From e2572ba2d8787c530d5b909106fc4854895dfc19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Fri, 19 Apr 2024 16:57:05 +0900 Subject: [PATCH 004/248] Enable control flow guard for AOT compilers (#101269) --- src/coreclr/tools/aot/AotCompilerCommon.props | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/tools/aot/AotCompilerCommon.props b/src/coreclr/tools/aot/AotCompilerCommon.props index 09d3cfdc92edce..90e63a4bff9831 100644 --- a/src/coreclr/tools/aot/AotCompilerCommon.props +++ b/src/coreclr/tools/aot/AotCompilerCommon.props @@ -4,6 +4,7 @@ false true Speed + Guard From 5d38457bf3293d8a5af34a1b170f47a42c3c08cf Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Fri, 19 Apr 2024 02:32:23 -0700 Subject: [PATCH 005/248] Workaround for build failure when EmitCompilerGeneratedFiles=true (#101279) When we build `cdacreader`, we run the `LinkNative` target. This depends on `Compile` not `Build`, which means the `BuildOnlySettings` target that sets `BuildingProject=true` doesn't run. When `EmitCompilerGeneratedFiles=true`, this results in the generated output path not being created and the compiler erroring when trying to emit files to the path. See https://github.com/dotnet/roslyn/issues/73075. CodeQL injects `-p:EmitCompilerGeneratedFiles=true` into the command line arguments. This was resulting in build failures in jobs where CodeQL is run. This change adds a workaround to our infrastructure for building NativeAOT-ed runtime components such that the generated output path is always created if `EmitCompilerGeneratedFiles=true`. Manually tested by explicitly passing that property on the command line. Fixes https://github.com/dotnet/source-build/issues/4335 --- src/native/managed/native-library.targets | 220 ++++++++++++---------- 1 file changed, 116 insertions(+), 104 deletions(-) diff --git a/src/native/managed/native-library.targets b/src/native/managed/native-library.targets index d1ad1ba0223639..298da3c50ce786 100644 --- a/src/native/managed/native-library.targets +++ b/src/native/managed/native-library.targets @@ -1,107 +1,119 @@ - - - - - $(OutputPath)stripped\ - $(StrippedOutputPath)$(TargetName)$(NativeBinaryExt) - .dylib.dwarf - .so.dbg - $(StrippedOutputPath)$(TargetName)$(StrippedExt) - - - - - - - true - - - - - - false - - - - - - - - - - - - - <_StripLike Condition="'$(TargetsOSX)' == 'true' or '$(TargetsAppleMobile)' == 'true'">apple - <_StripLike Condition="'$(_StripLike)' == ''">gnu - - - - - - - - - - - - - - - - - - $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', '$(RuntimeFlavor.ToLower())', '$(TargetOS).$(TargetArchitecture).$(RuntimeConfiguration)')) - - - - <_NormalizedInstallRuntimeComponentDest Include="$([MSBuild]::NormalizeDirectory('$(FinalRuntimeComponentDestinationBase)', '%(InstallRuntimeComponentDestination.Identity)'))" /> - - - - - - - - - - - - - - - - - - - + + + + + + + + + $(OutputPath)stripped\ + $(StrippedOutputPath)$(TargetName)$(NativeBinaryExt) + .dylib.dwarf + .so.dbg + $(StrippedOutputPath)$(TargetName)$(StrippedExt) + + + + + + + true + + + + + + false + + + + + + + + + + + + + <_StripLike Condition="'$(TargetsOSX)' == 'true' or '$(TargetsAppleMobile)' == 'true'">apple + <_StripLike Condition="'$(_StripLike)' == ''">gnu + + + + + + + + + + + + + + + + + + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', '$(RuntimeFlavor.ToLower())', '$(TargetOS).$(TargetArchitecture).$(RuntimeConfiguration)')) + + + + <_NormalizedInstallRuntimeComponentDest Include="$([MSBuild]::NormalizeDirectory('$(FinalRuntimeComponentDestinationBase)', '%(InstallRuntimeComponentDestination.Identity)'))" /> + + + + + + + + + + + + + + + + + + From 4f889f6dd51968344c60c045787fa0662141be27 Mon Sep 17 00:00:00 2001 From: Andrii Patsula Date: Fri, 19 Apr 2024 11:53:44 +0200 Subject: [PATCH 006/248] Pass GitHubRepositoryName as a build argument. (#101241) --- eng/DotNetBuild.props | 1 + 1 file changed, 1 insertion(+) diff --git a/eng/DotNetBuild.props b/eng/DotNetBuild.props index 52abdf92f094a2..9d68b8265b0c1f 100644 --- a/eng/DotNetBuild.props +++ b/eng/DotNetBuild.props @@ -84,6 +84,7 @@ $(InnerBuildArgs) /p:SourceBuiltNonShippingPackagesDir=$(SourceBuiltNonShippingPackagesDir) $(InnerBuildArgs) /p:SourceBuiltAssetManifestsDir=$(SourceBuiltAssetManifestsDir) $(InnerBuildArgs) /p:SourceBuiltSymbolsDir=$(SourceBuiltSymbolsDir) + $(InnerBuildArgs) /p:GitHubRepositoryName=$(GitHubRepositoryName) From 9c237f000246d98813827100bf577d8ea7e3f575 Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Fri, 19 Apr 2024 12:01:43 +0200 Subject: [PATCH 007/248] [browser][MT] faster memory view refresh + cleanup (#101249) --- src/mono/browser/runtime/cancelable-promise.ts | 4 +--- src/mono/browser/runtime/marshal.ts | 4 +--- src/mono/browser/runtime/memory.ts | 8 +++++--- src/mono/browser/runtime/scheduling.ts | 4 +--- src/mono/browser/runtime/web-socket.ts | 16 ++++------------ 5 files changed, 12 insertions(+), 24 deletions(-) diff --git a/src/mono/browser/runtime/cancelable-promise.ts b/src/mono/browser/runtime/cancelable-promise.ts index c82cbdacb19609..6964bee80dc538 100644 --- a/src/mono/browser/runtime/cancelable-promise.ts +++ b/src/mono/browser/runtime/cancelable-promise.ts @@ -166,9 +166,7 @@ export class PromiseHolder extends ManagedObject { try { mono_assert(!this.isPosted, "Promise is already posted to managed."); this.isPosted = true; - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } + forceThreadMemoryViewRefresh(); // we can unregister the GC handle just on JS side teardown_managed_proxy(this, this.gc_handle, /*skipManaged: */ true); diff --git a/src/mono/browser/runtime/marshal.ts b/src/mono/browser/runtime/marshal.ts index c0ece106f53b2a..e49387cc51eef9 100644 --- a/src/mono/browser/runtime/marshal.ts +++ b/src/mono/browser/runtime/marshal.ts @@ -65,9 +65,7 @@ const enum JSBindingHeaderOffsets { } export function alloc_stack_frame (size: number): JSMarshalerArguments { - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } + forceThreadMemoryViewRefresh(); const bytes = JavaScriptMarshalerArgSize * size; const args = Module.stackAlloc(bytes) as any; _zero_region(args, bytes); diff --git a/src/mono/browser/runtime/memory.ts b/src/mono/browser/runtime/memory.ts index 5a0ac71d3b3295..52b5b581a5bd71 100644 --- a/src/mono/browser/runtime/memory.ts +++ b/src/mono/browser/runtime/memory.ts @@ -447,8 +447,8 @@ export function copyBytes (srcPtr: VoidPtr, dstPtr: VoidPtr, bytes: number): voi // on non-MT build, this will be a no-op trimmed by rollup export function receiveWorkerHeapViews () { if (!WasmEnableThreads) return; - const memory = runtimeHelpers.getMemory(); - if (memory.buffer !== Module.HEAPU8.buffer) { + const wasmMemory = runtimeHelpers.getMemory(); + if (wasmMemory.buffer !== Module.HEAPU8.buffer) { runtimeHelpers.updateMemoryViews(); } } @@ -484,5 +484,7 @@ export function forceThreadMemoryViewRefresh () { This only works because their implementation does not skip doing work even when you ask to grow by 0 pages. */ wasmMemory.grow(0); - runtimeHelpers.updateMemoryViews(); + if (wasmMemory.buffer !== Module.HEAPU8.buffer) { + runtimeHelpers.updateMemoryViews(); + } } diff --git a/src/mono/browser/runtime/scheduling.ts b/src/mono/browser/runtime/scheduling.ts index 0be8cb19a72336..62c02961c5ce49 100644 --- a/src/mono/browser/runtime/scheduling.ts +++ b/src/mono/browser/runtime/scheduling.ts @@ -79,9 +79,7 @@ export function mono_wasm_schedule_timer (shortestDueTimeMs: number): void { function mono_wasm_schedule_timer_tick () { if (WasmEnableThreads) return; Module.maybeExit(); - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } + forceThreadMemoryViewRefresh(); if (!loaderHelpers.is_runtime_running()) { return; } diff --git a/src/mono/browser/runtime/web-socket.ts b/src/mono/browser/runtime/web-socket.ts index d97cc76cefe4a6..b328943ceaa6de 100644 --- a/src/mono/browser/runtime/web-socket.ts +++ b/src/mono/browser/runtime/web-socket.ts @@ -78,9 +78,7 @@ export function ws_wasm_create (uri: string, sub_protocols: string[] | null, rec try { if (ws[wasm_ws_is_aborted]) return; if (!loaderHelpers.is_runtime_running()) return; - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } + forceThreadMemoryViewRefresh(); open_promise_control.resolve(ws); prevent_timer_throttling(); } catch (error: any) { @@ -91,9 +89,7 @@ export function ws_wasm_create (uri: string, sub_protocols: string[] | null, rec try { if (ws[wasm_ws_is_aborted]) return; if (!loaderHelpers.is_runtime_running()) return; - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } + forceThreadMemoryViewRefresh(); web_socket_on_message(ws, ev); prevent_timer_throttling(); } catch (error: any) { @@ -105,9 +101,7 @@ export function ws_wasm_create (uri: string, sub_protocols: string[] | null, rec ws.removeEventListener("message", local_on_message); if (ws[wasm_ws_is_aborted]) return; if (!loaderHelpers.is_runtime_running()) return; - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } + forceThreadMemoryViewRefresh(); ws[wasm_ws_close_received] = true; ws["close_status"] = ev.code; @@ -137,9 +131,7 @@ export function ws_wasm_create (uri: string, sub_protocols: string[] | null, rec try { if (ws[wasm_ws_is_aborted]) return; if (!loaderHelpers.is_runtime_running()) return; - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } + forceThreadMemoryViewRefresh(); ws.removeEventListener("message", local_on_message); const message = ev.message ? "WebSocket error: " + ev.message From 6e051982f172b74b543067001e1ba5b3e357c421 Mon Sep 17 00:00:00 2001 From: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Fri, 19 Apr 2024 13:59:59 +0300 Subject: [PATCH 008/248] Extend the copy propagation type check to local field cases (#101256) NOL locals are not modeled faithfully by VN, which makes this type check universally necessary. --- src/coreclr/jit/copyprop.cpp | 18 +++--- src/tests/Directory.Build.props | 1 + .../JitBlue/Runtime_101034/Runtime_101034.cs | 58 +++++++++++++++++++ .../Runtime_101034/Runtime_101034.csproj | 8 +++ 4 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_101034/Runtime_101034.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_101034/Runtime_101034.csproj diff --git a/src/coreclr/jit/copyprop.cpp b/src/coreclr/jit/copyprop.cpp index bb645b26bb4902..11bce9e358e3d3 100644 --- a/src/coreclr/jit/copyprop.cpp +++ b/src/coreclr/jit/copyprop.cpp @@ -230,18 +230,16 @@ bool Compiler::optCopyProp( continue; } - if (tree->OperIs(GT_LCL_VAR)) + var_types newLclType = newLclVarDsc->TypeGet(); + if (!newLclVarDsc->lvNormalizeOnLoad()) { - var_types newLclType = newLclVarDsc->TypeGet(); - if (!newLclVarDsc->lvNormalizeOnLoad()) - { - newLclType = genActualType(newLclType); - } + newLclType = genActualType(newLclType); + } - if (newLclType != tree->TypeGet()) - { - continue; - } + var_types oldLclType = tree->OperIs(GT_LCL_VAR) ? tree->TypeGet() : varDsc->TypeGet(); + if (newLclType != oldLclType) + { + continue; } #ifdef DEBUG diff --git a/src/tests/Directory.Build.props b/src/tests/Directory.Build.props index 1575beb7044ad0..8f85e3a0c293f2 100644 --- a/src/tests/Directory.Build.props +++ b/src/tests/Directory.Build.props @@ -141,6 +141,7 @@ false false false + true diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_101034/Runtime_101034.cs b/src/tests/JIT/Regression/JitBlue/Runtime_101034/Runtime_101034.cs new file mode 100644 index 00000000000000..751dceda19632c --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_101034/Runtime_101034.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using Xunit; + +public static unsafe class Runtime_101034 +{ + [Fact] + public static void Test() + { + StructWithTwoShorts x = new() { ShortOne = -1, ShortTwo = -1 }; + StructWithThreeBytes y = default; + Problem(&x, &y); + Assert.True(y.ByteThree == 0); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static StructWithTwoShorts Problem(StructWithTwoShorts* s, StructWithThreeBytes* p) + { + StructWithTwoShorts y = *s; + + int z = 255; + ForceILLocal(&z); + if (z == 255) + { + y.ShortOne = 255; + } + else + { + y.ShortOne = 1; + } + + if (p != null) + { + int x = 255; + *p = Unsafe.As(ref x); + } + + return y; + } + + private static void ForceILLocal(void* x) { } + + struct StructWithTwoShorts + { + public short ShortOne; + public short ShortTwo; + } + + struct StructWithThreeBytes + { + public byte ByteOne; + public byte ByteTwo; + public byte ByteThree; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_101034/Runtime_101034.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_101034/Runtime_101034.csproj new file mode 100644 index 00000000000000..de6d5e08882e86 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_101034/Runtime_101034.csproj @@ -0,0 +1,8 @@ + + + True + + + + + From a3bf7d4804c86f17087b216fec74d9b496ec0001 Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Fri, 19 Apr 2024 13:39:07 +0200 Subject: [PATCH 009/248] [browser] make slow Utf8JsonWriterTests test OuterLoop (#101283) --- .../tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs index 7ccda56d737a2a..c776982b56d925 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs @@ -3072,6 +3072,7 @@ public void WritingHugeBase64Bytes(JsonWriterOptions options) [Theory] [MemberData(nameof(JsonOptions_TestData))] [SkipOnCoreClr("https://github.com/dotnet/runtime/issues/45464", ~RuntimeConfiguration.Release)] + [OuterLoop("Too slow", typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] public void Writing3MBBase64Bytes(JsonWriterOptions options) { byte[] value = new byte[3 * 1024 * 1024]; @@ -4421,6 +4422,7 @@ public void EscapeAsciiCharacters(JsonWriterOptions options) [Theory] [MemberData(nameof(JsonOptions_TestData))] + [OuterLoop("Too slow", typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] public void EscapeCharacters(JsonWriterOptions options) { // Do not include surrogate pairs. @@ -5303,6 +5305,7 @@ public void WriteDoubleValue(JsonWriterOptions options, double value) [Theory] [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] [MemberData(nameof(WriteValue_TestData))] + [OuterLoop("Too slow", typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] public void WriteNumbers(JsonWriterOptions options, string keyString) { var random = new Random(42); From ce6355775ae539d337896098f3a5960926a75106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Fri, 19 Apr 2024 21:31:53 +0900 Subject: [PATCH 010/248] Stop building AppHost in native AOT testing (#101270) Fixes #79575. --- eng/pipelines/coreclr/runtime-nativeaot-outerloop.yml | 10 +++++----- eng/pipelines/runtime-sanitized.yml | 2 +- eng/pipelines/runtime.yml | 8 ++++---- eng/testing/linker/trimmingTests.targets | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/eng/pipelines/coreclr/runtime-nativeaot-outerloop.yml b/eng/pipelines/coreclr/runtime-nativeaot-outerloop.yml index e8bfd86cd81dd2..494601a890df12 100644 --- a/eng/pipelines/coreclr/runtime-nativeaot-outerloop.yml +++ b/eng/pipelines/coreclr/runtime-nativeaot-outerloop.yml @@ -69,7 +69,7 @@ extends: testGroup: innerloop isSingleFile: true nameSuffix: NativeAOT_Libs - buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) /p:TestNativeAot=true /p:ArchiveTests=true /p:IlcUseServerGc=false /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs+libs.tests -c $(_BuildConfig) /p:TestNativeAot=true /p:ArchiveTests=true /p:IlcUseServerGc=false /p:RunAnalyzers=false timeoutInMinutes: 300 # doesn't normally take this long, but I've seen Helix queues backed up for 160 minutes includeAllPlatforms: true # extra steps, run tests @@ -95,7 +95,7 @@ extends: testGroup: innerloop isSingleFile: true nameSuffix: NativeAOT_Checked_Libs - buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:IlcUseServerGc=false /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:IlcUseServerGc=false /p:RunAnalyzers=false timeoutInMinutes: 360 # extra steps, run tests postBuildSteps: @@ -120,7 +120,7 @@ extends: testGroup: innerloop isSingleFile: true nameSuffix: NativeAOT_Checked_Libs_SizeOpt - buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:OptimizationPreference=Size /p:IlcUseServerGc=false /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:OptimizationPreference=Size /p:IlcUseServerGc=false /p:RunAnalyzers=false timeoutInMinutes: 240 # extra steps, run tests postBuildSteps: @@ -145,7 +145,7 @@ extends: testGroup: innerloop isSingleFile: true nameSuffix: NativeAOT_Checked_Libs_SpeedOpt - buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:OptimizationPreference=Speed /p:IlcUseServerGc=false /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:OptimizationPreference=Speed /p:IlcUseServerGc=false /p:RunAnalyzers=false timeoutInMinutes: 240 # extra steps, run tests postBuildSteps: @@ -176,7 +176,7 @@ extends: jobParameters: timeoutInMinutes: 300 # doesn't normally take this long, but we have had Helix queues backed up for over an hour nameSuffix: NativeAOT_Pri0 - buildArgs: -s clr.aot+host.native+libs -rc $(_BuildConfig) -lc Release -hc Release /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs -rc $(_BuildConfig) -lc Release /p:RunAnalyzers=false postBuildSteps: - template: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml parameters: diff --git a/eng/pipelines/runtime-sanitized.yml b/eng/pipelines/runtime-sanitized.yml index ed0334b61b3e9d..df461c03b7a70a 100644 --- a/eng/pipelines/runtime-sanitized.yml +++ b/eng/pipelines/runtime-sanitized.yml @@ -133,7 +133,7 @@ extends: testGroup: innerloop timeoutInMinutes: 120 nameSuffix: NativeAOT - buildArgs: -s clr.aot+host.native+libs -rc $(_BuildConfig) -lc Release -hc Release $(_nativeSanitizersArg) + buildArgs: -s clr.aot+libs -rc $(_BuildConfig) -lc Release $(_nativeSanitizersArg) postBuildSteps: - template: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml parameters: diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index f0591ff810c37a..338d53251f6ceb 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -567,7 +567,7 @@ extends: jobParameters: timeoutInMinutes: 120 nameSuffix: NativeAOT - buildArgs: -s clr.aot+host.native+libs -rc $(_BuildConfig) -lc Release -hc Release /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs -rc $(_BuildConfig) -lc Release /p:RunAnalyzers=false postBuildSteps: - template: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml parameters: @@ -606,7 +606,7 @@ extends: jobParameters: timeoutInMinutes: 180 nameSuffix: NativeAOT - buildArgs: -s clr.aot+host.native+libs.native+libs.sfx -rc $(_BuildConfig) -lc Release -hc Release /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs.native+libs.sfx -rc $(_BuildConfig) -lc Release /p:RunAnalyzers=false postBuildSteps: - template: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml parameters: @@ -651,7 +651,7 @@ extends: testGroup: innerloop timeoutInMinutes: 120 nameSuffix: NativeAOT - buildArgs: -s clr.aot+host.native+libs+tools.illink -c $(_BuildConfig) -rc $(_BuildConfig) -lc Release -hc Release /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs+tools.illink -c $(_BuildConfig) -rc $(_BuildConfig) -lc Release /p:RunAnalyzers=false postBuildSteps: - template: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml parameters: @@ -688,7 +688,7 @@ extends: testGroup: innerloop isSingleFile: true nameSuffix: NativeAOT_Libraries - buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) /p:TestNativeAot=true /p:RunSmokeTestsOnly=true /p:ArchiveTests=true /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs+libs.tests -c $(_BuildConfig) /p:TestNativeAot=true /p:RunSmokeTestsOnly=true /p:ArchiveTests=true /p:RunAnalyzers=false timeoutInMinutes: 240 # Doesn't actually take long, but we've seen the ARM64 Helix queue often get backlogged for 2+ hours # extra steps, run tests postBuildSteps: diff --git a/eng/testing/linker/trimmingTests.targets b/eng/testing/linker/trimmingTests.targets index 926bafa52cfef4..b29bc1dc75cf5b 100644 --- a/eng/testing/linker/trimmingTests.targets +++ b/eng/testing/linker/trimmingTests.targets @@ -142,7 +142,7 @@ + Properties="Configuration=$(Configuration);BuildProjectReferences=false;TargetOS=$(TargetOS);TargetArchitecture=$(TargetArchitecture);_IsPublishing=true" /> Date: Fri, 19 Apr 2024 10:28:09 -0400 Subject: [PATCH 011/248] SHAKE Read, Reset, and Clone --- .../Interop.Evp.cs | 15 ++ .../Interop.EVP.cs | 22 ++ .../ref/System.Security.Cryptography.cs | 8 + .../src/Resources/Strings.resx | 3 + .../Security/Cryptography/LiteHash.Apple.cs | 2 + .../Security/Cryptography/LiteHash.Browser.cs | 2 + .../Security/Cryptography/LiteHash.Unix.cs | 18 ++ .../Security/Cryptography/LiteHash.Windows.cs | 77 +++--- .../System/Security/Cryptography/Shake128.cs | 110 +++++++- .../System/Security/Cryptography/Shake256.cs | 110 +++++++- .../tests/Shake128Tests.cs | 4 + .../tests/Shake256Tests.cs | 4 + .../tests/ShakeTestDriver.cs | 238 +++++++++++++++++- .../configure.cmake | 5 + .../entrypoints.c | 2 + .../opensslshim.h | 9 + .../pal_crypto_config.h.in | 1 + .../pal_evp.c | 29 ++- .../pal_evp.h | 17 ++ 19 files changed, 639 insertions(+), 37 deletions(-) diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.cs index e94a88249a1d0a..59e93080c562e8 100644 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.cs +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.cs @@ -56,6 +56,21 @@ internal static unsafe int EvpDigestCurrentXOF(SafeEvpMdCtxHandle ctx, Span destination) + { + _ = ctx; + _ = destination; + Debug.Fail("Should have validated that XOF is not supported before getting here."); + throw new UnreachableException(); + } + internal static readonly int EVP_MAX_MD_SIZE = GetMaxMdSize(); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs index 088ee79ab02580..f9fd00f227f4e7 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs @@ -9,6 +9,9 @@ internal static partial class Interop { internal static partial class Crypto { + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMdCtxCopyEx")] + internal static partial SafeEvpMdCtxHandle EvpMdCtxCopyEx(SafeEvpMdCtxHandle ctx); + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMdCtxCreate")] internal static partial SafeEvpMdCtxHandle EvpMdCtxCreate(IntPtr type); @@ -18,6 +21,13 @@ internal static partial class Crypto [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestReset")] internal static partial int EvpDigestReset(SafeEvpMdCtxHandle ctx, IntPtr type); + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestSqueeze")] + private static partial int EvpDigestSqueeze( + SafeEvpMdCtxHandle ctx, + Span md, + uint len, + [MarshalAs(UnmanagedType.Bool)] out bool haveFeature); + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestUpdate")] internal static partial int EvpDigestUpdate(SafeEvpMdCtxHandle ctx, ReadOnlySpan d, int cnt); @@ -89,6 +99,18 @@ internal static unsafe int EvpDigestXOFOneShot(IntPtr type, ReadOnlySpan s return EvpDigestXOFOneShot(type, source, source.Length, destination, (uint)destination.Length); } + internal static int EvpDigestSqueeze(SafeEvpMdCtxHandle ctx, Span destination) + { + int ret = EvpDigestSqueeze(ctx, destination, (uint)destination.Length, out bool haveFeature); + + if (!haveFeature) + { + throw new PlatformNotSupportedException(); + } + + return ret; + } + internal static readonly int EVP_MAX_MD_SIZE = GetMaxMdSize(); } } diff --git a/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs b/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs index a6ee388c8ceca2..4bd007d9030c39 100644 --- a/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs +++ b/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs @@ -2587,6 +2587,7 @@ public Shake128() { } public static bool IsSupported { get { throw null; } } public void AppendData(byte[] data) { } public void AppendData(System.ReadOnlySpan data) { } + public System.Security.Cryptography.Shake128 Clone() { throw null; } public void Dispose() { } public byte[] GetCurrentHash(int outputLength) { throw null; } public void GetCurrentHash(System.Span destination) { } @@ -2599,6 +2600,9 @@ public static void HashData(System.IO.Stream source, System.Span destinati public static void HashData(System.ReadOnlySpan source, System.Span destination) { } public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, int outputLength, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public byte[] Read(int outputLength) { throw null; } + public void Read(System.Span destination) { } + public void Reset() { } } public sealed partial class Shake256 : System.IDisposable { @@ -2606,6 +2610,7 @@ public Shake256() { } public static bool IsSupported { get { throw null; } } public void AppendData(byte[] data) { } public void AppendData(System.ReadOnlySpan data) { } + public System.Security.Cryptography.Shake256 Clone() { throw null; } public void Dispose() { } public byte[] GetCurrentHash(int outputLength) { throw null; } public void GetCurrentHash(System.Span destination) { } @@ -2618,6 +2623,9 @@ public static void HashData(System.IO.Stream source, System.Span destinati public static void HashData(System.ReadOnlySpan source, System.Span destination) { } public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, int outputLength, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public byte[] Read(int outputLength) { throw null; } + public void Read(System.Span destination) { } + public void Reset() { } } public partial class SignatureDescription { diff --git a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx index b121f8fd75c2d8..05c91987126a78 100644 --- a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx @@ -780,6 +780,9 @@ The algorithm's block size is not supported. + + This operation is not supported once the algorithm has started reading. + CryptoApi ECDsa keys are not supported. diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Apple.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Apple.cs index 0b2fde720a20d4..1dbfd5567f02ea 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Apple.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Apple.cs @@ -39,6 +39,8 @@ internal static LiteXof CreateXof(string hashAlgorithmId) public int Finalize(Span destination) => throw new UnreachableException(); public void Current(Span destination) => throw new UnreachableException(); public int Reset() => throw new UnreachableException(); + public LiteXof Clone() => throw new UnreachableException(); + public void Read(Span destination) => throw new UnreachableException(); public void Dispose() => throw new UnreachableException(); #pragma warning restore IDE0060 #pragma warning restore CA1822 diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Browser.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Browser.cs index 92de5db403f3dc..5591479f0c794b 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Browser.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Browser.cs @@ -34,6 +34,8 @@ internal static LiteXof CreateXof(string hashAlgorithmId) public int Finalize(Span destination) => throw new UnreachableException(); public void Current(Span destination) => throw new UnreachableException(); public int Reset() => throw new UnreachableException(); + public LiteXof Clone() => throw new UnreachableException(); + public void Read(Span destination) => throw new UnreachableException(); public void Dispose() => throw new UnreachableException(); #pragma warning restore IDE0060 #pragma warning restore CA1822 diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Unix.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Unix.cs index ab09b7217f89a4..32ebdb5ce092cd 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Unix.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Unix.cs @@ -44,6 +44,12 @@ internal LiteXof(IntPtr algorithm) Interop.Crypto.CheckValidOpenSslHandle(_ctx); } + private LiteXof(SafeEvpMdCtxHandle ctx, IntPtr algorithm) + { + _ctx = ctx; + _algorithm = algorithm; + } + public void Append(ReadOnlySpan data) { if (data.IsEmpty) @@ -70,6 +76,18 @@ public void Current(Span destination) Check(Interop.Crypto.EvpDigestCurrentXOF(_ctx, destination)); } + public LiteXof Clone() + { + SafeEvpMdCtxHandle clone = Interop.Crypto.EvpMdCtxCopyEx(_ctx); + Interop.Crypto.CheckValidOpenSslHandle(clone); + return new LiteXof(clone, _algorithm); + } + + public void Read(Span destination) + { + Check(Interop.Crypto.EvpDigestSqueeze(_ctx, destination)); + } + public void Dispose() { _ctx.Dispose(); diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Windows.cs index bb3df4bb2f4c54..324001daee995e 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Windows.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Windows.cs @@ -159,10 +159,11 @@ private static void CheckStatus(NTSTATUS status) } } - internal struct LiteXof : ILiteHash + internal readonly struct LiteXof : ILiteHash { + private const int BCRYPT_HASH_DONT_RESET_FLAG = 0x00000001; private readonly nuint _algorithm; - private SafeBCryptHashHandle _hashHandle; + private readonly SafeBCryptHashHandle _hashHandle; internal LiteXof(string algorithm) { @@ -173,7 +174,24 @@ internal LiteXof(string algorithm) _ => throw FailThrow(algorithm), }; - Reset(); + SafeBCryptHashHandle hashHandle; + + NTSTATUS ntStatus = Interop.BCrypt.BCryptCreateHash( + _algorithm, + out hashHandle, + pbHashObject: IntPtr.Zero, + cbHashObject: 0, + secret: ReadOnlySpan.Empty, + cbSecret: 0, + BCryptCreateHashFlags.None); + + if (ntStatus != NTSTATUS.STATUS_SUCCESS) + { + hashHandle.Dispose(); + throw Interop.BCrypt.CreateCryptographicException(ntStatus); + } + + _hashHandle = hashHandle; static Exception FailThrow(string algorithm) { @@ -182,7 +200,13 @@ static Exception FailThrow(string algorithm) } } - public readonly int HashSizeInBytes + private LiteXof(SafeBCryptHashHandle hashHandle, nuint algorithm) + { + _algorithm = algorithm; + _hashHandle = hashHandle; + } + + public int HashSizeInBytes { get { @@ -191,7 +215,7 @@ public readonly int HashSizeInBytes } } - public readonly void Append(ReadOnlySpan data) + public void Append(ReadOnlySpan data) { if (data.IsEmpty) { @@ -206,7 +230,7 @@ public readonly void Append(ReadOnlySpan data) } } - public readonly unsafe int Finalize(Span destination) + public unsafe int Finalize(Span destination) { fixed (byte* pDestination = &Helpers.GetNonNullPinnableReference(destination)) { @@ -221,36 +245,33 @@ public readonly unsafe int Finalize(Span destination) } } - [MemberNotNull(nameof(_hashHandle))] - public void Reset() - { - _hashHandle?.Dispose(); - SafeBCryptHashHandle hashHandle; - - NTSTATUS ntStatus = Interop.BCrypt.BCryptCreateHash( - _algorithm, - out hashHandle, - pbHashObject: IntPtr.Zero, - cbHashObject: 0, - secret: ReadOnlySpan.Empty, - cbSecret: 0, - BCryptCreateHashFlags.None); + public void Reset() => Finalize(Span.Empty); - if (ntStatus != NTSTATUS.STATUS_SUCCESS) + public unsafe void Current(Span destination) + { + using (SafeBCryptHashHandle tmpHash = Interop.BCrypt.BCryptDuplicateHash(_hashHandle)) + fixed (byte* pDestination = &Helpers.GetNonNullPinnableReference(destination)) { - hashHandle.Dispose(); - throw Interop.BCrypt.CreateCryptographicException(ntStatus); + NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(tmpHash, pDestination, destination.Length, dwFlags: 0); + + if (ntStatus != NTSTATUS.STATUS_SUCCESS) + { + throw Interop.BCrypt.CreateCryptographicException(ntStatus); + } } + } - _hashHandle = hashHandle; + public LiteXof Clone() + { + SafeBCryptHashHandle clone = Interop.BCrypt.BCryptDuplicateHash(_hashHandle); + return new LiteXof(clone, _algorithm); } - public readonly unsafe void Current(Span destination) + public unsafe void Read(Span destination) { - using (SafeBCryptHashHandle tmpHash = Interop.BCrypt.BCryptDuplicateHash(_hashHandle)) fixed (byte* pDestination = &Helpers.GetNonNullPinnableReference(destination)) { - NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(tmpHash, pDestination, destination.Length, dwFlags: 0); + NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(_hashHandle, pDestination, destination.Length, dwFlags: BCRYPT_HASH_DONT_RESET_FLAG); if (ntStatus != NTSTATUS.STATUS_SUCCESS) { @@ -259,7 +280,7 @@ public readonly unsafe void Current(Span destination) } } - public readonly void Dispose() + public void Dispose() { _hashHandle.Dispose(); } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake128.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake128.cs index 14dc8e0eac407c..80740c59a657dd 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake128.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake128.cs @@ -19,10 +19,10 @@ namespace System.Security.Cryptography /// public sealed partial class Shake128 : IDisposable { - // Some platforms have a mutable struct for LiteXof, do not mark this field as readonly. - private LiteXof _hashProvider; + private readonly LiteXof _hashProvider; private bool _disposed; private ConcurrencyBlock _block; + private bool _reading; /// /// Initializes a new instance of the class. @@ -37,6 +37,11 @@ public Shake128() _hashProvider = LiteHashProvider.CreateXof(HashAlgorithmId); } + internal Shake128(LiteXof hashProvider) + { + _hashProvider = hashProvider; + } + /// /// Gets a value that indicates whether the algorithm is supported on the current platform. /// @@ -71,6 +76,7 @@ public void AppendData(ReadOnlySpan data) using (ConcurrencyBlock.Enter(ref _block)) { + CheckReading(); _hashProvider.Append(data); } } @@ -93,6 +99,7 @@ public byte[] GetHashAndReset(int outputLength) using (ConcurrencyBlock.Enter(ref _block)) { + CheckReading(); byte[] output = new byte[outputLength]; _hashProvider.Finalize(output); _hashProvider.Reset(); @@ -113,6 +120,7 @@ public void GetHashAndReset(Span destination) using (ConcurrencyBlock.Enter(ref _block)) { + CheckReading(); _hashProvider.Finalize(destination); _hashProvider.Reset(); } @@ -136,6 +144,7 @@ public byte[] GetCurrentHash(int outputLength) using (ConcurrencyBlock.Enter(ref _block)) { + CheckReading(); byte[] output = new byte[outputLength]; _hashProvider.Current(output); return output; @@ -155,10 +164,99 @@ public void GetCurrentHash(Span destination) using (ConcurrencyBlock.Enter(ref _block)) { + CheckReading(); _hashProvider.Current(destination); } } + /// + /// Retrieves the hash for the data accumulated from prior calls to the AppendData methods without + /// resetting the object to its initial state and allowing additional calls to continue retrieving the hash. + /// + /// The size of the hash to produce. + /// The computed hash. + /// + /// is negative. + /// + /// An error has occurred during the operation. + /// The object has already been disposed. + /// + /// The platform does not support multiple reads of the hash. can be used + /// to perform a single operation. + /// + public byte[] Read(int outputLength) + { + ArgumentOutOfRangeException.ThrowIfNegative(outputLength); + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + byte[] output = new byte[outputLength]; + _hashProvider.Read(output); + _reading = true; + return output; + } + } + + /// + /// Fills the buffer with the hash for the data accumulated from prior calls to the AppendData methods without + /// resetting the object to its initial state and allowing additional calls to continue retrieving the hash. + /// + /// The buffer to fill with the hash. + /// An error has occurred during the operation. + /// The object has already been disposed. + /// + /// The platform does not support multiple reads of the hash. can be used + /// to perform a single operation. + /// + public void Read(Span destination) + { + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + _hashProvider.Read(destination); + _reading = true; + } + } + + /// + /// Resets the instance back to its initial state. + /// + /// An error has occurred during the operation. + /// The object has already been disposed. + public void Reset() + { + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + _hashProvider.Reset(); + _reading = false; + } + } + + /// + /// Creates a new instance of with the existing appended data preserved. + /// + /// A clone of the current instance. + /// An error has occurred during the operation. + /// + /// The current instance is being read from and cannot be cloned. + /// + /// The object has already been disposed. + public Shake128 Clone() + { + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + CheckReading(); + LiteXof clone = _hashProvider.Clone(); + return new Shake128(clone); + } + } + /// /// Release all resources used by the current instance of the class. /// @@ -385,5 +483,13 @@ private static void CheckPlatformSupport() } private void CheckDisposed() => ObjectDisposedException.ThrowIf(_disposed, this); + + private void CheckReading() + { + if (_reading) + { + throw new InvalidOperationException(SR.InvalidOperation_AlreadyReading); + } + } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake256.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake256.cs index c801adde9395ca..d861257cf1e480 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake256.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake256.cs @@ -19,10 +19,10 @@ namespace System.Security.Cryptography /// public sealed partial class Shake256 : IDisposable { - // Some platforms have a mutable struct for LiteXof, do not mark this field as readonly. - private LiteXof _hashProvider; + private readonly LiteXof _hashProvider; private bool _disposed; private ConcurrencyBlock _block; + private bool _reading; /// /// Initializes a new instance of the class. @@ -37,6 +37,11 @@ public Shake256() _hashProvider = LiteHashProvider.CreateXof(HashAlgorithmId); } + internal Shake256(LiteXof hashProvider) + { + _hashProvider = hashProvider; + } + /// /// Gets a value that indicates whether the algorithm is supported on the current platform. /// @@ -71,6 +76,7 @@ public void AppendData(ReadOnlySpan data) using (ConcurrencyBlock.Enter(ref _block)) { + CheckReading(); _hashProvider.Append(data); } } @@ -93,6 +99,7 @@ public byte[] GetHashAndReset(int outputLength) using (ConcurrencyBlock.Enter(ref _block)) { + CheckReading(); byte[] output = new byte[outputLength]; _hashProvider.Finalize(output); _hashProvider.Reset(); @@ -113,6 +120,7 @@ public void GetHashAndReset(Span destination) using (ConcurrencyBlock.Enter(ref _block)) { + CheckReading(); _hashProvider.Finalize(destination); _hashProvider.Reset(); } @@ -136,6 +144,7 @@ public byte[] GetCurrentHash(int outputLength) using (ConcurrencyBlock.Enter(ref _block)) { + CheckReading(); byte[] output = new byte[outputLength]; _hashProvider.Current(output); return output; @@ -155,10 +164,99 @@ public void GetCurrentHash(Span destination) using (ConcurrencyBlock.Enter(ref _block)) { + CheckReading(); _hashProvider.Current(destination); } } + /// + /// Retrieves the hash for the data accumulated from prior calls to the AppendData methods without + /// resetting the object to its initial state and allowing additional calls to continue retrieving the hash. + /// + /// The size of the hash to produce. + /// The computed hash. + /// + /// is negative. + /// + /// An error has occurred during the operation. + /// The object has already been disposed. + /// + /// The platform does not support multiple reads of the hash. can be used + /// to perform a single operation. + /// + public byte[] Read(int outputLength) + { + ArgumentOutOfRangeException.ThrowIfNegative(outputLength); + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + byte[] output = new byte[outputLength]; + _hashProvider.Read(output); + _reading = true; + return output; + } + } + + /// + /// Fills the buffer with the hash for the data accumulated from prior calls to the AppendData methods without + /// resetting the object to its initial state and allowing additional calls to continue retrieving the hash. + /// + /// The buffer to fill with the hash. + /// An error has occurred during the operation. + /// The object has already been disposed. + /// + /// The platform does not support multiple reads of the hash. can be used + /// to perform a single operation. + /// + public void Read(Span destination) + { + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + _hashProvider.Read(destination); + _reading = true; + } + } + + /// + /// Resets the instance back to its initial state. + /// + /// An error has occurred during the operation. + /// The object has already been disposed. + public void Reset() + { + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + _hashProvider.Reset(); + _reading = false; + } + } + + /// + /// Creates a new instance of with the existing appended data preserved. + /// + /// A clone of the current instance. + /// An error has occurred during the operation. + /// + /// The current instance is being read from and cannot be cloned. + /// + /// The object has already been disposed. + public Shake256 Clone() + { + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + CheckReading(); + LiteXof clone = _hashProvider.Clone(); + return new Shake256(clone); + } + } + /// /// Release all resources used by the current instance of the class. /// @@ -385,5 +483,13 @@ private static void CheckPlatformSupport() } private void CheckDisposed() => ObjectDisposedException.ThrowIf(_disposed, this); + + private void CheckReading() + { + if (_reading) + { + throw new InvalidOperationException(SR.InvalidOperation_AlreadyReading); + } + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/Shake128Tests.cs b/src/libraries/System.Security.Cryptography/tests/Shake128Tests.cs index e203d77f46b6cf..8cfa95b57621e1 100644 --- a/src/libraries/System.Security.Cryptography/tests/Shake128Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Shake128Tests.cs @@ -21,6 +21,10 @@ public class Traits : IShakeTrait public static void GetHashAndReset(Shake128 shake, Span destination) => shake.GetHashAndReset(destination); public static byte[] GetCurrentHash(Shake128 shake, int outputLength) => shake.GetCurrentHash(outputLength); public static void GetCurrentHash(Shake128 shake, Span destination) => shake.GetCurrentHash(destination); + public static void Read(Shake128 shake, Span destination) => shake.Read(destination); + public static byte[] Read(Shake128 shake, int outputLength) => shake.Read(outputLength); + public static void Reset(Shake128 shake) => shake.Reset(); + public static Shake128 Clone(Shake128 shake) => shake.Clone(); public static byte[] HashData(byte[] source, int outputLength) => Shake128.HashData(source, outputLength); public static byte[] HashData(ReadOnlySpan source, int outputLength) => Shake128.HashData(source, outputLength); diff --git a/src/libraries/System.Security.Cryptography/tests/Shake256Tests.cs b/src/libraries/System.Security.Cryptography/tests/Shake256Tests.cs index 9631752e69444e..23886ccb2b2dce 100644 --- a/src/libraries/System.Security.Cryptography/tests/Shake256Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Shake256Tests.cs @@ -21,6 +21,10 @@ public class Traits : IShakeTrait public static void GetHashAndReset(Shake256 shake, Span destination) => shake.GetHashAndReset(destination); public static byte[] GetCurrentHash(Shake256 shake, int outputLength) => shake.GetCurrentHash(outputLength); public static void GetCurrentHash(Shake256 shake, Span destination) => shake.GetCurrentHash(destination); + public static void Read(Shake256 shake, Span destination) => shake.Read(destination); + public static byte[] Read(Shake256 shake, int outputLength) => shake.Read(outputLength); + public static void Reset(Shake256 shake) => shake.Reset(); + public static Shake256 Clone(Shake256 shake) => shake.Clone(); public static byte[] HashData(byte[] source, int outputLength) => Shake256.HashData(source, outputLength); public static byte[] HashData(ReadOnlySpan source, int outputLength) => Shake256.HashData(source, outputLength); diff --git a/src/libraries/System.Security.Cryptography/tests/ShakeTestDriver.cs b/src/libraries/System.Security.Cryptography/tests/ShakeTestDriver.cs index d0c25b1722eeaa..658d1b83a80d26 100644 --- a/src/libraries/System.Security.Cryptography/tests/ShakeTestDriver.cs +++ b/src/libraries/System.Security.Cryptography/tests/ShakeTestDriver.cs @@ -12,7 +12,7 @@ namespace System.Security.Cryptography.Tests { - public interface IShakeTrait where TShake : IDisposable, new() + public interface IShakeTrait where TShake : class, IDisposable, new() { static abstract TShake Create(); static abstract bool IsSupported { get; } @@ -22,6 +22,10 @@ namespace System.Security.Cryptography.Tests static abstract void GetHashAndReset(TShake shake, Span destination); static abstract byte[] GetCurrentHash(TShake shake, int outputLength); static abstract void GetCurrentHash(TShake shake, Span destination); + static abstract void Read(TShake shake, Span destination); + static abstract byte[] Read(TShake shake, int outputLength); + static abstract void Reset(TShake shake); + static abstract TShake Clone(TShake shake); static abstract byte[] HashData(byte[] source, int outputLength); static abstract byte[] HashData(ReadOnlySpan source, int outputLength); @@ -37,12 +41,21 @@ namespace System.Security.Cryptography.Tests public abstract class ShakeTestDriver where TShakeTrait : IShakeTrait - where TShake : IDisposable, new() + where TShake : class, IDisposable, new() { protected abstract IEnumerable<(string Msg, string Output)> Fips202Kats { get; } public static bool IsSupported => TShakeTrait.IsSupported; public static bool IsNotSupported => !IsSupported; + public static bool IsReadSupported + { + get + { + const long OpenSsl_3_2_0 = 0x30200000L; + return IsSupported && (PlatformDetection.IsWindows || SafeEvpPKeyHandle.OpenSslVersion >= OpenSsl_3_2_0); + } + } + [ConditionalFact(nameof(IsSupported))] public void KnownAnswerTests_Allocated_AllAtOnce() { @@ -151,6 +164,113 @@ public void KnownAnswerTests_Allocated_Hash_Destination() } } + [ConditionalFact(nameof(IsReadSupported))] + public void KnownAnswerTests_Allocated_Read_Twice() + { + foreach ((string Msg, string Output) kat in Fips202Kats) + { + byte[] message = Convert.FromHexString(kat.Msg); + + using (TShake shake = new TShake()) + { + TShakeTrait.AppendData(shake, message); + Span hash = new byte[kat.Output.Length / 2]; + ReadChunked(shake, hash); + Assert.Equal(kat.Output, Convert.ToHexString(hash), ignoreCase: true); + + TShakeTrait.Reset(shake); + hash.Clear(); + + TShakeTrait.AppendData(shake, message); + ReadChunked(shake, hash); + Assert.Equal(kat.Output, Convert.ToHexString(hash), ignoreCase: true); + } + } + } + + [ConditionalFact(nameof(IsReadSupported))] + public void KnownAnswerTests_Allocated_Read_GetHashAndReset() + { + foreach ((string Msg, string Output) kat in Fips202Kats) + { + byte[] message = Convert.FromHexString(kat.Msg); + + using (TShake shake = new TShake()) + { + TShakeTrait.AppendData(shake, message); + Span hash = new byte[kat.Output.Length / 2]; + ReadChunked(shake, hash); + Assert.Equal(kat.Output, Convert.ToHexString(hash), ignoreCase: true); + + TShakeTrait.Reset(shake); + hash.Clear(); + + TShakeTrait.AppendData(shake, message); + TShakeTrait.GetHashAndReset(shake, hash); + Assert.Equal(kat.Output, Convert.ToHexString(hash), ignoreCase: true); + } + } + } + + [ConditionalFact(nameof(IsSupported))] + public void KnownAnswerTests_Clone_Independent_Unobserved() + { + foreach ((string Msg, string Output) kat in Fips202Kats) + { + byte[] message = Convert.FromHexString(kat.Msg); + byte[] hash = new byte[kat.Output.Length / 2]; + + using (TShake shake = new TShake()) + using (TShake clone = TShakeTrait.Clone(shake)) + { + TShakeTrait.AppendData(shake, "badbadbad"u8); + + TShakeTrait.AppendData(clone, message); + TShakeTrait.GetCurrentHash(clone, hash); + Assert.Equal(kat.Output, Convert.ToHexString(hash), ignoreCase: true); + } + } + } + + [ConditionalFact(nameof(IsSupported))] + public void KnownAnswerTests_Clone_Independent_Disposed() + { + foreach ((string Msg, string Output) kat in Fips202Kats) + { + byte[] message = Convert.FromHexString(kat.Msg); + byte[] hash = new byte[kat.Output.Length / 2]; + + TShake shake = new TShake(); + using (TShake clone = TShakeTrait.Clone(shake)) + { + shake.Dispose(); + + TShakeTrait.AppendData(clone, message); + TShakeTrait.GetCurrentHash(clone, hash); + Assert.Equal(kat.Output, Convert.ToHexString(hash), ignoreCase: true); + } + } + } + + [ConditionalFact(nameof(IsSupported))] + public void KnownAnswerTests_Reset() + { + foreach ((string Msg, string Output) kat in Fips202Kats) + { + byte[] message = Convert.FromHexString(kat.Msg); + byte[] hash = new byte[kat.Output.Length / 2]; + + using (TShake shake = new TShake()) + { + TShakeTrait.AppendData(shake, "badbadbad"u8); + TShakeTrait.Reset(shake); + TShakeTrait.AppendData(shake, message); + TShakeTrait.GetCurrentHash(shake, hash); + Assert.Equal(kat.Output, Convert.ToHexString(hash), ignoreCase: true); + } + } + } + [ConditionalFact(nameof(IsSupported))] public void KnownAnswerTests_OneShot_HashData_ByteArray() { @@ -515,6 +635,10 @@ public void ArgValidation_Allocated_UseAfterDispose() Assert.Throws(() => TShakeTrait.GetHashAndReset(shake, buffer.AsSpan())); Assert.Throws(() => TShakeTrait.GetCurrentHash(shake, outputLength: 1)); Assert.Throws(() => TShakeTrait.GetCurrentHash(shake, buffer.AsSpan())); + Assert.Throws(() => TShakeTrait.Clone(shake)); + Assert.Throws(() => TShakeTrait.Reset(shake)); + Assert.Throws(() => TShakeTrait.Read(shake, buffer.AsSpan())); + Assert.Throws(() => TShakeTrait.Read(shake, outputLength: 1)); } [ConditionalFact(nameof(IsNotSupported))] @@ -539,6 +663,103 @@ public void IsSupported_AgreesWithPlatform() Assert.Equal(TShakeTrait.IsSupported, PlatformDetection.SupportsSha3); } + [ConditionalFact(nameof(IsSupported))] + public void Clone_DifferentInstance() + { + using (TShake shake = new TShake()) + using (TShake clone = TShakeTrait.Clone(shake)) + { + Assert.NotSame(shake, clone); + } + } + + [ConditionalFact(nameof(IsReadSupported))] + public void Read_MixedAppendAfterRead() + { + using (TShake shake = new TShake()) + { + TShakeTrait.Read(shake, Span.Empty); + + Assert.Throws(() => TShakeTrait.AppendData(shake, ReadOnlySpan.Empty)); + Assert.Throws(() => TShakeTrait.AppendData(shake, Array.Empty())); + + TShakeTrait.Reset(shake); + + // Assert.NoThrow + TShakeTrait.AppendData(shake, ReadOnlySpan.Empty); + TShakeTrait.AppendData(shake, Array.Empty()); + } + } + + [ConditionalFact(nameof(IsReadSupported))] + public void Read_MixedCloneAfterRead() + { + using (TShake shake = new TShake()) + { + TShakeTrait.Read(shake, Span.Empty); + Assert.Throws(() => TShakeTrait.Clone(shake)); + + TShakeTrait.Reset(shake); + + using (TShake clone = TShakeTrait.Clone(shake)) + { + Assert.NotNull(clone); + } + } + } + + [ConditionalFact(nameof(IsReadSupported))] + public void Read_MixedGetHashAndReset() + { + using (TShake shake = new TShake()) + { + TShakeTrait.Read(shake, Span.Empty); + Assert.Throws(() => TShakeTrait.GetHashAndReset(shake, Span.Empty)); + Assert.Throws(() => TShakeTrait.GetHashAndReset(shake, outputLength: 0)); + + TShakeTrait.Reset(shake); + + // Assert.NoThrow + TShakeTrait.GetHashAndReset(shake, Span.Empty); + TShakeTrait.GetHashAndReset(shake, outputLength: 0); + } + } + + [ConditionalFact(nameof(IsReadSupported))] + public void Read_MixedGetCurrentHash() + { + using (TShake shake = new TShake()) + { + TShakeTrait.Read(shake, Span.Empty); + + // Cannot GetCurrentHash while reading. + Assert.Throws(() => TShakeTrait.GetCurrentHash(shake, Span.Empty)); + Assert.Throws(() => TShakeTrait.GetCurrentHash(shake, outputLength: 0)); + + TShakeTrait.Reset(shake); + + // Assert.NoThrow + TShakeTrait.GetCurrentHash(shake, Span.Empty); + TShakeTrait.GetCurrentHash(shake, outputLength: 0); + } + } + + [ConditionalFact(nameof(IsSupported))] + public void Read_NotSupported() + { + // This is testing when a TShake can be created, but the platform does not have Read. + if (IsReadSupported) + { + return; + } + + using (TShake shake = new TShake()) + { + Assert.Throws(() => TShakeTrait.Read(shake, Span.Empty)); + Assert.Throws(() => TShakeTrait.Read(shake, outputLength: 0)); + } + } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] public void GetHashAndReset_ConcurrentUseDoesNotCrashProcess() { @@ -580,5 +801,18 @@ static void ThreadWork(object obj) } } } + + private static void ReadChunked(TShake shake, Span destination) + { + int read = 0; + int outputLength = destination.Length; + + while (read < outputLength) + { + int size = Math.Min(Math.Max(outputLength / 4, 1), outputLength - read); + TShakeTrait.Read(shake, destination.Slice(read, size)); + read += size; + } + } } } diff --git a/src/native/libs/System.Security.Cryptography.Native/configure.cmake b/src/native/libs/System.Security.Cryptography.Native/configure.cmake index 74ed49f5d19168..ea779318c667ca 100644 --- a/src/native/libs/System.Security.Cryptography.Native/configure.cmake +++ b/src/native/libs/System.Security.Cryptography.Native/configure.cmake @@ -22,6 +22,11 @@ check_function_exists( HAVE_OPENSSL_SHA3 ) +check_function_exists( + EVP_DigestSqueeze + HAVE_OPENSSL_SHA3_SQUEEZE +) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/pal_crypto_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/pal_crypto_config.h) diff --git a/src/native/libs/System.Security.Cryptography.Native/entrypoints.c b/src/native/libs/System.Security.Cryptography.Native/entrypoints.c index 0268221b428b93..a8bcbde96e5116 100644 --- a/src/native/libs/System.Security.Cryptography.Native/entrypoints.c +++ b/src/native/libs/System.Security.Cryptography.Native/entrypoints.c @@ -142,6 +142,7 @@ static const Entry s_cryptoNative[] = DllImportEntry(CryptoNative_EvpDigestFinalXOF) DllImportEntry(CryptoNative_EvpDigestOneShot) DllImportEntry(CryptoNative_EvpDigestReset) + DllImportEntry(CryptoNative_EvpDigestSqueeze) DllImportEntry(CryptoNative_EvpDigestUpdate) DllImportEntry(CryptoNative_EvpDigestXOFOneShot) DllImportEntry(CryptoNative_EvpMacFetch) @@ -155,6 +156,7 @@ static const Entry s_cryptoNative[] = DllImportEntry(CryptoNative_EvpMacOneShot) DllImportEntry(CryptoNative_EvpMacReset) DllImportEntry(CryptoNative_EvpMd5) + DllImportEntry(CryptoNative_EvpMdCtxCopyEx) DllImportEntry(CryptoNative_EvpMdCtxCreate) DllImportEntry(CryptoNative_EvpMdCtxDestroy) DllImportEntry(CryptoNative_EvpMdSize) diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h index b48d39de83cdd5..9dd878858822b7 100644 --- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h @@ -178,6 +178,13 @@ const EVP_MD *EVP_shake256(void); int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t len); #endif +#if !HAVE_OPENSSL_SHA3_SQUEEZE +#undef HAVE_OPENSSL_SHA3_SQUEEZE +#define HAVE_OPENSSL_SHA3_SQUEEZE 1 +int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen); +#endif + + #define API_EXISTS(fn) (fn != NULL) // List of all functions from the libssl that are used in the System.Security.Cryptography.Native. @@ -369,6 +376,7 @@ int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t len); REQUIRED_FUNCTION(EVP_DigestFinal_ex) \ LIGHTUP_FUNCTION(EVP_DigestFinalXOF) \ REQUIRED_FUNCTION(EVP_DigestInit_ex) \ + LIGHTUP_FUNCTION(EVP_DigestSqueeze) \ REQUIRED_FUNCTION(EVP_DigestUpdate) \ REQUIRED_FUNCTION(EVP_get_digestbyname) \ LIGHTUP_FUNCTION(EVP_MAC_fetch) \ @@ -895,6 +903,7 @@ FOR_ALL_OPENSSL_FUNCTIONS #define EVP_DigestFinal_ex EVP_DigestFinal_ex_ptr #define EVP_DigestFinalXOF EVP_DigestFinalXOF_ptr #define EVP_DigestInit_ex EVP_DigestInit_ex_ptr +#define EVP_DigestSqueeze EVP_DigestSqueeze_ptr #define EVP_DigestUpdate EVP_DigestUpdate_ptr #define EVP_get_digestbyname EVP_get_digestbyname_ptr #define EVP_md5 EVP_md5_ptr 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 d7aef5a7d1b674..c216e88e272e4a 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_crypto_config.h.in +++ b/src/native/libs/System.Security.Cryptography.Native/pal_crypto_config.h.in @@ -4,3 +4,4 @@ #cmakedefine01 HAVE_OPENSSL_ALPN #cmakedefine01 HAVE_OPENSSL_CHACHA20POLY1305 #cmakedefine01 HAVE_OPENSSL_SHA3 +#cmakedefine01 HAVE_OPENSSL_SHA3_SQUEEZE diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp.c b/src/native/libs/System.Security.Cryptography.Native/pal_evp.c index 7559b4c1970b24..1fcb0fc0058cea 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp.c @@ -143,7 +143,7 @@ int32_t CryptoNative_EvpDigestFinalXOF(EVP_MD_CTX* ctx, uint8_t* md, uint32_t le return 0; } -static EVP_MD_CTX* EvpDup(const EVP_MD_CTX* ctx) +EVP_MD_CTX* CryptoNative_EvpMdCtxCopyEx(const EVP_MD_CTX* ctx) { if (ctx == NULL) { @@ -174,7 +174,7 @@ int32_t CryptoNative_EvpDigestCurrent(const EVP_MD_CTX* ctx, uint8_t* md, uint32 { ERR_clear_error(); - EVP_MD_CTX* dup = EvpDup(ctx); + EVP_MD_CTX* dup = CryptoNative_EvpMdCtxCopyEx(ctx); if (dup != NULL) { @@ -190,7 +190,7 @@ int32_t CryptoNative_EvpDigestCurrentXOF(const EVP_MD_CTX* ctx, uint8_t* md, uin { ERR_clear_error(); - EVP_MD_CTX* dup = EvpDup(ctx); + EVP_MD_CTX* dup = CryptoNative_EvpMdCtxCopyEx(ctx); if (dup != NULL) { @@ -262,6 +262,29 @@ int32_t CryptoNative_EvpDigestXOFOneShot(const EVP_MD* type, const void* source, return ret; } +int32_t CryptoNative_EvpDigestSqueeze(EVP_MD_CTX* ctx, uint8_t* md, uint32_t len, int32_t* haveFeature) +{ + ERR_clear_error(); + + if (ctx == NULL || haveFeature == NULL || (md == NULL && len > 0)) + { + return 0; + } + + *haveFeature = 0; + int32_t ret = 0; + +#if HAVE_OPENSSL_SHA3_SQUEEZE + if (API_EXISTS(EVP_DigestSqueeze)) + { + *haveFeature = 1; + ret = EVP_DigestSqueeze(ctx, md, (size_t)len); + } +#endif + + return ret; +} + int32_t CryptoNative_EvpMdSize(const EVP_MD* md) { // No error queue impact. diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp.h b/src/native/libs/System.Security.Cryptography.Native/pal_evp.h index f31521ff0e6dee..5d8460c7b7d087 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp.h +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp.h @@ -89,6 +89,14 @@ Combines EVP_MD_CTX_create, EVP_DigestUpdate, and EVP_DigestFinalXOF in to a sin */ PALEXPORT int32_t CryptoNative_EvpDigestXOFOneShot(const EVP_MD* type, const void* source, int32_t sourceSize, uint8_t* md, uint32_t len); +/* +Function: +EvpMdCtxCopyEx + +Creates a new EVP_MD_CTX and copies the ctx input using EVP_MD_CTX_copy_ex. Returns NULL on error. +*/ +PALEXPORT EVP_MD_CTX* CryptoNative_EvpMdCtxCopyEx(const EVP_MD_CTX* ctx); + /* Function: EvpMdSize @@ -97,6 +105,15 @@ Direct shim to EVP_MD_size. */ PALEXPORT int32_t CryptoNative_EvpMdSize(const EVP_MD* md); +/* +Function: +EvpDigestSqueeze + +Calls EVP_DigestSqueeze. If the function is not available, haveFeature is set to zero and the return value should +be ignored. If the function is available, haveFeature is set to one and the operation result is returned. +*/ +PALEXPORT int32_t CryptoNative_EvpDigestSqueeze(EVP_MD_CTX* ctx, uint8_t* md, uint32_t len, int32_t* haveFeature); + /* Function: EvpMd5 From 56610095196ac12a397b1acd00835db4d86849b9 Mon Sep 17 00:00:00 2001 From: AdrienHache <83088022+AdrienHache@users.noreply.github.com> Date: Fri, 19 Apr 2024 16:51:18 +0200 Subject: [PATCH 012/248] Vector128 wrong throw helper call (#101258) Create(Vector64, Vector64) should use ThrowHelper.ThrowForUnsupportedIntrinsicsVector128BaseType instead of the Vector256 one. --- .../src/System/Runtime/Intrinsics/Vector128.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 66c0a47734429c..3e24e591a32c12 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 @@ -1041,7 +1041,7 @@ public static Vector128 Create(Vector64 lower, Vector64 upper) } else { - ThrowHelper.ThrowForUnsupportedIntrinsicsVector256BaseType(); + ThrowHelper.ThrowForUnsupportedIntrinsicsVector128BaseType(); Unsafe.SkipInit(out Vector128 result); result.SetLowerUnsafe(lower); From 30a7c4f0043c29e8b28c98e6343a1c787ace0089 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 11:30:01 -0500 Subject: [PATCH 013/248] [main] Update dependencies from dotnet/arcade (#101234) * Update dependencies from https://github.com/dotnet/arcade build 20240417.5 Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XliffTasks , Microsoft.DotNet.XUnitAssert , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 9.0.0-beta.24217.1 -> To Version 9.0.0-beta.24217.5 * Update dependencies from https://github.com/dotnet/arcade build 20240419.1 Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XliffTasks , Microsoft.DotNet.XUnitAssert , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 9.0.0-beta.24217.1 -> To Version 9.0.0-beta.24219.1 --------- Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 84 ++++++++++++++++++++--------------------- eng/Versions.props | 32 ++++++++-------- eng/common/build.ps1 | 4 +- eng/common/build.sh | 8 ---- global.json | 6 +-- 5 files changed, 62 insertions(+), 72 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 81d16576e39003..d8226036d48f40 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -92,87 +92,87 @@ - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f https://github.com/dotnet/runtime-assets @@ -332,9 +332,9 @@ https://github.com/dotnet/xharness 50b43ece7daf9f8a88ac16a95a4f8647a4c71c4b - + https://github.com/dotnet/arcade - 8ec8057ac5073b6b2e3fcb0a33d588d2a3357ad3 + b4f4d40741f161e2c0d96c19c51a4013850ef65f https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index 46b53f8ae070c9..ee1233c7327d81 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -83,22 +83,22 @@ 9.0.100-preview.4.24215.1 - 9.0.0-beta.24217.1 - 9.0.0-beta.24217.1 - 9.0.0-beta.24217.1 - 9.0.0-beta.24217.1 - 2.6.7-beta.24217.1 - 9.0.0-beta.24217.1 - 2.6.7-beta.24217.1 - 9.0.0-beta.24217.1 - 9.0.0-beta.24217.1 - 9.0.0-beta.24217.1 - 9.0.0-beta.24217.1 - 9.0.0-beta.24217.1 - 9.0.0-beta.24217.1 - 9.0.0-beta.24217.1 - 9.0.0-beta.24217.1 - 9.0.0-beta.24217.1 + 9.0.0-beta.24219.1 + 9.0.0-beta.24219.1 + 9.0.0-beta.24219.1 + 9.0.0-beta.24219.1 + 2.6.7-beta.24219.1 + 9.0.0-beta.24219.1 + 2.6.7-beta.24219.1 + 9.0.0-beta.24219.1 + 9.0.0-beta.24219.1 + 9.0.0-beta.24219.1 + 9.0.0-beta.24219.1 + 9.0.0-beta.24219.1 + 9.0.0-beta.24219.1 + 9.0.0-beta.24219.1 + 9.0.0-beta.24219.1 + 9.0.0-beta.24219.1 1.4.0 diff --git a/eng/common/build.ps1 b/eng/common/build.ps1 index 83e6d82e027a82..438f9920c43e4e 100644 --- a/eng/common/build.ps1 +++ b/eng/common/build.ps1 @@ -19,7 +19,6 @@ Param( [switch] $pack, [switch] $publish, [switch] $clean, - [switch] $verticalBuild, [switch][Alias('pb')]$productBuild, [switch][Alias('bl')]$binaryLog, [switch][Alias('nobl')]$excludeCIBinarylog, @@ -60,7 +59,6 @@ function Print-Usage() { Write-Host " -sign Sign build outputs" Write-Host " -publish Publish artifacts (e.g. symbols)" Write-Host " -clean Clean the solution" - Write-Host " -verticalBuild Run in 'vertical build' infra mode." Write-Host " -productBuild Build the solution in the way it will be built in the full .NET product (VMR) build (short: -pb)" Write-Host "" @@ -124,7 +122,7 @@ function Build { /p:Deploy=$deploy ` /p:Test=$test ` /p:Pack=$pack ` - /p:DotNetBuildRepo=$($productBuild -or $verticalBuild) ` + /p:DotNetBuildRepo=$productBuild ` /p:IntegrationTest=$integrationTest ` /p:PerformanceTest=$performanceTest ` /p:Sign=$sign ` diff --git a/eng/common/build.sh b/eng/common/build.sh index d82ebf7428080f..ac1ee8620cd2ab 100755 --- a/eng/common/build.sh +++ b/eng/common/build.sh @@ -62,7 +62,6 @@ scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" restore=false build=false source_build=false -vertical_build=false product_build=false rebuild=false test=false @@ -141,13 +140,6 @@ while [[ $# > 0 ]]; do restore=true pack=true ;; - -verticalbuild|-vb) - build=true - vertical_build=true - product_build=true - restore=true - pack=true - ;; -test|-t) test=true ;; diff --git a/global.json b/global.json index 4348e778e29b42..eb06a253442796 100644 --- a/global.json +++ b/global.json @@ -8,9 +8,9 @@ "dotnet": "9.0.100-preview.3.24204.13" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24217.1", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.24217.1", - "Microsoft.DotNet.SharedFramework.Sdk": "9.0.0-beta.24217.1", + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24219.1", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.24219.1", + "Microsoft.DotNet.SharedFramework.Sdk": "9.0.0-beta.24219.1", "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.Build.Traversal": "3.4.0", "Microsoft.NET.Sdk.IL": "9.0.0-preview.4.24215.1" From 94e8cda583bf1c78af181084e14320766298e7ed Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 11:31:06 -0500 Subject: [PATCH 014/248] [main] Update dependencies from dotnet/roslyn (#101179) * Update dependencies from https://github.com/dotnet/roslyn build 20240416.11 Microsoft.SourceBuild.Intermediate.roslyn , Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.CSharp , Microsoft.Net.Compilers.Toolset From Version 4.11.0-1.24215.10 -> To Version 4.11.0-1.24216.11 * Update dependencies from https://github.com/dotnet/roslyn build 20240418.1 Microsoft.SourceBuild.Intermediate.roslyn , Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.CSharp , Microsoft.Net.Compilers.Toolset From Version 4.11.0-1.24215.10 -> To Version 4.11.0-1.24218.1 * Update dependencies from https://github.com/dotnet/roslyn build 20240419.1 Microsoft.SourceBuild.Intermediate.roslyn , Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.CSharp , Microsoft.Net.Compilers.Toolset From Version 4.11.0-1.24215.10 -> To Version 4.11.0-1.24219.1 --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Larry Ewing --- eng/Version.Details.xml | 16 ++++++++-------- eng/Versions.props | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index d8226036d48f40..1f9d9e699d07b9 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -360,17 +360,17 @@ https://github.com/dotnet/runtime-assets 30b6a8d9d3af5681e4caef1ea453619a4b0e9f2e - + https://github.com/dotnet/roslyn - ca66296efa86bd8078508fe7b38b91b415364f78 + 3027ed4a9186a6924722a1597c8d31a59d411f7c - + https://github.com/dotnet/roslyn - ca66296efa86bd8078508fe7b38b91b415364f78 + 3027ed4a9186a6924722a1597c8d31a59d411f7c - + https://github.com/dotnet/roslyn - ca66296efa86bd8078508fe7b38b91b415364f78 + 3027ed4a9186a6924722a1597c8d31a59d411f7c https://github.com/dotnet/roslyn-analyzers @@ -381,9 +381,9 @@ b07c100bfc66013a8444172d00cfa04c9ceb5a97 - + https://github.com/dotnet/roslyn - ca66296efa86bd8078508fe7b38b91b415364f78 + 3027ed4a9186a6924722a1597c8d31a59d411f7c diff --git a/eng/Versions.props b/eng/Versions.props index ee1233c7327d81..b9c65331748549 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -42,9 +42,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.11.0-1.24215.10 - 4.11.0-1.24215.10 - 4.11.0-1.24215.10 + 4.11.0-1.24219.1 + 4.11.0-1.24219.1 + 4.11.0-1.24219.1 - false + false @@ -413,7 +411,7 @@ '$(IsReferenceAssemblyProject)' != 'true' and '$(IsGeneratorProject)' != 'true' and '$(IsTestProject)' != 'true' and - '$(IsPublishedAppTestProject)' != 'true' and + '$(IsTrimmingTestProject)' != 'true' and '$(IsTestSupportProject)' != 'true' and '$(UsingMicrosoftDotNetSharedFrameworkSdk)' != 'true' and '$(MSBuildProjectExtension)' != '.pkgproj' and @@ -464,7 +462,7 @@ - + true diff --git a/eng/pipelines/coreclr/nativeaot-post-build-steps.yml b/eng/pipelines/coreclr/nativeaot-post-build-steps.yml index 94761028f48ab0..bc29a657c456ce 100644 --- a/eng/pipelines/coreclr/nativeaot-post-build-steps.yml +++ b/eng/pipelines/coreclr/nativeaot-post-build-steps.yml @@ -21,11 +21,3 @@ steps: nativeAotTest: true helixQueues: ${{ parameters.helixQueues }} liveLibrariesBuildConfig: ${{ parameters.liveLibrariesBuildConfig }} - - # Can't run arm/arm64 tests on x64 build machines - - ${{ if and(ne(parameters.archType, 'arm'), ne(parameters.archType, 'arm64')) }}: - - # Publishing tooling doesn't support different configs between runtime and libs, so only run tests in Release config - - ${{ if eq(parameters.buildConfig, 'release') }}: - - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} $(_osParameter) -s libs.tests -c $(_BuildConfig) $(crossArg) $(_nativeSanitizersArg) /p:TestAssemblies=false /p:RunNativeAotTestApps=true $(_officialBuildParameter) /bl:$(Build.SourcesDirectory)/artifacts/log/$(buildConfigUpper)/NativeAotTests.binlog ${{ parameters.extraTestArgs }} - displayName: Run NativeAot Library Tests diff --git a/eng/pipelines/libraries/execute-trimming-tests-steps.yml b/eng/pipelines/libraries/execute-trimming-tests-steps.yml index 567abab0bb984e..13778ee0ab63a5 100644 --- a/eng/pipelines/libraries/execute-trimming-tests-steps.yml +++ b/eng/pipelines/libraries/execute-trimming-tests-steps.yml @@ -1,8 +1,14 @@ parameters: archType: '' extraTestArgs: '' + runAotTests: true steps: # Execute tests - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} $(_osParameter) -s libs.tests -c $(_BuildConfig) $(crossArg) /p:TestAssemblies=false /p:TestTrimming=true $(_officialBuildParameter) /bl:$(Build.SourcesDirectory)/artifacts/log/$(buildConfigUpper)/TrimmingTests.binlog ${{ parameters.extraTestArgs }} displayName: Run Trimming Tests + + # Execute AOT test app tests + - ${{ if eq(parameters.runAotTests, true) }}: + - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} $(_osParameter) -s libs.tests -c $(_BuildConfig) $(crossArg) /p:TestAssemblies=false /p:RunNativeAotTestApps=true $(_officialBuildParameter) /bl:$(Build.SourcesDirectory)/artifacts/log/$(buildConfigUpper)/NativeAotTestAppTests.binlog ${{ parameters.extraTestArgs }} + displayName: Run Native AOT Test App Tests diff --git a/eng/pipelines/runtime-linker-tests.yml b/eng/pipelines/runtime-linker-tests.yml index aec5e1057ac538..2b001b769f50f9 100644 --- a/eng/pipelines/runtime-linker-tests.yml +++ b/eng/pipelines/runtime-linker-tests.yml @@ -135,3 +135,4 @@ extends: - template: /eng/pipelines/libraries/execute-trimming-tests-steps.yml parameters: extraTestArgs: '/p:WasmBuildNative=false' + runAotTests: false diff --git a/eng/testing/linker/SupportFiles/Directory.Build.props b/eng/testing/linker/SupportFiles/Directory.Build.props index 5a54c83e569231..4e33801ab12837 100644 --- a/eng/testing/linker/SupportFiles/Directory.Build.props +++ b/eng/testing/linker/SupportFiles/Directory.Build.props @@ -11,6 +11,7 @@ false true + true $(NoWarn);IL2121 diff --git a/eng/testing/linker/trimmingTests.props b/eng/testing/linker/trimmingTests.props index b917cd5fe38268..b822294a93d04c 100644 --- a/eng/testing/linker/trimmingTests.props +++ b/eng/testing/linker/trimmingTests.props @@ -1,6 +1,8 @@ - $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'trimmingTests')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'trimmingTests')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'aotTests')) + $([MSBuild]::NormalizeDirectory('$(TrimmingTestDir)', 'projects')) $(MSBuildThisFileDirectory)project.csproj.template true diff --git a/eng/testing/linker/trimmingTests.targets b/eng/testing/linker/trimmingTests.targets index b29bc1dc75cf5b..9ff325e82972c0 100644 --- a/eng/testing/linker/trimmingTests.targets +++ b/eng/testing/linker/trimmingTests.targets @@ -81,6 +81,9 @@ <_additionalPropertiesString>@(_propertiesAsItems->'<%(Identity)>%(Value)</%(Identity)>', '%0a ') + + + - + diff --git a/src/libraries/Directory.Build.targets b/src/libraries/Directory.Build.targets index b219e7cf41a913..e3d599b2d8276a 100644 --- a/src/libraries/Directory.Build.targets +++ b/src/libraries/Directory.Build.targets @@ -131,7 +131,7 @@ - + diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/System.Diagnostics.DiagnosticSource.NativeAotTests.proj b/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/System.Diagnostics.DiagnosticSource.NativeAotTests.proj deleted file mode 100644 index 8001203352b581..00000000000000 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/System.Diagnostics.DiagnosticSource.NativeAotTests.proj +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/DiagnosticSourceEventSourceTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TrimmingTests/DiagnosticSourceEventSourceTests.cs similarity index 100% rename from src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/DiagnosticSourceEventSourceTests.cs rename to src/libraries/System.Diagnostics.DiagnosticSource/tests/TrimmingTests/DiagnosticSourceEventSourceTests.cs diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TrimmingTests/System.Diagnostics.DiagnosticSource.proj b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TrimmingTests/System.Diagnostics.DiagnosticSource.proj index ca9483e224ffb4..919c0b7614b145 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TrimmingTests/System.Diagnostics.DiagnosticSource.proj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TrimmingTests/System.Diagnostics.DiagnosticSource.proj @@ -2,6 +2,8 @@ + diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 659fda6a8d7d65..f89150c3e25d60 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -646,16 +646,23 @@ BuildInParallel="$(BuildTestInParallel)" /> + + + + + + + + + + + + - - Date: Mon, 22 Apr 2024 09:53:36 +0000 Subject: [PATCH 036/248] JIT: Remove fgCanonicalizedFirstBB (#101358) --- src/coreclr/jit/compiler.h | 1 - src/coreclr/jit/fgbasic.cpp | 1 - src/coreclr/jit/optimizer.cpp | 2 -- 3 files changed, 4 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 819c20629de134..3c19969d0c90d8 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -5166,7 +5166,6 @@ class Compiler bool fgModified; // True if the flow graph has been modified recently bool fgPredsComputed; // Have we computed the bbPreds list bool fgOptimizedFinally; // Did we optimize any try-finallys? - bool fgCanonicalizedFirstBB; // TODO-Quirk: did we end up canonicalizing first BB? bool fgHasSwitch; // any BBJ_SWITCH jumps? diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index 1638dfec507324..808d591a77f5c8 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -167,7 +167,6 @@ void Compiler::fgInit() fgHistogramInstrumentor = nullptr; fgValueInstrumentor = nullptr; fgPredListSortVector = nullptr; - fgCanonicalizedFirstBB = false; } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index f2de86fcdef21f..0de4cacc7bb0c5 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -5316,8 +5316,6 @@ PhaseStatus Compiler::fgCanonicalizeFirstBB() assert(!fgFirstBBisScratch()); fgEnsureFirstBBisScratch(); - // TODO-Quirk: Remove - fgCanonicalizedFirstBB = true; return PhaseStatus::MODIFIED_EVERYTHING; } From 66ce263237282f1f74ecb7b76edae2e1f634471d Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com> Date: Mon, 22 Apr 2024 14:15:35 +0200 Subject: [PATCH 037/248] [mt] Add signalR WBT on WASM browser app (#100723) * WIP, fixing net::ERR_CONNECTION_REFUSED. * Change of setup - aspnet project serving WASM static files. * Enable SharedArrayBuffer. * WIP, investigating `JsonSerializerIsReflectionDisabled` * Fix serialization issue. * Fixed * Cleanup. * Trying to fix integrity check issue. * Async interop + more logging. * Move test preparation code to a method. * Remove buttons, match other TestAppScenarios style. * Moved the test out of TestAppScenarios. Standalone version works. * Working version of test. * Cleanup. * Cleanup. * @maraf's feedback - simplify the prebuild steps. * WIP - merging blazor and wasmapp into one proj. * Missing change in a non-related test. * Do not pack blazor into a subfolder. * Remove old app. * Connect test logic, simplify. * Not intentional. * AspServer serves only "standard content types" * Prevent loosing `InnerException` on exceptions thrown during `TaskCompletionSource` completion. * Revert. * Cleanup. * @maraf's cleanup * SignalR hub is located in a url with path. * Fix "GET http://localhost:5000/wasmclient, Response status code: 404" --- .../scenarios/BuildWasmAppsJobsList.txt | 3 +- .../AspNetCore/SignalRClientTests.cs | 27 ++++ .../Blazor/BlazorWasmTestBase.cs | 2 +- .../Blazor/SignalRClientTests.cs | 30 +++++ .../wasm/Wasm.Build.Tests/SignalRTestsBase.cs | 49 ++++++++ .../TestAppScenarios/AppSettingsTests.cs | 2 +- .../TestAppScenarios/AppTestBase.cs | 37 +++--- .../TestAppScenarios/DebugLevelTests.cs | 14 +-- .../TestAppScenarios/LazyLoadingTests.cs | 4 +- .../LibraryInitializerTests.cs | 4 +- .../TestAppScenarios/ModuleConfigTests.cs | 4 +- .../TestAppScenarios/SatelliteLoadingTests.cs | 2 +- .../TestAppScenarios/SignalRClientTests.cs | 101 --------------- .../BlazorHosted.Client/Helper.cs | 42 ------- .../BlazorHosted.Client/Pages/Chat.razor | 116 ------------------ .../BlazorHosted.Client/wwwroot/favicon.ico | Bin 5430 -> 0 bytes .../BlazorHosted.Server/Program.cs | 52 -------- .../BlazorHosted.Server/appsettings.json | 8 -- .../AspNetCoreServer/AspNetCoreServer.csproj} | 5 +- .../AspNetCoreServer}/ChatHub.cs | 3 +- .../AspNetCoreServer/Program.cs | 62 ++++++++++ .../BlazorClient}/App.razor | 0 .../BlazorClient/BlazorClient.csproj} | 11 +- .../BlazorClient}/Layout/MainLayout.razor | 0 .../BlazorClient/Pages/Chat.razor | 34 +++++ .../BlazorClient}/Program.cs | 2 +- .../BlazorClient}/_Imports.razor | 5 +- .../BlazorClient}/wwwroot/index.html | 11 +- .../WasmOnAspNetCore/Shared/QueryParser.cs | 24 ++++ .../WasmOnAspNetCore/Shared/Shared.csproj | 19 +++ .../WasmOnAspNetCore/Shared/SignalRTest.cs | 114 +++++++++++++++++ .../WasmOnAspNetCore/Shared/TestOutput.cs | 20 +++ .../WasmBrowserClient/Program.cs | 21 ++++ .../WasmBrowserClient/TestOutput.cs | 18 +++ .../WasmBrowserClient.csproj | 17 +++ .../WasmBrowserClient/wwwroot/index.html | 17 +++ .../WasmBrowserClient/wwwroot/main.js | 19 +++ 37 files changed, 528 insertions(+), 371 deletions(-) create mode 100644 src/mono/wasm/Wasm.Build.Tests/AspNetCore/SignalRClientTests.cs create mode 100644 src/mono/wasm/Wasm.Build.Tests/Blazor/SignalRClientTests.cs create mode 100644 src/mono/wasm/Wasm.Build.Tests/SignalRTestsBase.cs delete mode 100644 src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SignalRClientTests.cs delete mode 100644 src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Helper.cs delete mode 100644 src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Pages/Chat.razor delete mode 100644 src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/wwwroot/favicon.ico delete mode 100644 src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/Program.cs delete mode 100644 src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/appsettings.json rename src/mono/wasm/testassets/{BlazorHostedApp/BlazorHosted.Server/BlazorHosted.Server.csproj => WasmOnAspNetCore/AspNetCoreServer/AspNetCoreServer.csproj} (63%) rename src/mono/wasm/testassets/{BlazorHostedApp/BlazorHosted.Server => WasmOnAspNetCore/AspNetCoreServer}/ChatHub.cs (93%) create mode 100644 src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/Program.cs rename src/mono/wasm/testassets/{BlazorHostedApp/BlazorHosted.Client => WasmOnAspNetCore/BlazorClient}/App.razor (100%) rename src/mono/wasm/testassets/{BlazorHostedApp/BlazorHosted.Client/BlazorHosted.Client.csproj => WasmOnAspNetCore/BlazorClient/BlazorClient.csproj} (67%) rename src/mono/wasm/testassets/{BlazorHostedApp/BlazorHosted.Client => WasmOnAspNetCore/BlazorClient}/Layout/MainLayout.razor (100%) create mode 100644 src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Pages/Chat.razor rename src/mono/wasm/testassets/{BlazorHostedApp/BlazorHosted.Client => WasmOnAspNetCore/BlazorClient}/Program.cs (95%) rename src/mono/wasm/testassets/{BlazorHostedApp/BlazorHosted.Client => WasmOnAspNetCore/BlazorClient}/_Imports.razor (72%) rename src/mono/wasm/testassets/{BlazorHostedApp/BlazorHosted.Client => WasmOnAspNetCore/BlazorClient}/wwwroot/index.html (62%) create mode 100644 src/mono/wasm/testassets/WasmOnAspNetCore/Shared/QueryParser.cs create mode 100644 src/mono/wasm/testassets/WasmOnAspNetCore/Shared/Shared.csproj create mode 100644 src/mono/wasm/testassets/WasmOnAspNetCore/Shared/SignalRTest.cs create mode 100644 src/mono/wasm/testassets/WasmOnAspNetCore/Shared/TestOutput.cs create mode 100644 src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/Program.cs create mode 100644 src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/TestOutput.cs create mode 100644 src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/WasmBrowserClient.csproj create mode 100644 src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/index.html create mode 100644 src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/main.js diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt index 63c4453b4ff66b..6afea6cb3e2237 100644 --- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt +++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt @@ -17,6 +17,7 @@ Wasm.Build.Tests.Blazor.NoopNativeRebuildTest Wasm.Build.Tests.Blazor.WorkloadRequiredTests Wasm.Build.Tests.Blazor.IcuTests Wasm.Build.Tests.Blazor.IcuShardingTests +Wasm.Build.Tests.Blazor.SignalRClientTests Wasm.Build.Tests.BuildPublishTests Wasm.Build.Tests.ConfigSrcTests Wasm.Build.Tests.HybridGlobalizationTests @@ -37,7 +38,7 @@ Wasm.Build.Tests.TestAppScenarios.LazyLoadingTests Wasm.Build.Tests.TestAppScenarios.LibraryInitializerTests Wasm.Build.Tests.TestAppScenarios.SatelliteLoadingTests Wasm.Build.Tests.TestAppScenarios.ModuleConfigTests -Wasm.Build.Tests.TestAppScenarios.SignalRClientTests +Wasm.Build.Tests.AspNetCore.SignalRClientTests Wasm.Build.Tests.WasmBuildAppTest Wasm.Build.Tests.WasmNativeDefaultsTests Wasm.Build.Tests.WasmRunOutOfAppBundleTests diff --git a/src/mono/wasm/Wasm.Build.Tests/AspNetCore/SignalRClientTests.cs b/src/mono/wasm/Wasm.Build.Tests/AspNetCore/SignalRClientTests.cs new file mode 100644 index 00000000000000..85f538fac1c20b --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/AspNetCore/SignalRClientTests.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Threading.Tasks; +using Xunit.Abstractions; +using Xunit; + +#nullable enable + +namespace Wasm.Build.Tests.AspNetCore; + +public class SignalRClientTests : SignalRTestsBase +{ + public SignalRClientTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + [ConditionalTheory(typeof(BuildTestBase), nameof(IsWorkloadWithMultiThreadingForDefaultFramework))] + [InlineData("Debug", "LongPolling")] + [InlineData("Release", "LongPolling")] + [InlineData("Debug", "WebSockets")] + [InlineData("Release", "WebSockets")] + public async Task SignalRPassMessageWasmBrowser(string config, string transport) => + await SignalRPassMessage("wasmclient", config, transport); +} diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs index da9c7764f2d1f2..46c8f2ce132870 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs @@ -205,7 +205,7 @@ public async Task BlazorRunTest(string runArgs, onConsoleMessage: OnConsoleMessage, onServerMessage: runOptions.OnServerMessage, onError: OnErrorMessage, - modifyBrowserUrl: browserUrl => browserUrl + runOptions.BrowserPath + runOptions.QueryString); + modifyBrowserUrl: browserUrl => new Uri(new Uri(browserUrl), runOptions.BrowserPath + runOptions.QueryString).ToString()); _testOutput.WriteLine("Waiting for page to load"); await page.WaitForLoadStateAsync(LoadState.DOMContentLoaded, new () { Timeout = 1 * 60 * 1000 }); diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/SignalRClientTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/SignalRClientTests.cs new file mode 100644 index 00000000000000..cf4f938bc1885d --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/SignalRClientTests.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +using System.Threading.Tasks; +using Xunit.Abstractions; +using Xunit; + +#nullable enable + +namespace Wasm.Build.Tests.Blazor; + +public class SignalRClientTests : SignalRTestsBase +{ + public SignalRClientTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + [ConditionalTheory(typeof(BuildTestBase), nameof(IsWorkloadWithMultiThreadingForDefaultFramework))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/100445")] // to be fixed by: "https://github.com/dotnet/aspnetcore/issues/54365" + [InlineData("Debug", "LongPolling")] + [InlineData("Release", "LongPolling")] + [InlineData("Debug", "WebSockets")] + [InlineData("Release", "WebSockets")] + public async Task SignalRPassMessageBlazor(string config, string transport) => + await SignalRPassMessage("blazorclient", config, transport); +} + diff --git a/src/mono/wasm/Wasm.Build.Tests/SignalRTestsBase.cs b/src/mono/wasm/Wasm.Build.Tests/SignalRTestsBase.cs new file mode 100644 index 00000000000000..183d984b39b481 --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/SignalRTestsBase.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Collections.Generic; +using Wasm.Build.Tests.TestAppScenarios; +using Xunit.Abstractions; +using Xunit; +#nullable enable + +namespace Wasm.Build.Tests; + +public class SignalRTestsBase : AppTestBase +{ + public SignalRTestsBase(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + protected async Task SignalRPassMessage(string staticWebAssetBasePath, string config, string transport) + { + CopyTestAsset("WasmOnAspNetCore", "SignalRClientTests", "AspNetCoreServer"); + PublishProject(config, runtimeType: RuntimeVariant.MultiThreaded, assertAppBundle: false); + + var result = await RunSdkStyleAppForBuild(new( + Configuration: config, + ServerEnvironment: new Dictionary { ["ASPNETCORE_ENVIRONMENT"] = "Development" }, + BrowserPath: staticWebAssetBasePath, + BrowserQueryString: new Dictionary { ["transport"] = transport, ["message"] = "ping" } )); + + string testOutput = string.Join("\n", result.TestOutput) ?? ""; + Assert.NotEmpty(testOutput); + // check sending and receiving threadId + string threadIdUsedForSending = GetThreadOfAction(testOutput, @"SignalRPassMessages was sent by CurrentManagedThreadId=(\d+)", "signalR message was sent"); + string threadIdUsedForReceiving = GetThreadOfAction(testOutput, @"ReceiveMessage from server on CurrentManagedThreadId=(\d+)", "signalR message was received"); + string consoleOutput = string.Join("\n", result.ConsoleOutput); + Assert.True("1" != threadIdUsedForSending || "1" != threadIdUsedForReceiving, + $"Expected to send/receive with signalR in non-UI threads, instead only CurrentManagedThreadId=1 was used. ConsoleOutput: {consoleOutput}."); + } + + private string GetThreadOfAction(string testOutput, string pattern, string actionDescription) + { + Match match = Regex.Match(testOutput, pattern); + Assert.True(match.Success, $"Expected to find a log that {actionDescription}. TestOutput: {testOutput}."); + return match.Groups[1].Value ?? ""; + } +} diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppSettingsTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppSettingsTests.cs index 5d028cc238909a..4ce41342917778 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppSettingsTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppSettingsTests.cs @@ -25,7 +25,7 @@ public AppSettingsTests(ITestOutputHelper output, SharedBuildPerTestClassFixture [InlineData("Production")] public async Task LoadAppSettingsBasedOnApplicationEnvironment(string applicationEnvironment) { - CopyTestAsset("WasmBasicTestApp", "AppSettingsTests"); + CopyTestAsset("WasmBasicTestApp", "AppSettingsTests", "App"); PublishProject("Debug"); var result = await RunSdkStyleAppForPublish(new( diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs index 01a1afe96c0bbb..9b228c65faaa44 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs @@ -23,7 +23,7 @@ protected AppTestBase(ITestOutputHelper output, SharedBuildPerTestClassFixture b protected string Id { get; set; } protected string LogPath { get; set; } - protected void CopyTestAsset(string assetName, string generatedProjectNamePrefix = null) + protected void CopyTestAsset(string assetName, string generatedProjectNamePrefix = null, string? projectDirSuffix = null) { Id = $"{generatedProjectNamePrefix ?? assetName}_{GetRandomId()}"; InitBlazorWasmProjectDir(Id); @@ -31,27 +31,21 @@ protected void CopyTestAsset(string assetName, string generatedProjectNamePrefix LogPath = Path.Combine(s_buildEnv.LogRootPath, Id); Utils.DirectoryCopy(Path.Combine(BuildEnvironment.TestAssetsPath, assetName), Path.Combine(_projectDir!)); - switch(assetName) + if (!string.IsNullOrEmpty(projectDirSuffix)) { - case "WasmBasicTestApp": - // WasmBasicTestApp consists of App + Library projects - _projectDir = Path.Combine(_projectDir!, "App"); - break; - case "BlazorHostedApp": - // BlazorHostedApp consists of BlazorHosted.Client and BlazorHosted.Server projects - _projectDir = Path.Combine(_projectDir!, "BlazorHosted.Server"); - break; + _projectDir = Path.Combine(_projectDir, projectDirSuffix); } } protected void BlazorHostedBuild( string config, string assetName, + string projectDirSuffix, string clientDirRelativeToProjectDir = "", string? generatedProjectNamePrefix = null, RuntimeVariant runtimeType = RuntimeVariant.SingleThreaded) { - CopyTestAsset(assetName, generatedProjectNamePrefix); + CopyTestAsset(assetName, generatedProjectNamePrefix, projectDirSuffix); string frameworkDir = FindBlazorHostedBinFrameworkDir(config, forPublish: false, clientDirRelativeToProjectDir: clientDirRelativeToProjectDir); @@ -76,9 +70,17 @@ protected void BuildProject( result.EnsureSuccessful(); } - protected void PublishProject(string configuration, params string[] extraArgs) + protected void PublishProject( + string configuration, + RuntimeVariant runtimeType = RuntimeVariant.SingleThreaded, + bool assertAppBundle = true, + params string[] extraArgs) { - (CommandResult result, _) = BlazorPublish(new BlazorBuildOptions(Id, configuration), extraArgs); + (CommandResult result, _) = BlazorPublish(new BlazorBuildOptions( + Id: Id, + Config: configuration, + RuntimeType: runtimeType, + AssertAppBundle: assertAppBundle), extraArgs); result.EnsureSuccessful(); } @@ -99,12 +101,11 @@ private async Task RunSdkStyleApp(RunOptions options, BlazorRunHost h query.Add("test", options.TestScenario); var queryString = query.Any() ? "?" + string.Join("&", query.Select(kvp => $"{kvp.Key}={kvp.Value}")) : ""; - var tcs = new TaskCompletionSource(); List testOutput = new(); List consoleOutput = new(); List serverOutput = new(); - Regex exitRegex = new Regex("(WASM EXIT (?[0-9]+)$)|(Program terminated with exit\\((?[0-9]+)\\))"); + Regex exitRegex = new Regex("WASM EXIT (?[0-9]+)$"); BlazorRunOptions blazorRunOptions = new( CheckCounter: false, @@ -114,7 +115,8 @@ private async Task RunSdkStyleApp(RunOptions options, BlazorRunHost h OnServerMessage: OnServerMessage, BrowserPath: options.BrowserPath, QueryString: queryString, - Host: host); + Host: host, + ExtraArgs: options.ExtraArgs); await BlazorRunTest(blazorRunOptions); @@ -171,7 +173,8 @@ protected record RunOptions( Dictionary ServerEnvironment = null, Action OnConsoleMessage = null, Action OnServerMessage = null, - int? ExpectedExitCode = 0 + int? ExpectedExitCode = 0, + string? ExtraArgs = null ); protected record RunResult( diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DebugLevelTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DebugLevelTests.cs index 1bbe8691d80db3..ee69b34819bbdc 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DebugLevelTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DebugLevelTests.cs @@ -33,7 +33,7 @@ private void AssertDebugLevel(RunResult result, int value) [InlineData("Release")] public async Task BuildWithDefaultLevel(string configuration) { - CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_BuildWithDefaultLevel_{configuration}"); + CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_BuildWithDefaultLevel_{configuration}", "App"); BuildProject(configuration); var result = await RunSdkStyleAppForBuild(new( @@ -50,7 +50,7 @@ public async Task BuildWithDefaultLevel(string configuration) [InlineData("Release", 0)] public async Task BuildWithExplicitValue(string configuration, int debugLevel) { - CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_BuildWithExplicitValue_{configuration}"); + CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_BuildWithExplicitValue_{configuration}", "App"); BuildProject(configuration: configuration, extraArgs: $"-p:WasmDebugLevel={debugLevel}"); var result = await RunSdkStyleAppForBuild(new( @@ -65,7 +65,7 @@ public async Task BuildWithExplicitValue(string configuration, int debugLevel) [InlineData("Release")] public async Task PublishWithDefaultLevel(string configuration) { - CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_PublishWithDefaultLevel_{configuration}"); + CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_PublishWithDefaultLevel_{configuration}", "App"); PublishProject(configuration); var result = await RunSdkStyleAppForPublish(new( @@ -82,8 +82,8 @@ public async Task PublishWithDefaultLevel(string configuration) [InlineData("Release", -1)] public async Task PublishWithExplicitValue(string configuration, int debugLevel) { - CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_PublishWithExplicitValue_{configuration}"); - PublishProject(configuration, $"-p:WasmDebugLevel={debugLevel}"); + CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_PublishWithExplicitValue_{configuration}", "App"); + PublishProject(configuration, RuntimeVariant.SingleThreaded, assertAppBundle: true, $"-p:WasmDebugLevel={debugLevel}"); var result = await RunSdkStyleAppForPublish(new( Configuration: configuration, @@ -97,8 +97,8 @@ public async Task PublishWithExplicitValue(string configuration, int debugLevel) [InlineData("Release")] public async Task PublishWithDefaultLevelAndPdbs(string configuration) { - CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_PublishWithDefaultLevelAndPdbs_{configuration}"); - PublishProject(configuration, $"-p:CopyOutputSymbolsToPublishDirectory=true"); + CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_PublishWithDefaultLevelAndPdbs_{configuration}", "App"); + PublishProject(configuration, RuntimeVariant.SingleThreaded, assertAppBundle: true, $"-p:CopyOutputSymbolsToPublishDirectory=true"); var result = await RunSdkStyleAppForPublish(new( Configuration: configuration, diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs index cf16a0536a38da..038951e1822e68 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs @@ -23,7 +23,7 @@ public LazyLoadingTests(ITestOutputHelper output, SharedBuildPerTestClassFixture [Fact] public async Task LoadLazyAssemblyBeforeItIsNeeded() { - CopyTestAsset("WasmBasicTestApp", "LazyLoadingTests"); + CopyTestAsset("WasmBasicTestApp", "LazyLoadingTests", "App"); PublishProject("Debug"); var result = await RunSdkStyleAppForPublish(new(Configuration: "Debug", TestScenario: "LazyLoadingTest")); @@ -33,7 +33,7 @@ public async Task LoadLazyAssemblyBeforeItIsNeeded() [Fact] public async Task FailOnMissingLazyAssembly() { - CopyTestAsset("WasmBasicTestApp", "LazyLoadingTests"); + CopyTestAsset("WasmBasicTestApp", "LazyLoadingTests", "App"); PublishProject("Debug"); var result = await RunSdkStyleAppForPublish(new( diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LibraryInitializerTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LibraryInitializerTests.cs index e985ad23d89a0b..c4380ed755a591 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LibraryInitializerTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LibraryInitializerTests.cs @@ -26,7 +26,7 @@ public LibraryInitializerTests(ITestOutputHelper output, SharedBuildPerTestClass [Fact] public async Task LoadLibraryInitializer() { - CopyTestAsset("WasmBasicTestApp", "LibraryInitializerTests_LoadLibraryInitializer"); + CopyTestAsset("WasmBasicTestApp", "LibraryInitializerTests_LoadLibraryInitializer", "App"); PublishProject("Debug"); var result = await RunSdkStyleAppForPublish(new(Configuration: "Debug", TestScenario: "LibraryInitializerTest")); @@ -39,7 +39,7 @@ public async Task LoadLibraryInitializer() [Fact] public async Task AbortStartupOnError() { - CopyTestAsset("WasmBasicTestApp", "LibraryInitializerTests_AbortStartupOnError"); + CopyTestAsset("WasmBasicTestApp", "LibraryInitializerTests_AbortStartupOnError", "App"); PublishProject("Debug"); var result = await RunSdkStyleAppForPublish(new( diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/ModuleConfigTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/ModuleConfigTests.cs index 4dc20e7358aa5b..532751a4ac5347 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/ModuleConfigTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/ModuleConfigTests.cs @@ -25,7 +25,7 @@ public ModuleConfigTests(ITestOutputHelper output, SharedBuildPerTestClassFixtur [InlineData(true)] public async Task DownloadProgressFinishes(bool failAssemblyDownload) { - CopyTestAsset("WasmBasicTestApp", $"ModuleConfigTests_DownloadProgressFinishes_{failAssemblyDownload}"); + CopyTestAsset("WasmBasicTestApp", $"ModuleConfigTests_DownloadProgressFinishes_{failAssemblyDownload}", "App"); PublishProject("Debug"); var result = await RunSdkStyleAppForPublish(new( @@ -58,7 +58,7 @@ public async Task DownloadProgressFinishes(bool failAssemblyDownload) [Fact] public async Task OutErrOverrideWorks() { - CopyTestAsset("WasmBasicTestApp", $"ModuleConfigTests_OutErrOverrideWorks"); + CopyTestAsset("WasmBasicTestApp", $"ModuleConfigTests_OutErrOverrideWorks", "App"); PublishProject("Debug"); var result = await RunSdkStyleAppForPublish(new( diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SatelliteLoadingTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SatelliteLoadingTests.cs index 2088e1522ad73b..517f34255f9969 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SatelliteLoadingTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SatelliteLoadingTests.cs @@ -26,7 +26,7 @@ public SatelliteLoadingTests(ITestOutputHelper output, SharedBuildPerTestClassFi [Fact] public async Task LoadSatelliteAssembly() { - CopyTestAsset("WasmBasicTestApp", "SatelliteLoadingTests"); + CopyTestAsset("WasmBasicTestApp", "SatelliteLoadingTests", "App"); BuildProject("Debug"); var result = await RunSdkStyleAppForBuild(new(Configuration: "Debug", TestScenario: "SatelliteAssembliesTest")); diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SignalRClientTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SignalRClientTests.cs deleted file mode 100644 index 1b09272b487931..00000000000000 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SignalRClientTests.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Microsoft.Playwright; -using Xunit.Abstractions; -using Xunit; - -#nullable enable - -namespace Wasm.Build.Tests.TestAppScenarios; - -public class SignalRClientTests : AppTestBase -{ - public SignalRClientTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) - : base(output, buildContext) - { - } - - [ConditionalTheory(typeof(BuildTestBase), nameof(IsWorkloadWithMultiThreadingForDefaultFramework))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/100445")] // to be fixed by: "https://github.com/dotnet/aspnetcore/issues/54365" - [InlineData("Debug", "LongPolling")] - [InlineData("Release", "LongPolling")] - [InlineData("Debug", "WebSockets")] - [InlineData("Release", "WebSockets")] - public async Task SignalRPassMessages(string config, string transport) - { - BlazorHostedBuild(config, - assetName: "BlazorHostedApp", - clientDirRelativeToProjectDir: "../BlazorHosted.Client", - generatedProjectNamePrefix: "SignalRClientTests", - runtimeType: RuntimeVariant.MultiThreaded); - - List consoleOutput = new(); - List serverOutput = new(); - - var result = await RunSdkStyleAppForBuild(new( - Configuration: config, - // We are using build (not publish), - // we need to instruct static web assets to use manifest file, - // because wwwroot in bin doesn't contain all files (for build) - ServerEnvironment: new Dictionary { ["ASPNETCORE_ENVIRONMENT"] = "Development" }, - BrowserPath: "/chat", - BrowserQueryString: new Dictionary { ["transport"] = transport, ["message"] = "ping" }, - OnServerMessage: (msg) => serverOutput.Add(msg), - OnConsoleMessage: async (page, msg) => - { - consoleOutput.Add(msg.Text); - if (msg.Text.Contains("TestOutput ->")) - _testOutput.WriteLine(msg.Text); - - // prevent timeouts with [Long Running Test] on error - if (msg.Text.ToLowerInvariant().Contains("error")) - { - Console.WriteLine(msg.Text); - Console.WriteLine(_testOutput); - throw new Exception(msg.Text); - } - - if (msg.Text.Contains("Finished GetQueryParameters")) - await SaveClickButtonAsync(page, "button#connectButton"); - - if (msg.Text.Contains("SignalR connected")) - await SaveClickButtonAsync(page, "button#subscribeButton"); - - if (msg.Text.Contains("Subscribed to ReceiveMessage")) - await SaveClickButtonAsync(page, "button#sendMessageButton"); - - if (msg.Text.Contains("ReceiveMessage from server")) - await SaveClickButtonAsync(page, "button#exitProgramButton"); - } - )); - - string output = _testOutput.ToString() ?? ""; - Assert.NotEmpty(output); - // check sending and receiving threadId - string threadIdUsedForSending = GetThreadOfAction(output, @"SignalRPassMessages was sent by CurrentManagedThreadId=(\d+)", "signalR message was sent"); - string threadIdUsedForReceiving = GetThreadOfAction(output, @"ReceiveMessage from server on CurrentManagedThreadId=(\d+)", "signalR message was received"); - Assert.True("1" != threadIdUsedForSending || "1" != threadIdUsedForReceiving, - $"Expected to send/receive with signalR in non-UI threads, instead only CurrentManagedThreadId=1 was used. TestOutput: {output}."); - } - - private string GetThreadOfAction(string testOutput, string pattern, string actionDescription) - { - Match match = Regex.Match(testOutput, pattern); - Assert.True(match.Success, $"Expected to find a log that {actionDescription}. TestOutput: {testOutput}."); - return match.Groups[1].Value ?? ""; - } - - private async Task SaveClickButtonAsync(IPage page, string selector) - { - await page.WaitForSelectorAsync(selector); - await page.ClickAsync(selector); - } -} diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Helper.cs b/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Helper.cs deleted file mode 100644 index 38ead1438099f3..00000000000000 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Helper.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Specialized; -using Microsoft.AspNetCore.Http.Connections; - -namespace BlazorHosted.Client; - -public static class Helper -{ - public static string GetValue(NameValueCollection parameters, string key) - { - var values = parameters.GetValues(key); - if (values == null || values.Length == 0) - { - throw new Exception($"Parameter '{key}' is required in the query string"); - } - if (values.Length > 1) - { - throw new Exception($"Parameter '{key}' should be unique in the query string"); - } - return values[0]; - } - - public static HttpTransportType StringToTransportType(string transport) - { - switch (transport.ToLowerInvariant()) - { - case "longpolling": - return HttpTransportType.LongPolling; - case "websockets": - return HttpTransportType.WebSockets; - default: - throw new Exception($"{transport} is invalid transport type"); - } - } - - public static void TestOutputWriteLine(string message) - { - Console.WriteLine("TestOutput -> " + message); - } -} diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Pages/Chat.razor b/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Pages/Chat.razor deleted file mode 100644 index f90aa96c87b92b..00000000000000 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Pages/Chat.razor +++ /dev/null @@ -1,116 +0,0 @@ -@page "/chat" -@using Microsoft.AspNetCore.SignalR -@using Microsoft.AspNetCore.SignalR.Client -@using Microsoft.AspNetCore.Http.Connections; -@using System.Web; -@inject NavigationManager NavigationManager -@inject IJSRuntime JSRuntime - -

Chat Room

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

@chatMessage

- } -
- -@code { - private string _hubUrl = string.Empty; - private HubConnection? _hubConnection; - private string message = string.Empty; - private string transport = string.Empty; - private List chatMessages = new List(); - private string wrongQueryError = "Query string with parameters 'message' and 'transport' are required"; - - // remove when https://github.com/dotnet/runtime/issues/96546 is fixed - // log that rendering is about to start in case we hit the issue before OnAfterRender is called - protected override bool ShouldRender() - { - bool shouldRender = base.ShouldRender(); - Helper.TestOutputWriteLine($"ShouldRender = {shouldRender}"); - return shouldRender; - } - - protected override void OnAfterRender(bool firstRender) - { - if (firstRender) - { - Helper.TestOutputWriteLine($"OnAfterRender on CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); - GetQueryParameters(); - } - base.OnAfterRender(firstRender); - } - - private void GetQueryParameters() - { - var uri = new Uri(NavigationManager.Uri); - if (string.IsNullOrEmpty(uri.Query)) - { - throw new Exception(wrongQueryError); - } - var parameters = HttpUtility.ParseQueryString(uri.Query); - if (parameters == null) - { - throw new Exception(wrongQueryError); - } - transport = Helper.GetValue(parameters, "transport"); - message = $"{transport} {Helper.GetValue(parameters, "message")}" ; - Helper.TestOutputWriteLine($"Finished GetQueryParameters on CurrentManagedThreadId={Environment.CurrentManagedThreadId}."); - } - - private async Task Connect() - { - _hubUrl = NavigationManager.BaseUri + "chathub"; - HttpTransportType httpTransportType = Helper.StringToTransportType(transport); - _hubConnection = new HubConnectionBuilder() - .WithUrl(_hubUrl, options => - { - options.Transports = httpTransportType; - }) - .Build(); - - await _hubConnection.StartAsync(); - Helper.TestOutputWriteLine($"SignalR connected by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); - } - - private void Subscribe() - { - _hubConnection.On("ReceiveMessage", (message) => - { - Helper.TestOutputWriteLine($"Message = [{message}]. ReceiveMessage from server on CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); - chatMessages.Add(message); - }); - Helper.TestOutputWriteLine($"Subscribed to ReceiveMessage by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); - } - - private async Task SignalRPassMessages() => - await Task.Run(async () => - { - await _hubConnection.SendAsync( "SendMessage", message, Environment.CurrentManagedThreadId); - Helper.TestOutputWriteLine($"SignalRPassMessages was sent by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); - }); - - private async Task SendExitSignal() - { - await DisposeHubConnection(); - // exit the client - Helper.TestOutputWriteLine($"SendExitSignal by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); - await JSRuntime.InvokeVoidAsync("eval", "setTimeout(() => { getDotnetRuntime(0).exit(0); }, 50);"); - } - - private async Task DisposeHubConnection() - { - if (_hubConnection != null) - { - _hubConnection.Remove("ReceiveMessage"); - await _hubConnection.DisposeAsync(); - _hubConnection = null; - } - Helper.TestOutputWriteLine($"SignalR disconnected by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); - } -} diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/wwwroot/favicon.ico b/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/wwwroot/favicon.ico deleted file mode 100644 index 63e859b476eff5055e0e557aaa151ca8223fbeef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5430 zcmc&&Yj2xp8Fqnv;>&(QB_ve7>^E#o2mu=cO~A%R>DU-_hfbSRv1t;m7zJ_AMrntN zy0+^f&8be>q&YYzH%(88lQ?#KwiCzaCO*ZEo%j&v;<}&Lj_stKTKK>#U3nin@AF>w zb3ONSAFR{u(S1d?cdw53y}Gt1b-Hirbh;;bm(Rcbnoc*%@jiaXM|4jU^1WO~`TYZ~ zC-~jh9~b-f?fX`DmwvcguQzn*uV}c^Vd&~?H|RUs4Epv~gTAfR(B0lT&?RWQOtduM z^1vUD9{HQsW!{a9|0crA34m7Z6lpG^}f6f?={zD+ zXAzk^i^aKN_}s2$eX81wjSMONE#WVdzf|MT)Ap*}Vsn!XbvsI#6o&ij{87^d%$|A{ z=F{KB%)g%@z76yBzbb7seW**Ju8r4e*Z3PWNX3_tTDgzZatz7)Q6ytwB%@&@A|XT; zecM`Snxx5po$C)%yCP!KEtos~eOS)@2=kX-RIm)4glMCoagTEFxrBeSX%Euz734Fk z%7)x(k~T!@Hbg_37NSQL!vlTBXoURSzt~I**Zw`&F24fH*&kx=%nvZv|49SC*daD( zIw<~%#=lk8{2-l(BcIjy^Q$Q&m#KlWL9?UG{b8@qhlD z;umc+6p%|NsAT~0@DgV4-NKgQuWPWrmPIK&&XhV&n%`{l zOl^bbWYjQNuVXTXESO)@|iUKVmErPUDfz2Wh`4dF@OFiaCW|d`3paV^@|r^8T_ZxM)Z+$p5qx# z#K=z@%;aBPO=C4JNNGqVv6@UGolIz;KZsAro``Rz8X%vq_gpi^qEV&evgHb_=Y9-l z`)imdx0UC>GWZYj)3+3aKh?zVb}=@%oNzg7a8%kfVl)SV-Amp1Okw&+hEZ3|v(k8vRjXW9?ih`&FFM zV$~{j3IzhtcXk?Mu_!12;=+I7XK-IR2>Yd%VB^?oI9c^E&Chb&&je$NV0P-R;ujkP z;cbLCCPEF6|22NDj=S`F^2e~XwT1ZnRX8ra0#DaFa9-X|8(xNW_+JhD75WnSd7cxo z2>I_J5{c|WPfrgl7E2R)^c}F7ry()Z>$Jhk9CzZxiPKL#_0%`&{MX>P_%b~Dx0D^S z7xP1(DQ!d_Icpk!RN3I1w@~|O1ru#CO==h#9M~S4Chx*@?=EKUPGBv$tmU+7Zs_al z`!jR?6T&Z7(%uVq>#yLu`abWk!FBlnY{RFNHlj~6zh*;@u}+}viRKsD`IIxN#R-X3 z@vxu#EA_m}I503U(8Qmx^}u;)KfGP`O9E1H1Q|xeeksX8jC%@!{YT1)!lWgO=+Y3*jr=iSxvOW1}^HSy=y){tOMQJ@an>sOl4FYniE z;GOxd7AqxZNbYFNqobpv&HVO$c-w!Y*6r;$2oJ~h(a#(Bp<-)dg*mNigX~9rPqcHv z^;c*|Md?tD)$y?6FO$DWl$jUGV`F1G_^E&E>sY*YnA~ruv3=z9F8&&~Xpm<<75?N3 z>x~`I&M9q)O1=zWZHN9hZWx>RQ}zLP+iL57Q)%&_^$Sme^^G7;e-P~CR?kqU#Io#( z(nH1Wn*Ig)|M>WLGrxoU?FZrS`4GO&w;+39A3f8w{{Q7eg|$+dIlNFPAe+tN=FOYU z{A&Fg|H73+w1IK(W=j*L>JQgz$g0 z7JpKXLHIh}#$wm|N`s}o-@|L_`>*(gTQ~)wr3Eap7g%PVNisKw82im;Gdv#85x#s+ zoqqtnwu4ycd>cOQgRh-=aEJbnvVK`}ja%+FZx}&ehtX)n(9nVfe4{mn0bgijUbNr7Tf5X^$*{qh2%`?--%+sbSrjE^;1e3>% zqa%jdY16{Y)a1hSy*mr0JGU05Z%=qlx5vGvTjSpTt6k%nR06q}1DU`SQh_ZAeJ}A@`hL~xvv05U?0%=spP`R>dk?cOWM9^KNb7B?xjex>OZo%JMQQ1Q zB|q@}8RiP@DWn-(fB;phPaIOP2Yp)XN3-Fsn)S3w($4&+p8f5W_f%gac}QvmkHfCj$2=!t`boCvQ zCW;&Dto=f8v##}dy^wg3VNaBy&kCe3N;1|@n@pUaMPT?(aJ9b*(gJ28$}(2qFt$H~u5z94xcIQkcOI++)*exzbrk?WOOOf*|%k5#KV zL=&ky3)Eirv$wbRJ2F2s_ILQY--D~~7>^f}W|Aw^e7inXr#WLI{@h`0|jHud2Y~cI~Yn{r_kU^Vo{1gja -{ - options.KeepAliveInterval = TimeSpan.Zero; // minimize keep-alive messages -}); - -var app = builder.Build(); - -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) -{ - app.UseWebAssemblyDebugging(); -} -else -{ - app.UseExceptionHandler("/Error"); - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); -} - -// Add headers to enable SharedArrayBuffer -app.Use(async (context, next) => -{ - var response = context.Response; - response.Headers.Append("Cross-Origin-Opener-Policy", "same-origin"); - response.Headers.Append("Cross-Origin-Embedder-Policy", "require-corp"); - - await next(); -}); -app.UseBlazorFrameworkFiles(); -app.UseStaticFiles(); - -app.UseRouting(); - -app.MapRazorPages(); -app.MapControllers(); -app.MapFallbackToFile("index.html"); - -app.MapHub("/chathub"); - -app.Run(); diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/appsettings.json b/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/appsettings.json deleted file mode 100644 index 75b7c2aa1ecedb..00000000000000 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/appsettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} \ No newline at end of file diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/BlazorHosted.Server.csproj b/src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/AspNetCoreServer.csproj similarity index 63% rename from src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/BlazorHosted.Server.csproj rename to src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/AspNetCoreServer.csproj index db0b51cd370081..9b556e8a965da2 100644 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/BlazorHosted.Server.csproj +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/AspNetCoreServer.csproj @@ -4,6 +4,7 @@ net9.0 enable enable + true CA2007
@@ -13,7 +14,9 @@ - + + +
diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/ChatHub.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/ChatHub.cs similarity index 93% rename from src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/ChatHub.cs rename to src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/ChatHub.cs index 8b2e77807c6fbc..2a1267d102c2fd 100644 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/ChatHub.cs +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/ChatHub.cs @@ -3,7 +3,8 @@ using Microsoft.AspNetCore.SignalR; -namespace BlazorHosted.Server.Hubs; +namespace Server; + public class ChatHub : Hub { public async Task SendMessage(string message, int sendingThreadId) diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/Program.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/Program.cs new file mode 100644 index 00000000000000..b22b8ded516a02 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/Program.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http.Connections; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.FileProviders; +using Microsoft.AspNetCore.StaticFiles; +using Server; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddSignalR(); +var app = builder.Build(); + +// Add headers to enable SharedArrayBuffer +app.Use(async (context, next) => +{ + var response = context.Response; + response.Headers.Append("Cross-Origin-Opener-Policy", "same-origin"); + response.Headers.Append("Cross-Origin-Embedder-Policy", "require-corp"); + + await next(); +}); + +app.UseDefaultFiles(); + +var provider = new FileExtensionContentTypeProvider(); +provider.Mappings[".dll"] = "application/octet-stream"; +provider.Mappings[".pdb"] = "application/octet-stream"; +provider.Mappings[".dat"] = "application/octet-stream"; +app.UseStaticFiles(new StaticFileOptions +{ + ContentTypeProvider = provider, +}); + +ConfigureClientApp(app, "wasmclient"); +ConfigureClientApp(app, "blazorclient"); + +app.Run(); + + +static void ConfigureClientApp(WebApplication app, string clientAppPath) +{ + app.MapWhen( + ctx => ctx.Request.Path.StartsWithSegments($"/{clientAppPath}", out var rest), + clientApp => + { + clientApp + .UseBlazorFrameworkFiles($"/{clientAppPath}") + .UsePathBase($"/{clientAppPath}") + .UseRouting() + .UseEndpoints(endpoints => + { + endpoints.MapHub("/chathub"); + endpoints.MapFallbackToFile($"{clientAppPath}/index.html"); + }); + } + ); +} diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/App.razor b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/App.razor similarity index 100% rename from src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/App.razor rename to src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/App.razor diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/BlazorHosted.Client.csproj b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/BlazorClient.csproj similarity index 67% rename from src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/BlazorHosted.Client.csproj rename to src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/BlazorClient.csproj index 237c5cf2d75acd..5c974a459386c2 100644 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/BlazorHosted.Client.csproj +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/BlazorClient.csproj @@ -7,13 +7,16 @@ true CS8604;CS4014 + blazorclient
- - - - + + + + + + diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Layout/MainLayout.razor b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Layout/MainLayout.razor similarity index 100% rename from src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Layout/MainLayout.razor rename to src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Layout/MainLayout.razor diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Pages/Chat.razor b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Pages/Chat.razor new file mode 100644 index 00000000000000..6009840f502213 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Pages/Chat.razor @@ -0,0 +1,34 @@ +@page "/" +@inject NavigationManager NavigationManager + +

Chat Room

+@code { + private SignalRTest signalRTest = new(); + + // remove when https://github.com/dotnet/runtime/issues/96546 is fixed + // log that rendering is about to start in case we hit the issue before OnAfterRender is called + protected override bool ShouldRender() + { + bool shouldRender = base.ShouldRender(); + TestOutput.WriteLine($"ShouldRender = {shouldRender}"); + return shouldRender; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + TestOutput.WriteLine($"SignalRTest is started on CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); + try + { + int result = await signalRTest.Run(NavigationManager.BaseUri, NavigationManager.Uri); + TestOutput.WriteLine($"SignalRTest finished with code {result}. WASM EXIT {result}"); + } + catch (Exception ex) + { + TestOutput.WriteLine($"SignalRTest failed with exception {ex}. WASM EXIT -1"); + } + } + base.OnAfterRenderAsync(firstRender); + } +} diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Program.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Program.cs similarity index 95% rename from src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Program.cs rename to src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Program.cs index 67a2fb06d6a1e1..bcc0dff43d9868 100644 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Program.cs +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Program.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using BlazorHosted.Client; +using BlazorClient; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/_Imports.razor b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/_Imports.razor similarity index 72% rename from src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/_Imports.razor rename to src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/_Imports.razor index d39afd384f8990..1c193c143df2ce 100644 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/_Imports.razor +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/_Imports.razor @@ -2,5 +2,6 @@ @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.JSInterop -@using BlazorHosted.Client -@using BlazorHosted.Client.Layout \ No newline at end of file +@using BlazorClient +@using BlazorClient.Layout +@using Shared \ No newline at end of file diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/wwwroot/index.html b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/wwwroot/index.html similarity index 62% rename from src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/wwwroot/index.html rename to src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/wwwroot/index.html index 56dd2027fdf839..f911682fdf48bb 100644 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/wwwroot/index.html +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/wwwroot/index.html @@ -5,7 +5,7 @@ BlazorHosted - + @@ -16,14 +16,7 @@ Reload 🗙 - - + diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/QueryParser.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/QueryParser.cs new file mode 100644 index 00000000000000..b863fa4ed54914 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/QueryParser.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Specialized; + +namespace Shared; + +public static class QueryParser +{ + public static string GetValue(NameValueCollection parameters, string key) + { + var values = parameters.GetValues(key); + if (values == null || values.Length == 0) + { + throw new Exception($"Parameter '{key}' is required in the query string"); + } + if (values.Length > 1) + { + throw new Exception($"Parameter '{key}' should be unique in the query string"); + } + return values[0]; + } +} diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/Shared.csproj b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/Shared.csproj new file mode 100644 index 00000000000000..5980a8781983ac --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/Shared.csproj @@ -0,0 +1,19 @@ + + + + net9.0 + Library + true + enable + CA2007 + + + + + + + + + + + diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/SignalRTest.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/SignalRTest.cs new file mode 100644 index 00000000000000..5b4253646413b5 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/SignalRTest.cs @@ -0,0 +1,114 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Specialized; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http.Connections; +using Microsoft.AspNetCore.SignalR.Client; +using System.Web; + +namespace Shared; + +public class SignalRTest +{ + private TaskCompletionSource? tcs; + private HubConnection? _hubConnection; + private string transport = string.Empty; + private string message = string.Empty; + private string wrongQueryError = "Query string with parameters 'message' and 'transport' is required"; + + public async Task Run(string origin, string fullUrl) + { + tcs = new TaskCompletionSource(); + GetQueryParameters(fullUrl); + await Connect(origin); + await SignalRPassMessages(); + + int delayInMin = 2; + await Task.WhenAny( + tcs!.Task, + Task.Delay(TimeSpan.FromMinutes(delayInMin))); + + if (!tcs!.Task.IsCompleted) + throw new TimeoutException($"Test timed out after waiting {delayInMin} minutes for process to exit."); + return tcs.Task.Result; + + } + + private void SetResult(int value) => tcs?.SetResult(value); + + private void GetQueryParameters(string url) + { + var uri = new Uri(url); + if (string.IsNullOrEmpty(uri.Query)) + { + throw new Exception(wrongQueryError); + } + var parameters = HttpUtility.ParseQueryString(uri.Query); + if (parameters == null) + { + throw new Exception(wrongQueryError); + } + transport = QueryParser.GetValue(parameters, "transport"); + message = $"{transport} {QueryParser.GetValue(parameters, "message")}" ; + TestOutput.WriteLine($"Finished GetQueryParameters on CurrentManagedThreadId={Environment.CurrentManagedThreadId}."); + } + + private async Task Connect(string baseUri) + { + string hubUrl = new Uri(new Uri(baseUri), "chathub").ToString(); + Console.WriteLine($"hubUrl: {hubUrl}"); + HttpTransportType httpTransportType = StringToTransportType(transport); + _hubConnection = new HubConnectionBuilder() + .WithUrl(hubUrl, options => + { + options.Transports = httpTransportType; + }) + .Build(); + + _hubConnection.On("ReceiveMessage", async (message) => + { + TestOutput.WriteLine($"Message = [{message}]. ReceiveMessage from server on CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); + await DisposeHubConnection(); + SetResult(0); + }); + TestOutput.WriteLine($"Subscribed to ReceiveMessage by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); + + await _hubConnection.StartAsync(); + TestOutput.WriteLine($"SignalR connected by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); + } + + private static HttpTransportType StringToTransportType(string transport) + { + switch (transport.ToLowerInvariant()) + { + case "longpolling": + return HttpTransportType.LongPolling; + case "websockets": + return HttpTransportType.WebSockets; + default: + throw new Exception($"{transport} is invalid transport type"); + } + } + + private async Task SignalRPassMessages() => + await Task.Run(async () => + { + if (_hubConnection == null) + throw new Exception("Cannot send messages before establishing hub connection"); + await _hubConnection!.SendAsync("SendMessage", message, Environment.CurrentManagedThreadId); + TestOutput.WriteLine($"SignalRPassMessages was sent by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); + }); + + private async Task DisposeHubConnection() + { + if (_hubConnection != null) + { + _hubConnection.Remove("ReceiveMessage"); + await _hubConnection.DisposeAsync(); + _hubConnection = null; + } + TestOutput.WriteLine($"SignalR disconnected by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); + } +} diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/TestOutput.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/TestOutput.cs new file mode 100644 index 00000000000000..3cb92a24277c28 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/TestOutput.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Shared; + +public static class TestOutput +{ + public static void WriteLine(string message) + { + Console.WriteLine("TestOutput -> " + message); + } + + public static void WriteLine(object message) + { + Console.Write("TestOutput -> "); + Console.WriteLine(message); + } +} diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/Program.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/Program.cs new file mode 100644 index 00000000000000..88bed62c360863 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/Program.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Threading.Tasks; +using Shared; + +public partial class Program +{ + public static async Task Main(string[] args) + { + if (args.Length < 2) + throw new Exception("Expected url origin and href passed as arguments"); + + SignalRTest test = new(); + Console.WriteLine($"arg0: {args[0]}, arg1: {args[1]}"); + int result = await test.Run(origin: args[0], fullUrl: args[1]); + if (result != 0) + throw new Exception($"WasmBrowser finished with non-success code: {result}"); + } +} diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/TestOutput.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/TestOutput.cs new file mode 100644 index 00000000000000..5755b753b5e492 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/TestOutput.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +public static class TestOutput +{ + public static void WriteLine(string message) + { + Console.WriteLine("TestOutput -> " + message); + } + + public static void WriteLine(object message) + { + Console.Write("TestOutput -> "); + Console.WriteLine(message); + } +} diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/WasmBrowserClient.csproj b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/WasmBrowserClient.csproj new file mode 100644 index 00000000000000..a74e1246d8bddf --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/WasmBrowserClient.csproj @@ -0,0 +1,17 @@ + + + net9.0 + browser-wasm + Exe + true + enable + + CA1050;CA2007;CA1861;IL2104 + true + wasmclient + + + + + + diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/index.html b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/index.html new file mode 100644 index 00000000000000..86bc345d2e23ad --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/index.html @@ -0,0 +1,17 @@ + + + + + + + WasmBrowser + + + + + + + + + + \ No newline at end of file diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/main.js b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/main.js new file mode 100644 index 00000000000000..f182fd9eff9919 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/main.js @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +import { dotnet, exit } from './_framework/dotnet.js' + +try { + const dotnetRuntime = await dotnet + .withElementOnExit() + .withExitCodeLogging() + .withExitOnUnhandledError() + .create(); + const config = dotnetRuntime.getConfig(); + var url = window.location.origin + window.location.pathname; + await dotnetRuntime.runMainAndExit(config.mainAssemblyName, [url, window.location.href]); + +} +catch (err) { + exit(2, err); +} \ No newline at end of file From f021ccfaf35b51d1adbcd1e94b646e48738c27b2 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Mon, 22 Apr 2024 15:35:14 +0200 Subject: [PATCH 038/248] Fix Redundant bound check for span.Length == 0 pattern (#101323) --- src/coreclr/jit/rangecheck.cpp | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/rangecheck.cpp b/src/coreclr/jit/rangecheck.cpp index e1046de8b99863..1fb068068e845c 100644 --- a/src/coreclr/jit/rangecheck.cpp +++ b/src/coreclr/jit/rangecheck.cpp @@ -866,10 +866,37 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse continue; } - // Doesn't tighten the current bound. So skip. - if (pRange->uLimit.IsConstant() && limit.vn != arrLenVN) + // Skip if it doesn't tighten the current bound: + if (pRange->uLimit.IsConstant() && ((cmpOper == GT_LE) || (cmpOper == GT_LT))) { - continue; + if (!limit.IsConstant() && (limit.vn != arrLenVN)) + { + // If our new limit is not constant and doesn't represent the array's length - bail out. + // NOTE: it's fine to replace the current constant limit with a non-constant arrLenVN. + continue; + } + if (limit.IsConstant() && (limit.cns > pRange->uLimit.cns)) + { + // The new constant limit doesn't tighten the current constant bound. + // E.g. current is "X < 10" and the new one is "X < 100" + continue; + } + } + // Same for the lower bound: + if (pRange->lLimit.IsConstant() && ((cmpOper == GT_GE) || (cmpOper == GT_GT))) + { + if (!limit.IsConstant() && (limit.vn != arrLenVN)) + { + // If our new limit is not constant and doesn't represent the array's length - bail out. + // NOTE: it's fine to replace the current constant limit with a non-constant arrLenVN. + continue; + } + if (limit.IsConstant() && (limit.cns < pRange->lLimit.cns)) + { + // The new constant limit doesn't tighten the current constant bound. + // E.g. current is "X > 10" and the new one is "X > 5" + continue; + } } // Check if the incoming limit from assertions tightens the existing upper limit. From 9ff6bb88cb04f9f7d39f9b01f9ac270a6764b12e Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Mon, 22 Apr 2024 09:56:22 -0400 Subject: [PATCH 039/248] Enable control flow guard for mono on windows (#101293) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves binskim warnings for the runtime and aot compilers on windows. Co-authored-by: Jan Kotas Co-authored-by: Alexander Köplinger --- src/mono/CMakeLists.txt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt index 47dc6aecf82c64..9fcbb6d8219659 100644 --- a/src/mono/CMakeLists.txt +++ b/src/mono/CMakeLists.txt @@ -272,12 +272,14 @@ elseif(CLR_CMAKE_HOST_OS STREQUAL "windows") set(MONO_ZERO_LEN_ARRAY 1) set(INTERNAL_ZLIB 1) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") # statically link VC runtime library - add_compile_options($<$:/W4>) # set warning level 4 - add_compile_options($<$:/WX>) # treat warnings as errors - add_compile_options($<$:/wd4324>) # 'struct_name' : structure was padded due to __declspec(align()) - add_compile_options($<$:/EHsc>) # set exception handling behavior - add_compile_options($<$:/FC>) # use full pathnames in diagnostics + add_compile_options($<$:/W4>) # set warning level 4 + add_compile_options($<$:/WX>) # treat warnings as errors + add_compile_options($<$:/wd4324>) # 'struct_name' : structure was padded due to __declspec(align()) + add_compile_options($<$:/EHsc>) # set exception handling behavior + add_compile_options($<$:/FC>) # use full pathnames in diagnostics + add_compile_options($<$:/guard:cf>) # Enable control flow guard add_link_options(/STACK:0x800000) # set stack size to 8MB (default is 1MB) + add_link_options(/guard:cf) if(CMAKE_BUILD_TYPE STREQUAL "Release") add_compile_options($<$:/Oi>) # enable intrinsics add_compile_options($<$:/GF>) # enable string pooling From aaebdd89e9453bf7d09325fd86aa15292e7c8560 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Mon, 22 Apr 2024 07:25:48 -0700 Subject: [PATCH 040/248] JIT: Move profile checking back until just before inlining (#101011) Fixes the following areas with proper profile updates: * GDV chaining * instrumentation-introduces flow * OSR step blocks * fgSplitEdge (used by instrumentation) Adds checking bypasses for: * callfinally pair tails * original method entries in OSR methods Contributes to #93020 --- src/coreclr/jit/compiler.cpp | 10 ++-- src/coreclr/jit/fgbasic.cpp | 54 +++++++++++++++++---- src/coreclr/jit/fgopt.cpp | 51 ++++++++++++------- src/coreclr/jit/fgprofile.cpp | 50 ++++++++++++++++++- src/coreclr/jit/indirectcalltransformer.cpp | 46 +++++++++++++++++- 5 files changed, 175 insertions(+), 36 deletions(-) diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index a32867660a01c3..d0bda29cb30891 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -4629,11 +4629,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // DoPhase(this, PHASE_IMPORTATION, &Compiler::fgImport); - // Drop back to just checking profile likelihoods. - // - activePhaseChecks &= ~PhaseChecks::CHECK_PROFILE; - activePhaseChecks |= PhaseChecks::CHECK_LIKELIHOODS; - // If this is a failed inline attempt, we're done. // if (compIsForInlining() && compInlineResult->IsFailure()) @@ -4688,6 +4683,11 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl return; } + // Drop back to just checking profile likelihoods. + // + activePhaseChecks &= ~PhaseChecks::CHECK_PROFILE; + activePhaseChecks |= PhaseChecks::CHECK_LIKELIHOODS; + // At this point in the phase list, all the inlinee phases have // been run, and inlinee compiles have exited, so we should only // get this far if we are jitting the root method. diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index 808d591a77f5c8..fb717e1a5a50ea 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -214,10 +214,33 @@ bool Compiler::fgEnsureFirstBBisScratch() block = BasicBlock::New(this); - // If we have profile data the new block will inherit fgFirstBlock's weight + // If we have profile data determine the weight of the scratch BB + // if (fgFirstBB->hasProfileWeight()) { - block->inheritWeight(fgFirstBB); + // If current entry has preds, sum up those weights + // + weight_t nonEntryWeight = 0; + for (FlowEdge* const edge : fgFirstBB->PredEdges()) + { + nonEntryWeight += edge->getLikelyWeight(); + } + + // entry weight is weight not from any pred + // + weight_t const entryWeight = fgFirstBB->bbWeight - nonEntryWeight; + if (entryWeight <= 0) + { + // If the result is clearly nonsensical, just inherit + // + JITDUMP("\fgEnsureFirstBBisScratch: Profile data could not be locally repaired. Data %s inconsisent.\n", + fgPgoConsistent ? "is now" : "was already"); + block->inheritWeight(fgFirstBB); + } + else + { + block->setBBProfileWeight(entryWeight); + } } // The new scratch bb will fall through to the old first bb @@ -5062,17 +5085,28 @@ BasicBlock* Compiler::fgSplitEdge(BasicBlock* curr, BasicBlock* succ) fgReplaceJumpTarget(curr, succ, newBlock); // And 'succ' has 'newBlock' as a new predecessor. - FlowEdge* const newEdge = fgAddRefPred(succ, newBlock); - newBlock->SetTargetEdge(newEdge); + FlowEdge* const newSuccEdge = fgAddRefPred(succ, newBlock); + newBlock->SetTargetEdge(newSuccEdge); - // This isn't accurate, but it is complex to compute a reasonable number so just assume that we take the - // branch 50% of the time. - // - // TODO: leverage edge likelihood. + // Set weight for newBlock // - if (!curr->KindIs(BBJ_ALWAYS)) + if (curr->KindIs(BBJ_ALWAYS)) + { + newBlock->inheritWeight(curr); + } + else { - newBlock->inheritWeightPercentage(curr, 50); + if (curr->hasProfileWeight()) + { + FlowEdge* const currNewEdge = fgGetPredForBlock(newBlock, curr); + newBlock->setBBProfileWeight(currNewEdge->getLikelyWeight()); + } + else + { + // Todo: use likelihood even w/o profile? + // + newBlock->inheritWeightPercentage(curr, 50); + } } // The bbLiveIn and bbLiveOut are both equal to the bbLiveIn of 'succ' diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index c1b919d37830a2..ac008eb140f9d7 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -731,17 +731,8 @@ PhaseStatus Compiler::fgPostImportationCleanup() // auto addConditionalFlow = [this, entryStateVar, &entryJumpTarget, &addedBlocks](BasicBlock* fromBlock, BasicBlock* toBlock) { - // We may have previously though this try entry was unreachable, but now we're going to - // step through it on the way to the OSR entry. So ensure it has plausible profile weight. - // - if (fgHaveProfileWeights() && !fromBlock->hasProfileWeight()) - { - JITDUMP("Updating block weight for now-reachable try entry " FMT_BB " via " FMT_BB "\n", - fromBlock->bbNum, fgFirstBB->bbNum); - fromBlock->inheritWeight(fgFirstBB); - } - BasicBlock* const newBlock = fgSplitBlockAtBeginning(fromBlock); + newBlock->inheritWeight(fromBlock); fromBlock->SetFlags(BBF_INTERNAL); newBlock->RemoveFlags(BBF_DONT_REMOVE); addedBlocks++; @@ -754,16 +745,40 @@ PhaseStatus Compiler::fgPostImportationCleanup() fgNewStmtAtBeg(fromBlock, jumpIfEntryStateZero); FlowEdge* const osrTryEntryEdge = fgAddRefPred(toBlock, fromBlock); - newBlock->inheritWeight(fromBlock); fromBlock->SetCond(osrTryEntryEdge, normalTryEntryEdge); - // Not sure what the correct edge likelihoods are just yet; - // for now we'll say the OSR path is the likely one. - // - // Todo: can we leverage profile data here to get a better answer? - // - osrTryEntryEdge->setLikelihood(0.9); - normalTryEntryEdge->setLikelihood(0.1); + if (fgHaveProfileWeights()) + { + // We are adding a path from (ultimately) the method entry to "fromBlock" + // Update the profile weight. + // + weight_t const entryWeight = fgFirstBB->bbWeight; + + JITDUMP("Updating block weight for now-reachable try entry " FMT_BB " via " FMT_BB "\n", + fromBlock->bbNum, fgFirstBB->bbNum); + fromBlock->setBBProfileWeight(fromBlock->bbWeight + entryWeight); + + // We updated the weight of fromBlock above. + // + // Set the likelihoods such that the additional weight flows to toBlock + // (and so the "normal path" profile out of fromBlock to newBlock is unaltered) + // + // In some stress cases we may have a zero-weight OSR entry. + // Tolerate this by capping the fromToLikelihood. + // + weight_t const fromWeight = fromBlock->bbWeight; + weight_t const fromToLikelihood = min(1.0, entryWeight / fromWeight); + + osrTryEntryEdge->setLikelihood(fromToLikelihood); + normalTryEntryEdge->setLikelihood(1.0 - fromToLikelihood); + } + else + { + // Just set likelihoods arbitrarily + // + osrTryEntryEdge->setLikelihood(0.9); + normalTryEntryEdge->setLikelihood(0.1); + } entryJumpTarget = fromBlock; }; diff --git a/src/coreclr/jit/fgprofile.cpp b/src/coreclr/jit/fgprofile.cpp index 79cd63e3ac3b51..05f97ffd14ef59 100644 --- a/src/coreclr/jit/fgprofile.cpp +++ b/src/coreclr/jit/fgprofile.cpp @@ -1689,16 +1689,42 @@ void EfficientEdgeCountInstrumentor::RelocateProbes() { BasicBlock* intermediary = m_comp->fgNewBBbefore(BBJ_ALWAYS, block, /* extendRegion */ true); intermediary->SetFlags(BBF_IMPORTED); - intermediary->inheritWeight(block); FlowEdge* const newEdge = m_comp->fgAddRefPred(block, intermediary); intermediary->SetTargetEdge(newEdge); NewRelocatedProbe(intermediary, probe->source, probe->target, &leader); SetModifiedFlow(); + // Redirect flow and figure out profile impact. + // + // We don't expect to see mixtures of profiled and unprofiled preds, + // but if we do, fall back to our old default behavior. + // + weight_t weight = 0; + bool allPredsHaveProfile = true; + while (criticalPreds.Height() > 0) { BasicBlock* const pred = criticalPreds.Pop(); m_comp->fgReplaceJumpTarget(pred, block, intermediary); + + if (pred->hasProfileWeight()) + { + FlowEdge* const predIntermediaryEdge = m_comp->fgGetPredForBlock(intermediary, pred); + weight += predIntermediaryEdge->getLikelyWeight(); + } + else + { + allPredsHaveProfile = false; + } + } + + if (allPredsHaveProfile) + { + intermediary->setBBProfileWeight(weight); + } + else + { + intermediary->inheritWeight(block); } } } @@ -4773,6 +4799,19 @@ bool Compiler::fgDebugCheckProfileWeights(ProfileChecks checks) verifyIncoming = false; } + // Original entries in OSR methods that also are + // loop headers. + // + // These will frequently have a profile imbalance as + // synthesis will have injected profile weight for + // method entry, but when we transform flow for OSR, + // only the loop back edges remain. + // + if (block == fgEntryBB) + { + verifyIncoming = false; + } + // Handler entries // if (block->hasEHBoundaryIn()) @@ -4935,6 +4974,15 @@ bool Compiler::fgDebugCheckIncomingProfileData(BasicBlock* block, ProfileChecks foundEHPreds = false; } + // We almost certainly won't get the likelihoods on a BBJ_EHFINALLYRET right, + // so special-case BBJ_CALLFINALLYRET incoming flow. + // + if (block->isBBCallFinallyPairTail()) + { + incomingLikelyWeight = block->Prev()->bbWeight; + foundEHPreds = false; + } + bool likelyWeightsValid = true; // If we have EH preds we may not have consistent incoming flow. diff --git a/src/coreclr/jit/indirectcalltransformer.cpp b/src/coreclr/jit/indirectcalltransformer.cpp index fad60de969d4c3..b8a2b2162fd26f 100644 --- a/src/coreclr/jit/indirectcalltransformer.cpp +++ b/src/coreclr/jit/indirectcalltransformer.cpp @@ -1052,7 +1052,7 @@ class IndirectCallTransformer // thenBlock = CreateAndInsertBasicBlock(BBJ_ALWAYS, checkBlock); thenBlock->CopyFlags(currBlock, BBF_SPLIT_GAINED); - thenBlock->inheritWeight(currBlock); + thenBlock->inheritWeight(checkBlock); thenBlock->scaleBBWeight(adjustedThenLikelihood); FlowEdge* const thenRemainderEdge = compiler->fgAddRefPred(remainderBlock, thenBlock); thenBlock->SetTargetEdge(thenRemainderEdge); @@ -1214,10 +1214,52 @@ class IndirectCallTransformer checkStmt = nextStmt; } - // Finally, rewire the cold block to jump to the else block, + // Rewire the cold block to jump to the else block, // not fall through to the check block. // compiler->fgRedirectTargetEdge(coldBlock, elseBlock); + + // Update the profile data + // + if (coldBlock->hasProfileWeight()) + { + // Check block + // + FlowEdge* const coldElseEdge = compiler->fgGetPredForBlock(elseBlock, coldBlock); + weight_t newCheckWeight = checkBlock->bbWeight - coldElseEdge->getLikelyWeight(); + + if (newCheckWeight < 0) + { + // If weights were consistent, we expect at worst a slight underflow. + // + if (compiler->fgPgoConsistent) + { + bool const isReasonableUnderflow = Compiler::fgProfileWeightsEqual(newCheckWeight, 0.0); + assert(isReasonableUnderflow); + + if (!isReasonableUnderflow) + { + compiler->fgPgoConsistent = false; + } + } + + // No matter what, the minimum weight is zero + // + newCheckWeight = 0; + } + checkBlock->setBBProfileWeight(newCheckWeight); + + // Else block + // + FlowEdge* const checkElseEdge = compiler->fgGetPredForBlock(elseBlock, checkBlock); + weight_t const newElseWeight = checkElseEdge->getLikelyWeight() + coldElseEdge->getLikelyWeight(); + elseBlock->setBBProfileWeight(newElseWeight); + + // Then block + // + FlowEdge* const checkThenEdge = compiler->fgGetPredForBlock(thenBlock, checkBlock); + thenBlock->setBBProfileWeight(checkThenEdge->getLikelyWeight()); + } } // When the current candidate has sufficiently high likelihood, scan From ec0a1e7a2413c21989d83bb4246ccd1852b67e26 Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Mon, 22 Apr 2024 10:58:58 -0400 Subject: [PATCH 041/248] [mono] UnsafeAccessor: Enable tests for extern static methods without type parameters (#101265) * Enable tests for methods without type parameters * Enable more field tests * Enable all field tests * Fix the type to get size for --- src/mono/mono/metadata/marshal-lightweight.c | 4 ++-- .../UnsafeAccessors/UnsafeAccessorsTests.Generics.cs | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index 86f64eeb40bba6..6399b315cfd208 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -2322,7 +2322,7 @@ method_sig_from_accessor_sig (MonoMethodBuilder *mb, gboolean hasthis, MonoMetho ret->hasthis = hasthis; for (int i = 1; i < ret->param_count; i++) ret->params [i - 1] = ret->params [i]; - memset (&ret->params[ret->param_count - 1], 0, sizeof (MonoType)); // just in case + memset (&ret->params[ret->param_count - 1], 0, sizeof (MonoType*)); // just in case ret->param_count--; return ret; } @@ -2467,7 +2467,7 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor static void emit_unsafe_accessor_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethod *accessor_method, MonoMethodSignature *sig, MonoGenericContext *ctx, MonoUnsafeAccessorKind kind, const char *member_name) { - if (accessor_method->is_inflated || accessor_method->is_generic || mono_class_is_ginst (accessor_method->klass) || ctx != NULL) { + if (accessor_method->is_generic || ctx != NULL) { mono_mb_emit_exception_full (mb, "System", "BadImageFormatException", "UnsafeAccessor_Generics"); return; } diff --git a/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs b/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs index e1029797bf12cc..e4fb9593dd3ed6 100644 --- a/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs +++ b/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs @@ -63,7 +63,6 @@ private void Add(Struct a) => } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_AccessStaticFieldClass() { Console.WriteLine($"Running {nameof(Verify_Generic_AccessStaticFieldClass)}"); @@ -99,7 +98,6 @@ public static void Verify_Generic_AccessStaticFieldClass() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_AccessFieldClass() { Console.WriteLine($"Running {nameof(Verify_Generic_AccessFieldClass)}"); @@ -284,7 +282,6 @@ public static void Verify_Generic_CallCtor() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_GenericTypeNonGenericInstanceMethod() { Console.WriteLine($"Running {nameof(Verify_Generic_GenericTypeNonGenericInstanceMethod)}"); @@ -358,7 +355,6 @@ public static void Verify_Generic_GenericTypeGenericInstanceMethod() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_GenericTypeNonGenericStaticMethod() { Console.WriteLine($"Running {nameof(Verify_Generic_GenericTypeNonGenericStaticMethod)}"); From 264e39c7b3bcde1c75b20bfef60005ab059b8290 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 23 Apr 2024 00:53:33 +0800 Subject: [PATCH 042/248] Optimize BigInteger formatting (#100181) * Cleanup DecStr formatting * Cleanup ToNumber portion * Clean and pool base1E9 buffer * Split leaf span and array path * Post cherry-pick update * Remove unworthy positive/negative span/string split * Use stackalloc for buffers * Update constant usage * Use UInt32ToDecChars * Fix type assert * Fix strLength --------- Co-authored-by: Tanner Gooding --- .../src/System/Number.Formatting.Common.cs | 2 + .../System.Private.CoreLib.Shared.projitems | 1 + .../FormattingHelpers.CountDigits.Int128.cs | 59 +++++ .../Text/FormattingHelpers.CountDigits.cs | 49 ---- .../src/System/Number.Formatting.cs | 2 - .../src/System.Runtime.Numerics.csproj | 2 + .../src/System/Number.BigInteger.cs | 217 ++++++++---------- .../src/System/Number.Polyfill.cs | 15 ++ 8 files changed, 179 insertions(+), 168 deletions(-) create mode 100644 src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.Int128.cs diff --git a/src/libraries/Common/src/System/Number.Formatting.Common.cs b/src/libraries/Common/src/System/Number.Formatting.Common.cs index 4caa59472eaea4..672ff2402682b9 100644 --- a/src/libraries/Common/src/System/Number.Formatting.Common.cs +++ b/src/libraries/Common/src/System/Number.Formatting.Common.cs @@ -12,6 +12,8 @@ namespace System { internal static partial class Number { + private const int CharStackBufferSize = 32; + private const int DefaultPrecisionExponentialFormat = 6; private const int MaxUInt32DecDigits = 10; diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 22a4ddea6ed606..b9f4be64bc9a74 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 @@ -133,6 +133,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.Int128.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.Int128.cs new file mode 100644 index 00000000000000..5264f100112eb7 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.Int128.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace System.Buffers.Text +{ + internal static partial class FormattingHelpers + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountDigits(UInt128 value) + { + ulong upper = value.Upper; + + // 1e19 is 8AC7_2304_89E8_0000 + // 1e20 is 5_6BC7_5E2D_6310_0000 + // 1e21 is 36_35C9_ADC5_DEA0_0000 + + if (upper == 0) + { + // We have less than 64-bits, so just return the lower count + return CountDigits(value.Lower); + } + + // We have more than 1e19, so we have at least 20 digits + int digits = 20; + + if (upper > 5) + { + // ((2^128) - 1) / 1e20 < 34_02_823_669_209_384_635 which + // is 18.5318 digits, meaning the result definitely fits + // into 64-bits and we only need to add the lower digit count + + value /= new UInt128(0x5, 0x6BC7_5E2D_6310_0000); // value /= 1e20 + Debug.Assert(value.Upper == 0); + + digits += CountDigits(value.Lower); + } + else if ((upper == 5) && (value.Lower >= 0x6BC75E2D63100000)) + { + // We're greater than 1e20, but definitely less than 1e21 + // so we have exactly 21 digits + + digits++; + Debug.Assert(digits == 21); + } + + return digits; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountHexDigits(UInt128 value) + { + // The number of hex digits is log16(value) + 1, or log2(value) / 4 + 1 + return ((int)UInt128.Log2(value) >> 2) + 1; + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs index 3da8684132f077..18eac2cf08eb7e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Buffers.Binary; using System.Diagnostics; using System.Numerics; using System.Runtime.CompilerServices; @@ -11,47 +10,6 @@ namespace System.Buffers.Text { internal static partial class FormattingHelpers { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CountDigits(UInt128 value) - { - ulong upper = value.Upper; - - // 1e19 is 8AC7_2304_89E8_0000 - // 1e20 is 5_6BC7_5E2D_6310_0000 - // 1e21 is 36_35C9_ADC5_DEA0_0000 - - if (upper == 0) - { - // We have less than 64-bits, so just return the lower count - return CountDigits(value.Lower); - } - - // We have more than 1e19, so we have at least 20 digits - int digits = 20; - - if (upper > 5) - { - // ((2^128) - 1) / 1e20 < 34_02_823_669_209_384_635 which - // is 18.5318 digits, meaning the result definitely fits - // into 64-bits and we only need to add the lower digit count - - value /= new UInt128(0x5, 0x6BC7_5E2D_6310_0000); // value /= 1e20 - Debug.Assert(value.Upper == 0); - - digits += CountDigits(value.Lower); - } - else if ((upper == 5) && (value.Lower >= 0x6BC75E2D63100000)) - { - // We're greater than 1e20, but definitely less than 1e21 - // so we have exactly 21 digits - - digits++; - Debug.Assert(digits == 21); - } - - return digits; - } - // Based on do_count_digits from https://github.com/fmtlib/fmt/blob/662adf4f33346ba9aba8b072194e319869ede54a/include/fmt/format.h#L1124 [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int CountDigits(ulong value) @@ -149,13 +107,6 @@ public static int CountDigits(uint value) return (int)((value + tableValue) >> 32); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CountHexDigits(UInt128 value) - { - // The number of hex digits is log16(value) + 1, or log2(value) / 4 + 1 - return ((int)UInt128.Log2(value) >> 2) + 1; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int CountHexDigits(ulong value) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs index ad75d88cbda7c1..2a89bf96385294 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs @@ -269,8 +269,6 @@ internal static partial class Number private const int SinglePrecisionCustomFormat = 7; private const int DoublePrecisionCustomFormat = 15; - private const int CharStackBufferSize = 32; - /// The non-inclusive upper bound of . /// /// This is a semi-arbitrary bound. For mono, which is often used for more size-constrained workloads, diff --git a/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj b/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj index d2003757c60f3d..6526656921c343 100644 --- a/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj +++ b/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj @@ -25,6 +25,8 @@ + fo return spanSuccess; } + private const uint kuBase = 1_000_000_000; // 10^9 + private const int kcchBase = 9; + private static unsafe string? FormatBigInteger( bool targetSpan, BigInteger value, string? formatString, ReadOnlySpan formatSpan, @@ -882,6 +886,7 @@ internal static bool TryFormatBigInteger(BigInteger value, ReadOnlySpan fo } else { + Debug.Assert(formatString != null); charsWritten = 0; spanSuccess = false; return value._sign.ToString(formatString, info); @@ -889,17 +894,17 @@ internal static bool TryFormatBigInteger(BigInteger value, ReadOnlySpan fo } // First convert to base 10^9. - const uint kuBase = 1000000000; // 10^9 - const int kcchBase = 9; - int cuSrc = value._bits.Length; - int cuMax; - try - { - cuMax = checked(cuSrc * 10 / 9 + 2); - } - catch (OverflowException e) { throw new FormatException(SR.Format_TooLarge, e); } - uint[] rguDst = new uint[cuMax]; + // A quick conservative max length of base 10^9 representation + // A uint contributes to no more than 10/9 of 10^9 block, +1 for ceiling of division + int cuMax = cuSrc * (kcchBase + 1) / kcchBase + 1; + Debug.Assert((long)BigInteger.MaxLength * (kcchBase + 1) / kcchBase + 1 < (long)int.MaxValue); // won't overflow + + uint[]? bufferToReturn = null; + Span base1E9Buffer = cuMax < BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[cuMax] : + (bufferToReturn = ArrayPool.Shared.Rent(cuMax)); + int cuDst = 0; for (int iuSrc = cuSrc; --iuSrc >= 0;) @@ -907,93 +912,86 @@ internal static bool TryFormatBigInteger(BigInteger value, ReadOnlySpan fo uint uCarry = value._bits[iuSrc]; for (int iuDst = 0; iuDst < cuDst; iuDst++) { - Debug.Assert(rguDst[iuDst] < kuBase); - ulong uuRes = NumericsHelpers.MakeUInt64(rguDst[iuDst], uCarry); - rguDst[iuDst] = (uint)(uuRes % kuBase); - uCarry = (uint)(uuRes / kuBase); + Debug.Assert(base1E9Buffer[iuDst] < kuBase); + + // Use X86Base.DivRem when stable + ulong uuRes = NumericsHelpers.MakeUInt64(base1E9Buffer[iuDst], uCarry); + (ulong quo, ulong rem) = Math.DivRem(uuRes, kuBase); + uCarry = (uint)quo; + base1E9Buffer[iuDst] = (uint)rem; } if (uCarry != 0) { - rguDst[cuDst++] = uCarry % kuBase; - uCarry /= kuBase; + (uCarry, base1E9Buffer[cuDst++]) = Math.DivRem(uCarry, kuBase); if (uCarry != 0) - rguDst[cuDst++] = uCarry; + base1E9Buffer[cuDst++] = uCarry; } } - int cchMax; - try - { - // Each uint contributes at most 9 digits to the decimal representation. - cchMax = checked(cuDst * kcchBase); - } - catch (OverflowException e) { throw new FormatException(SR.Format_TooLarge, e); } + ReadOnlySpan base1E9Value = base1E9Buffer[..cuDst]; + + int valueDigits = (base1E9Value.Length - 1) * kcchBase + FormattingHelpers.CountDigits(base1E9Value[^1]); + + string? strResult; - bool decimalFmt = (fmt == 'g' || fmt == 'G' || fmt == 'd' || fmt == 'D' || fmt == 'r' || fmt == 'R'); - if (decimalFmt) + if (fmt == 'g' || fmt == 'G' || fmt == 'd' || fmt == 'D' || fmt == 'r' || fmt == 'R') { - if (digits > 0 && digits > cchMax) - cchMax = digits; - if (value._sign < 0) + int strDigits = Math.Max(digits, valueDigits); + string? sNegative = value.Sign < 0 ? info.NegativeSign : null; + int strLength = strDigits + (sNegative?.Length ?? 0); + + if (targetSpan) { - try + if (destination.Length < strLength) + { + spanSuccess = false; + charsWritten = 0; + } + else { - // Leave an extra slot for a minus sign. - cchMax = checked(cchMax + info.NegativeSign.Length); + sNegative?.CopyTo(destination); + fixed (char* ptr = &MemoryMarshal.GetReference(destination)) + { + BigIntegerToDecChars((Utf16Char*)ptr + strLength, base1E9Value, digits); + } + charsWritten = strLength; + spanSuccess = true; } - catch (OverflowException e) { throw new FormatException(SR.Format_TooLarge, e); } + strResult = null; } - } - - int rgchBufSize; - - try - { - // We'll pass the rgch buffer to native code, which is going to treat it like a string of digits, so it needs - // to be null terminated. Let's ensure that we can allocate a buffer of that size. - rgchBufSize = checked(cchMax + 1); - } - catch (OverflowException e) { throw new FormatException(SR.Format_TooLarge, e); } - - char[] rgch = new char[rgchBufSize]; - - int ichDst = cchMax; - - for (int iuDst = 0; iuDst < cuDst - 1; iuDst++) - { - uint uDig = rguDst[iuDst]; - Debug.Assert(uDig < kuBase); - for (int cch = kcchBase; --cch >= 0;) + else { - rgch[--ichDst] = (char)('0' + uDig % 10); - uDig /= 10; + spanSuccess = false; + charsWritten = 0; + fixed (uint* ptr = base1E9Value) + { + strResult = string.Create(strLength, (digits, ptr: (IntPtr)ptr, base1E9Value.Length, sNegative), static (span, state) => + { + state.sNegative?.CopyTo(span); + fixed (char* ptr = &MemoryMarshal.GetReference(span)) + { + BigIntegerToDecChars((Utf16Char*)ptr + span.Length, new ReadOnlySpan((void*)state.ptr, state.Length), state.digits); + } + }); + } } } - for (uint uDig = rguDst[cuDst - 1]; uDig != 0;) - { - rgch[--ichDst] = (char)('0' + uDig % 10); - uDig /= 10; - } - - if (!decimalFmt) + else { - // sign = true for negative and false for 0 and positive values - bool sign = (value._sign < 0); - int scale = cchMax - ichDst; - - byte[]? buffer = ArrayPool.Shared.Rent(rgchBufSize + 1); - fixed (byte* ptr = buffer) // NumberBuffer expects pinned Digits + byte[]? numberBufferToReturn = null; + Span numberBuffer = valueDigits + 1 <= CharStackBufferSize ? + stackalloc byte[valueDigits + 1] : + (numberBufferToReturn = ArrayPool.Shared.Rent(valueDigits + 1)); + fixed (byte* ptr = numberBuffer) // NumberBuffer expects pinned Digits { - scoped NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, buffer); + scoped NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, ptr, valueDigits + 1); + BigIntegerToDecChars((Utf8Char*)ptr + valueDigits, base1E9Value, valueDigits); + number.Digits[^1] = 0; + number.DigitsCount = valueDigits; + number.Scale = valueDigits; + number.IsNegative = value.Sign < 0; - for (int i = 0; i < rgch.Length - ichDst; i++) - number.Digits[i] = (byte)rgch[ichDst + i]; - number.Digits[rgch.Length - ichDst] = 0; - number.DigitsCount = rgch.Length - ichDst - 1; // The cut-off point to switch (G)eneral from (F)ixed-point to (E)xponential form - number.Scale = scale; - number.IsNegative = sign; - - scoped var vlb = new ValueListBuilder(stackalloc Utf16Char[128]); // arbitrary stack cut-off + scoped var vlb = new ValueListBuilder(stackalloc Utf16Char[CharStackBufferSize]); // arbitrary stack cut-off if (fmt != 0) { @@ -1007,59 +1005,44 @@ internal static bool TryFormatBigInteger(BigInteger value, ReadOnlySpan fo if (targetSpan) { spanSuccess = vlb.TryCopyTo(MemoryMarshal.Cast(destination), out charsWritten); - vlb.Dispose(); - return null; + strResult = null; } else { charsWritten = 0; spanSuccess = false; - string result = MemoryMarshal.Cast(vlb.AsSpan()).ToString(); - vlb.Dispose(); - return result; + strResult = MemoryMarshal.Cast(vlb.AsSpan()).ToString(); + } + + vlb.Dispose(); + if (numberBufferToReturn != null) + { + ArrayPool.Shared.Return(numberBufferToReturn); } } } - // Format Round-trip decimal - // This format is supported for integral types only. The number is converted to a string of - // decimal digits (0-9), prefixed by a minus sign if the number is negative. The precision - // specifier indicates the minimum number of digits desired in the resulting string. If required, - // the number is padded with zeros to its left to produce the number of digits given by the - // precision specifier. - int numDigitsPrinted = cchMax - ichDst; - while (digits > 0 && digits > numDigitsPrinted) - { - // pad leading zeros - rgch[--ichDst] = '0'; - digits--; - } - if (value._sign < 0) + if (bufferToReturn != null) { - string negativeSign = info.NegativeSign; - for (int i = negativeSign.Length - 1; i > -1; i--) - rgch[--ichDst] = negativeSign[i]; + ArrayPool.Shared.Return(bufferToReturn); } - int resultLength = cchMax - ichDst; - if (!targetSpan) - { - charsWritten = 0; - spanSuccess = false; - return new string(rgch, ichDst, cchMax - ichDst); - } - else if (new ReadOnlySpan(rgch, ichDst, cchMax - ichDst).TryCopyTo(destination)) - { - charsWritten = resultLength; - spanSuccess = true; - return null; - } - else + return strResult; + } + + private static unsafe TChar* BigIntegerToDecChars(TChar* bufferEnd, ReadOnlySpan base1E9Value, int digits) + where TChar : unmanaged, IUtfChar + { + Debug.Assert(base1E9Value[^1] != 0, "Leading zeros should be trimmed by caller."); + + // The base 10^9 value is in reverse order + for (int i = 0; i < base1E9Value.Length - 1; i++) { - charsWritten = 0; - spanSuccess = false; - return null; + bufferEnd = UInt32ToDecChars(bufferEnd, base1E9Value[i], kcchBase); + digits -= kcchBase; } + + return UInt32ToDecChars(bufferEnd, base1E9Value[^1], digits); } } diff --git a/src/libraries/System.Runtime.Numerics/src/System/Number.Polyfill.cs b/src/libraries/System.Runtime.Numerics/src/System/Number.Polyfill.cs index d5de46b5842eb5..9c1c2a89daf5ef 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Number.Polyfill.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Number.Polyfill.cs @@ -43,6 +43,21 @@ internal readonly struct Utf16Char(char ch) : IUtfChar public bool Equals(Utf16Char other) => value == other.value; } +#pragma warning disable CA1067 // Polyfill only type + internal readonly struct Utf8Char(byte ch) : IUtfChar +#pragma warning restore CA1067 + { + private readonly byte value = ch; + + public static Utf8Char CastFrom(byte value) => new(value); + public static Utf8Char CastFrom(char value) => new((byte)value); + public static Utf8Char CastFrom(int value) => new((byte)value); + public static Utf8Char CastFrom(uint value) => new((byte)value); + public static Utf8Char CastFrom(ulong value) => new((byte)value); + public static uint CastToUInt32(Utf8Char value) => value.value; + public bool Equals(Utf8Char other) => value == other.value; + } + internal static partial class Number { internal static bool AllowHyphenDuringParsing(this NumberFormatInfo info) From 9bba3836ed4ddf2592ae9b92b3110dc6af03e453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Mon, 22 Apr 2024 20:18:23 +0200 Subject: [PATCH 043/248] Disable AllItemsEnumeratedOnce_For test on s390x (#101389) It is currently hanging in CI: https://github.com/dotnet/runtime/issues/101380 --- .../tests/ParallelForEachAsyncTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForEachAsyncTests.cs b/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForEachAsyncTests.cs index 77c16ddd72c928..01a4dd37908ee7 100644 --- a/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForEachAsyncTests.cs +++ b/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForEachAsyncTests.cs @@ -459,6 +459,7 @@ await Parallel.ForEachAsync(EnumerableRangeAsync(0, 0), (item, cancellationToken [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [InlineData(false)] [InlineData(true)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101380", typeof(PlatformDetection), nameof(PlatformDetection.IsS390xProcess))] public async Task AllItemsEnumeratedOnce_For(bool yield) { await Test(yield); From c1f91610c53681c7069ae1c1502a88e2644f2543 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 22 Apr 2024 15:01:47 -0400 Subject: [PATCH 044/248] Simplify ReadOnlySpan pointer ctor (#101362) --- .../System.Private.CoreLib/src/System/ReadOnlySpan.cs | 5 +++-- src/libraries/System.Private.CoreLib/src/System/Span.cs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs b/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs index b182d42b66ecd9..e2c49c820d7738 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs @@ -10,7 +10,8 @@ using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute; using EditorBrowsableState = System.ComponentModel.EditorBrowsableState; -#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span.Equals(object)' overrides non-obsolete member 'object.Equals(object)' +#pragma warning disable 0809 // Obsolete member 'Span.Equals(object)' overrides non-obsolete member 'object.Equals(object)' +#pragma warning disable 8500 // address / sizeof of managed types namespace System { @@ -107,7 +108,7 @@ public unsafe ReadOnlySpan(void* pointer, int length) if (length < 0) ThrowHelper.ThrowArgumentOutOfRangeException(); - _reference = ref Unsafe.As(ref *(byte*)pointer); + _reference = ref *(T*)pointer; _length = length; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Span.cs b/src/libraries/System.Private.CoreLib/src/System/Span.cs index 38b94e872b0cb3..691b2eb558f35b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Span.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Span.cs @@ -9,7 +9,7 @@ using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute; using EditorBrowsableState = System.ComponentModel.EditorBrowsableState; -#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span.Equals(object)' overrides non-obsolete member 'object.Equals(object)' +#pragma warning disable 0809 // Obsolete member 'Span.Equals(object)' overrides non-obsolete member 'object.Equals(object)' #pragma warning disable 8500 // address / sizeof of managed types namespace System From 6578e695d95213ae977642fae84f9708a0787b77 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 22 Apr 2024 14:10:04 -0700 Subject: [PATCH 045/248] Download contents into a subfolder to preserve previous paths (#101391) --- eng/pipelines/official/jobs/prepare-signed-artifacts.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/pipelines/official/jobs/prepare-signed-artifacts.yml b/eng/pipelines/official/jobs/prepare-signed-artifacts.yml index f52d685e964ef7..eb25d311890a98 100644 --- a/eng/pipelines/official/jobs/prepare-signed-artifacts.yml +++ b/eng/pipelines/official/jobs/prepare-signed-artifacts.yml @@ -33,7 +33,7 @@ jobs: fetchDepth: 20 - input: pipelineArtifact artifactName: IntermediateArtifacts - targetPath: $(Build.SourcesDirectory)\artifacts\PackageDownload + targetPath: $(Build.SourcesDirectory)\artifacts\PackageDownload\IntermediateArtifacts outputs: - output: pipelineArtifact displayName: 'Publish BuildLogs' From a4337b780f9d13a02633bd44b9ae675feb2c87df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Tue, 23 Apr 2024 06:14:35 +0900 Subject: [PATCH 046/248] Remove `IlcKeepManagedDebuggerSupport` (#101369) This was introduced in #82696, but on a second thought, we should be able to use the documented `DebuggerSupport` for this. We still don't want to full on default this to `false` for reasons described in the PR, but the explicit value of `true` can be the escape hatch. --- .../BuildIntegration/Microsoft.NETCore.Native.targets | 2 +- .../tests/System.Runtime.Tests/System.Runtime.Tests.csproj | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index ce4a3236f58e30..2c9a4e02aa496d 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -289,7 +289,7 @@ The .NET Foundation licenses this file to you under the MIT license. - + diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj index 4bf5a231b12ed2..1e6b01ecf75b30 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj @@ -12,9 +12,7 @@ true - - true - + true false From f191f5f44ece8e8a7ea134ca6bb4fe4531f33a16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Tue, 23 Apr 2024 06:15:13 +0900 Subject: [PATCH 047/248] Skip DispatchProxy app test on native AOT (#101374) --- eng/testing/linker/trimmingTests.targets | 8 +++++++- .../System.Reflection.DispatchProxy.TrimmingTests.proj | 7 +++++++ src/libraries/tests.proj | 1 - 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/eng/testing/linker/trimmingTests.targets b/eng/testing/linker/trimmingTests.targets index 9ff325e82972c0..d474e19b69accd 100644 --- a/eng/testing/linker/trimmingTests.targets +++ b/eng/testing/linker/trimmingTests.targets @@ -38,7 +38,13 @@ - + <_SkippedAppSourceFiles Include="@(TestConsoleAppSourceFiles)" Condition="$([System.String]::Copy('%(TestConsoleAppSourceFiles.SkipOnTestRuntimes)').Contains('$(PackageRID)'))" /> + + <_SkippedAppSourceFiles Include="@(TestConsoleAppSourceFiles)" Condition="'$(RunNativeAotTestApps)' == 'true' and '%(TestConsoleAppSourceFiles.NativeAotIncompatible)' == 'true'" /> + + <_AppSourceFiles Include="@(TestConsoleAppSourceFiles)" Exclude="@(_SkippedAppSourceFiles)" /> + + %(FullPath) diff --git a/src/libraries/System.Reflection.DispatchProxy/tests/TrimmingTests/System.Reflection.DispatchProxy.TrimmingTests.proj b/src/libraries/System.Reflection.DispatchProxy/tests/TrimmingTests/System.Reflection.DispatchProxy.TrimmingTests.proj index da4a46f2ae141a..adb54eab7335a0 100644 --- a/src/libraries/System.Reflection.DispatchProxy/tests/TrimmingTests/System.Reflection.DispatchProxy.TrimmingTests.proj +++ b/src/libraries/System.Reflection.DispatchProxy/tests/TrimmingTests/System.Reflection.DispatchProxy.TrimmingTests.proj @@ -1,5 +1,12 @@ + + + + true + + + diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index f89150c3e25d60..75eeb492b87c2d 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -652,7 +652,6 @@ - From f8903fe264818a77eb32097fab0b444ce426d5ed Mon Sep 17 00:00:00 2001 From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com> Date: Mon, 22 Apr 2024 14:32:36 -0700 Subject: [PATCH 048/248] Only add interface methods to _virtual_methods cache (#101139) We only ever do operations on interface methods, so we can only keep interface methods rather than all virtual methods --- .../src/linker/Linker.Steps/MarkStep.cs | 56 ++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs index 876ca9da73122b..f26a176c304120 100644 --- a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs @@ -60,7 +60,7 @@ protected LinkContext Context { } protected Queue<(MethodDefinition, DependencyInfo, MessageOrigin)> _methods; - protected Dictionary _virtual_methods; + protected Dictionary _interface_methods; protected Queue _assemblyLevelAttributes; protected Queue<(AttributeProviderPair, DependencyInfo, MarkScopeStack.Scope)> _lateMarkedAttributes; protected List<(TypeDefinition, MarkScopeStack.Scope)> _typesWithInterfaces; @@ -219,7 +219,7 @@ internal DynamicallyAccessedMembersTypeHierarchy DynamicallyAccessedMembersTypeH public MarkStep () { _methods = new Queue<(MethodDefinition, DependencyInfo, MessageOrigin)> (); - _virtual_methods = new Dictionary (); + _interface_methods = new Dictionary (); _assemblyLevelAttributes = new Queue (); _lateMarkedAttributes = new Queue<(AttributeProviderPair, DependencyInfo, MarkScopeStack.Scope)> (); _typesWithInterfaces = new List<(TypeDefinition, MarkScopeStack.Scope)> (); @@ -437,7 +437,7 @@ bool ProcessPrimaryQueue () while (!QueueIsEmpty ()) { ProcessQueue (); - ProcessVirtualMethods (); + ProcessInterfaceMethods (); ProcessMarkedTypesWithInterfaces (); ProcessDynamicCastableImplementationInterfaces (); ProcessPendingBodies (); @@ -530,11 +530,11 @@ protected virtual void EnqueueMethod (MethodDefinition method, in DependencyInfo _methods.Enqueue ((method, reason, origin)); } - void ProcessVirtualMethods () + void ProcessInterfaceMethods () { - foreach ((var method, var scope) in _virtual_methods) { + foreach ((var method, var scope) in _interface_methods) { using (ScopeStack.PushLocalScope (scope)) { - ProcessVirtualMethod (method); + ProcessInterfaceMethod (method); } } } @@ -568,7 +568,7 @@ void ProcessMarkedTypesWithInterfaces () continue; foreach (var ov in baseMethods) { if (ov.Base.DeclaringType is not null && ov.Base.DeclaringType.IsInterface && IgnoreScope (ov.Base.DeclaringType.Scope)) { - _virtual_methods.TryAdd (ov.Base, ScopeStack.CurrentScope); + MarkMethodAsVirtual (ov.Base, ScopeStack.CurrentScope); } } } @@ -651,28 +651,32 @@ void ProcessPendingBodies () } } } - - void ProcessVirtualMethod (MethodDefinition method) + void MarkMethodAsVirtual (MethodDefinition method, MarkScopeStack.Scope scope) { Annotations.EnqueueVirtualMethod (method); - if (method.DeclaringType.IsInterface) { - var defaultImplementations = Annotations.GetDefaultInterfaceImplementations (method); - if (defaultImplementations is not null) { - foreach (var dimInfo in defaultImplementations) { - ProcessDefaultImplementation (dimInfo); + _interface_methods.TryAdd (method, scope); + } + } - if (IsInterfaceImplementationMethodNeededByTypeDueToInterface (dimInfo)) - MarkMethod (dimInfo.Override, new DependencyInfo (DependencyKind.Override, dimInfo.Base), ScopeStack.CurrentScope.Origin); - } + void ProcessInterfaceMethod (MethodDefinition method) + { + Debug.Assert (method.DeclaringType.IsInterface); + var defaultImplementations = Annotations.GetDefaultInterfaceImplementations (method); + if (defaultImplementations is not null) { + foreach (var dimInfo in defaultImplementations) { + ProcessDefaultImplementation (dimInfo); + + if (IsInterfaceImplementationMethodNeededByTypeDueToInterface (dimInfo)) + MarkMethod (dimInfo.Override, new DependencyInfo (DependencyKind.Override, dimInfo.Base), ScopeStack.CurrentScope.Origin); } - List? overridingMethods = (List?)Annotations.GetOverrides (method); - if (overridingMethods is not null) { - for (int i = 0; i < overridingMethods.Count; i++) { - OverrideInformation ov = overridingMethods[i]; - if (IsInterfaceImplementationMethodNeededByTypeDueToInterface (ov)) - MarkMethod (ov.Override, new DependencyInfo (DependencyKind.Override, ov.Base), ScopeStack.CurrentScope.Origin); - } + } + List? overridingMethods = (List?)Annotations.GetOverrides (method); + if (overridingMethods is not null) { + for (int i = 0; i < overridingMethods.Count; i++) { + OverrideInformation ov = overridingMethods[i]; + if (IsInterfaceImplementationMethodNeededByTypeDueToInterface (ov)) + MarkMethod (ov.Override, new DependencyInfo (DependencyKind.Override, ov.Base), ScopeStack.CurrentScope.Origin); } } } @@ -3227,7 +3231,7 @@ protected virtual void ProcessMethod (MethodDefinition method, in DependencyInfo MarkMethodSpecialCustomAttributes (method); if (method.IsVirtual) - _virtual_methods.TryAdd (method, ScopeStack.CurrentScope); + MarkMethodAsVirtual (method, ScopeStack.CurrentScope); MarkNewCodeDependencies (method); @@ -3435,7 +3439,7 @@ void MarkBaseMethods (MethodDefinition method) // This will produce warnings for all interface methods and virtual methods regardless of whether the interface, interface implementation, or interface method is kept or not. if (ov.Base.DeclaringType.IsInterface && !method.DeclaringType.IsInterface) { // These are all virtual, no need to check IsVirtual before adding to list - _virtual_methods.TryAdd (ov.Base, ScopeStack.CurrentScope); + MarkMethodAsVirtual (ov.Base, ScopeStack.CurrentScope); continue; } From aa9edcc5c8b37e41554779c299cf52c17297723d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Tue, 23 Apr 2024 06:33:23 +0900 Subject: [PATCH 049/248] Fix S.D.Tracing testapps with AOT (#101373) I believe what the test is doing is not trim safe and only succeeds due to lucky IL trimming implementation details. --- .../tests/TrimmingTests/EventSourcePropertyValueTest.cs | 2 ++ src/libraries/tests.proj | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Diagnostics.Tracing/tests/TrimmingTests/EventSourcePropertyValueTest.cs b/src/libraries/System.Diagnostics.Tracing/tests/TrimmingTests/EventSourcePropertyValueTest.cs index 6682cb0fd45eb8..e98a84a45ae888 100644 --- a/src/libraries/System.Diagnostics.Tracing/tests/TrimmingTests/EventSourcePropertyValueTest.cs +++ b/src/libraries/System.Diagnostics.Tracing/tests/TrimmingTests/EventSourcePropertyValueTest.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; /// @@ -34,6 +35,7 @@ private class TestEventSource : EventSource public TestEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) { } [Event(1)] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(TestSubData))] public void LogData(TestData data) { Write("LogData", data); diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 75eeb492b87c2d..5d1b0a0c7fb4fe 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -648,7 +648,6 @@ Condition="'$(TestPackages)' == 'true'" /> - From e751fe855a4788a1e133b88f6972891d87256c41 Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Mon, 22 Apr 2024 14:57:14 -0700 Subject: [PATCH 050/248] [cdac] Read contract descriptor from target (#101208) - Get `DotNetRuntimeContractDescriptor` address from the target - Read contract descriptor to determine endianness and pointer size - Parse JSON descriptor and store contracts --- src/coreclr/debug/daccess/cdac.cpp | 20 +- src/coreclr/debug/daccess/cdac.h | 7 +- src/coreclr/debug/daccess/daccess.cpp | 10 +- .../src/ContractDescriptorParser.cs | 21 +- .../managed/cdacreader/src/Entrypoints.cs | 5 +- src/native/managed/cdacreader/src/Root.cs | 12 + src/native/managed/cdacreader/src/Target.cs | 208 ++++++++++++++++-- .../managed/cdacreader/src/cdacreader.csproj | 1 + .../tests/ContractDescriptorParserTests.cs | 2 + ...iagnostics.DataContractReader.Tests.csproj | 1 + 10 files changed, 241 insertions(+), 46 deletions(-) create mode 100644 src/native/managed/cdacreader/src/Root.cs diff --git a/src/coreclr/debug/daccess/cdac.cpp b/src/coreclr/debug/daccess/cdac.cpp index 23478592371a16..a4146709ec7233 100644 --- a/src/coreclr/debug/daccess/cdac.cpp +++ b/src/coreclr/debug/daccess/cdac.cpp @@ -28,8 +28,12 @@ namespace int ReadFromTargetCallback(uint64_t addr, uint8_t* dest, uint32_t count, void* context) { - CDAC* cdac = reinterpret_cast(context); - return cdac->ReadFromTarget(addr, dest, count); + ICorDebugDataTarget* target = reinterpret_cast(context); + HRESULT hr = ReadFromDataTarget(target, addr, dest, count); + if (FAILED(hr)) + return hr; + + return S_OK; } } @@ -52,11 +56,12 @@ CDAC::CDAC(HMODULE module, uint64_t descriptorAddr, ICorDebugDataTarget* target) return; } + m_target->AddRef(); decltype(&cdac_reader_init) init = reinterpret_cast(::GetProcAddress(m_module, "cdac_reader_init")); decltype(&cdac_reader_get_sos_interface) getSosInterface = reinterpret_cast(::GetProcAddress(m_module, "cdac_reader_get_sos_interface")); _ASSERTE(init != nullptr && getSosInterface != nullptr); - init(descriptorAddr, &ReadFromTargetCallback, this, &m_cdac_handle); + init(descriptorAddr, &ReadFromTargetCallback, m_target, &m_cdac_handle); getSosInterface(m_cdac_handle, &m_sos); } @@ -77,12 +82,3 @@ IUnknown* CDAC::SosInterface() { return m_sos; } - -int CDAC::ReadFromTarget(uint64_t addr, uint8_t* dest, uint32_t count) -{ - HRESULT hr = ReadFromDataTarget(m_target, addr, dest, count); - if (FAILED(hr)) - return hr; - - return S_OK; -} diff --git a/src/coreclr/debug/daccess/cdac.h b/src/coreclr/debug/daccess/cdac.h index 54418dc549f1f0..d5c0eecb0f7373 100644 --- a/src/coreclr/debug/daccess/cdac.h +++ b/src/coreclr/debug/daccess/cdac.h @@ -21,7 +21,7 @@ class CDAC final CDAC(CDAC&& other) : m_module{ other.m_module } , m_cdac_handle{ other.m_cdac_handle } - , m_target{ other.m_target } + , m_target{ other.m_target.Extract() } , m_sos{ other.m_sos.Extract() } { other.m_module = NULL; @@ -34,7 +34,7 @@ class CDAC final { m_module = other.m_module; m_cdac_handle = other.m_cdac_handle; - m_target = other.m_target; + m_target = other.m_target.Extract(); m_sos = other.m_sos.Extract(); other.m_module = NULL; @@ -54,7 +54,6 @@ class CDAC final // This does not AddRef the returned interface IUnknown* SosInterface(); - int ReadFromTarget(uint64_t addr, uint8_t* dest, uint32_t count); private: CDAC(HMODULE module, uint64_t descriptorAddr, ICorDebugDataTarget* target); @@ -62,7 +61,7 @@ class CDAC final private: HMODULE m_module; intptr_t m_cdac_handle; - ICorDebugDataTarget* m_target; + NonVMComHolder m_target; NonVMComHolder m_sos; }; diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp index 2f08750bc5c61b..971b8b90980b32 100644 --- a/src/coreclr/debug/daccess/daccess.cpp +++ b/src/coreclr/debug/daccess/daccess.cpp @@ -30,6 +30,8 @@ #include #else extern "C" bool TryGetSymbol(ICorDebugDataTarget* dataTarget, uint64_t baseAddress, const char* symbolName, uint64_t* symbolAddress); +// cDAC depends on symbol lookup to find the contract descriptor +#define CAN_USE_CDAC #endif #include "dwbucketmanager.hpp" @@ -5493,15 +5495,16 @@ ClrDataAccess::Initialize(void) IfFailRet(GetDacGlobalValues()); IfFailRet(DacGetHostVtPtrs()); +// TODO: [cdac] TryGetSymbol is only implemented for Linux, OSX, and Windows. +#ifdef CAN_USE_CDAC CLRConfigNoCache enable = CLRConfigNoCache::Get("ENABLE_CDAC"); if (enable.IsSet()) { DWORD val; if (enable.TryAsInteger(10, val) && val == 1) { - // TODO: [cdac] Get contract descriptor from exported symbol uint64_t contractDescriptorAddr = 0; - //if (TryGetSymbol(m_pTarget, m_globalBase, "DotNetRuntimeContractDescriptor", &contractDescriptorAddr)) + if (TryGetSymbol(m_pTarget, m_globalBase, "DotNetRuntimeContractDescriptor", &contractDescriptorAddr)) { m_cdac = CDAC::Create(contractDescriptorAddr, m_pTarget); if (m_cdac.IsValid()) @@ -5514,6 +5517,7 @@ ClrDataAccess::Initialize(void) } } } +#endif // // DAC is now setup and ready to use @@ -6946,7 +6950,7 @@ GetDacTableAddress(ICorDebugDataTarget* dataTarget, ULONG64 baseAddress, PULONG6 return E_INVALIDARG; } #endif - // On MacOS, FreeBSD or NetBSD use the RVA include file + // On FreeBSD, NetBSD, or SunOS use the RVA include file *dacTableAddress = baseAddress + DAC_TABLE_RVA; #else // Otherwise, try to get the dac table address via the export symbol diff --git a/src/native/managed/cdacreader/src/ContractDescriptorParser.cs b/src/native/managed/cdacreader/src/ContractDescriptorParser.cs index fbf76cd4e8d439..a82235731e4a07 100644 --- a/src/native/managed/cdacreader/src/ContractDescriptorParser.cs +++ b/src/native/managed/cdacreader/src/ContractDescriptorParser.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; using System.Text.Json; using System.Text.Json.Serialization; @@ -23,13 +24,15 @@ public partial class ContractDescriptorParser /// /// Parses the "compact" representation of a contract descriptor. /// + // Workaround for https://github.com/dotnet/runtime/issues/101205 + [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Root))] public static ContractDescriptor? ParseCompact(ReadOnlySpan json) { return JsonSerializer.Deserialize(json, ContractDescriptorContext.Default.ContractDescriptor); } [JsonSerializable(typeof(ContractDescriptor))] - [JsonSerializable(typeof(int))] + [JsonSerializable(typeof(int?))] [JsonSerializable(typeof(string))] [JsonSerializable(typeof(Dictionary))] [JsonSerializable(typeof(Dictionary))] @@ -38,11 +41,17 @@ public partial class ContractDescriptorParser [JsonSerializable(typeof(TypeDescriptor))] [JsonSerializable(typeof(FieldDescriptor))] [JsonSerializable(typeof(GlobalDescriptor))] + [JsonSerializable(typeof(Dictionary))] [JsonSourceGenerationOptions(AllowTrailingCommas = true, DictionaryKeyPolicy = JsonKnownNamingPolicy.Unspecified, // contracts, types and globals are case sensitive PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, NumberHandling = JsonNumberHandling.AllowReadingFromString, - ReadCommentHandling = JsonCommentHandling.Skip)] + ReadCommentHandling = JsonCommentHandling.Skip, + UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip, + UnknownTypeHandling = JsonUnknownTypeHandling.JsonElement, + Converters = [typeof(TypeDescriptorConverter), + typeof(FieldDescriptorConverter), + typeof(GlobalDescriptorConverter)])] internal sealed partial class ContractDescriptorContext : JsonSerializerContext { } @@ -58,7 +67,13 @@ public class ContractDescriptor public Dictionary? Globals { get; set; } [JsonExtensionData] - public Dictionary? Extras { get; set; } + public Dictionary? Extras { get; set; } + + public override string ToString() + { + return $"Version: {Version}, Baseline: {Baseline}, Contracts: {Contracts?.Count}, Types: {Types?.Count}, Globals: {Globals?.Count}"; + } + } [JsonConverter(typeof(TypeDescriptorConverter))] diff --git a/src/native/managed/cdacreader/src/Entrypoints.cs b/src/native/managed/cdacreader/src/Entrypoints.cs index 30cab9ec851887..908d534fe60c4e 100644 --- a/src/native/managed/cdacreader/src/Entrypoints.cs +++ b/src/native/managed/cdacreader/src/Entrypoints.cs @@ -14,7 +14,10 @@ internal static class Entrypoints [UnmanagedCallersOnly(EntryPoint = $"{CDAC}init")] private static unsafe int Init(ulong descriptor, delegate* unmanaged readFromTarget, void* readContext, IntPtr* handle) { - Target target = new(descriptor, readFromTarget, readContext); + // TODO: [cdac] Better error code/details + if (!Target.TryCreate(descriptor, readFromTarget, readContext, out Target? target)) + return -1; + GCHandle gcHandle = GCHandle.Alloc(target); *handle = GCHandle.ToIntPtr(gcHandle); return 0; diff --git a/src/native/managed/cdacreader/src/Root.cs b/src/native/managed/cdacreader/src/Root.cs new file mode 100644 index 00000000000000..05aefea3dea2a5 --- /dev/null +++ b/src/native/managed/cdacreader/src/Root.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text.Json.Serialization; + +namespace Microsoft.Diagnostics.DataContractReader; + +internal static class Root +{ + // https://github.com/dotnet/runtime/issues/101205 + public static JsonDerivedTypeAttribute[] R1 = new JsonDerivedTypeAttribute[] { null! }; +} diff --git a/src/native/managed/cdacreader/src/Target.cs b/src/native/managed/cdacreader/src/Target.cs index 898cab774bfb56..049a9f80ed2265 100644 --- a/src/native/managed/cdacreader/src/Target.cs +++ b/src/native/managed/cdacreader/src/Target.cs @@ -3,6 +3,7 @@ using System; using System.Buffers.Binary; +using System.Collections.Generic; namespace Microsoft.Diagnostics.DataContractReader; @@ -16,49 +17,210 @@ public struct TargetPointer internal sealed unsafe class Target { - private readonly delegate* unmanaged _readFromTarget; - private readonly void* _readContext; + private const int StackAllocByteThreshold = 1024; - private bool _isLittleEndian; - private int _pointerSize; + private readonly struct Configuration + { + public bool IsLittleEndian { get; init; } + public int PointerSize { get; init; } + } + + private readonly Configuration _config; + private readonly Reader _reader; + + private readonly IReadOnlyDictionary _contracts = new Dictionary(); + private readonly TargetPointer[] _pointerData = []; + + public static bool TryCreate(ulong contractDescriptor, delegate* unmanaged readFromTarget, void* readContext, out Target? target) + { + Reader reader = new Reader(readFromTarget, readContext); + if (TryReadContractDescriptor(contractDescriptor, reader, out Configuration config, out ContractDescriptorParser.ContractDescriptor? descriptor, out TargetPointer[] pointerData)) + { + target = new Target(config, descriptor!, pointerData, reader); + return true; + } + + target = null; + return false; + } - public Target(ulong _, delegate* unmanaged readFromTarget, void* readContext) + private Target(Configuration config, ContractDescriptorParser.ContractDescriptor descriptor, TargetPointer[] pointerData, Reader reader) { - _readFromTarget = readFromTarget; - _readContext = readContext; + _config = config; + _reader = reader; + + // TODO: [cdac] Read globals and types + // note: we will probably want to store the globals and types into a more usable form + _contracts = descriptor.Contracts ?? []; - // TODO: [cdac] Populate from descriptor - _isLittleEndian = BitConverter.IsLittleEndian; - _pointerSize = IntPtr.Size; + _pointerData = pointerData; + } + + // See docs/design/datacontracts/contract-descriptor.md + private static bool TryReadContractDescriptor( + ulong address, + Reader reader, + out Configuration config, + out ContractDescriptorParser.ContractDescriptor? descriptor, + out TargetPointer[] pointerData) + { + config = default; + descriptor = null; + pointerData = []; + + // Magic - uint64_t + Span buffer = stackalloc byte[sizeof(ulong)]; + if (reader.ReadFromTarget(address, buffer) < 0) + return false; + + address += sizeof(ulong); + ReadOnlySpan magicLE = "DNCCDAC\0"u8; + ReadOnlySpan magicBE = "\0CADCCND"u8; + bool isLittleEndian = buffer.SequenceEqual(magicLE); + if (!isLittleEndian && !buffer.SequenceEqual(magicBE)) + return false; + + // Flags - uint32_t + if (!TryReadUInt32(address, isLittleEndian, reader, out uint flags)) + return false; + + address += sizeof(uint); + + // Bit 1 represents the pointer size. 0 = 64-bit, 1 = 32-bit. + int pointerSize = (int)(flags & 0x2) == 0 ? sizeof(ulong) : sizeof(uint); + + config = new Configuration { IsLittleEndian = isLittleEndian, PointerSize = pointerSize }; + + // Descriptor size - uint32_t + if (!TryReadUInt32(address, config.IsLittleEndian, reader, out uint descriptorSize)) + return false; + + address += sizeof(uint); + + // Descriptor - char* + if (!TryReadPointer(address, config, reader, out TargetPointer descriptorAddr)) + return false; + + address += (uint)pointerSize; + + // Pointer data count - uint32_t + if (!TryReadUInt32(address, config.IsLittleEndian, reader, out uint pointerDataCount)) + return false; + + address += sizeof(uint); + + // Padding - uint32_t + address += sizeof(uint); + + // Pointer data - uintptr_t* + if (!TryReadPointer(address, config, reader, out TargetPointer pointerDataAddr)) + return false; + + // Read descriptor + Span descriptorBuffer = descriptorSize <= StackAllocByteThreshold + ? stackalloc byte[(int)descriptorSize] + : new byte[(int)descriptorSize]; + if (reader.ReadFromTarget(descriptorAddr.Value, descriptorBuffer) < 0) + return false; + + descriptor = ContractDescriptorParser.ParseCompact(descriptorBuffer); + if (descriptor is null) + return false; + + // Read pointer data + pointerData = new TargetPointer[pointerDataCount]; + for (int i = 0; i < pointerDataCount; i++) + { + if (!TryReadPointer(pointerDataAddr.Value + (uint)(i * pointerSize), config, reader, out pointerData[i])) + return false; + } + + return true; + } + + public uint ReadUInt32(ulong address) + { + if (!TryReadUInt32(address, out uint value)) + throw new InvalidOperationException($"Failed to read uint32 at 0x{address:x8}."); + + return value; + } + + public bool TryReadUInt32(ulong address, out uint value) + => TryReadUInt32(address, _config.IsLittleEndian, _reader, out value); + + private static bool TryReadUInt32(ulong address, bool isLittleEndian, Reader reader, out uint value) + { + value = 0; + + Span buffer = stackalloc byte[sizeof(uint)]; + if (reader.ReadFromTarget(address, buffer) < 0) + return false; + + value = isLittleEndian + ? BinaryPrimitives.ReadUInt32LittleEndian(buffer) + : BinaryPrimitives.ReadUInt32BigEndian(buffer); + + return true; + } + + public TargetPointer ReadPointer(ulong address) + { + if (!TryReadPointer(address, out TargetPointer pointer)) + throw new InvalidOperationException($"Failed to read pointer at 0x{address:x8}."); + + return pointer; } public bool TryReadPointer(ulong address, out TargetPointer pointer) + => TryReadPointer(address, _config, _reader, out pointer); + + private static bool TryReadPointer(ulong address, Configuration config, Reader reader, out TargetPointer pointer) { pointer = TargetPointer.Null; - byte* buffer = stackalloc byte[_pointerSize]; - ReadOnlySpan span = new ReadOnlySpan(buffer, _pointerSize); - if (ReadFromTarget(address, buffer, (uint)_pointerSize) < 0) + Span buffer = stackalloc byte[config.PointerSize]; + if (reader.ReadFromTarget(address, buffer) < 0) return false; - if (_pointerSize == sizeof(uint)) + if (config.PointerSize == sizeof(uint)) { pointer = new TargetPointer( - _isLittleEndian - ? BinaryPrimitives.ReadUInt32LittleEndian(span) - : BinaryPrimitives.ReadUInt32BigEndian(span)); + config.IsLittleEndian + ? BinaryPrimitives.ReadUInt32LittleEndian(buffer) + : BinaryPrimitives.ReadUInt32BigEndian(buffer)); } - else if (_pointerSize == sizeof(ulong)) + else if (config.PointerSize == sizeof(ulong)) { pointer = new TargetPointer( - _isLittleEndian - ? BinaryPrimitives.ReadUInt64LittleEndian(span) - : BinaryPrimitives.ReadUInt64BigEndian(span)); + config.IsLittleEndian + ? BinaryPrimitives.ReadUInt64LittleEndian(buffer) + : BinaryPrimitives.ReadUInt64BigEndian(buffer)); } return true; } - private int ReadFromTarget(ulong address, byte* buffer, uint bytesToRead) - => _readFromTarget(address, buffer, bytesToRead, _readContext); + private sealed class Reader + { + private readonly delegate* unmanaged _readFromTarget; + private readonly void* _context; + + public Reader(delegate* unmanaged readFromTarget, void* context) + { + _readFromTarget = readFromTarget; + _context = context; + } + + public int ReadFromTarget(ulong address, Span buffer) + { + fixed (byte* bufferPtr = buffer) + { + return _readFromTarget(address, bufferPtr, (uint)buffer.Length, _context); + } + } + + public int ReadFromTarget(ulong address, byte* buffer, uint bytesToRead) + => _readFromTarget(address, buffer, bytesToRead, _context); + } } diff --git a/src/native/managed/cdacreader/src/cdacreader.csproj b/src/native/managed/cdacreader/src/cdacreader.csproj index 253bb3c6c27e01..20ecd197c70460 100644 --- a/src/native/managed/cdacreader/src/cdacreader.csproj +++ b/src/native/managed/cdacreader/src/cdacreader.csproj @@ -9,6 +9,7 @@ false true + false diff --git a/src/native/managed/cdacreader/tests/ContractDescriptorParserTests.cs b/src/native/managed/cdacreader/tests/ContractDescriptorParserTests.cs index eca740870727bb..6f93b1225670e4 100644 --- a/src/native/managed/cdacreader/tests/ContractDescriptorParserTests.cs +++ b/src/native/managed/cdacreader/tests/ContractDescriptorParserTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Text.Json; using System.Text.Unicode; using Xunit; @@ -12,6 +13,7 @@ public class ContractDescriptorParserTests [Fact] public void ParsesEmptyContract() { + Assert.False(JsonSerializer.IsReflectionEnabledByDefault); ReadOnlySpan json = "{}"u8; ContractDescriptorParser.ContractDescriptor descriptor = ContractDescriptorParser.ParseCompact(json); Assert.Null(descriptor.Version); diff --git a/src/native/managed/cdacreader/tests/Microsoft.Diagnostics.DataContractReader.Tests.csproj b/src/native/managed/cdacreader/tests/Microsoft.Diagnostics.DataContractReader.Tests.csproj index 22e8d256e01df1..c12c45e6f1fe84 100644 --- a/src/native/managed/cdacreader/tests/Microsoft.Diagnostics.DataContractReader.Tests.csproj +++ b/src/native/managed/cdacreader/tests/Microsoft.Diagnostics.DataContractReader.Tests.csproj @@ -2,6 +2,7 @@ true $(NetCoreAppToolCurrent) + false From 6444f51b67324c4d86c7aa8c48385c8902767479 Mon Sep 17 00:00:00 2001 From: yowl Date: Mon, 22 Apr 2024 17:02:57 -0500 Subject: [PATCH 051/248] set generic ctx type to void* for non-x86 path also - fixes LLVM/Wasm type mismatch (#101394) --- .../Compiler/CompilerTypeSystemContext.InterfaceThunks.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerTypeSystemContext.InterfaceThunks.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerTypeSystemContext.InterfaceThunks.cs index 92a5be3fed38c4..51bf6a6888e2ff 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerTypeSystemContext.InterfaceThunks.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerTypeSystemContext.InterfaceThunks.cs @@ -313,7 +313,7 @@ public override MethodSignature Signature } else { - parameters[0] = Context.GetWellKnownType(WellKnownType.IntPtr); + parameters[0] = Context.GetWellKnownType(WellKnownType.Void).MakePointerType(); for (int i = 0; i < _methodRepresented.Signature.Length; i++) parameters[i + 1] = _methodRepresented.Signature[i]; } From 7bb7e74d6b1f22e69654f038b06d7688a6ac45de Mon Sep 17 00:00:00 2001 From: Brennan Date: Mon, 22 Apr 2024 15:25:49 -0700 Subject: [PATCH 052/248] Fix queue count in rate limiters (#90810) (#97041) --- .../RateLimiting/ConcurrencyLimiter.cs | 40 ++++++++++++++++--- .../RateLimiting/FixedWindowRateLimiter.cs | 39 +++++++++++++++--- .../RateLimiting/SlidingWindowRateLimiter.cs | 39 +++++++++++++++--- .../RateLimiting/TokenBucketRateLimiter.cs | 40 ++++++++++++++++--- 4 files changed, 136 insertions(+), 22 deletions(-) diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs index 6b5a4014990ef0..7131b4fe1d7999 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs @@ -156,8 +156,17 @@ protected override ValueTask AcquireAsyncCore(int permitCount, C Debug.Assert(_queueCount >= 0); if (!oldestRequest.TrySetResult(FailedLease)) { - // Updating queue count is handled by the cancellation code - _queueCount += oldestRequest.Count; + if (!oldestRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + oldestRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += oldestRequest.Count; + } } else { @@ -277,10 +286,19 @@ private void Release(int releaseCount) // Check if request was canceled if (!nextPendingRequest.TrySetResult(lease)) { - // Queued item was canceled so add count back + // Queued item was canceled so add count back, permits weren't acquired _permitCount += nextPendingRequest.Count; - // Updating queue count is handled by the cancellation code - _queueCount += nextPendingRequest.Count; + if (!nextPendingRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + nextPendingRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += nextPendingRequest.Count; + } } else { @@ -399,6 +417,9 @@ private sealed class RequestRegistration : TaskCompletionSource private readonly CancellationToken _cancellationToken; private CancellationTokenRegistration _cancellationTokenRegistration; + // Update under the limiter lock and only if the queue count was updated by the calling code + public bool QueueCountModified { get; set; } + // this field is used only by the disposal mechanics and never shared between threads private RequestRegistration? _next; @@ -429,7 +450,14 @@ private static void Cancel(object? state) var limiter = (ConcurrencyLimiter)registration.Task.AsyncState!; lock (limiter.Lock) { - limiter._queueCount -= registration.Count; + // Queuing and replenishing code might modify the _queueCount, since there is no guarantee of when the cancellation + // code runs and we only want to update the _queueCount once, we set a bool (under a lock) so either method + // can update the count and not double count. + if (!registration.QueueCountModified) + { + limiter._queueCount -= registration.Count; + registration.QueueCountModified = true; + } } } } diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs index d09c7973b18aa7..daaed9cf5ce422 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs @@ -173,7 +173,17 @@ protected override ValueTask AcquireAsyncCore(int permitCount, C Debug.Assert(_queueCount >= 0); if (!oldestRequest.TrySetResult(FailedLease)) { - _queueCount += oldestRequest.Count; + if (!oldestRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + oldestRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += oldestRequest.Count; + } } else { @@ -330,10 +340,19 @@ private void ReplenishInternal(long nowTicks) if (!nextPendingRequest.TrySetResult(SuccessfulLease)) { - // Queued item was canceled so add count back + // Queued item was canceled so add count back, permits weren't acquired _permitCount += nextPendingRequest.Count; - // Updating queue count is handled by the cancellation code - _queueCount += nextPendingRequest.Count; + if (!nextPendingRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + nextPendingRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += nextPendingRequest.Count; + } } else { @@ -435,6 +454,9 @@ private sealed class RequestRegistration : TaskCompletionSource private readonly CancellationToken _cancellationToken; private CancellationTokenRegistration _cancellationTokenRegistration; + // Update under the limiter lock and only if the queue count was updated by the calling code + public bool QueueCountModified { get; set; } + // this field is used only by the disposal mechanics and never shared between threads private RequestRegistration? _next; @@ -465,7 +487,14 @@ private static void Cancel(object? state) var limiter = (FixedWindowRateLimiter)registration.Task.AsyncState!; lock (limiter.Lock) { - limiter._queueCount -= registration.Count; + // Queuing and replenishing code might modify the _queueCount, since there is no guarantee of when the cancellation + // code runs and we only want to update the _queueCount once, we set a bool (under a lock) so either method + // can update the count and not double count. + if (!registration.QueueCountModified) + { + limiter._queueCount -= registration.Count; + registration.QueueCountModified = true; + } } } } diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs index a179720ede33fa..23dbf98e0fcdea 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs @@ -185,7 +185,17 @@ protected override ValueTask AcquireAsyncCore(int permitCount, C Debug.Assert(_queueCount >= 0); if (!oldestRequest.TrySetResult(FailedLease)) { - _queueCount += oldestRequest.Count; + if (!oldestRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + oldestRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += oldestRequest.Count; + } } else { @@ -342,11 +352,20 @@ private void ReplenishInternal(long nowTicks) if (!nextPendingRequest.TrySetResult(SuccessfulLease)) { - // Queued item was canceled so add count back + // Queued item was canceled so add count back, permits weren't acquired _permitCount += nextPendingRequest.Count; _requestsPerSegment[_currentSegmentIndex] -= nextPendingRequest.Count; - // Updating queue count is handled by the cancellation code - _queueCount += nextPendingRequest.Count; + if (!nextPendingRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + nextPendingRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += nextPendingRequest.Count; + } } else { @@ -448,6 +467,9 @@ private sealed class RequestRegistration : TaskCompletionSource private readonly CancellationToken _cancellationToken; private CancellationTokenRegistration _cancellationTokenRegistration; + // Update under the limiter lock and only if the queue count was updated by the calling code + public bool QueueCountModified { get; set; } + // this field is used only by the disposal mechanics and never shared between threads private RequestRegistration? _next; @@ -478,7 +500,14 @@ private static void Cancel(object? state) var limiter = (SlidingWindowRateLimiter)registration.Task.AsyncState!; lock (limiter.Lock) { - limiter._queueCount -= registration.Count; + // Queuing and replenishing code might modify the _queueCount, since there is no guarantee of when the cancellation + // code runs and we only want to update the _queueCount once, we set a bool (under a lock) so either method + // can update the count and not double count. + if (!registration.QueueCountModified) + { + limiter._queueCount -= registration.Count; + registration.QueueCountModified = true; + } } } } diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs index 5ad7859792ff7f..67a3a55a29ad03 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs @@ -178,8 +178,17 @@ protected override ValueTask AcquireAsyncCore(int tokenCount, Ca Debug.Assert(_queueCount >= 0); if (!oldestRequest.TrySetResult(FailedLease)) { - // Updating queue count is handled by the cancellation code - _queueCount += oldestRequest.Count; + if (!oldestRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + oldestRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += oldestRequest.Count; + } } else { @@ -345,10 +354,19 @@ private void ReplenishInternal(long nowTicks) if (!nextPendingRequest.TrySetResult(SuccessfulLease)) { - // Queued item was canceled so add count back + // Queued item was canceled so add count back, permits weren't acquired _tokenCount += nextPendingRequest.Count; - // Updating queue count is handled by the cancellation code - _queueCount += nextPendingRequest.Count; + if (!nextPendingRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + nextPendingRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += nextPendingRequest.Count; + } } else { @@ -450,6 +468,9 @@ private sealed class RequestRegistration : TaskCompletionSource private readonly CancellationToken _cancellationToken; private CancellationTokenRegistration _cancellationTokenRegistration; + // Update under the limiter lock and only if the queue count was updated by the calling code + public bool QueueCountModified { get; set; } + // this field is used only by the disposal mechanics and never shared between threads private RequestRegistration? _next; @@ -480,7 +501,14 @@ private static void Cancel(object? state) var limiter = (TokenBucketRateLimiter)registration.Task.AsyncState!; lock (limiter.Lock) { - limiter._queueCount -= registration.Count; + // Queuing and replenishing code might modify the _queueCount, since there is no guarantee of when the cancellation + // code runs and we only want to update the _queueCount once, we set a bool (under a lock) so either method + // can update the count and not double count. + if (!registration.QueueCountModified) + { + limiter._queueCount -= registration.Count; + registration.QueueCountModified = true; + } } } } From 1c824d929b734db420babbc04f44a1491d8a7efb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Cant=C3=BA?= Date: Mon, 22 Apr 2024 21:58:44 -0500 Subject: [PATCH 053/248] Reapply params ReadOnlySpan overloads without params keyword (#101308) * Reapply "Add params ReadOnlySpan overloads (#100898)" (#101123) This reverts commit 3e569f5696ddf6c93e56eeaaf1703bb64e561f1b. * Comment-out params keyword * Remove /*params*/ from ref --- .../Common/tests/Tests/System/StringTests.cs | 201 +++++++++++++--- .../Collections/Immutable/ImmutableArray.cs | 2 +- .../Immutable/ImmutableArray_1.Builder.cs | 4 +- .../Collections/Immutable/ImmutableArray_1.cs | 4 +- .../Collections/Immutable/ImmutableHashSet.cs | 4 +- .../Collections/Immutable/ImmutableList.cs | 2 +- .../Collections/Immutable/ImmutableQueue.cs | 2 +- .../Immutable/ImmutableSortedSet.cs | 4 +- .../Collections/Immutable/ImmutableStack.cs | 2 +- .../tests/ImmutableHashSetTest.cs | 4 +- .../tests/ImmutableListTest.cs | 2 +- .../tests/ImmutableQueueTest.cs | 2 +- .../tests/ImmutableSortedSetTest.cs | 4 +- .../tests/ImmutableStackTest.cs | 2 +- .../src/System.Collections.NonGeneric.csproj | 1 + .../src/System.Collections.Specialized.csproj | 1 + ...stem.ComponentModel.EventBasedAsync.csproj | 1 + .../System.ComponentModel.Primitives.csproj | 1 + .../System.Console/ref/System.Console.cs | 2 + .../System.Console/src/System/Console.cs | 22 ++ .../System.Console/tests/ReadAndWrite.cs | 30 ++- ...em.Diagnostics.DiagnosticSourceActivity.cs | 8 +- .../src/System/Diagnostics/Metrics/Counter.cs | 2 +- .../System/Diagnostics/Metrics/Histogram.cs | 2 +- .../System/Diagnostics/Metrics/Measurement.cs | 2 +- .../src/System/Diagnostics/Metrics/TagList.cs | 2 +- .../Diagnostics/Metrics/UpDownCounter.cs | 2 +- .../tests/MetricsTests.cs | 113 +++++++-- .../tests/TagListTests.cs | 9 +- .../System.IO.FileSystem.AccessControl.csproj | 2 +- .../src/System.IO.IsolatedStorage.csproj | 1 + .../src/System.IO.Pipes.AccessControl.csproj | 1 + .../src/System.Linq.Expressions.csproj | 1 + .../src/System.Linq.Parallel.csproj | 1 + .../src/System.Linq.Queryable.csproj | 1 + .../src/System.Net.Http.Json.csproj | 2 + .../src/System.ObjectModel.csproj | 1 + .../CodeDom/Compiler/IndentedTextWriter.cs | 23 ++ .../Generic/CollectionExtensions.cs | 4 +- .../src/System/Delegate.cs | 28 ++- .../src/System/IO/Path.cs | 20 +- .../src/System/IO/StreamWriter.cs | 34 +++ .../IO/TextWriter.CreateBroadcasting.cs | 16 ++ .../src/System/IO/TextWriter.cs | 28 +++ .../src/System/MemoryExtensions.cs | 2 +- .../src/System/String.Manipulation.cs | 217 ++++++++++++++++-- .../src/System/Text/StringBuilder.cs | 155 ++++++++++--- .../Threading/CancellationTokenSource.cs | 12 +- .../src/System/Threading/Tasks/Task.cs | 152 +++++++++--- .../System.Reflection.DispatchProxy.csproj | 1 + .../src/System.Resources.Writer.csproj | 1 + ...em.Runtime.Serialization.Primitives.csproj | 1 + .../System.Runtime/ref/System.Runtime.cs | 34 +++ ...namic.context.method.regmethod.regclass.cs | 2 + ...amic.overloadResolution.Operators.basic.cs | 4 + .../System.IO.Tests/IndentedTextWriter.cs | 27 ++- .../Stream/Stream.NullTests.cs | 6 +- .../StreamWriter/StreamWriter.cs | 16 +- .../TextWriter/TextWriterTests.cs | 41 +++- .../System/IO/PathTests_Combine.cs | 5 + .../System/IO/PathTests_Join.cs | 6 + .../System/MulticastDelegateTests.cs | 30 ++- .../System/String.SplitTests.cs | 2 + .../System/Text/CompositeFormatTests.cs | 39 ++-- .../System/Text/StringBuilderTests.cs | 56 ++++- .../CancellationTokenTests.cs | 12 +- .../MethodCoverage.cs | 62 +++++ .../Task/TaskRtTests_Core.cs | 5 - .../src/System.Security.Claims.csproj | 1 + .../System.Text.Json/ref/System.Text.Json.cs | 3 + .../src/System/Text/Json/Nodes/JsonArray.cs | 44 +++- .../Metadata/JsonTypeInfoResolver.cs | 19 ++ .../JsonNode/JsonArrayTests.cs | 21 +- .../JsonTypeInfoResolverTests.cs | 72 +++--- .../src/System.Threading.Channels.csproj | 1 + .../System.Threading.Tasks.Dataflow.csproj | 1 + .../System.Threading.Tasks.Parallel.csproj | 1 + 77 files changed, 1388 insertions(+), 263 deletions(-) diff --git a/src/libraries/Common/tests/Tests/System/StringTests.cs b/src/libraries/Common/tests/Tests/System/StringTests.cs index f21dbe3baad6a6..8e465475a5200e 100644 --- a/src/libraries/Common/tests/Tests/System/StringTests.cs +++ b/src/libraries/Common/tests/Tests/System/StringTests.cs @@ -314,6 +314,7 @@ void Validate(string result) } Validate(string.Concat(values)); + Validate(string.Concat((ReadOnlySpan)values)); Validate(string.Concat((IEnumerable)values)); Validate(string.Concat((IEnumerable)values)); // Call the generic IEnumerable-based overload } @@ -418,6 +419,7 @@ public static void Concat_Objects(object[] values, string expected) Assert.Equal(expected, string.Concat(values[0], values[1], values[2], values[3])); } Assert.Equal(expected, string.Concat(values)); + Assert.Equal(expected, string.Concat((ReadOnlySpan)values)); Assert.Equal(expected, string.Concat((IEnumerable)values)); } @@ -2730,9 +2732,11 @@ public static IEnumerable Format_Valid_TestData() public static void Format_Valid(IFormatProvider provider, string format, object[] values, string expected) { Assert.Equal(expected, string.Format(provider, format, values)); + Assert.Equal(expected, string.Format(provider, format, (ReadOnlySpan)values)); if (provider is null) { Assert.Equal(expected, string.Format(format, values)); + Assert.Equal(expected, string.Format(format, (ReadOnlySpan)values)); } switch (values.Length) @@ -3967,6 +3971,7 @@ public static void Join_StringArray(string separator, string[] values, int start if (startIndex + count == values.Length && count != 0) { Assert.Equal(expected, string.Join(separator, values)); + Assert.Equal(expected, string.Join(separator, (ReadOnlySpan)values)); var iEnumerableStringOptimized = new List(values); Assert.Equal(expected, string.Join(separator, iEnumerableStringOptimized)); @@ -3984,6 +3989,44 @@ public static void Join_StringArray(string separator, string[] values, int start { var arrayOfObjects = (object[])values; Assert.Equal(expected, string.Join(separator, arrayOfObjects)); + Assert.Equal(expected, string.Join(separator, (ReadOnlySpan)arrayOfObjects)); + } + } + Assert.Equal(expected, string.Join(separator, values, startIndex, count)); + } + + [Theory] + [InlineData('$', new string[] { }, 0, 0, "")] + [InlineData('$', new string[] { null }, 0, 1, "")] + [InlineData('$', new string[] { null, "Bar", null }, 0, 3, "$Bar$")] + [InlineData('$', new string[] { "", "", "" }, 0, 3, "$$")] + [InlineData('$', new string[] { "Foo", "Bar", "Baz" }, 0, 3, "Foo$Bar$Baz")] + [InlineData('$', new string[] { "Foo", "Bar", "Baz" }, 3, 0, "")] + [InlineData('$', new string[] { "Foo", "Bar", "Baz" }, 1, 1, "Bar")] + public static void Join_CharSeparator_StringArray(char separator, string[] values, int startIndex, int count, string expected) + { + if (startIndex + count == values.Length && count != 0) + { + Assert.Equal(expected, string.Join(separator, values)); + Assert.Equal(expected, string.Join(separator, (ReadOnlySpan)values)); + + var iEnumerableStringOptimized = new List(values); + Assert.Equal(expected, string.Join(separator, iEnumerableStringOptimized)); + Assert.Equal(expected, string.Join(separator, iEnumerableStringOptimized)); // Call the generic IEnumerable-based overload + + var iEnumerableStringNotOptimized = new Queue(values); + Assert.Equal(expected, string.Join(separator, iEnumerableStringNotOptimized)); + Assert.Equal(expected, string.Join(separator, iEnumerableStringNotOptimized)); + + var iEnumerableObject = new List(values); + Assert.Equal(expected, string.Join(separator, iEnumerableObject)); + + // Bug/Documented behavior: Join(string, object[]) returns "" when the first item in the array is null + if (values.Length == 0 || values[0] != null) + { + var arrayOfObjects = (object[])values; + Assert.Equal(expected, string.Join(separator, arrayOfObjects)); + Assert.Equal(expected, string.Join(separator, (ReadOnlySpan)arrayOfObjects)); } } Assert.Equal(expected, string.Join(separator, values, startIndex, count)); @@ -4038,6 +4081,31 @@ public static void Join_ObjectArray(string separator, object[] values, string ex { Assert.Equal(expected, string.Join(separator, values)); Assert.Equal(expected, string.Join(separator, (IEnumerable)values)); + Assert.Equal(expected, string.Join(separator, (ReadOnlySpan)values)); + } + + public static IEnumerable Join_CharSeparator_ObjectArray_TestData() + { + yield return new object[] { '$', new object[] { }, "" }; + yield return new object[] { '$', new object[] { new ObjectWithNullToString() }, "" }; + yield return new object[] { '$', new object[] { "Foo" }, "Foo" }; + yield return new object[] { '$', new object[] { "Foo", "Bar", "Baz" }, "Foo$Bar$Baz" }; + yield return new object[] { '$', new object[] { "Foo", null, "Baz" }, "Foo$$Baz" }; + + // Test join when first value is null + yield return new object[] { '$', new object[] { null, "Bar", "Baz" }, "$Bar$Baz" }; + + // Join should ignore objects that have a null ToString() value + yield return new object[] { "|", new object[] { new ObjectWithNullToString(), "Foo", new ObjectWithNullToString(), "Bar", new ObjectWithNullToString() }, "|Foo||Bar|" }; + } + + [Theory] + [MemberData(nameof(Join_CharSeparator_ObjectArray_TestData))] + public static void Join_CharSeparator_ObjectArray(char separator, object[] values, string expected) + { + Assert.Equal(expected, string.Join(separator, values)); + Assert.Equal(expected, string.Join(separator, (IEnumerable)values)); + Assert.Equal(expected, string.Join(separator, (ReadOnlySpan)values)); } [Fact] @@ -6098,6 +6166,7 @@ public static void Trim(string s, char[] trimChars, string expected) } Assert.Equal(expected, s.Trim(trimChars)); + Assert.Equal(expected, s.Trim((ReadOnlySpan)trimChars)); Assert.Equal(expected, s.AsSpan().Trim(trimChars).ToString()); } @@ -6128,6 +6197,7 @@ public static void TrimEnd(string s, char[] trimChars, string expected) } Assert.Equal(expected, s.TrimEnd(trimChars)); + Assert.Equal(expected, s.TrimEnd((ReadOnlySpan)trimChars)); Assert.Equal(expected, s.AsSpan().TrimEnd(trimChars).ToString()); } @@ -6158,6 +6228,7 @@ public static void TrimStart(string s, char[] trimChars, string expected) } Assert.Equal(expected, s.TrimStart(trimChars)); + Assert.Equal(expected, s.TrimStart((ReadOnlySpan)trimChars)); Assert.Equal(expected, s.AsSpan().TrimStart(trimChars).ToString()); } @@ -6388,18 +6459,27 @@ public static void ZeroLengthTrimCharacters() Assert.True(s1.SequenceEqual(s1.Trim(trimCharsString))); Assert.True(s1.SequenceEqual(s1.TrimStart(trimCharsString))); Assert.True(s1.SequenceEqual(s1.TrimEnd(trimCharsString))); + Assert.True(s1.SequenceEqual(s1.Trim((ReadOnlySpan)trimCharsString))); + Assert.True(s1.SequenceEqual(s1.TrimStart((ReadOnlySpan)trimCharsString))); + Assert.True(s1.SequenceEqual(s1.TrimEnd((ReadOnlySpan)trimCharsString))); char[] chars = { 'a', 'b', 'c', 'd', 'e' }; trimCharsString = chars; Assert.True(s1.SequenceEqual(s1.Trim(trimCharsString))); Assert.True(s1.SequenceEqual(s1.TrimStart(trimCharsString))); Assert.True(s1.SequenceEqual(s1.TrimEnd(trimCharsString))); + Assert.True(s1.SequenceEqual(s1.Trim((ReadOnlySpan)trimCharsString))); + Assert.True(s1.SequenceEqual(s1.TrimStart((ReadOnlySpan)trimCharsString))); + Assert.True(s1.SequenceEqual(s1.TrimEnd((ReadOnlySpan)trimCharsString))); string emptyString = string.Empty; char[] trimCharsArrayFromString = "abcde".ToCharArray(); Assert.True(emptyString.SequenceEqual(emptyString.Trim(trimCharsArrayFromString))); Assert.True(emptyString.SequenceEqual(emptyString.TrimStart(trimCharsArrayFromString))); Assert.True(emptyString.SequenceEqual(emptyString.TrimEnd(trimCharsArrayFromString))); + Assert.True(emptyString.SequenceEqual(emptyString.Trim((ReadOnlySpan)trimCharsArrayFromString))); + Assert.True(emptyString.SequenceEqual(emptyString.TrimStart((ReadOnlySpan)trimCharsArrayFromString))); + Assert.True(emptyString.SequenceEqual(emptyString.TrimEnd((ReadOnlySpan)trimCharsArrayFromString))); ReadOnlySpan span = s1.AsSpan(); ReadOnlySpan trimChars = trimCharsString.AsSpan(); @@ -6435,6 +6515,9 @@ public static void NoTrimCharacters() Assert.True(s1.SequenceEqual(s1.Trim(trimCharsString))); Assert.True(s1.SequenceEqual(s1.TrimStart(trimCharsString))); Assert.True(s1.SequenceEqual(s1.TrimEnd(trimCharsString))); + Assert.True(s1.SequenceEqual(s1.Trim((ReadOnlySpan)trimCharsString))); + Assert.True(s1.SequenceEqual(s1.TrimStart((ReadOnlySpan)trimCharsString))); + Assert.True(s1.SequenceEqual(s1.TrimEnd((ReadOnlySpan)trimCharsString))); ReadOnlySpan span = s1.AsSpan(); Assert.True(span.SequenceEqual(span.Trim(trimChars))); @@ -6454,6 +6537,9 @@ public static void NoTrimCharacters() Assert.True(s2.SequenceEqual(s2.Trim(chars))); Assert.True(s2.SequenceEqual(s2.TrimStart(chars))); Assert.True(s2.SequenceEqual(s2.TrimEnd(chars))); + Assert.True(s2.SequenceEqual(s2.Trim((ReadOnlySpan)chars))); + Assert.True(s2.SequenceEqual(s2.TrimStart((ReadOnlySpan)chars))); + Assert.True(s2.SequenceEqual(s2.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan span = s2.AsSpan(); Assert.True(span.SequenceEqual(span.Trim(chars))); @@ -6466,6 +6552,9 @@ public static void NoTrimCharacters() Assert.True(s3.SequenceEqual(s3.Trim(trimCharsFromString))); Assert.True(s3.SequenceEqual(s3.TrimStart(trimCharsFromString))); Assert.True(s3.SequenceEqual(s3.TrimEnd(trimCharsFromString))); + Assert.True(s3.SequenceEqual(s3.Trim((ReadOnlySpan)trimCharsFromString))); + Assert.True(s3.SequenceEqual(s3.TrimStart((ReadOnlySpan)trimCharsFromString))); + Assert.True(s3.SequenceEqual(s3.TrimEnd((ReadOnlySpan)trimCharsFromString))); ReadOnlySpan stringSpan = s3.AsSpan(); ReadOnlySpan trimCharsFromStringSpan = trimCharsFromString.AsSpan(); @@ -6490,6 +6579,9 @@ public static void OnlyTrimCharacters() Assert.True(string.Empty.SequenceEqual(s1.Trim(chars)), "G: " + length); Assert.True(string.Empty.SequenceEqual(s1.TrimStart(chars)), "H: " + length); Assert.True(string.Empty.SequenceEqual(s1.TrimEnd(chars)), "I: " + length); + Assert.True(string.Empty.SequenceEqual(s1.Trim((ReadOnlySpan)chars)), "G: " + length); + Assert.True(string.Empty.SequenceEqual(s1.TrimStart((ReadOnlySpan)chars)), "H: " + length); + Assert.True(string.Empty.SequenceEqual(s1.TrimEnd((ReadOnlySpan)chars)), "I: " + length); ReadOnlySpan span = s1.AsSpan(); Assert.True(ReadOnlySpan.Empty.SequenceEqual(span.Trim(chars)), "G: " + length); @@ -6502,6 +6594,9 @@ public static void OnlyTrimCharacters() Assert.True(string.Empty.SequenceEqual(s2.Trim(trimCharsString)), "J"); Assert.True(string.Empty.SequenceEqual(s2.TrimStart(trimCharsString)), "K"); Assert.True(string.Empty.SequenceEqual(s2.TrimEnd(trimCharsString)), "L"); + Assert.True(string.Empty.SequenceEqual(s2.Trim((ReadOnlySpan)trimCharsString)), "J"); + Assert.True(string.Empty.SequenceEqual(s2.TrimStart((ReadOnlySpan)trimCharsString)), "K"); + Assert.True(string.Empty.SequenceEqual(s2.TrimEnd((ReadOnlySpan)trimCharsString)), "L"); ReadOnlySpan stringSpan = s2.AsSpan(); ReadOnlySpan trimChars = trimCharsString.AsSpan(); @@ -6526,6 +6621,9 @@ public static void TrimCharactersAtStart() Assert.True(s1.Substring(1).SequenceEqual(s1.Trim(chars)), "A: " + length); Assert.True(s1.Substring(1).SequenceEqual(s1.TrimStart(chars)), "B: " + length); Assert.True(s1.SequenceEqual(s1.TrimEnd(chars)), "C: " + length); + Assert.True(s1.Substring(1).SequenceEqual(s1.Trim((ReadOnlySpan)chars)), "A: " + length); + Assert.True(s1.Substring(1).SequenceEqual(s1.TrimStart((ReadOnlySpan)chars)), "B: " + length); + Assert.True(s1.SequenceEqual(s1.TrimEnd((ReadOnlySpan)chars)), "C: " + length); ReadOnlySpan span = s1.AsSpan(); Assert.True(span.Slice(1).SequenceEqual(span.Trim(chars)), "A: " + length); @@ -6538,6 +6636,9 @@ public static void TrimCharactersAtStart() Assert.True(s2.Substring(3).SequenceEqual(s2.Trim(trimCharsString)), "D"); Assert.True(s2.Substring(3).SequenceEqual(s2.TrimStart(trimCharsString)), "E"); Assert.True(s2.SequenceEqual(s2.TrimEnd(trimCharsString)), "F"); + Assert.True(s2.Substring(3).SequenceEqual(s2.Trim((ReadOnlySpan)trimCharsString)), "D"); + Assert.True(s2.Substring(3).SequenceEqual(s2.TrimStart((ReadOnlySpan)trimCharsString)), "E"); + Assert.True(s2.SequenceEqual(s2.TrimEnd((ReadOnlySpan)trimCharsString)), "F"); ReadOnlySpan stringSpan = s2.AsSpan(); ReadOnlySpan trimChars = trimCharsString.AsSpan(); @@ -6563,6 +6664,9 @@ public static void TrimCharactersAtEnd() Assert.True(s1.Substring(0, length - 1).SequenceEqual(s1.Trim(chars))); Assert.True(s1.SequenceEqual(s1.TrimStart(chars))); Assert.True(s1.Substring(0, length - 1).SequenceEqual(s1.TrimEnd(chars))); + Assert.True(s1.Substring(0, length - 1).SequenceEqual(s1.Trim((ReadOnlySpan)chars))); + Assert.True(s1.SequenceEqual(s1.TrimStart((ReadOnlySpan)chars))); + Assert.True(s1.Substring(0, length - 1).SequenceEqual(s1.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan span = new ReadOnlySpan(a); Assert.True(span.Slice(0, length - 1).SequenceEqual(span.Trim(chars))); @@ -6600,6 +6704,9 @@ public static void TrimCharactersAtStartAndEnd() Assert.True(s1.Substring(1, length - 2).SequenceEqual(s1.Trim(chars))); Assert.True(s1.Substring(1).SequenceEqual(s1.TrimStart(chars))); Assert.True(s1.Substring(0, length - 1).SequenceEqual(s1.TrimEnd(chars))); + Assert.True(s1.Substring(1, length - 2).SequenceEqual(s1.Trim((ReadOnlySpan)chars))); + Assert.True(s1.Substring(1).SequenceEqual(s1.TrimStart((ReadOnlySpan)chars))); + Assert.True(s1.Substring(0, length - 1).SequenceEqual(s1.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan span = s1.AsSpan(); Assert.True(span.Slice(1, length - 2).SequenceEqual(span.Trim(chars))); @@ -6608,13 +6715,15 @@ public static void TrimCharactersAtStartAndEnd() } string s2 = "ccedafffffbdaa"; - char[] trimCharsString = "abcde".ToCharArray(); - Assert.True(s2.Substring(5, 5).SequenceEqual(s2.Trim(trimCharsString))); - Assert.True(s2.Substring(5).SequenceEqual(s2.TrimStart(trimCharsString))); - Assert.True(s2.Substring(0, 10).SequenceEqual(s2.TrimEnd(trimCharsString))); + Assert.True(s2.Substring(5, 5).SequenceEqual(s2.Trim(chars))); + Assert.True(s2.Substring(5).SequenceEqual(s2.TrimStart(chars))); + Assert.True(s2.Substring(0, 10).SequenceEqual(s2.TrimEnd(chars))); + Assert.True(s2.Substring(5, 5).SequenceEqual(s2.Trim((ReadOnlySpan)chars))); + Assert.True(s2.Substring(5).SequenceEqual(s2.TrimStart((ReadOnlySpan)chars))); + Assert.True(s2.Substring(0, 10).SequenceEqual(s2.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan stringSpan = s2.AsSpan(); - ReadOnlySpan trimChars = trimCharsString.AsSpan(); + ReadOnlySpan trimChars = chars.AsSpan(); Assert.True(stringSpan.Slice(5, 5).SequenceEqual(stringSpan.Trim(trimChars))); Assert.True(stringSpan.Slice(5).SequenceEqual(stringSpan.TrimStart(trimChars))); Assert.True(stringSpan.Slice(0, 10).SequenceEqual(stringSpan.TrimEnd(trimChars))); @@ -6637,6 +6746,9 @@ public static void TrimCharactersInMiddle() Assert.True(s1.SequenceEqual(s1.Trim(chars))); Assert.True(s1.SequenceEqual(s1.TrimStart(chars))); Assert.True(s1.SequenceEqual(s1.TrimEnd(chars))); + Assert.True(s1.SequenceEqual(s1.Trim((ReadOnlySpan)chars))); + Assert.True(s1.SequenceEqual(s1.TrimStart((ReadOnlySpan)chars))); + Assert.True(s1.SequenceEqual(s1.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan span = s1.AsSpan(); Assert.True(span.SequenceEqual(span.Trim(chars))); @@ -6645,13 +6757,15 @@ public static void TrimCharactersInMiddle() } string s2 = "fabbacddeeddef"; - char[] trimCharsString = "abcde".ToCharArray(); - Assert.True(s2.SequenceEqual(s2.Trim(trimCharsString))); - Assert.True(s2.SequenceEqual(s2.TrimStart(trimCharsString))); - Assert.True(s2.SequenceEqual(s2.TrimEnd(trimCharsString))); + Assert.True(s2.SequenceEqual(s2.Trim(chars))); + Assert.True(s2.SequenceEqual(s2.TrimStart(chars))); + Assert.True(s2.SequenceEqual(s2.TrimEnd(chars))); + Assert.True(s2.SequenceEqual(s2.Trim((ReadOnlySpan)chars))); + Assert.True(s2.SequenceEqual(s2.TrimStart((ReadOnlySpan)chars))); + Assert.True(s2.SequenceEqual(s2.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan stringSpan = s2.AsSpan(); - ReadOnlySpan trimChars = trimCharsString.AsSpan(); + ReadOnlySpan trimChars = chars.AsSpan(); Assert.True(stringSpan.SequenceEqual(stringSpan.Trim(trimChars))); Assert.True(stringSpan.SequenceEqual(stringSpan.TrimStart(trimChars))); Assert.True(stringSpan.SequenceEqual(stringSpan.TrimEnd(trimChars))); @@ -6684,6 +6798,19 @@ public static void TrimCharactersMultipleTimes() Assert.True(trimStartResultString.SequenceEqual(trimStartResultString.TrimStart(chars))); Assert.True(trimEndResultString.SequenceEqual(trimEndResultString.TrimEnd(chars))); + s1 = new string(a); + trimResultString = s1.Trim((ReadOnlySpan)chars); + trimStartResultString = s1.TrimStart((ReadOnlySpan)chars); + trimEndResultString = s1.TrimEnd((ReadOnlySpan)chars); + Assert.True(s1.Substring(1, length - 2).SequenceEqual(trimResultString)); + Assert.True(s1.Substring(1).SequenceEqual(trimStartResultString)); + Assert.True(s1.Substring(0, length - 1).SequenceEqual(trimEndResultString)); + + // 2nd attempt should do nothing + Assert.True(trimResultString.SequenceEqual(trimResultString.Trim((ReadOnlySpan)chars))); + Assert.True(trimStartResultString.SequenceEqual(trimStartResultString.TrimStart((ReadOnlySpan)chars))); + Assert.True(trimEndResultString.SequenceEqual(trimEndResultString.TrimEnd((ReadOnlySpan)chars))); + ReadOnlySpan span = s1.AsSpan(); ReadOnlySpan trimResult = span.Trim(chars); ReadOnlySpan trimStartResult = span.TrimStart(chars); @@ -6699,21 +6826,33 @@ public static void TrimCharactersMultipleTimes() } string s2 = "ccedafffffbdaa"; - char[] trimCharsString = "abcde".ToCharArray(); - string trimStringResultString = s2.Trim(trimCharsString); - string trimStartStringResultString = s2.TrimStart(trimCharsString); - string trimEndStringResultString = s2.TrimEnd(trimCharsString); + string trimStringResultString = s2.Trim(chars); + string trimStartStringResultString = s2.TrimStart(chars); + string trimEndStringResultString = s2.TrimEnd(chars); + Assert.True(s2.Substring(5, 5).SequenceEqual(trimStringResultString)); + Assert.True(s2.Substring(5).SequenceEqual(trimStartStringResultString)); + Assert.True(s2.Substring(0, 10).SequenceEqual(trimEndStringResultString)); + + // 2nd attempt should do nothing + Assert.True(trimStringResultString.SequenceEqual(trimStringResultString.Trim(chars))); + Assert.True(trimStartStringResultString.SequenceEqual(trimStartStringResultString.TrimStart(chars))); + Assert.True(trimEndStringResultString.SequenceEqual(trimEndStringResultString.TrimEnd(chars))); + + s2 = "ccedafffffbdaa"; + trimStringResultString = s2.Trim((ReadOnlySpan)chars); + trimStartStringResultString = s2.TrimStart((ReadOnlySpan)chars); + trimEndStringResultString = s2.TrimEnd((ReadOnlySpan)chars); Assert.True(s2.Substring(5, 5).SequenceEqual(trimStringResultString)); Assert.True(s2.Substring(5).SequenceEqual(trimStartStringResultString)); Assert.True(s2.Substring(0, 10).SequenceEqual(trimEndStringResultString)); // 2nd attempt should do nothing - Assert.True(trimStringResultString.SequenceEqual(trimStringResultString.Trim(trimCharsString))); - Assert.True(trimStartStringResultString.SequenceEqual(trimStartStringResultString.TrimStart(trimCharsString))); - Assert.True(trimEndStringResultString.SequenceEqual(trimEndStringResultString.TrimEnd(trimCharsString))); + Assert.True(trimStringResultString.SequenceEqual(trimStringResultString.Trim((ReadOnlySpan)chars))); + Assert.True(trimStartStringResultString.SequenceEqual(trimStartStringResultString.TrimStart((ReadOnlySpan)chars))); + Assert.True(trimEndStringResultString.SequenceEqual(trimEndStringResultString.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan stringSpan = s2.AsSpan(); - ReadOnlySpan trimChars = trimCharsString.AsSpan(); + ReadOnlySpan trimChars = chars.AsSpan(); ReadOnlySpan trimStringResult = stringSpan.Trim(trimChars); ReadOnlySpan trimStartStringResult = stringSpan.TrimStart(trimChars); @@ -6739,27 +6878,31 @@ public static void MakeSureNoTrimCharactersChecksGoOutOfRange() first[length - 1] = 'f'; string s1 = new string(first, 1, length - 2); Assert.Equal(s1.ToArray().Length, s1.Trim(chars).ToArray().Length); - Assert.True(s1.SequenceEqual(s1.Trim(chars)), "A : " + s1.Length); - Assert.True(s1.SequenceEqual(s1.TrimStart(chars)), "B :" + s1.Length); - Assert.True(s1.SequenceEqual(s1.TrimEnd(chars))); + Assert.True(s1.SequenceEqual(s1.Trim(chars)), "A: " + s1.Length); + Assert.True(s1.SequenceEqual(s1.TrimStart(chars)), "B: " + s1.Length); + Assert.True(s1.SequenceEqual(s1.TrimEnd(chars)), "C: " + s1.Length); ReadOnlySpan span = s1.AsSpan(); Assert.Equal(span.ToArray().Length, span.Trim(chars).ToArray().Length); - Assert.True(span.SequenceEqual(span.Trim(chars)), "A : " + span.Length); - Assert.True(span.SequenceEqual(span.TrimStart(chars)), "B :" + span.Length); - Assert.True(span.SequenceEqual(span.TrimEnd(chars))); + Assert.True(span.SequenceEqual(span.Trim(chars)), "A: " + span.Length); + Assert.True(span.SequenceEqual(span.TrimStart(chars)), "B: " + span.Length); + Assert.True(span.SequenceEqual(span.TrimEnd(chars)), "C: " + s1.Length); } string testString = "afghijklmnopqrstfe"; string s2 = testString.Substring(1, testString.Length - 2); - char[] trimCharsString = "abcde".ToCharArray(); - Assert.True(s2.SequenceEqual(s2.Trim(trimCharsString))); - Assert.True(s2.SequenceEqual(s2.TrimStart(trimCharsString))); - Assert.True(s2.SequenceEqual(s2.TrimEnd(trimCharsString))); + Assert.True(s2.SequenceEqual(s2.Trim(chars))); + Assert.True(s2.SequenceEqual(s2.TrimStart(chars))); + Assert.True(s2.SequenceEqual(s2.TrimEnd(chars))); + + s2 = testString.Substring(1, testString.Length - 2); + Assert.True(s2.SequenceEqual(s2.Trim((ReadOnlySpan)chars))); + Assert.True(s2.SequenceEqual(s2.TrimStart((ReadOnlySpan)chars))); + Assert.True(s2.SequenceEqual(s2.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan stringSpan = s2.AsSpan(); - ReadOnlySpan trimChars = trimCharsString.AsSpan(); + ReadOnlySpan trimChars = chars.AsSpan(); Assert.True(stringSpan.SequenceEqual(stringSpan.Trim(trimChars))); Assert.True(stringSpan.SequenceEqual(stringSpan.TrimStart(trimChars))); Assert.True(stringSpan.SequenceEqual(stringSpan.TrimEnd(trimChars))); diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray.cs index f2743d3f16f8c9..aafe4316eb7503 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray.cs @@ -87,7 +87,7 @@ public static ImmutableArray Create(T item1, T item2, T item3, T item4) /// The type of element stored in the array. /// The elements to store in the array. /// An immutable array containing the specified items. - public static ImmutableArray Create(ReadOnlySpan items) + public static ImmutableArray Create(/*params*/ ReadOnlySpan items) { if (items.IsEmpty) { diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs index 8af78d72a063e0..060492a40bd06e 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs @@ -430,7 +430,7 @@ public void AddRange(ImmutableArray items, int length) /// Adds the specified items to the end of the array. /// /// The items to add at the end of the array. - public void AddRange(ReadOnlySpan items) + public void AddRange(/*params*/ ReadOnlySpan items) { int offset = this.Count; this.Count += items.Length; @@ -443,7 +443,7 @@ public void AddRange(ReadOnlySpan items) /// /// The type that derives from the type of item already in the array. /// The items to add at the end of the array. - public void AddRange(ReadOnlySpan items) where TDerived : T + public void AddRange(/*params*/ ReadOnlySpan items) where TDerived : T { int offset = this.Count; this.Count += items.Length; diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.cs index 2d203d015b828a..04e05477e0ff7c 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.cs @@ -880,7 +880,7 @@ public IEnumerable OfType() /// /// The values to add. /// A new list with the elements added. - public ImmutableArray AddRange(ReadOnlySpan items) + public ImmutableArray AddRange(/*params*/ ReadOnlySpan items) { ImmutableArray self = this; return self.InsertRange(self.Length, items); @@ -949,7 +949,7 @@ public ImmutableArray InsertRange(int index, T[] items) /// The index at which to insert the value. /// The elements to insert. /// The new immutable collection. - public ImmutableArray InsertRange(int index, ReadOnlySpan items) + public ImmutableArray InsertRange(int index, /*params*/ ReadOnlySpan items) { ImmutableArray self = this; self.ThrowNullRefIfNotInitialized(); diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet.cs index 9630bb33b5c0fe..13742785d7d81e 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet.cs @@ -98,7 +98,7 @@ public static ImmutableHashSet Create(params T[] items) /// The type of items stored by the collection. /// The items to prepopulate. /// The new immutable collection. - public static ImmutableHashSet Create(ReadOnlySpan items) + public static ImmutableHashSet Create(/*params*/ ReadOnlySpan items) { return ImmutableHashSet.Empty.Union(items); } @@ -124,7 +124,7 @@ public static ImmutableHashSet Create(IEqualityComparer? equalityCompar /// The equality comparer. /// The items to prepopulate. /// The new immutable collection. - public static ImmutableHashSet Create(IEqualityComparer? equalityComparer, ReadOnlySpan items) + public static ImmutableHashSet Create(IEqualityComparer? equalityComparer, /*params*/ ReadOnlySpan items) { return ImmutableHashSet.Empty.WithComparer(equalityComparer).Union(items); } diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableList.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableList.cs index f3004e3fd0199f..977686b880cc8c 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableList.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableList.cs @@ -52,7 +52,7 @@ public static ImmutableList Create(params T[] items) /// The type of items stored by the collection. /// A span that contains the items to prepopulate the list with. /// A new immutable list that contains the specified items. - public static ImmutableList Create(ReadOnlySpan items) => ImmutableList.Empty.AddRange(items); + public static ImmutableList Create(/*params*/ ReadOnlySpan items) => ImmutableList.Empty.AddRange(items); /// /// Creates a new immutable list builder. diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableQueue.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableQueue.cs index 122bae100534f0..d2f5d142bbf869 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableQueue.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableQueue.cs @@ -83,7 +83,7 @@ public static ImmutableQueue Create(params T[] items) /// The type of items in the immutable queue. /// A span that contains the items to prepopulate the queue with. /// A new immutable queue that contains the specified items. - public static ImmutableQueue Create(ReadOnlySpan items) + public static ImmutableQueue Create(/*params*/ ReadOnlySpan items) { if (items.IsEmpty) { diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet.cs index 567997ed0472aa..ae5493ff083213 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet.cs @@ -97,7 +97,7 @@ public static ImmutableSortedSet Create(params T[] items) /// The type of items in the immutable set. /// A span that contains the items to prepopulate the set with. /// A new immutable set that contains the specified items. - public static ImmutableSortedSet Create(ReadOnlySpan items) + public static ImmutableSortedSet Create(/*params*/ ReadOnlySpan items) { return ImmutableSortedSet.Empty.Union(items); } @@ -123,7 +123,7 @@ public static ImmutableSortedSet Create(IComparer? comparer, params T[] /// The comparer. /// The items to prepopulate. /// The new immutable collection. - public static ImmutableSortedSet Create(IComparer? comparer, ReadOnlySpan items) + public static ImmutableSortedSet Create(IComparer? comparer, /*params*/ ReadOnlySpan items) { return ImmutableSortedSet.Empty.WithComparer(comparer).Union(items); } diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableStack.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableStack.cs index 4e11bb76888077..f964f55c79908c 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableStack.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableStack.cs @@ -70,7 +70,7 @@ public static ImmutableStack Create(params T[] items) /// The type of items in the immutable stack. /// A span that contains the items to prepopulate the stack with. /// A new immutable stack that contains the specified items. - public static ImmutableStack Create(ReadOnlySpan items) + public static ImmutableStack Create(/*params*/ ReadOnlySpan items) { ImmutableStack stack = ImmutableStack.Empty; foreach (T item in items) diff --git a/src/libraries/System.Collections.Immutable/tests/ImmutableHashSetTest.cs b/src/libraries/System.Collections.Immutable/tests/ImmutableHashSetTest.cs index 0aab9405d55930..d6a01aee099a26 100644 --- a/src/libraries/System.Collections.Immutable/tests/ImmutableHashSetTest.cs +++ b/src/libraries/System.Collections.Immutable/tests/ImmutableHashSetTest.cs @@ -118,7 +118,7 @@ public void Create() Assert.Equal(1, set.Count); Assert.Same(comparer, set.KeyComparer); - set = ImmutableHashSet.Create("a", "b"); + set = ImmutableHashSet.Create(new[] { "a", "b" }); Assert.Equal(2, set.Count); Assert.Same(EqualityComparer.Default, set.KeyComparer); @@ -126,7 +126,7 @@ public void Create() Assert.Equal(2, set.Count); Assert.Same(EqualityComparer.Default, set.KeyComparer); - set = ImmutableHashSet.Create(comparer, "a", "b"); + set = ImmutableHashSet.Create(comparer, new[] { "a", "b" }); Assert.Equal(2, set.Count); Assert.Same(comparer, set.KeyComparer); diff --git a/src/libraries/System.Collections.Immutable/tests/ImmutableListTest.cs b/src/libraries/System.Collections.Immutable/tests/ImmutableListTest.cs index ec569e77699464..7223c1305e9c62 100644 --- a/src/libraries/System.Collections.Immutable/tests/ImmutableListTest.cs +++ b/src/libraries/System.Collections.Immutable/tests/ImmutableListTest.cs @@ -584,7 +584,7 @@ public void Create() list = ImmutableList.Create("a"); Assert.Equal(1, list.Count); - list = ImmutableList.Create("a", "b"); + list = ImmutableList.Create(new[] { "a", "b" }); Assert.Equal(2, list.Count); list = ImmutableList.Create((ReadOnlySpan)new[] { "a", "b" }); diff --git a/src/libraries/System.Collections.Immutable/tests/ImmutableQueueTest.cs b/src/libraries/System.Collections.Immutable/tests/ImmutableQueueTest.cs index c03621929a5990..4aef1b5577a345 100644 --- a/src/libraries/System.Collections.Immutable/tests/ImmutableQueueTest.cs +++ b/src/libraries/System.Collections.Immutable/tests/ImmutableQueueTest.cs @@ -213,7 +213,7 @@ public void Create() Assert.False(queue.IsEmpty); Assert.Equal(new[] { 1 }, queue); - queue = ImmutableQueue.Create(1, 2); + queue = ImmutableQueue.Create(new int[] { 1, 2 }); Assert.False(queue.IsEmpty); Assert.Equal(new[] { 1, 2 }, queue); diff --git a/src/libraries/System.Collections.Immutable/tests/ImmutableSortedSetTest.cs b/src/libraries/System.Collections.Immutable/tests/ImmutableSortedSetTest.cs index eecff21ffb34b7..f16d59dd63ae1b 100644 --- a/src/libraries/System.Collections.Immutable/tests/ImmutableSortedSetTest.cs +++ b/src/libraries/System.Collections.Immutable/tests/ImmutableSortedSetTest.cs @@ -289,7 +289,7 @@ public void Create() Assert.Equal(1, set.Count); Assert.Same(comparer, set.KeyComparer); - set = ImmutableSortedSet.Create("a", "b"); + set = ImmutableSortedSet.Create(new [] { "a", "b" }); Assert.Equal(2, set.Count); Assert.Same(Comparer.Default, set.KeyComparer); @@ -297,7 +297,7 @@ public void Create() Assert.Equal(2, set.Count); Assert.Same(Comparer.Default, set.KeyComparer); - set = ImmutableSortedSet.Create(comparer, "a", "b"); + set = ImmutableSortedSet.Create(comparer, new[] { "a", "b" }); Assert.Equal(2, set.Count); Assert.Same(comparer, set.KeyComparer); diff --git a/src/libraries/System.Collections.Immutable/tests/ImmutableStackTest.cs b/src/libraries/System.Collections.Immutable/tests/ImmutableStackTest.cs index 26336209e12047..4abd031ed43b2d 100644 --- a/src/libraries/System.Collections.Immutable/tests/ImmutableStackTest.cs +++ b/src/libraries/System.Collections.Immutable/tests/ImmutableStackTest.cs @@ -241,7 +241,7 @@ public void Create() Assert.False(stack.IsEmpty); Assert.Equal(new[] { 1 }, stack); - stack = ImmutableStack.Create(1, 2); + stack = ImmutableStack.Create(new[] { 1, 2 }); Assert.False(stack.IsEmpty); Assert.Equal(new[] { 2, 1 }, stack); diff --git a/src/libraries/System.Collections.NonGeneric/src/System.Collections.NonGeneric.csproj b/src/libraries/System.Collections.NonGeneric/src/System.Collections.NonGeneric.csproj index 770e5fc0fc1816..1bc456cd13ba3a 100644 --- a/src/libraries/System.Collections.NonGeneric/src/System.Collections.NonGeneric.csproj +++ b/src/libraries/System.Collections.NonGeneric/src/System.Collections.NonGeneric.csproj @@ -21,6 +21,7 @@ + diff --git a/src/libraries/System.Collections.Specialized/src/System.Collections.Specialized.csproj b/src/libraries/System.Collections.Specialized/src/System.Collections.Specialized.csproj index 21e6fc760efae5..4301d885411c68 100644 --- a/src/libraries/System.Collections.Specialized/src/System.Collections.Specialized.csproj +++ b/src/libraries/System.Collections.Specialized/src/System.Collections.Specialized.csproj @@ -23,6 +23,7 @@ + diff --git a/src/libraries/System.ComponentModel.EventBasedAsync/src/System.ComponentModel.EventBasedAsync.csproj b/src/libraries/System.ComponentModel.EventBasedAsync/src/System.ComponentModel.EventBasedAsync.csproj index 0d413f6fd370ee..a5d9913733b441 100644 --- a/src/libraries/System.ComponentModel.EventBasedAsync/src/System.ComponentModel.EventBasedAsync.csproj +++ b/src/libraries/System.ComponentModel.EventBasedAsync/src/System.ComponentModel.EventBasedAsync.csproj @@ -18,6 +18,7 @@ + diff --git a/src/libraries/System.ComponentModel.Primitives/src/System.ComponentModel.Primitives.csproj b/src/libraries/System.ComponentModel.Primitives/src/System.ComponentModel.Primitives.csproj index 5fcff901309503..2938d1e641264e 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System.ComponentModel.Primitives.csproj +++ b/src/libraries/System.ComponentModel.Primitives/src/System.ComponentModel.Primitives.csproj @@ -47,6 +47,7 @@ + diff --git a/src/libraries/System.Console/ref/System.Console.cs b/src/libraries/System.Console/ref/System.Console.cs index 273290de2a89f2..7c5ca19cd01ad6 100644 --- a/src/libraries/System.Console/ref/System.Console.cs +++ b/src/libraries/System.Console/ref/System.Console.cs @@ -175,6 +175,7 @@ public static void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute( public static void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public static void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { } public static void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[]? arg) { } + public static void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, System.ReadOnlySpan arg) { } [System.CLSCompliantAttribute(false)] public static void Write(uint value) { } [System.CLSCompliantAttribute(false)] @@ -195,6 +196,7 @@ public static void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttrib public static void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public static void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { } public static void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[]? arg) { } + public static void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, System.ReadOnlySpan arg) { } [System.CLSCompliantAttribute(false)] public static void WriteLine(uint value) { } [System.CLSCompliantAttribute(false)] diff --git a/src/libraries/System.Console/src/System/Console.cs b/src/libraries/System.Console/src/System/Console.cs index 63736b59741706..5e0e387b8299fb 100644 --- a/src/libraries/System.Console/src/System/Console.cs +++ b/src/libraries/System.Console/src/System/Console.cs @@ -865,6 +865,17 @@ public static void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat Out.WriteLine(format, arg); } + /// + /// Writes the text representation of the specified span of objects, followed by the current line terminator, to the standard output stream using the specified format information. + /// + /// A composite format string. + /// A span of objects to write using format. + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan arg) + { + Out.WriteLine(format, arg); + } + [MethodImplAttribute(MethodImplOptions.NoInlining)] public static void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0) { @@ -892,6 +903,17 @@ public static void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] s Out.Write(format, arg); } + /// + /// Writes the text representation of the specified span of objects to the standard output stream using the specified format information. + /// + /// A composite format string. + /// A span of objects to write using format. + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan arg) + { + Out.Write(format, arg); + } + [MethodImplAttribute(MethodImplOptions.NoInlining)] public static void Write(bool value) { diff --git a/src/libraries/System.Console/tests/ReadAndWrite.cs b/src/libraries/System.Console/tests/ReadAndWrite.cs index 5fbf425fc84855..d60fd6aa34cc04 100644 --- a/src/libraries/System.Console/tests/ReadAndWrite.cs +++ b/src/libraries/System.Console/tests/ReadAndWrite.cs @@ -84,10 +84,14 @@ private static void WriteCore() Console.Write("{0}", null, null); Console.Write("{0} {1} {2}", 32, "Hello", (uint)50); Console.Write("{0}", null, null, null); - Console.Write("{0} {1} {2} {3}", 32, "Hello", (uint)50, (ulong)5); - Console.Write("{0}", null, null, null, null); - Console.Write("{0} {1} {2} {3} {4}", 32, "Hello", (uint)50, (ulong)5, 'a'); - Console.Write("{0}", null, null, null, null, null); + Console.Write("{0} {1} {2} {3}", new object[] { 32, "Hello", (uint)50, (ulong)5 }); + Console.Write("{0} {1} {2} {3}", new object[] { 32, "Hello", (uint)50, (ulong)5 }.AsSpan()); + Console.Write("{0}", new object[] { null, null, null, null }); + Console.Write("{0}", new object[] { null, null, null, null }.AsSpan()); + Console.Write("{0} {1} {2} {3} {4}", new object[] { 32, "Hello", (uint)50, (ulong)5, 'a' }); + Console.Write("{0} {1} {2} {3} {4}", new object[] { 32, "Hello", (uint)50, (ulong)5, 'a' }.AsSpan()); + Console.Write("{0}", new object[] { null, null, null, null, null }); + Console.Write("{0}", new object[] { null, null, null, null, null }.AsSpan()); Console.Write(true); Console.Write('a'); Console.Write(new char[] { 'a', 'b', 'c', 'd', }); @@ -120,10 +124,14 @@ private static void WriteLineCore() Console.WriteLine("{0}", null, null); Console.WriteLine("{0} {1} {2}", 32, "Hello", (uint)50); Console.WriteLine("{0}", null, null, null); - Console.WriteLine("{0} {1} {2} {3}", 32, "Hello", (uint)50, (ulong)5); - Console.WriteLine("{0}", null, null, null, null); - Console.WriteLine("{0} {1} {2} {3} {4}", 32, "Hello", (uint)50, (ulong)5, 'a'); - Console.WriteLine("{0}", null, null, null, null, null); + Console.WriteLine("{0} {1} {2} {3}", new object[] { 32, "Hello", (uint)50, (ulong)5 }); + Console.WriteLine("{0} {1} {2} {3}", new object[] { 32, "Hello", (uint)50, (ulong)5 }.AsSpan()); + Console.WriteLine("{0}", new object[] { null, null, null, null }); + Console.WriteLine("{0}", new object[] { null, null, null, null }.AsSpan()); + Console.WriteLine("{0} {1} {2} {3} {4}", new object[] { 32, "Hello", (uint)50, (ulong)5, 'a' }); + Console.WriteLine("{0} {1} {2} {3} {4}", new object[] { 32, "Hello", (uint)50, (ulong)5, 'a' }.AsSpan()); + Console.WriteLine("{0}", new object[] { null, null, null, null, null }); + Console.WriteLine("{0}", new object[] { null, null, null, null, null }.AsSpan()); Console.WriteLine(true); Console.WriteLine('a'); Console.WriteLine(new char[] { 'a', 'b', 'c', 'd', }); @@ -158,8 +166,10 @@ public static async Task OutWriteAndWriteLineOverloads() writer.Write("{0}", 32); writer.Write("{0} {1}", 32, "Hello"); writer.Write("{0} {1} {2}", 32, "Hello", (uint)50); - writer.Write("{0} {1} {2} {3}", 32, "Hello", (uint)50, (ulong)5); - writer.Write("{0} {1} {2} {3} {4}", 32, "Hello", (uint)50, (ulong)5, 'a'); + writer.Write("{0} {1} {2} {3}", new object[] { 32, "Hello", (uint)50, (ulong)5 }); + writer.Write("{0} {1} {2} {3}", new object[] { 32, "Hello", (uint)50, (ulong)5 }.AsSpan()); + writer.Write("{0} {1} {2} {3} {4}", new object[] { 32, "Hello", (uint)50, (ulong)5, 'a' }); + writer.Write("{0} {1} {2} {3} {4}", new object[] { 32, "Hello", (uint)50, (ulong)5, 'a' }.AsSpan()); writer.Write(true); writer.Write('a'); writer.Write(new char[] { 'a', 'b', 'c', 'd', }); diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs index 7cb90d245dcf93..382499070cd1d9 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs @@ -336,7 +336,7 @@ public sealed class Counter : Instrument where T : struct public void Add(T delta, System.Collections.Generic.KeyValuePair tag) { throw null; } public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2) { throw null; } public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2, System.Collections.Generic.KeyValuePair tag3) { throw null; } - public void Add(T delta, ReadOnlySpan> tags) { throw null; } + public void Add(T delta, System.ReadOnlySpan> tags) { throw null; } public void Add(T delta, params System.Collections.Generic.KeyValuePair[] tags) { throw null; } public void Add(T delta, in TagList tagList) { throw null; } internal Counter(Meter meter, string name, string? unit, string? description) : @@ -348,7 +348,7 @@ public sealed class UpDownCounter : Instrument where T : struct public void Add(T delta, System.Collections.Generic.KeyValuePair tag) { throw null; } public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2) { throw null; } public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2, System.Collections.Generic.KeyValuePair tag3) { throw null; } - public void Add(T delta, ReadOnlySpan> tags) { throw null; } + public void Add(T delta, System.ReadOnlySpan> tags) { throw null; } public void Add(T delta, params System.Collections.Generic.KeyValuePair[] tags) { throw null; } public void Add(T delta, in TagList tagList) { throw null; } internal UpDownCounter(Meter meter, string name, string? unit, string? description) : @@ -362,7 +362,7 @@ public sealed class Histogram : Instrument where T : struct public void Record(T value, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2) { throw null; } public void Record(T value, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2, System.Collections.Generic.KeyValuePair tag3) { throw null; } public void Record(T value, in TagList tagList) { throw null; } - public void Record(T value, ReadOnlySpan> tags) { throw null; } + public void Record(T value, System.ReadOnlySpan> tags) { throw null; } public void Record(T value, params System.Collections.Generic.KeyValuePair[] tags) { throw null; } } public interface IMeterFactory : System.IDisposable @@ -398,7 +398,7 @@ public abstract class Instrument : Instrument where T : struct public Measurement(T value) { throw null; } public Measurement(T value, System.Collections.Generic.IEnumerable>? tags) { throw null; } public Measurement(T value, params System.Collections.Generic.KeyValuePair[]? tags) { throw null; } - public Measurement(T value, ReadOnlySpan> tags) { throw null; } + public Measurement(T value, System.ReadOnlySpan> tags) { throw null; } public ReadOnlySpan> Tags { get { throw null; } } public T Value { get { throw null; } } } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Counter.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Counter.cs index 1d311d62196391..9f15ff37c70104 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Counter.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Counter.cs @@ -59,7 +59,7 @@ internal Counter(Meter meter, string name, string? unit, string? description, IE /// /// The increment measurement. /// A span of key-value pair tags associated with the measurement. - public void Add(T delta, ReadOnlySpan> tags) => RecordMeasurement(delta, tags); + public void Add(T delta, /*params*/ ReadOnlySpan> tags) => RecordMeasurement(delta, tags); /// /// Record the increment value of the measurement. diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Histogram.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Histogram.cs index ed3431edfce8be..91f5f40da6e80e 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Histogram.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Histogram.cs @@ -59,7 +59,7 @@ internal Histogram(Meter meter, string name, string? unit, string? description, /// /// The measurement value. /// A span of key-value pair tags associated with the measurement. - public void Record(T value, ReadOnlySpan> tags) => RecordMeasurement(value, tags); + public void Record(T value, /*params*/ ReadOnlySpan> tags) => RecordMeasurement(value, tags); /// /// Record a measurement value. diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Measurement.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Measurement.cs index 49db3c86f8dbf1..f678ef66014ff0 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Measurement.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Measurement.cs @@ -59,7 +59,7 @@ public Measurement(T value, params KeyValuePair[]? tags) /// /// The measurement value. /// The measurement associated tags list. - public Measurement(T value, ReadOnlySpan> tags) + public Measurement(T value, /*params*/ ReadOnlySpan> tags) { _tags = tags.ToArray(); Value = value; diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/TagList.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/TagList.cs index 7646bcc2d33a46..138da8875aeed6 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/TagList.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/TagList.cs @@ -43,7 +43,7 @@ public struct TagList : IList>, IReadOnlyList. /// /// A span of tags to initialize the list with. - public TagList(ReadOnlySpan> tagList) : this() + public TagList(/*params*/ ReadOnlySpan> tagList) : this() { _tagsCount = tagList.Length; switch (_tagsCount) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/UpDownCounter.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/UpDownCounter.cs index 79d0ed29d8f417..4a093865c5511d 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/UpDownCounter.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/UpDownCounter.cs @@ -58,7 +58,7 @@ internal UpDownCounter(Meter meter, string name, string? unit, string? descripti /// /// The amount to be added which can be positive, negative or zero. /// A span of key-value pair tags associated with the measurement. - public void Add(T delta, ReadOnlySpan> tags) => RecordMeasurement(delta, tags); + public void Add(T delta, /*params*/ ReadOnlySpan> tags) => RecordMeasurement(delta, tags); /// /// Record the delta value of the measurement. The delta can be positive, negative or zero. diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs index 4a3cd242bb8be0..b292e55f1bcf20 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs @@ -4,6 +4,7 @@ using Microsoft.DotNet.RemoteExecutor; using System.Collections.Generic; using System.Diagnostics.Metrics; +using System.Diagnostics.Tests; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -13,6 +14,29 @@ namespace System.Diagnostics.Metrics.Tests { public class MetricsTests { + [Fact] + public void MeasurementConstructionTest() + { + for (int i = 0; i < 30; i++) + { + TagListTests.CreateTagList(i, out TagList tags); + TagListTests.ValidateTags(in tags, i); + KeyValuePair[] tagsArray = tags.ToArray(); + + var measurement = new Measurement(i, tags); + Assert.Equal(i, measurement.Value); + TagListTests.ValidateTags(new TagList(measurement.Tags), tagsArray); + + measurement = new Measurement(i, tagsArray); + Assert.Equal(i, measurement.Value); + TagListTests.ValidateTags(new TagList(measurement.Tags), tagsArray); + + measurement = new Measurement(i, tagsArray.AsSpan()); + Assert.Equal(i, measurement.Value); + TagListTests.ValidateTags(new TagList(measurement.Tags), tagsArray); + } + } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] public void MeterConstructionTest() { @@ -238,76 +262,115 @@ public void ThrowingExceptionsFromObservableInstrumentCallbacks() }).Dispose(); } - [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] - public void InstrumentMeasurementTest() + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [InlineData(false)] + [InlineData(true)] + public void InstrumentMeasurementTest(bool useSpan) { - RemoteExecutor.Invoke(() => { + RemoteExecutor.Invoke((string useSpanStr) => { Meter meter = new Meter("InstrumentMeasurementTest"); + bool useSpan = bool.Parse(useSpanStr); Counter counter = meter.CreateCounter("byteCounter"); - InstrumentMeasurementAggregationValidation(counter, (value, tags) => { counter.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter, (value, tags) => { AddToCounter(counter, value, tags, useSpan); } ); UpDownCounter upDownCounter = meter.CreateUpDownCounter("byteUpDownCounter"); - InstrumentMeasurementAggregationValidation(upDownCounter, (value, tags) => { upDownCounter.Add(value, tags); }); + InstrumentMeasurementAggregationValidation(upDownCounter, (value, tags) => { AddToUpDownCounter(upDownCounter, value, tags, useSpan); }); Counter counter1 = meter.CreateCounter("shortCounter"); - InstrumentMeasurementAggregationValidation(counter1, (value, tags) => { counter1.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter1, (value, tags) => { AddToCounter(counter1, value, tags, useSpan); } ); UpDownCounter upDownCounter1 = meter.CreateUpDownCounter("shortUpDownCounter"); - InstrumentMeasurementAggregationValidation(upDownCounter1, (value, tags) => { upDownCounter1.Add(value, tags); }, true); + InstrumentMeasurementAggregationValidation(upDownCounter1, (value, tags) => { AddToUpDownCounter(upDownCounter1, value, tags, useSpan); }, true); Counter counter2 = meter.CreateCounter("intCounter"); - InstrumentMeasurementAggregationValidation(counter2, (value, tags) => { counter2.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter2, (value, tags) => { AddToCounter(counter2, value, tags, useSpan); } ); UpDownCounter upDownCounter2 = meter.CreateUpDownCounter("intUpDownCounter"); - InstrumentMeasurementAggregationValidation(upDownCounter2, (value, tags) => { upDownCounter2.Add(value, tags); }, true); + InstrumentMeasurementAggregationValidation(upDownCounter2, (value, tags) => { AddToUpDownCounter(upDownCounter2, value, tags, useSpan); }, true); Counter counter3 = meter.CreateCounter("longCounter"); - InstrumentMeasurementAggregationValidation(counter3, (value, tags) => { counter3.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter3, (value, tags) => { AddToCounter(counter3, value, tags, useSpan); } ); UpDownCounter upDownCounter3 = meter.CreateUpDownCounter("longUpDownCounter"); - InstrumentMeasurementAggregationValidation(upDownCounter3, (value, tags) => { upDownCounter3.Add(value, tags); }, true); + InstrumentMeasurementAggregationValidation(upDownCounter3, (value, tags) => { AddToUpDownCounter(upDownCounter3, value, tags, useSpan); }, true); Counter counter4 = meter.CreateCounter("floatCounter"); - InstrumentMeasurementAggregationValidation(counter4, (value, tags) => { counter4.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter4, (value, tags) => { AddToCounter(counter4, value, tags, useSpan); } ); UpDownCounter upDownCounter4 = meter.CreateUpDownCounter("floatUpDownCounter"); - InstrumentMeasurementAggregationValidation(upDownCounter4, (value, tags) => { upDownCounter4.Add(value, tags); }, true); + InstrumentMeasurementAggregationValidation(upDownCounter4, (value, tags) => { AddToUpDownCounter(upDownCounter4, value, tags, useSpan); }, true); Counter counter5 = meter.CreateCounter("doubleCounter"); - InstrumentMeasurementAggregationValidation(counter5, (value, tags) => { counter5.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter5, (value, tags) => { AddToCounter(counter5, value, tags, useSpan); } ); UpDownCounter upDownCounter5 = meter.CreateUpDownCounter("doubleUpDownCounter"); - InstrumentMeasurementAggregationValidation(upDownCounter5, (value, tags) => { upDownCounter5.Add(value, tags); }, true); + InstrumentMeasurementAggregationValidation(upDownCounter5, (value, tags) => { AddToUpDownCounter(upDownCounter5, value, tags, useSpan); }, true); Counter counter6 = meter.CreateCounter("decimalCounter"); - InstrumentMeasurementAggregationValidation(counter6, (value, tags) => { counter6.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter6, (value, tags) => { AddToCounter(counter6, value, tags, useSpan); } ); UpDownCounter upDownCounter6 = meter.CreateUpDownCounter("decimalUpDownCounter"); - InstrumentMeasurementAggregationValidation(upDownCounter6, (value, tags) => { upDownCounter6.Add(value, tags); }, true); + InstrumentMeasurementAggregationValidation(upDownCounter6, (value, tags) => { AddToUpDownCounter(upDownCounter6, value, tags, useSpan); }, true); Histogram histogram = meter.CreateHistogram("byteHistogram"); - InstrumentMeasurementAggregationValidation(histogram, (value, tags) => { histogram.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram, (value, tags) => { Record(histogram, value, tags, useSpan); } ); Histogram histogram1 = meter.CreateHistogram("shortHistogram"); - InstrumentMeasurementAggregationValidation(histogram1, (value, tags) => { histogram1.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram1, (value, tags) => { Record(histogram1, value, tags, useSpan); } ); Histogram histogram2 = meter.CreateHistogram("intHistogram"); - InstrumentMeasurementAggregationValidation(histogram2, (value, tags) => { histogram2.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram2, (value, tags) => { Record(histogram2, value, tags, useSpan); } ); Histogram histogram3 = meter.CreateHistogram("longHistogram"); - InstrumentMeasurementAggregationValidation(histogram3, (value, tags) => { histogram3.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram3, (value, tags) => { Record(histogram3, value, tags, useSpan); } ); Histogram histogram4 = meter.CreateHistogram("floatHistogram"); - InstrumentMeasurementAggregationValidation(histogram4, (value, tags) => { histogram4.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram4, (value, tags) => { Record(histogram4, value, tags, useSpan); } ); Histogram histogram5 = meter.CreateHistogram("doubleHistogram"); - InstrumentMeasurementAggregationValidation(histogram5, (value, tags) => { histogram5.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram5, (value, tags) => { Record(histogram5, value, tags, useSpan); } ); Histogram histogram6 = meter.CreateHistogram("decimalHistogram"); - InstrumentMeasurementAggregationValidation(histogram6, (value, tags) => { histogram6.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram6, (value, tags) => { Record(histogram6, value, tags, useSpan); } ); - }).Dispose(); + }, useSpan.ToString()).Dispose(); + + void AddToCounter(Counter counter, T delta, KeyValuePair[] tags, bool useSpan) where T : struct + { + if (useSpan) + { + counter.Add(delta, (ReadOnlySpan>)tags); + } + else + { + counter.Add(delta, tags); + } + } + + void AddToUpDownCounter(UpDownCounter upDownCounter, T delta, KeyValuePair[] tags, bool useSpan) where T : struct + { + if (useSpan) + { + upDownCounter.Add(delta, (ReadOnlySpan>)tags); + } + else + { + upDownCounter.Add(delta, tags); + } + } + + void Record(Histogram histogram, T value, KeyValuePair[] tags, bool useSpan) where T : struct + { + if (useSpan) + { + histogram.Record(value, (ReadOnlySpan>)tags); + } + else + { + histogram.Record(value, tags); + } + } } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TagListTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TagListTests.cs index 9f35cb9d47c027..59edc168186a65 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TagListTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TagListTests.cs @@ -3,7 +3,6 @@ using Xunit; using System.Collections.Generic; -using System.Diagnostics; namespace System.Diagnostics.Tests { @@ -21,7 +20,7 @@ public void TestConstruction() KeyValuePair[] array = new KeyValuePair[tagList.Count]; tagList.CopyTo(array); TagList list = new TagList(array.AsSpan()); - ValidateTags(in tagList, i); + ValidateTags(in list, i); } } @@ -303,7 +302,7 @@ public void TestNegativeCases() Assert.Throws(() => list.RemoveAt(2)); } - private void ValidateTags(in TagList tagList, KeyValuePair[] array) + internal static void ValidateTags(in TagList tagList, KeyValuePair[] array) { Assert.True(tagList.Count <= array.Length); for (int i = 0; i < tagList.Count; i++) @@ -313,7 +312,7 @@ private void ValidateTags(in TagList tagList, KeyValuePair[] ar } } - private void ValidateTags(in TagList tagList, int tagsCount) + internal static void ValidateTags(in TagList tagList, int tagsCount) { Assert.Equal(tagsCount, tagList.Count); for (int i = 0; i < tagList.Count; i++) @@ -323,7 +322,7 @@ private void ValidateTags(in TagList tagList, int tagsCount) } } - private void CreateTagList(int tagsCount, out TagList tagList) + internal static void CreateTagList(int tagsCount, out TagList tagList) { tagList = new TagList(); for (int i = 0; i < tagsCount; i++) diff --git a/src/libraries/System.IO.FileSystem.AccessControl/src/System.IO.FileSystem.AccessControl.csproj b/src/libraries/System.IO.FileSystem.AccessControl/src/System.IO.FileSystem.AccessControl.csproj index e120f89518cc3f..03cbd816a2ff71 100644 --- a/src/libraries/System.IO.FileSystem.AccessControl/src/System.IO.FileSystem.AccessControl.csproj +++ b/src/libraries/System.IO.FileSystem.AccessControl/src/System.IO.FileSystem.AccessControl.csproj @@ -95,7 +95,7 @@ - + diff --git a/src/libraries/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj b/src/libraries/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj index 3b224099af7611..a11a0d7077cc65 100644 --- a/src/libraries/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj +++ b/src/libraries/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj @@ -46,6 +46,7 @@ + diff --git a/src/libraries/System.IO.Pipes.AccessControl/src/System.IO.Pipes.AccessControl.csproj b/src/libraries/System.IO.Pipes.AccessControl/src/System.IO.Pipes.AccessControl.csproj index fcd66e7adf9a64..6e48d964b2744e 100644 --- a/src/libraries/System.IO.Pipes.AccessControl/src/System.IO.Pipes.AccessControl.csproj +++ b/src/libraries/System.IO.Pipes.AccessControl/src/System.IO.Pipes.AccessControl.csproj @@ -19,6 +19,7 @@ Condition="'$(TargetPlatformIdentifier)' == 'windows'" /> + diff --git a/src/libraries/System.Linq.Expressions/src/System.Linq.Expressions.csproj b/src/libraries/System.Linq.Expressions/src/System.Linq.Expressions.csproj index 9213e4c6c944fe..66a070211ddca4 100644 --- a/src/libraries/System.Linq.Expressions/src/System.Linq.Expressions.csproj +++ b/src/libraries/System.Linq.Expressions/src/System.Linq.Expressions.csproj @@ -219,6 +219,7 @@ + diff --git a/src/libraries/System.Linq.Parallel/src/System.Linq.Parallel.csproj b/src/libraries/System.Linq.Parallel/src/System.Linq.Parallel.csproj index 3d7f38289ac0aa..15ff9887505a59 100644 --- a/src/libraries/System.Linq.Parallel/src/System.Linq.Parallel.csproj +++ b/src/libraries/System.Linq.Parallel/src/System.Linq.Parallel.csproj @@ -157,6 +157,7 @@ + diff --git a/src/libraries/System.Linq.Queryable/src/System.Linq.Queryable.csproj b/src/libraries/System.Linq.Queryable/src/System.Linq.Queryable.csproj index 8298f938086124..343028ced1ad2a 100644 --- a/src/libraries/System.Linq.Queryable/src/System.Linq.Queryable.csproj +++ b/src/libraries/System.Linq.Queryable/src/System.Linq.Queryable.csproj @@ -19,6 +19,7 @@ + diff --git a/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj b/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj index 4f8e58e36abfbb..ef01da51d137d3 100644 --- a/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj +++ b/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj @@ -53,6 +53,7 @@ System.Net.Http.Json.JsonContent + @@ -65,6 +66,7 @@ System.Net.Http.Json.JsonContent + diff --git a/src/libraries/System.ObjectModel/src/System.ObjectModel.csproj b/src/libraries/System.ObjectModel/src/System.ObjectModel.csproj index 1a8f23c29c492b..0ef93fda9ecd4b 100644 --- a/src/libraries/System.ObjectModel/src/System.ObjectModel.csproj +++ b/src/libraries/System.ObjectModel/src/System.ObjectModel.csproj @@ -33,6 +33,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/CodeDom/Compiler/IndentedTextWriter.cs b/src/libraries/System.Private.CoreLib/src/System/CodeDom/Compiler/IndentedTextWriter.cs index 22ee77a8cc6e64..43608b97f78ff1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/CodeDom/Compiler/IndentedTextWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/CodeDom/Compiler/IndentedTextWriter.cs @@ -174,6 +174,17 @@ public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] _writer.Write(format, arg); } + /// + /// Writes out a formatted string, using the same semantics as specified. + /// + /// The formatting string to use. + /// The argument span to output. + public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan arg) + { + OutputTabs(); + _writer.Write(format, arg); + } + /// /// Asynchronously writes the specified to the underlying , inserting /// tabs at the start of every line. @@ -352,6 +363,18 @@ public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeForm _tabsPending = true; } + /// + /// Writes out a formatted string, followed by a line terminator, using the same semantics as specified. + /// + /// The formatting string to use. + /// The argument span to output. + public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan arg) + { + OutputTabs(); + _writer.WriteLine(format, arg); + _tabsPending = true; + } + [CLSCompliant(false)] public override void WriteLine(uint value) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/CollectionExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/CollectionExtensions.cs index 068536049a65f9..6c7949eed7bf74 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/CollectionExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/CollectionExtensions.cs @@ -82,7 +82,7 @@ public static ReadOnlyDictionary AsReadOnly(this IDi /// The list to which the elements should be added. /// The span whose elements should be added to the end of the . /// The is null. - public static void AddRange(this List list, ReadOnlySpan source) + public static void AddRange(this List list, /*params*/ ReadOnlySpan source) { if (list is null) { @@ -109,7 +109,7 @@ public static void AddRange(this List list, ReadOnlySpan source) /// The span whose elements should be added to the . /// The is null. /// is less than 0 or greater than 's . - public static void InsertRange(this List list, int index, ReadOnlySpan source) + public static void InsertRange(this List list, int index, /*params*/ ReadOnlySpan source) { if (list is null) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Delegate.cs b/src/libraries/System.Private.CoreLib/src/System/Delegate.cs index d24059770d5f88..cc8a66e341b529 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Delegate.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Delegate.cs @@ -23,14 +23,30 @@ public abstract partial class Delegate : ICloneable, ISerializable return a.CombineImpl(b); } - public static Delegate? Combine(params Delegate?[]? delegates) + public static Delegate? Combine(params Delegate?[]? delegates) => + Combine((ReadOnlySpan)delegates); + + /// + /// Concatenates the invocation lists of an span of delegates. + /// + /// The span of delegates to combine. + /// + /// A new delegate with an invocation list that concatenates the invocation lists of the delegates in the span. + /// Returns if is , + /// if contains zero elements, or if every entry in is . + /// + public static Delegate? Combine(/*params*/ ReadOnlySpan delegates) { - if (delegates == null || delegates.Length == 0) - return null; + Delegate? d = null; - Delegate? d = delegates[0]; - for (int i = 1; i < delegates.Length; i++) - d = Combine(d, delegates[i]); + if (!delegates.IsEmpty) + { + d = delegates[0]; + for (int i = 1; i < delegates.Length; i++) + { + d = Combine(d, delegates[i]); + } + } return d; } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Path.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Path.cs index 9d1dced98c8c0b..e6cc976336bbfd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Path.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Path.cs @@ -371,7 +371,16 @@ public static string Combine(string path1, string path2, string path3, string pa public static string Combine(params string[] paths) { ArgumentNullException.ThrowIfNull(paths); + return Combine((ReadOnlySpan)paths); + } + /// + /// Combines a span of strings into a path. + /// + /// A span of parts of the path. + /// The combined paths. + public static string Combine(/*params*/ ReadOnlySpan paths) + { int maxSize = 0; int firstComponent = 0; @@ -520,8 +529,17 @@ public static string Join(string? path1, string? path2, string? path3, string? p public static string Join(params string?[] paths) { ArgumentNullException.ThrowIfNull(paths); + return Join((ReadOnlySpan)paths); + } - if (paths.Length == 0) + /// + /// Concatenates a span of paths into a single path. + /// + /// A span of paths. + /// The concatenated path. + public static string Join(/*params*/ ReadOnlySpan paths) + { + if (paths.IsEmpty) { return string.Empty; } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs index d11c1313ba84d4..947c803d6d2747 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs @@ -568,6 +568,23 @@ public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] } } + /// + /// Writes a formatted string to the stream, using the same semantics as . + /// + /// A composite format string. + /// An object span that contains zero or more objects to format and write. + public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan arg) + { + if (GetType() == typeof(StreamWriter)) + { + WriteFormatHelper(format, arg, appendNewLine: false); + } + else + { + base.Write(format, arg); + } + } + public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0) { if (GetType() == typeof(StreamWriter)) @@ -619,6 +636,23 @@ public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeForm } } + /// + /// Writes out a formatted string and a new line to the stream, using the same semantics as . + /// + /// A composite format string. + /// An object span that contains zero or more objects to format and write. + public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan arg) + { + if (GetType() == typeof(StreamWriter)) + { + WriteFormatHelper(format, arg, appendNewLine: true); + } + else + { + base.WriteLine(format, arg); + } + } + public override Task WriteAsync(char value) { // If we have been inherited into a subclass, the following implementation could be incorrect diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.CreateBroadcasting.cs b/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.CreateBroadcasting.cs index 41fdf7eb56f964..82c9d6edd619d5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.CreateBroadcasting.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.CreateBroadcasting.cs @@ -268,6 +268,14 @@ public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] } } + public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan arg) + { + foreach (TextWriter writer in _writers) + { + writer.Write(format, arg); + } + } + public override void WriteLine() { foreach (TextWriter writer in _writers) @@ -428,6 +436,14 @@ public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeForm } } + public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan arg) + { + foreach (TextWriter writer in _writers) + { + writer.WriteLine(format, arg); + } + } + public override async Task WriteAsync(char value) { foreach (TextWriter writer in _writers) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs b/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs index 289ec5fac7a5e8..27a73516d4be96 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs @@ -317,6 +317,16 @@ public virtual void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] Write(string.Format(FormatProvider, format, arg)); } + /// + /// Writes a formatted string to the text stream, using the same semantics as . + /// + /// A composite format string. + /// An object span that contains zero or more objects to format and write. + public virtual void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan arg) + { + Write(string.Format(FormatProvider, format, arg)); + } + // Writes a line terminator to the text stream. The default line terminator // is Environment.NewLine, but this value can be changed by setting the NewLine property. // @@ -514,6 +524,16 @@ public virtual void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeForma WriteLine(string.Format(FormatProvider, format, arg)); } + /// + /// Writes out a formatted string and a new line to the text stream, using the same semantics as . + /// + /// A composite format string. + /// An object span that contains zero or more objects to format and write. + public virtual void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan arg) + { + WriteLine(string.Format(FormatProvider, format, arg)); + } + #region Task based Async APIs public virtual Task WriteAsync(char value) => Task.Factory.StartNew(static state => @@ -700,6 +720,7 @@ public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1) { } public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1, object? arg2) { } public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params object?[] arg) { } + public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan arg) { } public override Task WriteAsync(char value) => Task.CompletedTask; public override Task WriteAsync(string? value) => Task.CompletedTask; public override Task WriteAsync(StringBuilder? value, CancellationToken cancellationToken = default) => Task.CompletedTask; @@ -725,6 +746,7 @@ public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeForm public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1) { } public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1, object? arg2) { } public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params object?[] arg) { } + public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan arg) { } public override Task WriteLineAsync(char value) => Task.CompletedTask; public override Task WriteLineAsync(string? value) => Task.CompletedTask; public override Task WriteLineAsync(StringBuilder? value, CancellationToken cancellationToken = default) => Task.CompletedTask; @@ -833,6 +855,9 @@ protected override void Dispose(bool disposing) [MethodImpl(MethodImplOptions.Synchronized)] public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object?[] arg) => _out.Write(format, arg); + [MethodImpl(MethodImplOptions.Synchronized)] + public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, ReadOnlySpan arg) => _out.Write(format, arg); + [MethodImpl(MethodImplOptions.Synchronized)] public override void WriteLine() => _out.WriteLine(); @@ -893,6 +918,9 @@ protected override void Dispose(bool disposing) [MethodImpl(MethodImplOptions.Synchronized)] public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object?[] arg) => _out.WriteLine(format, arg); + [MethodImpl(MethodImplOptions.Synchronized)] + public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, ReadOnlySpan arg) => _out.WriteLine(format, arg); + // // On SyncTextWriter all APIs should run synchronously, even the async ones. // diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index 50a0d5b19d5acd..d3c9e28cb0ccda 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -4173,7 +4173,7 @@ public static bool TryWrite(this Span destination, IFormatProvider? provid /// if the entire interpolated string could be formatted successfully; otherwise, . /// is null. /// The index of a format item is greater than or equal to the number of supplied arguments. - public static bool TryWrite(this Span destination, IFormatProvider? provider, CompositeFormat format, out int charsWritten, ReadOnlySpan args) + public static bool TryWrite(this Span destination, IFormatProvider? provider, CompositeFormat format, out int charsWritten, /*params*/ ReadOnlySpan args) { ArgumentNullException.ThrowIfNull(format); format.ValidateNumberOfArgs(args.Length); diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs index 7f4f642526d451..596e743ebe215d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs @@ -62,10 +62,19 @@ public static string Concat(object? arg0, object? arg1, object? arg2) => public static string Concat(params object?[] args) { ArgumentNullException.ThrowIfNull(args); + return Concat((ReadOnlySpan)args); + } + /// + /// Concatenates the string representations of the elements in a specified span of objects. + /// + /// A span of objects that contains the elements to concatenate. + /// The concatenated string representations of the values of the elements in . + public static string Concat(/*params*/ ReadOnlySpan args) + { if (args.Length <= 1) { - return args.Length == 0 ? + return args.IsEmpty ? Empty : args[0]?.ToString() ?? Empty; } @@ -355,10 +364,19 @@ internal static string Concat(ReadOnlySpan str0, ReadOnlySpan str1, public static string Concat(params string?[] values) { ArgumentNullException.ThrowIfNull(values); + return Concat((ReadOnlySpan)values); + } + /// + /// Concatenates the elements of a specified span of . + /// + /// A span of instances. + /// The concatenated elements of . + public static string Concat(/*params*/ ReadOnlySpan values) + { if (values.Length <= 1) { - return values.Length == 0 ? + return values.IsEmpty ? Empty : values[0] ?? Empty; } @@ -416,7 +434,7 @@ public static string Concat(params string?[] values) // something changed concurrently to mutate the input array: fall back to // doing the concatenation again, but this time with a defensive copy. This // fall back should be extremely rare. - return copiedLength == totalLength ? result : Concat((string?[])values.Clone()); + return copiedLength == totalLength ? result : Concat((ReadOnlySpan)values.ToArray()); } public static string Format([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0) @@ -445,6 +463,17 @@ public static string Format([StringSyntax(StringSyntaxAttribute.CompositeFormat) ArgumentNullException.Throw(format is null ? nameof(format) : nameof(args)); } + return FormatHelper(null, format, (ReadOnlySpan)args); + } + + /// + /// Replaces the format item in a specified string with the string representation of a corresponding object in a specified span. + /// + /// A composite format string. + /// An object span that contains zero or more objects to format. + /// A copy of in which the format items have been replaced by the string representation of the corresponding objects in . + public static string Format([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan args) + { return FormatHelper(null, format, args); } @@ -474,6 +503,19 @@ public static string Format(IFormatProvider? provider, [StringSyntax(StringSynta ArgumentNullException.Throw(format is null ? nameof(format) : nameof(args)); } + return FormatHelper(provider, format, (ReadOnlySpan)args); + } + + /// + /// Replaces the format items in a string with the string representations of corresponding objects in a specified span. + /// A parameter supplies culture-specific formatting information. + /// + /// An object that supplies culture-specific formatting information. + /// A composite format string. + /// An object span that contains zero or more objects to format. + /// A copy of in which the format items have been replaced by the string representation of the corresponding objects in . + public static string Format(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan args) + { return FormatHelper(provider, format, args); } @@ -575,7 +617,7 @@ public static string Format(IFormatProvider? provider, CompositeFormat format, p /// The formatted string. /// is null. /// The index of a format item is greater than or equal to the number of supplied arguments. - public static string Format(IFormatProvider? provider, CompositeFormat format, ReadOnlySpan args) + public static string Format(IFormatProvider? provider, CompositeFormat format, /*params*/ ReadOnlySpan args) { ArgumentNullException.ThrowIfNull(format); format.ValidateNumberOfArgs(args.Length); @@ -669,6 +711,21 @@ public static string Join(char separator, params string?[] value) return JoinCore(new ReadOnlySpan(in separator), new ReadOnlySpan(value)); } + /// + /// Concatenates a span of strings, using the specified separator between each member. + /// + /// The character to use as a separator. is included in the returned string only if has more than one element. + /// A span that contains the elements to concatenate. + /// + /// A string that consists of the elements of delimited by the string. + /// -or- + /// if has zero elements. + /// + public static string Join(char separator, /*params*/ ReadOnlySpan value) + { + return JoinCore(new ReadOnlySpan(in separator), value); + } + public static string Join(string? separator, params string?[] value) { if (value == null) @@ -679,6 +736,21 @@ public static string Join(string? separator, params string?[] value) return JoinCore(separator.AsSpan(), new ReadOnlySpan(value)); } + /// + /// Concatenates a span of strings, using the specified separator between each member. + /// + /// The string to use as a separator. is included in the returned string only if has more than one element. + /// A span that contains the elements to concatenate. + /// + /// A string that consists of the elements of delimited by the string. + /// -or- + /// if has zero elements. + /// + public static string Join(string? separator, /*params*/ ReadOnlySpan value) + { + return JoinCore(separator.AsSpan(), value); + } + public static string Join(char separator, string?[] value, int startIndex, int count) => JoinCore(new ReadOnlySpan(in separator), value, startIndex, count); @@ -743,20 +815,55 @@ public static string Join(string? separator, IEnumerable values) } } - public static string Join(char separator, params object?[] values) => - JoinCore(new ReadOnlySpan(in separator), values); + public static string Join(char separator, params object?[] values) + { + if (values == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } - public static string Join(string? separator, params object?[] values) => - JoinCore(separator.AsSpan(), values); + return JoinCore(new ReadOnlySpan(in separator), (ReadOnlySpan)values); + } - private static string JoinCore(ReadOnlySpan separator, object?[] values) + /// + /// Concatenates the string representations of a span of objects, using the specified separator between each member. + /// + /// The character to use as a separator. is included in the returned string only if value has more than one element. + /// A span of objects whose string representations will be concatenated. + /// + /// A string that consists of the elements of delimited by the character. + /// -or- + /// if has zero elements. + /// + public static string Join(char separator, /*params*/ ReadOnlySpan values) => + JoinCore(new ReadOnlySpan(in separator), values); + + public static string Join(string? separator, params object?[] values) { if (values == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); } - if (values.Length == 0) + return JoinCore(separator.AsSpan(), (ReadOnlySpan)values); + } + + /// + /// Concatenates the string representations of a span of objects, using the specified separator between each member. + /// + /// The string to use as a separator. is included in the returned string only if has more than one element. + /// A span of objects whose string representations will be concatenated. + /// + /// A string that consists of the elements of delimited by the string. + /// -or- + /// if has zero elements. + /// + public static string Join(string? separator, /*params*/ ReadOnlySpan values) => + JoinCore(separator.AsSpan(), values); + + private static string JoinCore(ReadOnlySpan separator, ReadOnlySpan values) + { + if (values.IsEmpty) { return Empty; } @@ -793,11 +900,16 @@ public static string Join(string? separator, IEnumerable values) => private static string JoinCore(ReadOnlySpan separator, IEnumerable values) { + if (values is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } + if (typeof(T) == typeof(string)) { - if (values is List valuesList) + if (values.GetType() == typeof(List)) // avoid accidentally bypassing a derived type's reimplementation of IEnumerable { - return JoinCore(separator, CollectionsMarshal.AsSpan(valuesList)); + return JoinCore(separator, CollectionsMarshal.AsSpan(Unsafe.As>(values))); } if (values is string?[] valuesArray) @@ -806,11 +918,6 @@ private static string JoinCore(ReadOnlySpan separator, IEnumerable v } } - if (values == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); - } - using (IEnumerator e = values.GetEnumerator()) { if (!e.MoveNext()) @@ -1548,6 +1655,16 @@ public string[] Split(params char[]? separator) return SplitInternal(separator, int.MaxValue, StringSplitOptions.None); } + /// + /// Splits a string into substrings based on specified delimiting characters. + /// + /// A span of delimiting characters, or an empty span that contains no delimiters. + /// An array whose elements contain the substrings from this instance that are delimited by one or more characters in . + public string[] Split(/*params*/ ReadOnlySpan separator) + { + return SplitInternal(separator, int.MaxValue, StringSplitOptions.None); + } + // Creates an array of strings by splitting this string at each // occurrence of a separator. The separator is searched for, and if found, // the substring preceding the occurrence is stored as the first element in @@ -2241,6 +2358,28 @@ public unsafe string Trim(params char[]? trimChars) } } + /// + /// Removes all leading and trailing occurrences of a set of characters specified in a span from the current string. + /// + /// A span of Unicode characters to remove. + /// + /// The string that remains after all occurrences of the characters in the parameter are removed from the start and end of the current string. + /// If is empty, white-space characters are removed instead. + /// If no characters can be trimmed from the current instance, the method returns the current instance unchanged. + /// + public unsafe string Trim(/*params*/ ReadOnlySpan trimChars) + { + if (trimChars.IsEmpty) + { + return TrimWhiteSpaceHelper(TrimType.Both); + } + + fixed (char* pTrimChars = &MemoryMarshal.GetReference(trimChars)) + { + return TrimHelper(pTrimChars, trimChars.Length, TrimType.Both); + } + } + // Removes a set of characters from the beginning of this string. public string TrimStart() => TrimWhiteSpaceHelper(TrimType.Head); @@ -2260,6 +2399,28 @@ public unsafe string TrimStart(params char[]? trimChars) } } + /// + /// Removes all the leading occurrences of a set of characters specified in a span from the current string. + /// + /// A span of Unicode characters to remove. + /// + /// The string that remains after all occurrences of characters in the parameter are removed from the start of the current string. + /// If is empty, white-space characters are removed instead. + /// If no characters can be trimmed from the current instance, the method returns the current instance unchanged. + /// + public unsafe string TrimStart(/*params*/ ReadOnlySpan trimChars) + { + if (trimChars.IsEmpty) + { + return TrimWhiteSpaceHelper(TrimType.Head); + } + + fixed (char* pTrimChars = &MemoryMarshal.GetReference(trimChars)) + { + return TrimHelper(pTrimChars, trimChars.Length, TrimType.Head); + } + } + // Removes a set of characters from the end of this string. public string TrimEnd() => TrimWhiteSpaceHelper(TrimType.Tail); @@ -2279,6 +2440,28 @@ public unsafe string TrimEnd(params char[]? trimChars) } } + /// + /// Removes all the trailing occurrences of a set of characters specified in a span from the current string. + /// + /// A span of Unicode characters to remove. + /// + /// The string that remains after all occurrences of characters in the parameter are removed from the end of the current string. + /// If is empty, white-space characters are removed instead. + /// If no characters can be trimmed from the current instance, the method returns the current instance unchanged. + /// + public unsafe string TrimEnd(/*params*/ ReadOnlySpan trimChars) + { + if (trimChars.IsEmpty) + { + return TrimWhiteSpaceHelper(TrimType.Tail); + } + + fixed (char* pTrimChars = &trimChars[0]) + { + return TrimHelper(pTrimChars, trimChars.Length, TrimType.Tail); + } + } + private string TrimWhiteSpaceHelper(TrimType trimType) { // end will point to the first non-trimmed character on the right. diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs index 6f7b0abfa9b91f..e7bee231dbf45d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs @@ -1123,6 +1123,24 @@ public StringBuilder Append(ReadOnlySpan value) #region AppendJoin public StringBuilder AppendJoin(string? separator, params object?[] values) + { + if (values is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } + + separator ??= string.Empty; + return AppendJoinCore(ref separator.GetRawStringData(), separator.Length, values); + } + + /// + /// Concatenates the string representations of the elements in the provided span of objects, using the specified separator between each member, + /// then appends the result to the current instance of the string builder. + /// + /// The string to use as a separator. is included in the joined strings only if has more than one element. + /// A span that contains the strings to concatenate and append to the current instance of the string builder. + /// A reference to this instance after the append operation has completed. + public StringBuilder AppendJoin(string? separator, /*params*/ ReadOnlySpan values) { separator ??= string.Empty; return AppendJoinCore(ref separator.GetRawStringData(), separator.Length, values); @@ -1130,11 +1148,34 @@ public StringBuilder AppendJoin(string? separator, params object?[] values) public StringBuilder AppendJoin(string? separator, IEnumerable values) { + if (values is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } + separator ??= string.Empty; return AppendJoinCore(ref separator.GetRawStringData(), separator.Length, values); } public StringBuilder AppendJoin(string? separator, params string?[] values) + { + if (values is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } + + separator ??= string.Empty; + return AppendJoinCore(ref separator.GetRawStringData(), separator.Length, values); + } + + /// + /// Concatenates the strings of the provided span, using the specified separator between each string, + /// then appends the result to the current instance of the string builder. + /// + /// The string to use as a separator. is included in the joined strings only if has more than one element. + /// A span that contains the strings to concatenate and append to the current instance of the string builder. + /// A reference to this instance after the append operation has completed. + public StringBuilder AppendJoin(string? separator, /*params*/ ReadOnlySpan values) { separator ??= string.Empty; return AppendJoinCore(ref separator.GetRawStringData(), separator.Length, values); @@ -1142,30 +1183,60 @@ public StringBuilder AppendJoin(string? separator, params string?[] values) public StringBuilder AppendJoin(char separator, params object?[] values) { - return AppendJoinCore(ref separator, 1, values); + if (values is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } + + return AppendJoinCore(ref separator, 1, (ReadOnlySpan)values); } + /// + /// Concatenates the string representations of the elements in the provided span of objects, using the specified char separator between each member, + /// then appends the result to the current instance of the string builder. + /// + /// The character to use as a separator. is included in the joined strings only if has more than one element. + /// A span that contains the strings to concatenate and append to the current instance of the string builder. + /// A reference to this instance after the append operation has completed. + public StringBuilder AppendJoin(char separator, /*params*/ ReadOnlySpan values) => + AppendJoinCore(ref separator, 1, values); + public StringBuilder AppendJoin(char separator, IEnumerable values) { + if (values is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } + return AppendJoinCore(ref separator, 1, values); } public StringBuilder AppendJoin(char separator, params string?[] values) { - return AppendJoinCore(ref separator, 1, values); + if (values is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } + + return AppendJoinCore(ref separator, 1, (ReadOnlySpan)values); } + /// + /// Concatenates the strings of the provided span, using the specified char separator between each string, + /// then appends the result to the current instance of the string builder. + /// + /// The character to use as a separator. is included in the joined strings only if has more than one element. + /// A span that contains the strings to concatenate and append to the current instance of the string builder. + /// A reference to this instance after the append operation has completed. + public StringBuilder AppendJoin(char separator, /*params*/ ReadOnlySpan values) => + AppendJoinCore(ref separator, 1, values); + private StringBuilder AppendJoinCore(ref char separator, int separatorLength, IEnumerable values) { + Debug.Assert(values != null); Debug.Assert(!Unsafe.IsNullRef(ref separator)); Debug.Assert(separatorLength >= 0); - if (values == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); - } - - Debug.Assert(values != null); using (IEnumerator en = values.GetEnumerator()) { if (!en.MoveNext()) @@ -1192,15 +1263,9 @@ private StringBuilder AppendJoinCore(ref char separator, int separatorLength, return this; } - private StringBuilder AppendJoinCore(ref char separator, int separatorLength, T[] values) + private StringBuilder AppendJoinCore(ref char separator, int separatorLength, ReadOnlySpan values) { - if (values == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); - } - - Debug.Assert(values != null); - if (values.Length == 0) + if (values.IsEmpty) { return this; } @@ -1360,19 +1425,19 @@ private StringBuilder InsertSpanFormattable(int index, T value) where T : ISp public StringBuilder AppendFormat([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0) { - return AppendFormatHelper(null, format, new ReadOnlySpan(in arg0)); + return AppendFormat(null, format, new ReadOnlySpan(in arg0)); } public StringBuilder AppendFormat([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1) { TwoObjects two = new TwoObjects(arg0, arg1); - return AppendFormatHelper(null, format, two); + return AppendFormat(null, format, (ReadOnlySpan)two); } public StringBuilder AppendFormat([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1, object? arg2) { ThreeObjects three = new ThreeObjects(arg0, arg1, arg2); - return AppendFormatHelper(null, format, three); + return AppendFormat(null, format, (ReadOnlySpan)three); } public StringBuilder AppendFormat([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params object?[] args) @@ -1380,28 +1445,47 @@ public StringBuilder AppendFormat([StringSyntax(StringSyntaxAttribute.CompositeF if (args is null) { // To preserve the original exception behavior, throw an exception about format if both - // args and format are null. The actual null check for format is in AppendFormatHelper. + // args and format are null. The actual null check for format is in AppendFormat(..., span). ArgumentNullException.Throw(format is null ? nameof(format) : nameof(args)); } - return AppendFormatHelper(null, format, args); + return AppendFormat(null, format, args); + } + + /// + /// Appends the string returned by processing a composite format string, which contains zero or more format items, to this instance. + /// Each format item is replaced by the string representation of a corresponding argument in a parameter span. + /// + /// A composite format string. + /// A span of objects to format. + /// A reference to this instance after the append operation has completed. + /// is null. + /// The length of the expanded string would exceed . + /// + /// is invalid. + /// -or- + /// The index of a format item is less than 0 (zero), or greater than or equal to the length of the span. + /// + public StringBuilder AppendFormat([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan args) + { + return AppendFormat(null, format, args); } public StringBuilder AppendFormat(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0) { - return AppendFormatHelper(provider, format, new ReadOnlySpan(in arg0)); + return AppendFormat(provider, format, new ReadOnlySpan(in arg0)); } public StringBuilder AppendFormat(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1) { TwoObjects two = new TwoObjects(arg0, arg1); - return AppendFormatHelper(provider, format, two); + return AppendFormat(provider, format, (ReadOnlySpan)two); } public StringBuilder AppendFormat(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1, object? arg2) { ThreeObjects three = new ThreeObjects(arg0, arg1, arg2); - return AppendFormatHelper(provider, format, three); + return AppendFormat(provider, format, (ReadOnlySpan)three); } public StringBuilder AppendFormat(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params object?[] args) @@ -1409,14 +1493,29 @@ public StringBuilder AppendFormat(IFormatProvider? provider, [StringSyntax(Strin if (args is null) { // To preserve the original exception behavior, throw an exception about format if both - // args and format are null. The actual null check for format is in AppendFormatHelper. + // args and format are null. The actual null check for format is in AppendFormat(..., span). ArgumentNullException.Throw(format is null ? nameof(format) : nameof(args)); } - return AppendFormatHelper(provider, format, args); + return AppendFormat(provider, format, (ReadOnlySpan)args); } - internal StringBuilder AppendFormatHelper(IFormatProvider? provider, string format, ReadOnlySpan args) + /// + /// Appends the string returned by processing a composite format string, which contains zero or more format items, to this instance. + /// Each format item is replaced by the string representation of a corresponding argument in a parameter span using a specified format provider. + /// + /// An object that supplies culture-specific formatting information. + /// A composite format string. + /// A span of objects to format. + /// A reference to this instance after the append operation has completed. + /// is null. + /// The length of the expanded string would exceed . + /// + /// is invalid. + /// -or- + /// The index of a format item is less than 0 (zero), or greater than or equal to the length of the span. + /// + public StringBuilder AppendFormat(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, /*params*/ ReadOnlySpan args) { ArgumentNullException.ThrowIfNull(format); @@ -1776,7 +1875,7 @@ public StringBuilder AppendFormat(IFormatProvider? provider, CompositeFormat for /// A reference to this instance after the append operation has completed. /// is null. /// The index of a format item is greater than or equal to the number of supplied arguments. - public StringBuilder AppendFormat(IFormatProvider? provider, CompositeFormat format, ReadOnlySpan args) + public StringBuilder AppendFormat(IFormatProvider? provider, CompositeFormat format, /*params*/ ReadOnlySpan args) { ArgumentNullException.ThrowIfNull(format); format.ValidateNumberOfArgs(args.Length); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs index ace2ed4b943d93..092b9467232157 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs @@ -868,7 +868,17 @@ public static CancellationTokenSource CreateLinkedTokenSource(CancellationToken public static CancellationTokenSource CreateLinkedTokenSource(params CancellationToken[] tokens) { ArgumentNullException.ThrowIfNull(tokens); + return CreateLinkedTokenSource((ReadOnlySpan)tokens); + } + /// + /// Creates a that will be in the canceled state + /// when any of the source tokens are in the canceled state. + /// + /// The CancellationToken instances to observe. + /// A that is linked to the source tokens. + public static CancellationTokenSource CreateLinkedTokenSource(/*params*/ ReadOnlySpan tokens) + { return tokens.Length switch { 0 => throw new ArgumentException(SR.CancellationToken_CreateLinkedToken_TokensIsEmpty), @@ -935,7 +945,7 @@ private sealed class LinkedNCancellationTokenSource : CancellationTokenSource }; private CancellationTokenRegistration[]? _linkingRegistrations; - internal LinkedNCancellationTokenSource(CancellationToken[] tokens) + internal LinkedNCancellationTokenSource(ReadOnlySpan tokens) { _linkingRegistrations = new CancellationTokenRegistration[tokens.Length]; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs index fa03b43aff87cc..ab532be3e3da4e 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 @@ -4690,6 +4690,26 @@ public static void WaitAll(params Task[] tasks) Debug.Assert(waitResult, "expected wait to succeed"); } + /// + /// Waits for all of the provided objects to complete execution. + /// + /// + /// An array of instances on which to wait. + /// + /// + /// The argument contains a null element. + /// + /// + /// At least one of the instances was canceled -or- an exception was thrown during + /// the execution of at least one of the instances. + /// + [UnsupportedOSPlatform("browser")] + public static void WaitAll(/*params*/ ReadOnlySpan tasks) + { + bool waitResult = WaitAllCore(tasks, Timeout.Infinite, default); + Debug.Assert(waitResult, "expected wait to succeed"); + } + /// /// Waits for all of the provided objects to complete execution. /// @@ -4724,7 +4744,7 @@ public static void WaitAll(params Task[] tasks) public static bool WaitAll(Task[] tasks, TimeSpan timeout) { long totalMilliseconds = (long)timeout.TotalMilliseconds; - if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) + if (totalMilliseconds is < -1 or > int.MaxValue) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.timeout); } @@ -5953,7 +5973,7 @@ public static Task WhenAll(params Task[] tasks) /// /// /// The array contained a null task. - internal static Task WhenAll(ReadOnlySpan tasks) => // TODO https://github.com/dotnet/runtime/issues/77873: Make this public. + public static Task WhenAll(/*params*/ ReadOnlySpan tasks) => tasks.Length != 0 ? new WhenAllPromise(tasks) : CompletedTask; /// A Task that gets completed when all of its constituent tasks complete. @@ -6172,7 +6192,13 @@ public static Task WhenAll(IEnumerable> tasks) // Skip a List allocation/copy if tasks is a collection if (tasks is ICollection> taskCollection) { - taskArray = new Task[taskCollection.Count]; + int count = taskCollection.Count; + if (count == 0) + { + return new Task(false, Array.Empty(), TaskCreationOptions.None, default); + } + + taskArray = new Task[count]; taskCollection.CopyTo(taskArray, 0); foreach (Task task in taskArray) { @@ -6181,20 +6207,30 @@ public static Task WhenAll(IEnumerable> tasks) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks); } } - return InternalWhenAll(taskArray); + + return new WhenAllPromise(taskArray); } // Do some argument checking and convert tasks into a List (later an array) - if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); + if (tasks is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); + } + List> taskList = new List>(); foreach (Task task in tasks) { - if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks); + if (task is null) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks); + } + taskList.Add(task); } - // Delegate the rest to InternalWhenAll(). - return InternalWhenAll(taskList.ToArray()); + return taskList.Count == 0 ? + new Task(false, Array.Empty(), TaskCreationOptions.None, default) : + new WhenAllPromise(taskList.ToArray()); } /// @@ -6229,13 +6265,49 @@ public static Task WhenAll(IEnumerable> tasks) /// public static Task WhenAll(params Task[] tasks) { - // Do some argument checking and make a defensive copy of the tasks array - if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); + if (tasks is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); + } - int taskCount = tasks.Length; - if (taskCount == 0) return InternalWhenAll(tasks); // small optimization in the case of an empty task array + return WhenAll((ReadOnlySpan>)tasks); + } + + /// + /// Creates a task that will complete when all of the supplied tasks have completed. + /// + /// The tasks to wait on for completion. + /// A task that represents the completion of all of the supplied tasks. + /// + /// + /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state, + /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks. + /// + /// + /// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state. + /// + /// + /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state. + /// The Result of the returned task will be set to an array containing all of the results of the + /// supplied tasks in the same order as they were provided (e.g. if the input tasks array contained t1, t2, t3, the output + /// task's Result will return an TResult[] where arr[0] == t1.Result, arr[1] == t2.Result, and arr[2] == t3.Result). + /// + /// + /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion + /// state before it's returned to the caller. The returned TResult[] will be an array of 0 elements. + /// + /// + /// + /// The array contained a null task. + /// + public static Task WhenAll(/*params*/ ReadOnlySpan> tasks) + { + if (tasks.IsEmpty) + { + return new Task(false, Array.Empty(), TaskCreationOptions.None, default); + } - Task[] tasksCopy = (Task[])tasks.Clone(); + Task[] tasksCopy = tasks.ToArray(); foreach (Task task in tasksCopy) { if (task is null) @@ -6244,17 +6316,7 @@ public static Task WhenAll(params Task[] tasks) } } - // Delegate the rest to InternalWhenAll() - return InternalWhenAll(tasksCopy); - } - - // Some common logic to support WhenAll methods - private static Task InternalWhenAll(Task[] tasks) - { - Debug.Assert(tasks != null, "Expected a non-null tasks array"); - return (tasks.Length == 0) ? // take shortcut if there are no tasks upon which to wait - new Task(false, Array.Empty(), TaskCreationOptions.None, default) : - new WhenAllPromise(tasks); + return new WhenAllPromise(tasksCopy); } // A Task that gets completed when all of its constituent tasks complete. @@ -6394,7 +6456,7 @@ public static Task WhenAny(params Task[] tasks) { ArgumentNullException.ThrowIfNull(tasks); - return WhenAny((ReadOnlySpan)tasks); + return WhenAnyCore((ReadOnlySpan)tasks); } /// @@ -6409,7 +6471,22 @@ public static Task WhenAny(params Task[] tasks) /// /// The array contained a null task, or was empty. /// - private static Task WhenAny(ReadOnlySpan tasks) where TTask : Task + public static Task WhenAny(/*params*/ ReadOnlySpan tasks) => + WhenAnyCore(tasks); + + /// + /// Creates a task that will complete when any of the supplied tasks have completed. + /// + /// The tasks to wait on for completion. + /// A task that represents the completion of one of the supplied tasks. The return Task's Result is the task that completed. + /// + /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state + /// with its Result set to the first task to complete. This is true even if the first task to complete ended in the Canceled or Faulted state. + /// + /// + /// The array contained a null task, or was empty. + /// + private static Task WhenAnyCore(ReadOnlySpan tasks) where TTask : Task { if (tasks.Length == 2) { @@ -6589,13 +6666,13 @@ private static Task WhenAny(IEnumerable tasks) where TTask { // Take a more efficient path if tasks is actually a list or an array. Arrays are a bit less common, // since if argument was strongly-typed as an array, it would have bound to the array-based overload. - if (tasks is List tasksAsList) + if (tasks.GetType() == typeof(List)) { - return WhenAny((ReadOnlySpan)CollectionsMarshal.AsSpan(tasksAsList)); + return WhenAnyCore((ReadOnlySpan)CollectionsMarshal.AsSpan(Unsafe.As>(tasks))); } if (tasks is TTask[] tasksAsArray) { - return WhenAny((ReadOnlySpan)tasksAsArray); + return WhenAnyCore((ReadOnlySpan)tasksAsArray); } int count = tasksAsCollection.Count; @@ -6663,9 +6740,24 @@ public static Task> WhenAny(params Task[] tasks) { ArgumentNullException.ThrowIfNull(tasks); - return WhenAny((ReadOnlySpan>)tasks); + return WhenAnyCore((ReadOnlySpan>)tasks); } + /// + /// Creates a task that will complete when any of the supplied tasks have completed. + /// + /// The tasks to wait on for completion. + /// A task that represents the completion of one of the supplied tasks. The return Task's Result is the task that completed. + /// + /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state + /// with its Result set to the first task to complete. This is true even if the first task to complete ended in the Canceled or Faulted state. + /// + /// + /// The array contained a null task, or was empty. + /// + public static Task> WhenAny(/*params*/ ReadOnlySpan> tasks) => + WhenAnyCore(tasks); + /// Creates a task that will complete when either of the supplied tasks have completed. /// The first task to wait on for completion. /// The second task to wait on for completion. diff --git a/src/libraries/System.Reflection.DispatchProxy/src/System.Reflection.DispatchProxy.csproj b/src/libraries/System.Reflection.DispatchProxy/src/System.Reflection.DispatchProxy.csproj index 2d021999f5869c..17c279ab521382 100644 --- a/src/libraries/System.Reflection.DispatchProxy/src/System.Reflection.DispatchProxy.csproj +++ b/src/libraries/System.Reflection.DispatchProxy/src/System.Reflection.DispatchProxy.csproj @@ -16,6 +16,7 @@ + diff --git a/src/libraries/System.Resources.Writer/src/System.Resources.Writer.csproj b/src/libraries/System.Resources.Writer/src/System.Resources.Writer.csproj index bbe21a704c7f81..b2e3aeb636444c 100644 --- a/src/libraries/System.Resources.Writer/src/System.Resources.Writer.csproj +++ b/src/libraries/System.Resources.Writer/src/System.Resources.Writer.csproj @@ -20,6 +20,7 @@ + diff --git a/src/libraries/System.Runtime.Serialization.Primitives/src/System.Runtime.Serialization.Primitives.csproj b/src/libraries/System.Runtime.Serialization.Primitives/src/System.Runtime.Serialization.Primitives.csproj index 08ff96e95af3e1..ca2ed33befc50b 100644 --- a/src/libraries/System.Runtime.Serialization.Primitives/src/System.Runtime.Serialization.Primitives.csproj +++ b/src/libraries/System.Runtime.Serialization.Primitives/src/System.Runtime.Serialization.Primitives.csproj @@ -22,6 +22,7 @@ + diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 1080983cb9bb2c..14575b820c33ab 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -2163,6 +2163,7 @@ protected Delegate([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAt [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute("b")] public static System.Delegate? Combine(System.Delegate? a, System.Delegate? b) { throw null; } public static System.Delegate? Combine(params System.Delegate?[]? delegates) { throw null; } + public static System.Delegate? Combine(System.ReadOnlySpan delegates) { throw null; } protected virtual System.Delegate CombineImpl(System.Delegate? d) { throw null; } public static System.Delegate CreateDelegate(System.Type type, object? firstArgument, System.Reflection.MethodInfo method) { throw null; } public static System.Delegate? CreateDelegate(System.Type type, object? firstArgument, System.Reflection.MethodInfo method, bool throwOnBindFailure) { throw null; } @@ -5242,6 +5243,7 @@ public unsafe String(sbyte* value, int startIndex, int length, System.Text.Encod public static string Concat(object? arg0, object? arg1) { throw null; } public static string Concat(object? arg0, object? arg1, object? arg2) { throw null; } public static string Concat(params object?[] args) { throw null; } + public static string Concat(System.ReadOnlySpan args) { throw null; } public static string Concat(System.ReadOnlySpan str0, System.ReadOnlySpan str1) { throw null; } public static string Concat(System.ReadOnlySpan str0, System.ReadOnlySpan str1, System.ReadOnlySpan str2) { throw null; } public static string Concat(System.ReadOnlySpan str0, System.ReadOnlySpan str1, System.ReadOnlySpan str2, System.ReadOnlySpan str3) { throw null; } @@ -5249,6 +5251,7 @@ public unsafe String(sbyte* value, int startIndex, int length, System.Text.Encod public static string Concat(string? str0, string? str1, string? str2) { throw null; } public static string Concat(string? str0, string? str1, string? str2, string? str3) { throw null; } public static string Concat(params string?[] values) { throw null; } + public static string Concat(System.ReadOnlySpan values) { throw null; } public static string Concat(System.Collections.Generic.IEnumerable values) { throw null; } public bool Contains(char value) { throw null; } public bool Contains(char value, System.StringComparison comparisonType) { throw null; } @@ -5276,12 +5279,14 @@ public void CopyTo(System.Span destination) { } public static string Format(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { throw null; } public static string Format(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { throw null; } public static string Format(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] args) { throw null; } + public static string Format(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, System.ReadOnlySpan args) { throw null; } public static string Format(System.IFormatProvider? provider, System.Text.CompositeFormat format, params object?[] args) { throw null; } public static string Format(System.IFormatProvider? provider, System.Text.CompositeFormat format, System.ReadOnlySpan args) { throw null; } public static string Format([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0) { throw null; } public static string Format([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { throw null; } public static string Format([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { throw null; } public static string Format([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] args) { throw null; } + public static string Format([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, System.ReadOnlySpan args) { throw null; } public static string Format(System.IFormatProvider? provider, System.Text.CompositeFormat format, TArg0 arg0) { throw null; } public static string Format(System.IFormatProvider? provider, System.Text.CompositeFormat format, TArg0 arg0, TArg1 arg1) { throw null; } public static string Format(System.IFormatProvider? provider, System.Text.CompositeFormat format, TArg0 arg0, TArg1 arg1, TArg2 arg2) { throw null; } @@ -5314,11 +5319,15 @@ public void CopyTo(System.Span destination) { } public static bool IsNullOrEmpty([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] string? value) { throw null; } public static bool IsNullOrWhiteSpace([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] string? value) { throw null; } public static string Join(char separator, params object?[] values) { throw null; } + public static string Join(char separator, System.ReadOnlySpan values) { throw null; } public static string Join(char separator, params string?[] value) { throw null; } + public static string Join(char separator, System.ReadOnlySpan value) { throw null; } public static string Join(char separator, string?[] value, int startIndex, int count) { throw null; } public static string Join(string? separator, System.Collections.Generic.IEnumerable values) { throw null; } public static string Join(string? separator, params object?[] values) { throw null; } + public static string Join(string? separator, System.ReadOnlySpan values) { throw null; } public static string Join(string? separator, params string?[] value) { throw null; } + public static string Join(string? separator, System.ReadOnlySpan value) { throw null; } public static string Join(string? separator, string?[] value, int startIndex, int count) { throw null; } public static string Join(char separator, System.Collections.Generic.IEnumerable values) { throw null; } public static string Join(string? separator, System.Collections.Generic.IEnumerable values) { throw null; } @@ -5354,6 +5363,7 @@ public void CopyTo(System.Span destination) { } public string[] Split(char separator, int count, System.StringSplitOptions options = System.StringSplitOptions.None) { throw null; } public string[] Split(char separator, System.StringSplitOptions options = System.StringSplitOptions.None) { throw null; } public string[] Split(params char[]? separator) { throw null; } + public string[] Split(System.ReadOnlySpan separator) { throw null; } public string[] Split(char[]? separator, int count) { throw null; } public string[] Split(char[]? separator, int count, System.StringSplitOptions options) { throw null; } public string[] Split(char[]? separator, System.StringSplitOptions options) { throw null; } @@ -5401,12 +5411,15 @@ public void CopyTo(System.Span destination) { } public string Trim() { throw null; } public string Trim(char trimChar) { throw null; } public string Trim(params char[]? trimChars) { throw null; } + public string Trim(System.ReadOnlySpan trimChars) { throw null; } public string TrimEnd() { throw null; } public string TrimEnd(char trimChar) { throw null; } public string TrimEnd(params char[]? trimChars) { throw null; } + public string TrimEnd(System.ReadOnlySpan trimChars) { throw null; } public string TrimStart() { throw null; } public string TrimStart(char trimChar) { throw null; } public string TrimStart(params char[]? trimChars) { throw null; } + public string TrimStart(System.ReadOnlySpan trimChars) { throw null; } public bool TryCopyTo(System.Span destination) { throw null; } } public abstract partial class StringComparer : System.Collections.Generic.IComparer, System.Collections.Generic.IEqualityComparer, System.Collections.IComparer, System.Collections.IEqualityComparer @@ -7527,6 +7540,7 @@ public override void Write(string? s) { } public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0) { } public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] arg) { } + public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, System.ReadOnlySpan arg) { } public override System.Threading.Tasks.Task WriteAsync(char value) { throw null; } public override System.Threading.Tasks.Task WriteAsync(char[] buffer, int index, int count) { throw null; } public override System.Threading.Tasks.Task WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } @@ -7546,6 +7560,7 @@ public override void WriteLine(string? s) { } public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0) { } public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] arg) { } + public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, System.ReadOnlySpan arg) { } [System.CLSCompliantAttribute(false)] public override void WriteLine(uint value) { } public override System.Threading.Tasks.Task WriteLineAsync() { throw null; } @@ -10112,6 +10127,7 @@ public static partial class Path public static string Combine(string path1, string path2, string path3) { throw null; } public static string Combine(string path1, string path2, string path3, string path4) { throw null; } public static string Combine(params string[] paths) { throw null; } + public static string Combine(System.ReadOnlySpan paths) { throw null; } public static bool EndsInDirectorySeparator(System.ReadOnlySpan path) { throw null; } public static bool EndsInDirectorySeparator([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? path) { throw null; } public static bool Exists([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? path) { throw null; } @@ -10149,6 +10165,7 @@ public static partial class Path public static string Join(string? path1, string? path2, string? path3) { throw null; } public static string Join(string? path1, string? path2, string? path3, string? path4) { throw null; } public static string Join(params string?[] paths) { throw null; } + public static string Join(System.ReadOnlySpan paths) { throw null; } public static System.ReadOnlySpan TrimEndingDirectorySeparator(System.ReadOnlySpan path) { throw null; } public static string TrimEndingDirectorySeparator(string path) { throw null; } public static bool TryJoin(System.ReadOnlySpan path1, System.ReadOnlySpan path2, System.ReadOnlySpan path3, System.Span destination, out int charsWritten) { throw null; } @@ -10315,6 +10332,7 @@ public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribut public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { } public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] arg) { } + public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, System.ReadOnlySpan arg) { } public override System.Threading.Tasks.Task WriteAsync(char value) { throw null; } public override System.Threading.Tasks.Task WriteAsync(char[] buffer, int index, int count) { throw null; } public override System.Threading.Tasks.Task WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } @@ -10325,6 +10343,7 @@ public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttr public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { } public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] arg) { } + public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, System.ReadOnlySpan arg) { } public override System.Threading.Tasks.Task WriteLineAsync() { throw null; } public override System.Threading.Tasks.Task WriteLineAsync(char value) { throw null; } public override System.Threading.Tasks.Task WriteLineAsync(char[] buffer, int index, int count) { throw null; } @@ -10442,6 +10461,7 @@ public virtual void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute public virtual void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public virtual void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { } public virtual void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] arg) { } + public virtual void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, System.ReadOnlySpan arg) { } public virtual void Write(System.Text.StringBuilder? value) { } [System.CLSCompliantAttribute(false)] public virtual void Write(uint value) { } @@ -10470,6 +10490,7 @@ public virtual void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttri public virtual void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public virtual void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { } public virtual void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] arg) { } + public virtual void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, System.ReadOnlySpan arg) { } public virtual void WriteLine(System.Text.StringBuilder? value) { } [System.CLSCompliantAttribute(false)] public virtual void WriteLine(uint value) { } @@ -14915,19 +14936,25 @@ public StringBuilder(string? value, int startIndex, int length, int capacity) { public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { throw null; } public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { throw null; } public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] args) { throw null; } + public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, System.ReadOnlySpan args) { throw null; } public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, System.Text.CompositeFormat format, params object?[] args) { throw null; } public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, System.Text.CompositeFormat format, System.ReadOnlySpan args) { throw null; } public System.Text.StringBuilder AppendFormat([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0) { throw null; } public System.Text.StringBuilder AppendFormat([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { throw null; } public System.Text.StringBuilder AppendFormat([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { throw null; } public System.Text.StringBuilder AppendFormat([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] args) { throw null; } + public System.Text.StringBuilder AppendFormat([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, System.ReadOnlySpan args) { throw null; } public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, System.Text.CompositeFormat format, TArg0 arg0) { throw null; } public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, System.Text.CompositeFormat format, TArg0 arg0, TArg1 arg1) { throw null; } public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, System.Text.CompositeFormat format, TArg0 arg0, TArg1 arg1, TArg2 arg2) { throw null; } public System.Text.StringBuilder AppendJoin(char separator, params object?[] values) { throw null; } public System.Text.StringBuilder AppendJoin(char separator, params string?[] values) { throw null; } + public System.Text.StringBuilder AppendJoin(char separator, System.ReadOnlySpan values) { throw null; } + public System.Text.StringBuilder AppendJoin(char separator, System.ReadOnlySpan values) { throw null; } public System.Text.StringBuilder AppendJoin(string? separator, params object?[] values) { throw null; } public System.Text.StringBuilder AppendJoin(string? separator, params string?[] values) { throw null; } + public System.Text.StringBuilder AppendJoin(string? separator, System.ReadOnlySpan values) { throw null; } + public System.Text.StringBuilder AppendJoin(string? separator, System.ReadOnlySpan values) { throw null; } public System.Text.StringBuilder AppendJoin(char separator, System.Collections.Generic.IEnumerable values) { throw null; } public System.Text.StringBuilder AppendJoin(string? separator, System.Collections.Generic.IEnumerable values) { throw null; } public System.Text.StringBuilder AppendLine() { throw null; } @@ -15103,6 +15130,7 @@ public void CancelAfter(System.TimeSpan delay) { } public System.Threading.Tasks.Task CancelAsync() { throw null; } public static System.Threading.CancellationTokenSource CreateLinkedTokenSource(System.Threading.CancellationToken token) { throw null; } public static System.Threading.CancellationTokenSource CreateLinkedTokenSource(System.Threading.CancellationToken token1, System.Threading.CancellationToken token2) { throw null; } + public static System.Threading.CancellationTokenSource CreateLinkedTokenSource(System.ReadOnlySpan tokens) { throw null; } public static System.Threading.CancellationTokenSource CreateLinkedTokenSource(params System.Threading.CancellationToken[] tokens) { throw null; } public void Dispose() { } protected virtual void Dispose(bool disposing) { } @@ -15309,6 +15337,8 @@ public void Wait(System.Threading.CancellationToken cancellationToken) { } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public static void WaitAll(System.Collections.Generic.IEnumerable tasks, System.Threading.CancellationToken cancellationToken = default) { } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public static void WaitAll(System.ReadOnlySpan tasks) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public static void WaitAll(params System.Threading.Tasks.Task[] tasks) { } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public static bool WaitAll(System.Threading.Tasks.Task[] tasks, int millisecondsTimeout) { throw null; } @@ -15329,14 +15359,18 @@ public static void WaitAll(System.Threading.Tasks.Task[] tasks, System.Threading public System.Threading.Tasks.Task WaitAsync(System.TimeSpan timeout, System.TimeProvider timeProvider) { throw null; } public System.Threading.Tasks.Task WaitAsync(System.TimeSpan timeout, System.TimeProvider timeProvider, System.Threading.CancellationToken cancellationToken) { throw null; } public static System.Threading.Tasks.Task WhenAll(System.Collections.Generic.IEnumerable tasks) { throw null; } + public static System.Threading.Tasks.Task WhenAll(System.ReadOnlySpan tasks) { throw null; } public static System.Threading.Tasks.Task WhenAll(params System.Threading.Tasks.Task[] tasks) { throw null; } public static System.Threading.Tasks.Task WhenAll(System.Collections.Generic.IEnumerable> tasks) { throw null; } + public static System.Threading.Tasks.Task WhenAll(System.ReadOnlySpan> tasks) { throw null; } public static System.Threading.Tasks.Task WhenAll(params System.Threading.Tasks.Task[] tasks) { throw null; } public static System.Threading.Tasks.Task WhenAny(System.Collections.Generic.IEnumerable tasks) { throw null; } public static System.Threading.Tasks.Task WhenAny(System.Threading.Tasks.Task task1, System.Threading.Tasks.Task task2) { throw null; } + public static System.Threading.Tasks.Task WhenAny(System.ReadOnlySpan tasks) { throw null; } public static System.Threading.Tasks.Task WhenAny(params System.Threading.Tasks.Task[] tasks) { throw null; } public static System.Threading.Tasks.Task> WhenAny(System.Collections.Generic.IEnumerable> tasks) { throw null; } public static System.Threading.Tasks.Task> WhenAny(System.Threading.Tasks.Task task1, System.Threading.Tasks.Task task2) { throw null; } + public static System.Threading.Tasks.Task> WhenAny(System.ReadOnlySpan> tasks) { throw null; } public static System.Threading.Tasks.Task> WhenAny(params System.Threading.Tasks.Task[] tasks) { throw null; } public static System.Collections.Generic.IAsyncEnumerable WhenEach(System.Collections.Generic.IEnumerable tasks) { throw null; } public static System.Collections.Generic.IAsyncEnumerable WhenEach(params System.Threading.Tasks.Task[] tasks) { throw null; } diff --git a/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.regclass.cs b/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.regclass.cs index 4ab40934105281..6cf3503569751f 100644 --- a/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.regclass.cs +++ b/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.regclass.cs @@ -714,7 +714,9 @@ public static void CalledFrom_UsingExpression() { using (StreamWriter sw = new StreamWriter(sm)) { +#pragma warning disable CS9220 // One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. sw.WriteLine(mc.Method_ReturnString('a')); +#pragma warning restore CS9220 sw.Flush(); sm.Position = 0; using (StreamReader sr = new StreamReader(sm, (bool)mc.Method_ReturnBool())) diff --git a/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Operators.basic.cs b/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Operators.basic.cs index 1230648a1f443b..5d5933aaf4eea2 100644 --- a/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Operators.basic.cs +++ b/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Operators.basic.cs @@ -1169,7 +1169,9 @@ public static void ExecPositiveTest(dynamic dobj, Type exp_type, T exp_underv } else { +#pragma warning disable CS9220 // One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. System.Console.WriteLine("Got invalid result when testing {0}: {1}[{2}]", tip, dr, dr.GetType()); +#pragma warning restore CS9220 } } catch (Exception ex) @@ -1186,7 +1188,9 @@ public static void ExecNegativeTestWithBadOps(dynamic dobj, string[] exp_msg, st try { dynamic dr = test(dobj); +#pragma warning disable CS9220 // One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. System.Console.WriteLine("Got invalid result when testing {0}: {1}[{2}]", tip, dr, dr.GetType()); +#pragma warning restore CS9220 } catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex) { diff --git a/src/libraries/System.Runtime/tests/System.IO.Tests/IndentedTextWriter.cs b/src/libraries/System.Runtime/tests/System.IO.Tests/IndentedTextWriter.cs index 0de5d90f77bbdb..84ebd066786a22 100644 --- a/src/libraries/System.Runtime/tests/System.IO.Tests/IndentedTextWriter.cs +++ b/src/libraries/System.Runtime/tests/System.IO.Tests/IndentedTextWriter.cs @@ -104,6 +104,12 @@ public override void Write(string format, params object[] arg) LastCalledMethod = nameof(Write); } + public override void Write(string format, /*params*/ ReadOnlySpan arg) + { + base.Write(format, arg); + LastCalledMethod = nameof(Write); + } + public override void Write(string value) { base.Write(value); @@ -212,6 +218,12 @@ public override void WriteLine(string format, params object[] arg) LastCalledMethod = nameof(WriteLine); } + public override void WriteLine(string format, /*params*/ ReadOnlySpan arg) + { + base.WriteLine(format, arg); + LastCalledMethod = nameof(WriteLine); + } + public override void WriteLine(string value) { base.WriteLine(value); @@ -416,7 +428,8 @@ public static async Task Writes_ProducesExpectedOutput(string newline) itw.Write("{0}", 14); itw.Write("{0} {1}", 15, 16); itw.Write("{0} {1} {2}", 15, 16, 17); - itw.Write("{0} {1} {2} {3}", 15, 16, 17, 18); + itw.Write("{0} {1} {2} {3}", new object[] { 15, 16, 17, 18 }); + itw.Write("{0} {1} {2} {3}", (ReadOnlySpan)new object[] { 15, 16, 17, 18 }); itw.WriteLine(true); itw.WriteLine('a'); @@ -434,7 +447,8 @@ public static async Task Writes_ProducesExpectedOutput(string newline) itw.WriteLine("{0}", 14); itw.WriteLine("{0} {1}", 15, 16); itw.WriteLine("{0} {1} {2}", 15, 16, 17); - itw.WriteLine("{0} {1} {2} {3}", 15, 16, 17, 18); + itw.WriteLine("{0} {1} {2} {3}", new object[] { 15, 16, 17, 18 }); + itw.WriteLine("{0} {1} {2} {3}", (ReadOnlySpan)new object[] { 15, 16, 17, 18 }); await itw.WriteAsync('a'); await itw.WriteAsync(new char[] { 'b', 'c' }); @@ -450,7 +464,7 @@ public static async Task Writes_ProducesExpectedOutput(string newline) Assert.Equal( "t" + newline + - "tTrueabcde45.66.789101112131415 1615 16 1715 16 17 18True" + newline + + "tTrueabcde45.66.789101112131415 1615 16 1715 16 17 1815 16 17 18True" + newline + "ta" + newline + "tbc" + newline + "tde" + newline + @@ -467,6 +481,7 @@ public static async Task Writes_ProducesExpectedOutput(string newline) "t15 16" + newline + "t15 16 17" + newline + "t15 16 17 18" + newline + + "t15 16 17 18" + newline + "tabcde1a" + newline + "tbc" + newline + "tde" + newline + @@ -499,7 +514,8 @@ object[] CreateParameters(Action callWrite, string expected) yield return CreateParameters(x => x.Write("Hello {0} World", "Digital"), "Hello Digital World"); yield return CreateParameters(x => x.Write("Hello {0} World{1}", "Digital", "!!"), "Hello Digital World!!"); yield return CreateParameters(x => x.Write("Hello {0} {1} World{2}", "Dot", "NET", "!!"), "Hello Dot NET World!!"); - yield return CreateParameters(x => x.Write("Hello {0} {1} {2} World{3}", "Digital", "Dot", "NET", "!!"), "Hello Digital Dot NET World!!"); + yield return CreateParameters(x => x.Write("Hello {0} {1} {2} World{3}", new object[] { "Digital", "Dot", "NET", "!!" }), "Hello Digital Dot NET World!!"); + yield return CreateParameters(x => x.Write("Hello {0} {1} {2} World{3}", (ReadOnlySpan)new object[] { "Digital", "Dot", "NET", "!!" }), "Hello Digital Dot NET World!!"); yield return CreateParameters(x => x.Write("Hello World".ToCharArray(), 6, 5), "World"); } } @@ -530,7 +546,8 @@ object[] CreateParameters(Action callWriteLine, string expec yield return CreateParameters(x => x.WriteLine("Hello {0} {1} World", "Dot", "NET"), $"Hello Dot NET World{NewLine}"); yield return CreateParameters(x => x.WriteLine("Hello {0} {1} World{2}", "Dot", "NET", "!!"), $"Hello Dot NET World!!{NewLine}"); yield return CreateParameters(x => x.WriteLine("Hello World".ToCharArray(), 6, 5), $"World{NewLine}"); - yield return CreateParameters(x => x.WriteLine("Hello {0} {1} {2} World{3}", "Digital", "Dot", "NET", "!!"), $"Hello Digital Dot NET World!!{NewLine}"); + yield return CreateParameters(x => x.WriteLine("Hello {0} {1} {2} World{3}", new object[] { "Digital", "Dot", "NET", "!!" }), $"Hello Digital Dot NET World!!{NewLine}"); + yield return CreateParameters(x => x.WriteLine("Hello {0} {1} {2} World{3}", (ReadOnlySpan)new object[] { "Digital", "Dot", "NET", "!!" }), $"Hello Digital Dot NET World!!{NewLine}"); } } diff --git a/src/libraries/System.Runtime/tests/System.IO.Tests/Stream/Stream.NullTests.cs b/src/libraries/System.Runtime/tests/System.IO.Tests/Stream/Stream.NullTests.cs index 86ebfba5efbefb..3714ff3b2020dc 100644 --- a/src/libraries/System.Runtime/tests/System.IO.Tests/Stream/Stream.NullTests.cs +++ b/src/libraries/System.Runtime/tests/System.IO.Tests/Stream/Stream.NullTests.cs @@ -234,7 +234,8 @@ public static void TextNullTextWriter(TextWriter output) output.Write(" {0} ", "Friday"); output.Write(" {0}{1} ", "Saturday", "Sunday"); output.Write(" {0} {1} {2}", TimeSpan.FromSeconds(1), TimeSpan.FromMinutes(2), TimeSpan.FromDays(3)); - output.Write(" {0} {1} {2} {3}", (Int128)4, (UInt128)5, (nint)6, (nuint)7); + output.Write(" {0} {1} {2} {3}", new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7 }); + output.Write(" {0} {1} {2} {3} {4}", (ReadOnlySpan)new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7, "8" }); output.WriteLine(); output.WriteLine(true); output.WriteLine('a'); @@ -256,7 +257,8 @@ public static void TextNullTextWriter(TextWriter output) output.WriteLine(" {0} ", "Friday"); output.WriteLine(" {0}{1} ", "Saturday", "Sunday"); output.WriteLine(" {0} {1} {2}", TimeSpan.FromSeconds(1), TimeSpan.FromMinutes(2), TimeSpan.FromDays(3)); - output.WriteLine(" {0} {1} {2} {3}", (Int128)4, (UInt128)5, (nint)6, (nuint)7); + output.WriteLine(" {0} {1} {2} {3}", new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7 }); + output.WriteLine(" {0} {1} {2} {3} {4}", (ReadOnlySpan)new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7, "8" }); Assert.True(output.WriteAsync('a').IsCompletedSuccessfully); Assert.True(output.WriteAsync((char[])null).IsCompletedSuccessfully); Assert.True(output.WriteAsync(new char[] { 'b', 'c' }).IsCompletedSuccessfully); diff --git a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.cs b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.cs index 0d34fe6730f0ac..69edb13a8a1fce 100644 --- a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.cs +++ b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.cs @@ -58,20 +58,28 @@ public void FormatOverloadsCallWrite() Assert.Equal(2, writer.WriteCalls); writer.Write("{0}{1}{2}", "Zero", "One", "Two"); Assert.Equal(3, writer.WriteCalls); - writer.Write("{0}{1}{2}{3}", "Zero", "One", "Two", "Three"); + writer.Write("{0}{1}{2}{3}", new object[] { "Zero", "One", "Two", "Three" }); Assert.Equal(4, writer.WriteCalls); - writer.Write("{0}{1}{2}{3}{4}", "Zero", "One", "Two", "Three", "Four"); + writer.Write("{0}{1}{2}{3}", (ReadOnlySpan)new object[] { "Zero", "One", "Two", "Three" }); Assert.Equal(5, writer.WriteCalls); + writer.Write("{0}{1}{2}{3}{4}", new object[] { "Zero", "One", "Two", "Three", "Four" }); + Assert.Equal(6, writer.WriteCalls); + writer.Write("{0}{1}{2}{3}{4}", (ReadOnlySpan)new object[] { "Zero", "One", "Two", "Three", "Four" }); + Assert.Equal(7, writer.WriteCalls); writer.WriteLine("{0}", "Zero"); Assert.Equal(1, writer.WriteLineCalls); writer.WriteLine("{0}{1}", "Zero", "One"); Assert.Equal(2, writer.WriteLineCalls); writer.WriteLine("{0}{1}{2}", "Zero", "One", "Two"); Assert.Equal(3, writer.WriteLineCalls); - writer.WriteLine("{0}{1}{2}{3}", "Zero", "One", "Two", "Three"); + writer.WriteLine("{0}{1}{2}{3}", new object[] { "Zero", "One", "Two", "Three" }); Assert.Equal(4, writer.WriteLineCalls); - writer.WriteLine("{0}{1}{2}{3}{4}", "Zero", "One", "Two", "Three", "Four"); + writer.WriteLine("{0}{1}{2}{3}", (ReadOnlySpan)new object[] { "Zero", "One", "Two", "Three" }); Assert.Equal(5, writer.WriteLineCalls); + writer.WriteLine("{0}{1}{2}{3}{4}", new object[] { "Zero", "One", "Two", "Three", "Four" }); + Assert.Equal(6, writer.WriteLineCalls); + writer.WriteLine("{0}{1}{2}{3}{4}", (ReadOnlySpan)new object[] { "Zero", "One", "Two", "Three", "Four" }); + Assert.Equal(7, writer.WriteLineCalls); } } } diff --git a/src/libraries/System.Runtime/tests/System.IO.Tests/TextWriter/TextWriterTests.cs b/src/libraries/System.Runtime/tests/System.IO.Tests/TextWriter/TextWriterTests.cs index de3ed9530a1ee2..2299dc86f567db 100644 --- a/src/libraries/System.Runtime/tests/System.IO.Tests/TextWriter/TextWriterTests.cs +++ b/src/libraries/System.Runtime/tests/System.IO.Tests/TextWriter/TextWriterTests.cs @@ -226,15 +226,24 @@ public void WriteStringThreeObjectsTest() } [Fact] - public void WriteStringMultipleObjectsTest() + public void WriteStringMultipleObjectsArrayTest() { using (CharArrayTextWriter tw = NewTextWriter) { - tw.Write(TestDataProvider.FormatStringMultipleObjects, TestDataProvider.MultipleObjects); + tw.Write(TestDataProvider.FormatStringMultipleObjects, (object[])TestDataProvider.MultipleObjects); Assert.Equal(string.Format(TestDataProvider.FormatStringMultipleObjects, TestDataProvider.MultipleObjects), tw.Text); } } + [Fact] + public void WriteStringMultipleObjectsSpanTest() + { + using (CharArrayTextWriter tw = NewTextWriter) + { + tw.Write(TestDataProvider.FormatStringMultipleObjects, (ReadOnlySpan)TestDataProvider.MultipleObjects); + Assert.Equal(string.Format(TestDataProvider.FormatStringMultipleObjects, TestDataProvider.MultipleObjects), tw.Text); + } + } #endregion #region WriteLine Overloads @@ -454,11 +463,21 @@ public void WriteLineStringThreeObjectsTest() } [Fact] - public void WriteLineStringMultipleObjectsTest() + public void WriteLineStringMultipleObjectsArrayTest() { using (CharArrayTextWriter tw = NewTextWriter) { - tw.WriteLine(TestDataProvider.FormatStringMultipleObjects, TestDataProvider.MultipleObjects); + tw.WriteLine(TestDataProvider.FormatStringMultipleObjects, (object[])TestDataProvider.MultipleObjects); + Assert.Equal(string.Format(TestDataProvider.FormatStringMultipleObjects + tw.NewLine, TestDataProvider.MultipleObjects), tw.Text); + } + } + + [Fact] + public void WriteLineStringMultipleObjectsSpanTest() + { + using (CharArrayTextWriter tw = NewTextWriter) + { + tw.WriteLine(TestDataProvider.FormatStringMultipleObjects, (ReadOnlySpan)TestDataProvider.MultipleObjects); Assert.Equal(string.Format(TestDataProvider.FormatStringMultipleObjects + tw.NewLine, TestDataProvider.MultipleObjects), tw.Text); } } @@ -772,8 +791,11 @@ public async Task CreateBroadcasting_DelegatesToAllWriters() oracle.Write(" {0} {1} {2}", TimeSpan.FromSeconds(1), TimeSpan.FromMinutes(2), TimeSpan.FromDays(3)); broadcasting.Write(" {0} {1} {2}", TimeSpan.FromSeconds(1), TimeSpan.FromMinutes(2), TimeSpan.FromDays(3)); - oracle.Write(" {0} {1} {2} {3}", (Int128)4, (UInt128)5, (nint)6, (nuint)7); - broadcasting.Write(" {0} {1} {2} {3}", (Int128)4, (UInt128)5, (nint)6, (nuint)7); + oracle.Write(" {0} {1} {2} {3}", new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7 }); + broadcasting.Write(" {0} {1} {2} {3}", new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7 }); + + oracle.Write(" {0} {1} {2} {3} {4}", (ReadOnlySpan)new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7, "8" }); + broadcasting.Write(" {0} {1} {2} {3} {4}", (ReadOnlySpan)new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7, "8" }); oracle.WriteLine(); broadcasting.WriteLine(); @@ -835,8 +857,11 @@ public async Task CreateBroadcasting_DelegatesToAllWriters() oracle.WriteLine(" {0} {1} {2}", TimeSpan.FromSeconds(1), TimeSpan.FromMinutes(2), TimeSpan.FromDays(3)); broadcasting.WriteLine(" {0} {1} {2}", TimeSpan.FromSeconds(1), TimeSpan.FromMinutes(2), TimeSpan.FromDays(3)); - oracle.WriteLine(" {0} {1} {2} {3}", (Int128)4, (UInt128)5, (nint)6, (nuint)7); - broadcasting.WriteLine(" {0} {1} {2} {3}", (Int128)4, (UInt128)5, (nint)6, (nuint)7); + oracle.WriteLine(" {0} {1} {2} {3}", new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7 }); + broadcasting.WriteLine(" {0} {1} {2} {3}", new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7 }); + + oracle.WriteLine(" {0} {1} {2} {3} {4}", (ReadOnlySpan)new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7, "8" }); + broadcasting.WriteLine(" {0} {1} {2} {3} {4}", (ReadOnlySpan)new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7, "8" }); await oracle.WriteAsync('a'); await broadcasting.WriteAsync('a'); diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Combine.cs b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Combine.cs index 033168ce649a17..9493d5aed543ab 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Combine.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Combine.cs @@ -98,6 +98,7 @@ public static void Combine(string[] paths) // Combine(string[]) Assert.Equal(expected, Path.Combine(paths)); + Assert.Equal(expected, Path.Combine((ReadOnlySpan)paths)); // Verify special cases switch (paths.Length) @@ -166,6 +167,10 @@ public static void ContainsInvalidCharWithRooted_Windows_core() private static void VerifyException(string[] paths) where T : Exception { Assert.Throws(() => Path.Combine(paths)); + if (paths != null) + { + Assert.Throws(() => Path.Combine((ReadOnlySpan)paths)); + } //verify passed as elements case if (paths != null) diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Join.cs b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Join.cs index 0984a9145385ac..f8b61049251fee 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Join.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Join.cs @@ -200,36 +200,42 @@ public void JoinStringArray_ThrowsArgumentNullException() public void JoinStringArray_ZeroLengthArray() { Assert.Equal(string.Empty, Path.Join(new string[0])); + Assert.Equal(string.Empty, Path.Join((ReadOnlySpan)new string[0])); } [Theory, MemberData(nameof(TestData_JoinOnePath))] public void JoinStringArray_1(string path1, string expected) { Assert.Equal(expected, Path.Join(new string[] { path1 })); + Assert.Equal(expected, Path.Join((ReadOnlySpan)new string[] { path1 })); } [Theory, MemberData(nameof(TestData_JoinTwoPaths))] public void JoinStringArray_2(string path1, string path2, string expected) { Assert.Equal(expected, Path.Join(new string[] { path1, path2 })); + Assert.Equal(expected, Path.Join((ReadOnlySpan)new string[] { path1, path2 })); } [Theory, MemberData(nameof(TestData_JoinThreePaths))] public void JoinStringArray_3(string path1, string path2, string path3, string expected) { Assert.Equal(expected, Path.Join(new string[] { path1, path2, path3 })); + Assert.Equal(expected, Path.Join((ReadOnlySpan)new string[] { path1, path2, path3 })); } [Theory, MemberData(nameof(TestData_JoinFourPaths))] public void JoinStringArray_4(string path1, string path2, string path3, string path4, string expected) { Assert.Equal(expected, Path.Join(new string[] { path1, path2, path3, path4 })); + Assert.Equal(expected, Path.Join((ReadOnlySpan)new string[] { path1, path2, path3, path4 })); } [Theory, MemberData(nameof(TestData_JoinFourPaths))] public void JoinStringArray_8(string path1, string path2, string path3, string path4, string fourJoined) { Assert.Equal(Path.Join(fourJoined, fourJoined), Path.Join(new string[] { path1, path2, path3, path4, path1, path2, path3, path4 })); + Assert.Equal(Path.Join(fourJoined, fourJoined), Path.Join((ReadOnlySpan)new string[] { path1, path2, path3, path4, path1, path2, path3, path4 })); } } } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/MulticastDelegateTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/MulticastDelegateTests.cs index 9994fa02f10fac..ab798d6442beb0 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/MulticastDelegateTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/MulticastDelegateTests.cs @@ -105,7 +105,19 @@ public static void Combine() D nothing = (D)(Delegate.Combine()); Assert.Null(nothing); - D one = (D)(Delegate.Combine(a)); + nothing = (D)(Delegate.Combine(null)); + Assert.Null(nothing); + + nothing = (D)(Delegate.Combine(ReadOnlySpan.Empty)); + Assert.Null(nothing); + + D one = (D)(Delegate.Combine(new[] { a })); + t1.Clear(); + one(5); + Assert.Equal("A5", t1.S); + CheckInvokeList(new D[] { a }, one, t1); + + one = (D)(Delegate.Combine((ReadOnlySpan)new[] { a })); t1.Clear(); one(5); Assert.Equal("A5", t1.S); @@ -117,13 +129,25 @@ public static void Combine() Assert.Equal("A5B5", t1.S); CheckInvokeList(new D[] { a, b }, ab, t1); - D abc = (D)(Delegate.Combine(a, b, c)); + D abc = (D)(Delegate.Combine(new[] { a, b, c })); t1.Clear(); abc(5); Assert.Equal("A5B5C5", t1.S); CheckInvokeList(new D[] { a, b, c }, abc, t1); - D abcdabc = (D)(Delegate.Combine(abc, d, abc)); + abc = (D)(Delegate.Combine((ReadOnlySpan)new[] { a, b, c })); + t1.Clear(); + abc(5); + Assert.Equal("A5B5C5", t1.S); + CheckInvokeList(new D[] { a, b, c }, abc, t1); + + D abcdabc = (D)(Delegate.Combine(new[] { abc, d, abc })); + t1.Clear(); + abcdabc(9); + Assert.Equal("A9B9C9D9A9B9C9", t1.S); + CheckInvokeList(new D[] { a, b, c, d, a, b, c }, abcdabc, t1); + + abcdabc = (D)(Delegate.Combine((ReadOnlySpan)new[] { abc, d, abc })); t1.Clear(); abcdabc(9); Assert.Equal("A9B9C9D9A9B9C9", t1.S); diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs index b12bd2cb74fc48..037e7a98a95878 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs @@ -141,6 +141,7 @@ public static void SplitNoMatchSingleResult() Assert.Equal(expected, Value.Split(',', Options)); Assert.Equal(expected, Value.Split(',', Count, Options)); Assert.Equal(expected, Value.Split(new[] { ',' })); + Assert.Equal(expected, Value.Split((ReadOnlySpan)new[] { ',' })); Assert.Equal(expected, Value.Split(new[] { ',' }, Options)); Assert.Equal(expected, Value.Split(new[] { ',' }, Count)); Assert.Equal(expected, Value.Split(new[] { ',' }, Count, Options)); @@ -516,6 +517,7 @@ public static void SplitCharSeparator(string value, char separator, int count, S { Assert.Equal(expected, value.Split(separator)); Assert.Equal(expected, value.Split(new[] { separator })); + Assert.Equal(expected, value.Split((ReadOnlySpan)new[] { separator })); Assert.Equal(expected, value.Split(separator.ToString())); } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/CompositeFormatTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/CompositeFormatTests.cs index bdfde206c850f4..64c0caf8f8c396 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/CompositeFormatTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/CompositeFormatTests.cs @@ -68,12 +68,15 @@ public static void MinimumArgumentCount_MatchesExpectedValue(string format, int Assert.Equal(expected, cf.MinimumArgumentCount); - string s = string.Format(null, cf, Enumerable.Repeat((object)"arg", expected).ToArray()); - Assert.NotNull(s); + object[] args = Enumerable.Repeat((object)"arg", expected).ToArray(); + Assert.NotNull(string.Format(null, cf, args)); + Assert.NotNull(string.Format(null, cf, (ReadOnlySpan)args)); if (expected != 0) { - Assert.Throws(() => string.Format(null, cf, Enumerable.Repeat((object)"arg", expected - 1).ToArray())); + args = Enumerable.Repeat((object)"arg", expected - 1).ToArray(); + Assert.Throws(() => string.Format(null, cf, args)); + Assert.Throws(() => string.Format(null, cf, (ReadOnlySpan)args)); } } @@ -86,21 +89,20 @@ public static void StringFormat_Valid(IFormatProvider provider, string format, o Assert.Same(format, cf.Format); Assert.Equal(expected, string.Format(provider, cf, values)); - - Assert.Equal(expected, string.Format(provider, cf, (ReadOnlySpan)values)); + Assert.Equal(expected, string.Format(provider, cf, (ReadOnlySpan)values)); switch (values.Length) { case 1: - Assert.Equal(expected, string.Format(provider, cf, values[0])); + Assert.Equal(expected, string.Format(provider, cf, arg0: values[0])); break; case 2: - Assert.Equal(expected, string.Format(provider, cf, values[0], values[1])); + Assert.Equal(expected, string.Format(provider, cf, arg0: values[0], arg1: values[1])); break; case 3: - Assert.Equal(expected, string.Format(provider, cf, values[0], values[1], values[2])); + Assert.Equal(expected, string.Format(provider, cf, arg0: values[0], arg1: values[1], arg2: values[2])); break; } } @@ -188,6 +190,8 @@ public static void MemoryExtensionsTryWrite_Valid(IFormatProvider provider, stri dest = new char[expected.Length - 1]; Assert.False(dest.AsSpan().TryWrite(provider, cf, out charsWritten, values)); Assert.Equal(0, charsWritten); + Assert.False(dest.AsSpan().TryWrite(provider, cf, out charsWritten, (ReadOnlySpan)values)); + Assert.Equal(0, charsWritten); } } @@ -209,16 +213,17 @@ public static void StringFormat_Invalid_FormatExceptionFromArgs(IFormatProvider Assert.NotNull(cf); Assert.Throws(() => string.Format(provider, cf, args)); + Assert.Throws(() => string.Format(provider, cf, (ReadOnlySpan)args)); switch (args.Length) { case 1: - Assert.Throws(() => string.Format(provider, cf, args[0])); + Assert.Throws(() => string.Format(provider, cf, arg0: args[0])); break; case 2: - Assert.Throws(() => string.Format(provider, cf, args[0], args[1])); + Assert.Throws(() => string.Format(provider, cf, arg0: args[0], arg1: args[1])); break; case 3: - Assert.Throws(() => string.Format(provider, cf, args[0], args[1], args[2])); + Assert.Throws(() => string.Format(provider, cf, arg0: args[0], arg1: args[1], arg2: args[2])); break; } } @@ -233,16 +238,17 @@ public static void StringBuilderAppendFormat_Invalid_FormatExceptionFromArgs(IFo var sb = new StringBuilder(); Assert.Throws(() => sb.AppendFormat(provider, cf, args)); + Assert.Throws(() => sb.AppendFormat(provider, cf, (ReadOnlySpan)args)); switch (args.Length) { case 1: - Assert.Throws(() => sb.AppendFormat(provider, cf, args[0])); + Assert.Throws(() => sb.AppendFormat(provider, cf, arg0: args[0])); break; case 2: - Assert.Throws(() => sb.AppendFormat(provider, cf, args[0], args[1])); + Assert.Throws(() => sb.AppendFormat(provider, cf, arg0: args[0], arg1: args[1])); break; case 3: - Assert.Throws(() => sb.AppendFormat(provider, cf, args[0], args[1], args[2])); + Assert.Throws(() => sb.AppendFormat(provider, cf, arg0: args[0], arg1: args[1], arg2: args[2])); break; } } @@ -257,16 +263,17 @@ public static void MemoryExtensionsTryWrite_Invalid_FormatExceptionFromArgs(IFor char[] dest = new char[1024]; Assert.Throws(() => new Span(dest).TryWrite(provider, cf, out _, args)); + Assert.Throws(() => new Span(dest).TryWrite(provider, cf, out _, (ReadOnlySpan)args)); switch (args.Length) { case 1: Assert.Throws(() => new Span(dest).TryWrite(provider, cf, out _, args[0])); break; case 2: - Assert.Throws(() => new Span(dest).TryWrite(provider, cf, out _, args[0], args[1])); + Assert.Throws(() => new Span(dest).TryWrite(provider, cf, out _, arg0: args[0], arg1: args[1])); break; case 3: - Assert.Throws(() => new Span(dest).TryWrite(provider, cf, out _, args[0], args[1], args[2])); + Assert.Throws(() => new Span(dest).TryWrite(provider, cf, out _, arg0: args[0], arg1: args[1], arg2: args[2])); break; } } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/StringBuilderTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/StringBuilderTests.cs index 2d1f569dd103be..5671c6d3614e57 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/StringBuilderTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/StringBuilderTests.cs @@ -842,6 +842,19 @@ public static void AppendFormat(string original, IFormatProvider provider, strin builder = new StringBuilder(original); builder.AppendFormat(provider, format, values); Assert.Equal(expected, builder.ToString()); + + // Use AppendFormat(string, ReadOnlySpan) or AppendFormat(IFormatProvider, string, ReadOnlySpan) + if (provider == null) + { + // Use AppendFormat(string, ReadOnlySpan) + builder = new StringBuilder(original); + builder.AppendFormat(format, (ReadOnlySpan)values); + Assert.Equal(expected, builder.ToString()); + } + // Use AppendFormat(IFormatProvider, string, ReadOnlySpan) + builder = new StringBuilder(original); + builder.AppendFormat(provider, format, (ReadOnlySpan)values); + Assert.Equal(expected, builder.ToString()); } [Fact] @@ -855,17 +868,21 @@ public static void AppendFormat_Invalid() var obj2 = new object(); var obj3 = new object(); var obj4 = new object(); + var objArray = new object[] { obj1, obj2, obj3, obj4 }; AssertExtensions.Throws("format", () => builder.AppendFormat(null, obj1)); // Format is null AssertExtensions.Throws("format", () => builder.AppendFormat(null, obj1, obj2, obj3)); // Format is null - AssertExtensions.Throws("format", () => builder.AppendFormat(null, obj1, obj2, obj3)); // Format is null AssertExtensions.Throws("format", () => builder.AppendFormat(null, obj1, obj2, obj3, obj4)); // Format is null + AssertExtensions.Throws("format", () => builder.AppendFormat(null, objArray)); // Format is null + AssertExtensions.Throws("format", () => builder.AppendFormat(null, (ReadOnlySpan)objArray)); // Format is null AssertExtensions.Throws("args", () => builder.AppendFormat("", null)); // Args is null AssertExtensions.Throws("format", () => builder.AppendFormat(null, (object[])null)); // Both format and args are null AssertExtensions.Throws("format", () => builder.AppendFormat(formatter, (string)null, obj1)); // Format is null AssertExtensions.Throws("format", () => builder.AppendFormat(formatter, (string)null, obj1, obj2)); // Format is null AssertExtensions.Throws("format", () => builder.AppendFormat(formatter, (string)null, obj1, obj2, obj3)); // Format is null AssertExtensions.Throws("format", () => builder.AppendFormat(formatter, (string)null, obj1, obj2, obj3, obj4)); // Format is null + AssertExtensions.Throws("format", () => builder.AppendFormat(formatter, (string)null, objArray)); // Format is null + AssertExtensions.Throws("format", () => builder.AppendFormat(formatter, (string)null, (ReadOnlySpan)objArray)); // Format is null AssertExtensions.Throws("args", () => builder.AppendFormat(formatter, "", null)); // Args is null AssertExtensions.Throws("format", () => builder.AppendFormat(formatter, (string)null, null)); // Both format and args are null @@ -873,19 +890,27 @@ public static void AppendFormat_Invalid() Assert.Throws(() => builder.AppendFormat("{-1}", obj1, obj2)); // Format has value < 0 Assert.Throws(() => builder.AppendFormat("{-1}", obj1, obj2, obj3)); // Format has value < 0 Assert.Throws(() => builder.AppendFormat("{-1}", obj1, obj2, obj3, obj4)); // Format has value < 0 + Assert.Throws(() => builder.AppendFormat("{-1}", objArray)); // Format has value < 0 + Assert.Throws(() => builder.AppendFormat("{-1}", (ReadOnlySpan)objArray)); // Format has value < 0 Assert.Throws(() => builder.AppendFormat(formatter, "{-1}", obj1)); // Format has value < 0 Assert.Throws(() => builder.AppendFormat(formatter, "{-1}", obj1, obj2)); // Format has value < 0 Assert.Throws(() => builder.AppendFormat(formatter, "{-1}", obj1, obj2, obj3)); // Format has value < 0 Assert.Throws(() => builder.AppendFormat(formatter, "{-1}", obj1, obj2, obj3, obj4)); // Format has value < 0 + Assert.Throws(() => builder.AppendFormat(formatter, "{-1}", objArray)); // Format has value < 0 + Assert.Throws(() => builder.AppendFormat(formatter, "{-1}", (ReadOnlySpan)objArray)); // Format has value < 0 Assert.Throws(() => builder.AppendFormat("{1}", obj1)); // Format has value >= 1 Assert.Throws(() => builder.AppendFormat("{2}", obj1, obj2)); // Format has value >= 2 Assert.Throws(() => builder.AppendFormat("{3}", obj1, obj2, obj3)); // Format has value >= 3 Assert.Throws(() => builder.AppendFormat("{4}", obj1, obj2, obj3, obj4)); // Format has value >= 4 + Assert.Throws(() => builder.AppendFormat("{4}", objArray)); // Format has value >= 4 + Assert.Throws(() => builder.AppendFormat("{4}", (ReadOnlySpan)objArray)); // Format has value >= 4 Assert.Throws(() => builder.AppendFormat(formatter, "{1}", obj1)); // Format has value >= 1 Assert.Throws(() => builder.AppendFormat(formatter, "{2}", obj1, obj2)); // Format has value >= 2 Assert.Throws(() => builder.AppendFormat(formatter, "{3}", obj1, obj2, obj3)); // Format has value >= 3 Assert.Throws(() => builder.AppendFormat(formatter, "{4}", obj1, obj2, obj3, obj4)); // Format has value >= 4 + Assert.Throws(() => builder.AppendFormat(formatter, "{4}", objArray)); // Format has value >= 4 + Assert.Throws(() => builder.AppendFormat(formatter, "{4}", (ReadOnlySpan)objArray)); // Format has value >= 4 Assert.Throws(() => builder.AppendFormat("{", "")); // Format has unescaped { Assert.Throws(() => builder.AppendFormat("{a", "")); // Format has unescaped { @@ -900,7 +925,9 @@ public static void AppendFormat_Invalid() Assert.Throws(() => builder.AppendFormat("{0 ", "")); // Format with index and spaces is not closed Assert.Throws(() => builder.AppendFormat("{1000000", new string[10])); // Format index is too long + Assert.Throws(() => builder.AppendFormat("{1000000", (ReadOnlySpan)new string[10])); // Format index is too long Assert.Throws(() => builder.AppendFormat("{10000000}", new string[10])); // Format index is too long + Assert.Throws(() => builder.AppendFormat("{10000000}", (ReadOnlySpan)new string[10])); // Format index is too long Assert.Throws(() => builder.AppendFormat("{0,", "")); // Format with comma is not closed Assert.Throws(() => builder.AppendFormat("{0, ", "")); // Format with comma and spaces is not closed @@ -910,13 +937,19 @@ public static void AppendFormat_Invalid() Assert.Throws(() => builder.AppendFormat("{0,-a", "")); // Format has invalid character after minus sign Assert.Throws(() => builder.AppendFormat("{0,1000000", new string[10])); // Format length is too long + Assert.Throws(() => builder.AppendFormat("{0,1000000", (ReadOnlySpan)new string[10])); // Format length is too long Assert.Throws(() => builder.AppendFormat("{0,10000000}", new string[10])); // Format length is too long + Assert.Throws(() => builder.AppendFormat("{0,10000000}", (ReadOnlySpan)new string[10])); // Format length is too long Assert.Throws(() => builder.AppendFormat("{0:", new string[10])); // Format with colon is not closed + Assert.Throws(() => builder.AppendFormat("{0:", (ReadOnlySpan)new string[10])); // Format with colon is not closed Assert.Throws(() => builder.AppendFormat("{0: ", new string[10])); // Format with colon and spaces is not closed + Assert.Throws(() => builder.AppendFormat("{0: ", (ReadOnlySpan)new string[10])); // Format with colon and spaces is not closed Assert.Throws(() => builder.AppendFormat("{0:{", new string[10])); // Format with custom format contains unescaped { + Assert.Throws(() => builder.AppendFormat("{0:{", (ReadOnlySpan)new string[10])); // Format with custom format contains unescaped { Assert.Throws(() => builder.AppendFormat("{0:{}", new string[10])); // Format with custom format contains unescaped { + Assert.Throws(() => builder.AppendFormat("{0:{}", (ReadOnlySpan)new string[10])); // Format with custom format contains unescaped { Assert.Throws(() => builder.AppendFormat("{0}", new TooManyCharsWrittenSpanFormattable())); // ISpanFormattable that returns more characters than it actually wrote } @@ -1775,11 +1808,15 @@ public static void AppendJoin_TestValues(object[] values, string expected) var enumerable = values.Select(_ => _); Assert.Equal(expected, new StringBuilder().AppendJoin('|', values).ToString()); + Assert.Equal(expected, new StringBuilder().AppendJoin('|', (ReadOnlySpan)values).ToString()); Assert.Equal(expected, new StringBuilder().AppendJoin('|', enumerable).ToString()); Assert.Equal(expected, new StringBuilder().AppendJoin('|', stringValues).ToString()); + Assert.Equal(expected, new StringBuilder().AppendJoin('|', (ReadOnlySpan)stringValues).ToString()); Assert.Equal(expected, new StringBuilder().AppendJoin("|", values).ToString()); + Assert.Equal(expected, new StringBuilder().AppendJoin("|", (ReadOnlySpan)values).ToString()); Assert.Equal(expected, new StringBuilder().AppendJoin("|", enumerable).ToString()); Assert.Equal(expected, new StringBuilder().AppendJoin("|", stringValues).ToString()); + Assert.Equal(expected, new StringBuilder().AppendJoin("|", (ReadOnlySpan)stringValues).ToString()); } [Fact] @@ -1801,9 +1838,14 @@ private sealed class NullToStringObject [InlineData(", ", "1, 2, 3")] public static void AppendJoin_TestStringSeparators(string separator, string expected) { - Assert.Equal(expected, new StringBuilder().AppendJoin(separator, new object[] { 1, 2, 3 }).ToString()); + var values = new object[] { 1, 2, 3 }; + var stringValues = new string[] { "1", "2", "3" }; + + Assert.Equal(expected, new StringBuilder().AppendJoin(separator, values).ToString()); + Assert.Equal(expected, new StringBuilder().AppendJoin(separator, (ReadOnlySpan)values).ToString()); Assert.Equal(expected, new StringBuilder().AppendJoin(separator, Enumerable.Range(1, 3)).ToString()); - Assert.Equal(expected, new StringBuilder().AppendJoin(separator, new string[] { "1", "2", "3" }).ToString()); + Assert.Equal(expected, new StringBuilder().AppendJoin(separator, stringValues).ToString()); + Assert.Equal(expected, new StringBuilder().AppendJoin(separator, (ReadOnlySpan)stringValues).ToString()); } @@ -1825,12 +1867,16 @@ public static void AppendJoin_NoValues_NoSpareCapacity_DoesNotThrow(string separ if (separator?.Length == 1) { CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], values); + CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], (ReadOnlySpan)values); CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], enumerable); CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], stringValues); + CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], (ReadOnlySpan)stringValues); } CreateBuilderWithNoSpareCapacity().AppendJoin(separator, values); + CreateBuilderWithNoSpareCapacity().AppendJoin(separator, (ReadOnlySpan)values); CreateBuilderWithNoSpareCapacity().AppendJoin(separator, enumerable); CreateBuilderWithNoSpareCapacity().AppendJoin(separator, stringValues); + CreateBuilderWithNoSpareCapacity().AppendJoin(separator, (ReadOnlySpan)stringValues); } [Theory] @@ -1849,12 +1895,16 @@ public static void AppendJoin_NoSpareCapacity_ThrowsArgumentOutOfRangeException( if (separator?.Length == 1) { AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], values)); + AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], (ReadOnlySpan)values)); AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], enumerable)); AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], stringValues)); + AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], (ReadOnlySpan)stringValues)); } AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, values)); + AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, (ReadOnlySpan)values)); AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, enumerable)); AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, stringValues)); + AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, (ReadOnlySpan)stringValues)); } [Theory] diff --git a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/CancellationTokenTests.cs b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/CancellationTokenTests.cs index ba75f617bf0b5d..bc66b33cd9b68a 100644 --- a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/CancellationTokenTests.cs +++ b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/CancellationTokenTests.cs @@ -207,6 +207,7 @@ public static void TokenSourceDispose_Negative() //shouldn't throw CancellationTokenSource.CreateLinkedTokenSource(new[] { token, token }); + CancellationTokenSource.CreateLinkedTokenSource((ReadOnlySpan)new[] { token, token }); } /// @@ -431,15 +432,20 @@ public static void CreateLinkedTokenSource_Simple_TwoToken() "CreateLinkedToken_Simple_TwoToken: The combined token should now be signalled"); } - [Fact] - public static void CreateLinkedTokenSource_Simple_MultiToken() + [Theory] + [InlineData(false)] + [InlineData(true)] + public static void CreateLinkedTokenSource_Simple_MultiToken(bool useSpan) { CancellationTokenSource signal1 = new CancellationTokenSource(); CancellationTokenSource signal2 = new CancellationTokenSource(); CancellationTokenSource signal3 = new CancellationTokenSource(); //Neither token is signalled. - CancellationTokenSource combined = CancellationTokenSource.CreateLinkedTokenSource(new[] { signal1.Token, signal2.Token, signal3.Token }); + CancellationTokenSource combined = useSpan ? + CancellationTokenSource.CreateLinkedTokenSource((ReadOnlySpan)new[] { signal1.Token, signal2.Token, signal3.Token }) : + CancellationTokenSource.CreateLinkedTokenSource(new[] { signal1.Token, signal2.Token, signal3.Token }); + Assert.False(combined.IsCancellationRequested, "CreateLinkedToken_Simple_MultiToken: The combined token should start unsignalled"); diff --git a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/MethodCoverage.cs b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/MethodCoverage.cs index 2634e8340ef9ec..01af9fb525c035 100644 --- a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/MethodCoverage.cs +++ b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/MethodCoverage.cs @@ -188,14 +188,30 @@ public static void Task_WhenAny_TwoTasks_InvalidArgs_Throws() AssertExtensions.Throws("task2", () => Task.WhenAny(Task.FromResult(2), null)); } + [Fact] + public static void Task_WhenAny_NullTaskElement_Throws() + { + AssertExtensions.Throws("tasks", () => { Task.WhenAny(new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAny((ReadOnlySpan)new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAny(NullElementIterator()); }); + + AssertExtensions.Throws("tasks", () => { Task.WhenAny(new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAny((ReadOnlySpan>)new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAny(NullElementIterator>()); }); + + static IEnumerable NullElementIterator() where T : Task { yield return null; } + } + [Fact] public static void Task_WhenAny_NoTasks_Throws() { AssertExtensions.Throws("tasks", () => { Task.WhenAny(new Task[0]); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAny(ReadOnlySpan.Empty); }); AssertExtensions.Throws("tasks", () => { Task.WhenAny(new List()); }); AssertExtensions.Throws("tasks", () => { Task.WhenAny(EmptyIterator()); }); AssertExtensions.Throws("tasks", () => { Task.WhenAny(new Task[0]); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAny(ReadOnlySpan>.Empty); }); AssertExtensions.Throws("tasks", () => { Task.WhenAny(new List>()); }); AssertExtensions.Throws("tasks", () => { Task.WhenAny(EmptyIterator>()); }); @@ -353,6 +369,36 @@ public static void FromAsync() mre2.WaitOne(); } + [Fact] + public static void Task_WaitAll_NullArgument_Throws() + { + AssertExtensions.Throws("tasks", () => { Task.WaitAll((Task[])null); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll((Task[])null, CancellationToken.None); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll((Task[])null, 30_000); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll((Task[])null, TimeSpan.FromSeconds(30)); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll((Task[])null, 30_000, CancellationToken.None); }); + } + + [Fact] + public static void Task_WaitAll_NullTaskElement_Throws() + { + Task[] nullElement = [null]; + AssertExtensions.Throws("tasks", () => { Task.WaitAll(nullElement); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll((ReadOnlySpan)nullElement); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll(nullElement, CancellationToken.None); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll(nullElement, 30_000); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll(nullElement, TimeSpan.FromSeconds(30)); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll(nullElement, 30_000, CancellationToken.None); }); + } + + [Fact] + public static void Task_WaitAll_InvalidArgument_Throws() + { + Assert.Throws(() => Task.WaitAll([Task.Factory.StartNew(() => { })], -2)); + Assert.Throws(() => Task.WaitAll([Task.Factory.StartNew(() => { })], -2, CancellationToken.None)); + Assert.Throws(() => Task.WaitAll([Task.Factory.StartNew(() => { })], TimeSpan.FromMilliseconds(-2))); + } + [Fact] public static void Task_WhenAll_NullArgument_Throws() { @@ -363,14 +409,30 @@ public static void Task_WhenAll_NullArgument_Throws() AssertExtensions.Throws("tasks", () => { Task.WhenAll((IEnumerable>)null); }); } + [Fact] + public static void Task_WhenAll_NullTaskElement_Throws() + { + AssertExtensions.Throws("tasks", () => { Task.WhenAll(new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAll((ReadOnlySpan)new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAll(NullElementIterator()); }); + + AssertExtensions.Throws("tasks", () => { Task.WhenAll(new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAll((ReadOnlySpan>)new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAll(NullElementIterator>()); }); + + static IEnumerable NullElementIterator() where T : Task { yield return null; } + } + [Fact] public static void Task_WhenAll_NoTasks_IsCompletedSuccessfully() { Assert.True(Task.WhenAll(new Task[0]).IsCompletedSuccessfully); + Assert.True(Task.WhenAll(ReadOnlySpan.Empty).IsCompletedSuccessfully); Assert.True(Task.WhenAll(new List()).IsCompletedSuccessfully); Assert.True(Task.WhenAll(EmptyIterator()).IsCompletedSuccessfully); AssertIsCompletedWithEmptyResult(Task.WhenAll(new Task[0])); + AssertIsCompletedWithEmptyResult(Task.WhenAll(ReadOnlySpan>.Empty)); AssertIsCompletedWithEmptyResult(Task.WhenAll(new List>())); AssertIsCompletedWithEmptyResult(Task.WhenAll(EmptyIterator>())); diff --git a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskRtTests_Core.cs b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskRtTests_Core.cs index 088c45ddc116fc..1225ca6433a291 100644 --- a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskRtTests_Core.cs +++ b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskRtTests_Core.cs @@ -1338,11 +1338,6 @@ public static void RunTaskWaitAnyTests_WithCancellationTokenTests() [OuterLoop] public static void RunTaskWaitAllTests() { - Assert.Throws(() => Task.WaitAll((Task[])null)); - AssertExtensions.Throws("tasks", () => Task.WaitAll(new Task[] { null })); - Assert.Throws(() => Task.WaitAll(new Task[] { Task.Factory.StartNew(() => { }) }, -2)); - Assert.Throws(() => Task.WaitAll(new Task[] { Task.Factory.StartNew(() => { }) }, TimeSpan.FromMilliseconds(-2))); - ThreadPoolHelpers.EnsureMinThreadsAtLeast(10); RunTaskWaitAllTest(false, 1); RunTaskWaitAllTest(false, 10); diff --git a/src/libraries/System.Security.Claims/src/System.Security.Claims.csproj b/src/libraries/System.Security.Claims/src/System.Security.Claims.csproj index e1e3b9838c4c25..4376906dbbc4bf 100644 --- a/src/libraries/System.Security.Claims/src/System.Security.Claims.csproj +++ b/src/libraries/System.Security.Claims/src/System.Security.Claims.csproj @@ -18,6 +18,7 @@ + diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.cs index 0ff5bdc90a66ee..e16277de475290 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -659,7 +659,9 @@ namespace System.Text.Json.Nodes public sealed partial class JsonArray : System.Text.Json.Nodes.JsonNode, System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.IEnumerable { public JsonArray(System.Text.Json.Nodes.JsonNodeOptions? options = default(System.Text.Json.Nodes.JsonNodeOptions?)) { } + public JsonArray(System.Text.Json.Nodes.JsonNodeOptions options, System.ReadOnlySpan items) { } public JsonArray(System.Text.Json.Nodes.JsonNodeOptions options, params System.Text.Json.Nodes.JsonNode?[] items) { } + public JsonArray(System.ReadOnlySpan items) { } public JsonArray(params System.Text.Json.Nodes.JsonNode?[] items) { } public int Count { get { throw null; } } bool System.Collections.Generic.ICollection.IsReadOnly { get { throw null; } } @@ -1352,6 +1354,7 @@ public enum JsonTypeInfoKind } public static partial class JsonTypeInfoResolver { + public static System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver Combine(System.ReadOnlySpan resolvers) { throw null; } public static System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver Combine(params System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver?[] resolvers) { throw null; } public static System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver WithAddedModifier(this System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver resolver, System.Action modifier) { throw null; } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonArray.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonArray.cs index f8429dad3ffeef..600249db627b2b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonArray.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonArray.cs @@ -39,6 +39,16 @@ public JsonArray(JsonNodeOptions options, params JsonNode?[] items) : base(optio InitializeFromArray(items); } + /// + /// Initializes a new instance of the class that contains items from the specified params span. + /// + /// Options to control the behavior. + /// The items to add to the new . + public JsonArray(JsonNodeOptions options, /*params*/ ReadOnlySpan items) : base(options) + { + InitializeFromSpan(items); + } + /// /// Initializes a new instance of the class that contains items from the specified array. /// @@ -48,6 +58,15 @@ public JsonArray(params JsonNode?[] items) : base() InitializeFromArray(items); } + /// + /// Initializes a new instance of the class that contains items from the specified span. + /// + /// The items to add to the new . + public JsonArray(/*params*/ ReadOnlySpan items) : base() + { + InitializeFromSpan(items); + } + internal override JsonValueKind GetValueKindCore() => JsonValueKind.Array; internal override JsonNode DeepCloneCore() @@ -129,9 +148,30 @@ private void InitializeFromArray(JsonNode?[] items) { var list = new List(items); - for (int i = 0; i < items.Length; i++) + for (int i = 0; i < list.Count; i++) + { + list[i]?.AssignParent(this); + } + + _list = list; + } + + private void InitializeFromSpan(ReadOnlySpan items) + { + List list = new(items.Length); + +#if NET8_0_OR_GREATER + list.AddRange(items); +#else + foreach (JsonNode? item in items) + { + list.Add(item); + } +#endif + + for (int i = 0; i < list.Count; i++) { - items[i]?.AssignParent(this); + list[i]?.AssignParent(this); } _list = list; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoResolver.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoResolver.cs index 216329609f3b90..9bd63188cbe525 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoResolver.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoResolver.cs @@ -30,6 +30,25 @@ public static IJsonTypeInfoResolver Combine(params IJsonTypeInfoResolver?[] reso ThrowHelper.ThrowArgumentNullException(nameof(resolvers)); } + return Combine((ReadOnlySpan)resolvers); + } + + /// + /// Combines multiple sources into one. + /// + /// Sequence of contract resolvers to be queried for metadata. + /// A combining results from . + /// + /// The combined resolver will query each of in the specified order, + /// returning the first result that is non-null. If all return null, + /// then the combined resolver will also return . + /// + /// Can be used to combine multiple sources, + /// which typically define contract metadata for small subsets of types. + /// It can also be used to fall back to wherever necessary. + /// + public static IJsonTypeInfoResolver Combine(/*params*/ ReadOnlySpan resolvers) + { var resolverChain = new JsonTypeInfoResolverChain(); foreach (IJsonTypeInfoResolver? resolver in resolvers) { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonArrayTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonArrayTests.cs index ef51703958151c..3b8a7b8c4b6b4e 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonArrayTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonArrayTests.cs @@ -12,6 +12,25 @@ namespace System.Text.Json.Nodes.Tests { public static class JsonArrayTests { + [Fact] + public static void ParamsContructors() + { + JsonArray expectedArray = [41, 42, 43]; + JsonNodeOptions options = new JsonNodeOptions { PropertyNameCaseInsensitive = true }; + + Verify(new JsonArray(new JsonNode[] { 41, 42, 43 }), null); + Verify(new JsonArray((ReadOnlySpan)new JsonNode[] { 41, 42, 43 }), null); + Verify(new JsonArray(options, new JsonNode[] { 41, 42, 43 }), options); + Verify(new JsonArray(options, (ReadOnlySpan)new JsonNode[] { 41, 42, 43 }), options); + + void Verify(JsonArray jsonArray, JsonNodeOptions? expectedOptions) + { + Assert.Equal(expectedArray.Count, jsonArray.Count); + JsonNodeTests.AssertDeepEqual(expectedArray, jsonArray); + Assert.Equal(expectedOptions, jsonArray.Options); + } + } + [Fact] public static void FromElement() { @@ -34,7 +53,7 @@ public static void FromElement() public static void FromElement_WrongNodeTypeThrows(string json) { using (JsonDocument document = JsonDocument.Parse(json)) - Assert.Throws(() => JsonArray.Create(document.RootElement)); + Assert.Throws(() => JsonArray.Create(document.RootElement)); } [Fact] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/JsonTypeInfoResolverTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/JsonTypeInfoResolverTests.cs index 9136555b0fd9c9..17e1a73c970a00 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/JsonTypeInfoResolverTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/JsonTypeInfoResolverTests.cs @@ -7,32 +7,46 @@ namespace System.Text.Json.Serialization.Tests { - public static partial class JsonTypeInfoResolverTests + public class JsonTypeInfoResolverCombineArrayTests : JsonTypeInfoResolverCombineTests { + public override IJsonTypeInfoResolver Combine(params IJsonTypeInfoResolver?[] resolvers) => + JsonTypeInfoResolver.Combine(resolvers); + [Fact] - public static void CombineNullArgument() + public void CombineNullArgument() { IJsonTypeInfoResolver[] resolvers = null; - Assert.Throws(() => JsonTypeInfoResolver.Combine(resolvers)); + Assert.Throws(() => Combine(resolvers)); } + } + + public class JsonTypeInfoResolverCombineSpanTests : JsonTypeInfoResolverCombineTests + { + public override IJsonTypeInfoResolver Combine(params IJsonTypeInfoResolver?[] resolvers) => + JsonTypeInfoResolver.Combine((ReadOnlySpan)resolvers); + } + + public abstract class JsonTypeInfoResolverCombineTests + { + public abstract IJsonTypeInfoResolver Combine(params IJsonTypeInfoResolver?[] resolvers); [Fact] - public static void Combine_ShouldFlattenResolvers() + public void Combine_ShouldFlattenResolvers() { DefaultJsonTypeInfoResolver nonNullResolver1 = new(); DefaultJsonTypeInfoResolver nonNullResolver2 = new(); DefaultJsonTypeInfoResolver nonNullResolver3 = new(); - ValidateCombinations(Array.Empty(), JsonTypeInfoResolver.Combine()); - ValidateCombinations(Array.Empty(), JsonTypeInfoResolver.Combine(new IJsonTypeInfoResolver[] { null })); - ValidateCombinations(Array.Empty(), JsonTypeInfoResolver.Combine(null, null)); - ValidateCombinations(new[] { nonNullResolver1 }, JsonTypeInfoResolver.Combine(nonNullResolver1, null)); - ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2 }, JsonTypeInfoResolver.Combine(nonNullResolver1, nonNullResolver2, null)); - ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2 }, JsonTypeInfoResolver.Combine(nonNullResolver1, null, nonNullResolver2)); - ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2, nonNullResolver3 }, JsonTypeInfoResolver.Combine(JsonTypeInfoResolver.Combine(JsonTypeInfoResolver.Combine(nonNullResolver1), nonNullResolver2), nonNullResolver3)); - ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2, nonNullResolver3 }, JsonTypeInfoResolver.Combine(JsonTypeInfoResolver.Combine(nonNullResolver1, null, nonNullResolver2), nonNullResolver3)); + ValidateCombinations(Array.Empty(), Combine()); + ValidateCombinations(Array.Empty(), Combine(new IJsonTypeInfoResolver[] { null })); + ValidateCombinations(Array.Empty(), Combine(null, null)); + ValidateCombinations(new[] { nonNullResolver1 }, Combine(nonNullResolver1, null)); + ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2 }, Combine(nonNullResolver1, nonNullResolver2, null)); + ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2 }, Combine(nonNullResolver1, null, nonNullResolver2)); + ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2, nonNullResolver3 }, Combine(Combine(Combine(nonNullResolver1), nonNullResolver2), nonNullResolver3)); + ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2, nonNullResolver3 }, Combine(Combine(nonNullResolver1, null, nonNullResolver2), nonNullResolver3)); - static void ValidateCombinations(IJsonTypeInfoResolver[] expectedResolvers, IJsonTypeInfoResolver combinedResolver) + void ValidateCombinations(IJsonTypeInfoResolver[] expectedResolvers, IJsonTypeInfoResolver combinedResolver) { if (expectedResolvers.Length == 1) { @@ -46,9 +60,9 @@ static void ValidateCombinations(IJsonTypeInfoResolver[] expectedResolvers, IJso } [Fact] - public static void CombiningZeroResolversProducesValidResolver() + public void CombiningZeroResolversProducesValidResolver() { - IJsonTypeInfoResolver resolver = JsonTypeInfoResolver.Combine(); + IJsonTypeInfoResolver resolver = Combine(); Assert.NotNull(resolver); // calling twice to make sure we get the same answer @@ -57,7 +71,7 @@ public static void CombiningZeroResolversProducesValidResolver() } [Fact] - public static void CombiningSingleResolverProducesSameAnswersAsInputResolver() + public void CombiningSingleResolverProducesSameAnswersAsInputResolver() { JsonSerializerOptions options = new(); JsonTypeInfo t1 = JsonTypeInfo.CreateJsonTypeInfo(typeof(int), options); @@ -74,7 +88,7 @@ public static void CombiningSingleResolverProducesSameAnswersAsInputResolver() return null; }); - IJsonTypeInfoResolver combined = JsonTypeInfoResolver.Combine(resolver); + IJsonTypeInfoResolver combined = Combine(resolver); Assert.Same(t1, combined.GetTypeInfo(typeof(int), options)); Assert.Same(t2, combined.GetTypeInfo(typeof(uint), options)); @@ -84,7 +98,7 @@ public static void CombiningSingleResolverProducesSameAnswersAsInputResolver() } [Fact] - public static void CombiningUsesAndRespectsAllResolversInOrder() + public void CombiningUsesAndRespectsAllResolversInOrder() { JsonSerializerOptions options = new(); JsonTypeInfo t1 = JsonTypeInfo.CreateJsonTypeInfo(typeof(int), options); @@ -121,7 +135,7 @@ public static void CombiningUsesAndRespectsAllResolversInOrder() return null; }); - IJsonTypeInfoResolver combined = JsonTypeInfoResolver.Combine(r1, r2, r3); + IJsonTypeInfoResolver combined = Combine(r1, r2, r3); resolverId = 1; Assert.Same(t1, combined.GetTypeInfo(typeof(int), options)); @@ -144,7 +158,7 @@ public static void CombiningUsesAndRespectsAllResolversInOrder() Assert.Equal(4, resolverId); } - private static IList GetAndValidateCombinedResolvers(IJsonTypeInfoResolver resolver) + private IList GetAndValidateCombinedResolvers(IJsonTypeInfoResolver resolver) { var list = (IList)resolver; @@ -155,8 +169,12 @@ private static IList GetAndValidateCombinedResolvers(IJso return list; } + } + + public class JsonTypeInfoResolverTests + { [Fact] - public static void WithAddedModifier_CallsModifierOnResolvedMetadata() + public void WithAddedModifier_CallsModifierOnResolvedMetadata() { int modifierInvocationCount = 0; JsonSerializerOptions options = new(); @@ -175,11 +193,11 @@ public static void WithAddedModifier_CallsModifierOnResolvedMetadata() } [Fact] - public static void WithAddedModifier_DoesNotCallModifierOnUnResolvedMetadata() + public void WithAddedModifier_DoesNotCallModifierOnUnResolvedMetadata() { int modifierInvocationCount = 0; JsonSerializerOptions options = new(); - TestResolver resolver = new((_,_) => null); + TestResolver resolver = new((_, _) => null); IJsonTypeInfoResolver resolverWithModifier = resolver.WithAddedModifier(_ => modifierInvocationCount++); @@ -191,7 +209,7 @@ public static void WithAddedModifier_DoesNotCallModifierOnUnResolvedMetadata() } [Fact] - public static void WithAddedModifier_CanChainMultipleModifiers() + public void WithAddedModifier_CanChainMultipleModifiers() { int modifier1InvocationCount = 0; int modifier2InvocationCount = 0; @@ -208,7 +226,7 @@ public static void WithAddedModifier_CanChainMultipleModifiers() } [Fact] - public static void WithAddedModifier_ChainingDoesNotMutateIntermediateResolvers() + public void WithAddedModifier_ChainingDoesNotMutateIntermediateResolvers() { int modifier1InvocationCount = 0; int modifier2InvocationCount = 0; @@ -233,7 +251,7 @@ public static void WithAddedModifier_ChainingDoesNotMutateIntermediateResolvers( } [Fact] - public static void WithAddedModifier_ThrowsOnNullArguments() + public void WithAddedModifier_ThrowsOnNullArguments() { TestResolver resolver = new(JsonTypeInfo.CreateJsonTypeInfo); @@ -242,7 +260,7 @@ public static void WithAddedModifier_ThrowsOnNullArguments() } [Fact] - public static void NullResolver_ReturnsObjectMetadata() + public void NullResolver_ReturnsObjectMetadata() { var options = new JsonSerializerOptions(); var resolver = new NullResolver(); diff --git a/src/libraries/System.Threading.Channels/src/System.Threading.Channels.csproj b/src/libraries/System.Threading.Channels/src/System.Threading.Channels.csproj index 21e101ecd6d94e..c058b0b216b17a 100644 --- a/src/libraries/System.Threading.Channels/src/System.Threading.Channels.csproj +++ b/src/libraries/System.Threading.Channels/src/System.Threading.Channels.csproj @@ -50,6 +50,7 @@ System.Threading.Channel<T> + diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj b/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj index 2a1eaf2804e355..21e1af10705020 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj @@ -80,6 +80,7 @@ System.Threading.Tasks.Dataflow.WriteOnceBlock<T> + diff --git a/src/libraries/System.Threading.Tasks.Parallel/src/System.Threading.Tasks.Parallel.csproj b/src/libraries/System.Threading.Tasks.Parallel/src/System.Threading.Tasks.Parallel.csproj index 3278b9f2c5e19d..32d0f7c8cf6a3f 100644 --- a/src/libraries/System.Threading.Tasks.Parallel/src/System.Threading.Tasks.Parallel.csproj +++ b/src/libraries/System.Threading.Tasks.Parallel/src/System.Threading.Tasks.Parallel.csproj @@ -24,6 +24,7 @@ + From 5111fdc0dc464f01647d6b6078342f451bf3a499 Mon Sep 17 00:00:00 2001 From: Qiao Pengcheng Date: Tue, 23 Apr 2024 14:54:08 +0800 Subject: [PATCH 054/248] [LoongArch64] amend the LoongArch64Classifier::Classify for passing struct. (#101365) --- src/coreclr/jit/targetloongarch64.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/targetloongarch64.cpp b/src/coreclr/jit/targetloongarch64.cpp index 47f74094fab9dc..6d63951c8ea205 100644 --- a/src/coreclr/jit/targetloongarch64.cpp +++ b/src/coreclr/jit/targetloongarch64.cpp @@ -104,7 +104,7 @@ ABIPassingInformation LoongArch64Classifier::Classify(Compiler* comp, } else if ((floatFlags & STRUCT_FLOAT_FIELD_FIRST) != 0) { - slots = 1; + slots = 2; canPassArgInRegisters = (m_floatRegs.Count() > 0) && (m_intRegs.Count() > 0); argRegTypeInStruct1 = (floatFlags & STRUCT_FIRST_FIELD_SIZE_IS8) ? TYP_DOUBLE : TYP_FLOAT; @@ -112,7 +112,7 @@ ABIPassingInformation LoongArch64Classifier::Classify(Compiler* comp, } else if ((floatFlags & STRUCT_FLOAT_FIELD_SECOND) != 0) { - slots = 1; + slots = 2; canPassArgInRegisters = (m_floatRegs.Count() > 0) && (m_intRegs.Count() > 0); argRegTypeInStruct1 = (floatFlags & STRUCT_FIRST_FIELD_SIZE_IS8) ? TYP_LONG : TYP_INT; From 774bc93087ad61ef292030afa4392daa34c0233a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulus=20P=C3=A4rssinen?= Date: Tue, 23 Apr 2024 14:10:29 +0300 Subject: [PATCH 055/248] Use BitOperations.RoundUpToPowerOf2 in more places (#101405) * Use BitOperations.RoundUpToPowerOf2 in ThreadLocal * Use BitOperations.RoundUpToPowerOf2 in CacheDict --- .../src/System/Dynamic/Utils/CacheDict.cs | 19 ++--------- .../src/System/Threading/ThreadLocal.cs | 34 +++---------------- 2 files changed, 7 insertions(+), 46 deletions(-) diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/CacheDict.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/CacheDict.cs index b1446848ce6174..9a1c951c1b184f 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/CacheDict.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/CacheDict.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Numerics; using System.Threading; namespace System.Dynamic.Utils @@ -40,27 +41,11 @@ internal Entry(int hash, TKey key, TValue value) /// The maximum number of elements to store will be this number aligned to next ^2. internal CacheDict(int size) { - int alignedSize = AlignSize(size); + int alignedSize = (int)BitOperations.RoundUpToPowerOf2((uint)size); _mask = alignedSize - 1; _entries = new Entry[alignedSize]; } - private static int AlignSize(int size) - { - Debug.Assert(size > 0); - - size--; - size |= size >> 1; - size |= size >> 2; - size |= size >> 4; - size |= size >> 8; - size |= size >> 16; - size++; - - Debug.Assert((size & (~size + 1)) == size, "aligned size should be a power of 2"); - return size; - } - /// /// Tries to get the value associated with 'key', returning true if it's found and /// false if it's not present. diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadLocal.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadLocal.cs index 8890cde64f70d4..aa0c2e4478ca64 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadLocal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadLocal.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Numerics; // A class that provides a simple, lightweight implementation of thread-local lazy-initialization, where a value is initialized once per accessing // thread; this provides an alternative to using a ThreadStatic static variable and having @@ -552,40 +553,15 @@ private static int GetNewTableSize(int minSize) } Debug.Assert(minSize > 0); - // - // Round up the size to the next power of 2 - // - // The algorithm takes three steps: - // input -> subtract one -> propagate 1-bits to the right -> add one - // - // Let's take a look at the 3 steps in both interesting cases: where the input - // is (Example 1) and isn't (Example 2) a power of 2. - // - // Example 1: 100000 -> 011111 -> 011111 -> 100000 - // Example 2: 011010 -> 011001 -> 011111 -> 100000 - // - int newSize = minSize; - - // Step 1: Decrement - newSize--; - - // Step 2: Propagate 1-bits to the right. - newSize |= newSize >> 1; - newSize |= newSize >> 2; - newSize |= newSize >> 4; - newSize |= newSize >> 8; - newSize |= newSize >> 16; - - // Step 3: Increment - newSize++; + uint newSize = BitOperations.RoundUpToPowerOf2((uint)minSize); // Don't set newSize to more than Array.MaxArrayLength - if ((uint)newSize > Array.MaxLength) + if (newSize > Array.MaxLength) { - newSize = Array.MaxLength; + newSize = (uint)Array.MaxLength; } - return newSize; + return (int)newSize; } /// From edb6e7c154a4a75c8d1430cd6a996e6f1f9b401e Mon Sep 17 00:00:00 2001 From: Qiao Pengcheng Date: Tue, 23 Apr 2024 19:41:05 +0800 Subject: [PATCH 056/248] Adjust the calleeSavedRegs on top frame for LoongArch64/RISCV64 (#100962) The frame layout: | | |-----------------------| | incoming arguments | +=======================+ <---- Caller's SP | Varargs regs space | // Only for varargs main functions; not used for LA64. |-----------------------| | MonitorAcquired | // 8 bytes; for synchronized methods |-----------------------| | PSP slot | // 8 bytes (omitted in NativeAOT ABI) |-----------------------| |Callee saved registers | // multiple of 8 bytes, not includting FP/RA |-----------------------| | Saved RA | // 8 bytes |-----------------------| | Saved FP | // 8 bytes |-----------------------| | possible GS cookie | |-----------------------| | locals, temps, etc. | |-----------------------| | possible GS cookie | |-----------------------| | Outgoing arg space | // multiple of 8 bytes; if required (i.e., #outsz != 0) |-----------------------| <---- Ambient SP | | | ~ | Stack grows ~ | | downward | --- src/coreclr/jit/codegen.h | 23 +- src/coreclr/jit/codegencommon.cpp | 17 +- src/coreclr/jit/codegenloongarch64.cpp | 587 +++++++++---------------- src/coreclr/jit/codegenriscv64.cpp | 485 ++++++++------------ src/coreclr/jit/lclvars.cpp | 61 ++- src/coreclr/jit/regset.h | 3 +- 6 files changed, 450 insertions(+), 726 deletions(-) diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index 3511935a062b0a..f5e0dc857a7d4c 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -437,7 +437,7 @@ class CodeGen final : public CodeGenInterface FuncletFrameInfoDsc genFuncletInfo; -#elif defined(TARGET_LOONGARCH64) +#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) // A set of information that is used by funclet prolog and epilog generation. // It is collected once, before funclet prologs and epilogs are generated, @@ -448,26 +448,6 @@ class CodeGen final : public CodeGenInterface int fiFunction_CallerSP_to_FP_delta; // Delta between caller SP and the frame pointer in the parent function // (negative) int fiSP_to_CalleeSaved_delta; // CalleeSaved register save offset from SP (positive) - int fiCalleeSavedPadding; // CalleeSaved offset padding (positive) - int fiSP_to_PSP_slot_delta; // PSP slot offset from SP (positive) - int fiCallerSP_to_PSP_slot_delta; // PSP slot offset from Caller SP (negative) - int fiSpDelta; // Stack pointer delta (negative) - }; - - FuncletFrameInfoDsc genFuncletInfo; - -#elif defined(TARGET_RISCV64) - - // A set of information that is used by funclet prolog and epilog generation. - // It is collected once, before funclet prologs and epilogs are generated, - // and used by all funclet prologs and epilogs, which must all be the same. - struct FuncletFrameInfoDsc - { - regMaskTP fiSaveRegs; // Set of callee-saved registers saved in the funclet prolog (includes RA) - int fiFunction_CallerSP_to_FP_delta; // Delta between caller SP and the frame pointer in the parent function - // (negative) - int fiSP_to_CalleeSaved_delta; // CalleeSaved register save offset from SP (positive) - int fiCalleeSavedPadding; // CalleeSaved offset padding (positive) int fiSP_to_PSP_slot_delta; // PSP slot offset from SP (positive) int fiCallerSP_to_PSP_slot_delta; // PSP slot offset from Caller SP (negative) int fiSpDelta; // Stack pointer delta (negative) @@ -1272,7 +1252,6 @@ class CodeGen final : public CodeGenInterface void genJmpMethod(GenTree* jmp); BasicBlock* genCallFinally(BasicBlock* block); #if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - // TODO: refactor for LA. void genCodeForJumpCompare(GenTreeOpCC* tree); #endif #if defined(TARGET_ARM64) diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 417a7e6f31695d..c8211a7e731440 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -4744,20 +4744,13 @@ void CodeGen::genFinalizeFrame() #endif // defined(TARGET_XARCH) #if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - if (isFramePointerUsed()) - { - // For a FP based frame we have to push/pop the FP register - // - maskCalleeRegsPushed |= RBM_FPBASE; + // This assert check that we are not using REG_FP + assert(!regSet.rsRegsModified(RBM_FPBASE)); - // This assert check that we are not using REG_FP - // as both the frame pointer and as a codegen register - // - assert(!regSet.rsRegsModified(RBM_FPBASE)); - } + assert(isFramePointerUsed()); + // we always push FP/RA. See genPushCalleeSavedRegisters + maskCalleeRegsPushed |= (RBM_FPBASE | RBM_RA); - // we always push RA. See genPushCalleeSavedRegisters - maskCalleeRegsPushed |= RBM_RA; #endif // TARGET_LOONGARCH64 || TARGET_RISCV64 compiler->compCalleeRegsPushed = genCountBits(maskCalleeRegsPushed); diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index 2954a989c74668..1bd29a432ce170 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -190,8 +190,7 @@ void CodeGen::genStackPointerAdjustment(ssize_t spDelta, regNumber tmpReg, bool* // reg1 - First register of pair to save. // reg2 - Second register of pair to save. // spOffset - The offset from SP to store reg1 (must be positive or zero). -// spDelta - If non-zero, the amount to add to SP before the register saves (must be negative or -// zero). +// spDelta - Always zero for LoongArch64 now. // useSaveNextPair - True if the last prolog instruction was to save the previous register pair. This // allows us to emit the "save_next" unwind code. // tmpReg - An available temporary register. Needed for the case of large frames. @@ -210,8 +209,7 @@ void CodeGen::genPrologSaveRegPair(regNumber reg1, bool* pTmpRegIsZero) { assert(spOffset >= 0); - assert(spDelta <= 0); - assert((spDelta % 16) == 0); // SP changes must be 16-byte aligned + assert(spDelta == 0); assert(genIsValidFloatReg(reg1) == genIsValidFloatReg(reg2)); // registers must be both general-purpose, or both // FP/SIMD @@ -221,16 +219,6 @@ void CodeGen::genPrologSaveRegPair(regNumber reg1, ins = INS_fst_d; } - if (spDelta != 0) - { - // generate addi.d SP,SP,-imm - genStackPointerAdjustment(spDelta, tmpReg, pTmpRegIsZero, /* reportUnwindData */ true); - - assert((spDelta + spOffset + 16) <= 0); - - assert(spOffset <= 2031); // 2047-16 - } - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); compiler->unwindSaveReg(reg1, spOffset); @@ -249,8 +237,7 @@ void CodeGen::genPrologSaveRegPair(regNumber reg1, // Arguments: // reg1 - Register to save. // spOffset - The offset from SP to store reg1 (must be positive or zero). -// spDelta - If non-zero, the amount to add to SP before the register saves (must be negative or -// zero). +// spDelta - Always zero for LoongArch64 now. // tmpReg - An available temporary register. Needed for the case of large frames. // pTmpRegIsZero - If we use tmpReg, and pTmpRegIsZero is non-null, we set *pTmpRegIsZero to 'false'. // Otherwise, we don't touch it. @@ -261,8 +248,7 @@ void CodeGen::genPrologSaveRegPair(regNumber reg1, void CodeGen::genPrologSaveReg(regNumber reg1, int spOffset, int spDelta, regNumber tmpReg, bool* pTmpRegIsZero) { assert(spOffset >= 0); - assert(spDelta <= 0); - assert((spDelta % 16) == 0); // SP changes must be 16-byte aligned + assert(spDelta == 0); instruction ins = INS_st_d; if (genIsValidFloatReg(reg1)) @@ -270,12 +256,6 @@ void CodeGen::genPrologSaveReg(regNumber reg1, int spOffset, int spDelta, regNum ins = INS_fst_d; } - if (spDelta != 0) - { - // generate addi.d SP,SP,-imm - genStackPointerAdjustment(spDelta, tmpReg, pTmpRegIsZero, /* reportUnwindData */ true); - } - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); compiler->unwindSaveReg(reg1, spOffset); } @@ -290,8 +270,7 @@ void CodeGen::genPrologSaveReg(regNumber reg1, int spOffset, int spDelta, regNum // reg1 - First register of pair to restore. // reg2 - Second register of pair to restore. // spOffset - The offset from SP to load reg1 (must be positive or zero). -// spDelta - If non-zero, the amount to add to SP after the register restores (must be positive or -// zero). +// spDelta - Always zero for LoongArch64 now. // useSaveNextPair - True if the last prolog instruction was to save the previous register pair. This // allows us to emit the "save_next" unwind code. // tmpReg - An available temporary register. Needed for the case of large frames. @@ -310,8 +289,7 @@ void CodeGen::genEpilogRestoreRegPair(regNumber reg1, bool* pTmpRegIsZero) { assert(spOffset >= 0); - assert(spDelta >= 0); - assert((spDelta % 16) == 0); // SP changes must be 16-byte aligned + assert(spDelta == 0); assert(genIsValidFloatReg(reg1) == genIsValidFloatReg(reg2)); // registers must be both general-purpose, or both // FP/SIMD @@ -321,27 +299,11 @@ void CodeGen::genEpilogRestoreRegPair(regNumber reg1, ins = INS_fld_d; } - if (spDelta != 0) - { - assert(!useSaveNextPair); - - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg2, REG_SPBASE, spOffset + 8); - compiler->unwindSaveReg(reg2, spOffset + 8); - - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); - compiler->unwindSaveReg(reg1, spOffset); - - // generate addi.d SP,SP,imm - genStackPointerAdjustment(spDelta, tmpReg, pTmpRegIsZero, /* reportUnwindData */ true); - } - else - { - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg2, REG_SPBASE, spOffset + 8); - compiler->unwindSaveReg(reg2, spOffset + 8); + GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg2, REG_SPBASE, spOffset + 8); + compiler->unwindSaveReg(reg2, spOffset + 8); - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); - compiler->unwindSaveReg(reg1, spOffset); - } + GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); + compiler->unwindSaveReg(reg1, spOffset); } //------------------------------------------------------------------------ @@ -350,8 +312,7 @@ void CodeGen::genEpilogRestoreRegPair(regNumber reg1, // Arguments: // reg1 - Register to restore. // spOffset - The offset from SP to restore reg1 (must be positive or zero). -// spDelta - If non-zero, the amount to add to SP after the register restores (must be positive or -// zero). +// spDelta - Always zero for LoongArch64 now. // tmpReg - An available temporary register. Needed for the case of large frames. // pTmpRegIsZero - If we use tmpReg, and pTmpRegIsZero is non-null, we set *pTmpRegIsZero to 'false'. // Otherwise, we don't touch it. @@ -362,8 +323,7 @@ void CodeGen::genEpilogRestoreRegPair(regNumber reg1, void CodeGen::genEpilogRestoreReg(regNumber reg1, int spOffset, int spDelta, regNumber tmpReg, bool* pTmpRegIsZero) { assert(spOffset >= 0); - assert(spDelta >= 0); - assert((spDelta % 16) == 0); // SP changes must be 16-byte aligned + assert(spDelta == 0); instruction ins = INS_ld_d; if (genIsValidFloatReg(reg1)) @@ -371,20 +331,8 @@ void CodeGen::genEpilogRestoreReg(regNumber reg1, int spOffset, int spDelta, reg ins = INS_fld_d; } - if (spDelta != 0) - { - // ld.d reg1,SP,offset - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); - compiler->unwindSaveReg(reg1, spOffset); - - // generate addi.d SP,SP,imm - genStackPointerAdjustment(spDelta, tmpReg, pTmpRegIsZero, /* reportUnwindData */ true); - } - else - { - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); - compiler->unwindSaveReg(reg1, spOffset); - } + GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); + compiler->unwindSaveReg(reg1, spOffset); } //------------------------------------------------------------------------ @@ -519,12 +467,13 @@ int CodeGen::genGetSlotSizeForRegsInMask(regMaskTP regsMask) // genSaveCalleeSavedRegisterGroup: Saves the group of registers described by the mask. // // Arguments: -// regsMask - a mask of registers for prolog generation; -// spDelta - if non-zero, the amount to add to SP before the first register save (or together with it); -// spOffset - the offset from SP that is the beginning of the callee-saved register area; +// regsMask - a mask of registers for prolog generation; +// spDelta - Always zero for LoongArch64 now. +// spOffset - the offset from SP that is the beginning of the callee-saved register area; // void CodeGen::genSaveCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta, int spOffset) { + assert(spDelta == 0); const int slotSize = genGetSlotSizeForRegsInMask(regsMask); ArrayStack regStack(compiler->getAllocator(CMK_Codegen)); @@ -536,19 +485,16 @@ void CodeGen::genSaveCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta, i if (regPair.reg2 != REG_NA) { // We can use two SD instructions. - genPrologSaveRegPair(regPair.reg1, regPair.reg2, spOffset, spDelta, regPair.useSaveNextPair, REG_R21, - nullptr); + genPrologSaveRegPair(regPair.reg1, regPair.reg2, spOffset, 0, regPair.useSaveNextPair, REG_R21, nullptr); spOffset += 2 * slotSize; } else { // No register pair; we use a SD instruction. - genPrologSaveReg(regPair.reg1, spOffset, spDelta, REG_R21, nullptr); + genPrologSaveReg(regPair.reg1, spOffset, 0, REG_R21, nullptr); spOffset += slotSize; } - - spDelta = 0; // We've now changed SP already, if necessary; don't do it again. } } @@ -574,34 +520,22 @@ void CodeGen::genSaveCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta, i // // Arguments: // regsToSaveMask - The mask of callee-saved registers to save. If empty, this function does nothing. -// lowestCalleeSavedOffset - The offset from SP that is the beginning of the callee-saved register area. Note that -// if non-zero spDelta, then this is the offset of the first save *after* that -// SP adjustment. -// spDelta - If non-zero, the amount to add to SP before the register saves (must be negative or -// zero). +// lowestCalleeSavedOffset - The offset from SP that is the beginning of the callee-saved register area. +// spDelta - Always zero for LoongArch64 now. // // Notes: // The save set can not contain FP/RA in which case FP/RA is saved along with the other callee-saved registers. // void CodeGen::genSaveCalleeSavedRegistersHelp(regMaskTP regsToSaveMask, int lowestCalleeSavedOffset, int spDelta) { - assert(spDelta <= 0); + assert(spDelta == 0); - unsigned regsToSaveCount = genCountBits(regsToSaveMask); - if (regsToSaveCount == 0) + if (regsToSaveMask == 0) { - if (spDelta != 0) - { - // Currently this is the case for varargs only - // whose size is MAX_REG_ARG * REGSIZE_BYTES = 64 bytes. - genStackPointerAdjustment(spDelta, REG_R21, nullptr, /* reportUnwindData */ true); - } return; } - assert((spDelta % 16) == 0); - - assert(regsToSaveCount <= genCountBits(RBM_CALLEE_SAVED)); + assert(genCountBits(regsToSaveMask) <= genCountBits(RBM_CALLEE_SAVED)); // Save integer registers at higher addresses than floating-point registers. @@ -610,15 +544,14 @@ void CodeGen::genSaveCalleeSavedRegistersHelp(regMaskTP regsToSaveMask, int lowe if (maskSaveRegsFloat != RBM_NONE) { - genSaveCalleeSavedRegisterGroup(maskSaveRegsFloat, spDelta, lowestCalleeSavedOffset); - spDelta = 0; + genSaveCalleeSavedRegisterGroup(maskSaveRegsFloat, 0, lowestCalleeSavedOffset); lowestCalleeSavedOffset += genCountBits(maskSaveRegsFloat) * FPSAVE_REGSIZE_BYTES; } if (maskSaveRegsInt != RBM_NONE) { - genSaveCalleeSavedRegisterGroup(maskSaveRegsInt, spDelta, lowestCalleeSavedOffset); - // No need to update spDelta, lowestCalleeSavedOffset since they're not used after this. + // No need to update spDelta. + genSaveCalleeSavedRegisterGroup(maskSaveRegsInt, 0, lowestCalleeSavedOffset); } } @@ -627,11 +560,12 @@ void CodeGen::genSaveCalleeSavedRegistersHelp(regMaskTP regsToSaveMask, int lowe // // Arguments: // regsMask - a mask of registers for epilog generation; -// spDelta - if non-zero, the amount to add to SP after the last register restore (or together with it); +// spDelta - Always zero for LoongArch64 now. // spOffset - the offset from SP that is the beginning of the callee-saved register area; // void CodeGen::genRestoreCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta, int spOffset) { + assert(spDelta == 0); const int slotSize = genGetSlotSizeForRegsInMask(regsMask); ArrayStack regStack(compiler->getAllocator(CMK_Codegen)); @@ -640,15 +574,6 @@ void CodeGen::genRestoreCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta int stackDelta = 0; for (int i = 0; i < regStack.Height(); ++i) { - bool lastRestoreInTheGroup = (i == regStack.Height() - 1); - bool updateStackDelta = lastRestoreInTheGroup && (spDelta != 0); - if (updateStackDelta) - { - // Update stack delta only if it is the last restore (the first save). - assert(stackDelta == 0); - stackDelta = spDelta; - } - RegPair regPair = regStack.Top(i); if (regPair.reg2 != REG_NA) { @@ -670,10 +595,9 @@ void CodeGen::genRestoreCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta // in the function or funclet epilog. This exactly reverses the actions of genSaveCalleeSavedRegistersHelp(). // // Arguments: -// regsToRestoreMask - The mask of callee-saved registers to restore. If empty, this function does nothing. -// lowestCalleeSavedOffset - The offset from SP that is the beginning of the callee-saved register area. -// spDelta - If non-zero, the amount to add to SP after the register restores (must be positive or -// zero). +// regsToRestoreMask - The mask of callee-saved registers to restore. If empty, this function does nothing. +// lowestCalleeSavedOffset - The offset from SP that is the beginning of the callee-saved register area. +// spDelta - Always zero for LoongArch64 now. // // Here's an example restore sequence: // ld.d s8,sp,#xxx @@ -694,23 +618,15 @@ void CodeGen::genRestoreCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, int lowestCalleeSavedOffset, int spDelta) { - assert(spDelta >= 0); - unsigned regsToRestoreCount = genCountBits(regsToRestoreMask); - if (regsToRestoreCount == 0) + assert(spDelta == 0); + if (regsToRestoreMask == 0) { - if (spDelta != 0) - { - // Currently this is the case for varargs only - // whose size is MAX_REG_ARG * REGSIZE_BYTES = 64 bytes. - genStackPointerAdjustment(spDelta, REG_R21, nullptr, /* reportUnwindData */ true); - } return; } - assert((spDelta % 16) == 0); - - // We also can restore FP and RA, even though they are not in RBM_CALLEE_SAVED. - assert(regsToRestoreCount <= genCountBits(RBM_CALLEE_SAVED | RBM_FP | RBM_RA)); + unsigned regsToRestoreCount = genCountBits(regsToRestoreMask); + // The FP and RA are not in RBM_CALLEE_SAVED. + assert(regsToRestoreCount <= genCountBits(RBM_CALLEE_SAVED)); // Point past the end, to start. We predecrement to find the offset to load from. static_assert_no_msg(REGSIZE_BYTES == FPSAVE_REGSIZE_BYTES); @@ -725,15 +641,13 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in if (maskRestoreRegsInt != RBM_NONE) { - int spIntDelta = (maskRestoreRegsFloat != RBM_NONE) ? 0 : spDelta; // should we delay the SP adjustment? - genRestoreCalleeSavedRegisterGroup(maskRestoreRegsInt, spIntDelta, spOffset); + genRestoreCalleeSavedRegisterGroup(maskRestoreRegsInt, 0, spOffset); spOffset -= genCountBits(maskRestoreRegsInt) * REGSIZE_BYTES; } if (maskRestoreRegsFloat != RBM_NONE) { - // If there is any spDelta, it must be used here. - genRestoreCalleeSavedRegisterGroup(maskRestoreRegsFloat, spDelta, spOffset); + genRestoreCalleeSavedRegisterGroup(maskRestoreRegsFloat, 0, spOffset); // No need to update spOffset since it's not used after this. } } @@ -755,7 +669,7 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * filter: a0 = non-zero if the handler should handle the exception, zero otherwise (see GT_RETFILT) * finally/fault: none * - * The LOONGARCH64 funclet prolog is the following (Note: #framesz is total funclet frame size, + * The LoongArch64 funclet prolog is the following (Note: #framesz is total funclet frame size, * including everything; #outsz is outgoing argument space. #framesz must be a multiple of 16): * * Frame type liking: @@ -771,19 +685,17 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * |-----------------------| * | incoming arguments | * +=======================+ <---- Caller's SP - * | OSR padding | // If required - * |-----------------------| - * | Varargs regs space | // Only for varargs main functions; 64 bytes + * | Varargs regs space | // Only for varargs main functions; not used for LA64. * |-----------------------| * | MonitorAcquired | // 8 bytes; for synchronized methods * |-----------------------| * | PSP slot | // 8 bytes (omitted in NativeAOT ABI) * |-----------------------| - * ~ alignment padding ~ // To make the whole frame 16 byte aligned + * |Callee saved registers | // multiple of 8 bytes, not including FP/RA * |-----------------------| * | Saved FP, RA | // 16 bytes * |-----------------------| - * |Callee saved registers | // multiple of 8 bytes, not includting FP/RA + * ~ alignment padding ~ // To make the whole frame 16 byte aligned * |-----------------------| * | Outgoing arg space | // multiple of 8 bytes; if required (i.e., #outsz != 0) * |-----------------------| <---- Ambient SP @@ -793,38 +705,22 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * V * * - * Both #1 and #2 only change SP once. That means that there will be a maximum of one alignment slot needed. For the general case, #3, - * it is possible that we will need to add alignment to both changes to SP, leading to 16 bytes of alignment. Remember that the stack - * pointer needs to be 16 byte aligned at all times. The size of the PSP slot plus callee-saved registers space is a maximum of 232 bytes: - * - * FP,RA registers - * 9 int callee-saved register s0-s8 - * 8 float callee-saved registers f24-f31 - * 8 saved integer argument registers a0-a7, if varargs function support. - * 1 PSP slot - * == 20 slots * 8 bytes = 160 bytes. - * * The outgoing argument size, however, can be very large, if we call a function that takes a large number of * arguments (note that we currently use the same outgoing argument space size in the funclet as for the main * function, even if the funclet doesn't have any calls, or has a much smaller, or larger, maximum number of - * outgoing arguments for any call). In that case, we need to 16-byte align the initial change to SP, before - * saving off the callee-saved registers and establishing the PSPsym, so we can use the limited immediate offset - * encodings we have available, before doing another 16-byte aligned SP adjustment to create the outgoing argument - * space. Both changes to SP might need to add alignment padding. - * - * In addition to the above "standard" frames, we also need to support a frame where the saved FP/RA are at the - * highest addresses. This is to match the frame layout (specifically, callee-saved registers including FP/RA - * and the PSPSym) that is used in the main function when a GS cookie is required due to the use of localloc. - * (Note that localloc cannot be used in a funclet.) In these variants, not only has the position of FP/RA - * changed, but where the alignment padding is placed has also changed. - * + * outgoing arguments for any call). * - * Note that in all cases, the PSPSym is in exactly the same position with respect to Caller-SP, and that location is the same relative to Caller-SP - * as in the main function. + * Note that in all cases, the PSPSym is in exactly the same position with respect to Caller-SP, + * and that location is the same relative to Caller-SP as in the main function where higher than + * the callee-saved registers. + * That is to say, the PSPSym's relative offset to Caller-SP is not depended on the callee-saved registers. + * TODO-LoongArch64: the funclet's callee-saved registers should not shared with main function. * * Funclets do not have varargs arguments. However, because the PSPSym must exist at the same offset from Caller-SP as in the main function, we * must add buffer space for the saved varargs/argument registers here, if the main function did the same. * + * Note that localloc cannot be used in a funclet. + * * ; After this header, fill the PSP slot, for use by the VM (it gets reported with the GC info), or by code generation of nested filters. * ; This is not part of the "OS prolog"; it has no associated unwind data, and is not reversed in the funclet epilog. * @@ -880,7 +776,9 @@ void CodeGen::genFuncletProlog(BasicBlock* block) { #ifdef DEBUG if (verbose) + { printf("*************** In genFuncletProlog()\n"); + } #endif assert(block != NULL); @@ -910,42 +808,39 @@ void CodeGen::genFuncletProlog(BasicBlock* block) maskArgRegsLiveIn = RBM_A0; } - regMaskTP maskSaveRegs = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; - int regsSavedSize = (compiler->compCalleeRegsPushed - 2) << 3; + regMaskTP maskSaveRegs = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; + int FP_offset = genFuncletInfo.fiSP_to_CalleeSaved_delta; - int SP_to_CalleeSaved_delta = genFuncletInfo.fiSP_to_CalleeSaved_delta; - if ((SP_to_CalleeSaved_delta + regsSavedSize + genFuncletInfo.fiCalleeSavedPadding) <= 2040) + if ((FP_offset + (genCountBits(maskSaveRegs) << 3)) <= (2040 - 16)) // no FP/RA. { - SP_to_CalleeSaved_delta += genFuncletInfo.fiCalleeSavedPadding; - genStackPointerAdjustment(frameSize, REG_R21, nullptr, /* reportUnwindData */ true); - genSaveCalleeSavedRegistersHelp(maskSaveRegs, SP_to_CalleeSaved_delta, 0); - SP_to_CalleeSaved_delta += regsSavedSize; + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, SP_to_CalleeSaved_delta); - compiler->unwindSaveReg(REG_RA, SP_to_CalleeSaved_delta); + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, SP_to_CalleeSaved_delta + 8); - compiler->unwindSaveReg(REG_FP, SP_to_CalleeSaved_delta + 8); + genSaveCalleeSavedRegistersHelp(maskSaveRegs, FP_offset + 16, 0); } else { assert(frameSize < -2040); - int SP_delta = frameSize + SP_to_CalleeSaved_delta; - genStackPointerAdjustment(SP_delta, REG_R21, nullptr, /* reportUnwindData */ true); + genStackPointerAdjustment(frameSize + (FP_offset & -16), REG_R21, nullptr, true); - genSaveCalleeSavedRegistersHelp(maskSaveRegs, genFuncletInfo.fiCalleeSavedPadding, 0); - regsSavedSize += genFuncletInfo.fiCalleeSavedPadding; + frameSize = -(FP_offset & -16); + FP_offset &= 0xf; - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, regsSavedSize); - compiler->unwindSaveReg(REG_RA, regsSavedSize); + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, regsSavedSize + 8); - compiler->unwindSaveReg(REG_FP, regsSavedSize + 8); + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - genStackPointerAdjustment(-SP_to_CalleeSaved_delta, REG_R21, nullptr, /* reportUnwindData */ true); + genSaveCalleeSavedRegistersHelp(maskSaveRegs, FP_offset + 16, 0); + + genStackPointerAdjustment(frameSize, REG_R21, nullptr, true); } // This is the end of the OS-reported prolog for purposes of unwinding @@ -1012,41 +907,28 @@ void CodeGen::genFuncletEpilog() int frameSize = genFuncletInfo.fiSpDelta; assert(frameSize < 0); - regMaskTP regsToRestoreMask = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; - int regsRestoreSize = (compiler->compCalleeRegsPushed - 2) << 3; + regMaskTP maskSaveRegs = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; + int FP_offset = genFuncletInfo.fiSP_to_CalleeSaved_delta; - int SP_to_CalleeSaved_delta = genFuncletInfo.fiSP_to_CalleeSaved_delta; - if ((SP_to_CalleeSaved_delta + regsRestoreSize + genFuncletInfo.fiCalleeSavedPadding) <= 2040) + if ((FP_offset + (genCountBits(maskSaveRegs) << 3)) > (2040 - 16)) // no FP/RA. { - SP_to_CalleeSaved_delta += genFuncletInfo.fiCalleeSavedPadding; - genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, SP_to_CalleeSaved_delta, 0); - SP_to_CalleeSaved_delta += regsRestoreSize; - - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_RA, REG_SPBASE, SP_to_CalleeSaved_delta); - compiler->unwindSaveReg(REG_RA, SP_to_CalleeSaved_delta); + assert(frameSize < -2040); - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, SP_to_CalleeSaved_delta + 8); - compiler->unwindSaveReg(REG_FP, SP_to_CalleeSaved_delta + 8); + genStackPointerAdjustment(FP_offset & -16, REG_R21, nullptr, /* reportUnwindData */ true); - genStackPointerAdjustment(-frameSize, REG_R21, nullptr, /* reportUnwindData */ true); + frameSize += FP_offset & -16; + FP_offset = FP_offset & 0xf; } - else - { - assert(frameSize < -2040); - - genStackPointerAdjustment(SP_to_CalleeSaved_delta, REG_R21, nullptr, /* reportUnwindData */ true); - genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, genFuncletInfo.fiCalleeSavedPadding, 0); - regsRestoreSize += genFuncletInfo.fiCalleeSavedPadding; + genRestoreCalleeSavedRegistersHelp(maskSaveRegs, FP_offset + 16, 0); - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_RA, REG_SPBASE, regsRestoreSize); - compiler->unwindSaveReg(REG_RA, regsRestoreSize); + GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, regsRestoreSize + 8); - compiler->unwindSaveReg(REG_FP, regsRestoreSize + 8); + GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - genStackPointerAdjustment(-frameSize - SP_to_CalleeSaved_delta, REG_R21, nullptr, /* reportUnwindData */ true); - } + genStackPointerAdjustment(-frameSize, REG_R21, nullptr, /* reportUnwindData */ true); GetEmitter()->emitIns_R_R_I(INS_jirl, emitActualTypeSize(TYP_I_IMPL), REG_R0, REG_RA, 0); compiler->unwindReturn(REG_RA); @@ -1072,7 +954,6 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() } assert(isFramePointerUsed()); - // The frame size and offsets must be finalized assert(compiler->lvaDoneFrameLayout == Compiler::FINAL_FRAME_LAYOUT); @@ -1080,58 +961,40 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() assert((rsMaskSaveRegs & RBM_RA) != 0); assert((rsMaskSaveRegs & RBM_FP) != 0); - unsigned PSPSize = (compiler->lvaPSPSym != BAD_VAR_NUM) ? 8 : 0; - // Because a method and funclets must have the same caller-relative PSPSym offset, // if there is a PSPSym, we have to pad the funclet frame size for OSR. // - unsigned osrPad = 0; - if (compiler->opts.IsOSR() && (PSPSize > 0)) + int osrPad = 0; + if (compiler->opts.IsOSR()) { - osrPad = compiler->info.compPatchpointInfo->TotalFrameSize(); + osrPad -= compiler->info.compPatchpointInfo->TotalFrameSize(); // OSR pad must be already aligned to stack size. assert((osrPad % STACK_ALIGN) == 0); } - genFuncletInfo.fiCalleeSavedPadding = 0; - genFuncletInfo.fiFunction_CallerSP_to_FP_delta = genCallerSPtoFPdelta() - osrPad; - - unsigned regsSavedSize = genCountBits(rsMaskSaveRegs) << 3; - assert(genCountBits(rsMaskSaveRegs) == compiler->compCalleeRegsPushed); - - unsigned saveRegsPlusPSPSize = regsSavedSize + PSPSize; - - assert(compiler->lvaOutgoingArgSpaceSize % REGSIZE_BYTES == 0); - unsigned outgoingArgSpaceAligned = roundUp(compiler->lvaOutgoingArgSpaceSize, STACK_ALIGN); + /* Now save it for future use */ + genFuncletInfo.fiFunction_CallerSP_to_FP_delta = genCallerSPtoFPdelta() + osrPad; - unsigned funcletFrameSize = osrPad + saveRegsPlusPSPSize + compiler->lvaOutgoingArgSpaceSize; - unsigned funcletFrameSizeAligned = roundUp(funcletFrameSize, STACK_ALIGN); + int funcletFrameSize = compiler->lvaOutgoingArgSpaceSize; - int SP_to_CalleeSaved_delta = compiler->lvaOutgoingArgSpaceSize; - if ((SP_to_CalleeSaved_delta + regsSavedSize) >= 2040) - { - int offset = funcletFrameSizeAligned - SP_to_CalleeSaved_delta; - SP_to_CalleeSaved_delta = AlignUp((UINT)offset, STACK_ALIGN); + genFuncletInfo.fiSP_to_CalleeSaved_delta = funcletFrameSize; - genFuncletInfo.fiCalleeSavedPadding = SP_to_CalleeSaved_delta - offset; - } + funcletFrameSize += genCountBits(rsMaskSaveRegs) * REGSIZE_BYTES; - if (compiler->lvaMonAcquired != BAD_VAR_NUM && !compiler->opts.IsOSR()) + int delta_PSP = -TARGET_POINTER_SIZE; + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) { - // We furthermore allocate the "monitor acquired" bool between PSP and - // the saved registers because this is part of the EnC header. - // Note that OSR methods reuse the monitor bool created by tier 0. - osrPad += compiler->lvaLclSize(compiler->lvaMonAcquired); + delta_PSP -= TARGET_POINTER_SIZE; } - /* Now save it for future use */ - genFuncletInfo.fiSpDelta = -(int)funcletFrameSizeAligned; - genFuncletInfo.fiSaveRegs = rsMaskSaveRegs; - genFuncletInfo.fiSP_to_CalleeSaved_delta = SP_to_CalleeSaved_delta; + funcletFrameSize = funcletFrameSize - delta_PSP - osrPad; + funcletFrameSize = roundUp((unsigned)funcletFrameSize, STACK_ALIGN); - genFuncletInfo.fiSP_to_PSP_slot_delta = funcletFrameSizeAligned - osrPad - 8; - genFuncletInfo.fiCallerSP_to_PSP_slot_delta = -(int)osrPad - 8; + genFuncletInfo.fiSpDelta = -funcletFrameSize; + genFuncletInfo.fiSaveRegs = rsMaskSaveRegs; + genFuncletInfo.fiSP_to_PSP_slot_delta = funcletFrameSize + delta_PSP + osrPad; + genFuncletInfo.fiCallerSP_to_PSP_slot_delta = osrPad + delta_PSP; #ifdef DEBUG if (verbose) @@ -4278,9 +4141,17 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree) int CodeGenInterface::genSPtoFPdelta() const { assert(isFramePointerUsed()); - assert(compiler->compCalleeRegsPushed >= 2); + assert(compiler->compCalleeRegsPushed >= 2); // always FP/RA. - int delta = compiler->lvaOutgoingArgSpaceSize + (compiler->compCalleeRegsPushed << 3) - 8; + int delta = compiler->compLclFrameSize; + if (compiler->lvaPSPSym != BAD_VAR_NUM) + { + delta -= TARGET_POINTER_SIZE; + } + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) + { + delta -= TARGET_POINTER_SIZE; + } assert(delta >= 0); return delta; @@ -7660,8 +7531,8 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) * ... * st.d s8,sp,off2+8*8 * - * st.d ra,sp,off3 - * st.d fp,sp,off3+8 + * st.d ra,sp,off3+8 + * st.d fp,sp,off3 * * Notes: * 1. FP is always saved, and the first store is FP, RA. @@ -7669,37 +7540,41 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) * 3. For frames with varargs, not implemented completely and not tested ! * 4. We allocate the frame here; no further changes to SP are allowed (except in the body, for localloc). * - * For functions with GS and localloc, we change the frame so the frame pointer and RA are saved at the top - * of the frame, just under the varargs registers (if any). Note that the funclet frames must follow the same - * rule, and both main frame and funclet frames (if any) must put PSPSym in the same offset from Caller-SP. + * For functions with GS and localloc, we had saved the frame pointer and RA at the top + * of the frame. Note that the funclet frames must follow the same rule, + * and both main frame and funclet frames (if any) must put PSPSym in the same offset from Caller-SP. * Since this frame type is relatively rare, we force using it via stress modes, for additional coverage. * * The frames look like the following (simplified to only include components that matter for establishing the * frames). See also Compiler::lvaAssignFrameOffsets(). * - * * The LoongArch64's frame layout is liking: * + * If we need to generate a GS cookie, we need to make sure the saved frame pointer and return address + * (FP and RA) are protected from buffer overrun by the GS cookie. + * So we always save the FP/RA along with the rest of the callee-saved registers above. + * * | | * |-----------------------| * | incoming arguments | * +=======================+ <---- Caller's SP - * | Arguments Or | // if needed. * | Varargs regs space | // Only for varargs functions; (varargs not implemented for LoongArch64) * |-----------------------| * | MonitorAcquired | // 8 bytes; for synchronized methods * |-----------------------| - * | PSP slot | // 8 bytes (omitted in NativeAOT ABI) + * | PSPSym | // 8 bytes, Only for frames with EH, (omitted in NativeAOT ABI) * |-----------------------| - * | locals, temps, etc. | + * |Callee saved registers | // not including FP/RA; multiple of 8 bytes * |-----------------------| - * | possible GS cookie | + * | Saved RA | // 8 bytes * |-----------------------| * | Saved FP | // 8 bytes * |-----------------------| - * | Saved RA | // 8 bytes + * | possible GS cookie | * |-----------------------| - * |Callee saved registers | // not including FP/RA; multiple of 8 bytes + * | locals, temps, etc. | + * |-----------------------| + * | possible GS cookie | * |-----------------------| * | Outgoing arg space | // multiple of 8 bytes; if required (i.e., #outsz != 0) * |-----------------------| <---- Ambient SP @@ -7748,6 +7623,9 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe regSet.rsMaskCalleeSaved = rsPushRegs | RBM_FPBASE | RBM_RA; #ifdef DEBUG + JITDUMP("Frame info. #outsz=%d; #framesz=%d; LclFrameSize=%d;\n", unsigned(compiler->lvaOutgoingArgSpaceSize), + genTotalFrameSize(), compiler->compLclFrameSize); + if (compiler->compCalleeRegsPushed != genCountBits(regSet.rsMaskCalleeSaved)) { printf("Error: unexpected number of callee-saved registers to push. Expected: %d. Got: %d ", @@ -7770,84 +7648,52 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe } #endif // DEBUG - // The frameType number is arbitrary, is defined below, and corresponds to one of the frame styles we - // generate based on various sizes. - int frameType = 0; - - // The amount to add from SP before starting to store the callee-saved registers. - int calleeSaveSPDelta = 0; - - // If we need to generate a GS cookie, we need to make sure the saved frame pointer and return address - // (FP and RA) are protected from buffer overrun by the GS cookie. If FP/RA are at the lowest addresses, - // then they are safe, since they are lower than any unsafe buffers. And the GS cookie we add will - // protect our caller's frame. If we have a localloc, however, that is dynamically placed lower than our - // saved FP/RA. In that case, we save FP/RA along with the rest of the callee-saved registers, above - // the GS cookie. - // - // After the frame is allocated, the frame pointer is established, pointing at the saved frame pointer to - // create a frame pointer chain. - // + int totalFrameSize = genTotalFrameSize(); + int leftFrameSize = 0; + int localFrameSize = compiler->compLclFrameSize; + if (compiler->lvaPSPSym != BAD_VAR_NUM) + { + localFrameSize -= TARGET_POINTER_SIZE; + } + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) + { + localFrameSize -= TARGET_POINTER_SIZE; + } - // This will be the starting place for saving the callee-saved registers, in increasing order. - int offset = compiler->lvaOutgoingArgSpaceSize; +#ifdef DEBUG + if (compiler->opts.disAsm) + { + printf("Frame info. #outsz=%d; #framesz=%d; lcl=%d\n", unsigned(compiler->lvaOutgoingArgSpaceSize), + genTotalFrameSize(), localFrameSize); + } +#endif - int totalFrameSize = genTotalFrameSize(); - // The (totalFrameSize <= 2040) condition ensures the offsets of st.d/ld.d. + int FP_offset = localFrameSize; if (totalFrameSize <= 2040) { GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, -totalFrameSize); compiler->unwindAllocStack(totalFrameSize); - - // Case #1. - // - // Generate: - // addi.d sp, sp, -framesz - // st.d callee_saved_registers ### not including the fp and ra. - // st.d ra,sp,outsz - // st.d fp,sp,outsz+8 - // - // After saving callee-saved registers, ra and fp, we establish the frame pointer with: - // addi.d fp, sp, (the offset of saving fp) - // We do this *after* saving callee-saved registers, so the prolog/epilog unwind codes mostly match. - - JITDUMP("Frame type 1. #outsz=%d; #framesz=%d; LclFrameSize=%d\n", unsigned(compiler->lvaOutgoingArgSpaceSize), - totalFrameSize, compiler->compLclFrameSize); - - frameType = 1; } else { - JITDUMP("Frame type 2. #outsz=%d; #framesz=%d; LclFrameSize=%d\n", unsigned(compiler->lvaOutgoingArgSpaceSize), - totalFrameSize, compiler->compLclFrameSize); - - frameType = 2; - - if ((offset + (compiler->compCalleeRegsPushed << 3)) >= 2040) - { - offset = totalFrameSize - compiler->lvaOutgoingArgSpaceSize; - calleeSaveSPDelta = AlignUp((UINT)offset, STACK_ALIGN); - offset = calleeSaveSPDelta - offset; - - genStackPointerAdjustment(-calleeSaveSPDelta, initReg, pInitRegZeroed, /* reportUnwindData */ true); - } - else + if ((localFrameSize + (compiler->compCalleeRegsPushed << 3)) > 2040) { - genStackPointerAdjustment(-totalFrameSize, initReg, pInitRegZeroed, /* reportUnwindData */ true); + leftFrameSize = localFrameSize & -16; + totalFrameSize = totalFrameSize - (localFrameSize & -16); + FP_offset = localFrameSize & 0xf; } + genStackPointerAdjustment(-totalFrameSize, initReg, pInitRegZeroed, /* reportUnwindData */ true); } + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - JITDUMP(" offset=%d, calleeSaveSPDelta=%d\n", offset, calleeSaveSPDelta); - genSaveCalleeSavedRegistersHelp(rsPushRegs, offset, 0); - offset += (int)(genCountBits(rsPushRegs) << 3); - - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, offset); - compiler->unwindSaveReg(REG_RA, offset); + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, offset + 8); - compiler->unwindSaveReg(REG_FP, offset + 8); + genSaveCalleeSavedRegistersHelp(rsPushRegs, FP_offset + 16, 0); - JITDUMP(" offsetSpToSavedFp=%d\n", offset + 8); - genEstablishFramePointer(offset + 8, /* reportUnwindData */ true); + JITDUMP(" offsetSpToSavedFp=%d\n", FP_offset); + genEstablishFramePointer(FP_offset, /* reportUnwindData */ true); // For varargs, home the incoming arg registers last. Note that there is nothing to unwind here, // so we just report "NOP" unwind codes. If there's no more frame setup after this, we don't @@ -7858,19 +7704,9 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe NYI_LOONGARCH64("genPushCalleeSavedRegisters unsupports compIsVarArgs"); } -#ifdef DEBUG - if (compiler->opts.disAsm) - { - assert(frameType != 0); - printf("DEBUG: LOONGARCH64, frameType:%d\n\n", frameType); - } -#endif - - if (calleeSaveSPDelta != 0) + if (leftFrameSize != 0) { - assert(frameType == 2); - calleeSaveSPDelta = totalFrameSize - calleeSaveSPDelta; - genStackPointerAdjustment(-calleeSaveSPDelta, initReg, pInitRegZeroed, /* reportUnwindData */ true); + genStackPointerAdjustment(-leftFrameSize, initReg, pInitRegZeroed, /* reportUnwindData */ true); } } @@ -7882,85 +7718,78 @@ void CodeGen::genPopCalleeSavedRegisters(bool jmpEpilog) assert(isFramePointerUsed()); - // This will be the starting place for restoring the callee-saved registers, in decreasing order. - int calleeSaveSPOffset = 0; - int remainingSPSize = 0; - int totalFrameSize = genTotalFrameSize(); - if (totalFrameSize <= 2040) + int localFrameSize = compiler->compLclFrameSize; + if (compiler->lvaPSPSym != BAD_VAR_NUM) + { + localFrameSize -= TARGET_POINTER_SIZE; + } + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) { - JITDUMP("Frame type 1. #outsz=%d; #framesz=%d; localloc? %s\n", unsigned(compiler->lvaOutgoingArgSpaceSize), - totalFrameSize, dspBool(compiler->compLocallocUsed)); + localFrameSize -= TARGET_POINTER_SIZE; + } + + JITDUMP("Frame type. #outsz=%d; #framesz=%d; #calleeSaveRegsPushed:%d; " + "localloc? %s\n", + unsigned(compiler->lvaOutgoingArgSpaceSize), totalFrameSize, compiler->compCalleeRegsPushed, + dspBool(compiler->compLocallocUsed)); + emitter* emit = GetEmitter(); + int FP_offset = localFrameSize; + int remainingSPSize = totalFrameSize; + if (totalFrameSize <= 2040) + { if (compiler->compLocallocUsed) { - int SPtoFPdelta = (compiler->compCalleeRegsPushed << 3) - 8 + compiler->lvaOutgoingArgSpaceSize; - + int SPtoFPdelta = genSPtoFPdelta(); // Restore sp from fp - GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -SPtoFPdelta); + emit->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -SPtoFPdelta); compiler->unwindSetFrameReg(REG_FPBASE, SPtoFPdelta); } - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize; - remainingSPSize = totalFrameSize; } else { - JITDUMP("Frame type 2. #outsz=%d; #framesz=%d; #calleeSaveRegsPushed:%d; " - "localloc? %s\n", - unsigned(compiler->lvaOutgoingArgSpaceSize), totalFrameSize, compiler->compCalleeRegsPushed, - dspBool(compiler->compLocallocUsed)); - - if ((compiler->lvaOutgoingArgSpaceSize + (compiler->compCalleeRegsPushed << 3)) > 2047) + if (compiler->compLocallocUsed) { - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize & -16; - if (compiler->compLocallocUsed) + int SPtoFPdelta = genSPtoFPdelta(); + // Restore sp from fp + if (emitter::isValidSimm12(SPtoFPdelta)) { - int SPtoFPdelta = (compiler->compCalleeRegsPushed << 3) - 8; - - // Restore sp from fp - GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -SPtoFPdelta); - compiler->unwindSetFrameReg(REG_FPBASE, SPtoFPdelta); + emit->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -SPtoFPdelta); } else { - genStackPointerAdjustment(calleeSaveSPOffset, REG_RA, nullptr, /* reportUnwindData */ true); + emit->emitIns_I_la(EA_PTRSIZE, REG_RA, SPtoFPdelta); + emit->emitIns_R_R_R(INS_sub_d, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, REG_RA); } - remainingSPSize = totalFrameSize - calleeSaveSPOffset; - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize - calleeSaveSPOffset; } - else + if ((localFrameSize + (compiler->compCalleeRegsPushed << 3)) > 2040) { - if (compiler->compLocallocUsed) - { - int SPtoFPdelta = (compiler->compCalleeRegsPushed << 3) - 8 + compiler->lvaOutgoingArgSpaceSize; + remainingSPSize = localFrameSize & -16; + genStackPointerAdjustment(remainingSPSize, REG_RA, nullptr, /* reportUnwindData */ true); - // Restore sp from fp - GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -SPtoFPdelta); - compiler->unwindSetFrameReg(REG_FPBASE, SPtoFPdelta); - } - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize; - remainingSPSize = totalFrameSize; + remainingSPSize = totalFrameSize - remainingSPSize; + FP_offset = localFrameSize & 0xf; } } - JITDUMP(" calleeSaveSPOffset=%d\n", calleeSaveSPOffset); - genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, calleeSaveSPOffset, 0); - calleeSaveSPOffset += (compiler->compCalleeRegsPushed - 2) << 3; + JITDUMP(" calleeSaveSPOffset=%d\n", FP_offset + 16); + genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, FP_offset + 16, 0); - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_RA, REG_SPBASE, calleeSaveSPOffset); - compiler->unwindSaveReg(REG_RA, calleeSaveSPOffset); + emit->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, calleeSaveSPOffset + 8); - compiler->unwindSaveReg(REG_FP, calleeSaveSPOffset + 8); + emit->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); if (emitter::isValidUimm11(remainingSPSize)) { - GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, remainingSPSize); + emit->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, remainingSPSize); } else { - GetEmitter()->emitIns_I_la(EA_PTRSIZE, REG_R21, remainingSPSize); - GetEmitter()->emitIns_R_R_R(INS_add_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, REG_R21); + emit->emitIns_I_la(EA_PTRSIZE, REG_R21, remainingSPSize); + emit->emitIns_R_R_R(INS_add_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, REG_R21); } compiler->unwindAllocStack(remainingSPSize); @@ -7972,12 +7801,12 @@ void CodeGen::genPopCalleeSavedRegisters(bool jmpEpilog) if (emitter::isValidUimm11(tier0FrameSize)) { - GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, tier0FrameSize); + emit->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, tier0FrameSize); } else { - GetEmitter()->emitIns_I_la(EA_PTRSIZE, REG_R21, tier0FrameSize); - GetEmitter()->emitIns_R_R_R(INS_add_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, REG_R21); + emit->emitIns_I_la(EA_PTRSIZE, REG_R21, tier0FrameSize); + emit->emitIns_R_R_R(INS_add_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, REG_R21); } compiler->unwindAllocStack(tier0FrameSize); } diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index 546ba7b3180899..b7c119be94987c 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -770,8 +770,8 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * addi sp, sp, -#framesz ; establish the frame * sd s1, #outsz(sp) ; save callee-saved registers, as necessary * sd s2, #(outsz+8)(sp) - * sd ra, #(outsz+?)(sp) ; save RA (8 bytes) - * sd fp, #(outsz+?+8)(sp) ; save FP (8 bytes) + * sd ra, #(outsz+?+8)(sp) ; save RA (8 bytes) + * sd fp, #(outsz+?)(sp) ; save FP (8 bytes) * * The funclet frame layout: * @@ -779,8 +779,7 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * |-----------------------| * | incoming arguments | * +=======================+ <---- Caller's SP - * | Arguments Or | // if needed - * | Varargs regs space | // Only for varargs functions; NYI on RV64 + * | Varargs regs space | // Only for varargs main functions; not used for RV64. * |-----------------------| * | MonitorAcquired | // 8 bytes; for synchronized methods * |-----------------------| @@ -788,11 +787,9 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * |-----------------------| * ~ alignment padding ~ // To make the whole frame 16 byte aligned * |-----------------------| - * | Saved FP | // 8 bytes + * |Callee saved registers | // multiple of 8 bytes, not including FP/RA * |-----------------------| - * | Saved RA | // 8 bytes - * |-----------------------| - * |Callee saved registers | // multiple of 8 bytes, not includting RA/FP + * | Saved FP, RA | // 16 bytes * |-----------------------| * | Outgoing arg space | // multiple of 8 bytes; if required (i.e., #outsz != 0) * |-----------------------| <---- Ambient SP @@ -801,31 +798,27 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * | | downward | * V * - * Note, that SP only change once. That means, there will be a maximum of one alignment slot needed. - * Also remember, the stack oiubter needs to be 16 byte aligned at all times. - * The size of the PSP slot plus callee-saved registers space is a maximum of 280 bytes: - * - * RA,FP registers - * 11 int callee-saved register s1-s11 - * 12 float callee-saved registers f8-f9, f18-f27 - * 8 saved integer argument registers a0-a7, if varargs function support. - * 1 PSP slot - * 1 alignment slot or monitor acquired slot - * == 35 slots * 8 bytes = 280 bytes. * * The outgoing argument size, however, can be very large, if we call a function that takes a large number of * arguments (note that we currently use the same outgoing argument space size in the funclet as for the main * function, even if the funclet doesn't have any calls, or has a much smaller, or larger, maximum number of - * outgoing arguments for any call). In that case, we need to 16-byte align the initial change to SP, before - * saving off the callee-saved registers and establishing the PSPsym, so we can use the limited immediate offset - * encodings we have available, before doing another 16-byte aligned SP adjustment to create the outgoing argument - * space. Both changes to SP might need to add alignment padding. + * outgoing arguments for any call). + * + * Note that in all cases, the PSPSym is in exactly the same position with respect to Caller-SP, + * and that location is the same relative to Caller-SP as in the main function where higher than + * the callee-saved registers. + * That is to say, the PSPSym's relative offset to Caller-SP is not depended on the callee-saved registers. + * + * Funclets do not have varargs arguments. However, because the PSPSym must exist at the same offset from Caller-SP as in the main function, we + * must add buffer space for the saved varargs/argument registers here, if the main function did the same. + * + * Note that localloc cannot be used in a funclet. * * An example epilog sequence: * addi sp, sp, #outsz ; if any outgoing argument space * ld s1, #(xxx-8)(sp) ; restore callee-saved registers * ld s2, #xxx(sp) - * ld ra, #(xxx+?-8)(sp) ; restore RA + * ld ra, #(xxx+?+8)(sp) ; restore RA * ld fp, #(xxx+?)(sp) ; restore FP * addi sp, sp, #framesz * jarl zero, ra @@ -840,8 +833,8 @@ void CodeGen::genFuncletProlog(BasicBlock* block) printf("*************** In genFuncletProlog()\n"); } #endif + // TODO-RISCV64: Implement varargs (NYI_RISCV64) - // TODO-RISCV64-CQ: We can use C extension for optimization assert(block != NULL); assert(block->HasFlag(BBF_FUNCLET_BEG)); @@ -852,9 +845,8 @@ void CodeGen::genFuncletProlog(BasicBlock* block) compiler->unwindBegProlog(); - const bool isFilter = (block->bbCatchTyp == BBCT_FILTER); - const int frameSize = genFuncletInfo.fiSpDelta; - + bool isFilter = (block->bbCatchTyp == BBCT_FILTER); + int frameSize = genFuncletInfo.fiSpDelta; assert(frameSize < 0); regMaskTP maskArgRegsLiveIn; @@ -871,53 +863,39 @@ void CodeGen::genFuncletProlog(BasicBlock* block) maskArgRegsLiveIn = RBM_A0; } - regMaskTP maskSaveRegs = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; - int regsSavedSize = (compiler->compCalleeRegsPushed - 2) << 3; - - int calleeSavedDelta = genFuncletInfo.fiSP_to_CalleeSaved_delta; - - emitter* emit = GetEmitter(); + regMaskTP maskSaveRegs = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; + int FP_offset = genFuncletInfo.fiSP_to_CalleeSaved_delta; - if (calleeSavedDelta + regsSavedSize + genFuncletInfo.fiCalleeSavedPadding <= 2040) + if ((FP_offset + (genCountBits(maskSaveRegs) << 3)) <= (2040 - 16)) // no FP/RA. { - calleeSavedDelta += genFuncletInfo.fiCalleeSavedPadding; - - // addi sp, sp, #frameSize genStackPointerAdjustment(frameSize, REG_SCRATCH, nullptr, /* reportUnwindData */ true); - genSaveCalleeSavedRegistersHelp(maskSaveRegs, calleeSavedDelta, 0); - calleeSavedDelta += regsSavedSize; + GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - // sd ra, #calleeSavedDelta(sp) - emit->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_RA, REG_SPBASE, calleeSavedDelta); - compiler->unwindSaveReg(REG_RA, calleeSavedDelta); + GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - // sd fp, #(calleeSavedDelta+8)(sp) - emit->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_FP, REG_SPBASE, calleeSavedDelta + 8); - compiler->unwindSaveReg(REG_FP, calleeSavedDelta + 8); + genSaveCalleeSavedRegistersHelp(maskSaveRegs, FP_offset + 16, 0); } else { assert(frameSize < -2040); - int spDelta = frameSize + calleeSavedDelta; + genStackPointerAdjustment(frameSize + (FP_offset & -16), REG_SCRATCH, nullptr, true); - // addi sp, sp, #spDelta - genStackPointerAdjustment(spDelta, REG_SCRATCH, nullptr, /* reportUnwindData */ true); + frameSize = -(FP_offset & -16); + FP_offset &= 0xf; - genSaveCalleeSavedRegistersHelp(maskSaveRegs, genFuncletInfo.fiCalleeSavedPadding, 0); - regsSavedSize += genFuncletInfo.fiCalleeSavedPadding; + GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - // sd ra, #regsSavedSize(sp) - emit->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_RA, REG_SPBASE, regsSavedSize); - compiler->unwindSaveReg(REG_RA, regsSavedSize); + GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - // sd fp, #(regsSavedSize+8)(sp) - emit->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_FP, REG_SPBASE, regsSavedSize + 8); - compiler->unwindSaveReg(REG_FP, regsSavedSize + 8); + genSaveCalleeSavedRegistersHelp(maskSaveRegs, FP_offset + 16, 0); - // addi sp, sp -#calleeSavedDelta - genStackPointerAdjustment(-calleeSavedDelta, REG_SCRATCH, nullptr, /* reportUnwindData */ true); + genStackPointerAdjustment(frameSize, REG_SCRATCH, nullptr, true); } // This is the end of the OS-reported prolog for purposes of unwinding @@ -977,66 +955,38 @@ void CodeGen::genFuncletEpilog() printf("*************** In genFuncletEpilog()\n"); } #endif - // TODO-RISCV64: Implement varargs (NYI_RISCV64) - // TODO-RISCV64-CQ: We can use C extension for optimization ScopedSetVariable _setGeneratingEpilog(&compiler->compGeneratingEpilog, true); compiler->unwindBegEpilog(); - const int frameSize = genFuncletInfo.fiSpDelta; - + int frameSize = genFuncletInfo.fiSpDelta; assert(frameSize < 0); - regMaskTP maskRestoreRegs = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; - int regsRestoreSize = (compiler->compCalleeRegsPushed - 2) << 3; - - int calleeSavedDelta = genFuncletInfo.fiSP_to_CalleeSaved_delta; + regMaskTP maskSaveRegs = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; + int FP_offset = genFuncletInfo.fiSP_to_CalleeSaved_delta; - emitter* emit = GetEmitter(); - regNumber tempReg = rsGetRsvdReg(); - - if (calleeSavedDelta + regsRestoreSize + genFuncletInfo.fiCalleeSavedPadding <= 2040) + if ((FP_offset + (genCountBits(maskSaveRegs) << 3)) > (2040 - 16)) // no FP/RA. { - calleeSavedDelta += genFuncletInfo.fiCalleeSavedPadding; - genRestoreCalleeSavedRegistersHelp(maskRestoreRegs, calleeSavedDelta, 0); - calleeSavedDelta += regsRestoreSize; - - // ld ra, #calleeSavedDelta(sp) - emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_RA, REG_SPBASE, calleeSavedDelta); - compiler->unwindSaveReg(REG_RA, calleeSavedDelta); + assert(frameSize < -2040); - // ld fp, #(calleeSavedDelta+8)(sp) - emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_FP, REG_SPBASE, calleeSavedDelta + 8); - compiler->unwindSaveReg(REG_FP, calleeSavedDelta + 8); + genStackPointerAdjustment(FP_offset & -16, REG_SCRATCH, nullptr, /* reportUnwindData */ true); - // addi sp, sp, -#frameSize - genStackPointerAdjustment(-frameSize, tempReg, nullptr, /* reportUnwindData */ true); + frameSize += FP_offset & -16; + FP_offset = FP_offset & 0xf; } - else - { - assert(frameSize < -2040); - - // addi sp, sp, #calleeSavedDelta - genStackPointerAdjustment(calleeSavedDelta, tempReg, nullptr, /* reportUnwindData */ true); - genRestoreCalleeSavedRegistersHelp(maskRestoreRegs, genFuncletInfo.fiCalleeSavedPadding, 0); - regsRestoreSize += genFuncletInfo.fiCalleeSavedPadding; + genRestoreCalleeSavedRegistersHelp(maskSaveRegs, FP_offset + 16, 0); - // ld ra, #regsRestoreSize(sp) - emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_RA, REG_SPBASE, regsRestoreSize); - compiler->unwindSaveReg(REG_RA, regsRestoreSize); + GetEmitter()->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - // ld fp, #(regsRestoreSize+8)(sp) - emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_FP, REG_SPBASE, regsRestoreSize + 8); - compiler->unwindSaveReg(REG_FP, regsRestoreSize + 8); + GetEmitter()->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - // addi sp, sp, -#(frameSize + calleeSavedDelta) - genStackPointerAdjustment(-(frameSize + calleeSavedDelta), tempReg, nullptr, /* reportUnwindData */ true); - } + genStackPointerAdjustment(-frameSize, REG_SCRATCH, nullptr, /* reportUnwindData */ true); - // jarl zero, ra - emit->emitIns_R_R_I(INS_jalr, emitActualTypeSize(TYP_I_IMPL), REG_R0, REG_RA, 0); + GetEmitter()->emitIns_R_R_I(INS_jalr, emitActualTypeSize(TYP_I_IMPL), REG_R0, REG_RA, 0); compiler->unwindReturn(REG_RA); compiler->unwindEndEpilog(); @@ -1059,7 +1009,6 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() } assert(isFramePointerUsed()); - // The frame size and offsets must be finalized assert(compiler->lvaDoneFrameLayout == Compiler::FINAL_FRAME_LAYOUT); @@ -1067,74 +1016,56 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() assert((rsMaskSaveRegs & RBM_RA) != 0); assert((rsMaskSaveRegs & RBM_FP) != 0); - unsigned pspSize = (compiler->lvaPSPSym != BAD_VAR_NUM) ? 8 : 0; - - // If there is a PSP slot, we have to pad the funclet frame size for OSR. - // For more details see CodeGen::genFuncletProlog + // Because a method and funclets must have the same caller-relative PSPSym offset, + // if there is a PSPSym, we have to pad the funclet frame size for OSR. // - unsigned osrPad = 0; - if (compiler->opts.IsOSR() && (pspSize != 0)) + int osrPad = 0; + if (compiler->opts.IsOSR()) { - osrPad = compiler->info.compPatchpointInfo->TotalFrameSize(); + osrPad -= compiler->info.compPatchpointInfo->TotalFrameSize(); - // osrPad must be aligned to stackSize - assert(osrPad % STACK_ALIGN == 0); + // OSR pad must be already aligned to stack size. + assert((osrPad % STACK_ALIGN) == 0); } - genFuncletInfo.fiCalleeSavedPadding = 0; - genFuncletInfo.fiFunction_CallerSP_to_FP_delta = genCallerSPtoFPdelta() - osrPad; - - unsigned savedRegsSize = genCountBits(rsMaskSaveRegs); - assert(savedRegsSize == compiler->compCalleeRegsPushed); - savedRegsSize <<= 3; + /* Now save it for future use */ + genFuncletInfo.fiFunction_CallerSP_to_FP_delta = genCallerSPtoFPdelta() + osrPad; - unsigned saveRegsPlusPSPSize = savedRegsSize + pspSize; + int funcletFrameSize = compiler->lvaOutgoingArgSpaceSize; - assert(compiler->lvaOutgoingArgSpaceSize % REGSIZE_BYTES == 0); - unsigned outgoingArgSpaceAligned = roundUp(compiler->lvaOutgoingArgSpaceSize, STACK_ALIGN); + genFuncletInfo.fiSP_to_CalleeSaved_delta = funcletFrameSize; - unsigned funcletFrameSize = osrPad + saveRegsPlusPSPSize + compiler->lvaOutgoingArgSpaceSize; - unsigned funcletFrameSizeAligned = roundUp(funcletFrameSize, STACK_ALIGN); + funcletFrameSize += genCountBits(rsMaskSaveRegs) * REGSIZE_BYTES; - int SP_to_CalleeSaved_delta = compiler->lvaOutgoingArgSpaceSize; - if ((SP_to_CalleeSaved_delta + savedRegsSize) >= 2040) + int delta_PSP = -TARGET_POINTER_SIZE; + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) { - int offset = funcletFrameSizeAligned - SP_to_CalleeSaved_delta; - SP_to_CalleeSaved_delta = AlignUp((UINT)offset, STACK_ALIGN); - - genFuncletInfo.fiCalleeSavedPadding = SP_to_CalleeSaved_delta - offset; + delta_PSP -= TARGET_POINTER_SIZE; } - if (compiler->lvaMonAcquired != BAD_VAR_NUM && !compiler->opts.IsOSR()) - { - // We furthermore allocate the "monitor acquired" bool between PSP and - // the saved registers because this is part of the EnC header. - // Note that OSR methods reuse the monitor bool created by tier 0. - osrPad += compiler->lvaLclSize(compiler->lvaMonAcquired); - } + funcletFrameSize = funcletFrameSize - delta_PSP - osrPad; + funcletFrameSize = roundUp((unsigned)funcletFrameSize, STACK_ALIGN); - /* Now save it for future use */ - genFuncletInfo.fiSpDelta = -(int)funcletFrameSizeAligned; + genFuncletInfo.fiSpDelta = -funcletFrameSize; genFuncletInfo.fiSaveRegs = rsMaskSaveRegs; - genFuncletInfo.fiSP_to_CalleeSaved_delta = SP_to_CalleeSaved_delta; - genFuncletInfo.fiSP_to_PSP_slot_delta = funcletFrameSizeAligned - osrPad - 8; - genFuncletInfo.fiCallerSP_to_PSP_slot_delta = -(int)osrPad - 8; + genFuncletInfo.fiSP_to_PSP_slot_delta = funcletFrameSize + delta_PSP + osrPad; + genFuncletInfo.fiCallerSP_to_PSP_slot_delta = osrPad + delta_PSP; #ifdef DEBUG if (verbose) { printf("\n"); printf("Funclet prolog / epilog info\n"); - printf(" Save regs: "); + printf(" Save regs: "); dspRegMask(genFuncletInfo.fiSaveRegs); printf("\n"); if (compiler->opts.IsOSR()) { - printf(" OSR Pad: %d\n", osrPad); + printf(" OSR Pad: %d\n", osrPad); } - printf(" Function CallerSP-to-FP delta: %d\n", genFuncletInfo.fiFunction_CallerSP_to_FP_delta); + printf(" Function CallerSP-to-FP delta: %d\n", genFuncletInfo.fiFunction_CallerSP_to_FP_delta); printf(" SP to CalleeSaved location delta: %d\n", genFuncletInfo.fiSP_to_CalleeSaved_delta); - printf(" SP delta: %d\n", genFuncletInfo.fiSpDelta); + printf(" SP delta: %d\n", genFuncletInfo.fiSpDelta); } assert(genFuncletInfo.fiSP_to_CalleeSaved_delta >= 0); @@ -4224,9 +4155,17 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree) int CodeGenInterface::genSPtoFPdelta() const { assert(isFramePointerUsed()); - assert(compiler->compCalleeRegsPushed >= 2); + assert(compiler->compCalleeRegsPushed >= 2); // always FP/RA. - int delta = compiler->lvaOutgoingArgSpaceSize + (compiler->compCalleeRegsPushed << 3) - 8; + int delta = compiler->compLclFrameSize; + if (compiler->lvaPSPSym != BAD_VAR_NUM) + { + delta -= TARGET_POINTER_SIZE; + } + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) + { + delta -= TARGET_POINTER_SIZE; + } assert(delta >= 0); return delta; @@ -7733,8 +7672,8 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) * sd s11, #(offset+8*10)(sp) * * ; save ra, fp - * sd ra, #offset3(sp) ; save RA (8 bytes) - * sd fp, #(offset3+8)(sp) ; save FP (8 bytes) + * sd ra, #offset3+8(sp) ; save RA (8 bytes) + * sd fp, #(offset3)(sp) ; save FP (8 bytes) * * Notes: * 1. FP is always saved, and the first store is FP, RA. @@ -7742,9 +7681,9 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) * 3. For frames with varargs, not implemented completely and not tested ! * 4. We allocate the frame here; no further changes to SP are allowed (except in the body, for localloc). * - * For functions with GS and localloc, we change the frame so the frame pointer and RA are saved at the top - * of the frame, just under the varargs registers (if any). Note that the funclet frames must follow the same - * rule, and both main frame and funclet frames (if any) must put PSPSym in the same offset from Caller-SP. + * For functions with GS and localloc, we had saved the frame pointer and RA at the top + * of the frame. Note that the funclet frames must follow the same rule, + * and both main frame and funclet frames (if any) must put PSPSym in the same offset from Caller-SP. * Since this frame type is relatively rare, we force using it via stress modes, for additional coverage. * * The frames look like the following (simplified to only include components that matter for establishing the @@ -7752,6 +7691,10 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) * * The RISC-V's frame layout is liking: * + * If we need to generate a GS cookie, we need to make sure the saved frame pointer and return address + * (FP and RA) are protected from buffer overrun by the GS cookie. + * So we always save the FP/RA along with the rest of the callee-saved registers above. + * * | | * |-----------------------| * | incoming arguments | @@ -7763,15 +7706,17 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) * |-----------------------| * | PSP slot | // 8 bytes (omitted in NativeAOT ABI) * |-----------------------| - * | locals, temps, etc. | - * |-----------------------| - * | possible GS cookie | + * |Callee saved registers | // not including FP/RA; multiple of 8 bytes * |-----------------------| * | Saved FP | // 8 bytes * |-----------------------| * | Saved RA | // 8 bytes * |-----------------------| - * |Callee saved registers | // not including FP/RA; multiple of 8 bytes + * | possible GS cookie | + * |-----------------------| + * | locals, temps, etc. | + * |-----------------------| + * | possible GS cookie | * |-----------------------| * | Outgoing arg space | // multiple of 8 bytes; if required (i.e., #outsz != 0) * |-----------------------| <---- Ambient SP @@ -7785,12 +7730,6 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe { assert(compiler->compGeneratingProlog); - // The 'initReg' could have been calculated as one of the callee-saved registers (let's say T0, T1 and T2 are in - // use, so the next possible register is S1, which should be callee-save register). This is fine, as long as we - // save callee-saved registers before using 'initReg' for the first time. Instead, we can use REG_SCRATCH - // beforehand. We don't care if REG_SCRATCH will be overwritten, so we'll skip 'RegZeroed check'. - // - // Unlike on x86/x64, we can also push float registers to stack regMaskTP rsPushRegs = regSet.rsGetModifiedCalleeSavedRegsMask(); #if ETW_EBP_FRAMED @@ -7800,7 +7739,7 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe } #endif - // On RV64 we always use the FP (frame-pointer) + // We always use the FP (frame-pointer). assert(isFramePointerUsed()); // @@ -7823,25 +7762,25 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe // is not worth it. // - // we will push callee-saved registers along with fp and ra registers to stack - regMaskTP rsPushRegsMask = rsPushRegs | RBM_FP | RBM_RA; - regSet.rsMaskCalleeSaved = rsPushRegsMask; + regSet.rsMaskCalleeSaved = rsPushRegs | RBM_FPBASE | RBM_RA; #ifdef DEBUG - if (compiler->compCalleeRegsPushed != genCountBits(rsPushRegsMask)) + JITDUMP("Frame info. #outsz=%d; #framesz=%d; LclFrameSize=%d;\n", unsigned(compiler->lvaOutgoingArgSpaceSize), + genTotalFrameSize(), compiler->compLclFrameSize); + + if (compiler->compCalleeRegsPushed != genCountBits(regSet.rsMaskCalleeSaved)) { printf("Error: unexpected number of callee-saved registers to push. Expected: %d. Got: %d ", - compiler->compCalleeRegsPushed, genCountBits(rsPushRegsMask)); - dspRegMask(rsPushRegsMask); + compiler->compCalleeRegsPushed, genCountBits(rsPushRegs | RBM_FPBASE | RBM_RA)); + dspRegMask(rsPushRegs | RBM_FPBASE | RBM_RA); printf("\n"); - assert(compiler->compCalleeRegsPushed == genCountBits(rsPushRegsMask)); + assert(compiler->compCalleeRegsPushed == genCountBits(rsPushRegs | RBM_FPBASE | RBM_RA)); } if (verbose) { - regMaskTP maskSaveRegsFloat = rsPushRegs & RBM_FLT_CALLEE_SAVED; - regMaskTP maskSaveRegsInt = rsPushRegs & RBM_INT_CALLEE_SAVED; - + regMaskTP maskSaveRegsFloat = rsPushRegs & RBM_ALLFLOAT; + regMaskTP maskSaveRegsInt = rsPushRegs & ~maskSaveRegsFloat; printf("Save float regs: "); dspRegMask(maskSaveRegsFloat); printf("\n"); @@ -7851,80 +7790,57 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe } #endif // DEBUG - // The frameType number is arbitrary, is defined below, and corresponds to one of the frame styles we - // generate based on various sizes. - int frameType = 0; - - // The amount to subtract from SP before starting to store the callee-saved registers. It might be folded into the - // first save instruction as a "predecrement" amount, if possible. - int calleeSaveSPDelta = 0; - - // If we need to generate a GS cookie, we need to make sure the saved frame pointer and return address - // (FP and RA) are protected from buffer overrun by the GS cookie. If FP/RA are at the lowest addresses, - // then they are safe, since they are lower than any unsafe buffers. And the GS cookie we add will - // protect our caller's frame. If we have a localloc, however, that is dynamically placed lower than our - // saved FP/RA. In that case, we save FP/RA along with the rest of the callee-saved registers, above - // the GS cookie. - // - // After the frame is allocated, the frame pointer is established, pointing at the saved frame pointer to - // create a frame pointer chain. - // - - // This will be the starting place for saving the callee-saved registers, in increasing order. - int offset = compiler->lvaOutgoingArgSpaceSize; - int totalFrameSize = genTotalFrameSize(); + int leftFrameSize = 0; + int localFrameSize = compiler->compLclFrameSize; + if (compiler->lvaPSPSym != BAD_VAR_NUM) + { + localFrameSize -= TARGET_POINTER_SIZE; + } + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) + { + localFrameSize -= TARGET_POINTER_SIZE; + } - emitter* emit = GetEmitter(); +#ifdef DEBUG + if (compiler->opts.disAsm) + { + printf("Frame info. #outsz=%d; #framesz=%d; lcl=%d\n", unsigned(compiler->lvaOutgoingArgSpaceSize), + genTotalFrameSize(), localFrameSize); + } +#endif - // ensure offset of sd/ld + int FP_offset = localFrameSize; if (totalFrameSize <= 2040) { - frameType = 1; - - emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, -totalFrameSize); + GetEmitter()->emitIns_R_R_I(INS_addi, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, -totalFrameSize); compiler->unwindAllocStack(totalFrameSize); - - JITDUMP("Frame type 1. #outsz=%d; #framesz=%d; LclFrameSize=%d\n", unsigned(compiler->lvaOutgoingArgSpaceSize), - totalFrameSize, compiler->compLclFrameSize); } else { - frameType = 2; - // we have to adjust stack pointer; probably using add instead of addi - - JITDUMP("Frame type 2. #outsz=%d; #framesz=%d; LclFrameSize=%d\n", unsigned(compiler->lvaOutgoingArgSpaceSize), - totalFrameSize, compiler->compLclFrameSize); - - if ((offset + (compiler->compCalleeRegsPushed << 3)) >= 2040) - { - offset = totalFrameSize - compiler->lvaOutgoingArgSpaceSize; - calleeSaveSPDelta = AlignUp((UINT)offset, STACK_ALIGN); - offset = calleeSaveSPDelta - offset; - - genStackPointerAdjustment(-calleeSaveSPDelta, REG_SCRATCH, nullptr, /* reportUnwindData */ true); - } - else + if ((localFrameSize + (compiler->compCalleeRegsPushed << 3)) > 2040) { - genStackPointerAdjustment(-totalFrameSize, REG_SCRATCH, nullptr, /* reportUnwindData */ true); + leftFrameSize = localFrameSize & -16; + totalFrameSize = totalFrameSize - (localFrameSize & -16); + FP_offset = localFrameSize & 0xf; } + // The 'initReg' could have been calculated as one of the callee-saved registers (let's say T0, T1 and T2 are in + // use, so the next possible register is S1, which should be callee-save register). This is fine, as long as we + // save callee-saved registers before using 'initReg' for the first time. Instead, we can use REG_SCRATCH + // beforehand. We don't care if REG_SCRATCH will be overwritten, so we'll skip 'RegZeroed check'. + // TODO-RV64: this should be resolved before calling `genPushCalleeSavedRegisters`. + genStackPointerAdjustment(-totalFrameSize, REG_SCRATCH, nullptr, /* reportUnwindData */ true); } + GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - JITDUMP(" offset=%d, calleeSaveSPDelta=%d\n", offset, calleeSaveSPDelta); - - genSaveCalleeSavedRegistersHelp(rsPushRegs, offset, 0); - offset += (int)(genCountBits(rsPushRegs) << 3); // each reg has 8 bytes + GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - // From now on, we can safely use initReg. + genSaveCalleeSavedRegistersHelp(rsPushRegs, FP_offset + 16, 0); - emit->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_RA, REG_SPBASE, offset); - compiler->unwindSaveReg(REG_RA, offset); - - emit->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_FP, REG_SPBASE, offset + 8); - compiler->unwindSaveReg(REG_FP, offset + 8); - - JITDUMP(" offsetSpToSavedFp=%d\n", offset + 8); - genEstablishFramePointer(offset + 8, /* reportUnwindData */ true); + JITDUMP(" offsetSpToSavedFp=%d\n", FP_offset); + genEstablishFramePointer(FP_offset, /* reportUnwindData */ true); // For varargs, home the incoming arg registers last. Note that there is nothing to unwind here, // so we just report "NOP" unwind codes. If there's no more frame setup after this, we don't @@ -7935,18 +7851,9 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe NYI_RISCV64("genPushCalleeSavedRegisters unsupports compIsVarArgs"); } -#ifdef DEBUG - if (compiler->opts.disAsm) - { - printf("DEBUG: RISCV64, frameType:%d\n\n", frameType); - } -#endif - - if (calleeSaveSPDelta != 0) + if (leftFrameSize != 0) { - assert(frameType == 2); - calleeSaveSPDelta = totalFrameSize - calleeSaveSPDelta; - genStackPointerAdjustment(-calleeSaveSPDelta, initReg, pInitRegZeroed, /* reportUnwindData */ true); + genStackPointerAdjustment(-leftFrameSize, REG_SCRATCH, nullptr, /* reportUnwindData */ true); } } @@ -7956,80 +7863,72 @@ void CodeGen::genPopCalleeSavedRegisters(bool jmpEpilog) regMaskTP regsToRestoreMask = regSet.rsGetModifiedCalleeSavedRegsMask(); - // On RV64 we always use the FP (frame-pointer) assert(isFramePointerUsed()); - int totalFrameSize = genTotalFrameSize(); - int remainingSPSize = totalFrameSize; - int callerSPtoFPdelta = 0; - int calleeSaveSPOffset = 0; // This will be the starting place for restoring - // the callee-saved registers, in decreasing order. + int totalFrameSize = genTotalFrameSize(); + int localFrameSize = compiler->compLclFrameSize; + if (compiler->lvaPSPSym != BAD_VAR_NUM) + { + localFrameSize -= TARGET_POINTER_SIZE; + } + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) + { + localFrameSize -= TARGET_POINTER_SIZE; + } - emitter* emit = GetEmitter(); + JITDUMP("Frame type. #outsz=%d; #framesz=%d; #calleeSaveRegsPushed:%d; " + "localloc? %s\n", + unsigned(compiler->lvaOutgoingArgSpaceSize), totalFrameSize, compiler->compCalleeRegsPushed, + dspBool(compiler->compLocallocUsed)); - // ensure offset of sd/ld + emitter* emit = GetEmitter(); + int FP_offset = localFrameSize; + int remainingSPSize = totalFrameSize; if (totalFrameSize <= 2040) { - JITDUMP("Frame type 1. #outsz=%d; #framesz=%d; localloc? %s\n", unsigned(compiler->lvaOutgoingArgSpaceSize), - totalFrameSize, dspBool(compiler->compLocallocUsed)); - if (compiler->compLocallocUsed) { - callerSPtoFPdelta = (compiler->compCalleeRegsPushed << 3) - 8 + compiler->lvaOutgoingArgSpaceSize; + int SPtoFPdelta = genSPtoFPdelta(); + // Restore sp from fp + emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -SPtoFPdelta); + compiler->unwindSetFrameReg(REG_FPBASE, SPtoFPdelta); } - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize; - // remainingSPSize = totalFrameSize; } else { - JITDUMP("Frame type 2. #outsz=%d; #framesz=%d; calleeSaveRegsPushed: %d; localloc? %s\n", - unsigned(compiler->lvaOutgoingArgSpaceSize), totalFrameSize, compiler->compCalleeRegsPushed, - dspBool(compiler->compLocallocUsed)); - - if ((compiler->lvaOutgoingArgSpaceSize + (compiler->compCalleeRegsPushed << 3)) > 2047) + if (compiler->compLocallocUsed) { - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize & 0xfffffff0; - - if (compiler->compLocallocUsed) + int SPtoFPdelta = genSPtoFPdelta(); + // Restore sp from fp + if (emitter::isValidSimm12(SPtoFPdelta)) { - callerSPtoFPdelta = (compiler->compCalleeRegsPushed << 3) - 8; + emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -SPtoFPdelta); } else { - genStackPointerAdjustment(calleeSaveSPOffset, REG_RA, nullptr, /* reportUnwindData */ true); + regNumber tempReg = rsGetRsvdReg(); + emit->emitLoadImmediate(EA_PTRSIZE, tempReg, SPtoFPdelta); + emit->emitIns_R_R_R(INS_sub, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, tempReg); } - remainingSPSize = totalFrameSize - calleeSaveSPOffset; - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize - calleeSaveSPOffset; } - else + if ((localFrameSize + (compiler->compCalleeRegsPushed << 3)) > 2040) { - if (compiler->compLocallocUsed) - { - callerSPtoFPdelta = (compiler->compCalleeRegsPushed << 3) - 8 + compiler->lvaOutgoingArgSpaceSize; - } - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize; - // remainingSPSize = totalFrameSize; - } - } + remainingSPSize = localFrameSize & -16; + genStackPointerAdjustment(remainingSPSize, REG_RA, nullptr, /* reportUnwindData */ true); - if (compiler->compLocallocUsed) - { - // restore sp form fp: addi sp, -#callerSPtoFPdelta(fp) - emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -callerSPtoFPdelta); - compiler->unwindSetFrameReg(REG_FPBASE, callerSPtoFPdelta); + remainingSPSize = totalFrameSize - remainingSPSize; + FP_offset = localFrameSize & 0xf; + } } - JITDUMP(" calleeSaveSPOffset=%d, callerSPtoFPdelta=%d\n", calleeSaveSPOffset, callerSPtoFPdelta); - genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, calleeSaveSPOffset, 0); - - // restore ra/fp regs - calleeSaveSPOffset += (compiler->compCalleeRegsPushed - 2) << 3; + JITDUMP(" calleeSaveSPOffset=%d\n", FP_offset + 16); + genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, FP_offset + 16, 0); - emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_RA, REG_SPBASE, calleeSaveSPOffset); - compiler->unwindSaveReg(REG_RA, calleeSaveSPOffset); + emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_FP, REG_SPBASE, calleeSaveSPOffset + 8); - compiler->unwindSaveReg(REG_FP, calleeSaveSPOffset + 8); + emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); if (emitter::isValidUimm11(remainingSPSize)) { @@ -8043,7 +7942,7 @@ void CodeGen::genPopCalleeSavedRegisters(bool jmpEpilog) } compiler->unwindAllocStack(remainingSPSize); - // for OSR we have to adjust SP to remove tier0 frame + // For OSR, we must also adjust the SP to remove the Tier0 frame. if (compiler->opts.IsOSR()) { const int tier0FrameSize = compiler->info.compPatchpointInfo->TotalFrameSize(); diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index c101955fdea7ed..e6645e1f03d8f4 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -5669,23 +5669,52 @@ void Compiler::lvaFixVirtualFrameOffsets() // We set FP to be after LR, FP delta += 2 * REGSIZE_BYTES; } -#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) +#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) else { // FP is used. JITDUMP("--- delta bump %d for FP frame\n", codeGen->genTotalFrameSize() - codeGen->genSPtoFPdelta()); delta += codeGen->genTotalFrameSize() - codeGen->genSPtoFPdelta(); } -#endif // TARGET_AMD64 || TARGET_ARM64 || TARGET_LOONGARCH64 || TARGET_RISCV64 +#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) + else + { + // FP is used. + delta += (compCalleeRegsPushed << 3); + + if ((lvaMonAcquired != BAD_VAR_NUM) && !opts.IsOSR()) + { + int offset = lvaTable[lvaMonAcquired].GetStackOffset() + delta; + lvaTable[lvaMonAcquired].SetStackOffset(offset); + + if (lvaPSPSym != BAD_VAR_NUM) + { + int offset = lvaTable[lvaPSPSym].GetStackOffset() + delta; + lvaTable[lvaPSPSym].SetStackOffset(offset); + delta += TARGET_POINTER_SIZE; + } + + delta += lvaLclSize(lvaMonAcquired); + } + else if (lvaPSPSym != BAD_VAR_NUM) + { + int offset = lvaTable[lvaPSPSym].GetStackOffset() + delta; + lvaTable[lvaPSPSym].SetStackOffset(offset); + delta += TARGET_POINTER_SIZE; + } + + JITDUMP("--- delta bump %d for FP frame\n", delta); + } +#endif // !TARGET_LOONGARCH64 || !TARGET_RISCV64 if (opts.IsOSR()) { -#if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) // Stack offset includes Tier0 frame. // JITDUMP("--- delta bump %d for OSR + Tier0 frame\n", info.compPatchpointInfo->TotalFrameSize()); delta += info.compPatchpointInfo->TotalFrameSize(); -#endif +#endif // TARGET_AMD64 || TARGET_ARM64 } JITDUMP("--- virtual stack offset to actual stack offset delta is %d\n", delta); @@ -5775,26 +5804,20 @@ void Compiler::lvaFixVirtualFrameOffsets() #endif // FEATURE_FIXED_OUT_ARGS -#if defined(TARGET_ARM64) +#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) // We normally add alignment below the locals between them and the outgoing // arg space area. When we store fp/lr(ra) at the bottom, however, this will // be below the alignment. So we should not apply the alignment adjustment to // them. It turns out we always store these at +0 and +8 of the FP, // so instead of dealing with skipping adjustment just for them we just set // them here always. + // For LoongArch64 and RISCV64, the RA is always at fp+8. assert(codeGen->isFramePointerUsed()); if (lvaRetAddrVar != BAD_VAR_NUM) { lvaTable[lvaRetAddrVar].SetStackOffset(REGSIZE_BYTES); } -#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - assert(codeGen->isFramePointerUsed()); - if (lvaRetAddrVar != BAD_VAR_NUM) - { - // For LoongArch64 and RISCV64, the RA is below the fp. see the `genPushCalleeSavedRegisters` - lvaTable[lvaRetAddrVar].SetStackOffset(-REGSIZE_BYTES); - } -#endif // !TARGET_LOONGARCH64 +#endif // !TARGET_ARM64 || !TARGET_LOONGARCH64 || !TARGET_RISCV64 } #ifdef TARGET_ARM @@ -6548,9 +6571,13 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() // if (opts.IsOSR()) { +#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) + originalFrameStkOffs = info.compPatchpointInfo->TotalFrameSize(); +#else originalFrameSize = info.compPatchpointInfo->TotalFrameSize(); originalFrameStkOffs = stkOffs; stkOffs -= originalFrameSize; +#endif } #ifdef TARGET_XARCH @@ -6606,7 +6633,8 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() #elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - assert(compCalleeRegsPushed >= 2); + assert(compCalleeRegsPushed >= 2); // always FP/RA. + stkOffs -= (compCalleeRegsPushed << 3); #else // !TARGET_LOONGARCH64 && !TARGET_RISCV64 #ifdef TARGET_ARM @@ -7331,14 +7359,9 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() } #endif // FEATURE_FIXED_OUT_ARGS -#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - // For LoongArch64 and RISCV64, CalleeSavedRegs are at bottom. - int pushedCount = 0; -#else // compLclFrameSize equals our negated virtual stack offset minus the pushed registers and return address // and the pushed frame pointer register which for some strange reason isn't part of 'compCalleeRegsPushed'. int pushedCount = compCalleeRegsPushed; -#endif #ifdef TARGET_ARM64 if (info.compIsVarArgs) diff --git a/src/coreclr/jit/regset.h b/src/coreclr/jit/regset.h index dae93baebad306..20b55610594fc6 100644 --- a/src/coreclr/jit/regset.h +++ b/src/coreclr/jit/regset.h @@ -158,8 +158,9 @@ class RegSet regMaskTP _rsMaskVars; // backing store for rsMaskVars property #if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) + // TODO: the funclet's callee-saved registers should not shared with main function. regMaskTP rsMaskCalleeSaved; // mask of the registers pushed/popped in the prolog/epilog -#endif // TARGET_ARMARCH || TARGET_LOONGARCH64 +#endif // TARGET_ARMARCH || TARGET_LOONGARCH64 || TARGET_RISCV64 public: // TODO-Cleanup: Should be private, but Compiler uses it regMaskTP rsMaskResvd; // mask of the registers that are reserved for special purposes (typically empty) From 56dcfd700383a9462d4b8632e88abd75b4252357 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 23 Apr 2024 08:15:15 -0400 Subject: [PATCH 057/248] Remove some dead code from SharedArrayPool (#101410) In Trim, for high memory pressure, we're already setting the number of arrays to trim equal to the max number possible, so the subsequent logic that would increase the count wasn't useful. Deleting that also deleted the last use of _elementSize, which in turn allowed for the path that provided that value to be cleaned up. --- .../src/System/Buffers/SharedArrayPool.cs | 68 ++++--------------- 1 file changed, 15 insertions(+), 53 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/SharedArrayPool.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/SharedArrayPool.cs index 89bbd450452391..3fa044d074d607 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/SharedArrayPool.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/SharedArrayPool.cs @@ -40,10 +40,7 @@ internal sealed partial class SharedArrayPool : ArrayPool /// Allocate a new and try to store it into the array. private unsafe SharedArrayPoolPartitions CreatePerCorePartitions(int bucketIndex) { -#pragma warning disable 8500 // sizeof of managed types - int elementSize = sizeof(T); -#pragma warning restore 8500 - var inst = new SharedArrayPoolPartitions(elementSize); + var inst = new SharedArrayPoolPartitions(); return Interlocked.CompareExchange(ref _buckets[bucketIndex], inst, null) ?? inst; } @@ -199,7 +196,7 @@ public bool Trim() SharedArrayPoolPartitions?[] perCoreBuckets = _buckets; for (int i = 0; i < perCoreBuckets.Length; i++) { - perCoreBuckets[i]?.Trim(currentMilliseconds, Id, pressure, Utilities.GetMaxSizeForBucket(i)); + perCoreBuckets[i]?.Trim(currentMilliseconds, Id, pressure); } // Trim each of the TLS buckets. Note that threads may be modifying their TLS slots concurrently with @@ -323,14 +320,13 @@ internal sealed class SharedArrayPoolPartitions private readonly Partition[] _partitions; /// Initializes the partitions. - /// The size of the elements stored in arrays. - public SharedArrayPoolPartitions(int elementSize) + public SharedArrayPoolPartitions() { // Create the partitions. We create as many as there are processors, limited by our max. var partitions = new Partition[SharedArrayPoolStatics.s_partitionCount]; for (int i = 0; i < partitions.Length; i++) { - partitions[i] = new Partition(elementSize); + partitions[i] = new Partition(); } _partitions = partitions; } @@ -374,23 +370,20 @@ public bool TryPush(Array array) return null; } - public void Trim(int currentMilliseconds, int id, Utilities.MemoryPressure pressure, int bucketSize) + public void Trim(int currentMilliseconds, int id, Utilities.MemoryPressure pressure) { Partition[] partitions = _partitions; for (int i = 0; i < partitions.Length; i++) { - partitions[i].Trim(currentMilliseconds, id, pressure, bucketSize); + partitions[i].Trim(currentMilliseconds, id, pressure); } } /// Provides a simple, bounded stack of arrays, protected by a lock. - /// The size of the elements stored in arrays. - private sealed class Partition(int elementSize) + private sealed class Partition { /// The arrays in the partition. private readonly Array?[] _arrays = new Array[SharedArrayPoolStatics.s_maxArraysPerPartition]; - /// The size of the elements stored in arrays. - private readonly int _elementSize = elementSize; /// Number of arrays stored in . private int _count; /// Timestamp set by Trim when it sees this as 0. @@ -437,20 +430,11 @@ public bool TryPush(Array array) return arr; } - public void Trim(int currentMilliseconds, int id, Utilities.MemoryPressure pressure, int bucketSize) + public void Trim(int currentMilliseconds, int id, Utilities.MemoryPressure pressure) { const int TrimAfterMS = 60 * 1000; // Trim after 60 seconds for low/moderate pressure const int HighTrimAfterMS = 10 * 1000; // Trim after 10 seconds for high pressure - const int LargeBucket = 16384; // If the bucket is larger than this we'll trim an extra when under high pressure - - const int ModerateTypeSize = 16; // If T is larger than this we'll trim an extra when under high pressure - const int LargeTypeSize = 32; // If T is larger than this we'll trim an extra (additional) when under high pressure - - const int LowTrimCount = 1; // Trim one item when pressure is low - const int MediumTrimCount = 2; // Trim two items when pressure is moderate - int HighTrimCount = SharedArrayPoolStatics.s_maxArraysPerPartition; // Trim all items when pressure is high - if (_count == 0) { return; @@ -477,38 +461,16 @@ public void Trim(int currentMilliseconds, int id, Utilities.MemoryPressure press } // We've elapsed enough time since the first item went into the partition. - // Drop the top item so it can be collected and make the partition look a little newer. + // Drop the top item(s) so they can be collected. - ArrayPoolEventSource log = ArrayPoolEventSource.Log; - int trimCount = LowTrimCount; - switch (pressure) + int trimCount = pressure switch { - case Utilities.MemoryPressure.High: - trimCount = HighTrimCount; - - // When pressure is high, aggressively trim larger arrays. - if (bucketSize > LargeBucket) - { - trimCount++; - } - - if (_elementSize > ModerateTypeSize) - { - trimCount++; - - if (_elementSize > LargeTypeSize) - { - trimCount++; - } - } - - break; - - case Utilities.MemoryPressure.Medium: - trimCount = MediumTrimCount; - break; - } + Utilities.MemoryPressure.High => SharedArrayPoolStatics.s_maxArraysPerPartition, + Utilities.MemoryPressure.Medium => 2, + _ => 1, + }; + ArrayPoolEventSource log = ArrayPoolEventSource.Log; while (_count > 0 && trimCount-- > 0) { Array? array = _arrays[--_count]; From b4e0169bfe10cfe69f6e7a8952b8f80fdfe9e31e Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 23 Apr 2024 09:11:55 -0400 Subject: [PATCH 058/248] Dedup UnboundedChannel and UnboundedPriorityChannel (#101396) * Dedup UnboundedChannel and UnboundedPriorityChannel We can use generic specialization to avoid duplicating all the code for the different queue types. This should also make it much simpler to add other queue types in the future. * Address PR feedback --- .../src/System.Threading.Channels.csproj | 2 +- .../src/System/Threading/Channels/Channel.cs | 35 +- .../Threading/Channels/Channel.netcoreapp.cs | 44 ++- .../Threading/Channels/IDebugEnumerator.cs | 4 +- .../Channels/IUnboundedChannelQueue.cs | 35 ++ .../Threading/Channels/UnboundedChannel.cs | 92 +++-- .../Channels/UnboundedPriorityChannel.cs | 369 ------------------ 7 files changed, 179 insertions(+), 402 deletions(-) create mode 100644 src/libraries/System.Threading.Channels/src/System/Threading/Channels/IUnboundedChannelQueue.cs delete mode 100644 src/libraries/System.Threading.Channels/src/System/Threading/Channels/UnboundedPriorityChannel.cs diff --git a/src/libraries/System.Threading.Channels/src/System.Threading.Channels.csproj b/src/libraries/System.Threading.Channels/src/System.Threading.Channels.csproj index c058b0b216b17a..a5030bcee65616 100644 --- a/src/libraries/System.Threading.Channels/src/System.Threading.Channels.csproj +++ b/src/libraries/System.Threading.Channels/src/System.Threading.Channels.csproj @@ -25,6 +25,7 @@ System.Threading.Channel<T> + @@ -44,7 +45,6 @@ System.Threading.Channel<T> - diff --git a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.cs b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.cs index 317636579a05fd..834d8ad88ed1d7 100644 --- a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.cs +++ b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.cs @@ -1,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. +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + namespace System.Threading.Channels { /// Provides static methods for creating channels. @@ -9,7 +13,7 @@ public static partial class Channel /// Creates an unbounded channel usable by any number of readers and writers concurrently. /// The created channel. public static Channel CreateUnbounded() => - new UnboundedChannel(runContinuationsAsynchronously: true); + new UnboundedChannel>(new(new()), runContinuationsAsynchronously: true); /// Creates an unbounded channel subject to the provided options. /// Specifies the type of data in the channel. @@ -27,7 +31,7 @@ public static Channel CreateUnbounded(UnboundedChannelOptions options) return new SingleConsumerUnboundedChannel(!options.AllowSynchronousContinuations); } - return new UnboundedChannel(!options.AllowSynchronousContinuations); + return new UnboundedChannel>(new(new()), !options.AllowSynchronousContinuations); } /// Creates a channel with the specified maximum capacity. @@ -71,5 +75,32 @@ public static Channel CreateBounded(BoundedChannelOptions options, Action< return new BoundedChannel(options.Capacity, options.FullMode, !options.AllowSynchronousContinuations, itemDropped); } + + /// Provides an for a . + private readonly struct UnboundedChannelConcurrentQueue(ConcurrentQueue queue) : IUnboundedChannelQueue + { + private readonly ConcurrentQueue _queue = queue; + + /// + public bool IsThreadSafe => true; + + /// + public void Enqueue(T item) => _queue.Enqueue(item); + + /// + public bool TryDequeue([MaybeNullWhen(false)] out T item) => _queue.TryDequeue(out item); + + /// + public bool TryPeek([MaybeNullWhen(false)] out T item) => _queue.TryPeek(out item); + + /// + public int Count => _queue.Count; + + /// + public bool IsEmpty => _queue.IsEmpty; + + /// + public IEnumerator GetEnumerator() => _queue.GetEnumerator(); + } } } diff --git a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.netcoreapp.cs b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.netcoreapp.cs index 6c24b3e41ec7b5..c8fc9baebae7db 100644 --- a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.netcoreapp.cs +++ b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.netcoreapp.cs @@ -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.Threading.Channels { @@ -9,13 +10,14 @@ namespace System.Threading.Channels public static partial class Channel { /// Creates an unbounded prioritized channel usable by any number of readers and writers concurrently. + /// Specifies the type of data in the channel. /// The created channel. /// /// is used to determine priority of elements. /// The next item read from the channel will be the element available in the channel with the lowest priority value. /// public static Channel CreateUnboundedPrioritized() => - new UnboundedPrioritizedChannel(runContinuationsAsynchronously: true, comparer: null); + new UnboundedChannel>(new(new()), runContinuationsAsynchronously: true); /// Creates an unbounded prioritized channel subject to the provided options. /// Specifies the type of data in the channel. @@ -30,7 +32,45 @@ public static Channel CreateUnboundedPrioritized(UnboundedPrioritizedChann { ArgumentNullException.ThrowIfNull(options); - return new UnboundedPrioritizedChannel(!options.AllowSynchronousContinuations, options.Comparer); + return new UnboundedChannel>(new(new(options.Comparer)), !options.AllowSynchronousContinuations); + } + + /// Provides an for a . + private readonly struct UnboundedChannelPriorityQueue(PriorityQueue queue) : IUnboundedChannelQueue + { + private readonly PriorityQueue _queue = queue; + + /// + public bool IsThreadSafe => false; + + /// + public void Enqueue(T item) => _queue.Enqueue(true, item); + + /// + public bool TryDequeue([MaybeNullWhen(false)] out T item) => _queue.TryDequeue(out _, out item); + + /// + public bool TryPeek([MaybeNullWhen(false)] out T item) => _queue.TryPeek(out _, out item); + + /// + public int Count => _queue.Count; + + /// + public bool IsEmpty => _queue.Count == 0; + + /// + public IEnumerator GetEnumerator() + { + List list = []; + foreach ((bool _, T Priority) item in _queue.UnorderedItems) + { + list.Add(item.Priority); + } + + list.Sort(_queue.Comparer); + + return list.GetEnumerator(); + } } } } diff --git a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/IDebugEnumerator.cs b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/IDebugEnumerator.cs index a3d072ee9f7cb4..af2a77bb1bf775 100644 --- a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/IDebugEnumerator.cs +++ b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/IDebugEnumerator.cs @@ -11,7 +11,7 @@ internal interface IDebugEnumerable IEnumerator GetEnumerator(); } - internal sealed class DebugEnumeratorDebugView + internal class DebugEnumeratorDebugView { public DebugEnumeratorDebugView(IDebugEnumerable enumerable) { @@ -26,4 +26,6 @@ public DebugEnumeratorDebugView(IDebugEnumerable enumerable) [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public T[] Items { get; } } + + internal sealed class DebugEnumeratorDebugView(IDebugEnumerable enumerable) : DebugEnumeratorDebugView(enumerable); } diff --git a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/IUnboundedChannelQueue.cs b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/IUnboundedChannelQueue.cs new file mode 100644 index 00000000000000..b1b65a1dffeb10 --- /dev/null +++ b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/IUnboundedChannelQueue.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace System.Threading.Channels +{ + /// Representation of the queue data structure used by . + internal interface IUnboundedChannelQueue : IDebugEnumerable + { + /// Gets whether the other members are safe to use concurrently with each other and themselves. + bool IsThreadSafe { get; } + + /// Enqueues an item into the queue. + /// The item to enqueue. + void Enqueue(T item); + + /// Dequeues an item from the queue, if possible. + /// The dequeued item, or default if the queue was empty. + /// Whether an item was dequeued. + bool TryDequeue([MaybeNullWhen(false)] out T item); + + /// Peeks at the next item from the queue that would be dequeued, if possible. + /// The peeked item, or default if the queue was empty. + /// Whether an item was peeked. + bool TryPeek([MaybeNullWhen(false)] out T item); + + /// Gets the number of elements in the queue. + int Count { get; } + + /// Gets whether the queue is empty. + bool IsEmpty { get; } + } +} diff --git a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/UnboundedChannel.cs b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/UnboundedChannel.cs index fb3facf83dc47e..ad7ee0e3608d3c 100644 --- a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/UnboundedChannel.cs +++ b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/UnboundedChannel.cs @@ -5,19 +5,20 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Threading.Tasks; namespace System.Threading.Channels { /// Provides a buffered channel of unbounded capacity. [DebuggerDisplay("Items = {ItemsCountForDebugger}, Closed = {ChannelIsClosedForDebugger}")] - [DebuggerTypeProxy(typeof(DebugEnumeratorDebugView<>))] - internal sealed class UnboundedChannel : Channel, IDebugEnumerable + [DebuggerTypeProxy(typeof(DebugEnumeratorDebugView<,>))] + internal sealed class UnboundedChannel : Channel, IDebugEnumerable where TQueue : struct, IUnboundedChannelQueue { /// Task that indicates the channel has completed. private readonly TaskCompletionSource _completion; /// The items in the channel. - private readonly ConcurrentQueue _items = new ConcurrentQueue(); + private readonly TQueue _items; /// Readers blocked reading from the channel. private readonly Deque> _blockedReaders = new Deque>(); /// Whether to force continuations to be executed asynchronously from producer writes. @@ -29,8 +30,9 @@ internal sealed class UnboundedChannel : Channel, IDebugEnumerable private Exception? _doneWriting; /// Initialize the channel. - internal UnboundedChannel(bool runContinuationsAsynchronously) + internal UnboundedChannel(TQueue items, bool runContinuationsAsynchronously) { + _items = items; _runContinuationsAsynchronously = runContinuationsAsynchronously; _completion = new TaskCompletionSource(runContinuationsAsynchronously ? TaskCreationOptions.RunContinuationsAsynchronously : TaskCreationOptions.None); Reader = new UnboundedChannelReader(this); @@ -38,14 +40,14 @@ internal UnboundedChannel(bool runContinuationsAsynchronously) } [DebuggerDisplay("Items = {Count}")] - [DebuggerTypeProxy(typeof(DebugEnumeratorDebugView<>))] + [DebuggerTypeProxy(typeof(DebugEnumeratorDebugView<,>))] private sealed class UnboundedChannelReader : ChannelReader, IDebugEnumerable { - internal readonly UnboundedChannel _parent; + internal readonly UnboundedChannel _parent; private readonly AsyncOperation _readerSingleton; private readonly AsyncOperation _waiterSingleton; - internal UnboundedChannelReader(UnboundedChannel parent) + internal UnboundedChannelReader(UnboundedChannel parent) { _parent = parent; _readerSingleton = new AsyncOperation(parent._runContinuationsAsynchronously, pooled: true); @@ -68,8 +70,8 @@ public override ValueTask ReadAsync(CancellationToken cancellationToken) } // Dequeue an item if we can. - UnboundedChannel parent = _parent; - if (parent._items.TryDequeue(out T? item)) + UnboundedChannel parent = _parent; + if (parent._items.IsThreadSafe && parent._items.TryDequeue(out T? item)) { CompleteIfDone(parent); return new ValueTask(item); @@ -112,24 +114,60 @@ public override ValueTask ReadAsync(CancellationToken cancellationToken) public override bool TryRead([MaybeNullWhen(false)] out T item) { - UnboundedChannel parent = _parent; + UnboundedChannel parent = _parent; + return parent._items.IsThreadSafe ? + LockFree(parent, out item) : + Locked(parent, out item); - // Dequeue an item if we can - if (parent._items.TryDequeue(out item)) + static bool LockFree(UnboundedChannel parent, [MaybeNullWhen(false)] out T item) { - CompleteIfDone(parent); - return true; + if (parent._items.TryDequeue(out item)) + { + CompleteIfDone(parent); + return true; + } + + item = default; + return false; } - item = default; - return false; + static bool Locked(UnboundedChannel parent, [MaybeNullWhen(false)] out T item) + { + lock (parent.SyncObj) + { + if (parent._items.TryDequeue(out item)) + { + CompleteIfDone(parent); + return true; + } + } + + item = default; + return false; + } } - public override bool TryPeek([MaybeNullWhen(false)] out T item) => - _parent._items.TryPeek(out item); + public override bool TryPeek([MaybeNullWhen(false)] out T item) + { + UnboundedChannel parent = _parent; + return parent._items.IsThreadSafe ? + parent._items.TryPeek(out item) : + Locked(parent, out item); + + // Separated out to keep the try/finally from preventing TryPeek from being inlined + static bool Locked(UnboundedChannel parent, [MaybeNullWhen(false)] out T item) + { + lock (parent.SyncObj) + { + return parent._items.TryPeek(out item); + } + } + } - private static void CompleteIfDone(UnboundedChannel parent) + private static void CompleteIfDone(UnboundedChannel parent) { + Debug.Assert(parent._items.IsThreadSafe || Monitor.IsEntered(parent.SyncObj)); + if (parent._doneWriting != null && parent._items.IsEmpty) { // If we've now emptied the items queue and we're not getting any more, complete. @@ -144,12 +182,12 @@ public override ValueTask WaitToReadAsync(CancellationToken cancellationTo return new ValueTask(Task.FromCanceled(cancellationToken)); } - if (!_parent._items.IsEmpty) + if (_parent._items.IsThreadSafe && !_parent._items.IsEmpty) { return new ValueTask(true); } - UnboundedChannel parent = _parent; + UnboundedChannel parent = _parent; lock (parent.SyncObj) { @@ -192,15 +230,15 @@ public override ValueTask WaitToReadAsync(CancellationToken cancellationTo } [DebuggerDisplay("Items = {ItemsCountForDebugger}")] - [DebuggerTypeProxy(typeof(DebugEnumeratorDebugView<>))] + [DebuggerTypeProxy(typeof(DebugEnumeratorDebugView<,>))] private sealed class UnboundedChannelWriter : ChannelWriter, IDebugEnumerable { - internal readonly UnboundedChannel _parent; - internal UnboundedChannelWriter(UnboundedChannel parent) => _parent = parent; + internal readonly UnboundedChannel _parent; + internal UnboundedChannelWriter(UnboundedChannel parent) => _parent = parent; public override bool TryComplete(Exception? error) { - UnboundedChannel parent = _parent; + UnboundedChannel parent = _parent; bool completeTask; lock (parent.SyncObj) @@ -240,7 +278,7 @@ public override bool TryComplete(Exception? error) public override bool TryWrite(T item) { - UnboundedChannel parent = _parent; + UnboundedChannel parent = _parent; while (true) { AsyncOperation? blockedReader = null; @@ -321,7 +359,7 @@ public override ValueTask WriteAsync(T item, CancellationToken cancellationToken } /// Gets the object used to synchronize access to all state on this instance. - private object SyncObj => _items; + private object SyncObj => _blockedReaders; [Conditional("DEBUG")] private void AssertInvariants() diff --git a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/UnboundedPriorityChannel.cs b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/UnboundedPriorityChannel.cs deleted file mode 100644 index 7af18b9413ee29..00000000000000 --- a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/UnboundedPriorityChannel.cs +++ /dev/null @@ -1,369 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Threading.Tasks; - -// This file is primarily a copy of UnboundedChannel, subsequently tweaked to account for differences -// between ConcurrentQueue and PriorityQueue, e.g. that PQ isn't thread safe and so fast -// paths outside of locks need to be removed, that Enqueue/Dequeue methods take priorities, etc. Any -// changes made to this or that file should largely be kept in sync. - -namespace System.Threading.Channels -{ - /// Provides a buffered channel of unbounded capacity. - [DebuggerDisplay("Items = {ItemsCountForDebugger}, Closed = {ChannelIsClosedForDebugger}")] - [DebuggerTypeProxy(typeof(DebugEnumeratorDebugView<>))] - internal sealed class UnboundedPrioritizedChannel : Channel, IDebugEnumerable - { - /// Task that indicates the channel has completed. - private readonly TaskCompletionSource _completion; - /// The items in the channel. - /// To avoid double storing of a potentially large struct T, the priority doubles as the element and the element is ignored. - private readonly PriorityQueue _items; - /// Readers blocked reading from the channel. - private readonly Deque> _blockedReaders = new Deque>(); - /// Whether to force continuations to be executed asynchronously from producer writes. - private readonly bool _runContinuationsAsynchronously; - - /// Readers waiting for a notification that data is available. - private AsyncOperation? _waitingReadersTail; - /// Set to non-null once Complete has been called. - private Exception? _doneWriting; - - /// Initialize the channel. - internal UnboundedPrioritizedChannel(bool runContinuationsAsynchronously, IComparer? comparer) - { - _runContinuationsAsynchronously = runContinuationsAsynchronously; - _completion = new TaskCompletionSource(runContinuationsAsynchronously ? TaskCreationOptions.RunContinuationsAsynchronously : TaskCreationOptions.None); - Reader = new UnboundedPrioritizedChannelReader(this); - Writer = new UnboundedPrioritizedChannelWriter(this); - _items = new PriorityQueue(comparer); - } - - [DebuggerDisplay("Items = {Count}")] - [DebuggerTypeProxy(typeof(DebugEnumeratorDebugView<>))] - private sealed class UnboundedPrioritizedChannelReader : ChannelReader, IDebugEnumerable - { - internal readonly UnboundedPrioritizedChannel _parent; - private readonly AsyncOperation _readerSingleton; - private readonly AsyncOperation _waiterSingleton; - - internal UnboundedPrioritizedChannelReader(UnboundedPrioritizedChannel parent) - { - _parent = parent; - _readerSingleton = new AsyncOperation(parent._runContinuationsAsynchronously, pooled: true); - _waiterSingleton = new AsyncOperation(parent._runContinuationsAsynchronously, pooled: true); - } - - public override Task Completion => _parent._completion.Task; - - public override bool CanCount => true; - - public override bool CanPeek => true; - - public override int Count => _parent._items.Count; - - public override ValueTask ReadAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return ValueTask.FromCanceled(cancellationToken); - } - - // Dequeue an item if we can. - UnboundedPrioritizedChannel parent = _parent; - lock (parent.SyncObj) - { - parent.AssertInvariants(); - - // Try to dequeue again, now that we hold the lock. - if (parent._items.TryDequeue(out _, out T? item)) - { - CompleteIfDone(parent); - return new ValueTask(item); - } - - // There are no items, so if we're done writing, fail. - if (parent._doneWriting != null) - { - return ChannelUtilities.GetInvalidCompletionValueTask(parent._doneWriting); - } - - // If we're able to use the singleton reader, do so. - if (!cancellationToken.CanBeCanceled) - { - AsyncOperation singleton = _readerSingleton; - if (singleton.TryOwnAndReset()) - { - parent._blockedReaders.EnqueueTail(singleton); - return singleton.ValueTaskOfT; - } - } - - // Otherwise, create and queue a reader. - var reader = new AsyncOperation(parent._runContinuationsAsynchronously, cancellationToken); - parent._blockedReaders.EnqueueTail(reader); - return reader.ValueTaskOfT; - } - } - - public override bool TryRead([MaybeNullWhen(false)] out T item) - { - UnboundedPrioritizedChannel parent = _parent; - lock (parent.SyncObj) - { - // Dequeue an item if we can - if (parent._items.TryDequeue(out _, out item)) - { - CompleteIfDone(parent); - return true; - } - - item = default; - return false; - } - } - - public override bool TryPeek([MaybeNullWhen(false)] out T item) => - _parent._items.TryPeek(out _, out item); - - private static void CompleteIfDone(UnboundedPrioritizedChannel parent) - { - Debug.Assert(Monitor.IsEntered(parent.SyncObj)); - - if (parent._doneWriting != null && parent._items.Count == 0) - { - // If we've now emptied the items queue and we're not getting any more, complete. - ChannelUtilities.Complete(parent._completion, parent._doneWriting); - } - } - - public override ValueTask WaitToReadAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return ValueTask.FromCanceled(cancellationToken); - } - - UnboundedPrioritizedChannel parent = _parent; - lock (parent.SyncObj) - { - parent.AssertInvariants(); - - // Try again to read now that we're synchronized with writers. - if (parent._items.Count != 0) - { - return new ValueTask(true); - } - - // There are no items, so if we're done writing, there's never going to be data available. - if (parent._doneWriting != null) - { - return parent._doneWriting != ChannelUtilities.s_doneWritingSentinel ? - ValueTask.FromException(parent._doneWriting) : - default; - } - - // If we're able to use the singleton waiter, do so. - if (!cancellationToken.CanBeCanceled) - { - AsyncOperation singleton = _waiterSingleton; - if (singleton.TryOwnAndReset()) - { - ChannelUtilities.QueueWaiter(ref parent._waitingReadersTail, singleton); - return singleton.ValueTaskOfT; - } - } - - // Otherwise, create and queue a waiter. - var waiter = new AsyncOperation(parent._runContinuationsAsynchronously, cancellationToken); - ChannelUtilities.QueueWaiter(ref parent._waitingReadersTail, waiter); - return waiter.ValueTaskOfT; - } - } - - /// Gets an enumerator the debugger can use to show the contents of the channel. - IEnumerator IDebugEnumerable.GetEnumerator() => _parent.GetEnumerator(); - } - - [DebuggerDisplay("Items = {ItemsCountForDebugger}")] - [DebuggerTypeProxy(typeof(DebugEnumeratorDebugView<>))] - private sealed class UnboundedPrioritizedChannelWriter : ChannelWriter, IDebugEnumerable - { - internal readonly UnboundedPrioritizedChannel _parent; - internal UnboundedPrioritizedChannelWriter(UnboundedPrioritizedChannel parent) => _parent = parent; - - public override bool TryComplete(Exception? error) - { - UnboundedPrioritizedChannel parent = _parent; - bool completeTask; - - lock (parent.SyncObj) - { - parent.AssertInvariants(); - - // If we've already marked the channel as completed, bail. - if (parent._doneWriting != null) - { - return false; - } - - // Mark that we're done writing. - parent._doneWriting = error ?? ChannelUtilities.s_doneWritingSentinel; - completeTask = parent._items.Count == 0; - } - - // If there are no items in the queue, complete the channel's task, - // as no more data can possibly arrive at this point. We do this outside - // of the lock in case we'll be running synchronous completions, and we - // do it before completing blocked/waiting readers, so that when they - // wake up they'll see the task as being completed. - if (completeTask) - { - ChannelUtilities.Complete(parent._completion, error); - } - - // At this point, _blockedReaders and _waitingReaders will not be mutated: - // they're only mutated by readers while holding the lock, and only if _doneWriting is null. - // freely manipulate _blockedReaders and _waitingReaders without any concurrency concerns. - ChannelUtilities.FailOperations, T>(parent._blockedReaders, ChannelUtilities.CreateInvalidCompletionException(error)); - ChannelUtilities.WakeUpWaiters(ref parent._waitingReadersTail, result: false, error: error); - - // Successfully transitioned to completed. - return true; - } - - public override bool TryWrite(T item) - { - UnboundedPrioritizedChannel parent = _parent; - while (true) - { - AsyncOperation? blockedReader = null; - AsyncOperation? waitingReadersTail = null; - lock (parent.SyncObj) - { - // If writing has already been marked as done, fail the write. - parent.AssertInvariants(); - if (parent._doneWriting != null) - { - return false; - } - - // If there aren't any blocked readers, just add the data to the queue, - // and let any waiting readers know that they should try to read it. - // We can only complete such waiters here under the lock if they run - // continuations asynchronously (otherwise the synchronous continuations - // could be invoked under the lock). If we don't complete them here, we - // need to do so outside of the lock. - if (parent._blockedReaders.IsEmpty) - { - parent._items.Enqueue(true, item); - waitingReadersTail = parent._waitingReadersTail; - if (waitingReadersTail == null) - { - return true; - } - parent._waitingReadersTail = null; - } - else - { - // There were blocked readers. Grab one, and then complete it outside of the lock. - blockedReader = parent._blockedReaders.DequeueHead(); - } - } - - if (blockedReader != null) - { - // Complete the reader. It's possible the reader was canceled, in which - // case we loop around to try everything again. - if (blockedReader.TrySetResult(item)) - { - return true; - } - } - else - { - // Wake up all of the waiters. Since we've released the lock, it's possible - // we could cause some spurious wake-ups here, if we tell a waiter there's - // something available but all data has already been removed. It's a benign - // race condition, though, as consumers already need to account for such things. - ChannelUtilities.WakeUpWaiters(ref waitingReadersTail, result: true); - return true; - } - } - } - - public override ValueTask WaitToWriteAsync(CancellationToken cancellationToken) - { - Exception? doneWriting = _parent._doneWriting; - return - cancellationToken.IsCancellationRequested ? ValueTask.FromCanceled(cancellationToken) : - doneWriting == null ? new ValueTask(true) : // unbounded writing can always be done if we haven't completed - doneWriting != ChannelUtilities.s_doneWritingSentinel ? ValueTask.FromException(doneWriting) : - default; - } - - public override ValueTask WriteAsync(T item, CancellationToken cancellationToken) => - cancellationToken.IsCancellationRequested ? ValueTask.FromCanceled(cancellationToken) : - TryWrite(item) ? default : - ValueTask.FromException(ChannelUtilities.CreateInvalidCompletionException(_parent._doneWriting)); - - /// Gets the number of items in the channel. This should only be used by the debugger. - private int ItemsCountForDebugger => _parent._items.Count; - - /// Gets an enumerator the debugger can use to show the contents of the channel. - IEnumerator IDebugEnumerable.GetEnumerator() => _parent.GetEnumerator(); - } - - /// Gets the object used to synchronize access to all state on this instance. - private object SyncObj => _items; - - [Conditional("DEBUG")] - private void AssertInvariants() - { - Debug.Assert(SyncObj != null, "The sync obj must not be null."); - Debug.Assert(Monitor.IsEntered(SyncObj), "Invariants can only be validated while holding the lock."); - - if (_items.Count != 0) - { - if (_runContinuationsAsynchronously) - { - Debug.Assert(_blockedReaders.IsEmpty, "There's data available, so there shouldn't be any blocked readers."); - Debug.Assert(_waitingReadersTail == null, "There's data available, so there shouldn't be any waiting readers."); - } - Debug.Assert(!_completion.Task.IsCompleted, "We still have data available, so shouldn't be completed."); - } - if ((!_blockedReaders.IsEmpty || _waitingReadersTail != null) && _runContinuationsAsynchronously) - { - Debug.Assert(_items.Count == 0, "There are blocked/waiting readers, so there shouldn't be any data available."); - } - if (_completion.Task.IsCompleted) - { - Debug.Assert(_doneWriting != null, "We're completed, so we must be done writing."); - } - } - - /// Gets the number of items in the channel. This should only be used by the debugger. - private int ItemsCountForDebugger => _items.Count; - - /// Report if the channel is closed or not. This should only be used by the debugger. - private bool ChannelIsClosedForDebugger => _doneWriting != null; - - /// Gets an enumerator the debugger can use to show the contents of the channel. - public IEnumerator GetEnumerator() - { - List list = []; - foreach ((bool _, T Priority) item in _items.UnorderedItems) - { - list.Add(item.Priority); - } - - list.Sort(_items.Comparer); - - return list.GetEnumerator(); - } - } -} From 0a220d534b30495ff332b3bd65a04889e66b44f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Tue, 23 Apr 2024 15:23:13 +0200 Subject: [PATCH 059/248] Bump minimum Apple OS versions (#101342) As defined in the ".NET 9 - Supported OS versions" document: https://github.com/dotnet/core/blob/main/release-notes/9.0/supported-os.md - macOS 12.0 - iOS/iOSSimulator 12.2 - tvOS/tvOSSimulator 12.2 - MacCatalyst 15.0 (== macOS 12.0) Fixes https://github.com/dotnet/runtime/issues/91736 --- Directory.Build.props | 14 ++++++++----- eng/native/build-commons.sh | 8 ++++---- eng/native/configurecompiler.cmake | 20 ++++++++++++------- .../Microsoft.NETCore.Native.Unix.targets | 7 +++---- .../Compiler/ObjectWriter/MachObjectWriter.cs | 10 +++------- ...-framework-distribution-template-arm64.xml | 2 +- ...ed-framework-distribution-template-x64.xml | 2 +- .../NativeExports/NativeExports.csproj | 8 ++++---- .../Security/Cryptography/AesGcm.macOS.cs | 2 +- .../Cryptography/ChaCha20Poly1305.macOS.cs | 2 +- .../tests/ChaCha20Poly1305Tests.cs | 2 +- src/mono/mono.proj | 8 ++++---- .../mono/tools/offsets-tool/offsets-tool.py | 4 ++-- .../msbuild/apple/build/AppleBuild.targets | 4 ++-- .../pal_signverify.c | 9 +++++++++ .../pal_ssl.c | 4 ++++ .../pal_x509.c | 11 +--------- .../pal_x509chain.c | 3 +++ src/native/libs/build-native.sh | 8 ++++---- .../AotCompilerTask/MonoAOTCompiler.props | 4 ++-- src/tasks/AppleAppBuilder/Xcode.cs | 19 +++++++++++++----- .../MobileBuildTasks/Apple/AppleProject.cs | 2 +- 22 files changed, 87 insertions(+), 66 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index ef0e8c1b44d76d..40c75f103b8be8 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -56,18 +56,22 @@ - eng/native/configurecompiler.cmake - eng/native/build-commons.sh - src/native/libs/build-native.sh - - src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs + - src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/MachObjectWriter.cs - src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets + - src/mono/mono/tools/offsets-tool/offsets-tool.py + - src/mono/msbuild/apple/build/AppleBuild.targets - src/installer/pkg/sfx/bundle/shared-framework-distribution-template-x64.xml - src/installer/pkg/sfx/bundle/shared-framework-distribution-template-arm64.xml + - src/tasks/AotCompilerTask/MonoAOTCompiler.props + - src/tasks/AppleAppBuilder/Xcode.cs - src/tasks/MobileBuildTasks/Apple/AppleProject.cs - dotnet/installer repo > src/redist/targets/GeneratePKG.targets --> 21 - 11.0 - 11.0 - 10.15 - 11.0 + 12.2 + 12.2 + 12.0 + 15.0 diff --git a/eng/native/build-commons.sh b/eng/native/build-commons.sh index 0916abb396fa46..2cf33442a93253 100755 --- a/eng/native/build-commons.sh +++ b/eng/native/build-commons.sh @@ -109,7 +109,7 @@ build_native() # set default iOS simulator deployment target # keep in sync with SetOSTargetMinVersions in the root Directory.Build.props - cmakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $cmakeArgs" + cmakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $cmakeArgs" if [[ "$__TargetArch" == x64 ]]; then cmakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"x86_64\" $cmakeArgs" elif [[ "$__TargetArch" == arm64 ]]; then @@ -123,7 +123,7 @@ build_native() # set default iOS device deployment target # keep in sync with SetOSTargetMinVersions in the root Directory.Build.props - cmakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $cmakeArgs" + cmakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $cmakeArgs" if [[ "$__TargetArch" == arm64 ]]; then cmakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"arm64\" $cmakeArgs" else @@ -135,7 +135,7 @@ build_native() # set default tvOS simulator deployment target # keep in sync with SetOSTargetMinVersions in the root Directory.Build.props - cmakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $cmakeArgs" + cmakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $cmakeArgs" if [[ "$__TargetArch" == x64 ]]; then cmakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"x86_64\" $cmakeArgs" elif [[ "$__TargetArch" == arm64 ]]; then @@ -149,7 +149,7 @@ build_native() # set default tvOS device deployment target # keep in sync with SetOSTargetMinVersions in the root Directory.Build.props - cmakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvos -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $cmakeArgs" + cmakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvos -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $cmakeArgs" if [[ "$__TargetArch" == arm64 ]]; then cmakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"arm64\" $cmakeArgs" else diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index bdf370fdf966b6..4675a8b07cb6b4 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -14,6 +14,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) +include(CheckLinkerFlag) # "configureoptimization.cmake" must be included after CLR_CMAKE_HOST_UNIX has been set. include(${CMAKE_CURRENT_LIST_DIR}/configureoptimization.cmake) @@ -300,7 +301,13 @@ elseif(CLR_CMAKE_HOST_SUNOS) add_definitions(-D__EXTENSIONS__ -D_XPG4_2 -D_POSIX_PTHREAD_SEMANTICS) elseif(CLR_CMAKE_HOST_OSX AND NOT CLR_CMAKE_HOST_MACCATALYST AND NOT CLR_CMAKE_HOST_IOS AND NOT CLR_CMAKE_HOST_TVOS) add_definitions(-D_XOPEN_SOURCE) - add_linker_flag("-Wl,-bind_at_load") + + # the new linker in Xcode 15 (ld_new/ld_prime) deprecated the -bind_at_load flag for macOS which causes a warning + # that fails the build since we build with -Werror. Only pass the flag if we need it, i.e. older linkers. + check_linker_flag(C "-Wl,-bind_at_load,-fatal_warnings" LINKER_SUPPORTS_BIND_AT_LOAD_FLAG) + if(LINKER_SUPPORTS_BIND_AT_LOAD_FLAG) + add_linker_flag("-Wl,-bind_at_load") + endif() elseif(CLR_CMAKE_HOST_HAIKU) add_compile_options($<$:-Wa,--noexecstack>) add_linker_flag("-Wl,--no-undefined") @@ -662,11 +669,11 @@ if (CLR_CMAKE_HOST_UNIX) set(DISABLE_OVERRIDING_MIN_VERSION_ERROR -Wno-overriding-t-option) add_link_options(-Wno-overriding-t-option) if(CLR_CMAKE_HOST_ARCH_ARM64) - set(MACOS_VERSION_MIN_FLAGS "-target arm64-apple-ios14.2-macabi") - add_link_options(-target arm64-apple-ios14.2-macabi) + set(MACOS_VERSION_MIN_FLAGS "-target arm64-apple-ios15.0-macabi") + add_link_options(-target arm64-apple-ios15.0-macabi) elseif(CLR_CMAKE_HOST_ARCH_AMD64) - set(MACOS_VERSION_MIN_FLAGS "-target x86_64-apple-ios13.5-macabi") - add_link_options(-target x86_64-apple-ios13.5-macabi) + set(MACOS_VERSION_MIN_FLAGS "-target x86_64-apple-ios15.0-macabi") + add_link_options(-target x86_64-apple-ios15.0-macabi) else() clr_unknown_arch() endif() @@ -679,11 +686,10 @@ if (CLR_CMAKE_HOST_UNIX) set(CMAKE_OBJC_FLAGS "${CMAKE_OBJC_FLAGS} ${MACOS_VERSION_MIN_FLAGS} ${DISABLE_OVERRIDING_MIN_VERSION_ERROR}") set(CMAKE_OBJCXX_FLAGS "${CMAKE_OBJCXX_FLAGS} ${MACOS_VERSION_MIN_FLAGS} ${DISABLE_OVERRIDING_MIN_VERSION_ERROR}") elseif(CLR_CMAKE_HOST_OSX) + set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0") if(CLR_CMAKE_HOST_ARCH_ARM64) - set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0") add_compile_options(-arch arm64) elseif(CLR_CMAKE_HOST_ARCH_AMD64) - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15") add_compile_options(-arch x86_64) else() clr_unknown_arch() diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets index c9314487b0507d..7441f7da0f6249 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets @@ -74,9 +74,8 @@ The .NET Foundation licenses this file to you under the MIT license. - 13.5 - 14.2 - 11.0 + 15.0 + 12.2 <_AppleSdkName Condition="'$(_targetOS)' == 'ios'">iphoneos <_AppleSdkName Condition="'$(_targetOS)' == 'iossimulator'">iphonesimulator @@ -96,7 +95,7 @@ The .NET Foundation licenses this file to you under the MIT license. - 11.0 + 12.0 x86_64-apple-macos$(AppleMinOSVersion) arm64-apple-macos$(AppleMinOSVersion) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/MachObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/MachObjectWriter.cs index 86ac433262f990..e65f7c889dd19a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/MachObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/MachObjectWriter.cs @@ -244,16 +244,12 @@ private protected override void EmitObjectFile(string objectFilePath) { case TargetOS.OSX: buildVersion.Platform = PLATFORM_MACOS; - buildVersion.MinimumPlatformVersion = 0x0A_0C_00; // 10.12.0 + buildVersion.MinimumPlatformVersion = 0x0C_00_00; // 12.0.0 break; case TargetOS.MacCatalyst: buildVersion.Platform = PLATFORM_MACCATALYST; - buildVersion.MinimumPlatformVersion = _cpuType switch - { - CPU_TYPE_X86_64 => 0x0D_05_00u, // 13.5.0 - _ => 0x0E_02_00u, // 14.2.0 - }; + buildVersion.MinimumPlatformVersion = 0x0F_02_00; // 15.0.0 break; case TargetOS.iOS: @@ -268,7 +264,7 @@ private protected override void EmitObjectFile(string objectFilePath) TargetOS.tvOSSimulator => PLATFORM_TVOSSIMULATOR, _ => 0, }; - buildVersion.MinimumPlatformVersion = 0x0B_00_00; // 11.0.0 + buildVersion.MinimumPlatformVersion = 0x0C_02_00; // 12.2.0 break; } buildVersion.Write(outputFileStream); diff --git a/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-arm64.xml b/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-arm64.xml index 1b0dca06e4095d..2d501b30731695 100644 --- a/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-arm64.xml +++ b/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-arm64.xml @@ -7,7 +7,7 @@ - + diff --git a/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-x64.xml b/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-x64.xml index 419795e0f348fe..538f475d5d5836 100644 --- a/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-x64.xml +++ b/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-x64.xml @@ -7,7 +7,7 @@ - + diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj index 3daf1f99fe8b06..ad5bd11ee41cc2 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj @@ -91,12 +91,12 @@ - arm64-apple-ios14.2-macabi - x86_64-apple-ios13.5-macabi + arm64-apple-ios$(MacCatalystVersionMin)-macabi + x86_64-apple-ios$(MacCatalystVersionMin)-macabi - arm64-apple-macos11 - x86_64-apple-macos10.15 + arm64-apple-macos$(macOSVersionMin) + x86_64-apple-macos$(macOSVersionMin) macosx diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesGcm.macOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesGcm.macOS.cs index 3b528f496f4d91..d9f036f61ca5d7 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesGcm.macOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesGcm.macOS.cs @@ -11,7 +11,7 @@ public sealed partial class AesGcm { private FixedMemoryKeyBox _keyBox; - // CryptoKit added AES.GCM in macOS 10.15, which is our minimum target for macOS. + // CryptoKit added AES.GCM in macOS 10.15, which is lower than our minimum target for macOS. public static bool IsSupported => true; // CryptoKit only supports 16 byte tags. diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ChaCha20Poly1305.macOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ChaCha20Poly1305.macOS.cs index aa2cba5f234ba7..7e45061f971a6e 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ChaCha20Poly1305.macOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ChaCha20Poly1305.macOS.cs @@ -8,7 +8,7 @@ namespace System.Security.Cryptography { public sealed partial class ChaCha20Poly1305 { - // CryptoKit added ChaCha20Poly1305 in macOS 10.15, which is our minimum target for macOS. + // CryptoKit added ChaCha20Poly1305 in macOS 10.15, which is lower than our minimum target for macOS. public static bool IsSupported => true; private FixedMemoryKeyBox _keyBox; diff --git a/src/libraries/System.Security.Cryptography/tests/ChaCha20Poly1305Tests.cs b/src/libraries/System.Security.Cryptography/tests/ChaCha20Poly1305Tests.cs index ced6edcf350951..00ae5286b25a92 100644 --- a/src/libraries/System.Security.Cryptography/tests/ChaCha20Poly1305Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/ChaCha20Poly1305Tests.cs @@ -475,7 +475,7 @@ public static void CheckIsSupported() } else if (PlatformDetection.IsOSX) { - // CryptoKit is supported on macOS 10.15+, which is our minimum target. + // CryptoKit is supported on macOS 10.15+, which is lower than our minimum target. expectedIsSupported = true; } else if (PlatformDetection.OpenSslPresentOnSystem && PlatformDetection.IsOpenSslSupported) diff --git a/src/mono/mono.proj b/src/mono/mono.proj index 8b57badb1a2e38..47eeb0937a88fa 100644 --- a/src/mono/mono.proj +++ b/src/mono/mono.proj @@ -401,11 +401,11 @@ <_MonoCMakeArgs Include="-DCMAKE_SYSTEM_VARIANT=maccatalyst" /> <_MonoCPPFLAGS Include="-Wno-overriding-t-option" /> - <_MonoCFlags Condition="'$(TargetArchitecture)' == 'arm64'" Include="-target arm64-apple-ios14.2-macabi" /> - <_MonoCFlags Condition="'$(TargetArchitecture)' == 'x64'" Include="-target x86_64-apple-ios13.5-macabi" /> + <_MonoCFlags Condition="'$(TargetArchitecture)' == 'arm64'" Include="-target arm64-apple-ios$(MacCatalystVersionMin)-macabi" /> + <_MonoCFlags Condition="'$(TargetArchitecture)' == 'x64'" Include="-target x86_64-apple-ios$(MacCatalystVersionMin)-macabi" /> <_MonoCFLAGS Condition="'$(TargetArchitecture)' == 'arm64'" Include="-arch arm64" /> - <_MonoCXXFlags Condition="'$(TargetArchitecture)' == 'arm64'" Include="-target arm64-apple-ios14.2-macabi" /> - <_MonoCXXFlags Condition="'$(TargetArchitecture)' == 'x64'" Include="-target x86_64-apple-ios13.5-macabi" /> + <_MonoCXXFlags Condition="'$(TargetArchitecture)' == 'arm64'" Include="-target arm64-apple-ios$(MacCatalystVersionMin)-macabi" /> + <_MonoCXXFlags Condition="'$(TargetArchitecture)' == 'x64'" Include="-target x86_64-apple-ios$(MacCatalystVersionMin)-macabi" /> <_MonoCXXFLAGS Condition="'$(TargetArchitecture)' == 'arm64'" Include="-arch arm64" /> <_MonoBuildEnv Condition="'$(BuildArchitecture)' == 'arm64'" Include="arch -arch arm64" /> diff --git a/src/mono/mono/tools/offsets-tool/offsets-tool.py b/src/mono/mono/tools/offsets-tool/offsets-tool.py index ad450989afed50..058d27373d28dc 100644 --- a/src/mono/mono/tools/offsets-tool/offsets-tool.py +++ b/src/mono/mono/tools/offsets-tool/offsets-tool.py @@ -159,13 +159,13 @@ def require_emscipten_path (args): elif "x86_64-apple-maccatalyst" == args.abi: require_sysroot (args) self.target = Target ("TARGET_AMD64", "TARGET_MACCAT", IOS_DEFINES) - self.target_args += ["-target", "x86_64-apple-ios13.5-macabi"] + self.target_args += ["-target", "x86_64-apple-ios15.0-macabi"] self.target_args += ["-isysroot", args.sysroot] elif "aarch64-apple-maccatalyst" == args.abi: require_sysroot (args) self.target = Target ("TARGET_ARM64", "TARGET_MACCAT", IOS_DEFINES) - self.target_args += ["-target", "arm64-apple-ios14.2-macabi"] + self.target_args += ["-target", "arm64-apple-ios15.0-macabi"] self.target_args += ["-isysroot", args.sysroot] # watchOS diff --git a/src/mono/msbuild/apple/build/AppleBuild.targets b/src/mono/msbuild/apple/build/AppleBuild.targets index 914351a5cee4da..35d0f16c35b4b8 100644 --- a/src/mono/msbuild/apple/build/AppleBuild.targets +++ b/src/mono/msbuild/apple/build/AppleBuild.targets @@ -159,9 +159,9 @@ - + - + diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_signverify.c b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_signverify.c index 6e7c77e9d7d070..37f61c7b1215ad 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_signverify.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_signverify.c @@ -16,7 +16,10 @@ static int32_t ExecuteSignTransform(SecTransformRef signer, CFDataRef* pSignatur assert(pErrorOut != NULL); int32_t ret = INT_MIN; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" CFTypeRef signerResponse = SecTransformExecute(signer, pErrorOut); +#pragma clang diagnostic pop CFDataRef signature = NULL; if (signerResponse == NULL || *pErrorOut != NULL) @@ -62,7 +65,10 @@ static int32_t ExecuteVerifyTransform(SecTransformRef verifier, CFErrorRef* pErr assert(pErrorOut != NULL); int32_t ret = kErrorSeeError; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" CFTypeRef verifierResponse = SecTransformExecute(verifier, pErrorOut); +#pragma clang diagnostic pop if (verifierResponse != NULL) { @@ -79,6 +85,8 @@ static int32_t ExecuteVerifyTransform(SecTransformRef verifier, CFErrorRef* pErr static int32_t ConfigureSignVerifyTransform(SecTransformRef xform, CFDataRef cfDataHash, CFErrorRef* pErrorOut) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" if (!SecTransformSetAttribute(xform, kSecInputIsAttributeName, kSecInputIsDigest, pErrorOut)) { return 0; @@ -88,6 +96,7 @@ static int32_t ConfigureSignVerifyTransform(SecTransformRef xform, CFDataRef cfD { return 0; } +#pragma clang diagnostic pop return 1; } diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_ssl.c b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_ssl.c index d37f08ed14e2ec..9b44cbbef8e093 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_ssl.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_ssl.c @@ -463,7 +463,11 @@ int32_t AppleCryptoNative_SslIsHostnameMatch(SSLContextRef sslContext, CFStringR for (CFIndex i = 0; i < certificateCount; i++) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" SecCertificateRef item = SecTrustGetCertificateAtIndex(existingTrust, i); +#pragma clang diagnostic pop + CFArrayAppendValue(certs, item); // Copy the EE cert into the anchors set, this will make the chain part diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509.c b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509.c index 94e22f28c8794a..39b8e4619912b3 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509.c @@ -43,16 +43,7 @@ AppleCryptoNative_X509GetPublicKey(SecCertificateRef cert, SecKeyRef* pPublicKey if (cert == NULL || pPublicKeyOut == NULL) return kErrorUnknownState; - if (__builtin_available(macOS 10.14, iOS 12, tvOS 12, *)) - { - *pPublicKeyOut = SecCertificateCopyKey(cert); - } -#if defined(TARGET_IOS) || defined(TARGET_TVOS) - else - { - *pPublicKeyOut = SecCertificateCopyPublicKey(cert); - } -#endif + *pPublicKeyOut = SecCertificateCopyKey(cert); return 1; } diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509chain.c b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509chain.c index 152ed890ed6eda..de1a84f26798d4 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509chain.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509chain.c @@ -92,7 +92,10 @@ SecCertificateRef AppleCryptoNative_X509ChainGetCertificateAtIndex(SecTrustRef c if (chain == NULL || index < 0) return NULL; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return SecTrustGetCertificateAtIndex(chain, index); +#pragma clang diagnostic pop } CFArrayRef AppleCryptoNative_X509ChainGetTrustResults(SecTrustRef chain) diff --git a/src/native/libs/build-native.sh b/src/native/libs/build-native.sh index 3e90b3805aaec9..d3fefa7685a974 100755 --- a/src/native/libs/build-native.sh +++ b/src/native/libs/build-native.sh @@ -105,7 +105,7 @@ elif [[ "$__TargetOS" == linux-bionic && -z "$ROOTFS_DIR" ]]; then elif [[ "$__TargetOS" == iossimulator ]]; then # set default iOS simulator deployment target # keep in sync with SetOSTargetMinVersions in the root Directory.Build.props - __CMakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $__CMakeArgs" + __CMakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $__CMakeArgs" if [[ "$__TargetArch" == x64 ]]; then __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"x86_64\" $__CMakeArgs" elif [[ "$__TargetArch" == x86 ]]; then @@ -119,7 +119,7 @@ elif [[ "$__TargetOS" == iossimulator ]]; then elif [[ "$__TargetOS" == ios ]]; then # set default iOS device deployment target # keep in sync with SetOSTargetMinVersions in the root Directory.Build.props - __CMakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $__CMakeArgs" + __CMakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $__CMakeArgs" if [[ "$__TargetArch" == arm64 ]]; then __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"arm64\" $__CMakeArgs" elif [[ "$__TargetArch" == arm ]]; then @@ -131,7 +131,7 @@ elif [[ "$__TargetOS" == ios ]]; then elif [[ "$__TargetOS" == tvossimulator ]]; then # set default tvOS simulator deployment target # keep in sync with SetOSTargetMinVersions in the root Directory.Build.props - __CMakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $__CMakeArgs" + __CMakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $__CMakeArgs" if [[ "$__TargetArch" == x64 ]]; then __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"x86_64\" $__CMakeArgs" elif [[ "$__TargetArch" == arm64 ]]; then @@ -143,7 +143,7 @@ elif [[ "$__TargetOS" == tvossimulator ]]; then elif [[ "$__TargetOS" == tvos ]]; then # set default tvOS device deployment target # keep in sync with the root Directory.Build.props - __CMakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvos -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $__CMakeArgs" + __CMakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvos -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $__CMakeArgs" if [[ "$__TargetArch" == arm64 ]]; then __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"arm64\" $__CMakeArgs" else diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.props b/src/tasks/AotCompilerTask/MonoAOTCompiler.props index 1c7bc065d2a475..1fc8e8f41adf50 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.props +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.props @@ -1,9 +1,9 @@ - + - + diff --git a/src/tasks/AppleAppBuilder/Xcode.cs b/src/tasks/AppleAppBuilder/Xcode.cs index a9bf648f8129a3..aed4bf7dfaeba3 100644 --- a/src/tasks/AppleAppBuilder/Xcode.cs +++ b/src/tasks/AppleAppBuilder/Xcode.cs @@ -218,15 +218,24 @@ public void CreateXcodeProject(string projectName, string cmakeDirectoryPath) targetName = Target.ToString(); break; } - var deployTarget = (Target == TargetNames.MacCatalyst) ? " -DCMAKE_OSX_ARCHITECTURES=" + XcodeArch : " -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0"; var cmakeArgs = new StringBuilder(); cmakeArgs .Append("-S.") .Append(" -B").Append(projectName) .Append(" -GXcode") .Append(" -DTARGETS_APPLE_MOBILE=1") - .Append(" -DCMAKE_SYSTEM_NAME=").Append(targetName) - .Append(deployTarget); + .Append(" -DCMAKE_SYSTEM_NAME=").Append(targetName); + + if (Target == TargetNames.MacCatalyst) + { + // min deploy target version is passed later when invoking xcodebuild + cmakeArgs.Append(" -DCMAKE_OSX_ARCHITECTURES=" + XcodeArch); + } + else + { + // arch is passed later when invoking xcodebuild + cmakeArgs.Append(" -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2"); + } Utils.RunProcess(Logger, "cmake", cmakeArgs.ToString(), workingDir: cmakeDirectoryPath); } @@ -608,7 +617,7 @@ public string BuildAppBundle( .Append(" -UseModernBuildSystem=YES") .Append(" -archivePath \"").Append(Path.GetDirectoryName(xcodePrjPath)).Append('"') .Append(" -derivedDataPath \"").Append(Path.GetDirectoryName(xcodePrjPath)).Append('"') - .Append(" IPHONEOS_DEPLOYMENT_TARGET=14.2"); + .Append(" IPHONEOS_DEPLOYMENT_TARGET=15.0"); break; } } @@ -633,7 +642,7 @@ public string BuildAppBundle( .Append(" -UseModernBuildSystem=YES") .Append(" -archivePath \"").Append(Path.GetDirectoryName(xcodePrjPath)).Append('"') .Append(" -derivedDataPath \"").Append(Path.GetDirectoryName(xcodePrjPath)).Append('"') - .Append(" IPHONEOS_DEPLOYMENT_TARGET=13.5"); + .Append(" IPHONEOS_DEPLOYMENT_TARGET=15.0"); break; } } diff --git a/src/tasks/MobileBuildTasks/Apple/AppleProject.cs b/src/tasks/MobileBuildTasks/Apple/AppleProject.cs index f7927fa2bb5a81..6a0f61c1968c41 100644 --- a/src/tasks/MobileBuildTasks/Apple/AppleProject.cs +++ b/src/tasks/MobileBuildTasks/Apple/AppleProject.cs @@ -27,7 +27,7 @@ public AppleProject(string projectName, string runtimeIdentifier, TaskLoggingHel { GetTargets(runtimeIdentifier, out targetOS, out targetArchitecture); - defaultMinOSVersion = (targetOS == "maccatalyst") ? "13.1" : "11.0"; + defaultMinOSVersion = (targetOS == "maccatalyst") ? "15.0" : "12.2"; targetAbi = DetermineAbi(targetArchitecture); AppleSdk sdk = new AppleSdk(targetOS, logger); From d3a4043c23c3c5b4406552558c885b34b88d295b Mon Sep 17 00:00:00 2001 From: Jo Shields Date: Tue, 23 Apr 2024 10:36:02 -0400 Subject: [PATCH 060/248] Switch s390x and PPC64 to Mariner host OS, not ancient Ubuntu (#101424) --- eng/pipelines/common/templates/pipeline-with-resources.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/pipelines/common/templates/pipeline-with-resources.yml b/eng/pipelines/common/templates/pipeline-with-resources.yml index b9db26f6cb151c..e5e821f60fbc0e 100644 --- a/eng/pipelines/common/templates/pipeline-with-resources.yml +++ b/eng/pipelines/common/templates/pipeline-with-resources.yml @@ -77,12 +77,12 @@ extends: image: mcr.microsoft.com/dotnet-buildtools/prereqs:almalinux-8-source-build linux_s390x: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-cross-s390x + image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-s390x env: ROOTFS_DIR: /crossrootfs/s390x linux_ppc64le: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-cross-ppc64le + image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-ppc64le env: ROOTFS_DIR: /crossrootfs/ppc64le @@ -121,4 +121,4 @@ extends: image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-debpkg rpmpkg: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-fpm \ No newline at end of file + image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-fpm From d688ac290cd73af89e2048f1a13bf5ef89287b35 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Tue, 23 Apr 2024 07:43:45 -0700 Subject: [PATCH 061/248] JIT: metrics for profile consistency, gdv, devirt... (#101403) Add some metrics to early jit phases. Also add the ability to automatically merge inlinee counts to the root method, for successful inlines. --- src/coreclr/jit/fgbasic.cpp | 7 +++ src/coreclr/jit/fginline.cpp | 5 ++ src/coreclr/jit/fgprofilesynthesis.cpp | 3 ++ src/coreclr/jit/importer.cpp | 5 ++ src/coreclr/jit/importercalls.cpp | 5 ++ src/coreclr/jit/indirectcalltransformer.cpp | 12 ++++- src/coreclr/jit/jitmetadata.cpp | 14 ++++++ src/coreclr/jit/jitmetadata.h | 1 + src/coreclr/jit/jitmetadatalist.h | 55 ++++++++++++++------- 9 files changed, 87 insertions(+), 20 deletions(-) diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index fb717e1a5a50ea..af02d257d5dc29 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -235,6 +235,13 @@ bool Compiler::fgEnsureFirstBBisScratch() // JITDUMP("\fgEnsureFirstBBisScratch: Profile data could not be locally repaired. Data %s inconsisent.\n", fgPgoConsistent ? "is now" : "was already"); + + if (fgPgoConsistent) + { + Metrics.ProfileInconsistentScratchBB++; + fgPgoConsistent = false; + } + block->inheritWeight(fgFirstBB); } else diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp index 6812dfbffdb7e9..8fcea689c6c993 100644 --- a/src/coreclr/jit/fginline.cpp +++ b/src/coreclr/jit/fginline.cpp @@ -1590,6 +1590,11 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) // Update no-return call count optNoReturnCallCount += InlineeCompiler->optNoReturnCallCount; +#ifdef DEBUG + // Update metrics + Metrics.mergeToRoot(InlineeCompiler); +#endif + // Update optMethodFlags #ifdef DEBUG diff --git a/src/coreclr/jit/fgprofilesynthesis.cpp b/src/coreclr/jit/fgprofilesynthesis.cpp index d7661e5b873fae..b9ff493c87d49f 100644 --- a/src/coreclr/jit/fgprofilesynthesis.cpp +++ b/src/coreclr/jit/fgprofilesynthesis.cpp @@ -146,9 +146,12 @@ void ProfileSynthesis::Run(ProfileSynthesisOption option) m_comp->fgPgoSynthesized = true; m_comp->fgPgoConsistent = !m_approximate; + m_comp->Metrics.ProfileSynthesizedBlendedOrRepaired++; + if (m_approximate) { JITDUMP("Profile is inconsistent. Bypassing post-phase consistency checks.\n"); + m_comp->Metrics.ProfileInconsistentInitially++; } #ifdef DEBUG diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 62e215e7d65016..4998dbd6293fa9 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -5139,6 +5139,7 @@ void Compiler::impResetLeaveBlock(BasicBlock* block, unsigned jmpAddr) JITDUMP("\nimpResetLeaveBlock: Profile data could not be locally repaired. Data %s inconsisent.\n", fgPgoConsistent ? "is now" : "was already"); fgPgoConsistent = false; + Metrics.ProfileInconsistentResetLeave++; } } @@ -7319,6 +7320,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) fgRemoveRefPred(removedEdge); block->SetKindAndTargetEdge(BBJ_ALWAYS, retainedEdge); + Metrics.ImporterBranchFold++; // If we removed an edge carrying profile, try to do a local repair. // @@ -7370,6 +7372,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) JITDUMP("Profile data could not be locally repaired. Data %s inconsistent.\n", fgPgoConsistent ? "is now" : "was already"); fgPgoConsistent = false; + Metrics.ProfileInconsistentImporterBranchFold++; } } } @@ -7615,6 +7618,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) unsigned jumpCnt = block->GetSwitchTargets()->bbsCount; FlowEdge** jumpTab = block->GetSwitchTargets()->bbsDstTab; bool foundVal = false; + Metrics.ImporterSwitchFold++; for (unsigned val = 0; val < jumpCnt; val++, jumpTab++) { @@ -7656,6 +7660,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) JITDUMP("Profile data could not be locally repaired. Data %s inconsisent.\n", fgPgoConsistent ? "is now" : "was already"); fgPgoConsistent = false; + Metrics.ProfileInconsistentImporterSwitchFold++; } // Create a NOP node diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 07681c75c0e95c..0ec0d6b9afd3e8 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -7760,6 +7760,7 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, // the resulting method would be a generic method of the non-generic SZArrayHelper class. // assert(canDevirtualize); + Metrics.DevirtualizedCall++; JITDUMP(" %s; can devirtualize\n", note); @@ -7988,6 +7989,8 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, // We may end up inlining this call, so the local copy must be marked as "aliased", // making sure the inlinee importer will know when to spill references to its value. lvaGetDesc(localCopyThis->AsLclFld())->lvHasLdAddrOp = true; + Metrics.DevirtualizedCallRemovedBox++; + Metrics.DevirtualizedCallUnboxedEntry++; #if FEATURE_TAILCALL_OPT if (call->IsImplicitTailCall()) @@ -8051,6 +8054,7 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, derivedMethodAttribs = unboxedMethodAttribs; call->gtArgs.InsertInstParam(this, methodTableArg); + Metrics.DevirtualizedCallUnboxedEntry++; } } else @@ -8066,6 +8070,7 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, INDEBUG(call->gtCallDebugFlags |= GTF_CALL_MD_UNBOXED); derivedMethod = unboxedEntryMethod; pDerivedResolvedToken = &dvInfo.resolvedTokenDevirtualizedUnboxedMethod; + Metrics.DevirtualizedCallUnboxedEntry++; } } } diff --git a/src/coreclr/jit/indirectcalltransformer.cpp b/src/coreclr/jit/indirectcalltransformer.cpp index b8a2b2162fd26f..3f0c311e84a614 100644 --- a/src/coreclr/jit/indirectcalltransformer.cpp +++ b/src/coreclr/jit/indirectcalltransformer.cpp @@ -509,6 +509,12 @@ class IndirectCallTransformer (GetChecksCount() == 1) && ((origCall->gtCallMoreFlags & GTF_CALL_M_GUARDED_DEVIRT_EXACT) == 0); if (canChainGdv) { + compiler->Metrics.GDV++; + if (GetChecksCount() > 1) + { + compiler->Metrics.MultiGuessGDV++; + } + const bool isChainedGdv = (origCall->gtCallMoreFlags & GTF_CALL_M_GUARDED_DEVIRT_CHAIN) != 0; if (isChainedGdv) @@ -520,6 +526,7 @@ class IndirectCallTransformer if (isChainedGdv) { + compiler->Metrics.ChainedGDV++; TransformForChainedGdv(); } @@ -691,6 +698,7 @@ class IndirectCallTransformer GenTree* targetMethodTable = compiler->gtNewIconEmbClsHndNode(clsHnd); compare = compiler->gtNewOperNode(GT_NE, TYP_INT, targetMethodTable, methodTable); + compiler->Metrics.ClassGDV++; } else { @@ -725,6 +733,7 @@ class IndirectCallTransformer GenTree* compareTarTree = CreateTreeForLookup(methHnd, lookup); compare = compiler->gtNewOperNode(GT_NE, TYP_INT, compareTarTree, tarTree); } + compiler->Metrics.MethodGDV++; } GenTree* jmpTree = compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, compare); @@ -1240,10 +1249,11 @@ class IndirectCallTransformer if (!isReasonableUnderflow) { compiler->fgPgoConsistent = false; + compiler->Metrics.ProfileInconsistentChainedGDV++; } } - // No matter what, the minimum weight is zero + // No matter what, the minimum weight is zero // newCheckWeight = 0; } diff --git a/src/coreclr/jit/jitmetadata.cpp b/src/coreclr/jit/jitmetadata.cpp index 905cdb7317d8bb..bdf8a8d06d029e 100644 --- a/src/coreclr/jit/jitmetadata.cpp +++ b/src/coreclr/jit/jitmetadata.cpp @@ -46,6 +46,20 @@ void JitMetrics::report(Compiler* comp) #include "jitmetadatalist.h" } +//------------------------------------------------------------------------ +// JitMetrics::mergeToRoot: Merge inlinee compiler metrics to root compiler instance +// +// Parameters: +// inlineeComp - inlinee compiler instance +// +void JitMetrics::mergeToRoot(Compiler* inlineeComp) +{ + Compiler* const root = inlineeComp->impInlineRoot(); +#define JITMETADATAINFO(name, type, flags) +#define JITMETADATAMETRIC(name, type, flags) root->Metrics.name += inlineeComp->Metrics.name; +#include "jitmetadatalist.h" +} + //------------------------------------------------------------------------ // printMetric: Print a double metric value to jitstdout. // diff --git a/src/coreclr/jit/jitmetadata.h b/src/coreclr/jit/jitmetadata.h index 3b4b324497cc21..5dbd623a86daf3 100644 --- a/src/coreclr/jit/jitmetadata.h +++ b/src/coreclr/jit/jitmetadata.h @@ -23,4 +23,5 @@ class JitMetrics void report(Compiler* comp); void dump(); + void mergeToRoot(Compiler* inlineeComp); }; diff --git a/src/coreclr/jit/jitmetadatalist.h b/src/coreclr/jit/jitmetadatalist.h index f36c15ab9991d6..43afa6384d4c67 100644 --- a/src/coreclr/jit/jitmetadatalist.h +++ b/src/coreclr/jit/jitmetadatalist.h @@ -24,25 +24,42 @@ // and int64_t types supported). Their reporting is handled automatically and // they will be propagated all the way into SPMI replay/diff results. -// Name, type flags -JITMETADATAINFO(MethodFullName, const char*, 0) -JITMETADATAINFO(TieringName, const char*, 0) -JITMETADATAMETRIC(PhysicallyPromotedFields, int, 0) -JITMETADATAMETRIC(LoopsFoundDuringOpts, int, 0) -JITMETADATAMETRIC(LoopsCloned, int, 0) -JITMETADATAMETRIC(LoopsUnrolled, int, 0) -JITMETADATAMETRIC(LoopAlignmentCandidates, int, 0) -JITMETADATAMETRIC(LoopsAligned, int, 0) -JITMETADATAMETRIC(LoopsIVWidened, int, 0) -JITMETADATAMETRIC(WidenedIVs, int, 0) -JITMETADATAMETRIC(VarsInSsa, int, 0) -JITMETADATAMETRIC(HoistedExpressions, int, 0) -JITMETADATAMETRIC(RedundantBranchesEliminated, int, JIT_METADATA_HIGHER_IS_BETTER) -JITMETADATAMETRIC(JumpThreadingsPerformed, int, JIT_METADATA_HIGHER_IS_BETTER) -JITMETADATAMETRIC(CseCount, int, 0) -JITMETADATAMETRIC(BasicBlocksAtCodegen, int, 0) -JITMETADATAMETRIC(PerfScore, double, JIT_METADATA_LOWER_IS_BETTER) -JITMETADATAMETRIC(BytesAllocated, int64_t, JIT_METADATA_LOWER_IS_BETTER) +// Name, type flags +JITMETADATAINFO(MethodFullName, const char*, 0) +JITMETADATAINFO(TieringName, const char*, 0) +JITMETADATAMETRIC(PhysicallyPromotedFields, int, 0) +JITMETADATAMETRIC(LoopsFoundDuringOpts, int, 0) +JITMETADATAMETRIC(LoopsCloned, int, 0) +JITMETADATAMETRIC(LoopsUnrolled, int, 0) +JITMETADATAMETRIC(LoopAlignmentCandidates, int, 0) +JITMETADATAMETRIC(LoopsAligned, int, 0) +JITMETADATAMETRIC(LoopsIVWidened, int, 0) +JITMETADATAMETRIC(WidenedIVs, int, 0) +JITMETADATAMETRIC(VarsInSsa, int, 0) +JITMETADATAMETRIC(HoistedExpressions, int, 0) +JITMETADATAMETRIC(RedundantBranchesEliminated, int, JIT_METADATA_HIGHER_IS_BETTER) +JITMETADATAMETRIC(JumpThreadingsPerformed, int, JIT_METADATA_HIGHER_IS_BETTER) +JITMETADATAMETRIC(CseCount, int, 0) +JITMETADATAMETRIC(BasicBlocksAtCodegen, int, 0) +JITMETADATAMETRIC(PerfScore, double, JIT_METADATA_LOWER_IS_BETTER) +JITMETADATAMETRIC(BytesAllocated, int64_t, JIT_METADATA_LOWER_IS_BETTER) +JITMETADATAMETRIC(ImporterBranchFold, int, 0) +JITMETADATAMETRIC(ImporterSwitchFold, int, 0) +JITMETADATAMETRIC(DevirtualizedCall, int, 0) +JITMETADATAMETRIC(DevirtualizedCallUnboxedEntry, int, 0) +JITMETADATAMETRIC(DevirtualizedCallRemovedBox, int, 0) +JITMETADATAMETRIC(GDV, int, 0) +JITMETADATAMETRIC(ClassGDV, int, 0) +JITMETADATAMETRIC(MethodGDV, int, 0) +JITMETADATAMETRIC(MultiGuessGDV, int, 0) +JITMETADATAMETRIC(ChainedGDV, int, 0) +JITMETADATAMETRIC(ProfileSynthesizedBlendedOrRepaired, int, 0) +JITMETADATAMETRIC(ProfileInconsistentInitially, int, 0) +JITMETADATAMETRIC(ProfileInconsistentResetLeave, int, 0) +JITMETADATAMETRIC(ProfileInconsistentImporterBranchFold, int, 0) +JITMETADATAMETRIC(ProfileInconsistentImporterSwitchFold, int, 0) +JITMETADATAMETRIC(ProfileInconsistentChainedGDV, int, 0) +JITMETADATAMETRIC(ProfileInconsistentScratchBB, int, 0) #undef JITMETADATA #undef JITMETADATAINFO From b6281b60f9813f803e48f07e61a1b152dcb6ec65 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 11:12:49 -0400 Subject: [PATCH 062/248] Update dependencies from https://github.com/dotnet/source-build-externals build 20240422.1 (#101426) Microsoft.SourceBuild.Intermediate.source-build-externals From Version 9.0.0-alpha.1.24216.3 -> To Version 9.0.0-alpha.1.24222.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1f9d9e699d07b9..60e81c18d6d3ee 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -85,9 +85,9 @@ - + https://github.com/dotnet/source-build-externals - 5a273649709de76f61957e3d69e1f031e5ac82e2 + 1223ec47c74e79d44950d429a36386de6c7bf9c8 From 1f9e7e869636312c66e0b66c8ff492bb5477eaf1 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Tue, 23 Apr 2024 08:13:46 -0700 Subject: [PATCH 063/248] Remove AD0001 from NoWarn (#101404) --- .../System.Private.CoreLib/src/System.Private.CoreLib.csproj | 2 -- src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index 70928c997a5084..c7bfa7ff2215ed 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -1,8 +1,6 @@ true - - $(NoWarn);AD0001 diff --git a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj index 905dc83eb08dee..076fc42815c65c 100644 --- a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -36,8 +36,7 @@ $(ProductVersion) $(ProductVersion) - - $(NoWarn),0419,0649,AD0001 + $(NoWarn),0419,0649 enable From 2e75aac8dbbae5420a93f6fbe9568812dbeb3472 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 11:17:55 -0400 Subject: [PATCH 064/248] Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-optimization build 20240419.3 (#101375) optimization.linux-arm64.MIBC.Runtime , optimization.linux-x64.MIBC.Runtime , optimization.windows_nt-arm64.MIBC.Runtime , optimization.windows_nt-x64.MIBC.Runtime , optimization.windows_nt-x86.MIBC.Runtime , optimization.PGO.CoreCLR From Version 1.0.0-prerelease.24106.4 -> To Version 1.0.0-prerelease.24219.3 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 24 ++++++++++++------------ eng/Versions.props | 12 ++++++------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 60e81c18d6d3ee..d3abb581e0f162 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -336,21 +336,21 @@ https://github.com/dotnet/arcade b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 78a5b978e1965c1335edb4b9a22bc4d6ff5a77a6 + c54b8e8611d50594cc926fd7c81205871a38be6f - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 78a5b978e1965c1335edb4b9a22bc4d6ff5a77a6 + c54b8e8611d50594cc926fd7c81205871a38be6f - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 78a5b978e1965c1335edb4b9a22bc4d6ff5a77a6 + c54b8e8611d50594cc926fd7c81205871a38be6f - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 78a5b978e1965c1335edb4b9a22bc4d6ff5a77a6 + c54b8e8611d50594cc926fd7c81205871a38be6f https://github.com/dotnet/hotreload-utils @@ -396,13 +396,13 @@ cf8c24575410adf397c0823fd7061f9451049ea1 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 78a5b978e1965c1335edb4b9a22bc4d6ff5a77a6 + c54b8e8611d50594cc926fd7c81205871a38be6f - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 78a5b978e1965c1335edb4b9a22bc4d6ff5a77a6 + c54b8e8611d50594cc926fd7c81205871a38be6f diff --git a/eng/Versions.props b/eng/Versions.props index b9c65331748549..95e1a7403b2580 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -153,12 +153,12 @@ 9.0.0-beta.24215.1 9.0.0-beta.24215.1 - 1.0.0-prerelease.24106.4 - 1.0.0-prerelease.24106.4 - 1.0.0-prerelease.24106.4 - 1.0.0-prerelease.24106.4 - 1.0.0-prerelease.24106.4 - 1.0.0-prerelease.24106.4 + 1.0.0-prerelease.24219.3 + 1.0.0-prerelease.24219.3 + 1.0.0-prerelease.24219.3 + 1.0.0-prerelease.24219.3 + 1.0.0-prerelease.24219.3 + 1.0.0-prerelease.24219.3 2.0.0 17.8.0-beta1.23475.2 From bbf3a4a4031a13142a7c536c5b945b121497bf79 Mon Sep 17 00:00:00 2001 From: Katelyn Gadd Date: Tue, 23 Apr 2024 08:48:23 -0700 Subject: [PATCH 065/248] [mono] Miscellaneous startup optimizations (#101263) * Optimize out an unnecessary memset under g_slist_prepend * Don't inline constructors of Exception or its descendants into interpreter method bodies --- src/mono/mono/eglib/gslist.c | 3 ++- src/mono/mono/metadata/class-getters.h | 1 + src/mono/mono/metadata/class-init.c | 12 ++++++++++++ src/mono/mono/metadata/class-private-definition.h | 5 +++-- src/mono/mono/mini/interp/transform.c | 3 +++ 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/mono/mono/eglib/gslist.c b/src/mono/mono/eglib/gslist.c index 71cd6dfd972e97..aa03c4be8d1536 100644 --- a/src/mono/mono/eglib/gslist.c +++ b/src/mono/mono/eglib/gslist.c @@ -52,7 +52,8 @@ g_slist_append (GSList *list, gpointer data) GSList* g_slist_prepend (GSList *list, gpointer data) { - GSList *head = g_slist_alloc (); + // We don't need to zero the allocation using g_slist_alloc since we fully initialize the node + GSList *head = g_new (GSList, 1); head->data = data; head->next = list; diff --git a/src/mono/mono/metadata/class-getters.h b/src/mono/mono/metadata/class-getters.h index 8e9804ba45aa8b..30cc66fcf7c176 100644 --- a/src/mono/mono/metadata/class-getters.h +++ b/src/mono/mono/metadata/class-getters.h @@ -48,6 +48,7 @@ MONO_CLASS_GETTER(m_class_is_interfaces_inited, gboolean, , MonoClass, interface MONO_CLASS_GETTER(m_class_is_simd_type, gboolean, , MonoClass, simd_type) MONO_CLASS_GETTER(m_class_is_has_finalize_inited, gboolean, , MonoClass, has_finalize_inited) MONO_CLASS_GETTER(m_class_is_fields_inited, gboolean, , MonoClass, fields_inited) +MONO_CLASS_GETTER(m_class_is_exception_class, gboolean, , MonoClass, is_exception_class) MONO_CLASS_GETTER(m_class_has_failure, gboolean, , MonoClass, has_failure) MONO_CLASS_GETTER(m_class_has_deferred_failure, gboolean, , MonoClass, has_deferred_failure) MONO_CLASS_GETTER(m_class_has_weak_fields, gboolean, , MonoClass, has_weak_fields) diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c index c2210a0e41765c..13cf1fa612b359 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -735,6 +735,17 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError } } + // compute is_exception_class, used by interp to avoid inlining exception handling code + if ( + klass->parent && !m_class_is_valuetype (klass) && + !m_class_is_interface (klass) + ) { + if (m_class_is_exception_class (klass->parent)) + klass->is_exception_class = 1; + else if (!strcmp (klass->name, "Exception") && !strcmp(klass->name_space, "System")) + klass->is_exception_class = 1; + } + mono_loader_unlock (); MONO_PROFILER_RAISE (class_loaded, (klass)); @@ -926,6 +937,7 @@ mono_class_create_generic_inst (MonoGenericClass *gclass) klass->this_arg.byref__ = TRUE; klass->is_inlinearray = gklass->is_inlinearray; klass->inlinearray_value = gklass->inlinearray_value; + klass->is_exception_class = gklass->is_exception_class; klass->enumtype = gklass->enumtype; klass->valuetype = gklass->valuetype; diff --git a/src/mono/mono/metadata/class-private-definition.h b/src/mono/mono/metadata/class-private-definition.h index ff33e6dd8a78e6..1e0c01ab336b3b 100644 --- a/src/mono/mono/metadata/class-private-definition.h +++ b/src/mono/mono/metadata/class-private-definition.h @@ -68,9 +68,8 @@ struct _MonoClass { guint no_special_static_fields : 1; /* has no thread/context static fields */ guint nested_classes_inited : 1; /* Whenever nested_class is initialized */ - - /* next byte*/ guint interfaces_inited : 1; /* interfaces is initialized */ + /* next byte*/ guint simd_type : 1; /* class is a simd intrinsic type */ guint has_finalize_inited : 1; /* has_finalize is initialized */ guint fields_inited : 1; /* setup_fields () has finished */ @@ -79,6 +78,8 @@ struct _MonoClass { guint has_dim_conflicts : 1; /* Class has conflicting default interface methods */ guint any_field_has_auto_layout : 1; /* a field in this type's layout uses auto-layout */ guint has_deferred_failure : 1; + /* next byte*/ + guint is_exception_class : 1; /* is System.Exception or derived from it */ MonoClass *parent; MonoClass *nested_in; diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 88844dae725374..be1d722f146408 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -2907,6 +2907,9 @@ interp_method_check_inlining (TransformData *td, MonoMethod *method, MonoMethodS if (g_list_find (td->dont_inline, method)) return FALSE; + if (m_class_is_exception_class (method->klass) && !strcmp (method->name, ".ctor")) + return FALSE; + return TRUE; } From 02f10c1eb4eddc78496f0d803ed09d5838950185 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Tue, 23 Apr 2024 17:51:26 +0200 Subject: [PATCH 066/248] [wasm] Do not use link flags for bitcode compilation (#101397) * [wasm] Do not use link flags for bitcode compilation This avoids errors like: /root/helix/work/correlation/build/wasm-shared/WasmApp.Common.targets(832,5): error : emcc: warning: linker setting ignored during compilation: 'EXPORT_ES6' [-Wunused-command-line-argument] [/root/helix/work/workitem/e/publish/ProxyProjectForAOTOnHelix.proj] /root/helix/work/correlation/build/wasm-shared/WasmApp.Common.targets(832,5): error : emcc: warning: linker setting ignored during compilation: 'EXPORT_EXCEPTION_HANDLING_HELPERS' [-Wunused-command-line-argument] [/root/helix/work/workitem/e/publish/ProxyProjectForAOTOnHelix.proj] * Rename _BitcodeLDFlags to _BitcodeCompileFlags Update the comment as well. _BitcodeLDFlags were used only for the BC compilation. This way we keep the possibility to add extra flags via EmccExtraBitcodeCompilationFlags and WasiClangExtraBitcodeCompileFlags. --- src/mono/browser/build/BrowserWasmApp.targets | 4 ++-- src/mono/wasi/build/WasiApp.targets | 4 ++-- src/mono/wasm/build/WasmApp.Common.targets | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mono/browser/build/BrowserWasmApp.targets b/src/mono/browser/build/BrowserWasmApp.targets index aa231c45d8b7cc..484d3486c5eaa8 100644 --- a/src/mono/browser/build/BrowserWasmApp.targets +++ b/src/mono/browser/build/BrowserWasmApp.targets @@ -406,8 +406,8 @@ - <_BitcodeLDFlags Include="@(_EmccLDFlags)" /> - <_BitcodeLDFlags Include="$(EmccExtraBitcodeLDFlags)" /> + <_BitcodeCompileFlags Include="@(_EmccCommonFlags)" /> + <_BitcodeCompileFlags Include="$(EmccExtraBitcodeCompilationFlags)" /> diff --git a/src/mono/wasi/build/WasiApp.targets b/src/mono/wasi/build/WasiApp.targets index 37d6d40d1f172e..c5ecf84ad0c73c 100644 --- a/src/mono/wasi/build/WasiApp.targets +++ b/src/mono/wasi/build/WasiApp.targets @@ -265,8 +265,8 @@ - <_BitcodeLDFlags Include="@(_WasiClangLDFlags)" /> - <_BitcodeLDFlags Include="$(WasiClangExtraBitcodeLDFlags)" /> + <_BitcodeCompileFlags Include="@(_WasiClangCommonFlags)" /> + <_BitcodeCompileFlags Include="$(WasiClangExtraBitcodeCompileFlags)" /> diff --git a/src/mono/wasm/build/WasmApp.Common.targets b/src/mono/wasm/build/WasmApp.Common.targets index 7e4c7d343417fd..f06b9a1261fe5e 100644 --- a/src/mono/wasm/build/WasmApp.Common.targets +++ b/src/mono/wasm/build/WasmApp.Common.targets @@ -800,11 +800,11 @@ - + From 076ecd841e8059ccd9e48a85d79fa4e91c9c50c5 Mon Sep 17 00:00:00 2001 From: Katelyn Gadd Date: Tue, 23 Apr 2024 08:53:22 -0700 Subject: [PATCH 067/248] [mono] Optimize startup vtable setup (#101312) * Add new [ptr, ptr] -> ptr simdhash variant for caching * Cache mono_class_implement_interface_slow because we perform many redundant calls to it during application startup * Verify cache in checked builds --- src/mono/mono/metadata/CMakeLists.txt | 3 +- src/mono/mono/metadata/class-setup-vtable.c | 9 +- src/mono/mono/metadata/class.c | 116 +++++++++++++++++- src/native/containers/containers.cmake | 2 + .../containers/dn-simdhash-ptrpair-ptr.c | 39 ++++++ .../containers/dn-simdhash-specializations.h | 15 +++ src/native/containers/dn-simdhash.c | 16 ++- src/native/containers/dn-simdhash.h | 5 + 8 files changed, 196 insertions(+), 9 deletions(-) create mode 100644 src/native/containers/dn-simdhash-ptrpair-ptr.c diff --git a/src/mono/mono/metadata/CMakeLists.txt b/src/mono/mono/metadata/CMakeLists.txt index 9efd5ac0079c24..9d6010e95f3286 100644 --- a/src/mono/mono/metadata/CMakeLists.txt +++ b/src/mono/mono/metadata/CMakeLists.txt @@ -45,7 +45,8 @@ endif() set(imported_native_sources ../../../native/containers/dn-simdhash.c ../../../native/containers/dn-simdhash-string-ptr.c - ../../../native/containers/dn-simdhash-u32-ptr.c) + ../../../native/containers/dn-simdhash-u32-ptr.c + ../../../native/containers/dn-simdhash-ptrpair-ptr.c) set(metadata_common_sources appdomain.c diff --git a/src/mono/mono/metadata/class-setup-vtable.c b/src/mono/mono/metadata/class-setup-vtable.c index 9a235c1ec0cced..62afa76dde5b74 100644 --- a/src/mono/mono/metadata/class-setup-vtable.c +++ b/src/mono/mono/metadata/class-setup-vtable.c @@ -773,6 +773,13 @@ mono_method_get_method_definition (MonoMethod *method) static gboolean verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum) { + // on windows and arm, we define NDEBUG for release builds + // on browser and wasi, we define DEBUG for debug builds +#ifdef ENABLE_CHECKED_BUILD + if (klass->image == mono_defaults.corlib) + return TRUE; +#endif + int i; for (i = 0; i < onum; ++i) { @@ -1760,7 +1767,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o MonoMethod *override = iface_overrides [i*2 + 1]; if (mono_class_is_gtd (override->klass)) { override = mono_class_inflate_generic_method_full_checked (override, ic, mono_class_get_context (ic), error); - } + } // there used to be code here to inflate decl if decl->is_inflated, but in https://github.com/dotnet/runtime/pull/64102#discussion_r790019545 we // think that this does not correspond to any real code. if (!apply_override (klass, ic, vtable, decl, override, &override_map, &override_class_map, &conflict_map)) diff --git a/src/mono/mono/metadata/class.c b/src/mono/mono/metadata/class.c index 5ae4f1981d38ac..6045628bf49e7f 100644 --- a/src/mono/mono/metadata/class.c +++ b/src/mono/mono/metadata/class.c @@ -4331,12 +4331,16 @@ mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass) } return TRUE; } -/*Check if @candidate implements the interface @target*/ + static gboolean -mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate) +mono_class_implement_interface_slow_cached (MonoClass *target, MonoClass *candidate, dn_simdhash_ptrpair_ptr_t *cache); + +static gboolean +mono_class_implement_interface_slow_uncached (MonoClass *target, MonoClass *candidate, dn_simdhash_ptrpair_ptr_t *cache) { ERROR_DECL (error); int i; + gboolean is_variant = mono_class_has_variant_generic_params (target); if (is_variant && MONO_CLASS_IS_INTERFACE_INTERNAL (candidate)) { @@ -4365,7 +4369,7 @@ mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate) return TRUE; if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class)) return TRUE; - if (mono_class_implement_interface_slow (target, iface_class)) + if (mono_class_implement_interface_slow_cached (target, iface_class, cache)) return TRUE; } } @@ -4390,7 +4394,7 @@ mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate) if (is_variant && mono_class_is_variant_compatible_slow (target, candidate_interfaces [i])) return TRUE; - if (mono_class_implement_interface_slow (target, candidate_interfaces [i])) + if (mono_class_implement_interface_slow_cached (target, candidate_interfaces [i], cache)) return TRUE; } } @@ -4400,6 +4404,107 @@ mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate) return FALSE; } +// #define LOG_INTERFACE_CACHE_HITS 1 + +#if LOG_INTERFACE_CACHE_HITS +static gint64 implement_interface_hits = 0, implement_interface_misses = 0; + +static void +log_hit_rate (dn_simdhash_ptrpair_ptr_t *cache) +{ + gint64 total_calls = implement_interface_hits + implement_interface_misses; + if ((total_calls % 500) != 0) + return; + double hit_rate = implement_interface_hits * 100.0 / total_calls; + g_printf ("implement_interface cache hit rate: %f (%lld total calls). Overflow count: %u\n", hit_rate, total_calls, dn_simdhash_overflow_count (cache)); +} +#endif + +static gboolean +mono_class_implement_interface_slow_cached (MonoClass *target, MonoClass *candidate, dn_simdhash_ptrpair_ptr_t *cache) +{ + gpointer cached_result = NULL; + dn_ptrpair_t key = { target, candidate }; + gboolean result = 0, cache_hit = 0; + + // Skip the caching logic for exact matches + if (candidate == target) + return TRUE; + + cache_hit = dn_simdhash_ptrpair_ptr_try_get_value (cache, key, &cached_result); + if (cache_hit) { + // Testing shows a cache hit rate of 60% on S.R.Tests and S.T.J.Tests, + // and 40-50% for small app startup. Near-zero overflow count. +#if LOG_INTERFACE_CACHE_HITS + implement_interface_hits++; + log_hit_rate (cache); +#endif + result = (cached_result != NULL); +#ifndef ENABLE_CHECKED_BUILD + return result; +#endif + } + + gboolean uncached_result = mono_class_implement_interface_slow_uncached (target, candidate, cache); + + if (!cache_hit) { +#if LOG_INTERFACE_CACHE_HITS + implement_interface_misses++; + log_hit_rate (cache); +#endif + dn_simdhash_ptrpair_ptr_try_add (cache, key, uncached_result ? GUINT_TO_POINTER(1) : NULL); + } + +#ifdef ENABLE_CHECKED_BUILD + if (cache_hit) { + if (result != uncached_result) + g_print ( + "Cache mismatch for %s.%s and %s.%s: cached=%d, uncached=%d\n", + m_class_get_name_space (target), m_class_get_name (target), + m_class_get_name_space (candidate), m_class_get_name (candidate), + result, uncached_result + ); + g_assert (result == uncached_result); + } +#endif + return uncached_result; +} + +static dn_simdhash_ptrpair_ptr_t *implement_interface_scratch_cache = NULL; + +/*Check if @candidate implements the interface @target*/ +static gboolean +mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate) +{ + gpointer cas_result; + gboolean result; + dn_simdhash_ptrpair_ptr_t *cache = (dn_simdhash_ptrpair_ptr_t *)mono_atomic_xchg_ptr ((volatile gpointer *)&implement_interface_scratch_cache, NULL); + if (!cache) + // Roughly 64KB of memory usage and big enough to have fast lookups + // Smaller is viable but makes the hit rate worse + cache = dn_simdhash_ptrpair_ptr_new (2048, NULL); + else if (dn_simdhash_count (cache) >= 2250) { + // FIXME: 2250 is arbitrary (roughly 256 11-item buckets w/load factor) + // One step down reduces hit rate by approximately 2-4% + // HACK: Only clear the scratch cache once it gets too big. + // The pattern is that (especially during startup), we have lots + // of mono_class_implement_interface_slow calls back to back that + // perform similar checks, so keeping the cache data around between + // sequential calls will potentially optimize them a lot. + dn_simdhash_clear (cache); + } + + result = mono_class_implement_interface_slow_cached (target, candidate, cache); + + // Under most circumstances we won't have multiple threads competing to run implement_interface_slow, + // so it's not worth making this thread-local and potentially keeping a cache instance around per-thread. + cas_result = mono_atomic_cas_ptr ((volatile gpointer *)&implement_interface_scratch_cache, cache, NULL); + if (cas_result != NULL) + dn_simdhash_free (cache); + + return result; +} + /* * Check if @oklass can be assigned to @klass. * This function does the same as mono_class_is_assignable_from_internal but is safe to be used from mono_class_init_internal context. @@ -4416,8 +4521,9 @@ mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate) return TRUE; /*If target is not an interface there is no need to check them.*/ - if (MONO_CLASS_IS_INTERFACE_INTERNAL (target)) + if (MONO_CLASS_IS_INTERFACE_INTERNAL (target)) { return mono_class_implement_interface_slow (target, candidate); + } if (m_class_is_delegate (target) && mono_class_has_variant_generic_params (target)) return mono_class_is_variant_compatible (target, candidate, FALSE); diff --git a/src/native/containers/containers.cmake b/src/native/containers/containers.cmake index 16c41eab5619f8..4749dceea2dd9a 100644 --- a/src/native/containers/containers.cmake +++ b/src/native/containers/containers.cmake @@ -13,6 +13,8 @@ list(APPEND SHARED_CONTAINER_SOURCES # dn-simdhash-string-ptr.c # dn-simdhash-u32-ptr.c # dn-simdhash-ptr-ptr.c + # dn-simdhash-ght-compatible.c + # dn-simdhash-ptrpair-ptr.c ) list(APPEND SHARED_CONTAINER_HEADERS diff --git a/src/native/containers/dn-simdhash-ptrpair-ptr.c b/src/native/containers/dn-simdhash-ptrpair-ptr.c new file mode 100644 index 00000000000000..d377647b6636ac --- /dev/null +++ b/src/native/containers/dn-simdhash-ptrpair-ptr.c @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include +#include "dn-simdhash.h" + +#include "dn-simdhash-utils.h" + +typedef struct dn_ptrpair_t { + void *first; + void *second; +} dn_ptrpair_t; + +static inline uint32_t +dn_ptrpair_t_hash (dn_ptrpair_t key) +{ + return (MurmurHash3_32_ptr(key.first, 0) ^ MurmurHash3_32_ptr(key.second, 1)); +} + +static inline uint8_t +dn_ptrpair_t_equals (dn_ptrpair_t lhs, dn_ptrpair_t rhs) +{ + return (lhs.first == rhs.first) && (lhs.second == rhs.second); +} + +#define DN_SIMDHASH_T dn_simdhash_ptrpair_ptr +#define DN_SIMDHASH_KEY_T dn_ptrpair_t +#define DN_SIMDHASH_VALUE_T void * +#define DN_SIMDHASH_KEY_HASHER(hash, key) dn_ptrpair_t_hash(key) +#define DN_SIMDHASH_KEY_EQUALS(hash, lhs, rhs) dn_ptrpair_t_equals(lhs, rhs) +#if SIZEOF_VOID_P == 8 +// 192 bytes holds 12 16-byte blocks, so 11 keys and one suffix table +#define DN_SIMDHASH_BUCKET_CAPACITY 11 +#else +// 128 bytes holds 16 8-byte blocks, so 14 keys and one suffix table +#define DN_SIMDHASH_BUCKET_CAPACITY 14 +#endif + +#include "dn-simdhash-specialization.h" diff --git a/src/native/containers/dn-simdhash-specializations.h b/src/native/containers/dn-simdhash-specializations.h index 4966c7575d19a0..9533edfc5f3d1f 100644 --- a/src/native/containers/dn-simdhash-specializations.h +++ b/src/native/containers/dn-simdhash-specializations.h @@ -59,4 +59,19 @@ typedef struct dn_simdhash_str_key dn_simdhash_str_key; #include "dn-simdhash-ght-compatible.h" + +typedef struct dn_ptrpair_t { + void *first, *second; +} dn_ptrpair_t; + +#define DN_SIMDHASH_T dn_simdhash_ptrpair_ptr +#define DN_SIMDHASH_KEY_T dn_ptrpair_t +#define DN_SIMDHASH_VALUE_T void * + +#include "dn-simdhash-specialization-declarations.h" + +#undef DN_SIMDHASH_T +#undef DN_SIMDHASH_KEY_T +#undef DN_SIMDHASH_VALUE_T + #endif diff --git a/src/native/containers/dn-simdhash.c b/src/native/containers/dn-simdhash.c index 03d4d2bf3951aa..d1e2b6e330b6ef 100644 --- a/src/native/containers/dn-simdhash.c +++ b/src/native/containers/dn-simdhash.c @@ -119,8 +119,7 @@ dn_simdhash_clear (dn_simdhash_t *hash) if (hash->vtable.destroy_all) hash->vtable.destroy_all(hash); hash->count = 0; - // TODO: Scan through buckets sequentially and only erase ones with data in them - // Maybe skip erasing the key slots too? + // TODO: Implement a fast clear algorithm that scans buckets and only clears ones w/nonzero count memset(hash->buffers.buckets, 0, hash->buffers.buckets_length * hash->meta->bucket_size_bytes); // Skip this for performance; memset is especially slow in wasm // memset(hash->buffers.values, 0, hash->buffers.values_length * hash->meta->value_size); @@ -140,6 +139,19 @@ dn_simdhash_count (dn_simdhash_t *hash) return hash->count; } +uint32_t +dn_simdhash_overflow_count (dn_simdhash_t *hash) +{ + assert(hash); + uint32_t result = 0; + for (uint32_t bucket_index = 0; bucket_index < hash->buffers.buckets_length; bucket_index++) { + uint8_t *suffixes = ((uint8_t *)hash->buffers.buckets) + (bucket_index * hash->meta->bucket_size_bytes); + uint8_t cascade_count = suffixes[DN_SIMDHASH_CASCADED_SLOT]; + result += cascade_count; + } + return result; +} + void dn_simdhash_ensure_capacity (dn_simdhash_t *hash, uint32_t capacity) { diff --git a/src/native/containers/dn-simdhash.h b/src/native/containers/dn-simdhash.h index da4a7914e18873..a2d6e87c9045fe 100644 --- a/src/native/containers/dn-simdhash.h +++ b/src/native/containers/dn-simdhash.h @@ -144,6 +144,11 @@ dn_simdhash_capacity (dn_simdhash_t *hash); uint32_t dn_simdhash_count (dn_simdhash_t *hash); +// Returns the estimated number of items that have overflowed out of a bucket. +// WARNING: This is expensive to calculate. +uint32_t +dn_simdhash_overflow_count (dn_simdhash_t *hash); + // Automatically resizes the table if it is too small to hold the requested number // of items. Will not shrink the table if it is already bigger. void From af52e82167b2eac37ede88a64da62ce56230b5f6 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com> Date: Tue, 23 Apr 2024 18:06:37 +0200 Subject: [PATCH 068/248] [browser][hybrid] drop `wrap_error_root`, `wrap_no_error_root` (#101390) * Calendar - done * Culture info - done. * Missing change to the previous commit. * Change case - done. * issing change to previous commit * Collation - done. * Locales - done. * Feedback * remove MonoString that is not thread-safe * Preserve stack from JS correctly. --- .../src/Interop/Browser/Interop.Calendar.cs | 2 +- .../Interop/Browser/Interop.CompareInfo.cs | 8 +- .../src/Interop/Browser/Interop.Locale.cs | 8 +- .../src/Interop/Browser/Interop.TextInfo.cs | 4 +- .../Globalization/CalendarData.Browser.cs | 53 ++++---- .../System/Globalization/CompareInfo.Icu.cs | 22 ++-- .../Globalization/CompareInfo.WebAssembly.cs | 66 ++++------ .../Globalization/CultureData.Browser.cs | 115 +++++++++++------ .../Globalization/TextInfo.WebAssembly.cs | 17 ++- src/mono/browser/runtime/corebindings.c | 23 ++-- .../runtime/hybrid-globalization/calendar.ts | 29 ++--- .../hybrid-globalization/change-case.ts | 36 ++---- .../hybrid-globalization/collations.ts | 116 ++++++++---------- .../hybrid-globalization/culture-info.ts | 30 ++--- .../runtime/hybrid-globalization/helpers.ts | 32 ----- .../runtime/hybrid-globalization/locales.ts | 79 +++++------- 16 files changed, 297 insertions(+), 343 deletions(-) diff --git a/src/libraries/Common/src/Interop/Browser/Interop.Calendar.cs b/src/libraries/Common/src/Interop/Browser/Interop.Calendar.cs index 2a7b1d02ad21ad..73fbfa924d141d 100644 --- a/src/libraries/Common/src/Interop/Browser/Interop.Calendar.cs +++ b/src/libraries/Common/src/Interop/Browser/Interop.Calendar.cs @@ -9,6 +9,6 @@ internal static partial class Interop internal static unsafe partial class JsGlobalization { [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int GetCalendarInfo(in string culture, CalendarId calendarId, char* buffer, int bufferLength, out int exceptionalResult, out object result); + internal static extern unsafe nint GetCalendarInfo(char* culture, int cultureLength, CalendarId calendarId, char* buffer, int bufferMaxLength, out int bufferLength); } } diff --git a/src/libraries/Common/src/Interop/Browser/Interop.CompareInfo.cs b/src/libraries/Common/src/Interop/Browser/Interop.CompareInfo.cs index cb7edf5b380a26..638934edb416d6 100644 --- a/src/libraries/Common/src/Interop/Browser/Interop.CompareInfo.cs +++ b/src/libraries/Common/src/Interop/Browser/Interop.CompareInfo.cs @@ -8,15 +8,15 @@ internal static partial class Interop internal static unsafe partial class JsGlobalization { [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int CompareString(in string culture, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, out int exceptionalResult, out object result); + internal static extern unsafe nint CompareString(char* culture, int cultureLength, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, out int resultPtr); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe bool StartsWith(in string culture, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, out int exceptionalResult, out object result); + internal static extern unsafe nint StartsWith(char* culture, int cultureLength, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, out bool resultPtr); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe bool EndsWith(in string culture, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, out int exceptionalResult, out object result); + internal static extern unsafe nint EndsWith(char* culture, int cultureLength, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, out bool resultPtr); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int IndexOf(in string culture, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, bool fromBeginning, out int exceptionalResult, out object result); + internal static extern unsafe nint IndexOf(char* culture, int cultureLength, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, bool fromBeginning, out int resultPtr); } } diff --git a/src/libraries/Common/src/Interop/Browser/Interop.Locale.cs b/src/libraries/Common/src/Interop/Browser/Interop.Locale.cs index b831e72e70cdbc..b2dc0db99c00c0 100644 --- a/src/libraries/Common/src/Interop/Browser/Interop.Locale.cs +++ b/src/libraries/Common/src/Interop/Browser/Interop.Locale.cs @@ -8,12 +8,12 @@ internal static partial class Interop internal static unsafe partial class JsGlobalization { [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int GetCultureInfo(in string culture, char* buffer, int bufferLength, out int exceptionalResult, out object result); + internal static extern unsafe nint GetCultureInfo(char* culture, int cultureLength, char* buffer, int bufferMaxLength, out int resultLength); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int GetFirstDayOfWeek(in string culture, out int exceptionalResult, out object result); + internal static extern unsafe nint GetFirstDayOfWeek(char* culture, int cultureLength, out int resultPtr); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int GetFirstWeekOfYear(in string culture, out int exceptionalResult, out object result); + internal static extern unsafe nint GetFirstWeekOfYear(char* culture, int cultureLength, out int resultPtr); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int GetLocaleInfo(in string locale, in string culture, char* buffer, int bufferLength, out int exceptionalResult, out object result); + internal static extern unsafe nint GetLocaleInfo(char* locale, int localeLength, char* culture, int cultureLength, char* buffer, int bufferLength, out int resultLength); } } diff --git a/src/libraries/Common/src/Interop/Browser/Interop.TextInfo.cs b/src/libraries/Common/src/Interop/Browser/Interop.TextInfo.cs index ff157eb45f26cf..a10d2897f75be0 100644 --- a/src/libraries/Common/src/Interop/Browser/Interop.TextInfo.cs +++ b/src/libraries/Common/src/Interop/Browser/Interop.TextInfo.cs @@ -8,8 +8,8 @@ internal static partial class Interop internal static unsafe partial class JsGlobalization { [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe void ChangeCaseInvariant(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper, out int exceptionalResult, out object result); + internal static extern unsafe nint ChangeCaseInvariant(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe void ChangeCase(in string culture, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper, out int exceptionalResult, out object result); + internal static extern unsafe nint ChangeCase(char* culture, int cultureLen, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.Browser.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.Browser.cs index 87199ed3f1eedf..582492c6c40f84 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.Browser.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.Browser.cs @@ -14,32 +14,33 @@ internal sealed partial class CalendarData private const int CALENDAR_INFO_BUFFER_LEN = 1000; private unsafe bool JSLoadCalendarDataFromBrowser(string localeName, CalendarId calendarId) { - char* buffer = stackalloc char[CALENDAR_INFO_BUFFER_LEN]; - int exception; - object exResult; - int resultLength = Interop.JsGlobalization.GetCalendarInfo(localeName, calendarId, buffer, CALENDAR_INFO_BUFFER_LEN, out exception, out exResult); - if (exception != 0) - throw new Exception((string)exResult); - string result = new string(buffer, 0, resultLength); - string[] subresults = result.Split("##"); - if (subresults.Length < 14) - throw new Exception("CalendarInfo recieved from the Browser is in icorrect format."); - // JS always has one result per locale, so even arrays are initialized with one element - this.sNativeName = string.IsNullOrEmpty(subresults[0]) ? ((CalendarId)calendarId).ToString() : subresults[0]; // this is EnglishName, not NativeName but it's the best we can do - this.saYearMonths = new string[] { subresults[1] }; - this.sMonthDay = subresults[2]; - this.saLongDates = new string[] { subresults[3] }; - this.saShortDates = new string[] { subresults[4] }; - this.saEraNames = new string[] { subresults[5] }; - this.saAbbrevEraNames = new string[] { subresults[6] }; - this.saDayNames = subresults[7].Split("||"); - this.saAbbrevDayNames = subresults[8].Split("||"); - this.saSuperShortDayNames = subresults[9].Split("||"); - this.saMonthNames = ResizeMonthsArray(subresults[10].Split("||")); - this.saAbbrevMonthNames = ResizeMonthsArray(subresults[11].Split("||")); - this.saMonthGenitiveNames = ResizeMonthsArray(subresults[12].Split("||")); - this.saAbbrevMonthGenitiveNames = ResizeMonthsArray(subresults[13].Split("||")); - return true; + ReadOnlySpan localeNameSpan = localeName.AsSpan(); + fixed (char* pLocaleName = &MemoryMarshal.GetReference(localeNameSpan)) + { + char* buffer = stackalloc char[CALENDAR_INFO_BUFFER_LEN]; + nint exceptionPtr = Interop.JsGlobalization.GetCalendarInfo(pLocaleName, localeNameSpan.Length, calendarId, buffer, CALENDAR_INFO_BUFFER_LEN, out int resultLength); + Helper.MarshalAndThrowIfException(exceptionPtr); + string result = new string(buffer, 0, resultLength); + string[] subresults = result.Split("##"); + if (subresults.Length < 14) + throw new Exception("CalendarInfo recieved from the Browser is in icorrect format."); + // JS always has one result per locale, so even arrays are initialized with one element + this.sNativeName = string.IsNullOrEmpty(subresults[0]) ? ((CalendarId)calendarId).ToString() : subresults[0]; // this is EnglishName, not NativeName but it's the best we can do + this.saYearMonths = new string[] { subresults[1] }; + this.sMonthDay = subresults[2]; + this.saLongDates = new string[] { subresults[3] }; + this.saShortDates = new string[] { subresults[4] }; + this.saEraNames = new string[] { subresults[5] }; + this.saAbbrevEraNames = new string[] { subresults[6] }; + this.saDayNames = subresults[7].Split("||"); + this.saAbbrevDayNames = subresults[8].Split("||"); + this.saSuperShortDayNames = subresults[9].Split("||"); + this.saMonthNames = ResizeMonthsArray(subresults[10].Split("||")); + this.saAbbrevMonthNames = ResizeMonthsArray(subresults[11].Split("||")); + this.saMonthGenitiveNames = ResizeMonthsArray(subresults[12].Split("||")); + this.saAbbrevMonthGenitiveNames = ResizeMonthsArray(subresults[13].Split("||")); + return true; + } static string[] ResizeMonthsArray(string[] months) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.Icu.cs index 75440b2a23c458..bc532fcb26c059 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.Icu.cs @@ -198,10 +198,13 @@ private unsafe int IndexOfOrdinalIgnoreCaseHelper(ReadOnlySpan source, Rea #if TARGET_BROWSER if (GlobalizationMode.Hybrid) { - int result = Interop.JsGlobalization.IndexOf(m_name, b, target.Length, a, source.Length, options, fromBeginning, out int exception, out object ex_result); - if (exception != 0) - throw new Exception((string)ex_result); - return result; + ReadOnlySpan cultureNameSpan = m_name.AsSpan(); + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureNameSpan)) + { + nint exceptionPtr = Interop.JsGlobalization.IndexOf(pCultureName, cultureNameSpan.Length, b, target.Length, a, source.Length, options, fromBeginning, out int result); + Helper.MarshalAndThrowIfException(exceptionPtr); + return result; + } } #elif TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS if (GlobalizationMode.Hybrid) @@ -300,10 +303,13 @@ private unsafe int IndexOfOrdinalHelper(ReadOnlySpan source, ReadOnlySpan< #if TARGET_BROWSER if (GlobalizationMode.Hybrid) { - int result = Interop.JsGlobalization.IndexOf(m_name, b, target.Length, a, source.Length, options, fromBeginning, out int exception, out object ex_result); - if (exception != 0) - throw new Exception((string)ex_result); - return result; + ReadOnlySpan cultureNameSpan = m_name.AsSpan(); + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureNameSpan)) + { + nint exceptionPtr = Interop.JsGlobalization.IndexOf(pCultureName, cultureNameSpan.Length, b, target.Length, a, source.Length, options, fromBeginning, out int result); + Helper.MarshalAndThrowIfException(exceptionPtr); + return result; + } } #elif TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS if (GlobalizationMode.Hybrid) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.WebAssembly.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.WebAssembly.cs index 1d265dc70450a8..e8935a6d2439cc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.WebAssembly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.WebAssembly.cs @@ -47,86 +47,74 @@ private static void AssertIndexingSupported(CompareOptions options, string cultu private unsafe int JsCompareString(ReadOnlySpan string1, ReadOnlySpan string2, CompareOptions options) { AssertHybridOnWasm(options); - string cultureName = m_name; - AssertComparisonSupported(options, cultureName); + AssertComparisonSupported(options, m_name); - int cmpResult; + ReadOnlySpan cultureNameSpan = m_name.AsSpan(); fixed (char* pString1 = &MemoryMarshal.GetReference(string1)) fixed (char* pString2 = &MemoryMarshal.GetReference(string2)) + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureNameSpan)) { - cmpResult = Interop.JsGlobalization.CompareString(cultureName, pString1, string1.Length, pString2, string2.Length, options, out int exception, out object ex_result); - if (exception != 0) - throw new Exception((string)ex_result); + nint exceptionPtr = Interop.JsGlobalization.CompareString(pCultureName, cultureNameSpan.Length, pString1, string1.Length, pString2, string2.Length, options, out int cmpResult); + Helper.MarshalAndThrowIfException(exceptionPtr); + return cmpResult; } - - return cmpResult; } private unsafe bool JsStartsWith(ReadOnlySpan source, ReadOnlySpan prefix, CompareOptions options) { AssertHybridOnWasm(options); Debug.Assert(!prefix.IsEmpty); - string cultureName = m_name; - AssertIndexingSupported(options, cultureName); + AssertIndexingSupported(options, m_name); - bool result; + ReadOnlySpan cultureNameSpan = m_name.AsSpan(); fixed (char* pSource = &MemoryMarshal.GetReference(source)) fixed (char* pPrefix = &MemoryMarshal.GetReference(prefix)) + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureNameSpan)) { - result = Interop.JsGlobalization.StartsWith(cultureName, pSource, source.Length, pPrefix, prefix.Length, options, out int exception, out object ex_result); - if (exception != 0) - throw new Exception((string)ex_result); + nint exceptionPtr = Interop.JsGlobalization.StartsWith(pCultureName, cultureNameSpan.Length, pSource, source.Length, pPrefix, prefix.Length, options, out bool result); + Helper.MarshalAndThrowIfException(exceptionPtr); + return result; } - - - return result; } private unsafe bool JsEndsWith(ReadOnlySpan source, ReadOnlySpan prefix, CompareOptions options) { AssertHybridOnWasm(options); Debug.Assert(!prefix.IsEmpty); - string cultureName = m_name; - AssertIndexingSupported(options, cultureName); + AssertIndexingSupported(options, m_name); - bool result; + ReadOnlySpan cultureNameSpan = m_name.AsSpan(); fixed (char* pSource = &MemoryMarshal.GetReference(source)) fixed (char* pPrefix = &MemoryMarshal.GetReference(prefix)) + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureNameSpan)) { - result = Interop.JsGlobalization.EndsWith(cultureName, pSource, source.Length, pPrefix, prefix.Length, options, out int exception, out object ex_result); - if (exception != 0) - throw new Exception((string)ex_result); + nint exceptionPtr = Interop.JsGlobalization.EndsWith(pCultureName, cultureNameSpan.Length, pSource, source.Length, pPrefix, prefix.Length, options, out bool result); + Helper.MarshalAndThrowIfException(exceptionPtr); + return result; } - - return result; } private unsafe int JsIndexOfCore(ReadOnlySpan source, ReadOnlySpan target, CompareOptions options, int* matchLengthPtr, bool fromBeginning) { AssertHybridOnWasm(options); Debug.Assert(!target.IsEmpty); - string cultureName = m_name; - AssertIndexingSupported(options, cultureName); + AssertIndexingSupported(options, m_name); - int idx; if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options)) { - idx = (options & CompareOptions.IgnoreCase) != 0 ? + return (options & CompareOptions.IgnoreCase) != 0 ? IndexOfOrdinalIgnoreCaseHelper(source, target, options, matchLengthPtr, fromBeginning) : IndexOfOrdinalHelper(source, target, options, matchLengthPtr, fromBeginning); } - else + ReadOnlySpan cultureNameSpan = m_name.AsSpan(); + fixed (char* pSource = &MemoryMarshal.GetReference(source)) + fixed (char* pTarget = &MemoryMarshal.GetReference(target)) + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureNameSpan)) { - fixed (char* pSource = &MemoryMarshal.GetReference(source)) - fixed (char* pTarget = &MemoryMarshal.GetReference(target)) - { - idx = Interop.JsGlobalization.IndexOf(m_name, pTarget, target.Length, pSource, source.Length, options, fromBeginning, out int exception, out object ex_result); - if (exception != 0) - throw new Exception((string)ex_result); - } + nint exceptionPtr = Interop.JsGlobalization.IndexOf(pCultureName, cultureNameSpan.Length, pTarget, target.Length, pSource, source.Length, options, fromBeginning, out int idx); + Helper.MarshalAndThrowIfException(exceptionPtr); + return idx; } - - return idx; } // there are chars that are ignored by ICU hashing algorithm but not ignored by invariant hashing diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Browser.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Browser.cs index 8a8edadaf326d0..417bd563bf3574 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Browser.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Browser.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; namespace System.Globalization { @@ -41,17 +42,22 @@ private void JSInitLocaleInfo() private unsafe (string, string) JSGetLocaleInfo(string cultureName, string localeName) { - char* buffer = stackalloc char[LOCALE_INFO_BUFFER_LEN]; - int resultLength = Interop.JsGlobalization.GetLocaleInfo(cultureName, localeName, buffer, LOCALE_INFO_BUFFER_LEN, out int exception, out object exResult); - if (exception != 0) - throw new Exception((string)exResult); - string result = new string(buffer, 0, resultLength); - string[] subresults = result.Split("##"); - if (subresults.Length == 0) - throw new Exception("LocaleInfo recieved from the Browser is in incorrect format."); - if (subresults.Length == 1) - return (subresults[0], ""); // Neutral culture - return (subresults[0], subresults[1]); + ReadOnlySpan cultureNameSpan = cultureName.AsSpan(); + ReadOnlySpan localeNameSpan = localeName.AsSpan(); + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureNameSpan)) + fixed (char* pLocaleName = &MemoryMarshal.GetReference(localeNameSpan)) + { + char* buffer = stackalloc char[LOCALE_INFO_BUFFER_LEN]; + nint exceptionPtr = Interop.JsGlobalization.GetLocaleInfo(pCultureName, cultureNameSpan.Length, pLocaleName, localeNameSpan.Length, buffer, LOCALE_INFO_BUFFER_LEN, out int resultLength); + Helper.MarshalAndThrowIfException(exceptionPtr); + string result = new string(buffer, 0, resultLength); + string[] subresults = result.Split("##"); + if (subresults.Length == 0) + throw new Exception("LocaleInfo recieved from the Browser is in incorrect format."); + if (subresults.Length == 1) + return (subresults[0], ""); // Neutral culture + return (subresults[0], subresults[1]); + } } private string JSGetNativeDisplayName(string localeName, string cultureName) @@ -64,43 +70,82 @@ private string JSGetNativeDisplayName(string localeName, string cultureName) private static unsafe CultureData JSLoadCultureInfoFromBrowser(string localeName, CultureData culture) { - char* buffer = stackalloc char[CULTURE_INFO_BUFFER_LEN]; - int resultLength = Interop.JsGlobalization.GetCultureInfo(localeName, buffer, CULTURE_INFO_BUFFER_LEN, out int exception, out object exResult); - if (exception != 0) - throw new Exception((string)exResult); - string result = new string(buffer, 0, resultLength); - string[] subresults = result.Split("##"); - if (subresults.Length < 4) - throw new Exception("CultureInfo recieved from the Browser is in incorrect format."); - culture._sAM1159 = subresults[0]; - culture._sPM2359 = subresults[1]; - culture._saLongTimes = new string[] { subresults[2] }; - culture._saShortTimes = new string[] { subresults[3] }; + ReadOnlySpan localeNameSpan = localeName.AsSpan(); + fixed (char* pLocaleName = &MemoryMarshal.GetReference(localeNameSpan)) + { + char* buffer = stackalloc char[CULTURE_INFO_BUFFER_LEN]; + nint exceptionPtr = Interop.JsGlobalization.GetCultureInfo(pLocaleName, localeNameSpan.Length, buffer, CULTURE_INFO_BUFFER_LEN, out int resultLength); + Helper.MarshalAndThrowIfException(exceptionPtr); + string result = new string(buffer, 0, resultLength); + string[] subresults = result.Split("##"); + if (subresults.Length < 4) + throw new Exception("CultureInfo recieved from the Browser is in incorrect format."); + culture._sAM1159 = subresults[0]; + culture._sPM2359 = subresults[1]; + culture._saLongTimes = new string[] { subresults[2] }; + culture._saShortTimes = new string[] { subresults[3] }; + } return culture; } private static unsafe int GetFirstDayOfWeek(string localeName) { - int result = Interop.JsGlobalization.GetFirstDayOfWeek(localeName, out int exception, out object ex_result); - if (exception != 0) + ReadOnlySpan localeNameSpan = localeName.AsSpan(); + fixed (char* pLocaleName = &MemoryMarshal.GetReference(localeNameSpan)) { - // Failed, just use 0 - Debug.Fail($"[CultureData.GetFirstDayOfWeek()] failed with {ex_result}"); - return 0; + nint exceptionPtr = Interop.JsGlobalization.GetFirstDayOfWeek(pLocaleName, localeNameSpan.Length, out int result); + if (exceptionPtr != IntPtr.Zero) + { + int success = Helper.MarshalAndThrowIfException( + exceptionPtr, + failOnlyDebug: true, + failureMessage: $"[CultureData.GetFirstDayOfWeek()] failed with"); + // Failed, just use 0 + if (success == -1) + return 0; + } + return result; } - return result; } private static unsafe int GetFirstWeekOfYear(string localeName) { - int result = Interop.JsGlobalization.GetFirstWeekOfYear(localeName, out int exception, out object ex_result); - if (exception != 0) + ReadOnlySpan localeNameSpan = localeName.AsSpan(); + fixed (char* pLocaleName = &MemoryMarshal.GetReference(localeNameSpan)) + { + nint exceptionPtr = Interop.JsGlobalization.GetFirstWeekOfYear(pLocaleName, localeNameSpan.Length, out int result); + if (exceptionPtr != IntPtr.Zero) + { + int success = Helper.MarshalAndThrowIfException( + exceptionPtr, + failOnlyDebug: true, + failureMessage: $"[CultureData.GetFirstWeekOfYear()] failed with"); + // Failed, just use 0 + if (success == -1) + return 0; + } + return result; + } + } + } + + internal static class Helper + { + internal static int MarshalAndThrowIfException(nint exceptionPtr, bool failOnlyDebug = false, string failureMessage = "") + { + if (exceptionPtr != IntPtr.Zero) { - // Failed, just use 0 - Debug.Fail($"[CultureData.GetFirstDayOfWeek()] failed with {ex_result}"); - return 0; + string message = Marshal.PtrToStringUni(exceptionPtr)!; + Marshal.FreeHGlobal(exceptionPtr); + if (failOnlyDebug) + { + Debug.Fail($"{failureMessage} {message}"); + return -1; + } + throw new Exception(message); } - return result; + return 0; } + } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.WebAssembly.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.WebAssembly.cs index a2dd2a02c05f18..05e8cc3e1d0495 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.WebAssembly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.WebAssembly.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Runtime.InteropServices; namespace System.Globalization { @@ -13,18 +14,14 @@ internal unsafe void JsChangeCase(char* src, int srcLen, char* dstBuffer, int ds Debug.Assert(!GlobalizationMode.UseNls); Debug.Assert(GlobalizationMode.Hybrid); - int exception; - object ex_result; - if (HasEmptyCultureName) + ReadOnlySpan cultureName = _cultureName.AsSpan(); + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureName)) { - Interop.JsGlobalization.ChangeCaseInvariant(src, srcLen, dstBuffer, dstBufferCapacity, toUpper, out exception, out ex_result); + nint exceptionPtr = HasEmptyCultureName ? + Interop.JsGlobalization.ChangeCaseInvariant(src, srcLen, dstBuffer, dstBufferCapacity, toUpper) : + Interop.JsGlobalization.ChangeCase(pCultureName, cultureName.Length, src, srcLen, dstBuffer, dstBufferCapacity, toUpper); + Helper.MarshalAndThrowIfException(exceptionPtr); } - else - { - Interop.JsGlobalization.ChangeCase(_cultureName, src, srcLen, dstBuffer, dstBufferCapacity, toUpper, out exception, out ex_result); - } - if (exception != 0) - throw new Exception((string)ex_result); } } } diff --git a/src/mono/browser/runtime/corebindings.c b/src/mono/browser/runtime/corebindings.c index a6642a06d69fc8..39b25e5bff333d 100644 --- a/src/mono/browser/runtime/corebindings.c +++ b/src/mono/browser/runtime/corebindings.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -58,17 +59,17 @@ extern void mono_wasm_invoke_jsimport_ST (int function_handle, void *args); #endif /* DISABLE_THREADS */ // HybridGlobalization -extern void mono_wasm_change_case_invariant (const uint16_t* src, int32_t srcLength, uint16_t* dst, int32_t dstLength, mono_bool bToUpper, int *is_exception, MonoObject** ex_result); -extern void mono_wasm_change_case (MonoString **culture, const uint16_t* src, int32_t srcLength, uint16_t* dst, int32_t dstLength, mono_bool bToUpper, int *is_exception, MonoObject** ex_result); -extern int mono_wasm_compare_string (MonoString **culture, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, int *is_exception, MonoObject** ex_result); -extern mono_bool mono_wasm_starts_with (MonoString **culture, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, int *is_exception, MonoObject** ex_result); -extern mono_bool mono_wasm_ends_with (MonoString **culture, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, int *is_exception, MonoObject** ex_result); -extern int mono_wasm_index_of (MonoString **culture, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, mono_bool fromBeginning, int *is_exception, MonoObject** ex_result); -extern int mono_wasm_get_calendar_info (MonoString **culture, int32_t calendarId, const uint16_t* result, int32_t resultLength, int *is_exception, MonoObject** ex_result); -extern int mono_wasm_get_locale_info (MonoString **locale, MonoString **culture, const uint16_t* result, int32_t resultLength, int *is_exception, MonoObject** ex_result); -extern int mono_wasm_get_culture_info (MonoString **culture, const uint16_t* result, int32_t resultLength, int *is_exception, MonoObject** ex_result); -extern int mono_wasm_get_first_day_of_week (MonoString **culture, int *is_exception, MonoObject** ex_result); -extern int mono_wasm_get_first_week_of_year (MonoString **culture, int *is_exception, MonoObject** ex_result); +extern char16_t* mono_wasm_change_case_invariant (const uint16_t* src, int32_t srcLength, uint16_t* dst, int32_t dstLength, mono_bool bToUpper); +extern char16_t* mono_wasm_change_case (const uint16_t* culture, int32_t cultureLength, const uint16_t* src, int32_t srcLength, uint16_t* dst, int32_t dstLength, mono_bool bToUpper); +extern char16_t* mono_wasm_compare_string (const uint16_t* culture, int32_t cultureLength, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, int *resultPtr); +extern char16_t* mono_wasm_starts_with (const uint16_t* culture, int32_t cultureLength, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, mono_bool *resultPtr); +extern char16_t* mono_wasm_ends_with (const uint16_t* culture, int32_t cultureLength, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, mono_bool *resultPtr); +extern char16_t* mono_wasm_index_of (const uint16_t* culture, int32_t cultureLength, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, mono_bool fromBeginning, int *resultPtr); +extern char16_t* mono_wasm_get_calendar_info (const uint16_t* culture, int32_t cultureLength, int32_t calendarId, const uint16_t* result, int32_t resultMaxLength, int *resultLength); +extern char16_t* mono_wasm_get_culture_info (const uint16_t* culture, int32_t cultureLength, const uint16_t* result, int32_t resultMaxLength, int *resultLength); +extern char16_t* mono_wasm_get_locale_info (const uint16_t* locale, int32_t localeLength, const uint16_t* culture, int32_t cultureLength, const uint16_t* result, int32_t resultMaxLength, int *resultLength); +extern char16_t* mono_wasm_get_first_day_of_week (const uint16_t* culture, int32_t cultureLength, int *resultPtr); +extern char16_t* mono_wasm_get_first_week_of_year (const uint16_t* culture, int32_t cultureLength, int *resultPtr); void bindings_initialize_internals (void) { diff --git a/src/mono/browser/runtime/hybrid-globalization/calendar.ts b/src/mono/browser/runtime/hybrid-globalization/calendar.ts index d3944f514ce854..2d87d1c085cc04 100644 --- a/src/mono/browser/runtime/hybrid-globalization/calendar.ts +++ b/src/mono/browser/runtime/hybrid-globalization/calendar.ts @@ -2,23 +2,20 @@ // The .NET Foundation licenses this file to you under the MIT license. /* eslint-disable no-inner-declarations */ -import { mono_wasm_new_external_root } from "../roots"; -import { monoStringToString, stringToUTF16 } from "../strings"; -import { MonoObject, MonoObjectRef, MonoString, MonoStringRef } from "../types/internal"; -import { Int32Ptr } from "../types/emscripten"; -import { wrap_error_root, wrap_no_error_root } from "./helpers"; +import { stringToUTF16, stringToUTF16Ptr, utf16ToString } from "../strings"; +import { VoidPtrNull } from "../types/internal"; +import { Int32Ptr, VoidPtr } from "../types/emscripten"; import { INNER_SEPARATOR, OUTER_SEPARATOR, normalizeSpaces } from "./helpers"; +import { setI32 } from "../memory"; const MONTH_CODE = "MMMM"; const YEAR_CODE = "yyyy"; const DAY_CODE = "d"; // this function joins all calendar info with OUTER_SEPARATOR into one string and returns it back to managed code -export function mono_wasm_get_calendar_info (culture: MonoStringRef, calendarId: number, dst: number, dstLength: number, isException: Int32Ptr, exAddress: MonoObjectRef): number { - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(exAddress); +export function mono_wasm_get_calendar_info (culture: number, cultureLength: number, calendarId: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr): VoidPtr { try { - const cultureName = monoStringToString(cultureRoot); + const cultureName = utf16ToString(culture, (culture + 2 * cultureLength)); const locale = cultureName ? cultureName : undefined; const calendarInfo = { EnglishName: "", @@ -56,18 +53,14 @@ export function mono_wasm_get_calendar_info (culture: MonoStringRef, calendarId: calendarInfo.AbbreviatedEraNames = eraNames.abbreviatedEraNames; const result = Object.values(calendarInfo).join(OUTER_SEPARATOR); - if (result.length > dstLength) { - throw new Error(`Calendar info exceeds length of ${dstLength}.`); + if (result.length > dstMaxLength) { + throw new Error(`Calendar info exceeds length of ${dstMaxLength}.`); } stringToUTF16(dst, dst + 2 * result.length, result); - wrap_no_error_root(isException, exceptionRoot); - return result.length; + setI32(dstLength, result.length); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(isException, ex, exceptionRoot); - return -1; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + return stringToUTF16Ptr(ex.toString()); } } diff --git a/src/mono/browser/runtime/hybrid-globalization/change-case.ts b/src/mono/browser/runtime/hybrid-globalization/change-case.ts index 762eacc94c26bc..437aabb42bfcd2 100644 --- a/src/mono/browser/runtime/hybrid-globalization/change-case.ts +++ b/src/mono/browser/runtime/hybrid-globalization/change-case.ts @@ -1,16 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { mono_wasm_new_external_root } from "../roots"; -import { monoStringToString, utf16ToStringLoop, stringToUTF16 } from "../strings"; -import { MonoObject, MonoObjectRef, MonoString, MonoStringRef } from "../types/internal"; -import { Int32Ptr } from "../types/emscripten"; -import { wrap_error_root, wrap_no_error_root } from "./helpers"; +import { utf16ToStringLoop, stringToUTF16, stringToUTF16Ptr, utf16ToString } from "../strings"; +import { VoidPtrNull } from "../types/internal"; +import { VoidPtr } from "../types/emscripten"; import { localHeapViewU16, setU16_local } from "../memory"; import { isSurrogate } from "./helpers"; -export function mono_wasm_change_case_invariant (src: number, srcLength: number, dst: number, dstLength: number, toUpper: number, is_exception: Int32Ptr, ex_address: MonoObjectRef): void { - const exceptionRoot = mono_wasm_new_external_root(ex_address); +export function mono_wasm_change_case_invariant (src: number, srcLength: number, dst: number, dstLength: number, toUpper: number): VoidPtr { try { const input = utf16ToStringLoop(src, src + 2 * srcLength); const result = toUpper ? input.toUpperCase() : input.toLowerCase(); @@ -18,8 +15,7 @@ export function mono_wasm_change_case_invariant (src: number, srcLength: number, // originally we do not support this expansion if (result.length <= dstLength) { stringToUTF16(dst, dst + 2 * dstLength, result); - wrap_no_error_root(is_exception, exceptionRoot); - return; + return VoidPtrNull; } // workaround to maintain the ICU-like behavior @@ -59,19 +55,15 @@ export function mono_wasm_change_case_invariant (src: number, srcLength: number, } } } - wrap_no_error_root(is_exception, exceptionRoot); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(is_exception, ex, exceptionRoot); - } finally { - exceptionRoot.release(); + return stringToUTF16Ptr(ex.toString()); } } -export function mono_wasm_change_case (culture: MonoStringRef, src: number, srcLength: number, dst: number, dstLength: number, toUpper: number, is_exception: Int32Ptr, ex_address: MonoObjectRef): void { - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(ex_address); +export function mono_wasm_change_case (culture: number, cultureLength: number, src: number, srcLength: number, dst: number, dstLength: number, toUpper: number): VoidPtr { try { - const cultureName = monoStringToString(cultureRoot); + const cultureName = utf16ToString(culture, (culture + 2 * cultureLength)); if (!cultureName) throw new Error("Cannot change case, the culture name is null."); const input = utf16ToStringLoop(src, src + 2 * srcLength); @@ -79,8 +71,7 @@ export function mono_wasm_change_case (culture: MonoStringRef, src: number, srcL if (result.length <= input.length) { stringToUTF16(dst, dst + 2 * dstLength, result); - wrap_no_error_root(is_exception, exceptionRoot); - return; + return VoidPtrNull; } // workaround to maintain the ICU-like behavior const heapI16 = localHeapViewU16(); @@ -119,12 +110,9 @@ export function mono_wasm_change_case (culture: MonoStringRef, src: number, srcL } } } - wrap_no_error_root(is_exception, exceptionRoot); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(is_exception, ex, exceptionRoot); - } finally { - cultureRoot.release(); - exceptionRoot.release(); + return stringToUTF16Ptr(ex.toString()); } } diff --git a/src/mono/browser/runtime/hybrid-globalization/collations.ts b/src/mono/browser/runtime/hybrid-globalization/collations.ts index 523f63307e278c..b329b39b15d0e1 100644 --- a/src/mono/browser/runtime/hybrid-globalization/collations.ts +++ b/src/mono/browser/runtime/hybrid-globalization/collations.ts @@ -1,113 +1,106 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { mono_wasm_new_external_root } from "../roots"; -import { monoStringToString, utf16ToString } from "../strings"; -import { MonoObject, MonoObjectRef, MonoString, MonoStringRef } from "../types/internal"; -import { Int32Ptr } from "../types/emscripten"; -import { wrap_error_root, wrap_no_error_root } from "./helpers"; +import { stringToUTF16Ptr, utf16ToString } from "../strings"; +import { VoidPtrNull } from "../types/internal"; +import { Int32Ptr, VoidPtr } from "../types/emscripten"; import { GraphemeSegmenter } from "./grapheme-segmenter"; +import { setI32 } from "../memory"; const COMPARISON_ERROR = -2; const INDEXING_ERROR = -1; let graphemeSegmenterCached: GraphemeSegmenter | null; -export function mono_wasm_compare_string (culture: MonoStringRef, str1: number, str1Length: number, str2: number, str2Length: number, options: number, is_exception: Int32Ptr, ex_address: MonoObjectRef): number { - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(ex_address); +export function mono_wasm_compare_string (culture: number, cultureLength: number, str1: number, str1Length: number, str2: number, str2Length: number, options: number, resultPtr: Int32Ptr): VoidPtr { try { - const cultureName = monoStringToString(cultureRoot); + const cultureName = utf16ToString(culture, (culture + 2 * cultureLength)); const string1 = utf16ToString(str1, (str1 + 2 * str1Length)); const string2 = utf16ToString(str2, (str2 + 2 * str2Length)); const casePicker = (options & 0x1f); const locale = cultureName ? cultureName : undefined; - wrap_no_error_root(is_exception, exceptionRoot); - return compareStrings(string1, string2, locale, casePicker); + const result = compareStrings(string1, string2, locale, casePicker); + setI32(resultPtr, result); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(is_exception, ex, exceptionRoot); - return COMPARISON_ERROR; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + setI32(resultPtr, COMPARISON_ERROR); + return stringToUTF16Ptr(ex.toString()); } } -export function mono_wasm_starts_with (culture: MonoStringRef, str1: number, str1Length: number, str2: number, str2Length: number, options: number, is_exception: Int32Ptr, ex_address: MonoObjectRef): number { - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(ex_address); +export function mono_wasm_starts_with (culture: number, cultureLength: number, str1: number, str1Length: number, str2: number, str2Length: number, options: number, resultPtr: Int32Ptr): VoidPtr { try { - const cultureName = monoStringToString(cultureRoot); + const cultureName = utf16ToString(culture, (culture + 2 * cultureLength)); const prefix = decodeToCleanString(str2, str2Length); // no need to look for an empty string - if (prefix.length == 0) - return 1; // true + if (prefix.length == 0) { + setI32(resultPtr, 1); // true + return VoidPtrNull; + } const source = decodeToCleanString(str1, str1Length); - if (source.length < prefix.length) - return 0; //false + if (source.length < prefix.length) { + setI32(resultPtr, 0); // false + return VoidPtrNull; + } const sourceOfPrefixLength = source.slice(0, prefix.length); const casePicker = (options & 0x1f); const locale = cultureName ? cultureName : undefined; - const result = compareStrings(sourceOfPrefixLength, prefix, locale, casePicker); - wrap_no_error_root(is_exception, exceptionRoot); - return result === 0 ? 1 : 0; // equals ? true : false + const cmpResult = compareStrings(sourceOfPrefixLength, prefix, locale, casePicker); + const result = cmpResult === 0 ? 1 : 0; // equals ? true : false + setI32(resultPtr, result); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(is_exception, ex, exceptionRoot); - return INDEXING_ERROR; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + setI32(resultPtr, INDEXING_ERROR); + return stringToUTF16Ptr(ex.toString()); } } -export function mono_wasm_ends_with (culture: MonoStringRef, str1: number, str1Length: number, str2: number, str2Length: number, options: number, is_exception: Int32Ptr, ex_address: MonoObjectRef): number { - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(ex_address); +export function mono_wasm_ends_with (culture: number, cultureLength: number, str1: number, str1Length: number, str2: number, str2Length: number, options: number, resultPtr: Int32Ptr): VoidPtr { try { - const cultureName = monoStringToString(cultureRoot); + const cultureName = utf16ToString(culture, (culture + 2 * cultureLength)); const suffix = decodeToCleanString(str2, str2Length); - if (suffix.length == 0) - return 1; // true + if (suffix.length == 0) { + setI32(resultPtr, 1); // true + return VoidPtrNull; + } const source = decodeToCleanString(str1, str1Length); const diff = source.length - suffix.length; - if (diff < 0) - return 0; //false + if (diff < 0) { + setI32(resultPtr, 0); // false + return VoidPtrNull; + } const sourceOfSuffixLength = source.slice(diff, source.length); const casePicker = (options & 0x1f); const locale = cultureName ? cultureName : undefined; - const result = compareStrings(sourceOfSuffixLength, suffix, locale, casePicker); - wrap_no_error_root(is_exception, exceptionRoot); - return result === 0 ? 1 : 0; // equals ? true : false + const cmpResult = compareStrings(sourceOfSuffixLength, suffix, locale, casePicker); + const result = cmpResult === 0 ? 1 : 0; // equals ? true : false + setI32(resultPtr, result); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(is_exception, ex, exceptionRoot); - return INDEXING_ERROR; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + setI32(resultPtr, INDEXING_ERROR); + return stringToUTF16Ptr(ex.toString()); } } -export function mono_wasm_index_of (culture: MonoStringRef, needlePtr: number, needleLength: number, srcPtr: number, srcLength: number, options: number, fromBeginning: number, is_exception: Int32Ptr, ex_address: MonoObjectRef): number { - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(ex_address); +export function mono_wasm_index_of (culture: number, cultureLength: number, needlePtr: number, needleLength: number, srcPtr: number, srcLength: number, options: number, fromBeginning: number, resultPtr: Int32Ptr): VoidPtr { try { const needle = utf16ToString(needlePtr, (needlePtr + 2 * needleLength)); // no need to look for an empty string if (cleanString(needle).length == 0) { - wrap_no_error_root(is_exception, exceptionRoot); - return fromBeginning ? 0 : srcLength; + setI32(resultPtr, fromBeginning ? 0 : srcLength); + return VoidPtrNull; } const source = utf16ToString(srcPtr, (srcPtr + 2 * srcLength)); // no need to look in an empty string if (cleanString(source).length == 0) { - wrap_no_error_root(is_exception, exceptionRoot); - return fromBeginning ? 0 : srcLength; + setI32(resultPtr, fromBeginning ? 0 : srcLength); + return VoidPtrNull; } - const cultureName = monoStringToString(cultureRoot); + const cultureName = utf16ToString(culture, (culture + 2 * cultureLength)); const locale = cultureName ? cultureName : undefined; const casePicker = (options & 0x1f); let result = -1; @@ -148,14 +141,11 @@ export function mono_wasm_index_of (culture: MonoStringRef, needlePtr: number, n break; } } - wrap_no_error_root(is_exception, exceptionRoot); - return result; + setI32(resultPtr, result); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(is_exception, ex, exceptionRoot); - return INDEXING_ERROR; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + setI32(resultPtr, INDEXING_ERROR); + return stringToUTF16Ptr(ex.toString()); } function checkMatchFound (str1: string, str2: string, locale: string | undefined, casePicker: number): boolean { diff --git a/src/mono/browser/runtime/hybrid-globalization/culture-info.ts b/src/mono/browser/runtime/hybrid-globalization/culture-info.ts index 03bebd9ec65ee2..70b36296407bbb 100644 --- a/src/mono/browser/runtime/hybrid-globalization/culture-info.ts +++ b/src/mono/browser/runtime/hybrid-globalization/culture-info.ts @@ -1,18 +1,15 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { wrap_error_root, wrap_no_error_root } from "./helpers"; -import { mono_wasm_new_external_root } from "../roots"; -import { monoStringToString, stringToUTF16 } from "../strings"; -import { Int32Ptr } from "../types/emscripten"; -import { MonoObject, MonoObjectRef, MonoString, MonoStringRef } from "../types/internal"; +import { setI32 } from "../memory"; +import { stringToUTF16, stringToUTF16Ptr, utf16ToString } from "../strings"; +import { Int32Ptr, VoidPtr } from "../types/emscripten"; +import { VoidPtrNull } from "../types/internal"; import { OUTER_SEPARATOR, normalizeLocale, normalizeSpaces } from "./helpers"; -export function mono_wasm_get_culture_info (culture: MonoStringRef, dst: number, dstLength: number, isException: Int32Ptr, exAddress: MonoObjectRef): number { - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(exAddress); +export function mono_wasm_get_culture_info (culture: number, cultureLength: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr): VoidPtr { try { - const cultureName = monoStringToString(cultureRoot); + const cultureName = utf16ToString(culture, (culture + 2 * cultureLength)); const cultureInfo = { AmDesignator: "", PmDesignator: "", @@ -26,18 +23,15 @@ export function mono_wasm_get_culture_info (culture: MonoStringRef, dst: number, cultureInfo.LongTimePattern = getLongTimePattern(canonicalLocale, designators); cultureInfo.ShortTimePattern = getShortTimePattern(cultureInfo.LongTimePattern); const result = Object.values(cultureInfo).join(OUTER_SEPARATOR); - if (result.length > dstLength) { - throw new Error(`Culture info exceeds length of ${dstLength}.`); + if (result.length > dstMaxLength) { + throw new Error(`Culture info exceeds length of ${dstMaxLength}.`); } stringToUTF16(dst, dst + 2 * result.length, result); - wrap_no_error_root(isException, exceptionRoot); - return result.length; + setI32(dstLength, result.length); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(isException, ex, exceptionRoot); - return -1; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + setI32(dstLength, -1); + return stringToUTF16Ptr(ex.toString()); } } diff --git a/src/mono/browser/runtime/hybrid-globalization/helpers.ts b/src/mono/browser/runtime/hybrid-globalization/helpers.ts index 74134c4ca3cc1d..0cd2294447226f 100644 --- a/src/mono/browser/runtime/hybrid-globalization/helpers.ts +++ b/src/mono/browser/runtime/hybrid-globalization/helpers.ts @@ -1,12 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { normalize_exception } from "../invoke-js"; -import { receiveWorkerHeapViews, setI32_unchecked } from "../memory"; -import { stringToMonoStringRoot } from "../strings"; -import { Int32Ptr } from "../types/emscripten"; -import { MonoObject, WasmRoot } from "../types/internal"; - const SURROGATE_HIGHER_START = "\uD800"; const SURROGATE_HIGHER_END = "\uDBFF"; const SURROGATE_LOWER_START = "\uDC00"; @@ -48,29 +42,3 @@ export function isSurrogate (str: string, startIdx: number): boolean { SURROGATE_LOWER_START <= str[startIdx + 1] && str[startIdx + 1] <= SURROGATE_LOWER_END; } - -function _wrap_error_flag (is_exception: Int32Ptr | null, ex: any): string { - const res = normalize_exception(ex); - if (is_exception) { - receiveWorkerHeapViews(); - setI32_unchecked(is_exception, 1); - } - return res; -} - -export function wrap_error_root (is_exception: Int32Ptr | null, ex: any, result: WasmRoot): void { - const res = _wrap_error_flag(is_exception, ex); - stringToMonoStringRoot(res, result); -} - -// TODO replace it with replace it with UTF16 char*, no GC root needed -// https://github.com/dotnet/runtime/issues/98365 -export function wrap_no_error_root (is_exception: Int32Ptr | null, result?: WasmRoot): void { - if (is_exception) { - receiveWorkerHeapViews(); - setI32_unchecked(is_exception, 0); - } - if (result) { - result.clear(); - } -} diff --git a/src/mono/browser/runtime/hybrid-globalization/locales.ts b/src/mono/browser/runtime/hybrid-globalization/locales.ts index 252dfe1badf9e2..da6a478d1e3931 100644 --- a/src/mono/browser/runtime/hybrid-globalization/locales.ts +++ b/src/mono/browser/runtime/hybrid-globalization/locales.ts @@ -1,27 +1,23 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { wrap_error_root, wrap_no_error_root } from "./helpers"; -import { mono_wasm_new_external_root } from "../roots"; -import { monoStringToString, stringToUTF16 } from "../strings"; -import { Int32Ptr } from "../types/emscripten"; -import { MonoObject, MonoObjectRef, MonoString, MonoStringRef } from "../types/internal"; +import { setI32 } from "../memory"; +import { stringToUTF16, stringToUTF16Ptr, utf16ToString } from "../strings"; +import { Int32Ptr, VoidPtr } from "../types/emscripten"; +import { VoidPtrNull } from "../types/internal"; import { OUTER_SEPARATOR, normalizeLocale } from "./helpers"; -export function mono_wasm_get_locale_info (culture: MonoStringRef, locale: MonoStringRef, dst: number, dstLength: number, isException: Int32Ptr, exAddress: MonoObjectRef): number { - const localeRoot = mono_wasm_new_external_root(locale), - cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(exAddress); +export function mono_wasm_get_locale_info (culture: number, cultureLength: number, locale: number, localeLength: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr): VoidPtr { try { - const localeNameOriginal = monoStringToString(localeRoot); + const localeNameOriginal = utf16ToString(locale, (locale + 2 * localeLength)); const localeName = normalizeLocale(localeNameOriginal); if (!localeName && localeNameOriginal) { // handle non-standard or malformed locales by forwarding the locale code stringToUTF16(dst, dst + 2 * localeNameOriginal.length, localeNameOriginal); - wrap_no_error_root(isException, exceptionRoot); - return localeNameOriginal.length; + setI32(dstLength, localeNameOriginal.length); + return VoidPtrNull; } - const cultureNameOriginal = monoStringToString(cultureRoot); + const cultureNameOriginal = utf16ToString(culture, (culture + 2 * cultureLength)); const cultureName = normalizeLocale(cultureNameOriginal); if (!localeName || !cultureName) @@ -49,8 +45,8 @@ export function mono_wasm_get_locale_info (culture: MonoStringRef, locale: MonoS if (error instanceof RangeError && error.message === "invalid_argument" && localeNameOriginal) { // handle non-standard or malformed locales by forwarding the locale code, e.g. "xx-u-xx" stringToUTF16(dst, dst + 2 * localeNameOriginal.length, localeNameOriginal); - wrap_no_error_root(isException, exceptionRoot); - return localeNameOriginal.length; + setI32(dstLength, localeNameOriginal.length); + return VoidPtrNull; } throw error; } @@ -67,54 +63,41 @@ export function mono_wasm_get_locale_info (culture: MonoStringRef, locale: MonoS if (!result) throw new Error(`Locale info for locale=${localeName} is null or empty.`); - if (result.length > dstLength) - throw new Error(`Locale info for locale=${localeName} exceeds length of ${dstLength}.`); + if (result.length > dstMaxLength) + throw new Error(`Locale info for locale=${localeName} exceeds length of ${dstMaxLength}.`); stringToUTF16(dst, dst + 2 * result.length, result); - wrap_no_error_root(isException, exceptionRoot); - return result.length; + setI32(dstLength, result.length); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(isException, ex, exceptionRoot); - return -1; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + setI32(dstLength, -1); + return stringToUTF16Ptr(ex.toString()); } } -export function mono_wasm_get_first_day_of_week (culture: MonoStringRef, isException: Int32Ptr, exAddress: MonoObjectRef): number { - - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(exAddress); +export function mono_wasm_get_first_day_of_week (culture: number, cultureLength: number, resultPtr: Int32Ptr): VoidPtr { try { - const cultureName = monoStringToString(cultureRoot); + const cultureName = utf16ToString(culture, (culture + 2 * cultureLength)); const canonicalLocale = normalizeLocale(cultureName); - wrap_no_error_root(isException, exceptionRoot); - return getFirstDayOfWeek(canonicalLocale); + const result = getFirstDayOfWeek(canonicalLocale); + setI32(resultPtr, result); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(isException, ex, exceptionRoot); - return -1; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + setI32(resultPtr, -1); + return stringToUTF16Ptr(ex.toString()); } } -export function mono_wasm_get_first_week_of_year (culture: MonoStringRef, isException: Int32Ptr, exAddress: MonoObjectRef): number { - - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(exAddress); +export function mono_wasm_get_first_week_of_year (culture: number, cultureLength: number, resultPtr: Int32Ptr): VoidPtr { try { - const cultureName = monoStringToString(cultureRoot); + const cultureName = utf16ToString(culture, (culture + 2 * cultureLength)); const canonicalLocale = normalizeLocale(cultureName); - wrap_no_error_root(isException, exceptionRoot); - return getFirstWeekOfYear(canonicalLocale); + const result = getFirstWeekOfYear(canonicalLocale); + setI32(resultPtr, result); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(isException, ex, exceptionRoot); - return -1; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + setI32(resultPtr, -1); + return stringToUTF16Ptr(ex.toString()); } } From 7d91bf56ec48329ac3ed65c35fdfa9b6fd81c2d3 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 23 Apr 2024 12:06:53 -0400 Subject: [PATCH 069/248] Fix incorrect suffix search for alternation with RegexOptions.RightToLeft (#101408) * Fix incorrect suffix search for alternation with RegexOptions.RightToLeft Our limited RegexOptions.RightToLeft support for prefix optimizations is mishandling alternations. For RTL, this actually needs to create a suffix, but for alternations, we were actually creating a prefix. As this option is rarely used and it's not worth significant investment in optimizing, the fix is just to disable the handling of alternations for RTL, as the support has been broken since it was introduced in .NET 7. * Fix new tests * Avoid annoying skip message --- .../RegularExpressions/RegexPrefixAnalyzer.cs | 2 +- .../Regex.CompileToAssembly.Tests.cs | 93 +++++++++---------- .../FunctionalTests/Regex.Match.Tests.cs | 5 + .../UnitTests/RegexFindOptimizationsTests.cs | 2 +- 4 files changed, 53 insertions(+), 49 deletions(-) diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs index 926a28339162f6..b46af7b1b9d066 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs @@ -359,7 +359,7 @@ static bool Process(RegexNode node, ref ValueStringBuilder vsb) } // Alternation: find a string that's a shared prefix of all branches - case RegexNodeKind.Alternate: + case RegexNodeKind.Alternate when !rtl: // for RTL we'd need to be matching the suffixes of the alternation cases { int childCount = node.ChildCount(); diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.CompileToAssembly.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.CompileToAssembly.Tests.cs index a669f65bd023ed..c1d17ffa6a3ae5 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.CompileToAssembly.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.CompileToAssembly.Tests.cs @@ -14,63 +14,62 @@ namespace System.Text.RegularExpressions.Tests [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] public class RegexCompileToAssemblyTests : FileCleanupTestBase { - public static bool IsDebug => typeof(Regex).Assembly.GetCustomAttributes(false).OfType().Any(da => da.IsJITTrackingEnabled); - public static bool IsRelease => !IsDebug; - public static bool IsDebugAndRemoteExecutorSupported => IsDebug && RemoteExecutor.IsSupported; - - [ConditionalFact(nameof(IsRelease))] - public void CompileToAssembly_PNSE() + [Fact] + public void CompileToAssembly_SimpleTest() { - Assert.Throws(() => Regex.CompileToAssembly(null, null)); - Assert.Throws(() => Regex.CompileToAssembly(null, null, null)); - Assert.Throws(() => Regex.CompileToAssembly(null, null, null, null)); + bool isDebug = typeof(Regex).Assembly.GetCustomAttributes(false).OfType().Any(da => da.IsJITTrackingEnabled); - Assert.Throws(() => Regex.CompileToAssembly( - [new RegexCompilationInfo("abcd", RegexOptions.None, "abcd", "SomeNamespace", true)], - new AssemblyName("abcd"))); + if (!isDebug) + { + Assert.Throws(() => Regex.CompileToAssembly(null, null)); + Assert.Throws(() => Regex.CompileToAssembly(null, null, null)); + Assert.Throws(() => Regex.CompileToAssembly(null, null, null, null)); - Assert.Throws(() => Regex.CompileToAssembly( - [new RegexCompilationInfo("abcd", RegexOptions.None, "abcd", "SomeNamespace", true)], - new AssemblyName("abcd"), - [new CustomAttributeBuilder(typeof(AssemblyCompanyAttribute).GetConstructor([typeof(string)]), new[] { "TestCompany" })])); + Assert.Throws(() => Regex.CompileToAssembly( + [new RegexCompilationInfo("abcd", RegexOptions.None, "abcd", "SomeNamespace", true)], + new AssemblyName("abcd"))); - Assert.Throws(() => Regex.CompileToAssembly( - [new RegexCompilationInfo("abcd", RegexOptions.None, "abcd", "SomeNamespace", true)], - new AssemblyName("abcd"), - [new CustomAttributeBuilder(typeof(AssemblyCompanyAttribute).GetConstructor([typeof(string)]), new[] { "TestCompany" })], - "resourceFile")); - } + Assert.Throws(() => Regex.CompileToAssembly( + [new RegexCompilationInfo("abcd", RegexOptions.None, "abcd", "SomeNamespace", true)], + new AssemblyName("abcd"), + [new CustomAttributeBuilder(typeof(AssemblyCompanyAttribute).GetConstructor([typeof(string)]), new[] { "TestCompany" })])); - [ConditionalFact(nameof(IsDebugAndRemoteExecutorSupported))] - public void CompileToAssembly_SimpleUseInDebug() - { - RemoteExecutor.Invoke(() => + Assert.Throws(() => Regex.CompileToAssembly( + [new RegexCompilationInfo("abcd", RegexOptions.None, "abcd", "SomeNamespace", true)], + new AssemblyName("abcd"), + [new CustomAttributeBuilder(typeof(AssemblyCompanyAttribute).GetConstructor([typeof(string)]), new[] { "TestCompany" })], + "resourceFile")); + } + else if (RemoteExecutor.IsSupported) { - (RegexCompilationInfo rci, string validInput, string invalidInput)[] regexes = - [ - (new RegexCompilationInfo("abcd", RegexOptions.None, "Type1", "Namespace1", ispublic: true), "123abcd123", "123abed123"), - (new RegexCompilationInfo("(a|b|cde)+", RegexOptions.None, "Type2", "Namespace2.Sub", ispublic: true), "abcde", "cd"), - ]; + RemoteExecutor.Invoke(() => + { + (RegexCompilationInfo rci, string validInput, string invalidInput)[] regexes = + [ + (new RegexCompilationInfo("abcd", RegexOptions.None, "Type1", "Namespace1", ispublic: true), "123abcd123", "123abed123"), + (new RegexCompilationInfo("(a|b|cde)+", RegexOptions.None, "Type2", "Namespace2.Sub", ispublic: true), "abcde", "cd"), + ]; - string assemblyName = Path.GetRandomFileName(); + string assemblyName = Path.GetRandomFileName(); - string cwd = Environment.CurrentDirectory; - Environment.CurrentDirectory = TestDirectory; - try - { - Regex.CompileToAssembly(regexes.Select(r => r.rci).ToArray(), new AssemblyName(assemblyName)); - } - finally - { - Environment.CurrentDirectory = cwd; - } + string cwd = Environment.CurrentDirectory; + Environment.CurrentDirectory = TestDirectory; + try + { + Regex.CompileToAssembly(regexes.Select(r => r.rci).ToArray(), new AssemblyName(assemblyName)); + } + finally + { + Environment.CurrentDirectory = cwd; + } - string assemblyPath = Path.Combine(TestDirectory, assemblyName + ".dll"); - Assert.True(File.Exists(assemblyPath)); + string assemblyPath = Path.Combine(TestDirectory, assemblyName + ".dll"); + Assert.True(File.Exists(assemblyPath)); - // Uncomment to save the assembly to the desktop for inspection: - // File.Copy(assemblyPath, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), Path.GetFileName(assemblyPath))); - }).Dispose(); + // Uncomment to save the assembly to the desktop for inspection: + // File.Copy(assemblyPath, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), Path.GetFileName(assemblyPath))); + }).Dispose(); + } } } } diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs index 1b06272fba64ab..d58290174c222f 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs @@ -698,6 +698,11 @@ public static IEnumerable Match_MemberData() yield return (@"(...)(?(1)\w*|\s*)[a1 ]", "zabcaaaaaaa", RegexOptions.RightToLeft, 0, 11, true, "aaaa"); yield return (@"(...)(?(1)\w*|\s*)[a1 ]", "---- ", RegexOptions.RightToLeft, 0, 11, true, "--- "); yield return (@"(aaa)(?(1)aaa|b?)*", "aaaaaa", RegexOptions.None, 0, 6, true, "aaaaaa"); + + yield return (@"AAB|AAC", "AABAACD", RegexOptions.RightToLeft, 0, 6, true, "AAC"); + yield return (@"AAB|AA\d", "AABAACD", RegexOptions.RightToLeft, 0, 6, true, "AAB"); + yield return (@"(AB){3,}", "1234ABABABAB5678", RegexOptions.RightToLeft, 0, 16, true, "ABABABAB"); + yield return (@"(AB){1,3}", "1234ABABABAB5678", RegexOptions.RightToLeft, 0, 16, true, "ABABAB"); } // Character Class Subtraction diff --git a/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexFindOptimizationsTests.cs b/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexFindOptimizationsTests.cs index c962bc072b6fd7..4c0b02b266142e 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexFindOptimizationsTests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexFindOptimizationsTests.cs @@ -88,7 +88,6 @@ public void TrailingAnchor(string pattern, int options, int expectedMode, int ex [InlineData(@"(ab){2,4}(de){4,}", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "abab")] [InlineData(@"(ab){2,4}(de){4,}", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "de")] [InlineData(@"ab|(abc)|(abcd)", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "ab")] - [InlineData(@"ab|(abc)|(abcd)", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "ab")] [InlineData(@"ab(?=cd)", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "ab")] [InlineData(@"ab(?=cd)", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "ab")] [InlineData(@"\bab(?=\w)(?!=\d)c\b", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "abc")] @@ -110,6 +109,7 @@ public void LeadingPrefix(string pattern, int options, int expectedMode, string [InlineData(@"a", (int)RegexOptions.IgnoreCase | (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "Aa")] [InlineData(@"ab|cd|ef|gh", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "bdfh")] [InlineData(@"\bab(?=\w)(?!=\d)c\b", (int)(RegexOptions.IgnoreCase | RegexOptions.RightToLeft), (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "Cc")] + [InlineData(@"ab|(abc)|(abcd)", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "bcd")] public void LeadingSet(string pattern, int options, int expectedMode, string expectedChars) { RegexFindOptimizations opts = ComputeOptimizations(pattern, (RegexOptions)options); From 40bc2d88b6606324f5774cc972d480a1d26084f8 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan <96171496+mkhamoyan@users.noreply.github.com> Date: Tue, 23 Apr 2024 18:35:28 +0200 Subject: [PATCH 070/248] [mono][wasm] Fix function signature mismatch in m2n invoke (#101106) Fix signature mismatch --- src/mono/browser/runtime/runtime.c | 10 ++---- src/mono/mono/metadata/native-library.c | 29 +++++++++++++++++ src/mono/mono/metadata/native-library.h | 3 ++ src/mono/mono/mini/aot-compiler.c | 18 +++++++---- src/mono/mono/mini/mini-llvm.c | 11 +++++-- .../wasm/Wasm.Build.Tests/Common/TestUtils.cs | 4 ++- .../PInvokeTableGeneratorTests.cs | 26 +++++++++++++++ .../UnmanagedCallback.cs | 28 ++++++++++++++++ src/mono/wasm/testassets/native-libs/local.c | 10 ++++++ src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 21 +----------- src/tasks/Common/Utils.cs | 32 +++++++++++++++++++ .../ManagedToNativeGenerator.cs | 27 +--------------- .../WasmAppBuilder/PInvokeTableGenerator.cs | 2 +- 13 files changed, 157 insertions(+), 64 deletions(-) create mode 100644 src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/UnmanagedCallback.cs create mode 100644 src/mono/wasm/testassets/native-libs/local.c diff --git a/src/mono/browser/runtime/runtime.c b/src/mono/browser/runtime/runtime.c index 2132dd9906d597..8ddcdbce138637 100644 --- a/src/mono/browser/runtime/runtime.c +++ b/src/mono/browser/runtime/runtime.c @@ -65,6 +65,7 @@ int mono_wasm_enable_gc = 1; /* Missing from public headers */ +char *mono_fixup_symbol_name (char *key); void mono_icall_table_init (void); void mono_wasm_enable_debugging (int); void mono_ee_interp_init (const char *opts); @@ -213,13 +214,8 @@ get_native_to_interp (MonoMethod *method, void *extra_arg) assert (strlen (name) < 100); snprintf (key, sizeof(key), "%s_%s_%s", name, class_name, method_name); - len = strlen (key); - for (int i = 0; i < len; ++i) { - if (key [i] == '.') - key [i] = '_'; - } - - addr = wasm_dl_get_native_to_interp (key, extra_arg); + char* fixedName = mono_fixup_symbol_name(key); + addr = wasm_dl_get_native_to_interp (fixedName, extra_arg); MONO_EXIT_GC_UNSAFE; return addr; } diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c index f26ab2e9152afa..142c467fdd0af5 100644 --- a/src/mono/mono/metadata/native-library.c +++ b/src/mono/mono/metadata/native-library.c @@ -1222,3 +1222,32 @@ mono_loader_install_pinvoke_override (PInvokeOverrideFn override_fn) { pinvoke_override = override_fn; } + +// Keep synced with FixupSymbolName from src/tasks/Common/Utils.cs +char* mono_fixup_symbol_name (char *key) { + char* fixedName = malloc(256); + int sb_index = 0; + int len = (int)strlen (key); + + for (int i = 0; i < len; ++i) { + unsigned char b = key[i]; + if ((b >= '0' && b <= '9') || + (b >= 'a' && b <= 'z') || + (b >= 'A' && b <= 'Z') || + (b == '_')) { + fixedName[sb_index++] = b; + } + else if (b == '.' || b == '-' || b == '+' || b == '<' || b == '>') { + fixedName[sb_index++] = '_'; + } + else { + // Append the hexadecimal representation of b between underscores + sprintf(&fixedName[sb_index], "_%X_", b); + sb_index += 4; // Move the index after the appended hexadecimal characters + } + } + + // Null-terminate the fixedName string + fixedName[sb_index] = '\0'; + return fixedName; +} diff --git a/src/mono/mono/metadata/native-library.h b/src/mono/mono/metadata/native-library.h index 9108a86ae75460..8a0b0e20b9ec6d 100644 --- a/src/mono/mono/metadata/native-library.h +++ b/src/mono/mono/metadata/native-library.h @@ -35,4 +35,7 @@ mono_lookup_pinvoke_qcall_internal (const char *name); void mono_loader_install_pinvoke_override (PInvokeOverrideFn override_fn); +char * +mono_fixup_symbol_name (char *key); + #endif diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index fdd8511f478744..9aa0760231dd19 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -12407,7 +12408,6 @@ emit_file_info (MonoAotCompile *acfg) if (acfg->aot_opts.static_link) { char symbol [MAX_SYMBOL_SIZE]; - char *p; /* * Emit a global symbol which can be passed by an embedding app to @@ -12415,14 +12415,17 @@ emit_file_info (MonoAotCompile *acfg) * structure. */ sprintf (symbol, "%smono_aot_module_%s_info", acfg->user_symbol_prefix, acfg->image->assembly->aname.name); - +#ifdef TARGET_WASM + acfg->static_linking_symbol = g_strdup (mono_fixup_symbol_name(symbol)); +#else /* Get rid of characters which cannot occur in symbols */ - p = symbol; + char *p = symbol; for (p = symbol; *p; ++p) { if (!(isalnum (*p) || *p == '_')) *p = '_'; } acfg->static_linking_symbol = g_strdup (symbol); +#endif } if (acfg->llvm) @@ -14860,7 +14863,6 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options) { MonoImage *image = ass->image; MonoAotCompile *acfg; - char *p; int res; TV_DECLARE (atv); TV_DECLARE (btv); @@ -15120,13 +15122,17 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options) acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_LLVM_ONLY); acfg->assembly_name_sym = g_strdup (get_assembly_prefix (acfg->image)); - /* Get rid of characters which cannot occur in symbols */ +#ifdef TARGET_WASM + acfg->global_prefix = g_strdup_printf ("mono_aot_%s", g_strdup(mono_fixup_symbol_name (acfg->assembly_name_sym))); +#else + char *p; + /* Get rid of characters which cannot occur in symbols */ for (p = acfg->assembly_name_sym; *p; ++p) { if (!(isalnum (*p) || *p == '_')) *p = '_'; } - acfg->global_prefix = g_strdup_printf ("mono_aot_%s", acfg->assembly_name_sym); +#endif acfg->plt_symbol = g_strdup_printf ("%s_plt", acfg->global_prefix); acfg->got_symbol = g_strdup_printf ("%s_got", acfg->global_prefix); if (acfg->llvm) { diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index c8481b41bf9759..63ffbf994657f0 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -14519,17 +14520,21 @@ emit_aot_file_info (MonoLLVMModule *module) LLVMSetInitializer (info_var, LLVMConstNamedStruct (module->info_var_type, fields, nfields)); if (module->static_link) { - char *s, *p; + char *s; LLVMValueRef var; s = g_strdup_printf ("mono_aot_module_%s_info", module->assembly->aname.name); +#ifdef TARGET_WASM + var = LLVMAddGlobal (module->lmodule, pointer_type (LLVMInt8Type ()), g_strdup (mono_fixup_symbol_name(s))); +#else /* Get rid of characters which cannot occur in symbols */ - p = s; + char *p = s; for (p = s; *p; ++p) { if (!(isalnum (*p) || *p == '_')) - *p = '_'; + *p = '_'; } var = LLVMAddGlobal (module->lmodule, pointer_type (LLVMInt8Type ()), s); +#endif g_free (s); LLVMSetInitializer (var, LLVMConstBitCast (LLVMGetNamedGlobal (module->lmodule, "mono_aot_file_info"), pointer_type (LLVMInt8Type ()))); LLVMSetLinkage (var, LLVMExternalLinkage); diff --git a/src/mono/wasm/Wasm.Build.Tests/Common/TestUtils.cs b/src/mono/wasm/Wasm.Build.Tests/Common/TestUtils.cs index 97aa019d454302..fdf88fecc9ee0f 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Common/TestUtils.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Common/TestUtils.cs @@ -91,7 +91,9 @@ public static void AssertEqual(object expected, object actual, string label) $"[{label}]\n"); } - private static readonly char[] s_charsToReplace = new[] { '.', '-', '+' }; + private static readonly char[] s_charsToReplace = new[] { '.', '-', '+', '<', '>' }; + // Keep synced with FixupSymbolName from src/tasks/Common/Utils.cs + // and with mono_fixup_symbol_name from src/mono/mono/metadata/native-library.c public static string FixupSymbolName(string name) { UTF8Encoding utf8 = new(); diff --git a/src/mono/wasm/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs b/src/mono/wasm/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs index 8c0442a1b0d680..0daa8d0984920e 100644 --- a/src/mono/wasm/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs @@ -884,5 +884,31 @@ public void EnsureWasmAbiRulesAreFollowedInAOT(BuildArgs buildArgs, RunHost host [BuildAndRun(host: RunHost.Chrome, aot: false)] public void EnsureWasmAbiRulesAreFollowedInInterpreter(BuildArgs buildArgs, RunHost host, string id) => EnsureWasmAbiRulesAreFollowed(buildArgs, host, id); + + [Theory] + [BuildAndRun(host: RunHost.Chrome, aot: false)] + public void UCOWithSpecialCharacters(BuildArgs buildArgs, RunHost host, string id) + { + var extraProperties = "true"; + var extraItems = @""; + + buildArgs = ExpandBuildArgs(buildArgs, + extraItems: extraItems, + extraProperties: extraProperties); + + (string libraryDir, string output) = BuildProject(buildArgs, + id: id, + new BuildProjectOptions( + InitProject: () => + { + File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "Wasm.Buid.Tests.Programs", "UnmanagedCallback.cs"), Path.Combine(_projectDir!, "Program.cs")); + File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "native-libs", "local.c"), Path.Combine(_projectDir!, "local.c")); + }, + Publish: true, + DotnetWasmFromRuntimePack: false)); + + var runOutput = RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 42, host: host, id: id); + Assert.Contains("ManagedFunc returned 42", runOutput); + } } } diff --git a/src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/UnmanagedCallback.cs b/src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/UnmanagedCallback.cs new file mode 100644 index 00000000000000..2157909c3d5fc6 --- /dev/null +++ b/src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/UnmanagedCallback.cs @@ -0,0 +1,28 @@ +using System; +using System.Runtime.InteropServices; + +public unsafe partial class Test +{ + public unsafe static int Main(string[] args) + { + ((IntPtr)(delegate* unmanaged)&Interop.Managed8\u4F60Func).ToString(); + + Console.WriteLine($"main: {args.Length}"); + Interop.UnmanagedFunc(); + return 42; + } +} + +file partial class Interop +{ + [UnmanagedCallersOnly(EntryPoint = "ManagedFunc")] + public static int Managed8\u4F60Func(int number) + { + // called from UnmanagedFunc + Console.WriteLine($"Managed8\u4F60Func({number}) -> 42"); + return 42; + } + + [DllImport("local", EntryPoint = "UnmanagedFunc")] + public static extern void UnmanagedFunc(); // calls ManagedFunc +} diff --git a/src/mono/wasm/testassets/native-libs/local.c b/src/mono/wasm/testassets/native-libs/local.c new file mode 100644 index 00000000000000..4d7a660513c1fb --- /dev/null +++ b/src/mono/wasm/testassets/native-libs/local.c @@ -0,0 +1,10 @@ +#include +int ManagedFunc(int number); + +void UnmanagedFunc() +{ + int ret = 0; + printf("UnmanagedFunc calling ManagedFunc\n"); + ret = ManagedFunc(123); + printf("ManagedFunc returned %d\n", ret); +} \ No newline at end of file diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index 09d58b2a9d083d..4e98e9271490b6 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -1237,26 +1237,7 @@ private string FixupSymbolName(string name) if (_symbolNameFixups.TryGetValue(name, out string? fixedName)) return fixedName; - UTF8Encoding utf8 = new(); - byte[] bytes = utf8.GetBytes(name); - StringBuilder sb = new(); - - foreach (byte b in bytes) - { - if ((b >= (byte)'0' && b <= (byte)'9') || - (b >= (byte)'a' && b <= (byte)'z') || - (b >= (byte)'A' && b <= (byte)'Z') || - (b == (byte)'_')) - { - sb.Append((char)b); - } - else - { - sb.Append('_'); - } - } - - fixedName = sb.ToString(); + fixedName = Utils.FixupSymbolName(name); _symbolNameFixups[name] = fixedName; return fixedName; } diff --git a/src/tasks/Common/Utils.cs b/src/tasks/Common/Utils.cs index eca2ccd9740233..2f2e8b2ce02d1a 100644 --- a/src/tasks/Common/Utils.cs +++ b/src/tasks/Common/Utils.cs @@ -11,6 +11,7 @@ using System.Reflection.Metadata; using System.Security.Cryptography; using System.Text; +using System.Linq; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; @@ -33,6 +34,8 @@ public enum HashEncodingType private static readonly object s_SyncObj = new object(); + private static readonly char[] s_charsToReplace = new[] { '.', '-', '+', '<', '>' }; + public static string GetEmbeddedResource(string file) { using Stream stream = typeof(Utils).Assembly @@ -411,4 +414,33 @@ private static bool IsManagedAssembly(PEReader peReader) return false; } } + + // Keep synced with mono_fixup_symbol_name from src/mono/mono/metadata/native-library.c + public static string FixupSymbolName(string name) + { + UTF8Encoding utf8 = new(); + byte[] bytes = utf8.GetBytes(name); + StringBuilder sb = new(); + + foreach (byte b in bytes) + { + if ((b >= (byte)'0' && b <= (byte)'9') || + (b >= (byte)'a' && b <= (byte)'z') || + (b >= (byte)'A' && b <= (byte)'Z') || + (b == (byte)'_')) + { + sb.Append((char)b); + } + else if (s_charsToReplace.Contains((char)b)) + { + sb.Append('_'); + } + else + { + sb.Append($"_{b:X}_"); + } + } + + return sb.ToString(); + } } diff --git a/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs b/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs index 3acdcf06ba8a64..db9cf0cef04d87 100644 --- a/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs +++ b/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs @@ -36,8 +36,6 @@ public class ManagedToNativeGenerator : Task [Output] public string[]? FileWrites { get; private set; } - private static readonly char[] s_charsToReplace = new[] { '.', '-', '+', '<', '>' }; - public override bool Execute() { if (Assemblies!.Length == 0) @@ -108,30 +106,7 @@ string FixupSymbolName(string name) if (_symbolNameFixups.TryGetValue(name, out string? fixedName)) return fixedName; - UTF8Encoding utf8 = new(); - byte[] bytes = utf8.GetBytes(name); - StringBuilder sb = new(); - - foreach (byte b in bytes) - { - if ((b >= (byte)'0' && b <= (byte)'9') || - (b >= (byte)'a' && b <= (byte)'z') || - (b >= (byte)'A' && b <= (byte)'Z') || - (b == (byte)'_')) - { - sb.Append((char)b); - } - else if (s_charsToReplace.Contains((char)b)) - { - sb.Append('_'); - } - else - { - sb.Append($"_{b:X}_"); - } - } - - fixedName = sb.ToString(); + fixedName = Utils.FixupSymbolName(name); _symbolNameFixups[name] = fixedName; return fixedName; } diff --git a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs index 4a29b47666e94d..7808655b7f6b68 100644 --- a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs @@ -304,7 +304,7 @@ private string DelegateKey(PInvokeCallback export) // it needs to match the key generated in get_native_to_interp var method = export.Method; string module_symbol = method.DeclaringType!.Module!.Assembly!.GetName()!.Name!; - return $"\"{module_symbol}_{method.DeclaringType.Name}_{method.Name}\"".Replace('.', '_'); + return $"\"{_fixupSymbolName($"{module_symbol}_{method.DeclaringType.Name}_{method.Name}")}\""; } #pragma warning disable SYSLIB1045 // framework doesn't support GeneratedRegexAttribute From f27056529982d9aea44f0a84f24fc0bb0ee52c96 Mon Sep 17 00:00:00 2001 From: Koundinya Veluri Date: Tue, 23 Apr 2024 12:19:41 -0700 Subject: [PATCH 071/248] Fix class construction cycle in Lock on NativeAOT (#100374) When a thread reenters class construction through accessing NativeRuntimeEventSource.Log, Log would return null. Checks on IsFullyInitialized were added to ensure that the normal path would not be taken in that case, to avoid null checks in several places and in different files. That doesn't work when a different thread sees the initialization stage as Complete, as it would try to initialize NativeRuntimeEventSource and run into a class construction cycle. Fixed by removing the IsFullyInitialized checks, introducing a new initialization stage PartiallyCompelte, and not setting the stage to Complete until it has been verified that Log does not return null. When the stage is PartiallyCompelte, a thread would retry the relevant initialization. This again guarantees that there would be at most one attempt at initialization through Lock at any given time, and prevents the class construction cycle. Fixes https://github.com/dotnet/runtime/issues/99663 --- .../src/System/Threading/Lock.NativeAot.cs | 75 +++++++++++-------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs index 7ac43d2257e786..8a1c017a508098 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs @@ -92,18 +92,6 @@ internal void Reenter(uint previousRecursionCount) _recursionCount = previousRecursionCount; } - private static bool IsFullyInitialized - { - get - { - // If NativeRuntimeEventSource is already being class-constructed by this thread earlier in the stack, Log can - // be null. This property is used to avoid going down the wait path in that case to avoid null checks in several - // other places. - Debug.Assert((StaticsInitializationStage)s_staticsInitializationStage == StaticsInitializationStage.Complete); - return NativeRuntimeEventSource.Log != null; - } - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] private TryLockResult LazyInitializeOrEnter() { @@ -113,10 +101,6 @@ private TryLockResult LazyInitializeOrEnter() case StaticsInitializationStage.Complete: if (_spinCount == SpinCountNotInitialized) { - if (!IsFullyInitialized) - { - goto case StaticsInitializationStage.Started; - } _spinCount = s_maxSpinCount; } return TryLockResult.Spin; @@ -137,7 +121,7 @@ private TryLockResult LazyInitializeOrEnter() } stage = (StaticsInitializationStage)Volatile.Read(ref s_staticsInitializationStage); - if (stage == StaticsInitializationStage.Complete && IsFullyInitialized) + if (stage == StaticsInitializationStage.Complete) { goto case StaticsInitializationStage.Complete; } @@ -155,7 +139,9 @@ private TryLockResult LazyInitializeOrEnter() } default: - Debug.Assert(stage == StaticsInitializationStage.NotStarted); + Debug.Assert( + stage == StaticsInitializationStage.NotStarted || + stage == StaticsInitializationStage.PartiallyComplete); if (TryInitializeStatics()) { goto case StaticsInitializationStage.Complete; @@ -169,29 +155,49 @@ private static bool TryInitializeStatics() { // Since Lock is used to synchronize class construction, and some of the statics initialization may involve class // construction, update the stage first to avoid infinite recursion - switch ( - (StaticsInitializationStage) - Interlocked.CompareExchange( - ref s_staticsInitializationStage, - (int)StaticsInitializationStage.Started, - (int)StaticsInitializationStage.NotStarted)) + var oldStage = (StaticsInitializationStage)s_staticsInitializationStage; + while (true) { - case StaticsInitializationStage.Started: - return false; - case StaticsInitializationStage.Complete: + if (oldStage == StaticsInitializationStage.Complete) + { return true; + } + + var stageBeforeUpdate = + (StaticsInitializationStage)Interlocked.CompareExchange( + ref s_staticsInitializationStage, + (int)StaticsInitializationStage.Started, + (int)oldStage); + if (stageBeforeUpdate == StaticsInitializationStage.Started) + { + return false; + } + if (stageBeforeUpdate == oldStage) + { + Debug.Assert( + oldStage == StaticsInitializationStage.NotStarted || + oldStage == StaticsInitializationStage.PartiallyComplete); + break; + } + + oldStage = stageBeforeUpdate; } bool isFullyInitialized; try { - s_isSingleProcessor = Environment.IsSingleProcessor; - s_maxSpinCount = DetermineMaxSpinCount(); - s_minSpinCount = DetermineMinSpinCount(); + if (oldStage == StaticsInitializationStage.NotStarted) + { + // If the stage is PartiallyComplete, these will have already been initialized + s_isSingleProcessor = Environment.IsSingleProcessor; + s_maxSpinCount = DetermineMaxSpinCount(); + s_minSpinCount = DetermineMinSpinCount(); + } // Also initialize some types that are used later to prevent potential class construction cycles. If // NativeRuntimeEventSource is already being class-constructed by this thread earlier in the stack, Log can be - // null. Avoid going down the wait path in that case to avoid null checks in several other places. + // null. Avoid going down the wait path in that case to avoid null checks in several other places. If not fully + // initialized, the stage will also be set to PartiallyComplete to try again. isFullyInitialized = NativeRuntimeEventSource.Log != null; } catch @@ -200,7 +206,11 @@ private static bool TryInitializeStatics() throw; } - Volatile.Write(ref s_staticsInitializationStage, (int)StaticsInitializationStage.Complete); + Volatile.Write( + ref s_staticsInitializationStage, + isFullyInitialized + ? (int)StaticsInitializationStage.Complete + : (int)StaticsInitializationStage.PartiallyComplete); return isFullyInitialized; } @@ -242,6 +252,7 @@ private enum StaticsInitializationStage { NotStarted, Started, + PartiallyComplete, Complete } } From d92ac1f892a7f9c00561db6541671f25f3972eed Mon Sep 17 00:00:00 2001 From: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Tue, 23 Apr 2024 22:14:09 +0200 Subject: [PATCH 072/248] Fix SocketsHttpHandlerTest_HttpClientHandlerTest_Http3.ReadAsStreamAsync_Cancellation data race (#101428) * Fix SocketsHttpHandlerTest_HttpClientHandlerTest_Http3.ReadAsStreamAsync_Cancellation data race * Fix build --- .../tests/System/Net/Http/HttpClientHandlerTest.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs index 0ffd0d4ae82eda..7c3d3f385d0bd9 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs @@ -6,6 +6,9 @@ using System.Linq; using System.Net.Http.Headers; using System.Net.Sockets; +#if !NETFRAMEWORK +using System.Net.Quic; +#endif using System.Net.Test.Common; using System.Security.Authentication; using System.Security.Cryptography; @@ -1396,6 +1399,12 @@ await server.AcceptConnectionAsync(async connection => await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] { new HttpHeaderData("Transfer-Encoding", "chunked") }, isFinal: false); await connection.SendResponseBodyAsync("1\r\nh\r\n", false); } +#if !NETFRAMEWORK + catch (QuicException ex) when (ex.ApplicationErrorCode == 0x10c /*H3_REQUEST_CANCELLED*/) + { + // The request was cancelled before we sent the body, ignore + } +#endif catch (IOException ex) { // when testing in the browser, we are using the WebSocket for the loopback From 6e866a6ed62c6178efc55e4fe276d3e44190e4f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Wed, 24 Apr 2024 06:29:58 +0900 Subject: [PATCH 073/248] Fix running tests with process isolation under naot (#100331) We don't currently run any RequiresProcessIsolation tests under native AOT because we hit the "not an applicable OS" early out here: https://github.com/dotnet/runtime/blob/765ca4e9f2dddca2005ffdb45863b7980247a886/src/tests/Common/CoreCLRTestLibrary/OutOfProcessTest.cs#L75-L79 --- src/tests/Common/CLRTest.Jit.targets | 4 +- .../CoreCLRTestLibrary/OutOfProcessTest.cs | 12 +++-- .../Common/XUnitWrapperGenerator/ITestInfo.cs | 7 ++- .../XUnitWrapperGenerator/OptionsHelper.cs | 3 ++ .../XUnitWrapperGenerator.cs | 2 +- .../XUnitWrapperGenerator.props | 1 + .../Directed/tailcall/mutual_recursion.fsproj | 3 ++ .../Runtime_72845/Runtime_72845.fsproj | 3 ++ .../coreclr/GitHub_22888/test22888.csproj | 3 ++ src/tests/issues.targets | 49 +++++++++++++++++++ 10 files changed, 79 insertions(+), 8 deletions(-) diff --git a/src/tests/Common/CLRTest.Jit.targets b/src/tests/Common/CLRTest.Jit.targets index 6fd00de8977f6a..5c2a0735a414fe 100644 --- a/src/tests/Common/CLRTest.Jit.targets +++ b/src/tests/Common/CLRTest.Jit.targets @@ -140,7 +140,7 @@ IF NOT DEFINED DoLink ( DependsOnTargets="GetDisasmCheckData"> false - true + true $(scriptPath)__jit_disasm.out $(scriptPath)__jit_disasm_list.out @@ -184,7 +184,7 @@ fi DependsOnTargets="GetDisasmCheckData"> false - true + true $(scriptPath)__jit_disasm.out $(scriptPath)__jit_disasm_list.out diff --git a/src/tests/Common/CoreCLRTestLibrary/OutOfProcessTest.cs b/src/tests/Common/CoreCLRTestLibrary/OutOfProcessTest.cs index 0337fa9e624f0d..66937878587ddd 100644 --- a/src/tests/Common/CoreCLRTestLibrary/OutOfProcessTest.cs +++ b/src/tests/Common/CoreCLRTestLibrary/OutOfProcessTest.cs @@ -49,7 +49,7 @@ static OutOfProcessTest() && !OperatingSystem.IsBrowser() && !OperatingSystem.IsOSPlatform("Wasi"); - public static void RunOutOfProcessTest(string assemblyPath) + public static void RunOutOfProcessTest(string assemblyPath, string testPathPrefix) { int ret = -100; string baseDir = AppContext.BaseDirectory; @@ -63,17 +63,23 @@ public static void RunOutOfProcessTest(string assemblyPath) { CoreclrTestWrapperLib wrapper = new CoreclrTestWrapperLib(); + string testScriptPath = assemblyPath; + if (testPathPrefix != null) + testScriptPath = Path.Combine(testPathPrefix, testScriptPath); + if (OperatingSystem.IsWindows()) { - testExecutable = Path.Combine(baseDir, Path.ChangeExtension(assemblyPath, ".cmd")); + testExecutable = Path.Combine(baseDir, Path.ChangeExtension(testScriptPath, ".cmd")); } else { - testExecutable = Path.Combine(baseDir, Path.ChangeExtension(assemblyPath.Replace("\\", "/"), ".sh")); + testExecutable = Path.Combine(baseDir, Path.ChangeExtension(testScriptPath.Replace("\\", "/"), ".sh")); } if (!File.Exists(testExecutable)) { + Console.WriteLine($"Test executable '{testExecutable}' not found, skipping."); + // Skip platform-specific test when running on the excluded platform return; } diff --git a/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs b/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs index c4bdef69eb9e91..712c435162aaf3 100644 --- a/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs +++ b/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs @@ -336,13 +336,16 @@ public sealed class OutOfProcessTest : ITestInfo private CodeBuilder _executionStatement { get; } private string RelativeAssemblyPath { get; } - public OutOfProcessTest(string displayName, string relativeAssemblyPath) + public OutOfProcessTest(string displayName, string relativeAssemblyPath, string? testBuildMode) { Method = displayName; DisplayNameForFiltering = displayName; TestNameExpression = $"@\"{displayName}\""; RelativeAssemblyPath = relativeAssemblyPath; + // Native AOT tests get generated into a 'native' directory, so we need to get out of that one first to find the test + string testPathPrefix = string.Equals(testBuildMode, "nativeaot", StringComparison.OrdinalIgnoreCase) ? "\"..\"" : "null"; + _executionStatement = new CodeBuilder(); _executionStatement.AppendLine(); _executionStatement.AppendLine("if (TestLibrary.OutOfProcessTest.OutOfProcessTestsSupported)"); @@ -350,7 +353,7 @@ public OutOfProcessTest(string displayName, string relativeAssemblyPath) using (_executionStatement.NewBracesScope()) { _executionStatement.AppendLine($@"TestLibrary.OutOfProcessTest" - + $@".RunOutOfProcessTest(@""{relativeAssemblyPath}"");"); + + $@".RunOutOfProcessTest(@""{relativeAssemblyPath}"", {testPathPrefix});"); } } diff --git a/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs b/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs index 9b9dd10b23569d..61f4488f0aaa3e 100644 --- a/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs +++ b/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs @@ -9,6 +9,7 @@ public static class OptionsHelper private const string InMergedTestDirectoryOption = "build_property.InMergedTestDirectory"; private const string IsMergedTestRunnerAssemblyOption = "build_property.IsMergedTestRunnerAssembly"; private const string PriorityOption = "build_property.Priority"; + private const string TestBuildModeOption = "build_property.TestBuildMode"; private const string RuntimeFlavorOption = "build_property.RuntimeFlavor"; private const string IsOutOfProcessTestAssemblyOption = "build_metadata.AdditionalFiles.IsOutOfProcessTestAssembly"; private const string TestFilterOption = "build_property.TestFilter"; @@ -38,6 +39,8 @@ private static bool GetBoolOption(this AnalyzerConfigOptions options, string key internal static string RuntimeFlavor(this AnalyzerConfigOptions options) => options.TryGetValue(RuntimeFlavorOption, out string? flavor) ? flavor : "CoreCLR"; + internal static string? TestBuildMode(this AnalyzerConfigOptions options) => options.TryGetValue(TestBuildModeOption, out string? option) ? option : null; + internal static bool IsOutOfProcessTestAssembly(this AnalyzerConfigOptions options) => options.GetBoolOption(IsOutOfProcessTestAssemblyOption); internal static string? TestFilter(this AnalyzerConfigOptions options) => options.TryGetValue(TestFilterOption, out string? filter) ? filter : null; diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index 06cfdf3022c1b7..bbff22006a4bd0 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -56,7 +56,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) string? testDisplayName = fileOptions.TestDisplayName(); if (assemblyPath is not null && testDisplayName is not null) { - return ImmutableArray.Create(new OutOfProcessTest(testDisplayName, assemblyPath)); + return ImmutableArray.Create(new OutOfProcessTest(testDisplayName, assemblyPath, fileOptions.TestBuildMode())); } } diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props index 067c31f8d6b4d0..fca5c164fba2e1 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props @@ -5,6 +5,7 @@ + diff --git a/src/tests/JIT/Directed/tailcall/mutual_recursion.fsproj b/src/tests/JIT/Directed/tailcall/mutual_recursion.fsproj index 83624287a592ec..b6a0995379d76a 100644 --- a/src/tests/JIT/Directed/tailcall/mutual_recursion.fsproj +++ b/src/tests/JIT/Directed/tailcall/mutual_recursion.fsproj @@ -2,6 +2,9 @@ true + + + true True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_72845/Runtime_72845.fsproj b/src/tests/JIT/Regression/JitBlue/Runtime_72845/Runtime_72845.fsproj index 4ecbaba4ff4301..302b1099bdf8dc 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_72845/Runtime_72845.fsproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_72845/Runtime_72845.fsproj @@ -7,6 +7,9 @@ True $(NetCoreAppToolCurrent) True + + + true diff --git a/src/tests/Regressions/coreclr/GitHub_22888/test22888.csproj b/src/tests/Regressions/coreclr/GitHub_22888/test22888.csproj index f2a1d423be02aa..f74b821627d90b 100644 --- a/src/tests/Regressions/coreclr/GitHub_22888/test22888.csproj +++ b/src/tests/Regressions/coreclr/GitHub_22888/test22888.csproj @@ -3,6 +3,9 @@ true true + + + true diff --git a/src/tests/issues.targets b/src/tests/issues.targets index e5e6cc332a6292..8289fcefb924fb 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -682,6 +682,15 @@ + + needs triage + + + needs triage + + + https://github.com/dotnet/runtime/issues/91381 + https://github.com/dotnet/runtime/issues/89157 @@ -1151,6 +1160,46 @@ + + + + https://github.com/dotnet/runtime/issues/101284 + + + https://github.com/dotnet/runtime/issues/101284 + + + https://github.com/dotnet/runtime/issues/101284 + + + https://github.com/dotnet/runtime/issues/101284 + + + https://github.com/dotnet/runtime/issues/101284 + + + https://github.com/dotnet/runtime/issues/101284 + + + https://github.com/dotnet/runtime/issues/101363 + + + https://github.com/dotnet/runtime/issues/101363 + + + https://github.com/dotnet/runtime/issues/101363 + + + https://github.com/dotnet/runtime/issues/101363 + + + https://github.com/dotnet/runtime/issues/101363 + + + https://github.com/dotnet/runtime/issues/101364 + + + From 1af8ccd0e7ca5918610c97145fca226ab9329e7e Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 23 Apr 2024 16:13:06 -0700 Subject: [PATCH 074/248] Fix comment (#101440) --- src/coreclr/gc/gcpriv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 6db2e06d04c004..a7199e5d220ac0 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -140,10 +140,10 @@ inline void FATAL_GC_ERROR() // // This means any empty regions can be freely used for any generation. For // Server GC we will balance regions between heaps. -// For now disable regions for StandAlone GC, NativeAOT and MacOS builds +// For now disable regions for standalone GC and macOS builds #if defined (HOST_64BIT) && !defined (BUILD_AS_STANDALONE) && !defined(__APPLE__) #define USE_REGIONS -#endif //HOST_64BIT && BUILD_AS_STANDALONE +#endif //HOST_64BIT && BUILD_AS_STANDALONE && !__APPLE__ //#define SPINLOCK_HISTORY //#define RECORD_LOH_STATE From 8017222b29b64863babf214050ecc80d5f28e323 Mon Sep 17 00:00:00 2001 From: Vladimir Sadov Date: Tue, 23 Apr 2024 16:57:35 -0700 Subject: [PATCH 075/248] Disable UnrollEqualsStartsWith for gcstress. The test takes very long time. (#101455) * Disable UnrollEqualsStartsWith for gcstress. The test takes very long time. * fix comment * added a comment for the reason to exclude --- src/tests/JIT/opt/Vectorization/UnrollEqualsStartsWith.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tests/JIT/opt/Vectorization/UnrollEqualsStartsWith.csproj b/src/tests/JIT/opt/Vectorization/UnrollEqualsStartsWith.csproj index c9327d09cb4dc3..87fba405d81ec4 100644 --- a/src/tests/JIT/opt/Vectorization/UnrollEqualsStartsWith.csproj +++ b/src/tests/JIT/opt/Vectorization/UnrollEqualsStartsWith.csproj @@ -1,6 +1,10 @@ True + + true + + true From f55c5a80329644e7ee5cce499fbbb4da2899aabd Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Tue, 23 Apr 2024 18:16:58 -0700 Subject: [PATCH 076/248] Expose the `ConvertToIntegerNative` APIs (#100993) * Expose the ConvertToIntegerNative APIs for the floating-point types * Accelerate the ConvertToInteger and related APIs * Applying formatting patch * Fixing some tests for x86 and skipping some tests on Mono --- src/coreclr/jit/compiler.h | 20 +- src/coreclr/jit/emit.h | 4 + src/coreclr/jit/gentree.cpp | 260 +++++++++++++----- src/coreclr/jit/hwintrinsicarm64.cpp | 26 +- src/coreclr/jit/hwintrinsiclistarm64.h | 8 + src/coreclr/jit/hwintrinsiclistxarch.h | 14 +- src/coreclr/jit/hwintrinsicxarch.cpp | 108 ++++++-- src/coreclr/jit/importercalls.cpp | 128 ++++++++- src/coreclr/jit/namedintrinsiclist.h | 2 + src/coreclr/jit/simdashwintrinsic.cpp | 101 +++---- src/coreclr/jit/simdashwintrinsiclistarm64.h | 4 + src/coreclr/jit/simdashwintrinsiclistxarch.h | 4 + .../Common/tests/System/GenericMathHelpers.cs | 6 + .../ref/System.Numerics.Vectors.cs | 6 + .../src/System/Decimal.cs | 8 + .../src/System/Double.cs | 10 + .../System.Private.CoreLib/src/System/Half.cs | 8 + .../src/System/Numerics/IFloatingPoint.cs | 20 ++ .../src/System/Numerics/Vector.cs | 34 ++- .../System/Runtime/InteropServices/NFloat.cs | 8 + .../System/Runtime/Intrinsics/Vector128.cs | 62 ++++- .../System/Runtime/Intrinsics/Vector256.cs | 62 ++++- .../System/Runtime/Intrinsics/Vector512.cs | 62 ++++- .../src/System/Runtime/Intrinsics/Vector64.cs | 38 ++- .../src/System/Single.cs | 10 + .../ref/System.Runtime.InteropServices.cs | 2 + .../ref/System.Runtime.Intrinsics.cs | 24 ++ .../tests/Vectors/Vector128Tests.cs | 104 +++++++ .../tests/Vectors/Vector256Tests.cs | 104 +++++++ .../tests/Vectors/Vector512Tests.cs | 104 +++++++ .../tests/Vectors/Vector64Tests.cs | 73 +++++ .../System.Runtime/ref/System.Runtime.cs | 12 + .../System/DoubleTests.GenericMath.cs | 169 +++++++++++- .../System/SingleTests.GenericMath.cs | 167 +++++++++++ 34 files changed, 1578 insertions(+), 194 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 3c19969d0c90d8..5b8a04e868836c 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -3188,13 +3188,17 @@ class Compiler CorInfoType simdBaseJitType, unsigned simdSize); -#if defined(TARGET_XARCH) - GenTree* gtNewSimdCvtNode(var_types type, - GenTree* op1, - CorInfoType simdTargetBaseJitType, - CorInfoType simdSourceBaseJitType, - unsigned simdSize); -#endif //TARGET_XARCH + GenTree* gtNewSimdCvtNode(var_types type, + GenTree* op1, + CorInfoType simdTargetBaseJitType, + CorInfoType simdSourceBaseJitType, + unsigned simdSize); + + GenTree* gtNewSimdCvtNativeNode(var_types type, + GenTree* op1, + CorInfoType simdTargetBaseJitType, + CorInfoType simdSourceBaseJitType, + unsigned simdSize); GenTree* gtNewSimdCreateBroadcastNode( var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize); @@ -5928,7 +5932,7 @@ class Compiler void fgReplaceEhfSuccessor(BasicBlock* block, BasicBlock* oldSucc, BasicBlock* newSucc); void fgRemoveEhfSuccessor(BasicBlock* block, const unsigned succIndex); - + void fgRemoveEhfSuccessor(FlowEdge* succEdge); void fgReplaceJumpTarget(BasicBlock* block, BasicBlock* oldTarget, BasicBlock* newTarget); diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 40a729dd70fee2..4fb37df5149111 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -4020,6 +4020,8 @@ emitAttr emitter::emitGetBaseMemOpSize(instrDesc* id) const case INS_subss: case INS_ucomiss: case INS_vbroadcastss: + case INS_vcvttss2usi32: + case INS_vcvttss2usi64: case INS_vfmadd132ss: case INS_vfmadd213ss: case INS_vfmadd231ss: @@ -4067,6 +4069,8 @@ emitAttr emitter::emitGetBaseMemOpSize(instrDesc* id) const case INS_subsd: case INS_ucomisd: case INS_vbroadcastsd: + case INS_vcvttsd2usi32: + case INS_vcvttsd2usi64: case INS_vfmadd132sd: case INS_vfmadd213sd: case INS_vfmadd231sd: diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 878c02ac1603df..c6d6b78c48ca9e 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -21350,7 +21350,6 @@ GenTree* Compiler::gtNewSimdCeilNode(var_types type, GenTree* op1, CorInfoType s return gtNewSimdHWIntrinsicNode(type, op1, intrinsic, simdBaseJitType, simdSize); } -#if defined(TARGET_XARCH) GenTree* Compiler::gtNewSimdCvtNode(var_types type, GenTree* op1, CorInfoType simdTargetBaseJitType, @@ -21368,12 +21367,128 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, assert(varTypeIsIntegral(simdTargetBaseType)); assert(IsBaselineSimdIsaSupportedDebugOnly()); + +#if defined(TARGET_XARCH) assert(IsBaselineVector512IsaSupportedDebugOnly() || ((simdTargetBaseType == TYP_INT) && ((simdSize == 16 && compIsaSupportedDebugOnly(InstructionSet_SSE41)) || (simdSize == 32 && compIsaSupportedDebugOnly(InstructionSet_AVX))))); + GenTree* fixupVal; + + if (IsBaselineVector512IsaSupportedOpportunistically()) + { + /*Generate the control table for VFIXUPIMMSD/SS + - For conversion to unsigned + // QNAN: 0b1000: Saturate to Zero + // SNAN: 0b1000: Saturate to Zero + // ZERO: 0b0000 + // +ONE: 0b0000 + // -INF: 0b1000: Saturate to Zero + // +INF: 0b0000 + // -VAL: 0b1000: Saturate to Zero + // +VAL: 0b0000 + - For conversion to signed + // QNAN: 0b1000: Saturate to Zero + // SNAN: 0b1000: Saturate to Zero + // ZERO: 0b0000 + // +ONE: 0b0000 + // -INF: 0b0000 + // +INF: 0b0000 + // -VAL: 0b0000 + // +VAL: 0b0000 + */ + int32_t iconVal = varTypeIsUnsigned(simdTargetBaseType) ? 0x08080088 : 0x00000088; + GenTree* tblCon = gtNewSimdCreateBroadcastNode(type, gtNewIconNode(iconVal), simdTargetBaseJitType, simdSize); + + // We need op1Clone to run fixup + GenTree* op1Clone = fgMakeMultiUse(&op1); + + // run vfixupimmsd base on table and no flags reporting + fixupVal = gtNewSimdHWIntrinsicNode(type, op1, op1Clone, tblCon, gtNewIconNode(0), NI_AVX512F_Fixup, + simdSourceBaseJitType, simdSize); + } + else + { + // Zero out NaN values from the input. + // mask1 contains the output either 0xFFFFFFFF or 0. + // FixupVal zeros out any NaN values in the input by ANDing input with mask1. + GenTree* op1Clone1 = fgMakeMultiUse(&op1); + GenTree* op1Clone2 = fgMakeMultiUse(&op1); + GenTree* mask1 = gtNewSimdCmpOpNode(GT_EQ, type, op1, op1Clone1, simdSourceBaseJitType, simdSize); + fixupVal = gtNewSimdBinOpNode(GT_AND, type, op1Clone2, mask1, simdSourceBaseJitType, simdSize); + } + + if (varTypeIsSigned(simdTargetBaseType)) + { + GenTree* maxVal; + GenTree* maxValDup; + if (varTypeIsLong(simdTargetBaseType)) + { + int64_t actualMaxVal = INT64_MAX; + maxVal = gtNewDconNode(static_cast(actualMaxVal), simdSourceBaseType); + maxVal = gtNewSimdCreateBroadcastNode(type, maxVal, simdSourceBaseJitType, simdSize); + maxValDup = + gtNewSimdCreateBroadcastNode(type, gtNewLconNode(actualMaxVal), simdTargetBaseJitType, simdSize); + } + else + { + ssize_t actualMaxVal = INT32_MAX; + maxVal = gtNewDconNode(static_cast(actualMaxVal), simdSourceBaseType); + maxVal = gtNewSimdCreateBroadcastNode(type, maxVal, simdSourceBaseJitType, simdSize); + maxValDup = + gtNewSimdCreateBroadcastNode(type, gtNewIconNode(actualMaxVal), simdTargetBaseJitType, simdSize); + } + + // we will be using the input value twice + GenTree* fixupValDup = fgMakeMultiUse(&fixupVal); + + // compare with max value of integer/long + fixupVal = gtNewSimdCmpOpNode(GT_GE, type, fixupVal, maxVal, simdSourceBaseJitType, simdSize); + + // cast it + GenTree* castNode = + gtNewSimdCvtNativeNode(type, fixupValDup, simdTargetBaseJitType, simdSourceBaseJitType, simdSize); + + // use the fixupVal mask with input value and max value to blend + return gtNewSimdCndSelNode(type, fixupVal, maxValDup, castNode, simdTargetBaseJitType, simdSize); + } + else + { + return gtNewSimdCvtNativeNode(type, fixupVal, simdTargetBaseJitType, simdSourceBaseJitType, simdSize); + } +#elif defined(TARGET_ARM64) + return gtNewSimdCvtNativeNode(type, op1, simdTargetBaseJitType, simdSourceBaseJitType, simdSize); +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 +} + +GenTree* Compiler::gtNewSimdCvtNativeNode(var_types type, + GenTree* op1, + CorInfoType simdTargetBaseJitType, + CorInfoType simdSourceBaseJitType, + unsigned simdSize) +{ + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdSourceBaseType = JitType2PreciseVarType(simdSourceBaseJitType); + var_types simdTargetBaseType = JitType2PreciseVarType(simdTargetBaseJitType); + assert(varTypeIsFloating(simdSourceBaseType)); + assert(varTypeIsIntegral(simdTargetBaseType)); + + assert(IsBaselineSimdIsaSupportedDebugOnly()); + // Generate intrinsic needed for conversion NamedIntrinsic hwIntrinsicID = NI_Illegal; + +#if defined(TARGET_XARCH) + assert(IsBaselineVector512IsaSupportedDebugOnly() || + ((simdTargetBaseType == TYP_INT) && + ((simdSize == 16) || (simdSize == 32 && compIsaSupportedDebugOnly(InstructionSet_AVX))))); + switch (simdSourceBaseJitType) { case CORINFO_TYPE_FLOAT: @@ -21389,21 +21504,25 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, hwIntrinsicID = NI_AVX512F_ConvertToVector512Int32WithTruncation; break; } + case 32: { hwIntrinsicID = NI_AVX_ConvertToVector256Int32WithTruncation; break; } + case 16: { hwIntrinsicID = NI_SSE2_ConvertToVector128Int32WithTruncation; break; } + default: unreached(); } break; } + case CORINFO_TYPE_UINT: { switch (simdSize) @@ -21413,26 +21532,31 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, hwIntrinsicID = NI_AVX512F_ConvertToVector512UInt32WithTruncation; break; } + case 32: { hwIntrinsicID = NI_AVX512F_VL_ConvertToVector256UInt32WithTruncation; break; } + case 16: { hwIntrinsicID = NI_AVX512F_VL_ConvertToVector128UInt32WithTruncation; break; } + default: unreached(); } break; } + default: unreached(); } break; } + case CORINFO_TYPE_DOUBLE: { switch (simdTargetBaseJitType) @@ -21446,21 +21570,25 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, hwIntrinsicID = NI_AVX512DQ_ConvertToVector512Int64WithTruncation; break; } + case 32: { hwIntrinsicID = NI_AVX512DQ_VL_ConvertToVector256Int64WithTruncation; break; } + case 16: { hwIntrinsicID = NI_AVX512DQ_VL_ConvertToVector128Int64WithTruncation; break; } + default: unreached(); } break; } + case CORINFO_TYPE_ULONG: { switch (simdSize) @@ -21470,115 +21598,95 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, hwIntrinsicID = NI_AVX512DQ_ConvertToVector512UInt64WithTruncation; break; } + case 32: { hwIntrinsicID = NI_AVX512DQ_VL_ConvertToVector256UInt64WithTruncation; break; } + case 16: { hwIntrinsicID = NI_AVX512DQ_VL_ConvertToVector128UInt64WithTruncation; break; } + default: unreached(); } break; } + default: unreached(); } break; } + default: unreached(); } - assert(hwIntrinsicID != NI_Illegal); - - GenTree* fixupVal; +#elif defined(TARGET_ARM64) + assert((simdSize == 8) || (simdSize == 16)); - if (IsBaselineVector512IsaSupportedOpportunistically()) + switch (simdSourceBaseJitType) { - /*Generate the control table for VFIXUPIMMSD/SS - - For conversion to unsigned - // QNAN: 0b1000: Saturate to Zero - // SNAN: 0b1000: Saturate to Zero - // ZERO: 0b0000 - // +ONE: 0b0000 - // -INF: 0b1000: Saturate to Zero - // +INF: 0b0000 - // -VAL: 0b1000: Saturate to Zero - // +VAL: 0b0000 - - For conversion to signed - // QNAN: 0b1000: Saturate to Zero - // SNAN: 0b1000: Saturate to Zero - // ZERO: 0b0000 - // +ONE: 0b0000 - // -INF: 0b0000 - // +INF: 0b0000 - // -VAL: 0b0000 - // +VAL: 0b0000 - */ - int32_t iconVal = varTypeIsUnsigned(simdTargetBaseType) ? 0x08080088 : 0x00000088; - GenTree* tblCon = gtNewSimdCreateBroadcastNode(type, gtNewIconNode(iconVal), simdTargetBaseJitType, simdSize); - - // We need op1Clone to run fixup - GenTree* op1Clone = fgMakeMultiUse(&op1); + case CORINFO_TYPE_FLOAT: + { + switch (simdTargetBaseJitType) + { + case CORINFO_TYPE_INT: + { + hwIntrinsicID = NI_AdvSimd_ConvertToInt32RoundToZero; + break; + } - // run vfixupimmsd base on table and no flags reporting - fixupVal = gtNewSimdHWIntrinsicNode(type, op1, op1Clone, tblCon, gtNewIconNode(0), NI_AVX512F_Fixup, - simdSourceBaseJitType, simdSize); - } - else - { - // Zero out NaN values from the input. - // mask1 contains the output either 0xFFFFFFFF or 0. - // FixupVal zeros out any NaN values in the input by ANDing input with mask1. - GenTree* op1Clone1 = fgMakeMultiUse(&op1); - GenTree* op1Clone2 = fgMakeMultiUse(&op1); - GenTree* mask1 = gtNewSimdCmpOpNode(GT_EQ, type, op1, op1Clone1, simdSourceBaseJitType, simdSize); - fixupVal = gtNewSimdBinOpNode(GT_AND, type, op1Clone2, mask1, simdSourceBaseJitType, simdSize); - } + case CORINFO_TYPE_UINT: + { + hwIntrinsicID = NI_AdvSimd_ConvertToUInt32RoundToZero; + break; + } - if (varTypeIsSigned(simdTargetBaseType)) - { - GenTree* maxVal; - GenTree* maxValDup; - if (varTypeIsLong(simdTargetBaseType)) - { - int64_t actualMaxVal = INT64_MAX; - maxVal = gtNewDconNode(static_cast(actualMaxVal), simdSourceBaseType); - maxVal = gtNewSimdCreateBroadcastNode(type, maxVal, simdSourceBaseJitType, simdSize); - maxValDup = - gtNewSimdCreateBroadcastNode(type, gtNewLconNode(actualMaxVal), simdTargetBaseJitType, simdSize); - } - else - { - ssize_t actualMaxVal = INT32_MAX; - maxVal = gtNewDconNode(static_cast(actualMaxVal), simdSourceBaseType); - maxVal = gtNewSimdCreateBroadcastNode(type, maxVal, simdSourceBaseJitType, simdSize); - maxValDup = - gtNewSimdCreateBroadcastNode(type, gtNewIconNode(actualMaxVal), simdTargetBaseJitType, simdSize); + default: + unreached(); + } + break; } - // we will be using the input value twice - GenTree* fixupValDup = fgMakeMultiUse(&fixupVal); + case CORINFO_TYPE_DOUBLE: + { + switch (simdTargetBaseJitType) + { + case CORINFO_TYPE_LONG: + { + hwIntrinsicID = (simdSize == 8) ? NI_AdvSimd_Arm64_ConvertToInt64RoundToZeroScalar + : NI_AdvSimd_Arm64_ConvertToInt64RoundToZero; + break; + } - // compare with max value of integer/long - fixupVal = gtNewSimdCmpOpNode(GT_GE, type, fixupVal, maxVal, simdSourceBaseJitType, simdSize); + case CORINFO_TYPE_ULONG: + { + hwIntrinsicID = (simdSize == 8) ? NI_AdvSimd_Arm64_ConvertToUInt64RoundToZeroScalar + : NI_AdvSimd_Arm64_ConvertToUInt64RoundToZero; + break; + } - // cast it - GenTree* castNode = gtNewSimdHWIntrinsicNode(type, fixupValDup, hwIntrinsicID, simdSourceBaseJitType, simdSize); + default: + unreached(); + } + break; + } - // use the fixupVal mask with input value and max value to blend - return gtNewSimdCndSelNode(type, fixupVal, maxValDup, castNode, simdTargetBaseJitType, simdSize); - } - else - { - return gtNewSimdHWIntrinsicNode(type, fixupVal, hwIntrinsicID, simdSourceBaseJitType, simdSize); + default: + unreached(); } +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + + assert(hwIntrinsicID != NI_Illegal); + return gtNewSimdHWIntrinsicNode(type, op1, hwIntrinsicID, simdSourceBaseJitType, simdSize); } -#endif // TARGET_XARCH GenTree* Compiler::gtNewSimdCmpOpNode( genTreeOps op, var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize) diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp index 8e3288f75d7090..98342739cb4e0d 100644 --- a/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/jit/hwintrinsicarm64.cpp @@ -621,28 +621,28 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, } case NI_Vector64_ConvertToInt32: + case NI_Vector64_ConvertToInt32Native: case NI_Vector128_ConvertToInt32: + case NI_Vector128_ConvertToInt32Native: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_FLOAT); - op1 = impSIMDPopStack(); - retNode = - gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToInt32RoundToZero, simdBaseJitType, simdSize); + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); break; } case NI_Vector64_ConvertToInt64: + case NI_Vector64_ConvertToInt64Native: case NI_Vector128_ConvertToInt64: + case NI_Vector128_ConvertToInt64Native: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_DOUBLE); - intrinsic = (simdSize == 8) ? NI_AdvSimd_Arm64_ConvertToInt64RoundToZeroScalar - : NI_AdvSimd_Arm64_ConvertToInt64RoundToZero; - op1 = impSIMDPopStack(); - retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, simdBaseJitType, simdSize); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); break; } @@ -658,28 +658,28 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, } case NI_Vector64_ConvertToUInt32: + case NI_Vector64_ConvertToUInt32Native: case NI_Vector128_ConvertToUInt32: + case NI_Vector128_ConvertToUInt32Native: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_FLOAT); op1 = impSIMDPopStack(); - retNode = gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToUInt32RoundToZero, simdBaseJitType, - simdSize); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); break; } case NI_Vector64_ConvertToUInt64: + case NI_Vector64_ConvertToUInt64Native: case NI_Vector128_ConvertToUInt64: + case NI_Vector128_ConvertToUInt64Native: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_DOUBLE); - intrinsic = (simdSize == 8) ? NI_AdvSimd_Arm64_ConvertToUInt64RoundToZeroScalar - : NI_AdvSimd_Arm64_ConvertToUInt64RoundToZero; - op1 = impSIMDPopStack(); - retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, simdBaseJitType, simdSize); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); break; } diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h index f1a48b2d28127c..06feb2816de5ce 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/jit/hwintrinsiclistarm64.h @@ -37,10 +37,14 @@ HARDWARE_INTRINSIC(Vector64, Ceiling, 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, ConvertToInt32Native, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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, ConvertToInt64Native, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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, ConvertToUInt32Native, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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, ConvertToUInt64Native, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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) @@ -146,10 +150,14 @@ HARDWARE_INTRINSIC(Vector128, Ceiling, 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, ConvertToInt32Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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, ConvertToInt64Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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, ConvertToUInt32Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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, ConvertToUInt64Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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) diff --git a/src/coreclr/jit/hwintrinsiclistxarch.h b/src/coreclr/jit/hwintrinsiclistxarch.h index 07bc2e4838c88c..d3f7c575a86667 100644 --- a/src/coreclr/jit/hwintrinsiclistxarch.h +++ b/src/coreclr/jit/hwintrinsiclistxarch.h @@ -56,10 +56,14 @@ HARDWARE_INTRINSIC(Vector128, Ceiling, 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, ConvertToInt32Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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, ConvertToInt64Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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, ConvertToUInt32Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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, ConvertToUInt64Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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) @@ -162,10 +166,14 @@ HARDWARE_INTRINSIC(Vector256, Ceiling, 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, ConvertToInt32Native, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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, ConvertToInt64Native, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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, ConvertToUInt32Native, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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, ConvertToUInt64Native, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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) @@ -274,11 +282,15 @@ HARDWARE_INTRINSIC(Vector512, CreateScalar, HARDWARE_INTRINSIC(Vector512, CreateScalarUnsafe, 64, 1, true, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector512, CreateSequence, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector512, ConvertToDouble, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector512, ConvertToSingle, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, ConvertToInt32, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToInt32Native, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, ConvertToInt64, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToInt64Native, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToSingle, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, ConvertToUInt32, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToUInt32Native, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, ConvertToUInt64, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToUInt64Native, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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) diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp index fc3c01e4c31d29..553e1bdf78366a 100644 --- a/src/coreclr/jit/hwintrinsicxarch.cpp +++ b/src/coreclr/jit/hwintrinsicxarch.cpp @@ -1440,58 +1440,59 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } - case NI_Vector128_ConvertToInt64: - case NI_Vector256_ConvertToInt64: - case NI_Vector512_ConvertToInt64: + case NI_Vector128_ConvertToInt32: + case NI_Vector256_ConvertToInt32: + case NI_Vector512_ConvertToInt32: { assert(sig->numArgs == 1); - assert(simdBaseType == TYP_DOUBLE); - if (IsBaselineVector512IsaSupportedOpportunistically()) + assert(simdBaseType == TYP_FLOAT); + + if (compOpportunisticallyDependsOn(InstructionSet_SSE41)) { op1 = impSIMDPopStack(); - retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); + retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); } break; } - case NI_Vector128_ConvertToUInt32: - case NI_Vector256_ConvertToUInt32: - case NI_Vector512_ConvertToUInt32: + case NI_Vector128_ConvertToInt32Native: + case NI_Vector256_ConvertToInt32Native: + case NI_Vector512_ConvertToInt32Native: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_FLOAT); - if (IsBaselineVector512IsaSupportedOpportunistically()) - { - op1 = impSIMDPopStack(); - retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); - } + + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); break; } - case NI_Vector128_ConvertToUInt64: - case NI_Vector256_ConvertToUInt64: - case NI_Vector512_ConvertToUInt64: + case NI_Vector128_ConvertToInt64: + case NI_Vector256_ConvertToInt64: + case NI_Vector512_ConvertToInt64: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_DOUBLE); + if (IsBaselineVector512IsaSupportedOpportunistically()) { op1 = impSIMDPopStack(); - retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); + retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); } break; } - case NI_Vector128_ConvertToInt32: - case NI_Vector256_ConvertToInt32: - case NI_Vector512_ConvertToInt32: + case NI_Vector128_ConvertToInt64Native: + case NI_Vector256_ConvertToInt64Native: + case NI_Vector512_ConvertToInt64Native: { assert(sig->numArgs == 1); - assert(simdBaseType == TYP_FLOAT); - if (compOpportunisticallyDependsOn(InstructionSet_SSE41)) + assert(simdBaseType == TYP_DOUBLE); + + if (IsBaselineVector512IsaSupportedOpportunistically()) { op1 = impSIMDPopStack(); - retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); } break; } @@ -1545,6 +1546,65 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_ConvertToUInt32: + case NI_Vector256_ConvertToUInt32: + case NI_Vector512_ConvertToUInt32: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_FLOAT); + + if (IsBaselineVector512IsaSupportedOpportunistically()) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_ConvertToUInt32Native: + case NI_Vector256_ConvertToUInt32Native: + case NI_Vector512_ConvertToUInt32Native: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_FLOAT); + + if (IsBaselineVector512IsaSupportedOpportunistically()) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_ConvertToUInt64: + case NI_Vector256_ConvertToUInt64: + case NI_Vector512_ConvertToUInt64: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_DOUBLE); + if (IsBaselineVector512IsaSupportedOpportunistically()) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_ConvertToUInt64Native: + case NI_Vector256_ConvertToUInt64Native: + case NI_Vector512_ConvertToUInt64Native: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_DOUBLE); + + if (IsBaselineVector512IsaSupportedOpportunistically()) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); + } + break; + } + case NI_Vector128_Create: case NI_Vector256_Create: case NI_Vector512_Create: diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 0ec0d6b9afd3e8..4dc64523217230 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -5164,12 +5164,16 @@ GenTree* Compiler::impPrimitiveNamedIntrinsic(NamedIntrinsic intrinsic, assert(sig->sigInst.classInstCount == 0); var_types retType = JITtype2varType(sig->retType); - assert(varTypeIsArithmetic(retType)); + + if (!varTypeIsArithmetic(retType)) + { + assert((intrinsic == NI_PRIMITIVE_ConvertToInteger) || (intrinsic == NI_PRIMITIVE_ConvertToIntegerNative)); + return nullptr; + } NamedIntrinsic hwintrinsic = NI_Illegal; CORINFO_ARG_LIST_HANDLE args = sig->args; - assert((sig->numArgs == 1) || (sig->numArgs == 2)); CORINFO_CLASS_HANDLE op1ClsHnd; @@ -5180,6 +5184,113 @@ GenTree* Compiler::impPrimitiveNamedIntrinsic(NamedIntrinsic intrinsic, switch (intrinsic) { + case NI_PRIMITIVE_ConvertToInteger: + case NI_PRIMITIVE_ConvertToIntegerNative: + { + assert(sig->sigInst.methInstCount == 1); + assert(varTypeIsFloating(baseType)); + + var_types tgtType = JitType2PreciseVarType(sig->retType); + retType = genActualType(retType); + bool uns = varTypeIsUnsigned(tgtType) && !varTypeIsSmall(tgtType); + + GenTree* res = nullptr; + GenTree* op1 = nullptr; + +#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) + if ((intrinsic == NI_PRIMITIVE_ConvertToIntegerNative) && IsBaselineSimdIsaSupported()) + { + NamedIntrinsic hwIntrinsicId = NI_Illegal; + + if (retType == TYP_INT) + { + if (baseType == TYP_FLOAT) + { + if (!uns) + { + hwIntrinsicId = NI_SSE_ConvertToInt32WithTruncation; + } + else if (IsBaselineVector512IsaSupportedOpportunistically()) + { + hwIntrinsicId = NI_AVX512F_ConvertToUInt32WithTruncation; + } + } + else + { + assert(baseType == TYP_DOUBLE); + + if (!uns) + { + hwIntrinsicId = NI_SSE2_ConvertToInt32WithTruncation; + } + else if (IsBaselineVector512IsaSupportedOpportunistically()) + { + hwIntrinsicId = NI_AVX512F_ConvertToUInt32WithTruncation; + } + } + } +#if defined(TARGET_AMD64) + else + { + assert(retType == TYP_LONG); + + if (baseType == TYP_FLOAT) + { + if (!uns) + { + hwIntrinsicId = NI_SSE_X64_ConvertToInt64WithTruncation; + } + else if (IsBaselineVector512IsaSupportedOpportunistically()) + { + hwIntrinsicId = NI_AVX512F_X64_ConvertToUInt64WithTruncation; + } + } + else + { + assert(baseType == TYP_DOUBLE); + + if (!uns) + { + hwIntrinsicId = NI_SSE2_X64_ConvertToInt64WithTruncation; + } + else if (IsBaselineVector512IsaSupportedOpportunistically()) + { + hwIntrinsicId = NI_AVX512F_X64_ConvertToUInt64WithTruncation; + } + } + } +#endif // TARGET_AMD64 + + if (hwIntrinsicId != NI_Illegal) + { + op1 = impPopStack().val; + res = gtNewSimdHWIntrinsicNode(retType, op1, hwIntrinsicId, baseJitType, 16); + + if (varTypeIsSmall(tgtType)) + { + res = gtNewCastNode(TYP_INT, res, /* uns */ false, tgtType); + } + return res; + } + } +#endif // TARGET_XARCH && FEATURE_HW_INTRINSICS + + op1 = impPopStack().val; + + if (varTypeIsSmall(tgtType)) + { + res = gtNewCastNodeL(retType, op1, /* uns */ false, retType); + res = gtFoldExpr(res); + res = gtNewCastNode(TYP_INT, res, /* uns */ false, tgtType); + } + else + { + res = gtNewCastNodeL(retType, op1, /* uns */ false, tgtType); + } + + return gtFoldExpr(res); + } + case NI_PRIMITIVE_Crc32C: { assert(sig->numArgs == 2); @@ -10072,6 +10183,19 @@ NamedIntrinsic Compiler::lookupPrimitiveFloatNamedIntrinsic(CORINFO_METHOD_HANDL { result = NI_System_Math_Ceiling; } + else if (strncmp(methodName, "ConvertToInteger", 16) == 0) + { + methodName += 16; + + if (methodName[0] == '\0') + { + result = NI_PRIMITIVE_ConvertToInteger; + } + else if (strcmp(methodName, "Native") == 0) + { + result = NI_PRIMITIVE_ConvertToIntegerNative; + } + } else if (strncmp(methodName, "Cos", 3) == 0) { methodName += 3; diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index b3eb292677d809..67eec1059e82e8 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -227,6 +227,8 @@ enum NamedIntrinsic : unsigned short NI_PRIMITIVE_START, + NI_PRIMITIVE_ConvertToInteger, + NI_PRIMITIVE_ConvertToIntegerNative, NI_PRIMITIVE_Crc32C, NI_PRIMITIVE_LeadingZeroCount, NI_PRIMITIVE_Log2, diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 9ffd3b7b011d55..c9b227440d4e5d 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -523,20 +523,23 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return nullptr; } - case NI_VectorT_ConvertToInt64: - case NI_VectorT_ConvertToUInt32: - case NI_VectorT_ConvertToUInt64: + case NI_VectorT_ConvertToInt32: { - if (IsBaselineVector512IsaSupportedOpportunistically()) + if (compOpportunisticallyDependsOn(InstructionSet_SSE41)) { break; } return nullptr; } - case NI_VectorT_ConvertToInt32: + case NI_VectorT_ConvertToInt64: + case NI_VectorT_ConvertToInt64Native: + case NI_VectorT_ConvertToUInt32: + case NI_VectorT_ConvertToUInt32Native: + case NI_VectorT_ConvertToUInt64: + case NI_VectorT_ConvertToUInt64Native: { - if (compOpportunisticallyDependsOn(InstructionSet_SSE41)) + if (IsBaselineVector512IsaSupportedOpportunistically()) { break; } @@ -1175,34 +1178,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, } #if defined(TARGET_XARCH) - - case NI_VectorT_ConvertToInt64: - { - assert(sig->numArgs == 1); - assert(simdBaseType == TYP_DOUBLE); - return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); - } - - case NI_VectorT_ConvertToUInt32: - { - assert(sig->numArgs == 1); - assert(simdBaseType == TYP_FLOAT); - return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); - } - - case NI_VectorT_ConvertToUInt64: - { - assert(sig->numArgs == 1); - assert(simdBaseType == TYP_DOUBLE); - return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); - } - - case NI_VectorT_ConvertToInt32: - { - assert(simdBaseType == TYP_FLOAT); - return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); - } - case NI_VectorT_ConvertToDouble: { assert(sig->numArgs == 1); @@ -1273,43 +1248,71 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, simdSize); } + case NI_VectorT_ConvertToSingle: + { + assert((simdBaseType == TYP_INT) || (simdBaseType == TYP_UINT)); + return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToSingle, simdBaseJitType, + simdSize); + } +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + case NI_VectorT_ConvertToInt32: { + assert(sig->numArgs == 1); assert(simdBaseType == TYP_FLOAT); - return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToInt32RoundToZero, simdBaseJitType, - simdSize); + return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); + } + + case NI_VectorT_ConvertToInt32Native: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_FLOAT); + return gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); } case NI_VectorT_ConvertToInt64: { + assert(sig->numArgs == 1); assert(simdBaseType == TYP_DOUBLE); - return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_Arm64_ConvertToInt64RoundToZero, - simdBaseJitType, simdSize); + return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); } - case NI_VectorT_ConvertToSingle: + case NI_VectorT_ConvertToInt64Native: { - assert((simdBaseType == TYP_INT) || (simdBaseType == TYP_UINT)); - return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToSingle, simdBaseJitType, - simdSize); + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_DOUBLE); + return gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); } case NI_VectorT_ConvertToUInt32: { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_FLOAT); + return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); + } + + case NI_VectorT_ConvertToUInt32Native: + { + assert(sig->numArgs == 1); assert(simdBaseType == TYP_FLOAT); - return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToUInt32RoundToZero, - simdBaseJitType, simdSize); + return gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); } case NI_VectorT_ConvertToUInt64: { + assert(sig->numArgs == 1); assert(simdBaseType == TYP_DOUBLE); - return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_Arm64_ConvertToUInt64RoundToZero, - simdBaseJitType, simdSize); + return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); + } + + case NI_VectorT_ConvertToUInt64Native: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_DOUBLE); + return gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); } -#else -#error Unsupported platform -#endif // !TARGET_XARCH && !TARGET_ARM64 default: { diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index cb8d702be5e71f..911306e712409c 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -224,10 +224,14 @@ SIMD_AS_HWINTRINSIC_ID(VectorT, Ceiling, SIMD_AS_HWINTRINSIC_ID(VectorT, ConditionalSelect, 3, {NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToDouble, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToDouble, NI_VectorT_ConvertToDouble, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt32Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt32Native, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt64Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt64Native}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToSingle, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToSingle, NI_VectorT_ConvertToSingle, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt32Native, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64Native}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(VectorT, CreateBroadcast, ".ctor", 2, {NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(VectorT, CreateSequence, 2, {NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(VectorT, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_Divide, NI_VectorT_Divide}, SimdAsHWIntrinsicFlag::None) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index 5cf07eff0c84ae..dd1d6374bc248f 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -224,10 +224,14 @@ SIMD_AS_HWINTRINSIC_ID(VectorT, Ceiling, SIMD_AS_HWINTRINSIC_ID(VectorT, ConditionalSelect, 3, {NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToDouble, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToDouble, NI_VectorT_ConvertToDouble, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt32Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt32Native, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt64Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt64Native}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToSingle, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToSingle, NI_VectorT_ConvertToSingle, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt32Native, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64Native}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(VectorT, CreateBroadcast, ".ctor", 2, {NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(VectorT, CreateSequence, 2, {NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(VectorT, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_Divide, NI_VectorT_Divide}, SimdAsHWIntrinsicFlag::None) diff --git a/src/libraries/Common/tests/System/GenericMathHelpers.cs b/src/libraries/Common/tests/System/GenericMathHelpers.cs index 277580dc5920d8..a02f8a4e162a6e 100644 --- a/src/libraries/Common/tests/System/GenericMathHelpers.cs +++ b/src/libraries/Common/tests/System/GenericMathHelpers.cs @@ -151,6 +151,12 @@ public static class FloatingPointHelper { public static TSelf Ceiling(TSelf x) => TSelf.Ceiling(x); + public static TInteger ConvertToInteger(TSelf x) + where TInteger : IBinaryInteger => TSelf.ConvertToInteger(x); + + public static TInteger ConvertToIntegerNative(TSelf x) + where TInteger : IBinaryInteger => TSelf.ConvertToIntegerNative(x); + public static TSelf Floor(TSelf x) => TSelf.Floor(x); public static TSelf Round(TSelf x) => TSelf.Round(x); diff --git a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs index 8bf4cb6c534827..531a379cf06e99 100644 --- a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs +++ b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs @@ -235,14 +235,20 @@ public static partial class Vector [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector ConvertToDouble(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector ConvertToInt32(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ConvertToInt32Native(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector ConvertToInt64(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ConvertToInt64Native(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector ConvertToSingle(System.Numerics.Vector value) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector ConvertToSingle(System.Numerics.Vector value) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector ConvertToUInt32(System.Numerics.Vector value) { throw null; } [System.CLSCompliantAttribute(false)] + public static System.Numerics.Vector ConvertToUInt32Native(System.Numerics.Vector value) { throw null; } + [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector ConvertToUInt64(System.Numerics.Vector value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Numerics.Vector ConvertToUInt64Native(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector CreateSequence(T start, T step) { throw null; } public static System.Numerics.Vector Divide(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Divide(System.Numerics.Vector left, T right) { throw null; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs index f2d89445f834ba..189e54dcc1ef74 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs @@ -1117,6 +1117,14 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IFloatingPoint // + /// + public static TInteger ConvertToInteger(decimal value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + + /// + public static TInteger ConvertToIntegerNative(decimal value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + /// int IFloatingPoint.GetExponentByteCount() => sizeof(sbyte); diff --git a/src/libraries/System.Private.CoreLib/src/System/Double.cs b/src/libraries/System.Private.CoreLib/src/System/Double.cs index 71d73546bc1364..04e8269c78f464 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Double.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Double.cs @@ -655,6 +655,16 @@ public static bool IsPow2(double value) [Intrinsic] public static double Ceiling(double x) => Math.Ceiling(x); + /// + [Intrinsic] + public static TInteger ConvertToInteger(double value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + + /// + [Intrinsic] + public static TInteger ConvertToIntegerNative(double value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + /// [Intrinsic] public static double Floor(double x) => Math.Floor(x); diff --git a/src/libraries/System.Private.CoreLib/src/System/Half.cs b/src/libraries/System.Private.CoreLib/src/System/Half.cs index adc7df07932f7f..d4459c5162366f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Half.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Half.cs @@ -1314,6 +1314,14 @@ public static bool IsPow2(Half value) /// public static Half Ceiling(Half x) => (Half)MathF.Ceiling((float)x); + /// + public static TInteger ConvertToInteger(Half value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + + /// + public static TInteger ConvertToIntegerNative(Half value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + /// public static Half Floor(Half x) => (Half)MathF.Floor((float)x); diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs index e36c76007bbdfd..9c92a14f0e75c7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs @@ -16,6 +16,26 @@ public interface IFloatingPoint /// The ceiling of . static virtual TSelf Ceiling(TSelf x) => TSelf.Round(x, digits: 0, MidpointRounding.ToPositiveInfinity); + /// Converts a value to a specified integer type using saturation on overflow + /// The integer type to which is converted. + /// The value to be converted. + /// An instance of created from . + static virtual TInteger ConvertToInteger(TSelf value) + where TInteger : IBinaryInteger + { + return TInteger.CreateSaturating(value); + } + + /// Converts a value to a specified integer type using platform specific behavior on overflow. + /// The integer type to which is converted. + /// The value to be converted. + /// An instance of created from . + static virtual TInteger ConvertToIntegerNative(TSelf value) + where TInteger : IBinaryInteger + { + return TSelf.ConvertToInteger(value); + } + /// Computes the floor of a value. /// The value whose floor is to be computed. /// The floor of . diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs index 5d8bc58bbe26ee..0e968e6fca8f34 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs @@ -325,7 +325,7 @@ public static Vector ConvertToDouble(Vector value) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -342,7 +342,13 @@ public static Vector ConvertToInt32(Vector value) return result; } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + public static Vector ConvertToInt32Native(Vector value) => ConvertToInt32(value); + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -359,6 +365,12 @@ public static Vector ConvertToInt64(Vector value) return result; } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + public static Vector ConvertToInt64Native(Vector value) => ConvertToInt64(value); + /// Converts a to a . /// The vector to convert. /// The converted vector. @@ -396,7 +408,7 @@ public static Vector ConvertToSingle(Vector value) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -414,7 +426,14 @@ public static Vector ConvertToUInt32(Vector value) return result; } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + public static Vector ConvertToUInt32Native(Vector value) => ConvertToUInt32(value); + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -432,6 +451,13 @@ public static Vector ConvertToUInt64(Vector value) return result; } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + public static Vector ConvertToUInt64Native(Vector value) => ConvertToUInt64(value); + /// Creates a new instance where the elements begin at a specified value and which are spaced apart according to another specified value. /// The type of the elements in the vector. /// The value that element 0 will be initialized to. 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 37c39bbc029a24..b314daec02a93c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs @@ -992,6 +992,14 @@ static NFloat IBinaryNumber.AllBitsSet /// public static NFloat Ceiling(NFloat x) => new NFloat(NativeType.Ceiling(x._value)); + /// + public static TInteger ConvertToInteger(NFloat value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + + /// + public static TInteger ConvertToIntegerNative(NFloat value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + /// public static NFloat Floor(NFloat x) => new NFloat(NativeType.Floor(x._value)); 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 3e24e591a32c12..4080b06c92b77b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs @@ -468,7 +468,7 @@ public static unsafe Vector128 ConvertToDouble(Vector128 vector) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -481,7 +481,20 @@ public static unsafe Vector128 ConvertToInt32(Vector128 vector) ); } - /// Converts a to a . + /// Converts a to a platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector128 ConvertToInt32Native(Vector128 vector) + { + return Create( + Vector64.ConvertToInt32Native(vector._lower), + Vector64.ConvertToInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -494,6 +507,19 @@ public static unsafe Vector128 ConvertToInt64(Vector128 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector128 ConvertToInt64Native(Vector128 vector) + { + return Create( + Vector64.ConvertToInt64Native(vector._lower), + Vector64.ConvertToInt64Native(vector._upper) + ); + } + /// Converts a to a . /// The vector to convert. /// The converted vector. @@ -564,7 +590,7 @@ static Vector128 SoftwareFallback(Vector128 vector) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -578,7 +604,21 @@ public static unsafe Vector128 ConvertToUInt32(Vector128 vector) ); } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector128 ConvertToUInt32Native(Vector128 vector) + { + return Create( + Vector64.ConvertToUInt32Native(vector._lower), + Vector64.ConvertToUInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -592,6 +632,20 @@ public static unsafe Vector128 ConvertToUInt64(Vector128 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector128 ConvertToUInt64Native(Vector128 vector) + { + return Create( + Vector64.ConvertToUInt64Native(vector._lower), + Vector64.ConvertToUInt64Native(vector._upper) + ); + } + /// Copies a to a given array. /// The type of the elements in the vector. /// The vector to be copied. 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 1347a082afab97..4d174eef197544 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 @@ -386,7 +386,7 @@ public static Vector256 ConvertToDouble(Vector256 vector) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -399,7 +399,20 @@ public static Vector256 ConvertToInt32(Vector256 vector) ); } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 ConvertToInt32Native(Vector256 vector) + { + return Create( + Vector128.ConvertToInt32Native(vector._lower), + Vector128.ConvertToInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -412,6 +425,19 @@ public static Vector256 ConvertToInt64(Vector256 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 ConvertToInt64Native(Vector256 vector) + { + return Create( + Vector128.ConvertToInt64Native(vector._lower), + Vector128.ConvertToInt64Native(vector._upper) + ); + } + /// Converts a to a . /// The vector to convert. /// The converted vector. @@ -472,7 +498,7 @@ public static Vector256 ConvertToSingle(Vector256 vector) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -486,7 +512,21 @@ public static Vector256 ConvertToUInt32(Vector256 vector) ); } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 ConvertToUInt32Native(Vector256 vector) + { + return Create( + Vector128.ConvertToUInt32Native(vector._lower), + Vector128.ConvertToUInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -500,6 +540,20 @@ public static Vector256 ConvertToUInt64(Vector256 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 ConvertToUInt64Native(Vector256 vector) + { + return Create( + Vector128.ConvertToUInt64Native(vector._lower), + Vector128.ConvertToUInt64Native(vector._upper) + ); + } + /// Copies a to a given array. /// The type of the elements in the vector. /// The vector to be copied. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs index edb84585a987de..d63f12afb64d9c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs @@ -348,7 +348,7 @@ public static Vector512 ConvertToDouble(Vector512 vector) ); } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -361,7 +361,20 @@ public static Vector512 ConvertToInt32(Vector512 vector) ); } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 ConvertToInt32Native(Vector512 vector) + { + return Create( + Vector256.ConvertToInt32Native(vector._lower), + Vector256.ConvertToInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -374,6 +387,19 @@ public static Vector512 ConvertToInt64(Vector512 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 ConvertToInt64Native(Vector512 vector) + { + return Create( + Vector256.ConvertToInt64Native(vector._lower), + Vector256.ConvertToInt64Native(vector._upper) + ); + } + /// Converts a to a . /// The vector to convert. /// The converted vector. @@ -401,7 +427,7 @@ public static Vector512 ConvertToSingle(Vector512 vector) ); } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -415,7 +441,21 @@ public static Vector512 ConvertToUInt32(Vector512 vector) ); } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 ConvertToUInt32Native(Vector512 vector) + { + return Create( + Vector256.ConvertToUInt32Native(vector._lower), + Vector256.ConvertToUInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -429,6 +469,20 @@ public static Vector512 ConvertToUInt64(Vector512 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 ConvertToUInt64Native(Vector512 vector) + { + return Create( + Vector256.ConvertToUInt64Native(vector._lower), + Vector256.ConvertToUInt64Native(vector._upper) + ); + } + /// Copies a to a given array. /// The type of the elements in the vector. /// The vector to be copied. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs index 50e9f697c94f44..04c5e0672a9d1b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs @@ -339,7 +339,7 @@ public static unsafe Vector64 ConvertToDouble(Vector64 vector) return result; } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -357,7 +357,14 @@ public static unsafe Vector64 ConvertToInt32(Vector64 vector) return result; } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector64 ConvertToInt32Native(Vector64 vector) => ConvertToInt32(vector); + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -375,6 +382,13 @@ public static unsafe Vector64 ConvertToInt64(Vector64 vector) return result; } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector64 ConvertToInt64Native(Vector64 vector) => ConvertToInt64(vector); + /// Converts a to a . /// The vector to convert. /// The converted vector. @@ -412,7 +426,7 @@ public static unsafe Vector64 ConvertToSingle(Vector64 vector) return result; } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -431,7 +445,15 @@ public static unsafe Vector64 ConvertToUInt32(Vector64 vector) return result; } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector64 ConvertToUInt32Native(Vector64 vector) => ConvertToUInt32(vector); + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -450,6 +472,14 @@ public static unsafe Vector64 ConvertToUInt64(Vector64 vector) return result; } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector64 ConvertToUInt64Native(Vector64 vector) => ConvertToUInt64(vector); + /// Copies a to a given array. /// The type of the elements in the vector. /// The vector to be copied. diff --git a/src/libraries/System.Private.CoreLib/src/System/Single.cs b/src/libraries/System.Private.CoreLib/src/System/Single.cs index 9cc7c6b56c0adf..8a8a38aa2c0b48 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Single.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Single.cs @@ -650,6 +650,16 @@ public static bool IsPow2(float value) [Intrinsic] public static float Ceiling(float x) => MathF.Ceiling(x); + /// + [Intrinsic] + public static TInteger ConvertToInteger(float value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + + /// + [Intrinsic] + public static TInteger ConvertToIntegerNative(float value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + /// [Intrinsic] public static float Floor(float x) => MathF.Floor(x); diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs index c0fe858d94c608..3b718d224417c7 100644 --- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs +++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs @@ -1341,6 +1341,8 @@ public static void Free(void* ptr) { } public static System.Runtime.InteropServices.NFloat Clamp(System.Runtime.InteropServices.NFloat value, System.Runtime.InteropServices.NFloat min, System.Runtime.InteropServices.NFloat max) { throw null; } public int CompareTo(object? obj) { throw null; } public int CompareTo(System.Runtime.InteropServices.NFloat other) { throw null; } + public static TInteger ConvertToInteger(System.Runtime.InteropServices.NFloat value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + public static TInteger ConvertToIntegerNative(System.Runtime.InteropServices.NFloat value) where TInteger : System.Numerics.IBinaryInteger { throw null; } public static System.Runtime.InteropServices.NFloat CopySign(System.Runtime.InteropServices.NFloat value, System.Runtime.InteropServices.NFloat sign) { throw null; } public static System.Runtime.InteropServices.NFloat Cos(System.Runtime.InteropServices.NFloat x) { throw null; } public static System.Runtime.InteropServices.NFloat Cosh(System.Runtime.InteropServices.NFloat x) { throw null; } diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index c34725ba0bae50..bd7871cdf99065 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -49,14 +49,20 @@ public static partial class Vector128 [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 ConvertToDouble(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 ConvertToInt32(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ConvertToInt32Native(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 ConvertToInt64(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ConvertToInt64Native(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 ConvertToSingle(System.Runtime.Intrinsics.Vector128 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 ConvertToSingle(System.Runtime.Intrinsics.Vector128 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 ConvertToUInt32(System.Runtime.Intrinsics.Vector128 vector) { throw null; } [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector128 ConvertToUInt32Native(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 ConvertToUInt64(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector128 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, T[] destination, int startIndex) { } @@ -384,14 +390,20 @@ public static partial class Vector256 [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 ConvertToDouble(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 ConvertToInt32(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 ConvertToInt32Native(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 ConvertToInt64(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 ConvertToInt64Native(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 ConvertToSingle(System.Runtime.Intrinsics.Vector256 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 ConvertToSingle(System.Runtime.Intrinsics.Vector256 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 ConvertToUInt32(System.Runtime.Intrinsics.Vector256 vector) { throw null; } [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector256 ConvertToUInt32Native(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 ConvertToUInt64(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector256 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, T[] destination, int startIndex) { } @@ -719,14 +731,20 @@ public static partial class Vector512 [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 ConvertToDouble(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 ConvertToInt32(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 ConvertToInt32Native(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 ConvertToInt64(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 ConvertToInt64Native(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 ConvertToSingle(System.Runtime.Intrinsics.Vector512 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 ConvertToSingle(System.Runtime.Intrinsics.Vector512 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 ConvertToUInt32(System.Runtime.Intrinsics.Vector512 vector) { throw null; } [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector512 ConvertToUInt32Native(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 ConvertToUInt64(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector512 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, T[] destination, int startIndex) { } @@ -1050,14 +1068,20 @@ public static partial class Vector64 [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 ConvertToDouble(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 ConvertToInt32(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ConvertToInt32Native(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 ConvertToInt64(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ConvertToInt64Native(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 ConvertToSingle(System.Runtime.Intrinsics.Vector64 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 ConvertToSingle(System.Runtime.Intrinsics.Vector64 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 ConvertToUInt32(System.Runtime.Intrinsics.Vector64 vector) { throw null; } [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector64 ConvertToUInt32Native(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 ConvertToUInt64(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector64 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, T[] destination, int startIndex) { } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs index 0ebed660f33689..95cf6d16b66171 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs @@ -5,6 +5,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -4872,5 +4873,108 @@ public void Log2SingleTest(float value, float expectedResult, float variance) Vector128 actualResult = Vector128.Log2(Vector128.Create(value)); AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Create(variance)); } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32Test() + { + Assert.Equal(Vector128.Create(int.MinValue), Vector128.ConvertToInt32(Vector128.Create(float.MinValue))); + Assert.Equal(Vector128.Create(2), Vector128.ConvertToInt32(Vector128.Create(2.6f))); + Assert.Equal(Vector128.Create(int.MaxValue), Vector128.ConvertToInt32(Vector128.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32NativeTest() + { + if (Vector128.IsHardwareAccelerated && Sse2.IsSupported) + { + Assert.Equal(Vector128.Create(int.MinValue), Vector128.ConvertToInt32Native(Vector128.Create(float.MaxValue))); + } + else + { + Assert.Equal(Vector128.Create(int.MaxValue), Vector128.ConvertToInt32Native(Vector128.Create(float.MaxValue))); + } + Assert.Equal(Vector128.Create(int.MinValue), Vector128.ConvertToInt32Native(Vector128.Create(float.MinValue))); + Assert.Equal(Vector128.Create(2), Vector128.ConvertToInt32Native(Vector128.Create(2.6f))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64Test() + { + Assert.Equal(Vector128.Create(long.MinValue), Vector128.ConvertToInt64(Vector128.Create(double.MinValue))); + Assert.Equal(Vector128.Create(2L), Vector128.ConvertToInt64(Vector128.Create(2.6))); + Assert.Equal(Vector128.Create(long.MaxValue), Vector128.ConvertToInt64(Vector128.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512DQ.VL.IsSupported) + { + Assert.Equal(Vector128.Create(long.MinValue), Vector128.ConvertToInt64Native(Vector128.Create(double.MaxValue))); + } + else + { + Assert.Equal(Vector128.Create(long.MaxValue), Vector128.ConvertToInt64Native(Vector128.Create(double.MaxValue))); + } + + Assert.Equal(Vector128.Create(long.MinValue), Vector128.ConvertToInt64Native(Vector128.Create(double.MinValue))); + Assert.Equal(Vector128.Create(2L), Vector128.ConvertToInt64Native(Vector128.Create(2.6))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32Test() + { + Assert.Equal(Vector128.Create(uint.MinValue), Vector128.ConvertToUInt32(Vector128.Create(float.MinValue))); + Assert.Equal(Vector128.Create(2u), Vector128.ConvertToUInt32(Vector128.Create(2.6f))); + Assert.Equal(Vector128.Create(uint.MaxValue), Vector128.ConvertToUInt32(Vector128.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512F.VL.IsSupported) + { + Assert.Equal(Vector128.Create(uint.MaxValue), Vector128.ConvertToUInt32Native(Vector128.Create(float.MinValue))); + } + else + { + Assert.Equal(Vector128.Create(uint.MinValue), Vector128.ConvertToUInt32Native(Vector128.Create(float.MinValue))); + } + + Assert.Equal(Vector128.Create(2u), Vector128.ConvertToUInt32Native(Vector128.Create(2.6f))); + Assert.Equal(Vector128.Create(uint.MaxValue), Vector128.ConvertToUInt32Native(Vector128.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64Test() + { + Assert.Equal(Vector128.Create(ulong.MinValue), Vector128.ConvertToUInt64(Vector128.Create(double.MinValue))); + Assert.Equal(Vector128.Create(2UL), Vector128.ConvertToUInt64(Vector128.Create(2.6))); + Assert.Equal(Vector128.Create(ulong.MaxValue), Vector128.ConvertToUInt64(Vector128.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512DQ.VL.IsSupported) + { + Assert.Equal(Vector128.Create(ulong.MaxValue), Vector128.ConvertToUInt64Native(Vector128.Create(double.MinValue))); + } + else + { + Assert.Equal(Vector128.Create(ulong.MinValue), Vector128.ConvertToUInt64Native(Vector128.Create(double.MinValue))); + } + + Assert.Equal(Vector128.Create(2UL), Vector128.ConvertToUInt64Native(Vector128.Create(2.6))); + Assert.Equal(Vector128.Create(ulong.MaxValue), Vector128.ConvertToUInt64Native(Vector128.Create(double.MaxValue))); + } } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs index d658ca08b17b32..a5559d43c81505 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs @@ -4,6 +4,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -5887,5 +5888,108 @@ public void Log2SingleTest(float value, float expectedResult, float variance) Vector256 actualResult = Vector256.Log2(Vector256.Create(value)); AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Create(variance)); } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32Test() + { + Assert.Equal(Vector256.Create(int.MinValue), Vector256.ConvertToInt32(Vector256.Create(float.MinValue))); + Assert.Equal(Vector256.Create(2), Vector256.ConvertToInt32(Vector256.Create(2.6f))); + Assert.Equal(Vector256.Create(int.MaxValue), Vector256.ConvertToInt32(Vector256.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32NativeTest() + { + if (Vector128.IsHardwareAccelerated && Sse2.IsSupported) + { + Assert.Equal(Vector256.Create(int.MinValue), Vector256.ConvertToInt32Native(Vector256.Create(float.MaxValue))); + } + else + { + Assert.Equal(Vector256.Create(int.MaxValue), Vector256.ConvertToInt32Native(Vector256.Create(float.MaxValue))); + } + Assert.Equal(Vector256.Create(int.MinValue), Vector256.ConvertToInt32Native(Vector256.Create(float.MinValue))); + Assert.Equal(Vector256.Create(2), Vector256.ConvertToInt32Native(Vector256.Create(2.6f))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64Test() + { + Assert.Equal(Vector256.Create(long.MinValue), Vector256.ConvertToInt64(Vector256.Create(double.MinValue))); + Assert.Equal(Vector256.Create(2L), Vector256.ConvertToInt64(Vector256.Create(2.6))); + Assert.Equal(Vector256.Create(long.MaxValue), Vector256.ConvertToInt64(Vector256.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512DQ.VL.IsSupported) + { + Assert.Equal(Vector256.Create(long.MinValue), Vector256.ConvertToInt64Native(Vector256.Create(double.MaxValue))); + } + else + { + Assert.Equal(Vector256.Create(long.MaxValue), Vector256.ConvertToInt64Native(Vector256.Create(double.MaxValue))); + } + + Assert.Equal(Vector256.Create(long.MinValue), Vector256.ConvertToInt64Native(Vector256.Create(double.MinValue))); + Assert.Equal(Vector256.Create(2L), Vector256.ConvertToInt64Native(Vector256.Create(2.6))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32Test() + { + Assert.Equal(Vector256.Create(uint.MinValue), Vector256.ConvertToUInt32(Vector256.Create(float.MinValue))); + Assert.Equal(Vector256.Create(2u), Vector256.ConvertToUInt32(Vector256.Create(2.6f))); + Assert.Equal(Vector256.Create(uint.MaxValue), Vector256.ConvertToUInt32(Vector256.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512F.VL.IsSupported) + { + Assert.Equal(Vector256.Create(uint.MaxValue), Vector256.ConvertToUInt32Native(Vector256.Create(float.MinValue))); + } + else + { + Assert.Equal(Vector256.Create(uint.MinValue), Vector256.ConvertToUInt32Native(Vector256.Create(float.MinValue))); + } + + Assert.Equal(Vector256.Create(2u), Vector256.ConvertToUInt32Native(Vector256.Create(2.6f))); + Assert.Equal(Vector256.Create(uint.MaxValue), Vector256.ConvertToUInt32Native(Vector256.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64Test() + { + Assert.Equal(Vector256.Create(ulong.MinValue), Vector256.ConvertToUInt64(Vector256.Create(double.MinValue))); + Assert.Equal(Vector256.Create(2UL), Vector256.ConvertToUInt64(Vector256.Create(2.6))); + Assert.Equal(Vector256.Create(ulong.MaxValue), Vector256.ConvertToUInt64(Vector256.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512DQ.VL.IsSupported) + { + Assert.Equal(Vector256.Create(ulong.MaxValue), Vector256.ConvertToUInt64Native(Vector256.Create(double.MinValue))); + } + else + { + Assert.Equal(Vector256.Create(ulong.MinValue), Vector256.ConvertToUInt64Native(Vector256.Create(double.MinValue))); + } + + Assert.Equal(Vector256.Create(2UL), Vector256.ConvertToUInt64Native(Vector256.Create(2.6))); + Assert.Equal(Vector256.Create(ulong.MaxValue), Vector256.ConvertToUInt64Native(Vector256.Create(double.MaxValue))); + } } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs index 4b4f9e2d4692aa..c01f88facbf574 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs @@ -4,6 +4,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -5320,5 +5321,108 @@ public void Log2SingleTest(float value, float expectedResult, float variance) Vector512 actualResult = Vector512.Log2(Vector512.Create(value)); AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Create(variance)); } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32Test() + { + Assert.Equal(Vector512.Create(int.MinValue), Vector512.ConvertToInt32(Vector512.Create(float.MinValue))); + Assert.Equal(Vector512.Create(2), Vector512.ConvertToInt32(Vector512.Create(2.6f))); + Assert.Equal(Vector512.Create(int.MaxValue), Vector512.ConvertToInt32(Vector512.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32NativeTest() + { + if (Vector128.IsHardwareAccelerated && Sse2.IsSupported) + { + Assert.Equal(Vector512.Create(int.MinValue), Vector512.ConvertToInt32Native(Vector512.Create(float.MaxValue))); + } + else + { + Assert.Equal(Vector512.Create(int.MaxValue), Vector512.ConvertToInt32Native(Vector512.Create(float.MaxValue))); + } + Assert.Equal(Vector512.Create(int.MinValue), Vector512.ConvertToInt32Native(Vector512.Create(float.MinValue))); + Assert.Equal(Vector512.Create(2), Vector512.ConvertToInt32Native(Vector512.Create(2.6f))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64Test() + { + Assert.Equal(Vector512.Create(long.MinValue), Vector512.ConvertToInt64(Vector512.Create(double.MinValue))); + Assert.Equal(Vector512.Create(2L), Vector512.ConvertToInt64(Vector512.Create(2.6))); + Assert.Equal(Vector512.Create(long.MaxValue), Vector512.ConvertToInt64(Vector512.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512DQ.VL.IsSupported) + { + Assert.Equal(Vector512.Create(long.MinValue), Vector512.ConvertToInt64Native(Vector512.Create(double.MaxValue))); + } + else + { + Assert.Equal(Vector512.Create(long.MaxValue), Vector512.ConvertToInt64Native(Vector512.Create(double.MaxValue))); + } + + Assert.Equal(Vector512.Create(long.MinValue), Vector512.ConvertToInt64Native(Vector512.Create(double.MinValue))); + Assert.Equal(Vector512.Create(2L), Vector512.ConvertToInt64Native(Vector512.Create(2.6))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32Test() + { + Assert.Equal(Vector512.Create(uint.MinValue), Vector512.ConvertToUInt32(Vector512.Create(float.MinValue))); + Assert.Equal(Vector512.Create(2u), Vector512.ConvertToUInt32(Vector512.Create(2.6f))); + Assert.Equal(Vector512.Create(uint.MaxValue), Vector512.ConvertToUInt32(Vector512.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512F.VL.IsSupported) + { + Assert.Equal(Vector512.Create(uint.MaxValue), Vector512.ConvertToUInt32Native(Vector512.Create(float.MinValue))); + } + else + { + Assert.Equal(Vector512.Create(uint.MinValue), Vector512.ConvertToUInt32Native(Vector512.Create(float.MinValue))); + } + + Assert.Equal(Vector512.Create(2u), Vector512.ConvertToUInt32Native(Vector512.Create(2.6f))); + Assert.Equal(Vector512.Create(uint.MaxValue), Vector512.ConvertToUInt32Native(Vector512.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64Test() + { + Assert.Equal(Vector512.Create(ulong.MinValue), Vector512.ConvertToUInt64(Vector512.Create(double.MinValue))); + Assert.Equal(Vector512.Create(2UL), Vector512.ConvertToUInt64(Vector512.Create(2.6))); + Assert.Equal(Vector512.Create(ulong.MaxValue), Vector512.ConvertToUInt64(Vector512.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512DQ.VL.IsSupported) + { + Assert.Equal(Vector512.Create(ulong.MaxValue), Vector512.ConvertToUInt64Native(Vector512.Create(double.MinValue))); + } + else + { + Assert.Equal(Vector512.Create(ulong.MinValue), Vector512.ConvertToUInt64Native(Vector512.Create(double.MinValue))); + } + + Assert.Equal(Vector512.Create(2UL), Vector512.ConvertToUInt64Native(Vector512.Create(2.6))); + Assert.Equal(Vector512.Create(ulong.MaxValue), Vector512.ConvertToUInt64Native(Vector512.Create(double.MaxValue))); + } } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs index 69f37520ad735a..3c2d8064681fe1 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs @@ -4,6 +4,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -4287,5 +4288,77 @@ public void Log2SingleTest(float value, float expectedResult, float variance) Vector64 actualResult = Vector64.Log2(Vector64.Create(value)); AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Create(variance)); } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32Test() + { + Assert.Equal(Vector64.Create(int.MinValue), Vector64.ConvertToInt32(Vector64.Create(float.MinValue))); + Assert.Equal(Vector64.Create(2), Vector64.ConvertToInt32(Vector64.Create(2.6f))); + Assert.Equal(Vector64.Create(int.MaxValue), Vector64.ConvertToInt32(Vector64.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32NativeTest() + { + Assert.Equal(Vector64.Create(int.MinValue), Vector64.ConvertToInt32Native(Vector64.Create(float.MinValue))); + Assert.Equal(Vector64.Create(2), Vector64.ConvertToInt32Native(Vector64.Create(2.6f))); + Assert.Equal(Vector64.Create(int.MaxValue), Vector64.ConvertToInt32Native(Vector64.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64Test() + { + Assert.Equal(Vector64.Create(long.MinValue), Vector64.ConvertToInt64(Vector64.Create(double.MinValue))); + Assert.Equal(Vector64.Create(2L), Vector64.ConvertToInt64(Vector64.Create(2.6))); + Assert.Equal(Vector64.Create(long.MaxValue), Vector64.ConvertToInt64(Vector64.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64NativeTest() + { + Assert.Equal(Vector64.Create(long.MinValue), Vector64.ConvertToInt64Native(Vector64.Create(double.MinValue))); + Assert.Equal(Vector64.Create(2L), Vector64.ConvertToInt64Native(Vector64.Create(2.6))); + Assert.Equal(Vector64.Create(long.MaxValue), Vector64.ConvertToInt64Native(Vector64.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32Test() + { + Assert.Equal(Vector64.Create(uint.MinValue), Vector64.ConvertToUInt32(Vector64.Create(float.MinValue))); + Assert.Equal(Vector64.Create(2u), Vector64.ConvertToUInt32(Vector64.Create(2.6f))); + Assert.Equal(Vector64.Create(uint.MaxValue), Vector64.ConvertToUInt32(Vector64.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32NativeTest() + { + Assert.Equal(Vector64.Create(uint.MinValue), Vector64.ConvertToUInt32Native(Vector64.Create(float.MinValue))); + Assert.Equal(Vector64.Create(2u), Vector64.ConvertToUInt32Native(Vector64.Create(2.6f))); + Assert.Equal(Vector64.Create(uint.MaxValue), Vector64.ConvertToUInt32Native(Vector64.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64Test() + { + Assert.Equal(Vector64.Create(ulong.MinValue), Vector64.ConvertToUInt64(Vector64.Create(double.MinValue))); + Assert.Equal(Vector64.Create(2UL), Vector64.ConvertToUInt64(Vector64.Create(2.6))); + Assert.Equal(Vector64.Create(ulong.MaxValue), Vector64.ConvertToUInt64(Vector64.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64NativeTest() + { + Assert.Equal(Vector64.Create(ulong.MinValue), Vector64.ConvertToUInt64Native(Vector64.Create(double.MinValue))); + Assert.Equal(Vector64.Create(2UL), Vector64.ConvertToUInt64Native(Vector64.Create(2.6))); + Assert.Equal(Vector64.Create(ulong.MaxValue), Vector64.ConvertToUInt64Native(Vector64.Create(double.MaxValue))); + } } } diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 14575b820c33ab..a3f2a4b07e2f48 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -4,6 +4,8 @@ // Changes to this file must follow the https://aka.ms/api-review process. // ------------------------------------------------------------------------------ +using System.Numerics; + namespace Microsoft.Win32.SafeHandles { public abstract partial class CriticalHandleMinusOneIsInvalid : System.Runtime.InteropServices.CriticalHandle @@ -1985,6 +1987,8 @@ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, S public static int Compare(decimal d1, decimal d2) { throw null; } public int CompareTo(decimal value) { throw null; } public int CompareTo(object? value) { throw null; } + public static TInteger ConvertToInteger(decimal value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + public static TInteger ConvertToIntegerNative(decimal value) where TInteger : System.Numerics.IBinaryInteger { throw null; } public static decimal CopySign(decimal value, decimal sign) { throw null; } public static decimal CreateChecked(TOther value) where TOther : System.Numerics.INumberBase { throw null; } public static decimal CreateSaturating(TOther value) where TOther : System.Numerics.INumberBase { throw null; } @@ -2259,6 +2263,8 @@ public DivideByZeroException(string? message, System.Exception? innerException) public static double Clamp(double value, double min, double max) { throw null; } public int CompareTo(double value) { throw null; } public int CompareTo(object? value) { throw null; } + public static TInteger ConvertToInteger(double value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + public static TInteger ConvertToIntegerNative(double value) where TInteger : System.Numerics.IBinaryInteger { throw null; } public static double CopySign(double value, double sign) { throw null; } public static double Cos(double x) { throw null; } public static double Cosh(double x) { throw null; } @@ -2881,6 +2887,8 @@ public enum GCNotificationStatus public static System.Half Clamp(System.Half value, System.Half min, System.Half max) { throw null; } public int CompareTo(System.Half other) { throw null; } public int CompareTo(object? obj) { throw null; } + public static TInteger ConvertToInteger(System.Half value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + public static TInteger ConvertToIntegerNative(System.Half value) where TInteger : System.Numerics.IBinaryInteger { throw null; } public static System.Half CopySign(System.Half value, System.Half sign) { throw null; } public static System.Half Cos(System.Half x) { throw null; } public static System.Half Cosh(System.Half x) { throw null; } @@ -4998,6 +5006,8 @@ public SerializableAttribute() { } public static float Clamp(float value, float min, float max) { throw null; } public int CompareTo(object? value) { throw null; } public int CompareTo(float value) { throw null; } + public static TInteger ConvertToInteger(float value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + public static TInteger ConvertToIntegerNative(float value) where TInteger : System.Numerics.IBinaryInteger { throw null; } public static float CopySign(float value, float sign) { throw null; } public static float Cos(float x) { throw null; } public static float Cosh(float x) { throw null; } @@ -10809,6 +10819,8 @@ public partial interface IFloatingPointIeee754 : System.IComparable, Syst public partial interface IFloatingPoint : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointConstants, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IFloatingPoint? { static virtual TSelf Ceiling(TSelf x) { throw null; } + static virtual TInteger ConvertToInteger(TSelf value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + static virtual TInteger ConvertToIntegerNative(TSelf value) where TInteger : System.Numerics.IBinaryInteger { throw null; } static virtual TSelf Floor(TSelf x) { throw null; } int GetExponentByteCount(); int GetExponentShortestBitLength(); diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs index 05e71be7b325c2..d829eb1199d4d7 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Tests @@ -356,6 +357,172 @@ public static void op_InequalityTest() // IFloatingPoint // + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public static void ConvertToIntegerTest() + { + // Signed Values + + Assert.Equal(0, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(Int128.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToInteger(double.MinValue)); + + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + + Assert.Equal(-1, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(int.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(Int128.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(nint.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(-1, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + + // Unsigned Values + + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(UInt128.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + + Assert.Equal(byte.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(ushort.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(UInt128.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public static void ConvertToIntegerNativeTest() + { + // Signed Values + + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(Int128.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to int is natively supported and returns 0x8000_0000 + // * Conversion to long is natively supported on 64-bit and returns 0x8000_0000_0000_0000 + + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + + if (Environment.Is64BitProcess) + { + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + else + { + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + } + else + { + Assert.Equal(-1, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(int.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(nint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(-1, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + Assert.Equal(Int128.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + + // Unsigned Values + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to uint is natively supported w/ Avx512 and returns 0xFFFF_FFFF + // * Conversion to ulong is natively supported on 64-bit w/ Avx512 and returns 0xFFFF_FFFF_FFFF_FFFF + + if (Avx512F.IsSupported) + { + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + } + else + { + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + } + + if (Environment.Is64BitProcess && Avx512F.IsSupported) + { + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + } + else + { + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + } + } + else + { + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + } + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(UInt128.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to uint is natively supported w/ Avx512 and returns 0xFFFF_FFFF + // * Conversion to ulong is natively supported on 64-bit w/ Avx512 and returns 0xFFFF_FFFF_FFFF_FFFF + + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + else + { + Assert.Equal(byte.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(ushort.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(UInt128.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + [Fact] public static void GetExponentByteCountTest() { @@ -1055,7 +1222,7 @@ public static void CreateCheckedFromDecimalTest() AssertBitwiseEqual(-0.0, NumberBaseHelper.CreateChecked(-0.0m)); AssertBitwiseEqual(+0.0, NumberBaseHelper.CreateChecked(+0.0m)); AssertBitwiseEqual(+1.0, NumberBaseHelper.CreateChecked(+1.0m)); - AssertBitwiseEqual(+79228162514264337593543950335.0, NumberBaseHelper.CreateChecked(decimal.MaxValue)); + AssertBitwiseEqual(+79228162514264337593543950335.0, NumberBaseHelper.CreateChecked(decimal.MaxValue)); } [Fact] diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs index a6637de7f7e2a3..21a4ba2cd77a11 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Tests @@ -356,6 +357,172 @@ public static void op_InequalityTest() // IFloatingPoint // + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public static void ConvertToIntegerTest() + { + // Signed Values + + Assert.Equal(0, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(Int128.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToInteger(float.MinValue)); + + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + + Assert.Equal(-1, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(int.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(Int128.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(nint.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(-1, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + + // Unsigned Values + + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(UInt128.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + + Assert.Equal(byte.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(ushort.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(new UInt128(0xFFFF_FF00_0000_0000, 0x0000_0000_0000_0000), FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public static void ConvertToIntegerNativeTest() + { + // Signed Values + + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(Int128.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to int is natively supported and returns 0x8000_0000 + // * Conversion to long is natively supported on 64-bit and returns 0x8000_0000_0000_0000 + + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + + if (Environment.Is64BitProcess) + { + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + else + { + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + } + else + { + Assert.Equal(-1, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(int.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(nint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(-1, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + Assert.Equal(Int128.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + + // Unsigned Values + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to uint is natively supported w/ Avx512 and returns 0xFFFF_FFFF + // * Conversion to ulong is natively supported on 64-bit w/ Avx512 and returns 0xFFFF_FFFF_FFFF_FFFF + + if (Avx512F.IsSupported) + { + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + } + else + { + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + } + + if (Environment.Is64BitProcess && Avx512F.IsSupported) + { + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + } + else + { + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + } + } + else + { + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + } + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(UInt128.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to uint is natively supported w/ Avx512 and returns 0xFFFF_FFFF + // * Conversion to ulong is natively supported on 64-bit w/ Avx512 and returns 0xFFFF_FFFF_FFFF_FFFF + + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + else + { + Assert.Equal(byte.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(ushort.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(new UInt128(0xFFFF_FF00_0000_0000, 0x0000_0000_0000_0000), FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + [Fact] public static void GetExponentByteCountTest() { From a2bd5830ce09cd81d834afd5571bc6c9e5ad879b Mon Sep 17 00:00:00 2001 From: Tyler Brinkley Date: Tue, 23 Apr 2024 20:17:07 -0500 Subject: [PATCH 077/248] Make mutable generic collection interfaces implement read-only collection interfaces (#95830) * Make mutable generic collection interfaces implement read-only collection interfaces * More updates * Fix build * Update refs * Add DIM's to ref also * fixes * Try to fix arrays * Moved dim's to the end of the interfaces. Made the tests support .NET Framework 4.8. * Small fix * Small fix * Fix build * Fix * Cleanup * Incorporate #96672 * Check the correct inheritanceDepth in vm/array.cpp --------- Co-authored-by: Eirik Tsarpalis Co-authored-by: Tanner Gooding --- .../src/System/Array.CoreCLR.cs | 2 +- src/coreclr/vm/array.cpp | 19 +- .../System/Collections/CollectionAsserts.cs | 152 +++++++++++++++ .../Collections/ICollection.Generic.Tests.cs | 43 +++-- .../Collections/IDictionary.Generic.Tests.cs | 180 +++++++++++++++--- .../System/Collections/IList.Generic.Tests.cs | 75 ++++---- .../System/Collections/ISet.Generic.Tests.cs | 53 +++--- .../Generic/CollectionExtensionsTests.cs | 12 ++ .../System/Collections/Generic/ICollection.cs | 6 +- .../System/Collections/Generic/IDictionary.cs | 22 ++- .../src/System/Collections/Generic/IList.cs | 6 +- .../src/System/Collections/Generic/ISet.cs | 35 +++- .../System.Runtime/ref/System.Runtime.cs | 49 +++-- 13 files changed, 490 insertions(+), 164 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Array.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Array.CoreCLR.cs index de7b3021c458fe..74e07398481681 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Array.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Array.CoreCLR.cs @@ -694,7 +694,7 @@ public ArrayInitializeCache(RuntimeType arrayType) // it for type and executes it. // // The "T" will reflect the interface used to invoke the method. The actual runtime "this" will be - // array that is castable to "T[]" (i.e. for primitivs and valuetypes, it will be exactly + // array that is castable to "T[]" (i.e. for primitives and valuetypes, it will be exactly // "T[]" - for orefs, it may be a "U[]" where U derives from T.) //---------------------------------------------------------------------------------------- internal sealed class SZArrayHelper diff --git a/src/coreclr/vm/array.cpp b/src/coreclr/vm/array.cpp index ffb6e6def99ce0..e1e2b31e4df647 100644 --- a/src/coreclr/vm/array.cpp +++ b/src/coreclr/vm/array.cpp @@ -1210,29 +1210,14 @@ MethodDesc* GetActualImplementationForArrayGenericIListOrIReadOnlyListMethod(Met } CONTRACTL_END - int slot = pItfcMeth->GetSlot(); - - // We need to pick the right starting method depending on the depth of the inheritance chain - static const BinderMethodID startingMethod[] = { - METHOD__SZARRAYHELPER__GETENUMERATOR, // First method of IEnumerable`1 - METHOD__SZARRAYHELPER__GET_COUNT, // First method of ICollection`1/IReadOnlyCollection`1 - METHOD__SZARRAYHELPER__GET_ITEM // First method of IList`1/IReadOnlyList`1 - }; - // Subtract one for the non-generic IEnumerable that the generic enumerable inherits from unsigned int inheritanceDepth = pItfcMeth->GetMethodTable()->GetNumInterfaces() - 1; - PREFIX_ASSUME(0 <= inheritanceDepth && inheritanceDepth < ARRAY_SIZE(startingMethod)); - - MethodDesc *pGenericImplementor = CoreLibBinder::GetMethod((BinderMethodID)(startingMethod[inheritanceDepth] + slot)); - // The most common reason for this assert is that the order of the SZArrayHelper methods in - // corelib.h does not match the order they are implemented on the generic interfaces. - _ASSERTE(pGenericImplementor == MemberLoader::FindMethodByName(g_pSZArrayHelperClass, pItfcMeth->GetName())); + MethodDesc *pGenericImplementor = MemberLoader::FindMethodByName(g_pSZArrayHelperClass, pItfcMeth->GetName()); // OPTIMIZATION: For any method other than GetEnumerator(), we can safely substitute // "Object" for reference-type theT's. This causes fewer methods to be instantiated. - if (startingMethod[inheritanceDepth] != METHOD__SZARRAYHELPER__GETENUMERATOR && - !theT.IsValueType()) + if (inheritanceDepth != 0 && !theT.IsValueType()) { theT = TypeHandle(g_pObjectClass); } diff --git a/src/libraries/Common/tests/System/Collections/CollectionAsserts.cs b/src/libraries/Common/tests/System/Collections/CollectionAsserts.cs index 2de26be1737fdc..1e76d40ebb411f 100644 --- a/src/libraries/Common/tests/System/Collections/CollectionAsserts.cs +++ b/src/libraries/Common/tests/System/Collections/CollectionAsserts.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Collections.Generic; using System.Linq; using Xunit; @@ -9,6 +10,151 @@ namespace System.Collections.Tests { internal static class CollectionAsserts { + public static void HasCount(ICollection collection, int count) + { + Assert.Equal(count, collection.Count); +#if !NETFRAMEWORK + IReadOnlyCollection readOnlyCollection = collection; + Assert.Equal(count, readOnlyCollection.Count); +#endif + } + + public static void EqualAt(IList list, int index, T expected) + { + Assert.Equal(expected, list[index]); +#if !NETFRAMEWORK + IReadOnlyList readOnlyList = list; + Assert.Equal(expected, readOnlyList[index]); +#endif + } + + public static void NotEqualAt(IList list, int index, T expected) + { + Assert.NotEqual(expected, list[index]); +#if !NETFRAMEWORK + IReadOnlyList readOnlyList = list; + Assert.NotEqual(expected, readOnlyList[index]); +#endif + } + + public static void ThrowsElementAt(IList list, int index, Type exceptionType) + { + Assert.Throws(exceptionType, () => list[index]); +#if !NETFRAMEWORK + IReadOnlyList readOnlyList = list; + Assert.Throws(exceptionType, () => readOnlyList[index]); +#endif + } + + public static void ElementAtSucceeds(IList list, int index) + { + T result = list[index]; +#if !NETFRAMEWORK + IReadOnlyList readOnlyList = list; + Assert.Equal(result, readOnlyList[index]); +#endif + } + + public static void EqualAt(IDictionary dictionary, TKey key, TValue expected) + { + Assert.Equal(expected, dictionary[key]); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + Assert.Equal(expected, readOnlyDictionary[key]); +#endif + } + + public static void ContainsKey(IDictionary dictionary, TKey key, bool expected) + { + Assert.Equal(expected, dictionary.ContainsKey(key)); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + Assert.Equal(expected, readOnlyDictionary.ContainsKey(key)); +#endif + } + + public static void TryGetValue(IDictionary dictionary, TKey key, bool expected, TValue expectedValue = default) + { + Assert.Equal(expected, dictionary.TryGetValue(key, out TValue value)); + if (expected) + { + Assert.Equal(expectedValue, value); + } +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + Assert.Equal(expected, readOnlyDictionary.TryGetValue(key, out value)); + if (expected) + { + Assert.Equal(expectedValue, value); + } +#endif + } + + public static void Contains(ISet set, T expected) + { + Assert.True(set.Contains(expected)); +#if !NETFRAMEWORK + ICollection collection = set; + Assert.True(collection.Contains(expected)); + IReadOnlySet readOnlySet = set; + Assert.True(readOnlySet.Contains(expected)); +#endif + } + + public static void IsProperSubsetOf(ISet set, IEnumerable enumerable, bool expected) + { + Assert.Equal(expected, set.IsProperSubsetOf(enumerable)); +#if !NETFRAMEWORK + IReadOnlySet readOnlySet = set; + Assert.Equal(expected, readOnlySet.IsProperSubsetOf(enumerable)); +#endif + } + + public static void IsProperSupersetOf(ISet set, IEnumerable enumerable, bool expected) + { + Assert.Equal(expected, set.IsProperSupersetOf(enumerable)); +#if !NETFRAMEWORK + IReadOnlySet readOnlySet = set; + Assert.Equal(expected, readOnlySet.IsProperSupersetOf(enumerable)); +#endif + } + + public static void IsSubsetOf(ISet set, IEnumerable enumerable, bool expected) + { + Assert.Equal(expected, set.IsSubsetOf(enumerable)); +#if !NETFRAMEWORK + IReadOnlySet readOnlySet = set; + Assert.Equal(expected, readOnlySet.IsSubsetOf(enumerable)); +#endif + } + + public static void IsSupersetOf(ISet set, IEnumerable enumerable, bool expected) + { + Assert.Equal(expected, set.IsSupersetOf(enumerable)); +#if !NETFRAMEWORK + IReadOnlySet readOnlySet = set; + Assert.Equal(expected, readOnlySet.IsSupersetOf(enumerable)); +#endif + } + + public static void Overlaps(ISet set, IEnumerable enumerable, bool expected) + { + Assert.Equal(expected, set.Overlaps(enumerable)); +#if !NETFRAMEWORK + IReadOnlySet readOnlySet = set; + Assert.Equal(expected, readOnlySet.Overlaps(enumerable)); +#endif + } + + public static void SetEquals(ISet set, IEnumerable enumerable, bool expected) + { + Assert.Equal(expected, set.SetEquals(enumerable)); +#if !NETFRAMEWORK + IReadOnlySet readOnlySet = set; + Assert.Equal(expected, readOnlySet.SetEquals(enumerable)); +#endif + } + public static void Equal(ICollection expected, ICollection actual) { Assert.Equal(expected == null, actual == null); @@ -43,6 +189,12 @@ public static void Equal(ICollection expected, ICollection actual) return; } Assert.Equal(expected.Count, actual.Count); +#if !NETFRAMEWORK + IReadOnlyCollection readOnlyExpected = expected; + Assert.Equal(expected.Count, readOnlyExpected.Count); + IReadOnlyCollection readOnlyActual = actual; + Assert.Equal(actual.Count, readOnlyActual.Count); +#endif IEnumerator e = expected.GetEnumerator(); IEnumerator a = actual.GetEnumerator(); while (e.MoveNext()) diff --git a/src/libraries/Common/tests/System/Collections/ICollection.Generic.Tests.cs b/src/libraries/Common/tests/System/Collections/ICollection.Generic.Tests.cs index a94a9308b99ab4..8ae72dea074ab0 100644 --- a/src/libraries/Common/tests/System/Collections/ICollection.Generic.Tests.cs +++ b/src/libraries/Common/tests/System/Collections/ICollection.Generic.Tests.cs @@ -130,7 +130,7 @@ public void ICollection_Generic_IsReadOnly_Validity(int count) public void ICollection_Generic_Count_Validity(int count) { ICollection collection = GenericICollectionFactory(count); - Assert.Equal(count, collection.Count); + CollectionAsserts.HasCount(collection, count); } #endregion @@ -145,7 +145,7 @@ public virtual void ICollection_Generic_Add_DefaultValue(int count) { ICollection collection = GenericICollectionFactory(count); collection.Add(default(T)); - Assert.Equal(count + 1, collection.Count); + CollectionAsserts.HasCount(collection, count + 1); } } @@ -161,7 +161,7 @@ public void ICollection_Generic_Add_InvalidValueToMiddleOfCollection(int count) collection.Add(invalidValue); for (int i = 0; i < count; i++) collection.Add(CreateT(i)); - Assert.Equal(count * 2, collection.Count); + CollectionAsserts.HasCount(collection, count * 2); }); } } @@ -178,7 +178,7 @@ public void ICollection_Generic_Add_InvalidValueToBeginningOfCollection(int coun collection.Add(invalidValue); for (int i = 0; i < count; i++) collection.Add(CreateT(i)); - Assert.Equal(count, collection.Count); + CollectionAsserts.HasCount(collection, count); }); } } @@ -192,8 +192,9 @@ public void ICollection_Generic_Add_InvalidValueToEndOfCollection(int count) Assert.All(InvalidValues, invalidValue => { ICollection collection = GenericICollectionFactory(count); + collection.Add(invalidValue); - Assert.Equal(count, collection.Count); + CollectionAsserts.HasCount(collection, count); }); } } @@ -208,7 +209,7 @@ public void ICollection_Generic_Add_DuplicateValue(int count) T duplicateValue = CreateT(700); collection.Add(duplicateValue); collection.Add(duplicateValue); - Assert.Equal(count + 2, collection.Count); + CollectionAsserts.HasCount(collection, count + 2); } } @@ -221,7 +222,7 @@ public void ICollection_Generic_Add_AfterCallingClear(int count) ICollection collection = GenericICollectionFactory(count); collection.Clear(); AddToCollection(collection, 5); - Assert.Equal(5, collection.Count); + CollectionAsserts.HasCount(collection, 5); } } @@ -261,7 +262,7 @@ public void ICollection_Generic_Add_AfterRemovingAllItems(int count) for (int i = 0; i < count; i++) collection.Remove(collection.ElementAt(0)); collection.Add(CreateT(254)); - Assert.Equal(1, collection.Count); + CollectionAsserts.HasCount(collection, 1); } } @@ -273,7 +274,7 @@ public void ICollection_Generic_Add_ToReadOnlyCollection(int count) { ICollection collection = GenericICollectionFactory(count); Assert.Throws(() => collection.Add(CreateT(0))); - Assert.Equal(count, collection.Count); + CollectionAsserts.HasCount(collection, count); } } @@ -306,12 +307,12 @@ public void ICollection_Generic_Clear(int count) if (IsReadOnly || AddRemoveClear_ThrowsNotSupported) { Assert.Throws(() => collection.Clear()); - Assert.Equal(count, collection.Count); + CollectionAsserts.HasCount(collection, count); } else { collection.Clear(); - Assert.Equal(0, collection.Count); + CollectionAsserts.HasCount(collection, 0); } } @@ -325,14 +326,14 @@ public void ICollection_Generic_Clear_Repeatedly(int count) Assert.Throws(() => collection.Clear()); Assert.Throws(() => collection.Clear()); Assert.Throws(() => collection.Clear()); - Assert.Equal(count, collection.Count); + CollectionAsserts.HasCount(collection, count); } else { collection.Clear(); collection.Clear(); collection.Clear(); - Assert.Equal(0, collection.Count); + CollectionAsserts.HasCount(collection, 0); } } @@ -434,7 +435,7 @@ public void ICollection_Generic_Contains_ValidValueThatExistsTwiceInTheCollectio T item = CreateT(12); collection.Add(item); collection.Add(item); - Assert.Equal(count + 2, collection.Count); + CollectionAsserts.HasCount(collection, count + 2); } } @@ -567,7 +568,7 @@ public void ICollection_Generic_Remove_DefaultValueNotContainedInCollection(int count--; } Assert.False(collection.Remove(value)); - Assert.Equal(count, collection.Count); + CollectionAsserts.HasCount(collection, count); } } @@ -583,7 +584,7 @@ public void ICollection_Generic_Remove_NonDefaultValueNotContainedInCollection(i while (collection.Contains(value) || Enumerable.Contains(InvalidValues, value)) value = CreateT(seed++); Assert.False(collection.Remove(value)); - Assert.Equal(count, collection.Count); + CollectionAsserts.HasCount(collection, count); } } @@ -602,7 +603,7 @@ public virtual void ICollection_Generic_Remove_DefaultValueContainedInCollection count++; } Assert.True(collection.Remove(value)); - Assert.Equal(count - 1, collection.Count); + CollectionAsserts.HasCount(collection, count - 1); } } @@ -621,7 +622,7 @@ public void ICollection_Generic_Remove_NonDefaultValueContainedInCollection(int count++; } Assert.True(collection.Remove(value)); - Assert.Equal(count - 1, collection.Count); + CollectionAsserts.HasCount(collection, count - 1); } } @@ -639,7 +640,7 @@ public void ICollection_Generic_Remove_ValueThatExistsTwiceInCollection(int coun count += 2; Assert.True(collection.Remove(value)); Assert.True(collection.Contains(value)); - Assert.Equal(count - 1, collection.Count); + CollectionAsserts.HasCount(collection, count - 1); } } @@ -654,7 +655,7 @@ public void ICollection_Generic_Remove_EveryValue(int count) { Assert.True(collection.Remove(value)); }); - Assert.Empty(collection); + CollectionAsserts.HasCount(collection, 0); } } @@ -667,7 +668,7 @@ public void ICollection_Generic_Remove_InvalidValue_ThrowsArgumentException(int { Assert.Throws(() => collection.Remove(value)); }); - Assert.Equal(count, collection.Count); + CollectionAsserts.HasCount(collection, count); } [Theory] diff --git a/src/libraries/Common/tests/System/Collections/IDictionary.Generic.Tests.cs b/src/libraries/Common/tests/System/Collections/IDictionary.Generic.Tests.cs index df92ab206f6686..e6311ec89b4fc1 100644 --- a/src/libraries/Common/tests/System/Collections/IDictionary.Generic.Tests.cs +++ b/src/libraries/Common/tests/System/Collections/IDictionary.Generic.Tests.cs @@ -266,12 +266,16 @@ public void IDictionary_Generic_ItemGet_DefaultKey(int count) if (!DefaultValueAllowed) { Assert.Throws(() => dictionary[default(TKey)]); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + Assert.Throws(() => readOnlyDictionary[default(TKey)]); +#endif } else { TValue value = CreateTValue(3452); dictionary[default(TKey)] = value; - Assert.Equal(value, dictionary[default(TKey)]); + CollectionAsserts.EqualAt(dictionary, default(TKey), value); } } } @@ -283,6 +287,10 @@ public void IDictionary_Generic_ItemGet_MissingNonDefaultKey_ThrowsKeyNotFoundEx IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = GetNewKey(dictionary); Assert.Throws(() => dictionary[missingKey]); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + Assert.Throws(() => readOnlyDictionary[missingKey]); +#endif } [Theory] @@ -296,6 +304,10 @@ public void IDictionary_Generic_ItemGet_MissingDefaultKey_ThrowsKeyNotFoundExcep while (dictionary.ContainsKey(missingKey)) dictionary.Remove(missingKey); Assert.Throws(() => dictionary[missingKey]); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + Assert.Throws(() => readOnlyDictionary[missingKey]); +#endif } } @@ -306,7 +318,7 @@ public void IDictionary_Generic_ItemGet_PresentKeyReturnsCorrectValue(int count) IDictionary dictionary = GenericIDictionaryFactory(count); foreach (KeyValuePair pair in dictionary) { - Assert.Equal(pair.Value, dictionary[pair.Key]); + CollectionAsserts.EqualAt(dictionary, pair.Key, pair.Value); } } @@ -329,7 +341,7 @@ public void IDictionary_Generic_ItemSet_DefaultKey(int count) { TValue value = CreateTValue(3452); dictionary[default(TKey)] = value; - Assert.Equal(value, dictionary[default(TKey)]); + CollectionAsserts.EqualAt(dictionary, default(TKey), value); } } } @@ -355,7 +367,7 @@ public void IDictionary_Generic_ItemSet_AddsNewValueWhenNotPresent(int count) IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = GetNewKey(dictionary); dictionary[missingKey] = CreateTValue(543); - Assert.Equal(count + 1, dictionary.Count); + CollectionAsserts.HasCount(dictionary, count + 1); } } @@ -370,8 +382,8 @@ public void IDictionary_Generic_ItemSet_ReplacesExistingValueWhenPresent(int cou dictionary.Add(existingKey, CreateTValue(5342)); TValue newValue = CreateTValue(1234); dictionary[existingKey] = newValue; - Assert.Equal(count + 1, dictionary.Count); - Assert.Equal(newValue, dictionary[existingKey]); + CollectionAsserts.HasCount(dictionary, count + 1); + CollectionAsserts.EqualAt(dictionary, existingKey, newValue); } } @@ -386,6 +398,10 @@ public void IDictionary_Generic_Keys_ContainsAllCorrectKeys(int count) IDictionary dictionary = GenericIDictionaryFactory(count); IEnumerable expected = dictionary.Select((pair) => pair.Key); Assert.True(expected.SequenceEqual(dictionary.Keys)); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + Assert.True(expected.SequenceEqual(readOnlyDictionary.Keys)); +#endif } [Theory] @@ -396,6 +412,10 @@ public void IDictionary_Generic_Keys_ModifyingTheDictionaryUpdatesTheCollection( { IDictionary dictionary = GenericIDictionaryFactory(count); ICollection keys = dictionary.Keys; +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + IEnumerable readOnlyKeys = readOnlyDictionary.Keys; +#endif int previousCount = keys.Count; if (count > 0) Assert.NotEmpty(keys); @@ -403,10 +423,16 @@ public void IDictionary_Generic_Keys_ModifyingTheDictionaryUpdatesTheCollection( if (IDictionary_Generic_Keys_Values_ModifyingTheDictionaryUpdatesTheCollection) { Assert.Empty(keys); +#if !NETFRAMEWORK + Assert.Empty(readOnlyKeys); +#endif } else { Assert.Equal(previousCount, keys.Count); +#if !NETFRAMEWORK + Assert.Equal(previousCount, readOnlyKeys.Count()); +#endif } } } @@ -420,11 +446,20 @@ public void IDictionary_Generic_Keys_Enumeration_ParentDictionaryModifiedInvalid IDictionary dictionary = GenericIDictionaryFactory(count); ICollection keys = dictionary.Keys; IEnumerator keysEnum = keys.GetEnumerator(); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + IEnumerable readOnlyKeys = readOnlyDictionary.Keys; + IEnumerator readOnlyKeysEnum = readOnlyKeys.GetEnumerator(); +#endif dictionary.Add(GetNewKey(dictionary), CreateTValue(3432)); if (count == 0 ? Enumerator_Empty_ModifiedDuringEnumeration_ThrowsInvalidOperationException : IDictionary_Generic_Keys_Values_Enumeration_ThrowsInvalidOperation_WhenParentModified) { Assert.Throws(() => keysEnum.MoveNext()); Assert.Throws(() => keysEnum.Reset()); +#if !NETFRAMEWORK + Assert.Throws(() => readOnlyKeysEnum.MoveNext()); + Assert.Throws(() => readOnlyKeysEnum.Reset()); +#endif } else { @@ -433,6 +468,13 @@ public void IDictionary_Generic_Keys_Enumeration_ParentDictionaryModifiedInvalid _ = keysEnum.Current; } keysEnum.Reset(); +#if !NETFRAMEWORK + if (readOnlyKeysEnum.MoveNext()) + { + _ = readOnlyKeysEnum.Current; + } + readOnlyKeysEnum.Reset(); +#endif } } } @@ -456,10 +498,25 @@ public void IDictionary_Generic_Keys_Enumeration_Reset(int count) IDictionary dictionary = GenericIDictionaryFactory(count); ICollection keys = dictionary.Keys; IEnumerator enumerator = keys.GetEnumerator(); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + IEnumerable readOnlyKeys = readOnlyDictionary.Keys; + IEnumerator readOnlyEnumerator = readOnlyKeys.GetEnumerator(); +#endif if (IDictionary_Generic_Keys_Values_Enumeration_ResetImplemented) + { enumerator.Reset(); +#if !NETFRAMEWORK + readOnlyEnumerator.Reset(); +#endif + } else + { Assert.Throws(() => enumerator.Reset()); +#if !NETFRAMEWORK + Assert.Throws(() => readOnlyEnumerator.Reset()); +#endif + } } #endregion @@ -473,6 +530,10 @@ public void IDictionary_Generic_Values_ContainsAllCorrectValues(int count) IDictionary dictionary = GenericIDictionaryFactory(count); IEnumerable expected = dictionary.Select((pair) => pair.Value); Assert.True(expected.SequenceEqual(dictionary.Values)); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + Assert.True(expected.SequenceEqual(readOnlyDictionary.Values)); +#endif } [Theory] @@ -491,6 +552,10 @@ public void IDictionary_Generic_Values_IncludeDuplicatesMultipleTimes(int count) dictionary.Add(missingKey, pair.Value); } Assert.Equal(count * 2, dictionary.Values.Count); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + Assert.Equal(count * 2, readOnlyDictionary.Values.Count()); +#endif } } @@ -500,9 +565,18 @@ public void IDictionary_Generic_Values_ModifyingTheDictionaryUpdatesTheCollectio { IDictionary dictionary = GenericIDictionaryFactory(count); ICollection values = dictionary.Values; +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + IEnumerable readOnlyValues = readOnlyDictionary.Values; +#endif int previousCount = values.Count; if (count > 0) + { Assert.NotEmpty(values); +#if !NETFRAMEWORK + Assert.NotEmpty(readOnlyValues); +#endif + } if (!IsReadOnly) { @@ -510,10 +584,16 @@ public void IDictionary_Generic_Values_ModifyingTheDictionaryUpdatesTheCollectio if (IDictionary_Generic_Keys_Values_ModifyingTheDictionaryUpdatesTheCollection) { Assert.Empty(values); +#if !NETFRAMEWORK + Assert.Empty(readOnlyValues); +#endif } else { Assert.Equal(previousCount, values.Count); +#if !NETFRAMEWORK + Assert.Equal(previousCount, readOnlyValues.Count()); +#endif } } } @@ -527,11 +607,20 @@ public void IDictionary_Generic_Values_Enumeration_ParentDictionaryModifiedInval IDictionary dictionary = GenericIDictionaryFactory(count); ICollection values = dictionary.Values; IEnumerator valuesEnum = values.GetEnumerator(); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + IEnumerable readOnlyValues = readOnlyDictionary.Values; + IEnumerator readOnlyValuesEnum = readOnlyValues.GetEnumerator(); +#endif dictionary.Add(GetNewKey(dictionary), CreateTValue(3432)); if (count == 0 ? Enumerator_Empty_ModifiedDuringEnumeration_ThrowsInvalidOperationException : IDictionary_Generic_Keys_Values_Enumeration_ThrowsInvalidOperation_WhenParentModified) { Assert.Throws(() => valuesEnum.MoveNext()); Assert.Throws(() => valuesEnum.Reset()); +#if !NETFRAMEWORK + Assert.Throws(() => readOnlyValuesEnum.MoveNext()); + Assert.Throws(() => readOnlyValuesEnum.Reset()); +#endif } else { @@ -540,6 +629,13 @@ public void IDictionary_Generic_Values_Enumeration_ParentDictionaryModifiedInval _ = valuesEnum.Current; } valuesEnum.Reset(); +#if !NETFRAMEWORK + if (readOnlyValuesEnum.MoveNext()) + { + _ = readOnlyValuesEnum.Current; + } + readOnlyValuesEnum.Reset(); +#endif } } } @@ -563,10 +659,25 @@ public void IDictionary_Generic_Values_Enumeration_Reset(int count) IDictionary dictionary = GenericIDictionaryFactory(count); ICollection values = dictionary.Values; IEnumerator enumerator = values.GetEnumerator(); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + IEnumerable readOnlyValues = readOnlyDictionary.Values; + IEnumerator readOnlyEnumerator = readOnlyValues.GetEnumerator(); +#endif if (IDictionary_Generic_Keys_Values_Enumeration_ResetImplemented) + { enumerator.Reset(); +#if !NETFRAMEWORK + readOnlyEnumerator.Reset(); +#endif + } else + { Assert.Throws(() => enumerator.Reset()); +#if !NETFRAMEWORK + Assert.Throws(() => readOnlyEnumerator.Reset()); +#endif + } } #endregion @@ -594,8 +705,8 @@ public void IDictionary_Generic_Add_DefaultKey_DefaultValue(int count) if (DefaultValueAllowed && !IsReadOnly) { dictionary.Add(missingKey, value); - Assert.Equal(count + 1, dictionary.Count); - Assert.Equal(value, dictionary[missingKey]); + CollectionAsserts.HasCount(dictionary, count + 1); + CollectionAsserts.EqualAt(dictionary, missingKey, value); } else if (!IsReadOnly) { @@ -613,8 +724,8 @@ public void IDictionary_Generic_Add_DefaultKey_NonDefaultValue(int count) if (DefaultValueAllowed && !IsReadOnly) { dictionary.Add(missingKey, value); - Assert.Equal(count + 1, dictionary.Count); - Assert.Equal(value, dictionary[missingKey]); + CollectionAsserts.HasCount(dictionary, count + 1); + CollectionAsserts.EqualAt(dictionary, missingKey, value); } else if (!IsReadOnly) { @@ -632,8 +743,8 @@ public void IDictionary_Generic_Add_NonDefaultKey_DefaultValue(int count) TKey missingKey = GetNewKey(dictionary); TValue value = default(TValue); dictionary.Add(missingKey, value); - Assert.Equal(count + 1, dictionary.Count); - Assert.Equal(value, dictionary[missingKey]); + CollectionAsserts.HasCount(dictionary, count + 1); + CollectionAsserts.EqualAt(dictionary, missingKey, value); } } @@ -647,8 +758,8 @@ public void IDictionary_Generic_Add_NonDefaultKey_NonDefaultValue(int count) TKey missingKey = GetNewKey(dictionary); TValue value = CreateTValue(1342); dictionary.Add(missingKey, value); - Assert.Equal(count + 1, dictionary.Count); - Assert.Equal(value, dictionary[missingKey]); + CollectionAsserts.HasCount(dictionary, count + 1); + CollectionAsserts.EqualAt(dictionary, missingKey, value); } } @@ -666,6 +777,10 @@ public void IDictionary_Generic_Add_DuplicateValue(int count) dictionary.Add(GetNewKey(dictionary), duplicate); dictionary.Add(GetNewKey(dictionary), duplicate); Assert.Equal(2, dictionary.Values.Count((value) => value.Equals(duplicate))); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + Assert.Equal(2, readOnlyDictionary.Values.Count((value) => value.Equals(duplicate))); +#endif } } @@ -692,7 +807,7 @@ public void IDictionary_Generic_Add_DistinctValuesWithHashCollisions(int count) if (dictionary != null) { AddToCollection(dictionary, count); - Assert.Equal(count, dictionary.Count); + CollectionAsserts.HasCount(dictionary, count); } } } @@ -709,7 +824,7 @@ public void IDictionary_Generic_ContainsKey_ValidKeyNotContainedInDictionary(int { IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = GetNewKey(dictionary); - Assert.False(dictionary.ContainsKey(missingKey)); + CollectionAsserts.ContainsKey(dictionary, missingKey, false); } } @@ -722,7 +837,7 @@ public void IDictionary_Generic_ContainsKey_ValidKeyContainedInDictionary(int co IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = GetNewKey(dictionary); dictionary.Add(missingKey, CreateTValue(34251)); - Assert.True(dictionary.ContainsKey(missingKey)); + CollectionAsserts.ContainsKey(dictionary, missingKey, true); } } @@ -739,13 +854,17 @@ public void IDictionary_Generic_ContainsKey_DefaultKeyNotContainedInDictionary(i TKey missingKey = default(TKey); while (dictionary.ContainsKey(missingKey)) dictionary.Remove(missingKey); - Assert.False(dictionary.ContainsKey(missingKey)); + CollectionAsserts.ContainsKey(dictionary, missingKey, false); } } else { // throws ArgumentNullException Assert.Throws(() => dictionary.ContainsKey(default(TKey))); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + Assert.Throws(() => readOnlyDictionary.ContainsKey(default(TKey))); +#endif } } @@ -759,7 +878,7 @@ public void IDictionary_Generic_ContainsKey_DefaultKeyContainedInDictionary(int TKey missingKey = default(TKey); if (!dictionary.ContainsKey(missingKey)) dictionary.Add(missingKey, CreateTValue(5341)); - Assert.True(dictionary.ContainsKey(missingKey)); + CollectionAsserts.ContainsKey(dictionary, missingKey, true); } } @@ -789,7 +908,7 @@ public void IDictionary_Generic_RemoveKey_EveryKey(int count) { Assert.True(dictionary.Remove(key)); }); - Assert.Empty(dictionary); + CollectionAsserts.HasCount(dictionary, 0); } } @@ -802,7 +921,7 @@ public void IDictionary_Generic_RemoveKey_ValidKeyNotContainedInDictionary(int c IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = GetNewKey(dictionary); Assert.False(dictionary.Remove(missingKey)); - Assert.Equal(count, dictionary.Count); + CollectionAsserts.HasCount(dictionary, count); } } @@ -816,7 +935,7 @@ public void IDictionary_Generic_RemoveKey_ValidKeyContainedInDictionary(int coun TKey missingKey = GetNewKey(dictionary); dictionary.Add(missingKey, CreateTValue(34251)); Assert.True(dictionary.Remove(missingKey)); - Assert.Equal(count, dictionary.Count); + CollectionAsserts.HasCount(dictionary, count); } } @@ -909,8 +1028,7 @@ public void IDictionary_Generic_TryGetValue_ValidKeyNotContainedInDictionary(int IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = GetNewKey(dictionary); TValue value = CreateTValue(5123); - TValue outValue; - Assert.False(dictionary.TryGetValue(missingKey, out outValue)); + CollectionAsserts.TryGetValue(dictionary, missingKey, false); } [Theory] @@ -922,10 +1040,8 @@ public void IDictionary_Generic_TryGetValue_ValidKeyContainedInDictionary(int co IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = GetNewKey(dictionary); TValue value = CreateTValue(5123); - TValue outValue; dictionary.TryAdd(missingKey, value); - Assert.True(dictionary.TryGetValue(missingKey, out outValue)); - Assert.Equal(value, outValue); + CollectionAsserts.TryGetValue(dictionary, missingKey, true, value); } } @@ -942,12 +1058,16 @@ public void IDictionary_Generic_TryGetValue_DefaultKeyNotContainedInDictionary(i TKey missingKey = default(TKey); while (dictionary.ContainsKey(missingKey)) dictionary.Remove(missingKey); - Assert.False(dictionary.TryGetValue(missingKey, out outValue)); + CollectionAsserts.TryGetValue(dictionary, missingKey, false); } } else { Assert.Throws(() => dictionary.TryGetValue(default(TKey), out outValue)); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + Assert.Throws(() => readOnlyDictionary.TryGetValue(default(TKey), out outValue)); +#endif } } @@ -960,10 +1080,8 @@ public void IDictionary_Generic_TryGetValue_DefaultKeyContainedInDictionary(int IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = default(TKey); TValue value = CreateTValue(5123); - TValue outValue; dictionary.TryAdd(missingKey, value); - Assert.True(dictionary.TryGetValue(missingKey, out outValue)); - Assert.Equal(value, outValue); + CollectionAsserts.TryGetValue(dictionary, missingKey, true, value); } } diff --git a/src/libraries/Common/tests/System/Collections/IList.Generic.Tests.cs b/src/libraries/Common/tests/System/Collections/IList.Generic.Tests.cs index 44f67e0ca24f83..6d66f143f18d65 100644 --- a/src/libraries/Common/tests/System/Collections/IList.Generic.Tests.cs +++ b/src/libraries/Common/tests/System/Collections/IList.Generic.Tests.cs @@ -103,8 +103,8 @@ protected override IEnumerable GetModifyEnumerables(ModifyOper public void IList_Generic_ItemGet_NegativeIndex_ThrowsException(int count) { IList list = GenericIListFactory(count); - Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[-1]); - Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[int.MinValue]); + CollectionAsserts.ThrowsElementAt(list, -1, IList_Generic_Item_InvalidIndex_ThrowType); + CollectionAsserts.ThrowsElementAt(list, int.MinValue, IList_Generic_Item_InvalidIndex_ThrowType); } [Theory] @@ -112,8 +112,8 @@ public void IList_Generic_ItemGet_NegativeIndex_ThrowsException(int count) public void IList_Generic_ItemGet_IndexGreaterThanListCount_ThrowsException(int count) { IList list = GenericIListFactory(count); - Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[count]); - Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[count + 1]); + CollectionAsserts.ThrowsElementAt(list, count, IList_Generic_Item_InvalidIndex_ThrowType); + CollectionAsserts.ThrowsElementAt(list, count + 1, IList_Generic_Item_InvalidIndex_ThrowType); } [Theory] @@ -121,8 +121,7 @@ public void IList_Generic_ItemGet_IndexGreaterThanListCount_ThrowsException(int public void IList_Generic_ItemGet_ValidGetWithinListBounds(int count) { IList list = GenericIListFactory(count); - T result; - Assert.All(Enumerable.Range(0, count), index => result = list[index]); + Assert.All(Enumerable.Range(0, count), index => CollectionAsserts.ElementAtSucceeds(list, index)); } #endregion @@ -139,7 +138,7 @@ public void IList_Generic_ItemSet_NegativeIndex_ThrowsException(int count) T validAdd = CreateT(0); Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[-1] = validAdd); Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[int.MinValue] = validAdd); - Assert.Equal(count, list.Count); + CollectionAsserts.HasCount(list, count); } } @@ -153,7 +152,7 @@ public void IList_Generic_ItemSet_IndexGreaterThanListCount_ThrowsException(int T validAdd = CreateT(0); Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[count] = validAdd); Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[count + 1] = validAdd); - Assert.Equal(count, list.Count); + CollectionAsserts.HasCount(list, count); } } @@ -166,7 +165,7 @@ public void IList_Generic_ItemSet_OnReadOnlyList(int count) IList list = GenericIListFactory(count); T before = list[count / 2]; Assert.Throws(() => list[count / 2] = CreateT(321432)); - Assert.Equal(before, list[count / 2]); + CollectionAsserts.EqualAt(list, count / 2, before); } } @@ -179,7 +178,7 @@ public void IList_Generic_ItemSet_FirstItemToNonDefaultValue(int count) IList list = GenericIListFactory(count); T value = CreateT(123452); list[0] = value; - Assert.Equal(value, list[0]); + CollectionAsserts.EqualAt(list, 0, value); } } @@ -193,12 +192,12 @@ public void IList_Generic_ItemSet_FirstItemToDefaultValue(int count) if (DefaultValueAllowed) { list[0] = default(T); - Assert.Equal(default(T), list[0]); + CollectionAsserts.EqualAt(list, 0, default(T)); } else { Assert.Throws(() => list[0] = default(T)); - Assert.NotEqual(default(T), list[0]); + CollectionAsserts.NotEqualAt(list, 0, default(T)); } } } @@ -213,7 +212,7 @@ public void IList_Generic_ItemSet_LastItemToNonDefaultValue(int count) T value = CreateT(123452); int lastIndex = count > 0 ? count - 1 : 0; list[lastIndex] = value; - Assert.Equal(value, list[lastIndex]); + CollectionAsserts.EqualAt(list, lastIndex, value); } } @@ -228,12 +227,12 @@ public void IList_Generic_ItemSet_LastItemToDefaultValue(int count) if (DefaultValueAllowed) { list[lastIndex] = default(T); - Assert.Equal(default(T), list[lastIndex]); + CollectionAsserts.EqualAt(list, lastIndex, default(T)); } else { Assert.Throws(() => list[lastIndex] = default(T)); - Assert.NotEqual(default(T), list[lastIndex]); + CollectionAsserts.NotEqualAt(list, lastIndex, default(T)); } } } @@ -248,8 +247,8 @@ public void IList_Generic_ItemSet_DuplicateValues(int count) T value = CreateT(123452); list[0] = value; list[1] = value; - Assert.Equal(value, list[0]); - Assert.Equal(value, list[1]); + CollectionAsserts.EqualAt(list, 0, value); + CollectionAsserts.EqualAt(list, 1, value); } } @@ -396,7 +395,7 @@ public void IList_Generic_Insert_NegativeIndex_ThrowsArgumentOutOfRangeException T validAdd = CreateT(0); Assert.Throws(() => list.Insert(-1, validAdd)); Assert.Throws(() => list.Insert(int.MinValue, validAdd)); - Assert.Equal(count, list.Count); + CollectionAsserts.HasCount(list, count); } } @@ -409,8 +408,8 @@ public void IList_Generic_Insert_IndexGreaterThanListCount_Appends(int count) IList list = GenericIListFactory(count); T validAdd = CreateT(12350); list.Insert(count, validAdd); - Assert.Equal(count + 1, list.Count); - Assert.Equal(validAdd, list[count]); + CollectionAsserts.HasCount(list, count + 1); + CollectionAsserts.EqualAt(list, count, validAdd); } } @@ -422,7 +421,7 @@ public void IList_Generic_Insert_ToReadOnlyList(int count) { IList list = GenericIListFactory(count); Assert.Throws(() => list.Insert(count / 2, CreateT(321432))); - Assert.Equal(count, list.Count); + CollectionAsserts.HasCount(list, count); } } @@ -435,8 +434,8 @@ public void IList_Generic_Insert_FirstItemToNonDefaultValue(int count) IList list = GenericIListFactory(count); T value = CreateT(123452); list.Insert(0, value); - Assert.Equal(value, list[0]); - Assert.Equal(count + 1, list.Count); + CollectionAsserts.EqualAt(list, 0, value); + CollectionAsserts.HasCount(list, count + 1); } } @@ -449,8 +448,8 @@ public void IList_Generic_Insert_FirstItemToDefaultValue(int count) IList list = GenericIListFactory(count); T value = default(T); list.Insert(0, value); - Assert.Equal(value, list[0]); - Assert.Equal(count + 1, list.Count); + CollectionAsserts.EqualAt(list, 0, value); + CollectionAsserts.HasCount(list, count + 1); } } @@ -464,8 +463,8 @@ public void IList_Generic_Insert_LastItemToNonDefaultValue(int count) T value = CreateT(123452); int lastIndex = count > 0 ? count - 1 : 0; list.Insert(lastIndex, value); - Assert.Equal(value, list[lastIndex]); - Assert.Equal(count + 1, list.Count); + CollectionAsserts.EqualAt(list, lastIndex, value); + CollectionAsserts.HasCount(list, count + 1); } } @@ -479,8 +478,8 @@ public void IList_Generic_Insert_LastItemToDefaultValue(int count) T value = default(T); int lastIndex = count > 0 ? count - 1 : 0; list.Insert(lastIndex, value); - Assert.Equal(value, list[lastIndex]); - Assert.Equal(count + 1, list.Count); + CollectionAsserts.EqualAt(list, lastIndex, value); + CollectionAsserts.HasCount(list, count + 1); } } @@ -500,9 +499,9 @@ public void IList_Generic_Insert_DuplicateValues(int count) { list.Insert(0, value); list.Insert(1, value); - Assert.Equal(value, list[0]); - Assert.Equal(value, list[1]); - Assert.Equal(count + 2, list.Count); + CollectionAsserts.EqualAt(list, 0, value); + CollectionAsserts.EqualAt(list, 1, value); + CollectionAsserts.HasCount(list, count + 2); } } } @@ -535,7 +534,7 @@ public void IList_Generic_RemoveAt_NegativeIndex_ThrowsArgumentOutOfRangeExcepti T validAdd = CreateT(0); Assert.Throws(() => list.RemoveAt(-1)); Assert.Throws(() => list.RemoveAt(int.MinValue)); - Assert.Equal(count, list.Count); + CollectionAsserts.HasCount(list, count); } } @@ -549,7 +548,7 @@ public void IList_Generic_RemoveAt_IndexGreaterThanListCount_ThrowsArgumentOutOf T validAdd = CreateT(0); Assert.Throws(() => list.RemoveAt(count)); Assert.Throws(() => list.RemoveAt(count + 1)); - Assert.Equal(count, list.Count); + CollectionAsserts.HasCount(list, count); } } @@ -561,7 +560,7 @@ public void IList_Generic_RemoveAt_OnReadOnlyList(int count) { IList list = GenericIListFactory(count); Assert.Throws(() => list.RemoveAt(count / 2)); - Assert.Equal(count, list.Count); + CollectionAsserts.HasCount(list, count); } } @@ -572,11 +571,11 @@ public void IList_Generic_RemoveAt_AllValidIndices(int count) if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported) { IList list = GenericIListFactory(count); - Assert.Equal(count, list.Count); + CollectionAsserts.HasCount(list, count); Assert.All(Enumerable.Range(0, count).Reverse(), index => { list.RemoveAt(index); - Assert.Equal(index, list.Count); + CollectionAsserts.HasCount(list, index); }); } } @@ -591,7 +590,7 @@ public void IList_Generic_RemoveAt_ZeroMultipleTimes(int count) Assert.All(Enumerable.Range(0, count), index => { list.RemoveAt(0); - Assert.Equal(count - index - 1, list.Count); + CollectionAsserts.HasCount(list, count - index - 1); }); } } diff --git a/src/libraries/Common/tests/System/Collections/ISet.Generic.Tests.cs b/src/libraries/Common/tests/System/Collections/ISet.Generic.Tests.cs index 303001e8bd1443..350faab6f44cb7 100644 --- a/src/libraries/Common/tests/System/Collections/ISet.Generic.Tests.cs +++ b/src/libraries/Common/tests/System/Collections/ISet.Generic.Tests.cs @@ -84,8 +84,8 @@ public void ICollection_Generic_Add_ReturnValue(int count) Assert.True(set.Add(newValue)); if (!DuplicateValuesAllowed) Assert.False(set.Add(newValue)); - Assert.Equal(count + 1, set.Count); - Assert.True(set.Contains(newValue)); + CollectionAsserts.HasCount(set, count + 1); + CollectionAsserts.Contains(set, newValue); } } @@ -104,7 +104,7 @@ public void ICollection_Generic_Add_DuplicateValue_DoesNothing(int count) duplicateValue = CreateT(seed++); collection.Add(duplicateValue); collection.Add(duplicateValue); - Assert.Equal(count + 1, collection.Count); + CollectionAsserts.HasCount(collection, count + 1); } } } @@ -118,7 +118,7 @@ private void Validate_ExceptWith(ISet set, IEnumerable enumerable) if (set.Count == 0 || enumerable == set) { set.ExceptWith(enumerable); - Assert.Equal(0, set.Count); + CollectionAsserts.HasCount(set, 0); } else { @@ -126,7 +126,7 @@ private void Validate_ExceptWith(ISet set, IEnumerable enumerable) foreach (T element in enumerable) expected.Remove(element); set.ExceptWith(enumerable); - Assert.Equal(expected.Count, set.Count); + CollectionAsserts.HasCount(set, expected.Count); Assert.True(expected.SetEquals(set)); } } @@ -136,7 +136,7 @@ private void Validate_IntersectWith(ISet set, IEnumerable enumerable) if (set.Count == 0 || Enumerable.Count(enumerable) == 0) { set.IntersectWith(enumerable); - Assert.Equal(0, set.Count); + CollectionAsserts.HasCount(set, 0); } else if (set == enumerable) { @@ -152,7 +152,7 @@ private void Validate_IntersectWith(ISet set, IEnumerable enumerable) if (enumerable.Contains(value, comparer)) expected.Add(value); set.IntersectWith(enumerable); - Assert.Equal(expected.Count, set.Count); + CollectionAsserts.HasCount(set, expected.Count); Assert.True(expected.SetEquals(set)); } } @@ -178,7 +178,7 @@ private void Validate_IsProperSubsetOf(ISet set, IEnumerable enumerable) break; } } - Assert.Equal(!setContainsValueNotInEnumerable && enumerableContainsValueNotInSet, set.IsProperSubsetOf(enumerable)); + CollectionAsserts.IsProperSubsetOf(set, enumerable, !setContainsValueNotInEnumerable && enumerableContainsValueNotInSet); } private void Validate_IsProperSupersetOf(ISet set, IEnumerable enumerable) @@ -203,7 +203,7 @@ private void Validate_IsProperSupersetOf(ISet set, IEnumerable enumerable) } } isProperSuperset = isProperSuperset && setContainsElementsNotInEnumerable; - Assert.Equal(isProperSuperset, set.IsProperSupersetOf(enumerable)); + CollectionAsserts.IsProperSupersetOf(set, enumerable, isProperSuperset); } private void Validate_IsSubsetOf(ISet set, IEnumerable enumerable) @@ -212,10 +212,10 @@ private void Validate_IsSubsetOf(ISet set, IEnumerable enumerable) foreach (T value in set) if (!enumerable.Contains(value, comparer)) { - Assert.False(set.IsSubsetOf(enumerable)); + CollectionAsserts.IsSubsetOf(set, enumerable, false); return; } - Assert.True(set.IsSubsetOf(enumerable)); + CollectionAsserts.IsSubsetOf(set, enumerable, true); } private void Validate_IsSupersetOf(ISet set, IEnumerable enumerable) @@ -224,10 +224,10 @@ private void Validate_IsSupersetOf(ISet set, IEnumerable enumerable) foreach (T value in enumerable) if (!set.Contains(value, comparer)) { - Assert.False(set.IsSupersetOf(enumerable)); + CollectionAsserts.IsSupersetOf(set, enumerable, false); return; } - Assert.True(set.IsSupersetOf(enumerable)); + CollectionAsserts.IsSupersetOf(set, enumerable, true); } private void Validate_Overlaps(ISet set, IEnumerable enumerable) @@ -237,11 +237,11 @@ private void Validate_Overlaps(ISet set, IEnumerable enumerable) { if (set.Contains(value, comparer)) { - Assert.True(set.Overlaps(enumerable)); + CollectionAsserts.Overlaps(set, enumerable, true); return; } } - Assert.False(set.Overlaps(enumerable)); + CollectionAsserts.Overlaps(set, enumerable, false); } private void Validate_SetEquals(ISet set, IEnumerable enumerable) @@ -251,7 +251,7 @@ private void Validate_SetEquals(ISet set, IEnumerable enumerable) { if (!enumerable.Contains(value, comparer)) { - Assert.False(set.SetEquals(enumerable)); + CollectionAsserts.SetEquals(set, enumerable, false); return; } } @@ -259,11 +259,11 @@ private void Validate_SetEquals(ISet set, IEnumerable enumerable) { if (!set.Contains(value, comparer)) { - Assert.False(set.SetEquals(enumerable)); + CollectionAsserts.SetEquals(set, enumerable, false); return; } } - Assert.True(set.SetEquals(enumerable)); + CollectionAsserts.SetEquals(set, enumerable, true); } private void Validate_SymmetricExceptWith(ISet set, IEnumerable enumerable) @@ -277,7 +277,7 @@ private void Validate_SymmetricExceptWith(ISet set, IEnumerable enumerable if (!enumerable.Contains(element, comparer)) expected.Add(element); set.SymmetricExceptWith(enumerable); - Assert.Equal(expected.Count, set.Count); + CollectionAsserts.HasCount(set, expected.Count); Assert.True(expected.SetEquals(set)); } @@ -289,7 +289,7 @@ private void Validate_UnionWith(ISet set, IEnumerable enumerable) if (!set.Contains(element, comparer)) expected.Add(element); set.UnionWith(enumerable); - Assert.Equal(expected.Count, set.Count); + CollectionAsserts.HasCount(set, expected.Count); Assert.True(expected.SetEquals(set)); } @@ -308,6 +308,15 @@ public void ISet_Generic_NullEnumerableArgument(int count) Assert.Throws(() => set.IsSupersetOf(null)); Assert.Throws(() => set.Overlaps(null)); Assert.Throws(() => set.SetEquals(null)); +#if !NETFRAMEWORK + IReadOnlySet readOnlySet = set; + Assert.Throws(() => readOnlySet.IsProperSubsetOf(null)); + Assert.Throws(() => readOnlySet.IsProperSupersetOf(null)); + Assert.Throws(() => readOnlySet.IsSubsetOf(null)); + Assert.Throws(() => readOnlySet.IsSupersetOf(null)); + Assert.Throws(() => readOnlySet.Overlaps(null)); + Assert.Throws(() => readOnlySet.SetEquals(null)); +#endif if (!IsReadOnly) { Assert.Throws(() => set.ExceptWith(null)); @@ -502,7 +511,7 @@ public void ISet_Generic_Overlaps_Itself(int setLength) public void ISet_Generic_SetEquals_Itself(int setLength) { ISet set = GenericISetFactory(setLength); - Assert.True(set.SetEquals(set)); + CollectionAsserts.SetEquals(set, set, true); } [Theory] @@ -660,7 +669,7 @@ public void ISet_Generic_SymmetricExceptWith_AfterRemovingElements(EnumerableTyp if (!enumerable.Contains(element, comparer)) expected.Add(element); set.SymmetricExceptWith(enumerable); - Assert.Equal(expected.Count, set.Count); + CollectionAsserts.HasCount(set, expected.Count); Assert.True(expected.SetEquals(set)); } } diff --git a/src/libraries/System.Collections/tests/Generic/CollectionExtensionsTests.cs b/src/libraries/System.Collections/tests/Generic/CollectionExtensionsTests.cs index 213d9d6faca996..6a5b458232fc5c 100644 --- a/src/libraries/System.Collections/tests/Generic/CollectionExtensionsTests.cs +++ b/src/libraries/System.Collections/tests/Generic/CollectionExtensionsTests.cs @@ -61,6 +61,10 @@ public void TryAdd_KeyDoesntExistInIDictionary_ReturnsTrue() IDictionary dictionary = new SortedDictionary(); Assert.True(dictionary.TryAdd("key", "value")); Assert.Equal("value", dictionary["key"]); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + Assert.Equal("value", readOnlyDictionary["key"]); +#endif } [Fact] @@ -69,6 +73,10 @@ public void TryAdd_KeyExistsInIDictionary_ReturnsFalse() IDictionary dictionary = new SortedDictionary() { ["key"] = "value" }; Assert.False(dictionary.TryAdd("key", "value2")); Assert.Equal("value", dictionary["key"]); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + Assert.Equal("value", readOnlyDictionary["key"]); +#endif } [Fact] @@ -96,6 +104,10 @@ public void Remove_KeyExistsInIDictionary_ReturnsTrue() Assert.True(dictionary.Remove("key", out var value)); Assert.Equal("value", value); Assert.Throws(() => dictionary["key"]); +#if !NETFRAMEWORK + IReadOnlyDictionary readOnlyDictionary = dictionary; + Assert.Throws(() => readOnlyDictionary["key"]); +#endif } [Fact] 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 1c1095f8a5cf75..24cf81efb2b440 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 @@ -9,9 +9,9 @@ namespace System.Collections.Generic { // Base interface for all collections, defining enumerators, size, and // synchronization methods. - public interface ICollection : IEnumerable + public interface ICollection : IReadOnlyCollection { - int Count + new int Count { #if MONO [DynamicDependency(nameof(Array.InternalArray__ICollection_get_Count), typeof(Array))] @@ -53,5 +53,7 @@ bool IsReadOnly [DynamicDependency(nameof(Array.InternalArray__ICollection_Remove) + "``1", typeof(Array))] #endif bool Remove(T item); + + int IReadOnlyCollection.Count => Count; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IDictionary.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IDictionary.cs index 56a03106c205b6..7e3e30d8db0929 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IDictionary.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IDictionary.cs @@ -9,32 +9,32 @@ namespace System.Collections.Generic // Keys can be any non-null object. Values can be any object. // You can look up a value in an IDictionary via the default indexed // property, Items. - public interface IDictionary : ICollection> + public interface IDictionary : ICollection>, IReadOnlyDictionary { // Interfaces are not serializable // The Item property provides methods to read and edit entries // in the Dictionary. - TValue this[TKey key] + new TValue this[TKey key] { get; set; } // Returns a collections of the keys in this dictionary. - ICollection Keys + new ICollection Keys { get; } // Returns a collections of the values in this dictionary. - ICollection Values + new ICollection Values { get; } // Returns whether this dictionary contains a particular key. // - bool ContainsKey(TKey key); + new bool ContainsKey(TKey key); // Adds a key-value pair to the dictionary. // @@ -44,6 +44,16 @@ ICollection Values // bool Remove(TKey key); - bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value); + new bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value); + + TValue IReadOnlyDictionary.this[TKey key] => this[key]; + + IEnumerable IReadOnlyDictionary.Keys => Keys; + + IEnumerable IReadOnlyDictionary.Values => Values; + + bool IReadOnlyDictionary.ContainsKey(TKey key) => ContainsKey(key); + + bool IReadOnlyDictionary.TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) => TryGetValue(key, out value); } } 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 f45ae823daf650..ec8098c3ff7ea1 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 @@ -10,10 +10,10 @@ namespace System.Collections.Generic // An IList is an ordered collection of objects. The exact ordering // is up to the implementation of the list, ranging from a sorted // order to insertion order. - public interface IList : ICollection + public interface IList : ICollection, IReadOnlyList { // The Item property provides methods to read and edit entries in the List. - T this[int index] + new T this[int index] { #if MONO [DynamicDependency(nameof(Array.InternalArray__get_Item) + "``1", typeof(Array))] @@ -46,5 +46,7 @@ T this[int index] [DynamicDependency(nameof(Array.InternalArray__RemoveAt), typeof(Array))] #endif void RemoveAt(int index); + + T IReadOnlyList.this[int index] => this[index]; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ISet.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ISet.cs index cee05d198cda07..ce2e8e7c5f4ff1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ISet.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ISet.cs @@ -8,7 +8,7 @@ namespace System.Collections.Generic /// by some comparer. It also supports basic set operations such as Union, Intersection, /// Complement and Exclusive Complement. /// - public interface ISet : ICollection + public interface ISet : ICollection, IReadOnlySet { //Add ITEM to the set, return true if added, false if duplicate new bool Add(T item); @@ -26,21 +26,42 @@ public interface ISet : ICollection void SymmetricExceptWith(IEnumerable other); //Check if this set is a subset of other - bool IsSubsetOf(IEnumerable other); + new bool IsSubsetOf(IEnumerable other); //Check if this set is a superset of other - bool IsSupersetOf(IEnumerable other); + new bool IsSupersetOf(IEnumerable other); //Check if this set is a subset of other, but not the same as it - bool IsProperSupersetOf(IEnumerable other); + new bool IsProperSupersetOf(IEnumerable other); //Check if this set is a superset of other, but not the same as it - bool IsProperSubsetOf(IEnumerable other); + new bool IsProperSubsetOf(IEnumerable other); //Check if this set has any elements in common with other - bool Overlaps(IEnumerable other); + new bool Overlaps(IEnumerable other); //Check if this set contains the same and only the same elements as other - bool SetEquals(IEnumerable other); + new bool SetEquals(IEnumerable other); + + /// + /// Determines if the set contains a specific item + /// + /// The item to check if the set contains. + /// if found; otherwise . + new bool Contains(T item) => ((ICollection)this).Contains(item); + + bool IReadOnlySet.IsSubsetOf(IEnumerable other) => IsSubsetOf(other); + + bool IReadOnlySet.IsSupersetOf(IEnumerable other) => IsSupersetOf(other); + + bool IReadOnlySet.IsProperSupersetOf(IEnumerable other) => IsProperSupersetOf(other); + + bool IReadOnlySet.IsProperSubsetOf(IEnumerable other) => IsProperSubsetOf(other); + + bool IReadOnlySet.Overlaps(IEnumerable other) => Overlaps(other); + + bool IReadOnlySet.SetEquals(IEnumerable other) => SetEquals(other); + + bool IReadOnlySet.Contains(T value) => ((ICollection)this).Contains(value); } } diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index a3f2a4b07e2f48..c2f175247dc9b6 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -7803,29 +7803,35 @@ public partial interface IAsyncEnumerator : System.IAsyncDisposable T Current { get; } System.Threading.Tasks.ValueTask MoveNextAsync(); } - public partial interface ICollection : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable + public partial interface ICollection : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Collections.Generic.IReadOnlyCollection { - int Count { get; } + new int Count { get; } bool IsReadOnly { get; } void Add(T item); void Clear(); bool Contains(T item); void CopyTo(T[] array, int arrayIndex); bool Remove(T item); + int System.Collections.Generic.IReadOnlyCollection.Count => Count; } public partial interface IComparer { int Compare(T? x, T? y); } - public partial interface IDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable + public partial interface IDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable, System.Collections.Generic.IReadOnlyDictionary, System.Collections.Generic.IReadOnlyCollection> { - TValue this[TKey key] { get; set; } - System.Collections.Generic.ICollection Keys { get; } - System.Collections.Generic.ICollection Values { get; } + new TValue this[TKey key] { get; set; } + new System.Collections.Generic.ICollection Keys { get; } + new System.Collections.Generic.ICollection Values { get; } void Add(TKey key, TValue value); - bool ContainsKey(TKey key); + new bool ContainsKey(TKey key); bool Remove(TKey key); - bool TryGetValue(TKey key, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TValue value); + new bool TryGetValue(TKey key, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TValue value); + TValue System.Collections.Generic.IReadOnlyDictionary.this[TKey key] => this[key]; + System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Keys => Keys; + System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Values => Values; + bool System.Collections.Generic.IReadOnlyDictionary.ContainsKey(TKey key) => ContainsKey(key); + bool System.Collections.Generic.IReadOnlyDictionary.TryGetValue(TKey key, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TValue value) => TryGetValue(key, out value); } public partial interface IEnumerable : System.Collections.IEnumerable { @@ -7840,12 +7846,13 @@ public partial interface IEqualityComparer bool Equals(T? x, T? y); int GetHashCode([System.Diagnostics.CodeAnalysis.DisallowNullAttribute] T obj); } - public partial interface IList : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable + public partial interface IList : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.IReadOnlyCollection { - T this[int index] { get; set; } + new T this[int index] { get; set; } int IndexOf(T item); void Insert(int index, T item); void RemoveAt(int index); + T System.Collections.Generic.IReadOnlyList.this[int index] => this[index]; } public partial interface IReadOnlyCollection : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { @@ -7873,19 +7880,27 @@ public partial interface IReadOnlySet : System.Collections.Generic.IEnumerabl bool Overlaps(System.Collections.Generic.IEnumerable other); bool SetEquals(System.Collections.Generic.IEnumerable other); } - public partial interface ISet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable + public partial interface ISet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Collections.Generic.IReadOnlySet, System.Collections.Generic.IReadOnlyCollection { new bool Add(T item); void ExceptWith(System.Collections.Generic.IEnumerable other); void IntersectWith(System.Collections.Generic.IEnumerable other); - bool IsProperSubsetOf(System.Collections.Generic.IEnumerable other); - bool IsProperSupersetOf(System.Collections.Generic.IEnumerable other); - bool IsSubsetOf(System.Collections.Generic.IEnumerable other); - bool IsSupersetOf(System.Collections.Generic.IEnumerable other); - bool Overlaps(System.Collections.Generic.IEnumerable other); - bool SetEquals(System.Collections.Generic.IEnumerable other); + new bool IsProperSubsetOf(System.Collections.Generic.IEnumerable other); + new bool IsProperSupersetOf(System.Collections.Generic.IEnumerable other); + new bool IsSubsetOf(System.Collections.Generic.IEnumerable other); + new bool IsSupersetOf(System.Collections.Generic.IEnumerable other); + new bool Overlaps(System.Collections.Generic.IEnumerable other); + new bool SetEquals(System.Collections.Generic.IEnumerable other); void SymmetricExceptWith(System.Collections.Generic.IEnumerable other); void UnionWith(System.Collections.Generic.IEnumerable other); + new bool Contains(T item) => ((ICollection)this).Contains(item); + bool System.Collections.Generic.IReadOnlySet.Contains(T item) => ((ICollection)this).Contains(item); + bool System.Collections.Generic.IReadOnlySet.IsProperSubsetOf(System.Collections.Generic.IEnumerable other) => IsProperSubsetOf(other); + bool System.Collections.Generic.IReadOnlySet.IsProperSupersetOf(System.Collections.Generic.IEnumerable other) => IsProperSupersetOf(other); + bool System.Collections.Generic.IReadOnlySet.IsSubsetOf(System.Collections.Generic.IEnumerable other) => IsSubsetOf(other); + bool System.Collections.Generic.IReadOnlySet.IsSupersetOf(System.Collections.Generic.IEnumerable other) => IsSupersetOf(other); + bool System.Collections.Generic.IReadOnlySet.Overlaps(System.Collections.Generic.IEnumerable other) => Overlaps(other); + bool System.Collections.Generic.IReadOnlySet.SetEquals(System.Collections.Generic.IEnumerable other) => SetEquals(other); } public partial class KeyNotFoundException : System.SystemException { From 3e18c03f644b15060be2ac35d1f3b8cc2895bd32 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Tue, 23 Apr 2024 19:14:50 -0700 Subject: [PATCH 078/248] Simplify managed MetadataImport creation (#101353) * Simplify managed MetadataImport creation Consolidate the create mechanism for the managed MetadataImport type. This also removes some Helper Method Frame usage. * Always get the latest metadataimport instance. The field on the managed object can become stale during HotReload or EnC scenarios. --------- Co-authored-by: Jan Kotas --- .../src/System/Reflection/MdImport.cs | 15 ++++---- .../Reflection/RuntimeCustomAttributeData.cs | 35 ++++++++++++------- .../src/System/Reflection/RuntimeModule.cs | 4 +-- .../System/Reflection/RuntimeParameterInfo.cs | 21 +++++++---- .../System/Reflection/RuntimePropertyInfo.cs | 7 ++-- .../src/System/RuntimeHandles.cs | 25 +++---------- .../src/System/RuntimeType.CoreCLR.cs | 25 ++++++++----- src/coreclr/vm/domainassembly.cpp | 8 ++--- src/coreclr/vm/ecalllist.h | 3 +- src/coreclr/vm/managedmdimport.cpp | 10 ++++++ src/coreclr/vm/managedmdimport.hpp | 1 + src/coreclr/vm/runtimehandles.cpp | 29 --------------- src/coreclr/vm/runtimehandles.h | 10 +----- 13 files changed, 91 insertions(+), 102 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs index febf1a5055568f..6f74dde91fe7e0 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs @@ -205,9 +205,6 @@ internal readonly partial struct MetadataImport #pragma warning restore CA1067 { private readonly IntPtr m_metadataImport2; - private readonly object? m_keepalive; - - internal static MetadataImport EmptyImport => new MetadataImport(IntPtr.Zero, null); #region Override methods from Object public override int GetHashCode() @@ -304,10 +301,16 @@ internal static unsafe MarshalAsAttribute GetMarshalAs(ConstArray nativeType, Ru #endregion #region Constructor - internal MetadataImport(IntPtr metadataImport2, object? keepalive) + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern unsafe IntPtr GetMetadataImport(RuntimeModule module); + + internal MetadataImport(RuntimeModule module) { - m_metadataImport2 = metadataImport2; - m_keepalive = keepalive; + ArgumentNullException.ThrowIfNull(module); + + // The MetadataImport instance needs to be acquired in this manner + // since the instance can be replaced during HotReload and EnC scenarios. + m_metadataImport2 = GetMetadataImport(module); } #endregion 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 fd33d68fb0758e..38663e57cde246 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs @@ -215,6 +215,7 @@ internal static CustomAttributeRecord[] GetCustomAttributeRecords(RuntimeModule scope.GetCustomAttributeProps(tkCustomAttributeTokens[i], out records[i].tkCtor.Value, out records[i].blob); } + GC.KeepAlive(module); return records; } @@ -250,13 +251,13 @@ internal static CustomAttributeTypedArgument Filter(IList a private RuntimeCustomAttributeData(RuntimeModule scope, MetadataToken caCtorToken, in ConstArray blob) { m_scope = scope; - m_ctor = (RuntimeConstructorInfo)RuntimeType.GetMethodBase(scope, caCtorToken)!; + m_ctor = (RuntimeConstructorInfo)RuntimeType.GetMethodBase(m_scope, caCtorToken)!; if (m_ctor!.DeclaringType!.IsGenericType) { - MetadataImport metadataScope = scope.MetadataImport; - Type attributeType = scope.ResolveType(metadataScope.GetParentToken(caCtorToken), null, null)!; - m_ctor = (RuntimeConstructorInfo)scope.ResolveMethod(caCtorToken, attributeType.GenericTypeArguments, null)!.MethodHandle.GetMethodInfo(); + MetadataImport metadataScope = m_scope.MetadataImport; + Type attributeType = m_scope.ResolveType(metadataScope.GetParentToken(caCtorToken), null, null)!; + m_ctor = (RuntimeConstructorInfo)m_scope.ResolveMethod(caCtorToken, attributeType.GenericTypeArguments, null)!.MethodHandle.GetMethodInfo(); } ReadOnlySpan parameters = m_ctor.GetParametersAsSpan(); @@ -1466,6 +1467,7 @@ private static bool IsCustomAttributeDefined( } } } + GC.KeepAlive(decoratedModule); return false; } @@ -1615,6 +1617,7 @@ private static void AddCustomAttributes( attributes.Add(attribute); } + GC.KeepAlive(decoratedModule); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", @@ -2194,10 +2197,11 @@ internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType? caType) if ((method.Attributes & MethodAttributes.PinvokeImpl) == 0) return null; - MetadataImport scope = ModuleHandle.GetMetadataImport(method.Module.ModuleHandle.GetRuntimeModule()); + RuntimeModule module = method.Module.ModuleHandle.GetRuntimeModule(); + MetadataImport scope = module.MetadataImport; int token = method.MetadataToken; - scope.GetPInvokeMap(token, out PInvokeAttributes flags, out string entryPoint, out string dllName); + GC.KeepAlive(module); CharSet charSet = CharSet.None; @@ -2252,7 +2256,7 @@ internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType? caType) private static MarshalAsAttribute? GetMarshalAsCustomAttribute(int token, RuntimeModule scope) { - ConstArray nativeType = ModuleHandle.GetMetadataImport(scope).GetFieldMarshal(token); + ConstArray nativeType = scope.MetadataImport.GetFieldMarshal(token); if (nativeType.Length == 0) return null; @@ -2262,10 +2266,15 @@ internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType? caType) private static FieldOffsetAttribute? GetFieldOffsetCustomAttribute(RuntimeFieldInfo field) { - if (field.DeclaringType is not null && - field.GetRuntimeModule().MetadataImport.GetFieldOffset(field.DeclaringType.MetadataToken, field.MetadataToken, out int fieldOffset)) - return new FieldOffsetAttribute(fieldOffset); - + if (field.DeclaringType is not null) + { + RuntimeModule module = field.GetRuntimeModule(); + if (module.MetadataImport.GetFieldOffset(field.DeclaringType.MetadataToken, field.MetadataToken, out int fieldOffset)) + { + return new FieldOffsetAttribute(fieldOffset); + } + GC.KeepAlive(module); + } return null; } @@ -2291,7 +2300,9 @@ internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType? caType) case TypeAttributes.UnicodeClass: charSet = CharSet.Unicode; break; default: Debug.Fail("Unreachable code"); break; } - type.GetRuntimeModule().MetadataImport.GetClassLayout(type.MetadataToken, out int pack, out int size); + RuntimeModule module = type.GetRuntimeModule(); + module.MetadataImport.GetClassLayout(type.MetadataToken, out int pack, out int size); + GC.KeepAlive(module); StructLayoutAttribute attribute = new StructLayoutAttribute(layoutKind); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs index 8e7e4a05c73dde..4e9a4dffeb209a 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs @@ -202,7 +202,7 @@ public override byte[] ResolveSignature(int metadataToken) if (declaringType.IsGenericType || declaringType.IsArray) { - int tkDeclaringType = ModuleHandle.GetMetadataImport(this).GetParentToken(metadataToken); + int tkDeclaringType = MetadataImport.GetParentToken(metadataToken); declaringType = (RuntimeType)ResolveType(tkDeclaringType, genericTypeArguments, genericMethodArguments); } @@ -353,7 +353,7 @@ public override void GetPEKind(out PortableExecutableKinds peKind, out ImageFile #region Internal Members internal RuntimeType RuntimeType => m_runtimeType ??= ModuleHandle.GetModuleType(this); - internal MetadataImport MetadataImport => ModuleHandle.GetMetadataImport(this); + internal MetadataImport MetadataImport => new MetadataImport(this); #endregion #region ICustomAttributeProvider Members 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 5af77b790f49c3..24dd89c2113172 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs @@ -29,6 +29,11 @@ internal static ParameterInfo GetReturnParameter(IRuntimeMethodInfo method, Memb private static ParameterInfo[] GetParameters( IRuntimeMethodInfo methodHandle, MemberInfo member, Signature sig, out ParameterInfo? returnParameter, bool fetchReturnParameter) { + // The lifetime rules for MetadataImport expect these two objects to be the same instance. + // See the lifetime of MetadataImport, acquired through IRuntimeMethodInfo, but extended + // through the MemberInfo instance. + Debug.Assert(ReferenceEquals(methodHandle, member)); + returnParameter = null; int sigArgCount = sig.Arguments.Length; ParameterInfo[] args = @@ -43,7 +48,7 @@ private static ParameterInfo[] GetParameters( // are generated on the fly by the runtime. if (!MdToken.IsNullToken(tkMethodDef)) { - MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(RuntimeMethodHandle.GetDeclaringType(methodHandle)); + MetadataImport scope = RuntimeMethodHandle.GetDeclaringType(methodHandle).GetRuntimeModule().MetadataImport; scope.EnumParams(tkMethodDef, out MetadataEnumResult tkParamDefs); @@ -73,7 +78,7 @@ private static ParameterInfo[] GetParameters( } else if (!fetchReturnParameter && position >= 0) { - // position beyong sigArgCount? + // position beyond sigArgCount? if (position >= sigArgCount) throw new BadImageFormatException(SR.BadImageFormat_ParameterSignatureMismatch); @@ -86,7 +91,7 @@ private static ParameterInfo[] GetParameters( // Fill in empty ParameterInfos for those without tokens if (fetchReturnParameter) { - returnParameter ??= new RuntimeParameterInfo(sig, MetadataImport.EmptyImport, 0, -1, (ParameterAttributes)0, member); + returnParameter ??= new RuntimeParameterInfo(sig, default, 0, -1, (ParameterAttributes)0, member); } else { @@ -97,7 +102,7 @@ private static ParameterInfo[] GetParameters( if (args[i] != null) continue; - args[i] = new RuntimeParameterInfo(sig, MetadataImport.EmptyImport, 0, i, (ParameterAttributes)0, member); + args[i] = new RuntimeParameterInfo(sig, default, 0, i, (ParameterAttributes)0, member); } } } @@ -165,7 +170,7 @@ private RuntimeParameterInfo(RuntimeParameterInfo accessor, MemberInfo member) PositionImpl = accessor.Position; AttrsImpl = accessor.Attributes; - // Strictly speeking, property's don't contain parameter tokens + // Strictly speaking, properties don't contain parameter tokens // However we need this to make ca's work... oh well... m_tkParamDef = MdToken.IsNullToken(accessor.MetadataToken) ? (int)MetadataTokenType.ParamDef : accessor.MetadataToken; m_scope = accessor.m_scope; @@ -176,7 +181,7 @@ private RuntimeParameterInfo( int position, ParameterAttributes attributes, MemberInfo member) { Debug.Assert(member != null); - Debug.Assert(MdToken.IsNullToken(tkParamDef) == scope.Equals(MetadataImport.EmptyImport)); + Debug.Assert(MdToken.IsNullToken(tkParamDef) == scope.Equals((MetadataImport)default)); Debug.Assert(MdToken.IsNullToken(tkParamDef) || MdToken.IsTokenOfType(tkParamDef, MetadataTokenType.ParamDef)); PositionImpl = position; @@ -201,7 +206,7 @@ internal RuntimeParameterInfo(MethodInfo owner, string? name, Type parameterType PositionImpl = position; AttrsImpl = ParameterAttributes.None; m_tkParamDef = (int)MetadataTokenType.ParamDef; - m_scope = MetadataImport.EmptyImport; + m_scope = default; } #endregion @@ -239,6 +244,7 @@ public override string? Name if (!MdToken.IsNullToken(m_tkParamDef)) { string name = m_scope.GetName(m_tkParamDef).ToString(); + GC.KeepAlive(this); NameImpl = name; } @@ -339,6 +345,7 @@ private bool TryGetDefaultValueInternal(bool raw, out object? defaultValue) #region Look for a default value in metadata // This will return DBNull.Value if no constant value is defined on m_tkParamDef in the metadata. defaultValue = MdConstant.GetValue(m_scope, m_tkParamDef, ParameterType.TypeHandle, raw); + GC.KeepAlive(this); // If default value is not specified in metadata, look for it in custom attributes if (defaultValue == DBNull.Value) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs index 933e05d0bf7854..d49ac821e684d9 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs @@ -35,7 +35,8 @@ internal RuntimePropertyInfo( Debug.Assert(reflectedTypeCache != null); Debug.Assert(!reflectedTypeCache.IsGlobal); - MetadataImport scope = declaredType.GetRuntimeModule().MetadataImport; + RuntimeModule module = declaredType.GetRuntimeModule(); + MetadataImport scope = module.MetadataImport; m_token = tkProperty; m_reflectedTypeCache = reflectedTypeCache; @@ -47,6 +48,7 @@ internal RuntimePropertyInfo( out _, out _, out _, out m_getterMethod, out m_setterMethod, out m_otherMethod, out isPrivate, out m_bindingFlags); + GC.KeepAlive(module); } #endregion @@ -65,9 +67,9 @@ internal Signature Signature { if (m_signature == null) { - GetRuntimeModule().MetadataImport.GetPropertyProps( m_token, out _, out _, out ConstArray sig); + GC.KeepAlive(this); m_signature = new Signature(sig.Signature.ToPointer(), sig.Length, m_declaringType); } @@ -210,6 +212,7 @@ public override Type[] GetOptionalCustomModifiers() internal object GetConstantValue(bool raw) { object? defaultValue = MdConstant.GetValue(GetRuntimeModule().MetadataImport, m_token, PropertyType.TypeHandle, raw); + GC.KeepAlive(this); if (defaultValue == DBNull.Value) // Arg_EnumLitValueNotFound -> "Literal value was not found." diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index 001a9fcdfee6a8..380981993451e9 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -650,14 +650,6 @@ internal static bool SatisfiesConstraints(RuntimeType paramType, RuntimeType[]? } } - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern IntPtr _GetMetadataImport(RuntimeType type); - - internal static MetadataImport GetMetadataImport(RuntimeType type) - { - return new MetadataImport(_GetMetadataImport(type), type); - } - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_RegisterCollectibleTypeDependency")] private static partial void RegisterCollectibleTypeDependency(QCallTypeHandle type, QCallAssembly assembly); @@ -1247,8 +1239,6 @@ internal ModuleHandle(RuntimeModule module) } #endregion - #region Internal FCalls - internal RuntimeModule GetRuntimeModule() { return m_ptr; @@ -1278,6 +1268,7 @@ public bool Equals(ModuleHandle handle) public static bool operator !=(ModuleHandle left, ModuleHandle right) => !left.Equals(right); + #region Internal FCalls [MethodImpl(MethodImplOptions.InternalCall)] internal static extern IRuntimeMethodInfo GetDynamicMethod(Reflection.Emit.DynamicMethod method, RuntimeModule module, string name, byte[] sig, Resolver resolver); @@ -1336,7 +1327,7 @@ public RuntimeTypeHandle ResolveTypeHandle(int typeToken, RuntimeTypeHandle[]? t } catch (Exception) { - if (!GetMetadataImport(module).IsValidToken(typeToken)) + if (!module.MetadataImport.IsValidToken(typeToken)) throw new ArgumentOutOfRangeException(nameof(typeToken), SR.Format(SR.Argument_InvalidToken, typeToken, new ModuleHandle(module))); throw; @@ -1389,7 +1380,7 @@ internal static RuntimeMethodHandleInternal ResolveMethodHandleInternal(RuntimeM } catch (Exception) { - if (!GetMetadataImport(module).IsValidToken(methodToken)) + if (!module.MetadataImport.IsValidToken(methodToken)) throw new ArgumentOutOfRangeException(nameof(methodToken), SR.Format(SR.Argument_InvalidToken, methodToken, new ModuleHandle(module))); throw; @@ -1442,7 +1433,7 @@ public RuntimeFieldHandle ResolveFieldHandle(int fieldToken, RuntimeTypeHandle[] } catch (Exception) { - if (!GetMetadataImport(module).IsValidToken(fieldToken)) + if (!module.MetadataImport.IsValidToken(fieldToken)) throw new ArgumentOutOfRangeException(nameof(fieldToken), SR.Format(SR.Argument_InvalidToken, fieldToken, new ModuleHandle(module))); throw; @@ -1485,14 +1476,6 @@ internal static void GetPEKind(RuntimeModule module, out PortableExecutableKinds internal static extern int GetMDStreamVersion(RuntimeModule module); public int MDStreamVersion => GetMDStreamVersion(GetRuntimeModule()); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern IntPtr _GetMetadataImport(RuntimeModule module); - - internal static MetadataImport GetMetadataImport(RuntimeModule module) - { - return new MetadataImport(_GetMetadataImport(module), module); - } #endregion } diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index 56ff2e26850ccc..c6ea76fde9b85f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -932,7 +932,8 @@ private void PopulateLiteralFields(Filter filter, RuntimeType declaringType, ref if (MdToken.IsNullToken(tkDeclaringType)) return; - MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(declaringType); + RuntimeModule module = declaringType.GetRuntimeModule(); + MetadataImport scope = module.MetadataImport; scope.EnumFields(tkDeclaringType, out MetadataEnumResult tkFields); @@ -976,6 +977,7 @@ private void PopulateLiteralFields(Filter filter, RuntimeType declaringType, ref list.Add(runtimeFieldInfo); } } + GC.KeepAlive(module); } private void AddSpecialInterface( @@ -1102,7 +1104,7 @@ private RuntimeType[] PopulateNestedClasses(Filter filter) ListBuilder list = default; ModuleHandle moduleHandle = new ModuleHandle(RuntimeTypeHandle.GetModule(declaringType)); - MetadataImport scope = ModuleHandle.GetMetadataImport(moduleHandle.GetRuntimeModule()); + MetadataImport scope = moduleHandle.GetRuntimeModule().MetadataImport; scope.EnumNestedTypes(tkEnclosingType, out MetadataEnumResult tkNestedClasses); @@ -1174,7 +1176,8 @@ private void PopulateEvents( if (MdToken.IsNullToken(tkDeclaringType)) return; - MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(declaringType); + RuntimeModule module = declaringType.GetRuntimeModule(); + MetadataImport scope = module.MetadataImport; scope.EnumEvents(tkDeclaringType, out MetadataEnumResult tkEvents); @@ -1220,6 +1223,7 @@ private void PopulateEvents( list.Add(eventInfo); } + GC.KeepAlive(module); } private RuntimePropertyInfo[] PopulateProperties(Filter filter) @@ -1286,7 +1290,8 @@ private void PopulateProperties( if (MdToken.IsNullToken(tkDeclaringType)) return; - MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(declaringType); + RuntimeModule module = declaringType.GetRuntimeModule(); + MetadataImport scope = module.MetadataImport; scope.EnumProperties(tkDeclaringType, out MetadataEnumResult tkProperties); @@ -1304,7 +1309,7 @@ private void PopulateProperties( if (filter.RequiresStringComparison()) { - MdUtf8String name = declaringType.GetRuntimeModule().MetadataImport.GetName(tkProperty); + MdUtf8String name = scope.GetName(tkProperty); if (!filter.Match(name)) continue; @@ -1399,6 +1404,7 @@ private void PopulateProperties( list.Add(propertyInfo); } + GC.KeepAlive(module); } #endregion @@ -1571,7 +1577,9 @@ internal Type[] FunctionPointerReturnAndParameterTypes while (type.IsNested) type = type.DeclaringType!; - m_namespace = RuntimeTypeHandle.GetMetadataImport((RuntimeType)type).GetNamespace(type.MetadataToken).ToString(); + RuntimeModule module = ((RuntimeType)type).GetRuntimeModule(); + m_namespace = module.MetadataImport.GetNamespace(type.MetadataToken).ToString(); + GC.KeepAlive(module); } return m_namespace; @@ -3499,8 +3507,9 @@ public override GenericParameterAttributes GenericParameterAttributes if (!IsGenericParameter) throw new InvalidOperationException(SR.Arg_NotGenericParameter); - - RuntimeTypeHandle.GetMetadataImport(this).GetGenericParamProps(MetadataToken, out GenericParameterAttributes attributes); + RuntimeModule module = GetRuntimeModule(); + module.MetadataImport.GetGenericParamProps(MetadataToken, out GenericParameterAttributes attributes); + GC.KeepAlive(module); return attributes; } diff --git a/src/coreclr/vm/domainassembly.cpp b/src/coreclr/vm/domainassembly.cpp index 0e86d312ae88a3..ead21d61193433 100644 --- a/src/coreclr/vm/domainassembly.cpp +++ b/src/coreclr/vm/domainassembly.cpp @@ -344,14 +344,14 @@ OBJECTREF DomainAssembly::GetExposedModuleObject() { REFLECTMODULEBASEREF refClass = NULL; - // Will be TRUE only if LoaderAllocator managed object was already collected and therefore we should + // Will be true only if LoaderAllocator managed object was already collected and therefore we should // return NULL - BOOL fIsLoaderAllocatorCollected = FALSE; + bool fIsLoaderAllocatorCollected = false; GCPROTECT_BEGIN(refClass); refClass = (REFLECTMODULEBASEREF) AllocateObject(CoreLibBinder::GetClass(CLASS__MODULE)); - refClass->SetModule(m_pModule); + refClass->SetModule(GetModule()); // Attach the reference to the assembly to keep the LoaderAllocator for this collectible type // alive as long as a reference to the module is kept alive. @@ -360,7 +360,7 @@ OBJECTREF DomainAssembly::GetExposedModuleObject() OBJECTREF refAssembly = GetModule()->GetAssembly()->GetExposedObject(); if ((refAssembly == NULL) && GetModule()->GetAssembly()->IsCollectible()) { - fIsLoaderAllocatorCollected = TRUE; + fIsLoaderAllocatorCollected = true; } refClass->SetAssembly(refAssembly); } diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 5406bc85c7a1c3..98a38b8603419c 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -137,7 +137,6 @@ FCFuncStart(gCOMTypeHandleFuncs) FCFuncElement("GetFields", RuntimeTypeHandle::GetFields) FCFuncElement("GetInterfaces", RuntimeTypeHandle::GetInterfaces) FCFuncElement("GetAttributes", RuntimeTypeHandle::GetAttributes) - FCFuncElement("_GetMetadataImport", RuntimeTypeHandle::GetMetadataImport) FCFuncElement("GetNumVirtuals", RuntimeTypeHandle::GetNumVirtuals) FCFuncElement("GetNumVirtualsAndStaticVirtuals", RuntimeTypeHandle::GetNumVirtualsAndStaticVirtuals) FCFuncElement("CanCastTo", RuntimeTypeHandle::CanCastTo) @@ -156,6 +155,7 @@ FCFuncStart(gCOMTypeHandleFuncs) FCFuncEnd() FCFuncStart(gMetaDataImport) + FCFuncElement("GetMetadataImport", MetaDataImport::GetMetadataImport) FCFuncElement("GetDefaultValue", MetaDataImport::GetDefaultValue) FCFuncElement("GetName", MetaDataImport::GetName) FCFuncElement("GetUserString", MetaDataImport::GetUserString) @@ -236,7 +236,6 @@ FCFuncEnd() FCFuncStart(gCOMModuleHandleFuncs) FCFuncElement("GetToken", ModuleHandle::GetToken) FCFuncElement("GetDynamicMethod", ModuleHandle::GetDynamicMethod) - FCFuncElement("_GetMetadataImport", ModuleHandle::GetMetadataImport) FCFuncElement("GetMDStreamVersion", ModuleHandle::GetMDStreamVersion) FCFuncEnd() diff --git a/src/coreclr/vm/managedmdimport.cpp b/src/coreclr/vm/managedmdimport.cpp index 200a330df62c67..8ab00a85f5320c 100644 --- a/src/coreclr/vm/managedmdimport.cpp +++ b/src/coreclr/vm/managedmdimport.cpp @@ -67,6 +67,16 @@ FCIMPL11(FC_BOOL_RET, MetaDataImport::GetMarshalAs, } FCIMPLEND +FCIMPL1(IMDInternalImport*, MetaDataImport::GetMetadataImport, ReflectModuleBaseObject * pModuleUNSAFE) +{ + FCALL_CONTRACT; + + REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE); + Module *pModule = refModule->GetModule(); + return pModule->GetMDImport(); +} +FCIMPLEND + FCIMPL6(HRESULT, MetaDataImport::GetDefaultValue, IMDInternalImport* pScope, mdToken tk, INT64* pDefaultValue, LPCWSTR* pStringValue, INT32* pLength, INT32* pCorElementType) { FCALL_CONTRACT; diff --git a/src/coreclr/vm/managedmdimport.hpp b/src/coreclr/vm/managedmdimport.hpp index 817c5fa426a4c5..4db05291d6fd0b 100644 --- a/src/coreclr/vm/managedmdimport.hpp +++ b/src/coreclr/vm/managedmdimport.hpp @@ -27,6 +27,7 @@ typedef struct class MetaDataImport { public: + static FCDECL1(IMDInternalImport*, GetMetadataImport, ReflectModuleBaseObject* pModuleUNSAFE); static FCDECL2(HRESULT, GetScopeProps, IMDInternalImport* pScope, GUID* pmvid); static FCDECL3(HRESULT, GetMemberRefProps, IMDInternalImport* pScope, mdMemberRef mr, ConstArray* ppvSigBlob); diff --git a/src/coreclr/vm/runtimehandles.cpp b/src/coreclr/vm/runtimehandles.cpp index 4598f4d1e49a4b..c660763f11577b 100644 --- a/src/coreclr/vm/runtimehandles.cpp +++ b/src/coreclr/vm/runtimehandles.cpp @@ -1488,21 +1488,6 @@ FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::ContainsGenericVariables, PTR_ReflectCla } FCIMPLEND -FCIMPL1(IMDInternalImport*, RuntimeTypeHandle::GetMetadataImport, ReflectClassBaseObject * pTypeUNSAFE) -{ - FCALL_CONTRACT; - - REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE); - - if (refType == NULL) - FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); - - Module *pModule = refType->GetType().GetModule(); - - return pModule->GetMDImport(); -} -FCIMPLEND - extern "C" void* QCALLTYPE RuntimeTypeHandle_AllocateTypeAssociatedMemory(QCall::TypeHandle type, uint32_t size) { QCALL_CONTRACT; @@ -2790,20 +2775,6 @@ FCIMPL1(INT32, ModuleHandle::GetToken, ReflectModuleBaseObject * pModuleUNSAFE) } FCIMPLEND -FCIMPL1(IMDInternalImport*, ModuleHandle::GetMetadataImport, ReflectModuleBaseObject * pModuleUNSAFE) -{ - FCALL_CONTRACT; - - REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE); - - if (refModule == NULL) - FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); - - Module *pModule = refModule->GetModule(); - return pModule->GetMDImport(); -} -FCIMPLEND - extern "C" void QCALLTYPE ModuleHandle_ResolveType(QCall::ModuleHandle pModule, INT32 tkType, TypeHandle *typeArgs, INT32 typeArgsCount, TypeHandle *methodArgs, INT32 methodArgsCount, QCall::ObjectHandleOnStack retType) { QCALL_CONTRACT; diff --git a/src/coreclr/vm/runtimehandles.h b/src/coreclr/vm/runtimehandles.h index 6b0d995977c654..56bb2df245f9f7 100644 --- a/src/coreclr/vm/runtimehandles.h +++ b/src/coreclr/vm/runtimehandles.h @@ -163,8 +163,6 @@ class RuntimeTypeHandle { static FCDECL1(MethodDesc *, GetFirstIntroducedMethod, ReflectClassBaseObject* pType); static FCDECL1(void, GetNextIntroducedMethod, MethodDesc **ppMethod); - static FCDECL1(IMDInternalImport*, GetMetadataImport, ReflectClassBaseObject * pModuleUNSAFE); - // Helper methods not called by managed code static void ValidateTypeAbleToBeInstantiated(TypeHandle typeHandle, bool fGetUninitializedObject); @@ -316,13 +314,7 @@ class ModuleHandle { public: static FCDECL5(ReflectMethodObject*, GetDynamicMethod, ReflectMethodObject *pMethodUNSAFE, ReflectModuleBaseObject *pModuleUNSAFE, StringObject *name, U1Array *sig, Object *resolver); static FCDECL1(INT32, GetToken, ReflectModuleBaseObject *pModuleUNSAFE); - - static - FCDECL1(IMDInternalImport*, GetMetadataImport, ReflectModuleBaseObject * pModuleUNSAFE); - - static - FCDECL1(INT32, GetMDStreamVersion, ReflectModuleBaseObject * pModuleUNSAFE); - + static FCDECL1(INT32, GetMDStreamVersion, ReflectModuleBaseObject * pModuleUNSAFE); }; extern "C" void QCALLTYPE ModuleHandle_GetModuleType(QCall::ModuleHandle pModule, QCall::ObjectHandleOnStack retType); From 33092b8097464a17a021224476ff121fedc4a8fd Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 21:29:47 -0500 Subject: [PATCH 079/248] Update dependencies from https://github.com/dotnet/emsdk build 20240422.2 (#101425) Microsoft.SourceBuild.Intermediate.emsdk , Microsoft.NET.Runtime.Emscripten.3.1.34.Python.win-x64 , Microsoft.NET.Workload.Emscripten.Current.Manifest-9.0.100.Transport From Version 9.0.0-preview.4.24215.3 -> To Version 9.0.0-preview.4.24222.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 12 ++++++------ eng/Versions.props | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index d3abb581e0f162..3473e1d653c37e 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -12,9 +12,9 @@ https://github.com/dotnet/wcf 7f504aabb1988e9a093c1e74d8040bd52feb2f01 - + https://github.com/dotnet/emsdk - 19c9523f5c2dd091b49959700723af795d6ad2b4 + 9d28301f6a5f512db14f242f7403a4bfbcbcc8a4 https://github.com/dotnet/llvm-project @@ -68,14 +68,14 @@ 861f49c137941b9722a43e5993ccac7716c8528c - + https://github.com/dotnet/emsdk - 19c9523f5c2dd091b49959700723af795d6ad2b4 + 9d28301f6a5f512db14f242f7403a4bfbcbcc8a4 - + https://github.com/dotnet/emsdk - 19c9523f5c2dd091b49959700723af795d6ad2b4 + 9d28301f6a5f512db14f242f7403a4bfbcbcc8a4 diff --git a/eng/Versions.props b/eng/Versions.props index 95e1a7403b2580..5e732a3a2e1871 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -235,9 +235,9 @@ Note: when the name is updated, make sure to update dependency name in eng/pipelines/common/xplat-setup.yml like - DarcDependenciesChanged.Microsoft_NET_Workload_Emscripten_Current_Manifest-9_0_100_Transport --> - 9.0.0-preview.4.24215.3 + 9.0.0-preview.4.24222.2 $(MicrosoftNETWorkloadEmscriptenCurrentManifest90100TransportVersion) - 9.0.0-preview.4.24215.3 + 9.0.0-preview.4.24222.2 1.1.87-gba258badda 1.0.0-v3.14.0.5722 From 9aaf6027cae3fe92e5d5903adaddfd1b0dbdb1fa Mon Sep 17 00:00:00 2001 From: Austin Wise Date: Tue, 23 Apr 2024 20:51:46 -0700 Subject: [PATCH 080/248] [mono] Fix condition for disabling extra checks in verify_class_overrides (#101445) `ENABLE_CHECKED_BUILD` is defined to mean "Enable additional checks" and is enabled in checked and debug builds. Therefore this performance optimization should be enabled when `ENABLE_CHECKED_BUILD` is *not* defined. Ref: #101312 --- src/mono/mono/metadata/class-setup-vtable.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/mono/mono/metadata/class-setup-vtable.c b/src/mono/mono/metadata/class-setup-vtable.c index 62afa76dde5b74..b2f13d72dfc47c 100644 --- a/src/mono/mono/metadata/class-setup-vtable.c +++ b/src/mono/mono/metadata/class-setup-vtable.c @@ -773,9 +773,7 @@ mono_method_get_method_definition (MonoMethod *method) static gboolean verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum) { - // on windows and arm, we define NDEBUG for release builds - // on browser and wasi, we define DEBUG for debug builds -#ifdef ENABLE_CHECKED_BUILD +#ifndef ENABLE_CHECKED_BUILD if (klass->image == mono_defaults.corlib) return TRUE; #endif From bc9fc5a774d96f95abe0ea5c90fac48b38ed2e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Wed, 24 Apr 2024 17:16:43 +0900 Subject: [PATCH 081/248] Run System.Net.Http trimming tests with AOT (#101416) --- .../tests/TrimmingTests/System.Net.Http.TrimmingTests.proj | 2 ++ src/libraries/tests.proj | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Net.Http/tests/TrimmingTests/System.Net.Http.TrimmingTests.proj b/src/libraries/System.Net.Http/tests/TrimmingTests/System.Net.Http.TrimmingTests.proj index ca55774a5ac45d..ea8bfeffaa4bbb 100644 --- a/src/libraries/System.Net.Http/tests/TrimmingTests/System.Net.Http.TrimmingTests.proj +++ b/src/libraries/System.Net.Http/tests/TrimmingTests/System.Net.Http.TrimmingTests.proj @@ -5,6 +5,8 @@ browser-wasm + + true diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 5d1b0a0c7fb4fe..6610727190fb34 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -650,7 +650,6 @@ - From 3027ff1de78eca5319f1f3239c12817a5d7c7063 Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Wed, 24 Apr 2024 14:09:12 +0300 Subject: [PATCH 082/248] Fix a compiler error on alpine-arm64 (#101206) --- src/coreclr/jit/optimizebools.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/optimizebools.cpp b/src/coreclr/jit/optimizebools.cpp index 0524fc5d2022c6..f915cf7c349481 100644 --- a/src/coreclr/jit/optimizebools.cpp +++ b/src/coreclr/jit/optimizebools.cpp @@ -1248,7 +1248,7 @@ void OptBoolsDsc::optOptimizeBoolsUpdateTrees() optReturnBlock = true; } - assert(m_cmpOp != NULL && m_c1 != nullptr && m_c2 != nullptr); + assert(m_cmpOp != GT_NONE && m_c1 != nullptr && m_c2 != nullptr); GenTree* cmpOp1 = m_foldOp == GT_NONE ? m_c1 : m_comp->gtNewOperNode(m_foldOp, m_foldType, m_c1, m_c2); if (m_testInfo1.isBool && m_testInfo2.isBool) From 33e3f0c746c38e10b701932d14230830647dddc6 Mon Sep 17 00:00:00 2001 From: Andzej Korovacki Date: Wed, 24 Apr 2024 14:15:14 +0300 Subject: [PATCH 083/248] Change all Cookie localized DateTime logic with Universal alternative (#100489) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Change all localized DateTime logic with Universal alternative * tests adjusted * comment updated according to changes * Update src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest.cs Co-authored-by: Radek Zikmund <32671551+rzikm@users.noreply.github.com> * Code review comment fix --------- Co-authored-by: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Co-authored-by: Marie Píchová <11718369+ManickaP@users.noreply.github.com> --- src/libraries/Common/src/System/Net/CookieParser.cs | 2 +- .../System.Net.Primitives/src/System/Net/Cookie.cs | 8 ++++---- .../tests/FunctionalTests/CookieTest.cs | 10 ++++++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/libraries/Common/src/System/Net/CookieParser.cs b/src/libraries/Common/src/System/Net/CookieParser.cs index bd6b262b5b4f54..9148b479a1f113 100644 --- a/src/libraries/Common/src/System/Net/CookieParser.cs +++ b/src/libraries/Common/src/System/Net/CookieParser.cs @@ -665,7 +665,7 @@ private static FieldInfo IsQuotedVersionField expiresSet = true; if (int.TryParse(CheckQuoted(_tokenizer.Value), out int parsed)) { - cookie!.Expires = DateTime.Now.AddSeconds(parsed); + cookie!.Expires = DateTime.UtcNow.AddSeconds(parsed); } else { diff --git a/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs b/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs index 8e21138d1b58f5..b25a5df1db2d1c 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs @@ -63,7 +63,7 @@ public sealed class Cookie private bool m_secure; // Do not rename (binary serialization) [System.Runtime.Serialization.OptionalField] private bool m_httpOnly = false; // Do not rename (binary serialization) - private DateTime m_timeStamp = DateTime.Now; // Do not rename (binary serialization) + private DateTime m_timeStamp = DateTime.UtcNow; // Do not rename (binary serialization) private string m_value = string.Empty; // Do not rename (binary serialization) private int m_version; // Do not rename (binary serialization) @@ -199,13 +199,13 @@ public bool Expired { get { - return (m_expires != DateTime.MinValue) && (m_expires.ToLocalTime() <= DateTime.Now); + return (m_expires != DateTime.MinValue) && (m_expires.ToUniversalTime() <= DateTime.UtcNow); } set { if (value) { - m_expires = DateTime.Now; + m_expires = DateTime.UtcNow; } } } @@ -801,7 +801,7 @@ internal void ToString(StringBuilder sb) } if (Expires != DateTime.MinValue) { - int seconds = (int)(Expires.ToLocalTime() - DateTime.Now).TotalSeconds; + int seconds = (int)(Expires.ToUniversalTime() - DateTime.UtcNow).TotalSeconds; if (seconds < 0) { // This means that the cookie has already expired. Set Max-Age to 0 diff --git a/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest.cs b/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest.cs index 1ba710d4f46e86..11fa3ba37026ee 100644 --- a/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest.cs +++ b/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest.cs @@ -116,10 +116,10 @@ public static void Expired_GetSet_Success() Cookie c = new Cookie(); Assert.False(c.Expired); - c.Expires = DateTime.Now.AddDays(-1); + c.Expires = DateTime.UtcNow.AddDays(-1); Assert.True(c.Expired); - c.Expires = DateTime.Now.AddDays(1); + c.Expires = DateTime.UtcNow.AddDays(1); Assert.False(c.Expired); c.Expired = true; @@ -135,7 +135,7 @@ public static void Expires_GetSet_Success() Cookie c = new Cookie(); Assert.Equal(c.Expires, DateTime.MinValue); - DateTime dt = DateTime.Now; + DateTime dt = DateTime.UtcNow; c.Expires = dt; Assert.Equal(dt, c.Expires); } @@ -226,7 +226,9 @@ public static void Secure_GetSet_Success() [Fact] public static void Timestamp_GetSet_Success() { - DateTime dt = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, 0); //DateTime.Now changes as the test runs + //DateTime.UtcNow changes as the test runs + DateTime dt = DateTime.UtcNow; + dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0); Cookie c = new Cookie(); Assert.True(c.TimeStamp >= dt); } From e01db175827165aa9b056d3127ce2bcc40a311f9 Mon Sep 17 00:00:00 2001 From: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Wed, 24 Apr 2024 13:30:55 +0200 Subject: [PATCH 084/248] Disable frequently failing tests (#101439) --- .../Net/Http/HttpClientHandlerTest.Cookies.cs | 9 +++- .../System/Net/Http/HttpClientHandlerTest.cs | 49 ++++++++++--------- .../HttpClientHandlerTest.AltSvc.cs | 9 +++- .../HttpClientHandlerTest.Headers.cs | 9 +++- 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs index b2f03bfbc930e5..714cec7bae3d56 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs @@ -216,10 +216,15 @@ private string GetCookieValue(HttpRequestData request) return cookieHeaderValue; } - [Fact] + [ConditionalFact] [SkipOnPlatform(TestPlatforms.Browser, "CookieContainer is not supported on Browser")] public async Task GetAsync_SetCookieContainerAndCookieHeader_BothCookiesSent() { + if (UseVersion == HttpVersion30) + { + throw new SkipTestException("https://github.com/dotnet/runtime/issues/101377"); + } + await LoopbackServerFactory.CreateServerAsync(async (server, url) => { HttpClientHandler handler = CreateHttpClientHandler(); @@ -313,7 +318,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async url => using (HttpClient client = CreateHttpClient(handler)) { client.DefaultRequestHeaders.ConnectionClose = true; // to avoid issues with connection pooling - await client.GetAsync(url1); + await client.GetAsync(url1); } }, async server => diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs index 7c3d3f385d0bd9..0e6faffa6d1622 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs @@ -270,7 +270,7 @@ await LoopbackServer.CreateClientAndServerAsync(async proxyUri => public static IEnumerable SecureAndNonSecure_IPBasedUri_MemberData() => from address in new[] { IPAddress.Loopback, IPAddress.IPv6Loopback } from useSsl in BoolValues - // we could not create SslStream in browser, [ActiveIssue("https://github.com/dotnet/runtime/issues/37669", TestPlatforms.Browser)] + // we could not create SslStream in browser, [ActiveIssue("https://github.com/dotnet/runtime/issues/37669", TestPlatforms.Browser)] where PlatformDetection.IsNotBrowser || !useSsl select new object[] { address, useSsl }; @@ -880,8 +880,8 @@ await LoopbackServer.CreateClientAndServerAsync(async url => "\r\n" + "5\r\n" + "hello" + // missing \r\n terminator - //"5\r\n" + - //"world" + // missing \r\n terminator + //"5\r\n" + + //"world" + // missing \r\n terminator "0\r\n" + "\r\n")); } @@ -985,7 +985,7 @@ await connection.WriteStringAsync( }); } - [Theory] + [ConditionalTheory] [InlineData(true, true, true)] [InlineData(true, true, false)] [InlineData(true, false, false)] @@ -995,6 +995,11 @@ await connection.WriteStringAsync( [ActiveIssue("https://github.com/dotnet/runtime/issues/65429", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] public async Task ReadAsStreamAsync_HandlerProducesWellBehavedResponseStream(bool? chunked, bool enableWasmStreaming, bool slowChunks) { + if (UseVersion == HttpVersion30) + { + throw new SkipTestException("https://github.com/dotnet/runtime/issues/91757"); + } + if (IsWinHttpHandler && UseVersion >= HttpVersion20.Value) { return; @@ -1094,7 +1099,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => if (PlatformDetection.IsBrowser) { #if !NETFRAMEWORK - if(slowChunks) + if (slowChunks) { Assert.Equal(1, await responseStream.ReadAsync(new Memory(buffer2))); Assert.Equal((byte)'h', buffer2[0]); @@ -1204,7 +1209,7 @@ await server.AcceptConnectionAsync(async connection => { case true: await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] { new HttpHeaderData("Transfer-Encoding", "chunked") }, isFinal: false); - if(PlatformDetection.IsBrowser && slowChunks) + if (PlatformDetection.IsBrowser && slowChunks) { await connection.SendResponseBodyAsync("1\r\nh\r\n", false); await tcs.Task; @@ -1219,12 +1224,12 @@ await server.AcceptConnectionAsync(async connection => break; case false: - await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] { new HttpHeaderData("Content-Length", "11")}, content: "hello world"); + await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] { new HttpHeaderData("Content-Length", "11") }, content: "hello world"); break; case null: // This inject Content-Length header with null value to hint Loopback code to not include one automatically. - await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] { new HttpHeaderData("Content-Length", null)}, isFinal: false); + await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] { new HttpHeaderData("Content-Length", null) }, isFinal: false); await connection.SendResponseBodyAsync("hello world"); break; } @@ -1459,10 +1464,10 @@ await LoopbackServerFactory.CreateServerAsync(async (server3, url3) => Task serverTask3 = server3.AcceptConnectionAsync(async connection3 => { await connection3.ReadRequestDataAsync(); - await connection3.SendResponseAsync(HttpStatusCode.OK, new HttpHeaderData[] { new HttpHeaderData("Content-Length", "20") }, isFinal : false); - await connection3.SendResponseBodyAsync("1234567890", isFinal : false); + await connection3.SendResponseAsync(HttpStatusCode.OK, new HttpHeaderData[] { new HttpHeaderData("Content-Length", "20") }, isFinal: false); + await connection3.SendResponseBodyAsync("1234567890", isFinal: false); await unblockServers.Task; - await connection3.SendResponseBodyAsync("1234567890", isFinal : true); + await connection3.SendResponseBodyAsync("1234567890", isFinal: true); }); // Make three requests @@ -1536,7 +1541,7 @@ public async Task GetAsync_UnicodeHostName_SuccessStatusCodeInResponse() } } -#region Post Methods Tests + #region Post Methods Tests [Fact] [SkipOnPlatform(TestPlatforms.Browser, "ExpectContinue not supported on Browser")] @@ -1580,13 +1585,13 @@ await server.AcceptConnectionAsync(async connection => public static IEnumerable Interim1xxStatusCode() { - yield return new object[] { (HttpStatusCode) 100 }; // 100 Continue. + yield return new object[] { (HttpStatusCode)100 }; // 100 Continue. // 101 SwitchingProtocols will be treated as a final status code. - yield return new object[] { (HttpStatusCode) 102 }; // 102 Processing. - yield return new object[] { (HttpStatusCode) 103 }; // 103 EarlyHints. - yield return new object[] { (HttpStatusCode) 150 }; - yield return new object[] { (HttpStatusCode) 180 }; - yield return new object[] { (HttpStatusCode) 199 }; + yield return new object[] { (HttpStatusCode)102 }; // 102 Processing. + yield return new object[] { (HttpStatusCode)103 }; // 103 EarlyHints. + yield return new object[] { (HttpStatusCode)150 }; + yield return new object[] { (HttpStatusCode)180 }; + yield return new object[] { (HttpStatusCode)199 }; } [Theory] @@ -1647,7 +1652,7 @@ await server.AcceptConnectionAsync(async connection => new HttpHeaderData("Content-type", "text/xml"), new HttpHeaderData("Set-Cookie", SetCookieIgnored1)}, isFinal: false); - await connection.SendResponseAsync(responseStatusCode, headers: new HttpHeaderData[] { + await connection.SendResponseAsync(responseStatusCode, headers: new HttpHeaderData[] { new HttpHeaderData("Cookie", "ignore_cookie=choco2"), new HttpHeaderData("Content-type", "text/plain"), new HttpHeaderData("Set-Cookie", SetCookieIgnored2)}, isFinal: false); @@ -1751,7 +1756,7 @@ await server.AcceptConnectionAsync(async connection => { await connection.ReadRequestDataAsync(readBody: false); // Send multiple 100-Continue responses. - for (int count = 0 ; count < 4; count++) + for (int count = 0; count < 4; count++) { await connection.SendResponseAsync(HttpStatusCode.Continue, isFinal: false); } @@ -1855,7 +1860,7 @@ await server.AcceptConnectionAsync(async connection => { await connection.ReadRequestDataAsync(readBody: false); - await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] {new HttpHeaderData("Content-Length", $"{ResponseString.Length}")}, isFinal : false); + await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] { new HttpHeaderData("Content-Length", $"{ResponseString.Length}") }, isFinal: false); byte[] body = await connection.ReadRequestBodyAsync(); Assert.Equal(RequestString, Encoding.ASCII.GetString(body)); @@ -2136,7 +2141,7 @@ await LoopbackServerFactory.CreateServerAsync(async (server, rootUrl) => } }); } -#endregion + #endregion [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowserDomSupported))] public async Task GetAsync_InvalidUrl_ExpectedExceptionThrown() diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AltSvc.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AltSvc.cs index f71efde6631058..d20b0f2635dcab 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AltSvc.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AltSvc.cs @@ -8,6 +8,8 @@ using System.Net.Test.Common; using System.Net.Quic; +using Microsoft.DotNet.XUnitExtensions; + namespace System.Net.Http.Functional.Tests { public abstract class HttpClientHandler_AltSvc_Test : HttpClientHandlerTestBase @@ -71,9 +73,14 @@ public async Task AltSvc_Header_Upgrade_Success(Version fromVersion, bool overri { HttpVersion.Version20, false } }; - [Fact] + [ConditionalFact] public async Task AltSvc_ConnectionFrame_UpgradeFrom20_Success() { + if (UseVersion == HttpVersion30) + { + throw new SkipTestException("https://github.com/dotnet/runtime/issues/101376"); + } + using Http2LoopbackServer firstServer = Http2LoopbackServer.CreateServer(); using Http3LoopbackServer secondServer = CreateHttp3LoopbackServer(); using HttpClient client = CreateHttpClient(HttpVersion.Version20); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs index 663e3e3a4e1483..4807d9de7842cd 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs @@ -13,6 +13,8 @@ using Xunit; using Xunit.Abstractions; +using Microsoft.DotNet.XUnitExtensions; + namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; @@ -283,12 +285,17 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => }); } - [Theory] + [ConditionalTheory] [InlineData("Thu, 01 Dec 1994 16:00:00 GMT", true)] [InlineData("-1", false)] [InlineData("0", false)] public async Task SendAsync_Expires_Success(string value, bool isValid) { + if (UseVersion == HttpVersion30) + { + throw new SkipTestException("https://github.com/dotnet/runtime/issues/91757"); + } + await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { using (HttpClient client = CreateHttpClient()) From e58be4792208e1cda48620901e6c7822262809e5 Mon Sep 17 00:00:00 2001 From: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Wed, 24 Apr 2024 13:33:23 +0200 Subject: [PATCH 085/248] Fix ReadAsStreamAsync_HandlerProducesWellBehavedResponseStream for Http3 (#101447) --- .../Common/tests/System/Net/Http/Http3LoopbackConnection.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs index 9d6fef5fb3a720..5635b753a5f6cf 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs @@ -198,7 +198,6 @@ public async Task DisposeCurrentStream() await _currentStream.DisposeAsync().ConfigureAwait(false); _openStreams.Remove((int)_currentStreamId); _currentStream = null; - _currentStreamId = -4; } public override async Task ReadRequestBodyAsync() From 0549076be34a047c712033372f29d4b0c11fffae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Wed, 24 Apr 2024 14:34:11 +0200 Subject: [PATCH 086/248] [browser] More meaningful code in browser template (#101287) --- .../scenarios/BuildWasmAppsJobsList.txt | 2 +- .../Templates/WasmTemplateTests.cs | 78 +++++++++++++------ .../InterpPgoTests.cs | 50 +++--------- .../templates/templates/browser/Program.cs | 51 ++++++++++-- .../templates/browser/wwwroot/index.html | 9 ++- .../templates/browser/wwwroot/main.js | 23 +++--- .../WasmBasicTestApp/App/InterpPgoTest.cs | 21 +++++ .../WasmBasicTestApp/App/wwwroot/main.js | 23 +++++- 8 files changed, 177 insertions(+), 80 deletions(-) rename src/mono/wasm/Wasm.Build.Tests/{Templates => TestAppScenarios}/InterpPgoTests.cs (65%) create mode 100644 src/mono/wasm/testassets/WasmBasicTestApp/App/InterpPgoTest.cs diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt index 6afea6cb3e2237..11bfdab2c7414e 100644 --- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt +++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt @@ -3,7 +3,7 @@ Wasm.Build.NativeRebuild.Tests.NoopNativeRebuildTest Wasm.Build.NativeRebuild.Tests.OptimizationFlagChangeTests Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest Wasm.Build.NativeRebuild.Tests.SimpleSourceChangeRebuildTest -Wasm.Build.Templates.Tests.InterpPgoTests +Wasm.Build.Tests.TestAppScenarios.InterpPgoTests Wasm.Build.Templates.Tests.NativeBuildTests Wasm.Build.Tests.Blazor.AppsettingsTests Wasm.Build.Tests.Blazor.BuildPublishTests diff --git a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs index d3e2e506b477a4..b1927711236c8c 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs @@ -20,7 +20,25 @@ public WasmTemplateTests(ITestOutputHelper output, SharedBuildPerTestClassFixtur { } - private void UpdateProgramCS() + private string StringReplaceWithAssert(string oldContent, string oldValue, string newValue) + { + string newContent = oldContent.Replace(oldValue, newValue); + if (oldValue != newValue && oldContent == newContent) + throw new XunitException($"Replacing '{oldValue}' with '{newValue}' did not change the content '{oldContent}'"); + + return newContent; + } + + private void UpdateBrowserProgramCs() + { + var path = Path.Combine(_projectDir!, "Program.cs"); + string text = File.ReadAllText(path); + text = StringReplaceWithAssert(text, "while(true)", $"int i = 0;{Environment.NewLine}while(i++ < 10)"); + text = StringReplaceWithAssert(text, "partial class StopwatchSample", $"return 42;{Environment.NewLine}partial class StopwatchSample"); + File.WriteAllText(path, text); + } + + private void UpdateConsoleProgramCs() { string programText = """ Console.WriteLine("Hello, Console!"); @@ -30,25 +48,36 @@ private void UpdateProgramCS() """; var path = Path.Combine(_projectDir!, "Program.cs"); string text = File.ReadAllText(path); - text = text.Replace(@"Console.WriteLine(""Hello, Console!"");", programText); - text = text.Replace("return 0;", "return 42;"); + text = StringReplaceWithAssert(text, @"Console.WriteLine(""Hello, Console!"");", programText); + text = StringReplaceWithAssert(text, "return 0;", "return 42;"); File.WriteAllText(path, text); } private void UpdateBrowserMainJs(string targetFramework, string runtimeAssetsRelativePath = DefaultRuntimeAssetsRelativePath) { - base.UpdateBrowserMainJs((mainJsContent) => { - // .withExitOnUnhandledError() is available only only >net7.0 - mainJsContent = mainJsContent.Replace(".create()", + base.UpdateBrowserMainJs( + (mainJsContent) => + { + // .withExitOnUnhandledError() is available only only >net7.0 + mainJsContent = StringReplaceWithAssert( + mainJsContent, + ".create()", (targetFramework == "net8.0" || targetFramework == "net9.0") ? ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().withExitOnUnhandledError().create()" - : ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().create()"); + : ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().create()" + ); - mainJsContent = mainJsContent.Replace("runMain()", "dotnet.run()"); - mainJsContent = mainJsContent.Replace("from './_framework/dotnet.js'", $"from '{runtimeAssetsRelativePath}dotnet.js'"); + // dotnet.run() is already used in <= net8.0 + if (targetFramework != "net8.0") + mainJsContent = StringReplaceWithAssert(mainJsContent, "runMain()", "dotnet.run()"); - return mainJsContent; - }, targetFramework, runtimeAssetsRelativePath); + mainJsContent = StringReplaceWithAssert(mainJsContent, "from './_framework/dotnet.js'", $"from '{runtimeAssetsRelativePath}dotnet.js'"); + + return mainJsContent; + }, + targetFramework, + runtimeAssetsRelativePath + ); } private void UpdateConsoleMainJs() @@ -56,8 +85,7 @@ private void UpdateConsoleMainJs() string mainJsPath = Path.Combine(_projectDir!, "main.mjs"); string mainJsContent = File.ReadAllText(mainJsPath); - mainJsContent = mainJsContent - .Replace(".create()", ".withConsoleForwarding().create()"); + mainJsContent = StringReplaceWithAssert(mainJsContent, ".create()", ".withConsoleForwarding().create()"); File.WriteAllText(mainJsPath, mainJsContent); } @@ -73,8 +101,7 @@ private void UpdateMainJsEnvironmentVariables(params (string key, string value)[ js.Append($".withEnvironmentVariable(\"{variable.key}\", \"{variable.value}\")"); } - mainJsContent = mainJsContent - .Replace(".create()", js.ToString() + ".create()"); + mainJsContent = StringReplaceWithAssert(mainJsContent, ".create()", js.ToString() + ".create()"); File.WriteAllText(mainJsPath, mainJsContent); } @@ -88,6 +115,7 @@ public void BrowserBuildThenPublish(string config) string projectFile = CreateWasmTemplateProject(id, "wasmbrowser"); string projectName = Path.GetFileNameWithoutExtension(projectFile); + UpdateBrowserProgramCs(); UpdateBrowserMainJs(DefaultTargetFramework); var buildArgs = new BuildArgs(projectName, config, false, id, null); @@ -96,10 +124,10 @@ public void BrowserBuildThenPublish(string config) atTheEnd: """ - - <_LinkedOutFile Include="$(IntermediateOutputPath)\linked\*.dll" /> - - + + <_LinkedOutFile Include="$(IntermediateOutputPath)\linked\*.dll" /> + + """ ); @@ -212,7 +240,7 @@ private void ConsoleBuildAndRun(string config, bool relinking, string extraNewAr string projectFile = CreateWasmTemplateProject(id, "wasmconsole", extraNewArgs, addFrameworkArg: addFrameworkArg); string projectName = Path.GetFileNameWithoutExtension(projectFile); - UpdateProgramCS(); + UpdateConsoleProgramCs(); UpdateConsoleMainJs(); if (relinking) AddItemsPropertiesToProject(projectFile, "true"); @@ -277,6 +305,7 @@ private async Task BrowserRunTwiceWithAndThenWithoutBuildAsync(string config, st string id = $"browser_{config}_{GetRandomId()}"; string projectFile = CreateWasmTemplateProject(id, "wasmbrowser"); + UpdateBrowserProgramCs(); UpdateBrowserMainJs(DefaultTargetFramework); if (!string.IsNullOrEmpty(extraProperties)) @@ -310,7 +339,7 @@ private Task ConsoleRunWithAndThenWithoutBuildAsync(string config, string extraP string id = $"console_{config}_{GetRandomId()}"; string projectFile = CreateWasmTemplateProject(id, "wasmconsole"); - UpdateProgramCS(); + UpdateConsoleProgramCs(); UpdateConsoleMainJs(); if (!string.IsNullOrEmpty(extraProperties)) @@ -374,7 +403,7 @@ public void ConsolePublishAndRun(string config, bool aot, bool relinking) string projectFile = CreateWasmTemplateProject(id, "wasmconsole"); string projectName = Path.GetFileNameWithoutExtension(projectFile); - UpdateProgramCS(); + UpdateConsoleProgramCs(); UpdateConsoleMainJs(); if (aot) @@ -436,6 +465,9 @@ public async Task BrowserBuildAndRun(string extraNewArgs, string targetFramework string id = $"browser_{config}_{GetRandomId()}"; CreateWasmTemplateProject(id, "wasmbrowser", extraNewArgs, addFrameworkArg: extraNewArgs.Length == 0); + if (targetFramework != "net8.0") + UpdateBrowserProgramCs(); + UpdateBrowserMainJs(targetFramework, runtimeAssetsRelativePath); new DotNetCommand(s_buildEnv, _testOutput) @@ -518,7 +550,7 @@ public void Test_WasmStripILAfterAOT(string stripILAfterAOT, bool expectILStripp string projectDirectory = Path.GetDirectoryName(projectFile)!; bool aot = true; - UpdateProgramCS(); + UpdateConsoleProgramCs(); UpdateConsoleMainJs(); string extraProperties = "true"; diff --git a/src/mono/wasm/Wasm.Build.Tests/Templates/InterpPgoTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/InterpPgoTests.cs similarity index 65% rename from src/mono/wasm/Wasm.Build.Tests/Templates/InterpPgoTests.cs rename to src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/InterpPgoTests.cs index 4fe88ee8daca3d..24e052f96d3fb4 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Templates/InterpPgoTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/InterpPgoTests.cs @@ -13,9 +13,9 @@ #nullable enable -namespace Wasm.Build.Templates.Tests; +namespace Wasm.Build.Tests.TestAppScenarios; -public class InterpPgoTests : WasmTemplateTestBase +public class InterpPgoTests : AppTestBase { public InterpPgoTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) : base(output, buildContext) @@ -32,41 +32,11 @@ public async Task FirstRunGeneratesTableAndSecondRunLoadsIt(string config) // Invoking it too many times makes the test meaningfully slower. const int iterationCount = 70; - string id = $"browser_{config}_{GetRandomId()}"; _testOutput.WriteLine("/// Creating project"); - string projectFile = CreateWasmTemplateProject(id, "wasmbrowser", extraProperties: "0"); - - _testOutput.WriteLine("/// Updating JS"); - UpdateBrowserMainJs((js) => { - // We need to capture INTERNAL so we can explicitly save the PGO table - js = js.Replace( - "const { setModuleImports, getAssemblyExports, getConfig, runMain } = await dotnet", - "const { setModuleImports, getAssemblyExports, getConfig, runMain, INTERNAL } = await dotnet" - ); - // Enable interpreter PGO + interpreter PGO logging + console output capturing - js = js.Replace( - ".create()", - ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().withExitOnUnhandledError().withRuntimeOptions(['--interp-pgo-logging']).withInterpreterPgo(true).create()" - ); - js = js.Replace("runMain()", "dotnet.run()"); - // Call Greeting in a loop to exercise enough code to cause something to tier, - // then call INTERNAL.interp_pgo_save_data() to save the interp PGO table - js = js.Replace( - "const text = exports.MyClass.Greeting();", - "console.log(`WASM debug level ${getConfig().debugLevel}`);\n" + - "let text = '';\n" + - $"for (let i = 0; i < {iterationCount}; i++) {{ text = exports.MyClass.Greeting(); }};\n" + - "await INTERNAL.interp_pgo_save_data();" - ); - return js; - }, DefaultTargetFramework); + CopyTestAsset("WasmBasicTestApp", "InterpPgoTest", "App"); _testOutput.WriteLine("/// Building"); - - new DotNetCommand(s_buildEnv, _testOutput) - .WithWorkingDirectory(_projectDir!) - .Execute($"build -c {config} -bl:{Path.Combine(s_buildEnv.LogRootPath, $"{id}.binlog")}") - .EnsureSuccessful(); + BuildProject(config, extraArgs: "-p:WasmDebugLevel=0"); _testOutput.WriteLine("/// Starting server"); @@ -75,7 +45,11 @@ public async Task FirstRunGeneratesTableAndSecondRunLoadsIt(string config) using var runCommand = new RunCommand(s_buildEnv, _testOutput) .WithWorkingDirectory(_projectDir!); await using var runner = new BrowserRunner(_testOutput); - var url = await runner.StartServerAndGetUrlAsync(runCommand, $"run --no-silent -c {config} --no-build --project \"{projectFile}\" --forward-console"); + var url = await runner.StartServerAndGetUrlAsync(runCommand, $"run --no-silent -c {config} --no-build --project \"{_projectDir!}\" --forward-console"); + url = $"{url}?test=InterpPgoTest&iterationCount={iterationCount}"; + + _testOutput.WriteLine($"/// Spawning browser at URL {url}"); + IBrowser browser = await runner.SpawnBrowserAsync(url); IBrowserContext context = await browser.NewContextAsync(); @@ -83,11 +57,11 @@ public async Task FirstRunGeneratesTableAndSecondRunLoadsIt(string config) { _testOutput.WriteLine("/// First run"); var page = await runner.RunAsync(context, url); - await runner.WaitForExitMessageAsync(TimeSpan.FromSeconds(30)); + await runner.WaitForExitMessageAsync(TimeSpan.FromSeconds(6 * 30)); lock (runner.OutputLines) output = string.Join(Environment.NewLine, runner.OutputLines); - Assert.Contains("Hello, Browser!", output); + Assert.Contains("Hello, World!", output); // Verify that no PGO table was located in cache Assert.Contains("Failed to load interp_pgo table", output); // Verify that the table was saved after the app ran @@ -107,7 +81,7 @@ public async Task FirstRunGeneratesTableAndSecondRunLoadsIt(string config) lock (runner.OutputLines) output = string.Join(Environment.NewLine, runner.OutputLines); - Assert.Contains("Hello, Browser!", output); + Assert.Contains("Hello, World!", output); // Verify that table data was loaded from cache // if this breaks, it could be caused by change in config which affects the config hash and the cache storage hash key Assert.Contains(" bytes of interp_pgo data (table size == ", output); diff --git a/src/mono/wasm/templates/templates/browser/Program.cs b/src/mono/wasm/templates/templates/browser/Program.cs index ecf115b0e71284..a9726e67fd6aca 100644 --- a/src/mono/wasm/templates/templates/browser/Program.cs +++ b/src/mono/wasm/templates/templates/browser/Program.cs @@ -1,18 +1,55 @@ using System; +using System.Diagnostics; using System.Runtime.InteropServices.JavaScript; +using System.Threading.Tasks; Console.WriteLine("Hello, Browser!"); -public partial class MyClass +if (args.Length == 1 && args[0] == "start") + StopwatchSample.Start(); + +while(true) +{ + StopwatchSample.Render(); + await Task.Delay(1000); +} + +partial class StopwatchSample { + private static Stopwatch stopwatch = new(); + + public static void Start() => stopwatch.Start(); + public static void Render() => SetInnerText("#time", stopwatch.Elapsed.ToString(@"mm\:ss")); + + [JSImport("dom.setInnerText", "main.js")] + internal static partial void SetInnerText(string selector, string content); + [JSExport] - internal static string Greeting() + internal static bool Toggle() { - var text = $"Hello, World! Greetings from {GetHRef()}"; - Console.WriteLine(text); - return text; + if (stopwatch.IsRunning) + { + stopwatch.Stop(); + return false; + } + else + { + stopwatch.Start(); + return true; + } } - [JSImport("window.location.href", "main.js")] - internal static partial string GetHRef(); + [JSExport] + internal static void Reset() + { + if (stopwatch.IsRunning) + stopwatch.Restart(); + else + stopwatch.Reset(); + + Render(); + } + + [JSExport] + internal static bool IsRunning() => stopwatch.IsRunning; } diff --git a/src/mono/wasm/templates/templates/browser/wwwroot/index.html b/src/mono/wasm/templates/templates/browser/wwwroot/index.html index 417803bf38d934..287d8b5319216a 100644 --- a/src/mono/wasm/templates/templates/browser/wwwroot/index.html +++ b/src/mono/wasm/templates/templates/browser/wwwroot/index.html @@ -11,7 +11,14 @@ - +

Stopwatch

+

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

+

+ + +

diff --git a/src/mono/wasm/templates/templates/browser/wwwroot/main.js b/src/mono/wasm/templates/templates/browser/wwwroot/main.js index afcf21e4e6510d..82c86ed196b4ef 100644 --- a/src/mono/wasm/templates/templates/browser/wwwroot/main.js +++ b/src/mono/wasm/templates/templates/browser/wwwroot/main.js @@ -4,24 +4,29 @@ import { dotnet } from './_framework/dotnet.js' const { setModuleImports, getAssemblyExports, getConfig, runMain } = await dotnet - .withDiagnosticTracing(false) - .withApplicationArgumentsFromQuery() + .withApplicationArguments("start") .create(); setModuleImports('main.js', { - window: { - location: { - href: () => globalThis.window.location.href - } + dom: { + setInnerText: (selector, time) => document.querySelector(selector).innerText = time } }); const config = getConfig(); const exports = await getAssemblyExports(config.mainAssemblyName); -const text = exports.MyClass.Greeting(); -console.log(text); -document.getElementById('out').innerHTML = text; +document.getElementById('reset').addEventListener('click', e => { + exports.StopwatchSample.Reset(); + e.preventDefault(); +}); + +const pauseButton = document.getElementById('pause'); +pauseButton.addEventListener('click', e => { + const isRunning = exports.StopwatchSample.Toggle(); + pauseButton.innerText = isRunning ? 'Pause' : 'Start'; + e.preventDefault(); +}); // run the C# Main() method and keep the runtime process running and executing further API calls await runMain(); \ No newline at end of file diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/InterpPgoTest.cs b/src/mono/wasm/testassets/WasmBasicTestApp/App/InterpPgoTest.cs new file mode 100644 index 00000000000000..6d093133b3771c --- /dev/null +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/InterpPgoTest.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.IO; +using System.Text.Json; +using System.Runtime.InteropServices.JavaScript; + +public partial class InterpPgoTest +{ + [JSImport("window.location.href", "main.js")] + internal static partial string GetHRef(); + + [JSExport] + internal static string Greeting() + { + var text = $"Hello, World! Greetings from {GetHRef()}"; + Console.WriteLine(text); + return text; + } +} diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js index 5aeeb024096d56..7df0706d568193 100644 --- a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js @@ -78,9 +78,15 @@ switch (testCase) { }, }); break; + case "InterpPgoTest": + dotnet + .withConsoleForwarding() + .withRuntimeOptions(['--interp-pgo-logging']) + .withInterpreterPgo(true); + break; } -const { getAssemblyExports, getConfig, INTERNAL } = await dotnet.create(); +const { setModuleImports, getAssemblyExports, getConfig, INTERNAL } = await dotnet.create(); const config = getConfig(); const exports = await getAssemblyExports(config.mainAssemblyName); const assemblyExtension = config.resources.assembly['System.Private.CoreLib.wasm'] !== undefined ? ".wasm" : ".dll"; @@ -116,6 +122,21 @@ try { testOutput("WasmDebugLevel: " + config.debugLevel); exit(0); break; + case "InterpPgoTest": + setModuleImports('main.js', { + window: { + location: { + href: () => globalThis.window.location.href + } + } + }); + const iterationCount = params.get("iterationCount") ?? 70; + for (let i = 0; i < iterationCount; i++) { + exports.InterpPgoTest.Greeting(); + }; + await INTERNAL.interp_pgo_save_data(); + exit(0); + break; default: console.error(`Unknown test case: ${testCase}`); exit(3); From 7e29a451396466bb4a8e5abb9ebfdd444cd2e8a1 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Wed, 24 Apr 2024 16:19:26 +0300 Subject: [PATCH 087/248] Disable System.Text.Json.Tests suite on interp with debug runtime (#101483) Interpreter gets very slow on debug builds and this suite can also timeout. --- .../tests/System.Text.Json.Tests/AssemblyInfo.cs | 7 +++++++ .../System.Text.Json.Tests/System.Text.Json.Tests.csproj | 1 + 2 files changed, 8 insertions(+) create mode 100644 src/libraries/System.Text.Json/tests/System.Text.Json.Tests/AssemblyInfo.cs diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/AssemblyInfo.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/AssemblyInfo.cs new file mode 100644 index 00000000000000..68af8051230a6d --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/AssemblyInfo.cs @@ -0,0 +1,7 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using Xunit; + +[assembly: ActiveIssue("Interpreter with debug runtime can be very slow", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoInterpreter), nameof(PlatformDetection.IsDebugRuntime))] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj index cada80f5cee613..1e3c083791c653 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 @@ -31,6 +31,7 @@ + From 56ee7c5950b55529c2b5618d8f9b796d1b425813 Mon Sep 17 00:00:00 2001 From: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Wed, 24 Apr 2024 16:13:16 +0200 Subject: [PATCH 088/248] Fix deadlock in TestUtilities.TestEventListener (#101493) --- .../tests/TestUtilities/TestEventListener.cs | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/libraries/Common/tests/TestUtilities/TestEventListener.cs b/src/libraries/Common/tests/TestUtilities/TestEventListener.cs index bd7b633ba6f822..3c33bdb633e36b 100644 --- a/src/libraries/Common/tests/TestUtilities/TestEventListener.cs +++ b/src/libraries/Common/tests/TestUtilities/TestEventListener.cs @@ -55,34 +55,44 @@ public TestEventListener(ITestOutputHelper output, params string[] sourceNames) public TestEventListener(Action writeFunc, params string[] sourceNames) { + List eventSources = _eventSources; + lock (this) { _writeFunc = writeFunc; _sourceNames = new HashSet(sourceNames); - foreach (EventSource eventSource in _eventSources) + _eventSources = null; + } + + // eventSources were populated in the base ctor and are now owned by this thread, enable them now. + foreach (EventSource eventSource in eventSources) + { + if (_sourceNames.Contains(eventSource.Name)) { - OnEventSourceCreated(eventSource); + EnableEvents(eventSource, EventLevel.LogAlways); } - _eventSources = null; } } protected override void OnEventSourceCreated(EventSource eventSource) { - lock (this) + // We're likely called from base ctor, if so, just save the event source for later initialization. + if (_sourceNames is null) { - // We're called from base ctor, just save the event source for later initialization. - if (_sourceNames is null) + lock (this) { - _eventSources.Add(eventSource); - return; + if (_sourceNames is null) + { + _eventSources.Add(eventSource); + return; + } } + } - // Second pass called from our ctor, allow logging for specified source names. - if (_sourceNames.Contains(eventSource.Name)) - { - EnableEvents(eventSource, EventLevel.LogAlways); - } + // Second pass called after our ctor, allow logging for specified source names. + if (_sourceNames.Contains(eventSource.Name)) + { + EnableEvents(eventSource, EventLevel.LogAlways); } } @@ -102,7 +112,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) } try { - _writeFunc(sb.ToString()); + _writeFunc?.Invoke(sb.ToString()); } catch { } } From 36e01f7193be4718624c89323e29db7f931d9f41 Mon Sep 17 00:00:00 2001 From: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Wed, 24 Apr 2024 17:03:11 +0200 Subject: [PATCH 089/248] Add more logging to HTTP3 and QUIC code (#101449) * Add more logging to QuicConnection and QuicStream * Fix ptr format * wip * Add more http3 logging * fixup! Add more http3 logging * Code review feedback --- .../SocketsHttpHandler/Http3Connection.cs | 13 +++++++++ .../Net/Quic/Internal/MsQuicExtensions.cs | 27 ++++++++++++++++-- .../src/System/Net/Quic/QuicConnection.cs | 28 +++++++++++++++++++ .../src/System/Net/Quic/QuicListener.cs | 11 ++++++++ .../src/System/Net/Quic/QuicStream.cs | 11 ++++++++ 5 files changed, 87 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs index a4e8efeca6412e..75b9d9b1f8a964 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs @@ -300,6 +300,11 @@ internal Exception Abort(Exception abortException) private void OnServerGoAway(long firstRejectedStreamId) { + if (NetEventSource.Log.IsEnabled()) + { + Trace($"GOAWAY received. First rejected stream ID = {firstRejectedStreamId}"); + } + // Stop sending requests to this connection. _pool.InvalidateHttp3Connection(this); @@ -649,6 +654,10 @@ private async Task ProcessServerControlStreamAsync(QuicStream stream, ArrayBuffe case Http3FrameType.ReservedHttp2Ping: case Http3FrameType.ReservedHttp2WindowUpdate: case Http3FrameType.ReservedHttp2Continuation: + if (NetEventSource.Log.IsEnabled()) + { + Trace($"Received reserved frame: {frameType}"); + } throw HttpProtocolException.CreateHttp3ConnectionException(Http3ErrorCode.UnexpectedFrame); case Http3FrameType.PushPromise: case Http3FrameType.CancelPush: @@ -663,6 +672,10 @@ private async Task ProcessServerControlStreamAsync(QuicStream stream, ArrayBuffe } if (!shuttingDown) { + if (NetEventSource.Log.IsEnabled()) + { + Trace($"Control stream closed by the server."); + } throw HttpProtocolException.CreateHttp3ConnectionException(Http3ErrorCode.ClosedCriticalStream); } return; diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicExtensions.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicExtensions.cs index 5c079f65287415..cfc5a09a37171c 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicExtensions.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Net.Quic; namespace Microsoft.Quic; @@ -17,7 +18,7 @@ public override string ToString() => Type switch { QUIC_LISTENER_EVENT_TYPE.NEW_CONNECTION - => $"{{ {nameof(NEW_CONNECTION.Info)} = {{ {nameof(QUIC_NEW_CONNECTION_INFO.QuicVersion)} = {NEW_CONNECTION.Info->QuicVersion}, {nameof(QUIC_NEW_CONNECTION_INFO.LocalAddress)} = {MsQuicHelpers.QuicAddrToIPEndPoint(NEW_CONNECTION.Info->LocalAddress)}, {nameof(QUIC_NEW_CONNECTION_INFO.RemoteAddress)} = {MsQuicHelpers.QuicAddrToIPEndPoint(NEW_CONNECTION.Info->RemoteAddress)} }} }}", + => $"{{ {nameof(NEW_CONNECTION.Info)} = {{ {nameof(QUIC_NEW_CONNECTION_INFO.QuicVersion)} = {NEW_CONNECTION.Info->QuicVersion}, {nameof(QUIC_NEW_CONNECTION_INFO.LocalAddress)} = {MsQuicHelpers.QuicAddrToIPEndPoint(NEW_CONNECTION.Info->LocalAddress)}, {nameof(QUIC_NEW_CONNECTION_INFO.RemoteAddress)} = {MsQuicHelpers.QuicAddrToIPEndPoint(NEW_CONNECTION.Info->RemoteAddress)} }}, {nameof(NEW_CONNECTION.Connection)} = 0x{(IntPtr)NEW_CONNECTION.Connection:X11} }}", _ => string.Empty }; } @@ -40,9 +41,29 @@ public override string ToString() QUIC_CONNECTION_EVENT_TYPE.PEER_ADDRESS_CHANGED => $"{{ {nameof(PEER_ADDRESS_CHANGED.Address)} = {MsQuicHelpers.QuicAddrToIPEndPoint(PEER_ADDRESS_CHANGED.Address)} }}", QUIC_CONNECTION_EVENT_TYPE.PEER_STREAM_STARTED - => $"{{ {nameof(PEER_STREAM_STARTED.Flags)} = {PEER_STREAM_STARTED.Flags} }}", + => $"{{ {nameof(PEER_STREAM_STARTED.Stream)} = 0x{(IntPtr)PEER_STREAM_STARTED.Stream:X11} {nameof(PEER_STREAM_STARTED.Flags)} = {PEER_STREAM_STARTED.Flags} }}", + QUIC_CONNECTION_EVENT_TYPE.STREAMS_AVAILABLE + => $"{{ {nameof(STREAMS_AVAILABLE.BidirectionalCount)} = {STREAMS_AVAILABLE.BidirectionalCount}, {nameof(STREAMS_AVAILABLE.UnidirectionalCount)} = {STREAMS_AVAILABLE.UnidirectionalCount} }}", + QUIC_CONNECTION_EVENT_TYPE.PEER_NEEDS_STREAMS + => $"{{ {nameof(PEER_NEEDS_STREAMS.Bidirectional)} = {PEER_NEEDS_STREAMS.Bidirectional} }}", + QUIC_CONNECTION_EVENT_TYPE.IDEAL_PROCESSOR_CHANGED + => $"{{ {nameof(IDEAL_PROCESSOR_CHANGED.IdealProcessor)} = {IDEAL_PROCESSOR_CHANGED.IdealProcessor}, {nameof(IDEAL_PROCESSOR_CHANGED.PartitionIndex)} = {IDEAL_PROCESSOR_CHANGED.PartitionIndex} }}", + QUIC_CONNECTION_EVENT_TYPE.DATAGRAM_STATE_CHANGED + => $"{{ {nameof(DATAGRAM_STATE_CHANGED.SendEnabled)} = {DATAGRAM_STATE_CHANGED.SendEnabled}, {nameof(DATAGRAM_STATE_CHANGED.MaxSendLength)} = {DATAGRAM_STATE_CHANGED.MaxSendLength} }}", + QUIC_CONNECTION_EVENT_TYPE.DATAGRAM_RECEIVED + => $"{{ {nameof(DATAGRAM_RECEIVED.Flags)} = {DATAGRAM_RECEIVED.Flags} }}", + QUIC_CONNECTION_EVENT_TYPE.DATAGRAM_SEND_STATE_CHANGED + => $"{{ {nameof(DATAGRAM_SEND_STATE_CHANGED.ClientContext)} = 0x{(IntPtr)DATAGRAM_SEND_STATE_CHANGED.ClientContext:X11}, {nameof(DATAGRAM_SEND_STATE_CHANGED.State)} = {DATAGRAM_SEND_STATE_CHANGED.State} }}", + QUIC_CONNECTION_EVENT_TYPE.RESUMED + => $"{{ {nameof(RESUMED.ResumptionStateLength)} = {RESUMED.ResumptionStateLength} }}", + QUIC_CONNECTION_EVENT_TYPE.RESUMPTION_TICKET_RECEIVED + => $"{{ {nameof(RESUMPTION_TICKET_RECEIVED.ResumptionTicketLength)} = {RESUMPTION_TICKET_RECEIVED.ResumptionTicketLength} }}", QUIC_CONNECTION_EVENT_TYPE.PEER_CERTIFICATE_RECEIVED - => $"{{ {nameof(PEER_CERTIFICATE_RECEIVED.DeferredStatus)} = {PEER_CERTIFICATE_RECEIVED.DeferredStatus}, {nameof(PEER_CERTIFICATE_RECEIVED.DeferredErrorFlags)} = {PEER_CERTIFICATE_RECEIVED.DeferredErrorFlags} }}", + => $"{{ {nameof(PEER_CERTIFICATE_RECEIVED.DeferredStatus)} = {PEER_CERTIFICATE_RECEIVED.DeferredStatus}, {nameof(PEER_CERTIFICATE_RECEIVED.DeferredErrorFlags)} = {PEER_CERTIFICATE_RECEIVED.DeferredErrorFlags}, {nameof(PEER_CERTIFICATE_RECEIVED.Certificate)} = 0x{(IntPtr)PEER_CERTIFICATE_RECEIVED.Certificate:X11} }}", + QUIC_CONNECTION_EVENT_TYPE.RELIABLE_RESET_NEGOTIATED + => $"{{ {nameof(RELIABLE_RESET_NEGOTIATED.IsNegotiated)} = {RELIABLE_RESET_NEGOTIATED.IsNegotiated} }}", + QUIC_CONNECTION_EVENT_TYPE.ONE_WAY_DELAY_NEGOTIATED + => $"{{ {nameof(ONE_WAY_DELAY_NEGOTIATED.SendNegotiated)} = {ONE_WAY_DELAY_NEGOTIATED.SendNegotiated}, {nameof(ONE_WAY_DELAY_NEGOTIATED.ReceiveNegotiated)} = {ONE_WAY_DELAY_NEGOTIATED.ReceiveNegotiated} }}", _ => string.Empty }; } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs index 315352d2797bb4..e568eeb6f97b7a 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 @@ -252,6 +252,11 @@ private unsafe QuicConnection() throw; } + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} New outbound connection."); + } + _tlsSecret = MsQuicTlsSecret.Create(_handle); } @@ -411,6 +416,12 @@ public async ValueTask OpenOutboundStreamAsync(QuicStreamType type, try { stream = new QuicStream(_handle, type, _defaultStreamErrorCode); + + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} New outbound {type} stream {stream}."); + } + await stream.StartAsync(cancellationToken).ConfigureAwait(false); } catch @@ -482,6 +493,11 @@ public ValueTask CloseAsync(long errorCode, CancellationToken cancellationToken if (_shutdownTcs.TryGetValueTask(out ValueTask valueTask, this, cancellationToken)) { + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} Closing connection, Error code = {errorCode}"); + } + unsafe { MsQuicApi.Api.ConnectionShutdown( @@ -551,6 +567,13 @@ private unsafe int HandleEventPeerAddressChanged(ref PEER_ADDRESS_CHANGED_DATA d private unsafe int HandleEventPeerStreamStarted(ref PEER_STREAM_STARTED_DATA data) { QuicStream stream = new QuicStream(_handle, data.Stream, data.Flags, _defaultStreamErrorCode); + + if (NetEventSource.Log.IsEnabled()) + { + QuicStreamType type = data.Flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? QuicStreamType.Unidirectional : QuicStreamType.Bidirectional; + NetEventSource.Info(this, $"{this} New inbound {type} stream {stream}, Id = {stream.Id}."); + } + if (!_acceptQueue.Writer.TryWrite(stream)) { if (NetEventSource.Log.IsEnabled()) @@ -648,6 +671,11 @@ public async ValueTask DisposeAsync() return; } + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} Disposing."); + } + // Check if the connection has been shut down and if not, shut it down. if (_shutdownTcs.TryGetValueTask(out ValueTask valueTask, this)) { diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs index 88ea309054a7db..249f7571519131 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs @@ -335,6 +335,12 @@ private unsafe int HandleEventNewConnection(ref NEW_CONNECTION_DATA data) } QuicConnection connection = new QuicConnection(data.Connection, data.Info); + + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} New inbound connection {connection}."); + } + SslClientHelloInfo clientHello = new SslClientHelloInfo(data.Info->ServerNameLength > 0 ? Marshal.PtrToStringUTF8((IntPtr)data.Info->ServerName, data.Info->ServerNameLength) : "", SslProtocols.Tls13); // Kicks off the rest of the handshake in the background, the process itself will enqueue the result in the accept queue. @@ -404,6 +410,11 @@ public async ValueTask DisposeAsync() return; } + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} Disposing."); + } + // Check if the listener has been shut down and if not, shut it down. if (_shutdownTcs.TryInitialize(out ValueTask valueTask, this)) { diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs index 06515f3310bf7f..6af0f5c5c099f3 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs @@ -225,6 +225,7 @@ internal unsafe QuicStream(MsQuicContextSafeHandle connectionHandle, QUIC_HANDLE } _id = (long)GetMsQuicParameter(_handle, QUIC_PARAM_STREAM_ID); _type = flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? QuicStreamType.Unidirectional : QuicStreamType.Bidirectional; + _startedTcs.TrySetResult(); } @@ -325,6 +326,11 @@ public override async ValueTask ReadAsync(Memory buffer, Cancellation } } + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} Stream read '{totalCopied}' bytes."); + } + return totalCopied; } @@ -690,6 +696,11 @@ public override async ValueTask DisposeAsync() return; } + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} Disposing."); + } + // If the stream wasn't started successfully, gracelessly abort it. if (!_startedTcs.IsCompletedSuccessfully) { From 5fe1a569099272cbe3cec4972c52e5531223b58e Mon Sep 17 00:00:00 2001 From: SwapnilGaikwad Date: Wed, 24 Apr 2024 16:07:10 +0100 Subject: [PATCH 090/248] Fix checks to accommodate register wraparounds in multi-reg ops (#101430) Fixes issue #101070 --- src/coreclr/jit/codegen.h | 10 ++++++++++ src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 8 ++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index f5e0dc857a7d4c..441db5f6b50d47 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -101,6 +101,16 @@ class CodeGen final : public CodeGenInterface } } +#if defined(TARGET_ARM64) + regNumber getNextSIMDRegWithWraparound(regNumber reg) + { + regNumber nextReg = REG_NEXT(reg); + + // Wraparound if necessary, REG_V0 comes next after REG_V31. + return (nextReg > REG_V31) ? REG_V0 : nextReg; + } +#endif // defined(TARGET_ARM64) + static GenTreeIndir indirForm(var_types type, GenTree* base); static GenTreeStoreInd storeIndirForm(var_types type, GenTree* base, GenTree* data); diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index 9a3a98e087a274..01914951576bfa 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -833,7 +833,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GenTree* argNode = use.GetNode(); assert(argReg == argNode->GetRegNum()); - argReg = REG_NEXT(argReg); + argReg = getNextSIMDRegWithWraparound(argReg); } assert((ins == INS_st2 && regCount == 2) || (ins == INS_st3 && regCount == 3) || (ins == INS_st4 && regCount == 4)); @@ -883,7 +883,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GenTree* argNode = use.GetNode(); assert(argReg == argNode->GetRegNum()); - argReg = REG_NEXT(argReg); + argReg = getNextSIMDRegWithWraparound(argReg); } assert((ins == INS_st1_2regs && regCount == 2) || (ins == INS_st2 && regCount == 2) || (ins == INS_st1_3regs && regCount == 3) || (ins == INS_st3 && regCount == 3) || @@ -1186,7 +1186,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GenTree* argNode = use.GetNode(); assert(argReg == argNode->GetRegNum()); - argReg = REG_NEXT(argReg); + argReg = getNextSIMDRegWithWraparound(argReg); #endif } } @@ -1241,7 +1241,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) assert(argReg == argNode->GetRegNum()); // and they should not interfere with targetReg assert(targetReg != argReg); - argReg = REG_NEXT(argReg); + argReg = getNextSIMDRegWithWraparound(argReg); #endif } } From b5ee98696f9e858a953289131c8d9e66bbde50d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Wed, 24 Apr 2024 19:26:42 +0200 Subject: [PATCH 091/248] Disable terminal logger experience for dotnet test in manual tests. (#100333) --- src/libraries/System.Console/tests/ManualTests/Readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Console/tests/ManualTests/Readme.md b/src/libraries/System.Console/tests/ManualTests/Readme.md index 6c56bce87840a7..4cd91a362a94d7 100644 --- a/src/libraries/System.Console/tests/ManualTests/Readme.md +++ b/src/libraries/System.Console/tests/ManualTests/Readme.md @@ -6,7 +6,8 @@ To run the suite, follow these steps: 1. Build the CLR and libraries. 2. Using a terminal, navigate to the current folder. 3. Enable manual testing by defining the `MANUAL_TESTS` environment variable (e.g. on bash `export MANUAL_TESTS=true`). -4. Run `dotnet test` and follow the instructions in the command prompt. +4. Disable terminal logger output for dotnet test by setting `MSBUILDENSURESTDOUTFORTASKPROCESSES=1` environment variable. (e.g. on bash `export MSBUILDENSURESTDOUTFORTASKPROCESSES=1`). +5. Run `dotnet test` and follow the instructions in the command prompt. ## Instructions for Windows testers From 1a93a9d0fc121a98f63345754cabe0f4427e37d2 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Wed, 24 Apr 2024 19:58:46 +0200 Subject: [PATCH 092/248] TypeName parsing API (#100094) Co-authored-by: Jan Kotas --- .../Reflection/TypeNameParser.CoreCLR.cs | 91 ++- .../src/System/Type.CoreCLR.cs | 1 - .../System/Reflection/RuntimeAssemblyName.cs | 23 +- .../Reflection/TypeNameParser.NativeAot.cs | 69 +- .../CustomAttributeTypeNameParser.cs | 29 +- .../ILVerification/ILVerification.projitems | 35 +- .../Dataflow/TypeNameParser.Dataflow.cs | 46 +- .../ILCompiler.Compiler.csproj | 4 +- .../ILCompiler.TypeSystem.csproj | 29 +- .../Reflection/AssemblyNameFormatter.cs | 12 +- .../System/Reflection/AssemblyNameParser.cs | 506 ++++++++++++ .../Reflection/Metadata/AssemblyNameInfo.cs | 219 +++++ .../System/Reflection/Metadata/TypeName.cs | 398 ++++++++++ .../Reflection/Metadata/TypeNameParser.cs | 260 ++++++ .../Metadata/TypeNameParserHelpers.cs | 383 +++++++++ .../Metadata/TypeNameParserOptions.cs | 41 + .../Reflection/TypeNameParser.Helpers.cs | 192 +++++ .../src/System/Reflection/TypeNameParser.cs | 701 ---------------- ...alueStringBuilder.AppendSpanFormattable.cs | 2 + .../System.Private.CoreLib.Shared.projitems | 27 +- .../UnconditionalSuppressMessageAttribute.cs | 2 + .../System/Reflection/AssemblyNameParser.cs | 438 ---------- .../ref/System.Reflection.Metadata.cs | 43 + .../src/Resources/Strings.resx | 21 + .../src/System.Reflection.Metadata.csproj | 11 + .../tests/Metadata/AssemblyNameInfoTests.cs | 105 +++ .../Metadata/TypeNameParserHelpersTests.cs | 173 ++++ .../tests/Metadata/TypeNameParserSamples.cs | 255 ++++++ .../tests/Metadata/TypeNameTests.cs | 748 ++++++++++++++++++ .../System.Reflection.Metadata.Tests.csproj | 6 + .../System/Reflection/TypeNameParser.Mono.cs | 29 +- 31 files changed, 3599 insertions(+), 1300 deletions(-) rename src/libraries/{System.Private.CoreLib => Common}/src/System/Reflection/AssemblyNameFormatter.cs (92%) create mode 100644 src/libraries/Common/src/System/Reflection/AssemblyNameParser.cs create mode 100644 src/libraries/Common/src/System/Reflection/Metadata/AssemblyNameInfo.cs create mode 100644 src/libraries/Common/src/System/Reflection/Metadata/TypeName.cs create mode 100644 src/libraries/Common/src/System/Reflection/Metadata/TypeNameParser.cs create mode 100644 src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserHelpers.cs create mode 100644 src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserOptions.cs create mode 100644 src/libraries/Common/src/System/Reflection/TypeNameParser.Helpers.cs delete mode 100644 src/libraries/Common/src/System/Reflection/TypeNameParser.cs delete mode 100644 src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs create mode 100644 src/libraries/System.Reflection.Metadata/tests/Metadata/AssemblyNameInfoTests.cs create mode 100644 src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameParserHelpersTests.cs create mode 100644 src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameParserSamples.cs create mode 100644 src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameTests.cs diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameParser.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameParser.CoreCLR.cs index 2af4bb792d4588..35fa0b5718e387 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameParser.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameParser.CoreCLR.cs @@ -4,11 +4,9 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; -using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Loader; -using System.Text; using System.Threading; namespace System.Reflection @@ -57,7 +55,13 @@ internal partial struct TypeNameParser return null; } - return new TypeNameParser(typeName) + Metadata.TypeName? parsed = Metadata.TypeNameParser.Parse(typeName, throwOnError: throwOnError); + if (parsed is null) + { + return null; + } + + return new TypeNameParser() { _assemblyResolver = assemblyResolver, _typeResolver = typeResolver, @@ -65,7 +69,7 @@ internal partial struct TypeNameParser _ignoreCase = ignoreCase, _extensibleParser = extensibleParser, _requestingAssembly = requestingAssembly - }.Parse(); + }.Resolve(parsed); } [RequiresUnreferencedCode("The type might be removed")] @@ -75,13 +79,24 @@ internal partial struct TypeNameParser bool ignoreCase, Assembly topLevelAssembly) { - return new TypeNameParser(typeName) + Metadata.TypeName? parsed = Metadata.TypeNameParser.Parse(typeName, throwOnError); + + if (parsed is null) + { + return null; + } + else if (topLevelAssembly is not null && parsed.AssemblyName is not null) + { + return throwOnError ? throw new ArgumentException(SR.Argument_AssemblyGetTypeCannotSpecifyAssembly) : null; + } + + return new TypeNameParser() { _throwOnError = throwOnError, _ignoreCase = ignoreCase, _topLevelAssembly = topLevelAssembly, _requestingAssembly = topLevelAssembly - }.Parse(); + }.Resolve(parsed); } // Resolve type name referenced by a custom attribute metadata. @@ -95,12 +110,13 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName, RuntimeAssembly requestingAssembly = scope.GetRuntimeAssembly(); - RuntimeType? type = (RuntimeType?)new TypeNameParser(typeName) + Metadata.TypeName parsed = Metadata.TypeName.Parse(typeName); + RuntimeType? type = (RuntimeType?)new TypeNameParser() { _throwOnError = true, _suppressContextualReflectionContext = true, _requestingAssembly = requestingAssembly - }.Parse(); + }.Resolve(parsed); Debug.Assert(type != null); @@ -124,13 +140,19 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName, return null; } - RuntimeType? type = (RuntimeType?)new TypeNameParser(typeName) + Metadata.TypeName? parsed = Metadata.TypeNameParser.Parse(typeName, throwOnError); + if (parsed is null) + { + return null; + } + + RuntimeType? type = (RuntimeType?)new TypeNameParser() { _requestingAssembly = requestingAssembly, _throwOnError = throwOnError, _suppressContextualReflectionContext = true, _requireAssemblyQualifiedName = requireAssemblyQualifiedName, - }.Parse(); + }.Resolve(parsed); if (type != null) RuntimeTypeHandle.RegisterCollectibleTypeDependency(type, requestingAssembly); @@ -138,23 +160,12 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName, return type; } - private bool CheckTopLevelAssemblyQualifiedName() - { - if (_topLevelAssembly is not null) - { - if (_throwOnError) - throw new ArgumentException(SR.Argument_AssemblyGetTypeCannotSpecifyAssembly); - return false; - } - return true; - } - - private Assembly? ResolveAssembly(string assemblyName) + private Assembly? ResolveAssembly(AssemblyName assemblyName) { Assembly? assembly; if (_assemblyResolver is not null) { - assembly = _assemblyResolver(new AssemblyName(assemblyName)); + assembly = _assemblyResolver(assemblyName); if (assembly is null && _throwOnError) { throw new FileNotFoundException(SR.Format(SR.FileNotFound_ResolveAssembly, assemblyName)); @@ -162,7 +173,7 @@ private bool CheckTopLevelAssemblyQualifiedName() } else { - assembly = RuntimeAssembly.InternalLoad(new AssemblyName(assemblyName), ref Unsafe.NullRef(), + assembly = RuntimeAssembly.InternalLoad(assemblyName, ref Unsafe.NullRef(), _suppressContextualReflectionContext ? null : AssemblyLoadContext.CurrentContextualReflectionContext, requestingAssembly: (RuntimeAssembly?)_requestingAssembly, throwOnFileNotFound: _throwOnError); } @@ -173,13 +184,14 @@ private bool CheckTopLevelAssemblyQualifiedName() Justification = "TypeNameParser.GetType is marked as RequiresUnreferencedCode.")] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", Justification = "TypeNameParser.GetType is marked as RequiresUnreferencedCode.")] - private Type? GetType(string typeName, ReadOnlySpan nestedTypeNames, string? assemblyNameIfAny) + private Type? GetType(string escapedTypeName, // For nested types, it's Name. For other types it's FullName + ReadOnlySpan nestedTypeNames, Metadata.TypeName parsedName) { Assembly? assembly; - if (assemblyNameIfAny is not null) + if (parsedName.AssemblyName is not null) { - assembly = ResolveAssembly(assemblyNameIfAny); + assembly = ResolveAssembly(parsedName.AssemblyName.ToAssemblyName()); if (assembly is null) return null; } @@ -193,8 +205,6 @@ private bool CheckTopLevelAssemblyQualifiedName() // Resolve the top level type. if (_typeResolver is not null) { - string escapedTypeName = EscapeTypeName(typeName); - type = _typeResolver(assembly, escapedTypeName, _ignoreCase); if (type is null) @@ -216,28 +226,29 @@ private bool CheckTopLevelAssemblyQualifiedName() { if (_throwOnError) { - throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveType, EscapeTypeName(typeName))); + throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveType, escapedTypeName)); } return null; } - return GetTypeFromDefaultAssemblies(typeName, nestedTypeNames); + return GetTypeFromDefaultAssemblies(UnescapeTypeName(escapedTypeName), nestedTypeNames, parsedName); } if (assembly is RuntimeAssembly runtimeAssembly) { + string unescapedTypeName = UnescapeTypeName(escapedTypeName); // Compat: Non-extensible parser allows ambiguous matches with ignore case lookup if (!_extensibleParser || !_ignoreCase) { - return runtimeAssembly.GetTypeCore(typeName, nestedTypeNames, throwOnError: _throwOnError, ignoreCase: _ignoreCase); + return runtimeAssembly.GetTypeCore(unescapedTypeName, nestedTypeNames, throwOnError: _throwOnError, ignoreCase: _ignoreCase); } - type = runtimeAssembly.GetTypeCore(typeName, default, throwOnError: _throwOnError, ignoreCase: _ignoreCase); + type = runtimeAssembly.GetTypeCore(unescapedTypeName, default, throwOnError: _throwOnError, ignoreCase: _ignoreCase); } else { // This is a third-party Assembly object. Emulate GetTypeCore() by calling the public GetType() // method. This is wasteful because it'll probably reparse a type string that we've already parsed // but it can't be helped. - type = assembly.GetType(EscapeTypeName(typeName), throwOnError: _throwOnError, ignoreCase: _ignoreCase); + type = assembly.GetType(escapedTypeName, throwOnError: _throwOnError, ignoreCase: _ignoreCase); } if (type is null) @@ -257,7 +268,7 @@ private bool CheckTopLevelAssemblyQualifiedName() if (_throwOnError) { throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveNestedType, - nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : typeName)); + nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : escapedTypeName)); } return null; } @@ -266,12 +277,12 @@ private bool CheckTopLevelAssemblyQualifiedName() return type; } - private Type? GetTypeFromDefaultAssemblies(string typeName, ReadOnlySpan nestedTypeNames) + private Type? GetTypeFromDefaultAssemblies(string typeName, ReadOnlySpan nestedTypeNames, Metadata.TypeName parsedName) { RuntimeAssembly? requestingAssembly = (RuntimeAssembly?)_requestingAssembly; if (requestingAssembly is not null) { - Type? type = ((RuntimeAssembly)requestingAssembly).GetTypeCore(typeName, nestedTypeNames, throwOnError: false, ignoreCase: _ignoreCase); + Type? type = requestingAssembly.GetTypeCore(typeName, nestedTypeNames, throwOnError: false, ignoreCase: _ignoreCase); if (type is not null) return type; } @@ -279,12 +290,12 @@ private bool CheckTopLevelAssemblyQualifiedName() RuntimeAssembly coreLib = (RuntimeAssembly)typeof(object).Assembly; if (requestingAssembly != coreLib) { - Type? type = ((RuntimeAssembly)coreLib).GetTypeCore(typeName, nestedTypeNames, throwOnError: false, ignoreCase: _ignoreCase); + Type? type = coreLib.GetTypeCore(typeName, nestedTypeNames, throwOnError: false, ignoreCase: _ignoreCase); if (type is not null) return type; } - RuntimeAssembly? resolvedAssembly = AssemblyLoadContext.OnTypeResolve(requestingAssembly, EscapeTypeName(typeName, nestedTypeNames)); + RuntimeAssembly? resolvedAssembly = AssemblyLoadContext.OnTypeResolve(requestingAssembly, parsedName.FullName); if (resolvedAssembly is not null) { Type? type = resolvedAssembly.GetTypeCore(typeName, nestedTypeNames, throwOnError: false, ignoreCase: _ignoreCase); @@ -293,7 +304,7 @@ private bool CheckTopLevelAssemblyQualifiedName() } if (_throwOnError) - throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, EscapeTypeName(typeName), (requestingAssembly ?? coreLib).FullName)); + throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, parsedName.FullName, (requestingAssembly ?? coreLib).FullName)); return null; } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs index 03a92b709eb1a5..81caecb09c99aa 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs @@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; -using System.Runtime.Versioning; using System.Security; using StackCrawlMark = System.Threading.StackCrawlMark; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs index ee76c4a5e302dd..5e855eb58565d6 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Reflection.Metadata; namespace System.Reflection { @@ -129,6 +130,11 @@ public AssemblyName ToAssemblyName() return assemblyName; } + internal static RuntimeAssemblyName FromAssemblyNameInfo(AssemblyNameInfo source) + { + return new(source.Name, source.Version, source.CultureName, source._flags, source.PublicKeyOrToken); + } + // // Copies a RuntimeAssemblyName into a freshly allocated AssemblyName with no data aliasing to any other object. // @@ -142,10 +148,10 @@ public void CopyToAssemblyName(AssemblyName blank) // Our "Flags" contain both the classic flags and the ProcessorArchitecture + ContentType bits. The public AssemblyName has separate properties for // these. The setters for these properties quietly mask out any bits intended for the other one, so we needn't do that ourselves.. - blank.Flags = ExtractAssemblyNameFlags(this.Flags); - blank.ContentType = ExtractAssemblyContentType(this.Flags); + blank.Flags = AssemblyNameInfo.ExtractAssemblyNameFlags(this.Flags); + blank.ContentType = AssemblyNameInfo.ExtractAssemblyContentType(this.Flags); #pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete - blank.ProcessorArchitecture = ExtractProcessorArchitecture(this.Flags); + blank.ProcessorArchitecture = AssemblyNameInfo.ExtractProcessorArchitecture(this.Flags); #pragma warning restore SYSLIB0037 if (this.PublicKeyOrToken != null) @@ -168,17 +174,8 @@ public string FullName get { byte[]? pkt = (0 != (Flags & AssemblyNameFlags.PublicKey)) ? AssemblyNameHelpers.ComputePublicKeyToken(PublicKeyOrToken) : PublicKeyOrToken; - return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, ExtractAssemblyNameFlags(Flags), ExtractAssemblyContentType(Flags)); + return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, AssemblyNameInfo.ExtractAssemblyNameFlags(Flags), AssemblyNameInfo.ExtractAssemblyContentType(Flags)); } } - - private static AssemblyNameFlags ExtractAssemblyNameFlags(AssemblyNameFlags combinedFlags) - => combinedFlags & unchecked((AssemblyNameFlags)0xFFFFF10F); - - private static AssemblyContentType ExtractAssemblyContentType(AssemblyNameFlags flags) - => (AssemblyContentType)((((int)flags) >> 9) & 0x7); - - private static ProcessorArchitecture ExtractProcessorArchitecture(AssemblyNameFlags flags) - => (ProcessorArchitecture)((((int)flags) >> 4) & 0x7); } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameParser.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameParser.NativeAot.cs index e370cb4eed0a83..2149003ddcfb4c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameParser.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameParser.NativeAot.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Collections.Generic; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection.Runtime.Assemblies; @@ -53,7 +51,13 @@ internal partial struct TypeNameParser return null; } - return new TypeNameParser(typeName) + Metadata.TypeName? parsed = Metadata.TypeNameParser.Parse(typeName, throwOnError); + if (parsed is null) + { + return null; + } + + return new TypeNameParser() { _assemblyResolver = assemblyResolver, _typeResolver = typeResolver, @@ -61,7 +65,7 @@ internal partial struct TypeNameParser _ignoreCase = ignoreCase, _extensibleParser = extensibleParser, _defaultAssemblyName = defaultAssemblyName - }.Parse(); + }.Resolve(parsed); } internal static Type? GetType( @@ -70,35 +74,35 @@ internal partial struct TypeNameParser bool ignoreCase, Assembly topLevelAssembly) { - return new TypeNameParser(typeName) + Metadata.TypeName? parsed = Metadata.TypeNameParser.Parse(typeName, throwOnError); + + if (parsed is null) + { + return null; + } + else if (topLevelAssembly is not null && parsed.AssemblyName is not null) + { + return throwOnError ? throw new ArgumentException(SR.Argument_AssemblyGetTypeCannotSpecifyAssembly) : null; + } + + return new TypeNameParser() { _throwOnError = throwOnError, _ignoreCase = ignoreCase, _topLevelAssembly = topLevelAssembly, - }.Parse(); + }.Resolve(parsed); } - private bool CheckTopLevelAssemblyQualifiedName() - { - if (_topLevelAssembly is not null) - { - if (_throwOnError) - throw new ArgumentException(SR.Argument_AssemblyGetTypeCannotSpecifyAssembly); - return false; - } - return true; - } - - private Assembly? ResolveAssembly(string assemblyName) + private Assembly? ResolveAssembly(Metadata.AssemblyNameInfo assemblyName) { Assembly? assembly; if (_assemblyResolver is not null) { - assembly = _assemblyResolver(new AssemblyName(assemblyName)); + assembly = _assemblyResolver(assemblyName.ToAssemblyName()); } else { - assembly = RuntimeAssemblyInfo.GetRuntimeAssemblyIfExists(RuntimeAssemblyName.Parse(assemblyName)); + assembly = RuntimeAssemblyInfo.GetRuntimeAssemblyIfExists(RuntimeAssemblyName.FromAssemblyNameInfo(assemblyName)); } if (assembly is null && _throwOnError) @@ -113,13 +117,13 @@ private bool CheckTopLevelAssemblyQualifiedName() Justification = "GetType APIs are marked as RequiresUnreferencedCode.")] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", Justification = "GetType APIs are marked as RequiresUnreferencedCode.")] - private Type? GetType(string typeName, ReadOnlySpan nestedTypeNames, string? assemblyNameIfAny) + private Type? GetType(string escapedTypeName, ReadOnlySpan nestedTypeNames, Metadata.TypeName parsedName) { Assembly? assembly; - if (assemblyNameIfAny is not null) + if (parsedName.AssemblyName is not null) { - assembly = ResolveAssembly(assemblyNameIfAny); + assembly = ResolveAssembly(parsedName.AssemblyName); if (assembly is null) return null; } @@ -133,8 +137,6 @@ private bool CheckTopLevelAssemblyQualifiedName() // Resolve the top level type. if (_typeResolver is not null) { - string escapedTypeName = EscapeTypeName(typeName); - type = _typeResolver(assembly, escapedTypeName, _ignoreCase); if (type is null) @@ -154,14 +156,14 @@ private bool CheckTopLevelAssemblyQualifiedName() { if (assembly is RuntimeAssemblyInfo runtimeAssembly) { - type = runtimeAssembly.GetTypeCore(typeName, throwOnError: _throwOnError, ignoreCase: _ignoreCase); + type = runtimeAssembly.GetTypeCore(UnescapeTypeName(escapedTypeName), throwOnError: _throwOnError, ignoreCase: _ignoreCase); } else { // This is a third-party Assembly object. We can emulate GetTypeCore() by calling the public GetType() // method. This is wasteful because it'll probably reparse a type string that we've already parsed // but it can't be helped. - type = assembly.GetType(EscapeTypeName(typeName), throwOnError: _throwOnError, ignoreCase: _ignoreCase); + type = assembly.GetType(escapedTypeName, throwOnError: _throwOnError, ignoreCase: _ignoreCase); } if (type is null) @@ -169,13 +171,15 @@ private bool CheckTopLevelAssemblyQualifiedName() } else { + string? unescapedTypeName = UnescapeTypeName(escapedTypeName); + RuntimeAssemblyInfo? defaultAssembly = null; if (_defaultAssemblyName != null) { defaultAssembly = RuntimeAssemblyInfo.GetRuntimeAssemblyIfExists(RuntimeAssemblyName.Parse(_defaultAssemblyName)); if (defaultAssembly != null) { - type = defaultAssembly.GetTypeCore(typeName, throwOnError: false, ignoreCase: _ignoreCase); + type = defaultAssembly.GetTypeCore(unescapedTypeName, throwOnError: false, ignoreCase: _ignoreCase); } } @@ -185,7 +189,7 @@ private bool CheckTopLevelAssemblyQualifiedName() coreLib = (RuntimeAssemblyInfo)typeof(object).Assembly; if (coreLib != assembly) { - type = coreLib.GetTypeCore(typeName, throwOnError: false, ignoreCase: _ignoreCase); + type = coreLib.GetTypeCore(unescapedTypeName, throwOnError: false, ignoreCase: _ignoreCase); } } @@ -193,7 +197,7 @@ private bool CheckTopLevelAssemblyQualifiedName() { if (_throwOnError) { - throw Helpers.CreateTypeLoadException(typeName, (defaultAssembly ?? coreLib).FullName); + throw Helpers.CreateTypeLoadException(unescapedTypeName, (defaultAssembly ?? coreLib).FullName); } return null; } @@ -214,10 +218,9 @@ private bool CheckTopLevelAssemblyQualifiedName() if (type is null && _ignoreCase && !_extensibleParser) { // Return the first name that matches. Which one gets returned on a multiple match is an implementation detail. - string lowerName = nestedTypeNames[i].ToLowerInvariant(); foreach (Type nt in declaringType.GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Public)) { - if (nt.Name.ToLowerInvariant() == lowerName) + if (nt.Name.Equals(nestedTypeNames[i], StringComparison.InvariantCultureIgnoreCase)) { type = nt; break; @@ -230,7 +233,7 @@ private bool CheckTopLevelAssemblyQualifiedName() if (_throwOnError) { throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveNestedType, - nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : typeName)); + nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : escapedTypeName)); } return null; } diff --git a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs index a52a68f0028a48..72779375f4697a 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs @@ -2,8 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Collections.Generic; -using System.Text; +using System.Reflection.Metadata; using Internal.TypeSystem; @@ -37,12 +36,17 @@ internal partial struct TypeNameParser public static TypeDesc ResolveType(ModuleDesc module, string name, bool throwIfNotFound, Func canonResolver) { - return new TypeNameParser(name.AsSpan()) + if (!TypeName.TryParse(name.AsSpan(), out TypeName parsed)) + { + ThrowHelper.ThrowTypeLoadException(name, module); + } + + return new TypeNameParser() { _module = module, _throwIfNotFound = throwIfNotFound, _canonResolver = canonResolver - }.Parse()?.Value; + }.Resolve(parsed)?.Value; } private sealed class Type @@ -64,12 +68,10 @@ public Type MakeGenericType(Type[] typeArguments) } } - private static bool CheckTopLevelAssemblyQualifiedName() => true; - - private Type GetType(string typeName, ReadOnlySpan nestedTypeNames, string assemblyNameIfAny) + private Type GetType(string typeName, ReadOnlySpan nestedTypeNames, TypeName parsedName) { - ModuleDesc module = (assemblyNameIfAny == null) ? _module : - _module.Context.ResolveAssembly(new AssemblyName(assemblyNameIfAny), throwIfNotFound: _throwIfNotFound); + ModuleDesc module = (parsedName.AssemblyName == null) ? _module : + _module.Context.ResolveAssembly(parsedName.AssemblyName.ToAssemblyName(), throwIfNotFound: _throwIfNotFound); if (_canonResolver != null && nestedTypeNames.IsEmpty) { @@ -86,7 +88,7 @@ private Type GetType(string typeName, ReadOnlySpan nestedTypeNames, stri } // If it didn't resolve and wasn't assembly-qualified, we also try core library - if (assemblyNameIfAny == null) + if (parsedName.AssemblyName == null) { Type type = GetTypeCore(module.Context.SystemModule, typeName, nestedTypeNames); if (type != null) @@ -94,7 +96,7 @@ private Type GetType(string typeName, ReadOnlySpan nestedTypeNames, stri } if (_throwIfNotFound) - ThrowHelper.ThrowTypeLoadException(EscapeTypeName(typeName, nestedTypeNames), module); + ThrowHelper.ThrowTypeLoadException(parsedName.FullName, module); return null; } @@ -115,10 +117,5 @@ private static Type GetTypeCore(ModuleDesc module, string typeName, ReadOnlySpan return new Type(type); } - - private void ParseError() - { - ThrowHelper.ThrowTypeLoadException(_input.ToString(), _module); - } } } diff --git a/src/coreclr/tools/ILVerification/ILVerification.projitems b/src/coreclr/tools/ILVerification/ILVerification.projitems index 81ce9f65d1139a..3b2c30ddef1f18 100644 --- a/src/coreclr/tools/ILVerification/ILVerification.projitems +++ b/src/coreclr/tools/ILVerification/ILVerification.projitems @@ -66,12 +66,45 @@ Utilities\CustomAttributeTypeNameParser.cs - + + Utilities\HexConverter.cs + + + Utilities\AssemblyNameFormatter.cs + + + Utilities\AssemblyNameParser.cs + + + Utilities\Metadata\AssemblyNameInfo.cs + + + Utilities\TypeName.cs + + + Utilities\TypeNameParserOptions.cs + + Utilities\TypeNameParser.cs + + Utilities\TypeNameParserHelpers.cs + + + System\Diagnostics\CodeAnalysis\UnconditionalSuppressMessageAttribute.cs + + + System\Diagnostics\CodeAnalysis\NullableAttributes.cs + + + Utilities\CustomAttributeTypeNameParser.Helpers + Utilities\ValueStringBuilder.cs + + Utilities\ValueStringBuilder.AppendSpanFormattable.cs + Utilities\LockFreeReaderHashtable.cs diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeNameParser.Dataflow.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeNameParser.Dataflow.cs index 90b63f39c9f026..5b0cfdb12b4445 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeNameParser.Dataflow.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeNameParser.Dataflow.cs @@ -2,10 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Reflection; - +using System.Reflection.Metadata; using Internal.TypeSystem; namespace System.Reflection @@ -20,14 +17,20 @@ internal partial struct TypeNameParser public static TypeDesc ResolveType(string name, ModuleDesc callingModule, TypeSystemContext context, List referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary) { - var parser = new TypeNameParser(name) + if (!TypeName.TryParse(name, out TypeName parsed)) + { + typeWasNotFoundInAssemblyNorBaseLibrary = false; + return null; + } + + var parser = new TypeNameParser() { _context = context, _callingModule = callingModule, _referencedModules = referencedModules }; - TypeDesc result = parser.Parse()?.Value; + TypeDesc result = parser.Resolve(parsed)?.Value; typeWasNotFoundInAssemblyNorBaseLibrary = parser._typeWasNotFoundInAssemblyNorBaseLibrary; return result; @@ -52,16 +55,13 @@ public Type MakeGenericType(Type[] typeArguments) } } - private static bool CheckTopLevelAssemblyQualifiedName() => true; - - private Type GetType(string typeName, ReadOnlySpan nestedTypeNames, string assemblyNameIfAny) + private Type GetType(string typeName, ReadOnlySpan nestedTypeNames, TypeName parsedName) { ModuleDesc module; - if (assemblyNameIfAny != null) + if (parsedName.AssemblyName != null) { - module = (TryParseAssemblyName(assemblyNameIfAny) is AssemblyName an) ? - _context.ResolveAssembly(an, throwIfNotFound: false) : null; + module = _context.ResolveAssembly(parsedName.AssemblyName.ToAssemblyName(), throwIfNotFound: false); } else { @@ -79,7 +79,7 @@ private Type GetType(string typeName, ReadOnlySpan nestedTypeNames, stri } // If it didn't resolve and wasn't assembly-qualified, we also try core library - if (assemblyNameIfAny == null) + if (parsedName.AssemblyName == null) { Type type = GetTypeCore(_context.SystemModule, typeName, nestedTypeNames); if (type != null) @@ -94,22 +94,6 @@ private Type GetType(string typeName, ReadOnlySpan nestedTypeNames, stri return null; } - private static AssemblyName TryParseAssemblyName(string assemblyName) - { - try - { - return new AssemblyName(assemblyName); - } - catch (FileLoadException) - { - return null; - } - catch (ArgumentException) - { - return null; - } - } - private static Type GetTypeCore(ModuleDesc module, string typeName, ReadOnlySpan nestedTypeNames) { (string typeNamespace, string name) = SplitFullTypeName(typeName); @@ -127,9 +111,5 @@ private static Type GetTypeCore(ModuleDesc module, string typeName, ReadOnlySpan return new Type(type); } - - private static void ParseError() - { - } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj index 37c8c2108d9172..a895dbe1726fa3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj @@ -397,8 +397,8 @@ - - Compiler\Dataflow\TypeNameParser.cs + + Compiler\Dataflow\TypeNameParser.Helpers.cs Utilities\ValueStringBuilder.cs diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem/ILCompiler.TypeSystem.csproj b/src/coreclr/tools/aot/ILCompiler.TypeSystem/ILCompiler.TypeSystem.csproj index c46d5fecbfb76c..23afa3780b1abc 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem/ILCompiler.TypeSystem.csproj +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem/ILCompiler.TypeSystem.csproj @@ -198,12 +198,39 @@ Utilities\CustomAttributeTypeNameParser.cs - + + Utilities\HexConverter.cs + + + Utilities\AssemblyNameFormatter.cs + + + Utilities\AssemblyNameParser.cs + + + Utilities\AssemblyNameInfo.cs + + + Utilities\TypeName.cs + + Utilities\TypeNameParser.cs + + Utilities\TypeNameParserHelpers.cs + + + Utilities\TypeNameParserOptions.cs + + + Utilities\CustomAttributeTypeNameParser.Helpers + Utilities\ValueStringBuilder.cs + + Utilities\ValueStringBuilder.AppendSpanFormattable.cs + Utilities\GCPointerMap.Algorithm.cs diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameFormatter.cs b/src/libraries/Common/src/System/Reflection/AssemblyNameFormatter.cs similarity index 92% rename from src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameFormatter.cs rename to src/libraries/Common/src/System/Reflection/AssemblyNameFormatter.cs index c1a810db507557..9d5eeebc85a6d0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameFormatter.cs +++ b/src/libraries/Common/src/System/Reflection/AssemblyNameFormatter.cs @@ -6,6 +6,8 @@ using System.Globalization; using System.Text; +#nullable enable + namespace System.Reflection { internal static class AssemblyNameFormatter @@ -91,7 +93,8 @@ private static void AppendQuoted(this ref ValueStringBuilder vsb, string s) // App-compat: You can use double or single quotes to quote a name, and Fusion (or rather the IdentityAuthority) picks one // by some algorithm. Rather than guess at it, we use double quotes consistently. - if (s != s.Trim() || s.Contains('\"') || s.Contains('\'')) + ReadOnlySpan span = s.AsSpan(); + if (s.Length != span.Trim().Length || span.IndexOfAny('\"', '\'') >= 0) needsQuoting = true; if (needsQuoting) @@ -125,5 +128,12 @@ private static void AppendQuoted(this ref ValueStringBuilder vsb, string s) if (needsQuoting) vsb.Append(quoteChar); } + +#if !NETCOREAPP + private static void AppendSpanFormattable(this ref ValueStringBuilder vsb, ushort value) + { + vsb.Append(value.ToString()); + } +#endif } } diff --git a/src/libraries/Common/src/System/Reflection/AssemblyNameParser.cs b/src/libraries/Common/src/System/Reflection/AssemblyNameParser.cs new file mode 100644 index 00000000000000..bfd91d781a4ecc --- /dev/null +++ b/src/libraries/Common/src/System/Reflection/AssemblyNameParser.cs @@ -0,0 +1,506 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.IO; +using System.Runtime.CompilerServices; +using System.Text; + +#nullable enable + +namespace System.Reflection +{ + /// + /// Parses an assembly name. + /// + internal ref partial struct AssemblyNameParser + { + public readonly struct AssemblyNameParts + { + public AssemblyNameParts(string name, Version? version, string? cultureName, AssemblyNameFlags flags, byte[]? publicKeyOrToken) + { + _name = name; + _version = version; + _cultureName = cultureName; + _flags = flags; + _publicKeyOrToken = publicKeyOrToken; + } + + public readonly string _name; + public readonly Version? _version; + public readonly string? _cultureName; + public readonly AssemblyNameFlags _flags; + public readonly byte[]? _publicKeyOrToken; + } + + /// + /// Token categories for the lexer. + /// + private enum Token + { + Equals = 1, + Comma = 2, + String = 3, + End = 4, + } + + private enum AttributeKind + { + Version = 1, + Culture = 2, + PublicKeyOrToken = 4, + ProcessorArchitecture = 8, + Retargetable = 16, + ContentType = 32 + } + + private readonly ReadOnlySpan _input; + private int _index; + + private AssemblyNameParser(ReadOnlySpan input) + { +#if SYSTEM_PRIVATE_CORELIB + if (input.Length == 0) + throw new ArgumentException(SR.Format_StringZeroLength); +#else + Debug.Assert(input.Length > 0); +#endif + + _input = input; + _index = 0; + } + +#if SYSTEM_PRIVATE_CORELIB + public static AssemblyNameParts Parse(string name) => Parse(name.AsSpan()); + + public static AssemblyNameParts Parse(ReadOnlySpan name) + { + AssemblyNameParser parser = new(name); + AssemblyNameParts result = default; + if (parser.TryParse(ref result)) + { + return result; + } + throw new FileLoadException(SR.InvalidAssemblyName, name.ToString()); + } +#endif + + internal static bool TryParse(ReadOnlySpan name, ref AssemblyNameParts parts) + { + AssemblyNameParser parser = new(name); + return parser.TryParse(ref parts); + } + + private static bool TryRecordNewSeen(scoped ref AttributeKind seenAttributes, AttributeKind newAttribute) + { + if ((seenAttributes & newAttribute) != 0) + { + return false; + } + seenAttributes |= newAttribute; + return true; + } + + private bool TryParse(ref AssemblyNameParts result) + { + // Name must come first. + if (!TryGetNextToken(out string name, out Token token) || token != Token.String || string.IsNullOrEmpty(name)) + return false; + + Version? version = null; + string? cultureName = null; + byte[]? pkt = null; + AssemblyNameFlags flags = 0; + + AttributeKind alreadySeen = default; + if (!TryGetNextToken(out _, out token)) + return false; + + while (token != Token.End) + { + if (token != Token.Comma) + return false; + + if (!TryGetNextToken(out string attributeName, out token) || token != Token.String) + return false; + + if (!TryGetNextToken(out _, out token) || token != Token.Equals) + return false; + + if (!TryGetNextToken(out string attributeValue, out token) || token != Token.String) + return false; + + if (attributeName == string.Empty) + return false; + + if (IsAttribute(attributeName, "Version")) + { + if (!TryRecordNewSeen(ref alreadySeen, AttributeKind.Version)) + { + return false; + } + if (!TryParseVersion(attributeValue, ref version)) + { + return false; + } + } + else if (IsAttribute(attributeName, "Culture")) + { + if (!TryRecordNewSeen(ref alreadySeen, AttributeKind.Culture)) + { + return false; + } + if (!TryParseCulture(attributeValue, out cultureName)) + { + return false; + } + } + else if (IsAttribute(attributeName, "PublicKeyToken")) + { + if (!TryRecordNewSeen(ref alreadySeen, AttributeKind.PublicKeyOrToken)) + { + return false; + } + if (!TryParsePKT(attributeValue, isToken: true, out pkt)) + { + return false; + } + } + else if (IsAttribute(attributeName, "PublicKey")) + { + if (!TryRecordNewSeen(ref alreadySeen, AttributeKind.PublicKeyOrToken)) + { + return false; + } + if (!TryParsePKT(attributeValue, isToken: false, out pkt)) + { + return false; + } + flags |= AssemblyNameFlags.PublicKey; + } + else if (IsAttribute(attributeName, "ProcessorArchitecture")) + { + if (!TryRecordNewSeen(ref alreadySeen, AttributeKind.ProcessorArchitecture)) + { + return false; + } + if (!TryParseProcessorArchitecture(attributeValue, out ProcessorArchitecture arch)) + { + return false; + } + flags |= (AssemblyNameFlags)(((int)arch) << 4); + } + else if (IsAttribute(attributeName, "Retargetable")) + { + if (!TryRecordNewSeen(ref alreadySeen, AttributeKind.Retargetable)) + { + return false; + } + + if (attributeValue.Equals("Yes", StringComparison.OrdinalIgnoreCase)) + { + flags |= AssemblyNameFlags.Retargetable; + } + else if (attributeValue.Equals("No", StringComparison.OrdinalIgnoreCase)) + { + // nothing to do + } + else + { + return false; + } + } + else if (IsAttribute(attributeName, "ContentType")) + { + if (!TryRecordNewSeen(ref alreadySeen, AttributeKind.ContentType)) + { + return false; + } + + if (attributeValue.Equals("WindowsRuntime", StringComparison.OrdinalIgnoreCase)) + { + flags |= (AssemblyNameFlags)(((int)AssemblyContentType.WindowsRuntime) << 9); + } + else + { + return false; + } + } + else + { + // Desktop compat: If we got here, the attribute name is unknown to us. Ignore it. + } + + if (!TryGetNextToken(out _, out token)) + { + return false; + } + } + + result = new AssemblyNameParts(name, version, cultureName, flags, pkt); + return true; + } + + private static bool IsAttribute(string candidate, string attributeKind) + => candidate.Equals(attributeKind, StringComparison.OrdinalIgnoreCase); + + private static bool TryParseVersion(string attributeValue, ref Version? version) + { +#if NET8_0_OR_GREATER + ReadOnlySpan attributeValueSpan = attributeValue; + Span parts = stackalloc Range[5]; + parts = parts.Slice(0, attributeValueSpan.Split(parts, '.')); +#else + string[] parts = attributeValue.Split('.'); +#endif + if (parts.Length is < 2 or > 4) + { + return false; + } + + Span versionNumbers = stackalloc ushort[4] { ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue }; + for (int i = 0; i < parts.Length; i++) + { + if (!ushort.TryParse( +#if NET8_0_OR_GREATER + attributeValueSpan[parts[i]], +#else + parts[i], +#endif + NumberStyles.None, NumberFormatInfo.InvariantInfo, out versionNumbers[i])) + { + return false; + } + } + + if (versionNumbers[0] == ushort.MaxValue || + versionNumbers[1] == ushort.MaxValue) + { + return false; + } + + version = + versionNumbers[2] == ushort.MaxValue ? new Version(versionNumbers[0], versionNumbers[1]) : + versionNumbers[3] == ushort.MaxValue ? new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2]) : + new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2], versionNumbers[3]); + + return true; + } + + private static bool TryParseCulture(string attributeValue, out string? result) + { + if (attributeValue.Equals("Neutral", StringComparison.OrdinalIgnoreCase)) + { + result = ""; + return true; + } + + result = attributeValue; + return true; + } + + private static bool TryParsePKT(string attributeValue, bool isToken, out byte[]? result) + { + if (attributeValue.Equals("null", StringComparison.OrdinalIgnoreCase) || attributeValue == string.Empty) + { + result = Array.Empty(); + return true; + } + + if (attributeValue.Length % 2 != 0 || (isToken && attributeValue.Length != 8 * 2)) + { + result = null; + return false; + } + + byte[] pkt = new byte[attributeValue.Length / 2]; + if (!HexConverter.TryDecodeFromUtf16(attributeValue.AsSpan(), pkt, out int _)) + { + result = null; + return false; + } + + result = pkt; + return true; + } + + private static bool TryParseProcessorArchitecture(string attributeValue, out ProcessorArchitecture result) + { + result = attributeValue switch + { + _ when attributeValue.Equals("msil", StringComparison.OrdinalIgnoreCase) => ProcessorArchitecture.MSIL, + _ when attributeValue.Equals("x86", StringComparison.OrdinalIgnoreCase) => ProcessorArchitecture.X86, + _ when attributeValue.Equals("ia64", StringComparison.OrdinalIgnoreCase) => ProcessorArchitecture.IA64, + _ when attributeValue.Equals("amd64", StringComparison.OrdinalIgnoreCase) => ProcessorArchitecture.Amd64, + _ when attributeValue.Equals("arm", StringComparison.OrdinalIgnoreCase) => ProcessorArchitecture.Arm, + _ when attributeValue.Equals("msil", StringComparison.OrdinalIgnoreCase) => ProcessorArchitecture.MSIL, + _ => ProcessorArchitecture.None + }; + return result != ProcessorArchitecture.None; + } + + private static bool IsWhiteSpace(char ch) + => ch is '\n' or '\r' or ' ' or '\t'; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private bool TryGetNextChar(out char ch) + { + if (_index < _input.Length) + { + ch = _input[_index++]; + if (ch == '\0') + { + return false; + } + } + else + { + ch = '\0'; + } + + return true; + } + + // + // Return the next token in assembly name. If the result is Token.String, + // sets "tokenString" to the tokenized string. + // + private bool TryGetNextToken(out string tokenString, out Token token) + { + tokenString = string.Empty; + char c; + + while (true) + { + if (!TryGetNextChar(out c)) + { + token = default; + return false; + } + + switch (c) + { + case ',': + { + token = Token.Comma; + return true; + } + case '=': + { + token = Token.Equals; + return true; + } + case '\0': + { + token = Token.End; + return true; + } + } + + if (!IsWhiteSpace(c)) + { + break; + } + } + + using ValueStringBuilder sb = new ValueStringBuilder(stackalloc char[64]); + + char quoteChar = '\0'; + if (c is '\'' or '\"') + { + quoteChar = c; + if (!TryGetNextChar(out c)) + { + token = default; + return false; + } + } + + for (; ; ) + { + if (c == 0) + { + if (quoteChar != 0) + { + // EOS and unclosed quotes is an error + token = default; + return false; + } + // Reached end of input and therefore of string + break; + } + + if (quoteChar != 0 && c == quoteChar) + break; // Terminate: Found closing quote of quoted string. + + if (quoteChar == 0 && (c is ',' or '=')) + { + _index--; + break; // Terminate: Found start of a new ',' or '=' token. + } + + if (quoteChar == 0 && (c is '\'' or '\"')) + { + token = default; + return false; + } + + if (c is '\\') + { + if (!TryGetNextChar(out c)) + { + token = default; + return false; + } + + switch (c) + { + case '\\': + case ',': + case '=': + case '\'': + case '"': + sb.Append(c); + break; + case 't': + sb.Append('\t'); + break; + case 'r': + sb.Append('\r'); + break; + case 'n': + sb.Append('\n'); + break; + default: + token = default; + return false; + } + } + else + { + sb.Append(c); + } + + if (!TryGetNextChar(out c)) + { + token = default; + return false; + } + } + + + int length = sb.Length; + if (quoteChar == 0) + { + while (length > 0 && IsWhiteSpace(sb[length - 1])) + length--; + } + + tokenString = sb.AsSpan(0, length).ToString(); + token = Token.String; + return true; + } + } +} diff --git a/src/libraries/Common/src/System/Reflection/Metadata/AssemblyNameInfo.cs b/src/libraries/Common/src/System/Reflection/Metadata/AssemblyNameInfo.cs new file mode 100644 index 00000000000000..ee586e3b57a8c0 --- /dev/null +++ b/src/libraries/Common/src/System/Reflection/Metadata/AssemblyNameInfo.cs @@ -0,0 +1,219 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#nullable enable + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Text; + +#if !SYSTEM_PRIVATE_CORELIB +using System.Collections.Immutable; +using System.Linq; +#endif + +namespace System.Reflection.Metadata +{ + /// + /// Describes an assembly. + /// + /// + /// It's a more lightweight, immutable version of that does not pre-allocate instances. + /// + [DebuggerDisplay("{FullName}")] +#if SYSTEM_PRIVATE_CORELIB + internal +#else + public +#endif + sealed class AssemblyNameInfo + { + internal readonly AssemblyNameFlags _flags; + private string? _fullName; + +#if !SYSTEM_PRIVATE_CORELIB + /// + /// Initializes a new instance of the AssemblyNameInfo class. + /// + /// The simple name of the assembly. + /// The version of the assembly. + /// The name of the culture associated with the assembly. + /// The attributes of the assembly. + /// The public key or its token. Set to when it's public key. + /// is null. + public AssemblyNameInfo(string name, Version? version = null, string? cultureName = null, AssemblyNameFlags flags = AssemblyNameFlags.None, ImmutableArray publicKeyOrToken = default) + { + Name = name ?? throw new ArgumentNullException(nameof(name)); + Version = version; + CultureName = cultureName; + _flags = flags; + PublicKeyOrToken = publicKeyOrToken; + } +#endif + + internal AssemblyNameInfo(AssemblyNameParser.AssemblyNameParts parts) + { + Name = parts._name; + Version = parts._version; + CultureName = parts._cultureName; + _flags = parts._flags; +#if SYSTEM_PRIVATE_CORELIB + PublicKeyOrToken = parts._publicKeyOrToken; +#else + PublicKeyOrToken = parts._publicKeyOrToken is null ? default : parts._publicKeyOrToken.Length == 0 + ? ImmutableArray.Empty + #if NET8_0_OR_GREATER + : Runtime.InteropServices.ImmutableCollectionsMarshal.AsImmutableArray(parts._publicKeyOrToken); + #else + : ImmutableArray.Create(parts._publicKeyOrToken); + #endif +#endif + } + + /// + /// Gets the simple name of the assembly. + /// + public string Name { get; } + + /// + /// Gets the version of the assembly. + /// + public Version? Version { get; } + + /// + /// Gets the name of the culture associated with the assembly. + /// + public string? CultureName { get; } + + /// + /// Gets the attributes of the assembly. + /// + public AssemblyNameFlags Flags => _flags; + + /// + /// Gets the public key or the public key token of the assembly. + /// + /// Check for flag to see whether it's public key or its token. +#if SYSTEM_PRIVATE_CORELIB + public byte[]? PublicKeyOrToken { get; } +#else + public ImmutableArray PublicKeyOrToken { get; } +#endif + + /// + /// Gets the full name of the assembly, also known as the display name. + /// + /// In contrary to it does not validate public key token neither computes it based on the provided public key. + public string FullName + { + get + { + if (_fullName is null) + { + byte[]? publicKeyToken = ((Flags & AssemblyNameFlags.PublicKey) != 0) ? null : +#if SYSTEM_PRIVATE_CORELIB + PublicKeyOrToken; +#elif NET8_0_OR_GREATER + !PublicKeyOrToken.IsDefault ? Runtime.InteropServices.ImmutableCollectionsMarshal.AsArray(PublicKeyOrToken) : null; +#else + !PublicKeyOrToken.IsDefault ? PublicKeyOrToken.ToArray() : null; +#endif + _fullName = AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, publicKeyToken, + ExtractAssemblyNameFlags(_flags), ExtractAssemblyContentType(_flags)); + } + + return _fullName; + } + } + + /// + /// Initializes a new instance of the class based on the stored information. + /// + public AssemblyName ToAssemblyName() + { + AssemblyName assemblyName = new(); + assemblyName.Name = Name; + assemblyName.CultureName = CultureName; + assemblyName.Version = Version; + assemblyName.Flags = Flags; + assemblyName.ContentType = ExtractAssemblyContentType(_flags); +#pragma warning disable SYSLIB0037 // Type or member is obsolete + assemblyName.ProcessorArchitecture = ExtractProcessorArchitecture(_flags); +#pragma warning restore SYSLIB0037 // Type or member is obsolete + +#if SYSTEM_PRIVATE_CORELIB + if (PublicKeyOrToken is not null) + { + if ((Flags & AssemblyNameFlags.PublicKey) != 0) + { + assemblyName.SetPublicKey(PublicKeyOrToken); + } + else + { + assemblyName.SetPublicKeyToken(PublicKeyOrToken); + } + } +#else + if (!PublicKeyOrToken.IsDefault) + { +#pragma warning disable RS0030 // TypeSystem does not allow System.Linq, but we need to use System.Linq.ImmutableArrayExtensions.ToArray + // A copy of the array needs to be created, as AssemblyName allows for the mutation of provided array. + if ((Flags & AssemblyNameFlags.PublicKey) != 0) + { + assemblyName.SetPublicKey(PublicKeyOrToken.ToArray()); + } + else + { + assemblyName.SetPublicKeyToken(PublicKeyOrToken.ToArray()); + } +#pragma warning restore RS0030 + } +#endif + + return assemblyName; + } + + /// + /// Parses a span of characters into a assembly name. + /// + /// A span containing the characters representing the assembly name to parse. + /// Parsed type name. + /// Provided assembly name was invalid. + public static AssemblyNameInfo Parse(ReadOnlySpan assemblyName) + => TryParse(assemblyName, out AssemblyNameInfo? result) + ? result! +#if SYSTEM_REFLECTION_METADATA || SYSTEM_PRIVATE_CORELIB + : throw new ArgumentException(SR.InvalidAssemblyName, nameof(assemblyName)); +#else // tools that reference this file as a link + : throw new ArgumentException("The given assembly name was invalid.", nameof(assemblyName)); +#endif + + /// + /// Tries to parse a span of characters into an assembly name. + /// + /// A span containing the characters representing the assembly name to parse. + /// Contains the result when parsing succeeds. + /// true if assembly name was converted successfully, otherwise, false. + public static bool TryParse(ReadOnlySpan assemblyName, [NotNullWhen(true)] out AssemblyNameInfo? result) + { + AssemblyNameParser.AssemblyNameParts parts = default; + if (AssemblyNameParser.TryParse(assemblyName, ref parts)) + { + result = new(parts); + return true; + } + + result = null; + return false; + } + + internal static AssemblyNameFlags ExtractAssemblyNameFlags(AssemblyNameFlags combinedFlags) + => combinedFlags & unchecked((AssemblyNameFlags)0xFFFFF10F); + + internal static AssemblyContentType ExtractAssemblyContentType(AssemblyNameFlags flags) + => (AssemblyContentType)((((int)flags) >> 9) & 0x7); + + internal static ProcessorArchitecture ExtractProcessorArchitecture(AssemblyNameFlags flags) + => (ProcessorArchitecture)((((int)flags) >> 4) & 0x7); + } +} diff --git a/src/libraries/Common/src/System/Reflection/Metadata/TypeName.cs b/src/libraries/Common/src/System/Reflection/Metadata/TypeName.cs new file mode 100644 index 00000000000000..2fac2f8ffd74db --- /dev/null +++ b/src/libraries/Common/src/System/Reflection/Metadata/TypeName.cs @@ -0,0 +1,398 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#nullable enable + +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using System.Text; + +#if !SYSTEM_PRIVATE_CORELIB +using System.Collections.Immutable; +#endif + +namespace System.Reflection.Metadata +{ + [DebuggerDisplay("{AssemblyQualifiedName}")] +#if SYSTEM_PRIVATE_CORELIB + internal +#else + public +#endif + sealed class TypeName + { + /// + /// Positive value is array rank. + /// Negative value is modifier encoded using constants defined in . + /// + private readonly sbyte _rankOrModifier; + /// + /// To avoid the need of allocating a string for all declaring types (example: A+B+C+D+E+F+G), + /// length of the name is stored and the fullName passed in ctor represents the full name of the nested type. + /// So when the name is needed, a substring is being performed. + /// + private readonly int _nestedNameLength; + private readonly TypeName? _elementOrGenericType; + private readonly TypeName? _declaringType; +#if SYSTEM_PRIVATE_CORELIB + private readonly List? _genericArguments; +#else + private readonly ImmutableArray _genericArguments; +#endif + private string? _name, _fullName, _assemblyQualifiedName; + + internal TypeName(string? fullName, + AssemblyNameInfo? assemblyName, + TypeName? elementOrGenericType = default, + TypeName? declaringType = default, +#if SYSTEM_PRIVATE_CORELIB + List? genericTypeArguments = default, +#else + ImmutableArray.Builder? genericTypeArguments = default, +#endif + sbyte rankOrModifier = default, + int nestedNameLength = -1) + { + _fullName = fullName; + AssemblyName = assemblyName; + _rankOrModifier = rankOrModifier; + _elementOrGenericType = elementOrGenericType; + _declaringType = declaringType; + _nestedNameLength = nestedNameLength; + +#if SYSTEM_PRIVATE_CORELIB + _genericArguments = genericTypeArguments; +#else + _genericArguments = genericTypeArguments is null + ? ImmutableArray.Empty + : genericTypeArguments.Count == genericTypeArguments.Capacity ? genericTypeArguments.MoveToImmutable() : genericTypeArguments.ToImmutableArray(); +#endif + } + + /// + /// The assembly-qualified name of the type; e.g., "System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089". + /// + /// + /// If returns null, simply returns . + /// + public string AssemblyQualifiedName + => _assemblyQualifiedName ??= AssemblyName is null ? FullName : $"{FullName}, {AssemblyName.FullName}"; + + /// + /// Returns assembly name which contains this type, or null if this was not + /// created from a fully-qualified name. + /// + public AssemblyNameInfo? AssemblyName { get; } + + /// + /// If this type is a nested type (see ), gets + /// the declaring type. If this type is not a nested type, throws. + /// + /// + /// For example, given "Namespace.Declaring+Nested", unwraps the outermost type and returns "Namespace.Declaring". + /// + /// The current type is not a nested type. + public TypeName DeclaringType + { + get + { + if (_declaringType is null) + { + TypeNameParserHelpers.ThrowInvalidOperation_NotNestedType(); + } + + return _declaringType; + } + } + + /// + /// The full name of this type, including namespace, but without the assembly name; e.g., "System.Int32". + /// Nested types are represented with a '+'; e.g., "MyNamespace.MyType+NestedType". + /// + /// + /// For constructed generic types, the type arguments will be listed using their fully qualified + /// names. For example, given "List<int>", the property will return + /// "System.Collections.Generic.List`1[[System.Int32, mscorlib, ...]]". + /// For open generic types, the convention is to use a backtick ("`") followed by + /// the arity of the generic type. For example, given "Dictionary<,>", the + /// property will return "System.Collections.Generic.Dictionary`2". Given "Dictionary<,>.Enumerator", + /// the property will return "System.Collections.Generic.Dictionary`2+Enumerator". + /// See ECMA-335, Sec. I.10.7.2 (Type names and arity encoding) for more information. + /// + public string FullName + { + get + { + if (_fullName is null) + { + if (IsConstructedGenericType) + { + _fullName = TypeNameParserHelpers.GetGenericTypeFullName(GetGenericTypeDefinition().FullName.AsSpan(), +#if SYSTEM_PRIVATE_CORELIB + CollectionsMarshal.AsSpan(_genericArguments)); +#else + _genericArguments.AsSpan()); +#endif + } + else if (IsArray || IsPointer || IsByRef) + { + ValueStringBuilder builder = new(stackalloc char[128]); + builder.Append(GetElementType().FullName); + _fullName = TypeNameParserHelpers.GetRankOrModifierStringRepresentation(_rankOrModifier, ref builder); + } + else + { + Debug.Fail("Pre-allocated full name should have been provided in the ctor"); + } + } + else if (_nestedNameLength > 0 && _fullName.Length > _nestedNameLength) // Declaring types + { + // Stored fullName represents the full name of the nested type. + // Example: Namespace.Declaring+Nested + _fullName = _fullName.Substring(0, _nestedNameLength); + } + + return _fullName!; + } + } + + /// + /// Returns true if this type represents any kind of array, regardless of the array's + /// rank or its bounds. + /// + public bool IsArray => _rankOrModifier == TypeNameParserHelpers.SZArray || _rankOrModifier > 0; + + /// + /// Returns true if this type represents a constructed generic type (e.g., "List<int>"). + /// + /// + /// Returns false for open generic types (e.g., "Dictionary<,>"). + /// + public bool IsConstructedGenericType => +#if SYSTEM_PRIVATE_CORELIB + _genericArguments is not null; +#else + _genericArguments.Length > 0; +#endif + + /// + /// Returns true if this is a "plain" type; that is, not an array, not a pointer, not a reference, and + /// not a constructed generic type. Examples of elemental types are "System.Int32", + /// "System.Uri", and "YourNamespace.YourClass". + /// + /// + /// This property returning true doesn't mean that the type is a primitive like string + /// or int; it just means that there's no underlying type. + /// This property will return true for generic type definitions (e.g., "Dictionary<,>"). + /// This is because determining whether a type truly is a generic type requires loading the type + /// and performing a runtime check. + /// + public bool IsSimple => _elementOrGenericType is null; + + /// + /// Returns true if this is a managed pointer type (e.g., "ref int"). + /// Managed pointer types are sometimes called byref types () + /// + public bool IsByRef => _rankOrModifier == TypeNameParserHelpers.ByRef; + + /// + /// Returns true if this is a nested type (e.g., "Namespace.Declaring+Nested"). + /// For nested types returns their declaring type. + /// + public bool IsNested => _declaringType is not null; + + /// + /// Returns true if this type represents a single-dimensional, zero-indexed array (e.g., "int[]"). + /// + public bool IsSZArray => _rankOrModifier == TypeNameParserHelpers.SZArray; + + /// + /// Returns true if this type represents an unmanaged pointer (e.g., "int*" or "void*"). + /// Unmanaged pointer types are often just called pointers () + /// + public bool IsPointer => _rankOrModifier == TypeNameParserHelpers.Pointer; + + /// + /// Returns true if this type represents a variable-bound array; that is, an array of rank greater + /// than 1 (e.g., "int[,]") or a single-dimensional array which isn't necessarily zero-indexed. + /// + public bool IsVariableBoundArrayType => _rankOrModifier >= 1; + + /// + /// The name of this type, without the namespace and the assembly name; e.g., "Int32". + /// Nested types are represented without a '+'; e.g., "MyNamespace.MyType+NestedType" is just "NestedType". + /// + public string Name + { + get + { + if (_name is null) + { + if (IsConstructedGenericType) + { + _name = TypeNameParserHelpers.GetName(GetGenericTypeDefinition().FullName.AsSpan()).ToString(); + } + else if (IsPointer || IsByRef || IsArray) + { + ValueStringBuilder builder = new(stackalloc char[64]); + builder.Append(GetElementType().Name); + _name = TypeNameParserHelpers.GetRankOrModifierStringRepresentation(_rankOrModifier, ref builder); + } + else if (_nestedNameLength > 0 && _fullName is not null) + { + _name = TypeNameParserHelpers.GetName(_fullName.AsSpan(0, _nestedNameLength)).ToString(); + } + else + { + _name = TypeNameParserHelpers.GetName(FullName.AsSpan()).ToString(); + } + } + + return _name; + } + } + + /// + /// Represents the total number of instances that are used to describe + /// this instance, including any generic arguments or underlying types. + /// + /// + /// This value is computed every time this method gets called, it's not cached. + /// There's not really a parallel concept to this in reflection. Think of it + /// as the total number of instances that would be created if + /// you were to totally deconstruct this instance and visit each intermediate + /// that occurs as part of deconstruction. + /// "int" and "Person" each have complexities of 1 because they're standalone types. + /// "int[]" has a node count of 2 because to fully inspect it involves inspecting the + /// array type itself, plus unwrapping the underlying type ("int") and inspecting that. + /// + /// "Dictionary<string, List<int[][]>>" has node count 8 because fully visiting it + /// involves inspecting 8 instances total: + /// + /// Dictionary<string, List<int[][]>> (the original type) + /// Dictionary`2 (the generic type definition) + /// string (a type argument of Dictionary) + /// List<int[][]> (a type argument of Dictionary) + /// List`1 (the generic type definition) + /// int[][] (a type argument of List) + /// int[] (the underlying type of int[][]) + /// int (the underlying type of int[]) + /// + /// + /// + public int GetNodeCount() + { + int result = 1; + + if (IsNested) + { + result += DeclaringType.GetNodeCount(); + } + else if (IsConstructedGenericType) + { + result++; + } + else if (IsArray || IsPointer || IsByRef) + { + result += GetElementType().GetNodeCount(); + } + + foreach (TypeName genericArgument in GetGenericArguments()) + { + result += genericArgument.GetNodeCount(); + } + + return result; + } + + /// + /// The TypeName of the object encompassed or referred to by the current array, pointer, or reference type. + /// + /// + /// For example, given "int[][]", unwraps the outermost array and returns "int[]". + /// + /// The current type is not an array, pointer or reference. + public TypeName GetElementType() + { + if (!(IsArray || IsPointer || IsByRef)) + { + TypeNameParserHelpers.ThrowInvalidOperation_NoElement(); + } + + return _elementOrGenericType!; + } + + /// + /// Returns a TypeName object that represents a generic type name definition from which the current generic type name can be constructed. + /// + /// + /// Given "Dictionary<string, int>", returns the generic type definition "Dictionary<,>". + /// + /// The current type is not a generic type. + public TypeName GetGenericTypeDefinition() + { + if (!IsConstructedGenericType) + { + TypeNameParserHelpers.ThrowInvalidOperation_NotGenericType(); + } + + return _elementOrGenericType!; + } + + /// + /// Parses a span of characters into a type name. + /// + /// A span containing the characters representing the type name to parse. + /// An object that describes optional parameters to use. + /// Parsed type name. + /// Provided type name was invalid. + /// Parsing has exceeded the limit set by . + public static TypeName Parse(ReadOnlySpan typeName, TypeNameParseOptions? options = default) + => TypeNameParser.Parse(typeName, throwOnError: true, options)!; + + /// + /// Tries to parse a span of characters into a type name. + /// + /// A span containing the characters representing the type name to parse. + /// An object that describes optional parameters to use. + /// Contains the result when parsing succeeds. + /// true if type name was converted successfully, otherwise, false. + public static bool TryParse(ReadOnlySpan typeName, [NotNullWhen(true)] out TypeName? result, TypeNameParseOptions? options = default) + { + result = TypeNameParser.Parse(typeName, throwOnError: false, options); + return result is not null; + } + + /// + /// Gets the number of dimensions in an array. + /// + /// An integer that contains the number of dimensions in the current type. + /// The current type is not an array. + public int GetArrayRank() + { + if (!(_rankOrModifier == TypeNameParserHelpers.SZArray || _rankOrModifier > 0)) + { + TypeNameParserHelpers.ThrowInvalidOperation_HasToBeArrayClass(); + } + + return _rankOrModifier == TypeNameParserHelpers.SZArray ? 1 : _rankOrModifier; + } + + /// + /// If this represents a constructed generic type, returns an array + /// of all the generic arguments. Otherwise it returns an empty array. + /// + /// + /// For example, given "Dictionary<string, int>", returns a 2-element array containing + /// string and int. + /// + public +#if SYSTEM_PRIVATE_CORELIB + IReadOnlyList GetGenericArguments() => _genericArguments is null ? Array.Empty() : _genericArguments; +#else + ImmutableArray GetGenericArguments() => _genericArguments; +#endif + } +} diff --git a/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParser.cs b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParser.cs new file mode 100644 index 00000000000000..7c75f3ee844d6d --- /dev/null +++ b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParser.cs @@ -0,0 +1,260 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics; + +#if !SYSTEM_PRIVATE_CORELIB +using System.Collections.Immutable; +#endif + +using static System.Reflection.Metadata.TypeNameParserHelpers; + +#nullable enable + +namespace System.Reflection.Metadata +{ + [DebuggerDisplay("{_inputString}")] + internal ref struct TypeNameParser + { + private static readonly TypeNameParseOptions _defaults = new(); + private readonly bool _throwOnError; + private readonly TypeNameParseOptions _parseOptions; + private ReadOnlySpan _inputString; + + private TypeNameParser(ReadOnlySpan name, bool throwOnError, TypeNameParseOptions? options) : this() + { + _inputString = name; + _throwOnError = throwOnError; + _parseOptions = options ?? _defaults; + } + + internal static TypeName? Parse(ReadOnlySpan typeName, bool throwOnError, TypeNameParseOptions? options = default) + { + ReadOnlySpan trimmedName = typeName.TrimStart(); // whitespaces at beginning are always OK + if (trimmedName.IsEmpty) + { + if (throwOnError) + { + ThrowArgumentException_InvalidTypeName(errorIndex: 0); // whitespace input needs to report the error index as 0 + } + + return null; + } + + int recursiveDepth = 0; + TypeNameParser parser = new(trimmedName, throwOnError, options); + TypeName? parsedName = parser.ParseNextTypeName(allowFullyQualifiedName: true, ref recursiveDepth); + + if (parsedName is null || !parser._inputString.IsEmpty) // unconsumed input == error + { + if (throwOnError) + { + if (recursiveDepth >= parser._parseOptions.MaxNodes) + { + ThrowInvalidOperation_MaxNodesExceeded(parser._parseOptions.MaxNodes); + } + + int errorIndex = typeName.Length - parser._inputString.Length; + ThrowArgumentException_InvalidTypeName(errorIndex); + } + + return null; + } + + return parsedName; + } + + // this method should return null instead of throwing, so the caller can get errorIndex and include it in error msg + private TypeName? ParseNextTypeName(bool allowFullyQualifiedName, ref int recursiveDepth) + { + if (!TryDive(ref recursiveDepth)) + { + return null; + } + + List? nestedNameLengths = null; + if (!TryGetTypeNameInfo(ref _inputString, ref nestedNameLengths, out int fullTypeNameLength)) + { + return null; + } + + ReadOnlySpan fullTypeName = _inputString.Slice(0, fullTypeNameLength); + _inputString = _inputString.Slice(fullTypeNameLength); + + // Don't allocate now, as it may be an open generic type like "Name`1" +#if SYSTEM_PRIVATE_CORELIB + List? genericArgs = null; +#else + ImmutableArray.Builder? genericArgs = null; +#endif + + // Are there any captured generic args? We'll look for "[[" and "[". + // There are no spaces allowed before the first '[', but spaces are allowed + // after that. The check slices _inputString, so we'll capture it into + // a local so we can restore it later if needed. + ReadOnlySpan capturedBeforeProcessing = _inputString; + if (IsBeginningOfGenericArgs(ref _inputString, out bool doubleBrackets)) + { + ParseAnotherGenericArg: + + // Namespace.Type`2[[GenericArgument1, AssemblyName1],[GenericArgument2, AssemblyName2]] - double square bracket syntax allows for fully qualified type names + // Namespace.Type`2[GenericArgument1,GenericArgument2] - single square bracket syntax is legal only for non-fully qualified type names + // Namespace.Type`2[[GenericArgument1, AssemblyName1], GenericArgument2] - mixed mode + // Namespace.Type`2[GenericArgument1, [GenericArgument2, AssemblyName2]] - mixed mode + TypeName? genericArg = ParseNextTypeName(allowFullyQualifiedName: doubleBrackets, ref recursiveDepth); + if (genericArg is null) // parsing failed + { + return null; + } + + // For [[, there had better be a ']' after the type name. + if (doubleBrackets && !TryStripFirstCharAndTrailingSpaces(ref _inputString, ']')) + { + return null; + } + + if (genericArgs is null) + { +#if SYSTEM_PRIVATE_CORELIB + genericArgs = new List(2); +#else + genericArgs = ImmutableArray.CreateBuilder(2); +#endif + } + genericArgs.Add(genericArg); + + // Is there a ',[' indicating fully qualified generic type arg? + // Is there a ',' indicating non-fully qualified generic type arg? + if (TryStripFirstCharAndTrailingSpaces(ref _inputString, ',')) + { + doubleBrackets = TryStripFirstCharAndTrailingSpaces(ref _inputString, '['); + + goto ParseAnotherGenericArg; + } + + // The only other allowable character is ']', indicating the end of + // the generic type arg list. + if (!TryStripFirstCharAndTrailingSpaces(ref _inputString, ']')) + { + return null; + } + } + + // If there was an error stripping the generic args, back up to + // before we started processing them, and let the decorator + // parser try handling it. + if (genericArgs is null) + { + _inputString = capturedBeforeProcessing; + } + + int previousDecorator = default; + // capture the current state so we can reprocess it again once we know the AssemblyName + capturedBeforeProcessing = _inputString; + // iterate over the decorators to ensure there are no illegal combinations + while (TryParseNextDecorator(ref _inputString, out int parsedDecorator)) + { + if (!TryDive(ref recursiveDepth)) + { + return null; + } + + // Currently it's illegal for managed reference to be followed by any other decorator, + // but this is a runtime-specific behavior and the parser is not enforcing that rule. + previousDecorator = parsedDecorator; + } + + AssemblyNameInfo? assemblyName = null; + if (allowFullyQualifiedName && !TryParseAssemblyName(ref assemblyName)) + { +#if SYSTEM_PRIVATE_CORELIB + // backward compat: throw FileLoadException for non-empty invalid strings + if (_throwOnError || !_inputString.TrimStart().StartsWith(",")) + { + throw new IO.FileLoadException(SR.InvalidAssemblyName, _inputString.ToString()); + } +#else + return null; +#endif + } + + // No matter what was parsed, the full name string is allocated only once. + // In case of generic, nested, array, pointer and byref types the full name is allocated + // when needed for the first time . + string fullName = fullTypeName.ToString(); + + TypeName? declaringType = GetDeclaringType(fullName, nestedNameLengths, assemblyName); + TypeName result = new(fullName, assemblyName, declaringType: declaringType); + if (genericArgs is not null) + { + result = new(fullName: null, assemblyName, elementOrGenericType: result, declaringType, genericArgs); + } + + if (previousDecorator != default) // some decorators were recognized + { + while (TryParseNextDecorator(ref capturedBeforeProcessing, out int parsedModifier)) + { + result = new(fullName: null, assemblyName, elementOrGenericType: result, rankOrModifier: (sbyte)parsedModifier); + } + } + + return result; + } + + /// false means the input was invalid and parsing has failed. Empty input is valid and returns true. + private bool TryParseAssemblyName(ref AssemblyNameInfo? assemblyName) + { + ReadOnlySpan capturedBeforeProcessing = _inputString; + if (TryStripFirstCharAndTrailingSpaces(ref _inputString, ',')) + { + if (_inputString.IsEmpty) + { + _inputString = capturedBeforeProcessing; // restore the state + return false; + } + + ReadOnlySpan candidate = GetAssemblyNameCandidate(_inputString); + if (!AssemblyNameInfo.TryParse(candidate, out assemblyName)) + { + return false; + } + + _inputString = _inputString.Slice(candidate.Length); + return true; + } + + return true; + } + + private static TypeName? GetDeclaringType(string fullTypeName, List? nestedNameLengths, AssemblyNameInfo? assemblyName) + { + if (nestedNameLengths is null) + { + return null; + } + + TypeName? declaringType = null; + int nameOffset = 0; + foreach (int nestedNameLength in nestedNameLengths) + { + Debug.Assert(nestedNameLength > 0, "TryGetTypeNameInfo should return error on zero lengths"); + int fullNameLength = nameOffset + nestedNameLength; + declaringType = new(fullTypeName, assemblyName, declaringType: declaringType, nestedNameLength: fullNameLength); + nameOffset += nestedNameLength + 1; // include the '+' that was skipped in name + } + + return declaringType; + } + + private bool TryDive(ref int depth) + { + if (depth >= _parseOptions.MaxNodes) + { + return false; + } + depth++; + return true; + } + } +} diff --git a/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserHelpers.cs b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserHelpers.cs new file mode 100644 index 00000000000000..3783f56c73d4b7 --- /dev/null +++ b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserHelpers.cs @@ -0,0 +1,383 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Text; + +#nullable enable + +namespace System.Reflection.Metadata +{ + internal static class TypeNameParserHelpers + { + internal const sbyte SZArray = -1; + internal const sbyte Pointer = -2; + internal const sbyte ByRef = -3; + private const char EscapeCharacter = '\\'; +#if NET8_0_OR_GREATER + private static readonly SearchValues s_endOfFullTypeNameDelimitersSearchValues = SearchValues.Create("[]&*,+\\"); +#endif + + internal static string GetGenericTypeFullName(ReadOnlySpan fullTypeName, ReadOnlySpan genericArgs) + { + Debug.Assert(genericArgs.Length > 0); + + ValueStringBuilder result = new(stackalloc char[128]); + result.Append(fullTypeName); + + result.Append('['); + foreach (TypeName genericArg in genericArgs) + { + result.Append('['); + result.Append(genericArg.AssemblyQualifiedName); + result.Append(']'); + result.Append(','); + } + result[result.Length - 1] = ']'; // replace ',' with ']' + + return result.ToString(); + } + + /// Positive length or negative value for invalid name + internal static int GetFullTypeNameLength(ReadOnlySpan input, out bool isNestedType) + { + isNestedType = false; + + // NET 6+ guarantees that MemoryExtensions.IndexOfAny has worst-case complexity + // O(m * i) if a match is found, or O(m * n) if a match is not found, where: + // i := index of match position + // m := number of needles + // n := length of search space (haystack) + // + // Downlevel versions of .NET do not make this guarantee, instead having a + // worst-case complexity of O(m * n) even if a match occurs at the beginning of + // the search space. Since we're running this in a loop over untrusted user + // input, that makes the total loop complexity potentially O(m * n^2), where + // 'n' is adversary-controlled. To avoid DoS issues here, we'll loop manually. + +#if NET8_0_OR_GREATER + int offset = input.IndexOfAny(s_endOfFullTypeNameDelimitersSearchValues); + if (offset < 0) + { + return input.Length; // no type name end chars were found, the whole input is the type name + } + + if (input[offset] == EscapeCharacter) // this is very rare (IL Emit or pure IL) + { + offset = GetUnescapedOffset(input, startOffset: offset); // this is slower, but very rare so acceptable + } +#else + int offset = GetUnescapedOffset(input, startOffset: 0); +#endif + isNestedType = offset > 0 && offset < input.Length && input[offset] == '+'; + return offset; + + static int GetUnescapedOffset(ReadOnlySpan input, int startOffset) + { + int offset = startOffset; + for (; offset < input.Length; offset++) + { + char c = input[offset]; + if (c == EscapeCharacter) + { + offset++; // skip the escaped char + + if (offset == input.Length || // invalid name that ends with escape character + !NeedsEscaping(input[offset])) // invalid name, escapes a char that does not need escaping + { + return -1; + } + } + else if (NeedsEscaping(c)) + { + break; + } + } + return offset; + } + + static bool NeedsEscaping(char c) => c is '[' or ']' or '&' or '*' or ',' or '+' or EscapeCharacter; + } + + internal static ReadOnlySpan GetName(ReadOnlySpan fullName) + { + int offset = fullName.LastIndexOfAny('.', '+'); + + if (offset > 0 && fullName[offset - 1] == EscapeCharacter) // this should be very rare (IL Emit & pure IL) + { + offset = GetUnescapedOffset(fullName, startIndex: offset); + } + + return offset < 0 ? fullName : fullName.Slice(offset + 1); + + static int GetUnescapedOffset(ReadOnlySpan fullName, int startIndex) + { + int offset = startIndex; + for (; offset >= 0; offset--) + { + if (fullName[offset] is '.' or '+') + { + if (offset == 0 || fullName[offset - 1] != EscapeCharacter) + { + break; + } + offset--; // skip the escaping character + } + } + return offset; + } + } + + // this method handles escaping of the ] just to let the AssemblyNameParser fail for the right input + internal static ReadOnlySpan GetAssemblyNameCandidate(ReadOnlySpan input) + { + // The only delimiter which can terminate an assembly name is ']'. + // Otherwise EOL serves as the terminator. + int offset = input.IndexOf(']'); + + if (offset > 0 && input[offset - 1] == EscapeCharacter) // this should be very rare (IL Emit & pure IL) + { + offset = GetUnescapedOffset(input, startIndex: offset); + } + + return offset < 0 ? input : input.Slice(0, offset); + + static int GetUnescapedOffset(ReadOnlySpan input, int startIndex) + { + int offset = startIndex; + for (; offset < input.Length; offset++) + { + if (input[offset] is ']') + { + if (input[offset - 1] != EscapeCharacter) + { + break; + } + } + } + return offset; + } + } + + internal static string GetRankOrModifierStringRepresentation(int rankOrModifier, ref ValueStringBuilder builder) + { + if (rankOrModifier == ByRef) + { + builder.Append('&'); + } + else if (rankOrModifier == Pointer) + { + builder.Append('*'); + } + else if (rankOrModifier == SZArray) + { + builder.Append("[]"); + } + else if (rankOrModifier == 1) + { + builder.Append("[*]"); + } + else + { + Debug.Assert(rankOrModifier >= 2); + + builder.Append('['); + builder.Append(',', rankOrModifier - 1); + builder.Append(']'); + } + + return builder.ToString(); + } + + /// + /// Are there any captured generic args? We'll look for "[[" and "[" that is not followed by "]", "*" and ",". + /// + internal static bool IsBeginningOfGenericArgs(ref ReadOnlySpan span, out bool doubleBrackets) + { + doubleBrackets = false; + + if (!span.IsEmpty && span[0] == '[') + { + // There are no spaces allowed before the first '[', but spaces are allowed after that. + ReadOnlySpan trimmed = span.Slice(1).TrimStart(); + if (!trimmed.IsEmpty) + { + if (trimmed[0] == '[') + { + doubleBrackets = true; + span = trimmed.Slice(1).TrimStart(); + return true; + } + if (!(trimmed[0] is ',' or '*' or ']')) // [] or [*] or [,] or [,,,, ...] + { + span = trimmed; + return true; + } + } + } + + return false; + } + + internal static bool TryGetTypeNameInfo(ref ReadOnlySpan input, ref List? nestedNameLengths, out int totalLength) + { + bool isNestedType; + totalLength = 0; + do + { + int length = GetFullTypeNameLength(input.Slice(totalLength), out isNestedType); + if (length <= 0) + { + // invalid type names: + // -1: invalid escaping + // 0: pair of unescaped "++" characters + return false; + } + +#if SYSTEM_PRIVATE_CORELIB + // Compat: Ignore leading '.' for type names without namespace. .NET Framework historically ignored leading '.' here. It is likely + // that code out there depends on this behavior. For example, type names formed by concatenating namespace and name, without checking for + // empty namespace (bug), are going to have superfluous leading '.'. + // This behavior means that types that start with '.' are not round-trippable via type name. + if (length > 1 && input[0] == '.' && input.Slice(0, length).LastIndexOf('.') == 0) + { + input = input.Slice(1); + length--; + } +#endif + if (isNestedType) + { + (nestedNameLengths ??= new()).Add(length); + totalLength += 1; // skip the '+' sign in next search + } + totalLength += length; + } while (isNestedType); + + return true; + } + + internal static bool TryParseNextDecorator(ref ReadOnlySpan input, out int rankOrModifier) + { + // Then try pulling a single decorator. + // Whitespace cannot precede the decorator, but it can follow the decorator. + + ReadOnlySpan originalInput = input; // so we can restore on 'false' return + + if (TryStripFirstCharAndTrailingSpaces(ref input, '*')) + { + rankOrModifier = Pointer; + return true; + } + + if (TryStripFirstCharAndTrailingSpaces(ref input, '&')) + { + rankOrModifier = ByRef; + return true; + } + + if (TryStripFirstCharAndTrailingSpaces(ref input, '[')) + { + // SZArray := [] + // MDArray := [*] or [,] or [,,,, ...] + + int rank = 1; + bool hasSeenAsterisk = false; + + ReadNextArrayToken: + + if (TryStripFirstCharAndTrailingSpaces(ref input, ']')) + { + // End of array marker + rankOrModifier = rank == 1 && !hasSeenAsterisk ? SZArray : rank; + return true; + } + + if (!hasSeenAsterisk) + { + if (rank == 1 && TryStripFirstCharAndTrailingSpaces(ref input, '*')) + { + // [*] + hasSeenAsterisk = true; + goto ReadNextArrayToken; + } + else if (TryStripFirstCharAndTrailingSpaces(ref input, ',')) + { + // [,,, ...] + checked { rank++; } + goto ReadNextArrayToken; + } + } + + // Don't know what this token is. + // Fall through to 'return false' statement. + } + + input = originalInput; // ensure 'ref input' not mutated + rankOrModifier = 0; + return false; + } + + internal static bool TryStripFirstCharAndTrailingSpaces(ref ReadOnlySpan span, char value) + { + if (!span.IsEmpty && span[0] == value) + { + span = span.Slice(1).TrimStart(); + return true; + } + return false; + } + + [DoesNotReturn] + internal static void ThrowInvalidOperation_MaxNodesExceeded(int limit) => throw +#if SYSTEM_REFLECTION_METADATA + new InvalidOperationException(SR.Format(SR.InvalidOperation_MaxNodesExceeded, limit)); +#else // corelib and tools that reference this file as a link + new InvalidOperationException(); +#endif + + [DoesNotReturn] + internal static void ThrowArgumentException_InvalidTypeName(int errorIndex) => throw +#if SYSTEM_PRIVATE_CORELIB + new ArgumentException(SR.Arg_ArgumentException, $"typeName@{errorIndex}"); +#elif SYSTEM_REFLECTION_METADATA + new ArgumentException(SR.Argument_InvalidTypeName, $"typeName@{errorIndex}"); +#else // tools that reference this file as a link + new ArgumentException(); +#endif + + [DoesNotReturn] + internal static void ThrowInvalidOperation_NotGenericType() => throw +#if SYSTEM_REFLECTION_METADATA || SYSTEM_PRIVATE_CORELIB + new InvalidOperationException(SR.InvalidOperation_NotGenericType); +#else // tools that reference this file as a link + new InvalidOperationException(); +#endif + + [DoesNotReturn] + internal static void ThrowInvalidOperation_NotNestedType() => throw +#if SYSTEM_REFLECTION_METADATA + new InvalidOperationException(SR.InvalidOperation_NotNestedType); +#else // corelib and tools that reference this file as a link + new InvalidOperationException(); +#endif + + [DoesNotReturn] + internal static void ThrowInvalidOperation_NoElement() => throw +#if SYSTEM_REFLECTION_METADATA + new InvalidOperationException(SR.InvalidOperation_NoElement); +#else // corelib and tools that reference this file as a link + new InvalidOperationException(); +#endif + + [DoesNotReturn] + internal static void ThrowInvalidOperation_HasToBeArrayClass() => throw +#if SYSTEM_REFLECTION_METADATA || SYSTEM_PRIVATE_CORELIB + new InvalidOperationException(SR.Argument_HasToBeArrayClass); +#else // tools that reference this file as a link + new InvalidOperationException(); +#endif + } +} diff --git a/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserOptions.cs b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserOptions.cs new file mode 100644 index 00000000000000..66350c9a44cac7 --- /dev/null +++ b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserOptions.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Reflection.Metadata +{ +#if SYSTEM_PRIVATE_CORELIB + internal +#else + public +#endif + sealed class TypeNameParseOptions + { + private int _maxNodes = +#if SYSTEM_PRIVATE_CORELIB + int.MaxValue; // CoreLib has never introduced any limits +#else + 20; +#endif + + /// + /// Limits the maximum value of node count that parser can handle. + /// + public int MaxNodes + { + get => _maxNodes; + set + { +#if NET8_0_OR_GREATER + ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(value, 0, nameof(value)); +#else + if (value <= 0) + { + throw new ArgumentOutOfRangeException(paramName: nameof(value)); + } +#endif + + _maxNodes = value; + } + } + } +} diff --git a/src/libraries/Common/src/System/Reflection/TypeNameParser.Helpers.cs b/src/libraries/Common/src/System/Reflection/TypeNameParser.Helpers.cs new file mode 100644 index 00000000000000..bcb2125d3f4ea3 --- /dev/null +++ b/src/libraries/Common/src/System/Reflection/TypeNameParser.Helpers.cs @@ -0,0 +1,192 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Reflection.Metadata; +using System.Text; + +#nullable enable + +namespace System.Reflection +{ + internal partial struct TypeNameParser + { +#if !MONO // Mono never needs unescaped names + private const char EscapeCharacter = '\\'; + + /// + /// Removes escape characters from the string (if there were any found). + /// + private static string UnescapeTypeName(string name) + { + int indexOfEscapeCharacter = name.IndexOf(EscapeCharacter); + if (indexOfEscapeCharacter < 0) + { + return name; + } + + return Unescape(name, indexOfEscapeCharacter); + + static string Unescape(string name, int indexOfEscapeCharacter) + { + // this code path is executed very rarely (IL Emit or pure IL with chars not allowed in C# or F#) + var sb = new ValueStringBuilder(stackalloc char[64]); + sb.EnsureCapacity(name.Length); + sb.Append(name.AsSpan(0, indexOfEscapeCharacter)); + + for (int i = indexOfEscapeCharacter; i < name.Length;) + { + char c = name[i++]; + + if (c != EscapeCharacter) + { + sb.Append(c); + } + else if (i < name.Length && name[i] == EscapeCharacter) // escaped escape character ;) + { + sb.Append(c); + // Consume the escaped escape character, it's important for edge cases + // like escaped escape character followed by another escaped char (example: "\\\\\\+") + i++; + } + } + + return sb.ToString(); + } + } +#endif + + private static (string typeNamespace, string name) SplitFullTypeName(string typeName) + { + string typeNamespace, name; + + // Matches algorithm from ns::FindSep in src\coreclr\utilcode\namespaceutil.cpp + // This could result in the type name beginning with a '.' character. + int separator = typeName.LastIndexOf('.'); + if (separator <= 0) + { + typeNamespace = ""; + name = typeName; + } + else + { + if (typeName[separator - 1] == '.') + separator--; + typeNamespace = typeName.Substring(0, separator); + name = typeName.Substring(separator + 1); + } + + return (typeNamespace, name); + } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050:RequiresDynamicCode", + Justification = "Used to implement resolving types from strings.")] + private Type? Resolve(TypeName typeName) + { + if (typeName.IsNested) + { + TypeName? current = typeName; + int nestingDepth = 0; + while (current is not null && current.IsNested) + { + nestingDepth++; + current = current.DeclaringType; + } + + // We're performing real type resolution, it is assumed that the caller has already validated the correctness + // of this TypeName object against their own policies, so there is no need for this method to perform any further checks. + string[] nestedTypeNames = new string[nestingDepth]; + current = typeName; + while (current is not null && current.IsNested) + { +#if MONO + nestedTypeNames[--nestingDepth] = current.Name; +#else // CLR, NativeAOT and tools require unescaped nested type names + nestedTypeNames[--nestingDepth] = UnescapeTypeName(current.Name); +#endif + current = current.DeclaringType; + } +#if SYSTEM_PRIVATE_CORELIB + string nonNestedParentName = current!.FullName; +#else // the tools require unescaped names + string nonNestedParentName = UnescapeTypeName(current!.FullName); +#endif + Type? type = GetType(nonNestedParentName, nestedTypeNames, typeName); + return type is null || !typeName.IsConstructedGenericType ? type : MakeGenericType(type, typeName); + } + else if (typeName.IsConstructedGenericType) + { + Type? type = Resolve(typeName.GetGenericTypeDefinition()); + return type is null ? null : MakeGenericType(type, typeName); + } + else if (typeName.IsArray || typeName.IsPointer || typeName.IsByRef) + { + Type? type = Resolve(typeName.GetElementType()); + if (type is null) + { + return null; + } + + if (typeName.IsByRef) + { + return type.MakeByRefType(); + } + else if (typeName.IsPointer) + { + return type.MakePointerType(); + } + else if (typeName.IsSZArray) + { + return type.MakeArrayType(); + } + else + { + Debug.Assert(typeName.IsVariableBoundArrayType); + + return type.MakeArrayType(rank: typeName.GetArrayRank()); + } + } + else + { + Debug.Assert(typeName.IsSimple); + + Type? type = GetType( +#if SYSTEM_PRIVATE_CORELIB + typeName.FullName, +#else // the tools require unescaped names + UnescapeTypeName(typeName.FullName), +#endif + nestedTypeNames: ReadOnlySpan.Empty, typeName); + + return type; + } + } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern", + Justification = "Used to implement resolving types from strings.")] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050:RequiresDynamicCode", + Justification = "Used to implement resolving types from strings.")] + private Type? MakeGenericType(Type type, TypeName typeName) + { + var genericArgs = typeName.GetGenericArguments(); +#if SYSTEM_PRIVATE_CORELIB + int size = genericArgs.Count; +#else + int size = genericArgs.Length; +#endif + Type[] genericTypes = new Type[size]; + for (int i = 0; i < size; i++) + { + Type? genericArg = Resolve(genericArgs[i]); + if (genericArg is null) + { + return null; + } + genericTypes[i] = genericArg; + } + + return type.MakeGenericType(genericTypes); + } + } +} diff --git a/src/libraries/Common/src/System/Reflection/TypeNameParser.cs b/src/libraries/Common/src/System/Reflection/TypeNameParser.cs deleted file mode 100644 index 0b69e4e18aaae4..00000000000000 --- a/src/libraries/Common/src/System/Reflection/TypeNameParser.cs +++ /dev/null @@ -1,701 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; -using System.Text; - -#nullable enable - -namespace System.Reflection -{ - // - // Parser for type names passed to GetType() apis. - // - [StructLayout(LayoutKind.Auto)] - internal ref partial struct TypeNameParser - { - private ReadOnlySpan _input; - private int _index; - private int _errorIndex; // Position for error reporting - - private TypeNameParser(ReadOnlySpan name) - { - _input = name; - _errorIndex = _index = 0; - } - - // - // Parses a type name. The type name may be optionally postpended with a "," followed by a legal assembly name. - // - private Type? Parse() - { - TypeName? typeName = ParseNonQualifiedTypeName(); - if (typeName is null) - return null; - - string? assemblyName = null; - - TokenType token = GetNextToken(); - if (token != TokenType.End) - { - if (token != TokenType.Comma) - { - ParseError(); - return null; - } - - if (!CheckTopLevelAssemblyQualifiedName()) - return null; - - assemblyName = GetNextAssemblyName(); - if (assemblyName is null) - return null; - Debug.Assert(Peek == TokenType.End); - } - - return typeName.ResolveType(ref this, assemblyName); - } - - // - // Parses a type name without any assembly name qualification. - // - private TypeName? ParseNonQualifiedTypeName() - { - // Parse the named type or constructed generic type part first. - TypeName? typeName = ParseNamedOrConstructedGenericTypeName(); - if (typeName is null) - return null; - - // Iterate through any "has-element" qualifiers ([], &, *). - while (true) - { - TokenType token = Peek; - if (token == TokenType.End) - break; - if (token == TokenType.Asterisk) - { - Skip(); - typeName = new ModifierTypeName(typeName, ModifierTypeName.Pointer); - } - else if (token == TokenType.Ampersand) - { - Skip(); - typeName = new ModifierTypeName(typeName, ModifierTypeName.ByRef); - } - else if (token == TokenType.OpenSqBracket) - { - Skip(); - token = GetNextToken(); - if (token == TokenType.Asterisk) - { - typeName = new ModifierTypeName(typeName, 1); - token = GetNextToken(); - } - else - { - int rank = 1; - while (token == TokenType.Comma) - { - token = GetNextToken(); - rank++; - } - if (rank == 1) - typeName = new ModifierTypeName(typeName, ModifierTypeName.Array); - else - typeName = new ModifierTypeName(typeName, rank); - } - if (token != TokenType.CloseSqBracket) - { - ParseError(); - return null; - } - } - else - { - break; - } - } - return typeName; - } - - // - // Foo or Foo+Inner or Foo[String] or Foo+Inner[String] - // - private TypeName? ParseNamedOrConstructedGenericTypeName() - { - TypeName? namedType = ParseNamedTypeName(); - if (namedType is null) - return null; - - // Because "[" is used both for generic arguments and array indexes, we must peek two characters deep. - if (!(Peek is TokenType.OpenSqBracket && (PeekSecond is TokenType.Other or TokenType.OpenSqBracket))) - return namedType; - - Skip(); - - TypeName[] typeArguments = new TypeName[2]; - int typeArgumentsCount = 0; - while (true) - { - TypeName? typeArgument = ParseGenericTypeArgument(); - if (typeArgument is null) - return null; - if (typeArgumentsCount >= typeArguments.Length) - Array.Resize(ref typeArguments, 2 * typeArgumentsCount); - typeArguments[typeArgumentsCount++] = typeArgument; - TokenType token = GetNextToken(); - if (token == TokenType.CloseSqBracket) - break; - if (token != TokenType.Comma) - { - ParseError(); - return null; - } - } - - return new GenericTypeName(namedType, typeArguments, typeArgumentsCount); - } - - // - // Foo or Foo+Inner - // - private TypeName? ParseNamedTypeName() - { - string? fullName = GetNextIdentifier(); - if (fullName is null) - return null; - - fullName = ApplyLeadingDotCompatQuirk(fullName); - - if (Peek == TokenType.Plus) - { - string[] nestedNames = new string[1]; - int nestedNamesCount = 0; - - do - { - Skip(); - - string? nestedName = GetNextIdentifier(); - if (nestedName is null) - return null; - - nestedName = ApplyLeadingDotCompatQuirk(nestedName); - - if (nestedNamesCount >= nestedNames.Length) - Array.Resize(ref nestedNames, 2 * nestedNamesCount); - nestedNames[nestedNamesCount++] = nestedName; - } - while (Peek == TokenType.Plus); - - return new NestedNamespaceTypeName(fullName, nestedNames, nestedNamesCount); - } - else - { - return new NamespaceTypeName(fullName); - } - - // Compat: Ignore leading '.' for type names without namespace. .NET Framework historically ignored leading '.' here. It is likely - // that code out there depends on this behavior. For example, type names formed by concatenating namespace and name, without checking for - // empty namespace (bug), are going to have superfluous leading '.'. - // This behavior means that types that start with '.' are not round-trippable via type name. - static string ApplyLeadingDotCompatQuirk(string typeName) - { -#if NETCOREAPP - return (typeName.StartsWith('.') && !typeName.AsSpan(1).Contains('.')) ? typeName.Substring(1) : typeName; -#else - return ((typeName.Length > 0) && (typeName[0] == '.') && typeName.LastIndexOf('.') == 0) ? typeName.Substring(1) : typeName; -#endif - } - } - - // - // Parse a generic argument. In particular, generic arguments can take the special form [,]. - // - private TypeName? ParseGenericTypeArgument() - { - TokenType token = GetNextToken(); - if (token == TokenType.Other) - { - return ParseNonQualifiedTypeName(); - } - if (token != TokenType.OpenSqBracket) - { - ParseError(); - return null; - } - string? assemblyName = null; - TypeName? typeName = ParseNonQualifiedTypeName(); - if (typeName is null) - return null; - - token = GetNextToken(); - if (token == TokenType.Comma) - { - assemblyName = GetNextEmbeddedAssemblyName(); - token = GetNextToken(); - } - if (token != TokenType.CloseSqBracket) - { - ParseError(); - return null; - } - - return (assemblyName != null) ? new AssemblyQualifiedTypeName(typeName, assemblyName) : typeName; - } - - // - // String tokenizer for type names passed to the GetType() APIs. - // - - private TokenType Peek - { - get - { - SkipWhiteSpace(); - char c = (_index < _input.Length) ? _input[_index] : '\0'; - return CharToToken(c); - } - } - - private TokenType PeekSecond - { - get - { - SkipWhiteSpace(); - int index = _index + 1; - while (index < _input.Length && char.IsWhiteSpace(_input[index])) - index++; - char c = (index < _input.Length) ? _input[index] : '\0'; - return CharToToken(c); - } - } - - private void Skip() - { - SkipWhiteSpace(); - if (_index < _input.Length) - _index++; - } - - // Return the next token and skip index past it unless already at end of string - // or the token is not a reserved token. - private TokenType GetNextToken() - { - _errorIndex = _index; - - TokenType tokenType = Peek; - if (tokenType == TokenType.End || tokenType == TokenType.Other) - return tokenType; - Skip(); - return tokenType; - } - - // - // Lex the next segment as part of a type name. (Do not use for assembly names.) - // - // Note that unescaped "."'s do NOT terminate the identifier, but unescaped "+"'s do. - // - // Terminated by the first non-escaped reserved character ('[', ']', '+', '&', '*' or ',') - // - private string? GetNextIdentifier() - { - SkipWhiteSpace(); - - ValueStringBuilder sb = new ValueStringBuilder(stackalloc char[64]); - - int src = _index; - while (true) - { - if (src >= _input.Length) - break; - char c = _input[src]; - TokenType token = CharToToken(c); - if (token != TokenType.Other) - break; - src++; - if (c == '\\') // Check for escaped character - { - // Update error location - _errorIndex = src - 1; - - c = (src < _input.Length) ? _input[src++] : '\0'; - - if (!NeedsEscapingInTypeName(c)) - { - // If we got here, a backslash was used to escape a character that is not legal to escape inside a type name. - ParseError(); - return null; - } - } - sb.Append(c); - } - _index = src; - - if (sb.Length == 0) - { - // The identifier has to be non-empty - _errorIndex = src; - ParseError(); - return null; - } - - return sb.ToString(); - } - - // - // Lex the next segment as the assembly name at the end of an assembly-qualified type name. (Do not use for - // assembly names embedded inside generic type arguments.) - // - private string? GetNextAssemblyName() - { - if (!StartAssemblyName()) - return null; - - string assemblyName = _input.Slice(_index).ToString(); - _index = _input.Length; - return assemblyName; - } - - // - // Lex the next segment as an assembly name embedded inside a generic argument type. - // - // Terminated by an unescaped ']'. - // - private string? GetNextEmbeddedAssemblyName() - { - if (!StartAssemblyName()) - return null; - - ValueStringBuilder sb = new ValueStringBuilder(stackalloc char[64]); - - int src = _index; - while (true) - { - if (src >= _input.Length) - { - ParseError(); - return null; - } - char c = _input[src]; - if (c == ']') - break; - src++; - - // Backslash can be used to escape a ']' - any other backslash character is left alone (along with the backslash) - // for the AssemblyName parser to handle. - if (c == '\\' && (src < _input.Length) && _input[src] == ']') - { - c = _input[src++]; - } - sb.Append(c); - } - _index = src; - - if (sb.Length == 0) - { - // The assembly name has to be non-empty - _errorIndex = src; - ParseError(); - return null; - } - - return sb.ToString(); - } - - private bool StartAssemblyName() - { - // Compat: Treat invalid starting token of assembly name as type name parsing error instead of assembly name parsing error. This only affects - // exception returned by the parser. - if (Peek is TokenType.End or TokenType.Comma) - { - ParseError(); - return false; - } - return true; - } - - // - // Classify a character as a TokenType. (Fortunately, all tokens in type name strings other than identifiers are single-character tokens.) - // - private static TokenType CharToToken(char c) - { - return c switch - { - '\0' => TokenType.End, - '[' => TokenType.OpenSqBracket, - ']' => TokenType.CloseSqBracket, - ',' => TokenType.Comma, - '+' => TokenType.Plus, - '*' => TokenType.Asterisk, - '&' => TokenType.Ampersand, - _ => TokenType.Other, - }; - } - - // - // The type name parser has a strange attitude towards whitespace. It throws away whitespace between punctuation tokens and whitespace - // preceding identifiers or assembly names (and this cannot be escaped away). But whitespace between the end of an identifier - // and the punctuation that ends it is *not* ignored. - // - // In other words, GetType(" Foo") searches for "Foo" but GetType("Foo ") searches for "Foo ". - // - // Whitespace between the end of an assembly name and the punction mark that ends it is also not ignored by this parser, - // but this is irrelevant since the assembly name is then turned over to AssemblyName for parsing, which *does* ignore trailing whitespace. - // - private void SkipWhiteSpace() - { - while (_index < _input.Length && char.IsWhiteSpace(_input[_index])) - _index++; - } - - private enum TokenType - { - End = 0, //At end of string - OpenSqBracket = 1, //'[' - CloseSqBracket = 2, //']' - Comma = 3, //',' - Plus = 4, //'+' - Asterisk = 5, //'*' - Ampersand = 6, //'&' - Other = 7, //Type identifier, AssemblyName or embedded AssemblyName. - } - - // - // The TypeName class is the base class for a family of types that represent the nodes in a parse tree for - // assembly-qualified type names. - // - private abstract class TypeName - { - /// - /// Helper for the Type.GetType() family of APIs. "containingAssemblyIsAny" is the assembly to search for (as determined - /// by a qualifying assembly string in the original type string passed to Type.GetType(). If null, it means the type stream - /// didn't specify an assembly name. How to respond to that is up to the type resolver delegate in getTypeOptions - this class - /// is just a middleman. - /// - public abstract Type? ResolveType(ref TypeNameParser parser, string? containingAssemblyIfAny); - } - - // - // Represents a parse of a type name qualified by an assembly name. - // - private sealed class AssemblyQualifiedTypeName : TypeName - { - private readonly string _assemblyName; - private readonly TypeName _nonQualifiedTypeName; - - public AssemblyQualifiedTypeName(TypeName nonQualifiedTypeName, string assemblyName) - { - _nonQualifiedTypeName = nonQualifiedTypeName; - _assemblyName = assemblyName; - } - - public override Type? ResolveType(ref TypeNameParser parser, string? containingAssemblyIfAny) - { - return _nonQualifiedTypeName.ResolveType(ref parser, _assemblyName); - } - } - - // - // Non-nested named type. The full name is the namespace-qualified name. For example, the FullName for - // System.Collections.Generic.IList<> is "System.Collections.Generic.IList`1". - // - private sealed partial class NamespaceTypeName : TypeName - { - private readonly string _fullName; - public NamespaceTypeName(string fullName) - { - _fullName = fullName; - } - - public override Type? ResolveType(ref TypeNameParser parser, string? containingAssemblyIfAny) - { - return parser.GetType(_fullName, default, containingAssemblyIfAny); - } - } - - // - // Nested type name. - // - private sealed partial class NestedNamespaceTypeName : TypeName - { - private readonly string _fullName; - private readonly string[] _nestedNames; - private readonly int _nestedNamesCount; - - public NestedNamespaceTypeName(string fullName, string[] nestedNames, int nestedNamesCount) - { - _fullName = fullName; - _nestedNames = nestedNames; - _nestedNamesCount = nestedNamesCount; - } - - public override Type? ResolveType(ref TypeNameParser parser, string? containingAssemblyIfAny) - { - return parser.GetType(_fullName, _nestedNames.AsSpan(0, _nestedNamesCount), containingAssemblyIfAny); - } - } - - // - // Array, byref or pointer type name. - // - private sealed class ModifierTypeName : TypeName - { - private readonly TypeName _elementTypeName; - - // Positive value is multi-dimensional array rank. - // Negative value is modifier encoded using constants below. - private readonly int _rankOrModifier; - - public const int Array = -1; - public const int Pointer = -2; - public const int ByRef = -3; - - public ModifierTypeName(TypeName elementTypeName, int rankOrModifier) - { - _elementTypeName = elementTypeName; - _rankOrModifier = rankOrModifier; - } - -#if NETCOREAPP - [UnconditionalSuppressMessage("AotAnalysis", "IL3050:AotUnfriendlyApi", - Justification = "Used to implement resolving types from strings.")] -#endif - public override Type? ResolveType(ref TypeNameParser parser, string? containingAssemblyIfAny) - { - Type? elementType = _elementTypeName.ResolveType(ref parser, containingAssemblyIfAny); - if (elementType is null) - return null; - - return _rankOrModifier switch - { - Array => elementType.MakeArrayType(), - Pointer => elementType.MakePointerType(), - ByRef => elementType.MakeByRefType(), - _ => elementType.MakeArrayType(_rankOrModifier) - }; - } - } - - // - // Constructed generic type name. - // - private sealed class GenericTypeName : TypeName - { - private readonly TypeName _typeDefinition; - private readonly TypeName[] _typeArguments; - private readonly int _typeArgumentsCount; - - public GenericTypeName(TypeName genericTypeDefinition, TypeName[] typeArguments, int typeArgumentsCount) - { - _typeDefinition = genericTypeDefinition; - _typeArguments = typeArguments; - _typeArgumentsCount = typeArgumentsCount; - } - -#if NETCOREAPP - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern", - Justification = "Used to implement resolving types from strings.")] - [UnconditionalSuppressMessage("AotAnalysis", "IL3050:AotUnfriendlyApi", - Justification = "Used to implement resolving types from strings.")] -#endif - public override Type? ResolveType(ref TypeNameParser parser, string? containingAssemblyIfAny) - { - Type? typeDefinition = _typeDefinition.ResolveType(ref parser, containingAssemblyIfAny); - if (typeDefinition is null) - return null; - - Type[] arguments = new Type[_typeArgumentsCount]; - for (int i = 0; i < arguments.Length; i++) - { - Type? typeArgument = _typeArguments[i].ResolveType(ref parser, null); - if (typeArgument is null) - return null; - arguments[i] = typeArgument; - } - - return typeDefinition.MakeGenericType(arguments); - } - } - - // - // Type name escaping helpers - // - -#if NETCOREAPP - private static ReadOnlySpan CharsToEscape => "\\[]+*&,"; - - private static bool NeedsEscapingInTypeName(char c) - => CharsToEscape.Contains(c); -#else - private static char[] CharsToEscape { get; } = "\\[]+*&,".ToCharArray(); - - private static bool NeedsEscapingInTypeName(char c) - => Array.IndexOf(CharsToEscape, c) >= 0; -#endif - - private static string EscapeTypeName(string name) - { - if (name.AsSpan().IndexOfAny(CharsToEscape) < 0) - return name; - - var sb = new ValueStringBuilder(stackalloc char[64]); - foreach (char c in name) - { - if (NeedsEscapingInTypeName(c)) - sb.Append('\\'); - sb.Append(c); - } - - return sb.ToString(); - } - - private static string EscapeTypeName(string typeName, ReadOnlySpan nestedTypeNames) - { - string fullName = EscapeTypeName(typeName); - if (nestedTypeNames.Length > 0) - { - var sb = new StringBuilder(fullName); - for (int i = 0; i < nestedTypeNames.Length; i++) - { - sb.Append('+'); - sb.Append(EscapeTypeName(nestedTypeNames[i])); - } - fullName = sb.ToString(); - } - return fullName; - } - - private static (string typeNamespace, string name) SplitFullTypeName(string typeName) - { - string typeNamespace, name; - - // Matches algorithm from ns::FindSep in src\coreclr\utilcode\namespaceutil.cpp - int separator = typeName.LastIndexOf('.'); - if (separator <= 0) - { - typeNamespace = ""; - name = typeName; - } - else - { - if (typeName[separator - 1] == '.') - separator--; - typeNamespace = typeName.Substring(0, separator); - name = typeName.Substring(separator + 1); - } - - return (typeNamespace, name); - } - -#if SYSTEM_PRIVATE_CORELIB - private void ParseError() - { - if (_throwOnError) - throw new ArgumentException(SR.Arg_ArgumentException, $"typeName@{_errorIndex}"); - } -#endif - } -} diff --git a/src/libraries/Common/src/System/Text/ValueStringBuilder.AppendSpanFormattable.cs b/src/libraries/Common/src/System/Text/ValueStringBuilder.AppendSpanFormattable.cs index 04e9fcbdb55240..3e9cf2c56d3ea6 100644 --- a/src/libraries/Common/src/System/Text/ValueStringBuilder.AppendSpanFormattable.cs +++ b/src/libraries/Common/src/System/Text/ValueStringBuilder.AppendSpanFormattable.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. +#nullable enable + namespace System.Text { internal ref partial struct ValueStringBuilder 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 b9f4be64bc9a74..4dd47c701586ca 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 @@ -649,9 +649,7 @@ - - @@ -1473,8 +1471,29 @@ Common\System\IO\PathInternal.CaseSensitivity.cs - - Common\System\Reflection\TypeNameParser.cs + + Common\System\Reflection\TypeNameParser.Helpers + + + Common\System\Reflection\AssemblyNameParser.cs + + + Common\System\Reflection\AssemblyNameFormatter.cs + + + Common\System\Reflection\Metadata\AssemblyNameInfo.cs + + + Common\System\Reflection\Metadata\TypeName.cs + + + Common\System\Reflection\Metadata\TypeNameParser.cs + + + Common\System\Reflection\Metadata\TypeNameParserHelpers.cs + + + Common\System\Reflection\Metadata\TypeNameParserOptions.cs Common\System\Runtime\Versioning\NonVersionableAttribute.cs diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs index 2d82ed0c0e7f50..5ee6c949bc97e5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.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. +#nullable enable + namespace System.Diagnostics.CodeAnalysis { /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs deleted file mode 100644 index dbaaefd4d8c9dd..00000000000000 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs +++ /dev/null @@ -1,438 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.IO; -using System.Runtime.CompilerServices; -using System.Text; - -namespace System.Reflection -{ - // - // Parses an assembly name. - // - internal ref struct AssemblyNameParser - { - public readonly struct AssemblyNameParts - { - public AssemblyNameParts(string name, Version? version, string? cultureName, AssemblyNameFlags flags, byte[]? publicKeyOrToken) - { - _name = name; - _version = version; - _cultureName = cultureName; - _flags = flags; - _publicKeyOrToken = publicKeyOrToken; - } - - public readonly string _name; - public readonly Version? _version; - public readonly string? _cultureName; - public readonly AssemblyNameFlags _flags; - public readonly byte[]? _publicKeyOrToken; - } - - // Token categories for the lexer. - private enum Token - { - Equals = 1, - Comma = 2, - String = 3, - End = 4, - } - - private enum AttributeKind - { - Version = 1, - Culture = 2, - PublicKeyOrToken = 4, - ProcessorArchitecture = 8, - Retargetable = 16, - ContentType = 32 - } - - private readonly ReadOnlySpan _input; - private int _index; - - private AssemblyNameParser(ReadOnlySpan input) - { - if (input.Length == 0) - throw new ArgumentException(SR.Format_StringZeroLength); - - _input = input; - _index = 0; - } - - public static AssemblyNameParts Parse(string name) - { - return new AssemblyNameParser(name).Parse(); - } - - public static AssemblyNameParts Parse(ReadOnlySpan name) - { - return new AssemblyNameParser(name).Parse(); - } - - private void RecordNewSeenOrThrow(scoped ref AttributeKind seenAttributes, AttributeKind newAttribute) - { - if ((seenAttributes & newAttribute) != 0) - { - ThrowInvalidAssemblyName(); - } - seenAttributes |= newAttribute; - } - - private AssemblyNameParts Parse() - { - // Name must come first. - Token token = GetNextToken(out string name); - if (token != Token.String) - ThrowInvalidAssemblyName(); - - if (string.IsNullOrEmpty(name)) - ThrowInvalidAssemblyName(); - - Version? version = null; - string? cultureName = null; - byte[]? pkt = null; - AssemblyNameFlags flags = 0; - - AttributeKind alreadySeen = default; - token = GetNextToken(); - while (token != Token.End) - { - if (token != Token.Comma) - ThrowInvalidAssemblyName(); - - token = GetNextToken(out string attributeName); - if (token != Token.String) - ThrowInvalidAssemblyName(); - - token = GetNextToken(); - if (token != Token.Equals) - ThrowInvalidAssemblyName(); - - token = GetNextToken(out string attributeValue); - if (token != Token.String) - ThrowInvalidAssemblyName(); - - if (attributeName == string.Empty) - ThrowInvalidAssemblyName(); - - if (attributeName.Equals("Version", StringComparison.OrdinalIgnoreCase)) - { - RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.Version); - version = ParseVersion(attributeValue); - } - - if (attributeName.Equals("Culture", StringComparison.OrdinalIgnoreCase)) - { - RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.Culture); - cultureName = ParseCulture(attributeValue); - } - - if (attributeName.Equals("PublicKey", StringComparison.OrdinalIgnoreCase)) - { - RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.PublicKeyOrToken); - pkt = ParsePKT(attributeValue, isToken: false); - flags |= AssemblyNameFlags.PublicKey; - } - - if (attributeName.Equals("PublicKeyToken", StringComparison.OrdinalIgnoreCase)) - { - RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.PublicKeyOrToken); - pkt = ParsePKT(attributeValue, isToken: true); - } - - if (attributeName.Equals("ProcessorArchitecture", StringComparison.OrdinalIgnoreCase)) - { - RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.ProcessorArchitecture); - flags |= (AssemblyNameFlags)(((int)ParseProcessorArchitecture(attributeValue)) << 4); - } - - if (attributeName.Equals("Retargetable", StringComparison.OrdinalIgnoreCase)) - { - RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.Retargetable); - if (attributeValue.Equals("Yes", StringComparison.OrdinalIgnoreCase)) - { - flags |= AssemblyNameFlags.Retargetable; - } - else if (attributeValue.Equals("No", StringComparison.OrdinalIgnoreCase)) - { - // nothing to do - } - else - { - ThrowInvalidAssemblyName(); - } - } - - if (attributeName.Equals("ContentType", StringComparison.OrdinalIgnoreCase)) - { - RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.ContentType); - if (attributeValue.Equals("WindowsRuntime", StringComparison.OrdinalIgnoreCase)) - { - flags |= (AssemblyNameFlags)(((int)AssemblyContentType.WindowsRuntime) << 9); - } - else - { - ThrowInvalidAssemblyName(); - } - } - - // Desktop compat: If we got here, the attribute name is unknown to us. Ignore it. - token = GetNextToken(); - } - - return new AssemblyNameParts(name, version, cultureName, flags, pkt); - } - - private Version ParseVersion(string attributeValue) - { - ReadOnlySpan attributeValueSpan = attributeValue; - Span parts = stackalloc Range[5]; - parts = parts.Slice(0, attributeValueSpan.Split(parts, '.')); - if (parts.Length is < 2 or > 4) - { - ThrowInvalidAssemblyName(); - } - - Span versionNumbers = stackalloc ushort[4]; - for (int i = 0; i < versionNumbers.Length; i++) - { - if ((uint)i >= (uint)parts.Length) - { - versionNumbers[i] = ushort.MaxValue; - break; - } - - if (!ushort.TryParse(attributeValueSpan[parts[i]], NumberStyles.None, NumberFormatInfo.InvariantInfo, out versionNumbers[i])) - { - ThrowInvalidAssemblyName(); - } - } - - if (versionNumbers[0] == ushort.MaxValue || - versionNumbers[1] == ushort.MaxValue) - { - ThrowInvalidAssemblyName(); - } - - return - versionNumbers[2] == ushort.MaxValue ? new Version(versionNumbers[0], versionNumbers[1]) : - versionNumbers[3] == ushort.MaxValue ? new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2]) : - new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2], versionNumbers[3]); - } - - private static string ParseCulture(string attributeValue) - { - if (attributeValue.Equals("Neutral", StringComparison.OrdinalIgnoreCase)) - { - return ""; - } - - return attributeValue; - } - - private byte[] ParsePKT(string attributeValue, bool isToken) - { - if (attributeValue.Equals("null", StringComparison.OrdinalIgnoreCase) || attributeValue == string.Empty) - return Array.Empty(); - - if (isToken && attributeValue.Length != 8 * 2) - ThrowInvalidAssemblyName(); - - byte[] pkt = new byte[attributeValue.Length / 2]; - int srcIndex = 0; - for (int i = 0; i < pkt.Length; i++) - { - char hi = attributeValue[srcIndex++]; - char lo = attributeValue[srcIndex++]; - pkt[i] = (byte)((ParseHexNybble(hi) << 4) | ParseHexNybble(lo)); - } - return pkt; - } - - private ProcessorArchitecture ParseProcessorArchitecture(string attributeValue) - { - if (attributeValue.Equals("msil", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.MSIL; - if (attributeValue.Equals("x86", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.X86; - if (attributeValue.Equals("ia64", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.IA64; - if (attributeValue.Equals("amd64", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.Amd64; - if (attributeValue.Equals("arm", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.Arm; - ThrowInvalidAssemblyName(); - return default; // unreachable - } - - private byte ParseHexNybble(char c) - { - int value = HexConverter.FromChar(c); - if (value == 0xFF) - { - ThrowInvalidAssemblyName(); - } - return (byte)value; - } - - // - // Return the next token in assembly name. If you expect the result to be Token.String, - // use GetNext(out String) instead. - // - private Token GetNextToken() - { - return GetNextToken(out _); - } - - private static bool IsWhiteSpace(char ch) - { - switch (ch) - { - case '\n': - case '\r': - case ' ': - case '\t': - return true; - default: - return false; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private char GetNextChar() - { - char ch; - if (_index < _input.Length) - { - ch = _input[_index++]; - if (ch == '\0') - { - ThrowInvalidAssemblyName(); - } - } - else - { - ch = '\0'; - } - - return ch; - } - - // - // Return the next token in assembly name. If the result is Token.String, - // sets "tokenString" to the tokenized string. - // - private Token GetNextToken(out string tokenString) - { - tokenString = string.Empty; - char c; - - while (true) - { - c = GetNextChar(); - switch (c) - { - case ',': - return Token.Comma; - case '=': - return Token.Equals; - case '\0': - return Token.End; - } - - if (!IsWhiteSpace(c)) - { - break; - } - } - - ValueStringBuilder sb = new ValueStringBuilder(stackalloc char[64]); - - char quoteChar = '\0'; - if (c == '\'' || c == '\"') - { - quoteChar = c; - c = GetNextChar(); - } - - for (; ; ) - { - if (c == 0) - { - if (quoteChar != 0) - { - // EOS and unclosed quotes is an error - ThrowInvalidAssemblyName(); - } - // Reached end of input and therefore of string - break; - } - - if (quoteChar != 0 && c == quoteChar) - break; // Terminate: Found closing quote of quoted string. - - if (quoteChar == 0 && (c == ',' || c == '=')) - { - _index--; - break; // Terminate: Found start of a new ',' or '=' token. - } - - if (quoteChar == 0 && (c == '\'' || c == '\"')) - ThrowInvalidAssemblyName(); - - if (c == '\\') - { - c = GetNextChar(); - - switch (c) - { - case '\\': - case ',': - case '=': - case '\'': - case '"': - sb.Append(c); - break; - case 't': - sb.Append('\t'); - break; - case 'r': - sb.Append('\r'); - break; - case 'n': - sb.Append('\n'); - break; - default: - ThrowInvalidAssemblyName(); - break; //unreachable - } - } - else - { - sb.Append(c); - } - - c = GetNextChar(); - } - - - if (quoteChar == 0) - { - while (sb.Length > 0 && IsWhiteSpace(sb[sb.Length - 1])) - sb.Length--; - } - - tokenString = sb.ToString(); - return Token.String; - } - - [DoesNotReturn] - private void ThrowInvalidAssemblyName() - => throw new FileLoadException(SR.InvalidAssemblyName, _input.ToString()); - } -} diff --git a/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs b/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs index d656738565288c..6eaf4ea70e61ee 100644 --- a/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs +++ b/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs @@ -2408,6 +2408,49 @@ public readonly partial struct TypeLayout public int PackingSize { get { throw null; } } public int Size { get { throw null; } } } + public sealed partial class AssemblyNameInfo + { + public AssemblyNameInfo(string name, System.Version? version = null, string? cultureName = null, System.Reflection.AssemblyNameFlags flags = AssemblyNameFlags.None, + Collections.Immutable.ImmutableArray publicKeyOrToken = default) { } + public string Name { get { throw null; } } + public string? CultureName { get { throw null; } } + public string FullName { get { throw null; } } + public System.Version? Version { get { throw null; } } + public System.Reflection.AssemblyNameFlags Flags { get { throw null; } } + public System.Collections.Immutable.ImmutableArray PublicKeyOrToken { get { throw null; } } + public static System.Reflection.Metadata.AssemblyNameInfo Parse(System.ReadOnlySpan assemblyName) { throw null; } + public static bool TryParse(System.ReadOnlySpan assemblyName, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Reflection.Metadata.AssemblyNameInfo? result) { throw null; } + public System.Reflection.AssemblyName ToAssemblyName() { throw null; } + } + public sealed partial class TypeName + { + internal TypeName() { } + public string AssemblyQualifiedName { get { throw null; } } + public AssemblyNameInfo? AssemblyName { get { throw null; } } + public System.Reflection.Metadata.TypeName? DeclaringType { get { throw null; } } + public string FullName { get { throw null; } } + public bool IsArray { get { throw null; } } + public bool IsByRef { get { throw null; } } + public bool IsConstructedGenericType { get { throw null; } } + public bool IsNested { get { throw null; } } + public bool IsPointer { get { throw null; } } + public bool IsSimple { get { throw null; } } + public bool IsSZArray { get { throw null; } } + public bool IsVariableBoundArrayType { get { throw null; } } + public string Name { get { throw null; } } + public static System.Reflection.Metadata.TypeName Parse(System.ReadOnlySpan typeName, System.Reflection.Metadata.TypeNameParseOptions? options = null) { throw null; } + public static bool TryParse(System.ReadOnlySpan typeName, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Reflection.Metadata.TypeName? result, System.Reflection.Metadata.TypeNameParseOptions? options = null) { throw null; } + public int GetArrayRank() { throw null; } + public System.Collections.Immutable.ImmutableArray GetGenericArguments() { throw null; } + public System.Reflection.Metadata.TypeName GetGenericTypeDefinition() { throw null; } + public System.Reflection.Metadata.TypeName GetElementType() { throw null; } + public int GetNodeCount() { throw null; } + } + public sealed partial class TypeNameParseOptions + { + public TypeNameParseOptions() { } + public int MaxNodes { get { throw null; } set { } } + } public readonly partial struct TypeReference { private readonly object _dummy; diff --git a/src/libraries/System.Reflection.Metadata/src/Resources/Strings.resx b/src/libraries/System.Reflection.Metadata/src/Resources/Strings.resx index c035a3efee098f..963e4d0af9f8a3 100644 --- a/src/libraries/System.Reflection.Metadata/src/Resources/Strings.resx +++ b/src/libraries/System.Reflection.Metadata/src/Resources/Strings.resx @@ -411,4 +411,25 @@ The SwitchInstructionEncoder.Branch method was invoked too many times. + + The name of the type is invalid. + + + Maximum node count of {0} exceeded. + + + Must be an array type. + + + This operation is only valid on generic types. + + + This operation is only valid on nested types. + + + This operation is only valid on arrays, pointers and references. + + + The given assembly name was invalid. + \ No newline at end of file diff --git a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj index e713d6210651f9..266d4c6f55fddd 100644 --- a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj +++ b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj @@ -16,6 +16,7 @@ The System.Reflection.Metadata library is built-in as part of the shared framewo $(DefineConstants);FEATURE_CER + $(DefineConstants);SYSTEM_REFLECTION_METADATA @@ -250,7 +251,17 @@ The System.Reflection.Metadata library is built-in as part of the shared framewo + + + + + + + + + + diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/AssemblyNameInfoTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/AssemblyNameInfoTests.cs new file mode 100644 index 00000000000000..230e051ab045cb --- /dev/null +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/AssemblyNameInfoTests.cs @@ -0,0 +1,105 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace System.Reflection.Metadata.Tests.Metadata +{ + public class AssemblyNameInfoTests + { + [Theory] + [InlineData("MyAssemblyName, Version=1.0.0.0, PublicKeyToken=b77a5c561934e089")] + public void WithPublicTokenKey(string fullName) + { + AssemblyName assemblyName = new AssemblyName(fullName); + + AssemblyNameInfo assemblyNameInfo = AssemblyNameInfo.Parse(fullName.AsSpan()); + + Assert.Equal(fullName, assemblyName.FullName); + Assert.Equal(fullName, assemblyNameInfo.FullName); + + Roundtrip(assemblyName); + } + + [Fact] + public void NoPublicKeyOrToken() + { + AssemblyName source = new AssemblyName(); + source.Name = "test"; + source.Version = new Version(1, 2, 3, 4); + source.CultureName = "en-US"; + + Roundtrip(source); + } + + [Theory] + [InlineData(ProcessorArchitecture.MSIL)] + [InlineData(ProcessorArchitecture.X86)] + [InlineData(ProcessorArchitecture.IA64)] + [InlineData(ProcessorArchitecture.Amd64)] + [InlineData(ProcessorArchitecture.Arm)] + public void ProcessorArchitectureIsPropagated(ProcessorArchitecture architecture) + { + string input = $"Abc, ProcessorArchitecture={architecture}"; + AssemblyNameInfo assemblyNameInfo = AssemblyNameInfo.Parse(input.AsSpan()); + + AssemblyName assemblyName = assemblyNameInfo.ToAssemblyName(); + + Assert.Equal(architecture, assemblyName.ProcessorArchitecture); + Assert.Equal(AssemblyContentType.Default, assemblyName.ContentType); + // By design (desktop compat) AssemblyName.FullName and ToString() do not include ProcessorArchitecture. + Assert.Equal(assemblyName.FullName, assemblyNameInfo.FullName); + Assert.DoesNotContain("ProcessorArchitecture", assemblyNameInfo.FullName); + } + + [Fact] + public void AssemblyContentTypeIsPropagated() + { + const string input = "Abc, ContentType=WindowsRuntime"; + AssemblyNameInfo assemblyNameInfo = AssemblyNameInfo.Parse(input.AsSpan()); + + AssemblyName assemblyName = assemblyNameInfo.ToAssemblyName(); + + Assert.Equal(AssemblyContentType.WindowsRuntime, assemblyName.ContentType); + Assert.Equal(ProcessorArchitecture.None, assemblyName.ProcessorArchitecture); + Assert.Equal(input, assemblyNameInfo.FullName); + Assert.Equal(assemblyName.FullName, assemblyNameInfo.FullName); + } + + [Fact] + public void RetargetableIsPropagated() + { + const string input = "Abc, Retargetable=Yes"; + AssemblyNameInfo assemblyNameInfo = AssemblyNameInfo.Parse(input.AsSpan()); + Assert.True((assemblyNameInfo.Flags & AssemblyNameFlags.Retargetable) != 0); + + AssemblyName assemblyName = assemblyNameInfo.ToAssemblyName(); + + Assert.True((assemblyName.Flags & AssemblyNameFlags.Retargetable) != 0); + Assert.Equal(AssemblyContentType.Default, assemblyName.ContentType); + Assert.Equal(ProcessorArchitecture.None, assemblyName.ProcessorArchitecture); + Assert.Equal(input, assemblyNameInfo.FullName); + Assert.Equal(assemblyName.FullName, assemblyNameInfo.FullName); + } + + [Fact] + public void EscapedSquareBracketIsNotAllowedInTheName() + => Assert.False(AssemblyNameInfo.TryParse("Esc\\[aped".AsSpan(), out _)); + + static void Roundtrip(AssemblyName source) + { + AssemblyNameInfo parsed = AssemblyNameInfo.Parse(source.FullName.AsSpan()); + Assert.Equal(source.Name, parsed.Name); + Assert.Equal(source.Version, parsed.Version); + Assert.Equal(source.CultureName, parsed.CultureName); + Assert.Equal(source.FullName, parsed.FullName); + + AssemblyName fromParsed = parsed.ToAssemblyName(); + Assert.Equal(source.Name, fromParsed.Name); + Assert.Equal(source.Version, fromParsed.Version); + Assert.Equal(source.CultureName, fromParsed.CultureName); + Assert.Equal(source.FullName, fromParsed.FullName); + Assert.Equal(source.GetPublicKeyToken(), fromParsed.GetPublicKeyToken()); + } + } +} diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameParserHelpersTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameParserHelpersTests.cs new file mode 100644 index 00000000000000..b9d23a2be15244 --- /dev/null +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameParserHelpersTests.cs @@ -0,0 +1,173 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text; +using Xunit; + +namespace System.Reflection.Metadata.Tests +{ + public class TypeNameParserHelpersTests + { + [Theory] + [InlineData("A[]", 1, false)] + [InlineData("AB[a,b]", 2, false)] + [InlineData("AB[[a, b],[c,d]]", 2, false)] + [InlineData("12]]", 2, false)] + [InlineData("ABC&", 3, false)] + [InlineData("ABCD*", 4, false)] + [InlineData("ABCDE,otherType]]", 5, false)] + [InlineData("Containing+Nested", 10, true)] + [InlineData("NoSpecial.Characters", 20, false)] + [InlineData("Requires\\+Escaping", 18, false)] + [InlineData("Requires\\[Escaping+Nested", 18, true)] + [InlineData("Worst\\[\\]\\&\\*\\,\\+Case", 21, false)] + [InlineData("EscapingSthThatShouldNotBeEscaped\\A", -1 , false)] + [InlineData("EndsWithEscaping\\", -1, false)] + public void GetFullTypeNameLengthReturnsExpectedValue(string input, int expected, bool expectedIsNested) + { + Assert.Equal(expected, TypeNameParserHelpers.GetFullTypeNameLength(input.AsSpan(), out bool isNested)); + Assert.Equal(expectedIsNested, isNested); + + string withNamespace = $"Namespace1.Namespace2.Namespace3.{input}"; + int expectedWithNamespace = expected < 0 ? expected : expected + withNamespace.Length - input.Length; + Assert.Equal(expectedWithNamespace, TypeNameParserHelpers.GetFullTypeNameLength(withNamespace.AsSpan(), out isNested)); + Assert.Equal(expectedIsNested, isNested); + } + + [Theory] + [InlineData("JustTypeName", "JustTypeName")] + [InlineData("Namespace.TypeName", "TypeName")] + [InlineData("Namespace1.Namespace2.TypeName", "TypeName")] + [InlineData("Namespace.NotNamespace\\.TypeName", "NotNamespace\\.TypeName")] + [InlineData("Namespace1.Namespace2.Containing+Nested", "Nested")] + [InlineData("Namespace1.Namespace2.Not\\+Nested", "Not\\+Nested")] + [InlineData("NotNamespace1\\.NotNamespace2\\.TypeName", "NotNamespace1\\.NotNamespace2\\.TypeName")] + [InlineData("NotNamespace1\\.NotNamespace2\\.Not\\+Nested", "NotNamespace1\\.NotNamespace2\\.Not\\+Nested")] + public void GetNameReturnsJustName(string fullName, string expected) + => Assert.Equal(expected, TypeNameParserHelpers.GetName(fullName.AsSpan()).ToString()); + + [Theory] + [InlineData("simple", "simple")] + [InlineData("simple]", "simple")] + [InlineData("esc\\]aped", "esc\\]aped")] + [InlineData("esc\\]aped]", "esc\\]aped")] + public void GetAssemblyNameCandidateReturnsExpectedValue(string input, string expected) + => Assert.Equal(expected, TypeNameParserHelpers.GetAssemblyNameCandidate(input.AsSpan()).ToString()); + + [Theory] + [InlineData(TypeNameParserHelpers.SZArray, "[]")] + [InlineData(TypeNameParserHelpers.Pointer, "*")] + [InlineData(TypeNameParserHelpers.ByRef, "&")] + [InlineData(1, "[*]")] + [InlineData(2, "[,]")] + [InlineData(3, "[,,]")] + [InlineData(4, "[,,,]")] + public void AppendRankOrModifierStringRepresentationAppendsExpectedString(int input, string expected) + { + ValueStringBuilder builder = new ValueStringBuilder(initialCapacity: 10); + Assert.Equal(expected, TypeNameParserHelpers.GetRankOrModifierStringRepresentation(input, ref builder)); + } + + [Theory] + [InlineData(typeof(List))] + [InlineData(typeof(int?))] + [InlineData(typeof(List))] + [InlineData(typeof(Dictionary))] + [InlineData(typeof(ValueTuple))] + [InlineData(typeof(ValueTuple))] + public void GetGenericTypeFullNameReturnsSameStringAsTypeAPI(Type genericType) + { + TypeName openGenericTypeName = TypeName.Parse(genericType.GetGenericTypeDefinition().FullName.AsSpan()); + ReadOnlySpan genericArgNames = genericType.GetGenericArguments().Select(arg => TypeName.Parse(arg.AssemblyQualifiedName.AsSpan())).ToArray(); + + Assert.Equal(genericType.FullName, TypeNameParserHelpers.GetGenericTypeFullName(openGenericTypeName.FullName.AsSpan(), genericArgNames)); + } + + [Theory] + [InlineData("", false, false, "")] + [InlineData("[", false, false, "[")] // too little to be able to tell + [InlineData("[[", true, true, "")] + [InlineData("[[A],[B]]", true, true, "A],[B]]")] + [InlineData("[ [ A],[B]]", true, true, "A],[B]]")] + [InlineData("[\t[\t \r\nA],[B]]", true, true, "A],[B]]")] // whitespaces other than ' ' + [InlineData("[A,B]", true, false, "A,B]")] + [InlineData("[ A,B]", true, false, "A,B]")] + [InlineData("[]", false, false, "[]")] + [InlineData("[*]", false, false, "[*]")] + [InlineData("[,]", false, false, "[,]")] + [InlineData("[,,]", false, false, "[,,]")] + public void IsBeginningOfGenericAgsHandlesAllCasesProperly(string input, bool expectedResult, bool expectedDoubleBrackets, string expectedConsumedInput) + { + ReadOnlySpan inputSpan = input.AsSpan(); + + Assert.Equal(expectedResult, TypeNameParserHelpers.IsBeginningOfGenericArgs(ref inputSpan, out bool doubleBrackets)); + Assert.Equal(expectedDoubleBrackets, doubleBrackets); + Assert.Equal(expectedConsumedInput, inputSpan.ToString()); + } + + [Theory] + [InlineData("A.B.C", true, null, 5)] + [InlineData("A.B.C\\", false, null, 0)] // invalid type name: ends with escape character + [InlineData("A.B.C\\DoeNotNeedEscaping", false, null, 0)] // invalid type name: escapes non-special character + [InlineData("A.B+C", true, new int[] { 3 }, 5)] + [InlineData("A.B++C", false, null, 0)] // invalid type name: two following, unescaped + + [InlineData("A.B`1", true, null, 5)] + [InlineData("A+B`1+C1`2+DD2`3+E", true, new int[] { 1, 3, 4, 5 }, 18)] + [InlineData("Integer`2147483646+NoOverflow`1", true, new int[] { 18 }, 31)] + [InlineData("Integer`2147483647+Overflow`1", true, new int[] { 18 }, 29)] + public void TryGetTypeNameInfoGetsAllTheInfo(string input, bool expectedResult, int[] expectedNestedNameLengths, int expectedTotalLength) + { + List? nestedNameLengths = null; + ReadOnlySpan span = input.AsSpan(); + bool result = TypeNameParserHelpers.TryGetTypeNameInfo(ref span, ref nestedNameLengths, out int totalLength); + + Assert.Equal(expectedResult, result); + + if (expectedResult) + { + Assert.Equal(expectedNestedNameLengths, nestedNameLengths?.ToArray()); + Assert.Equal(expectedTotalLength, totalLength); + } + } + + [Theory] + [InlineData("*", true, TypeNameParserHelpers.Pointer, "")] + [InlineData(" *", false, default(int), " *")] // Whitespace cannot precede the decorator + [InlineData("* *", true, TypeNameParserHelpers.Pointer, "*")] // but it can follow the decorator. + [InlineData("&", true, TypeNameParserHelpers.ByRef, "")] + [InlineData("\t&", false, default(int), "\t&")] + [InlineData("&\t\r\n[]", true, TypeNameParserHelpers.ByRef, "[]")] + [InlineData("[]", true, TypeNameParserHelpers.SZArray, "")] + [InlineData("\r\n[]", false, default(int), "\r\n[]")] + [InlineData("[] []", true, TypeNameParserHelpers.SZArray, "[]")] + [InlineData("[,]", true, 2, "")] + [InlineData(" [,,,]", false, default(int), " [,,,]")] + [InlineData("[,,,,] *[]", true, 5, "*[]")] + public void TryParseNextDecoratorParsesTheDecoratorAndConsumesFollowingWhitespaces( + string input, bool expectedResult, int expectedModifier, string expectedConsumedInput) + { + ReadOnlySpan inputSpan = input.AsSpan(); + + Assert.Equal(expectedResult, TypeNameParserHelpers.TryParseNextDecorator(ref inputSpan, out int parsedModifier)); + Assert.Equal(expectedModifier, parsedModifier); + Assert.Equal(expectedConsumedInput, inputSpan.ToString()); + } + + [Theory] + [InlineData(" , ", ',', false, " , ")] // it can not start with a whitespace + [InlineData("AB", ',', false, "AB")] // does not start with given character + [InlineData(", ", ',', true, "")] // trimming + [InlineData(",[AB]", ',', true, "[AB]")] // nothing to trim + public void TryStripFirstCharAndTrailingSpacesWorksAsExpected( + string input, char argument, bool expectedResult, string expectedConsumedInput) + { + ReadOnlySpan inputSpan = input.AsSpan(); + + Assert.Equal(expectedResult, TypeNameParserHelpers.TryStripFirstCharAndTrailingSpaces(ref inputSpan, argument)); + Assert.Equal(expectedConsumedInput, inputSpan.ToString()); + } + } +} diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameParserSamples.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameParserSamples.cs new file mode 100644 index 00000000000000..0c48cdc2641d97 --- /dev/null +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameParserSamples.cs @@ -0,0 +1,255 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using Xunit; + +namespace System.Reflection.Metadata.Tests +{ + public class TypeNameParserSamples + { + internal sealed class SampleSerializationBinder : SerializationBinder + { + private static TypeNameParseOptions _options; + + // we could use Frozen collections here ;) + private readonly static Dictionary _alwaysAllowed = new() + { + { typeof(string).FullName, typeof(string) }, + { typeof(int).FullName, typeof(int) }, + { typeof(uint).FullName, typeof(uint) }, + { typeof(long).FullName, typeof(long) }, + { typeof(ulong).FullName, typeof(ulong) }, + { typeof(double).FullName, typeof(double) }, + { typeof(float).FullName, typeof(float) }, + { typeof(bool).FullName, typeof(bool) }, + { typeof(short).FullName, typeof(short) }, + { typeof(ushort).FullName, typeof(ushort) }, + { typeof(byte).FullName, typeof(byte) }, + { typeof(char).FullName, typeof(char) }, + { typeof(DateTime).FullName, typeof(DateTime) }, + { typeof(TimeSpan).FullName, typeof(TimeSpan) }, + { typeof(Guid).FullName, typeof(Guid) }, + { typeof(Uri).FullName, typeof(Uri) }, + { typeof(DateTimeOffset).FullName, typeof(DateTimeOffset) }, + { typeof(Version).FullName, typeof(Version) }, + { typeof(Nullable).FullName, typeof(Nullable) }, // Nullable is generic! + }; + + private readonly Dictionary? _userDefined; + + public SampleSerializationBinder(Type[]? allowedTypes = null) + => _userDefined = allowedTypes?.ToDictionary(type => type.FullName); + + public override Type? BindToType(string assemblyName, string typeName) + { + // Fast path for common primitive type names and user-defined type names + // that use the same syntax and casing as System.Type.FullName API. + if (TryGetTypeFromFullName(typeName, out Type type)) + { + return type; + } + + _options ??= new TypeNameParseOptions() // there is no need for lazy initialization, I just wanted to have everything important in one method + { + // To prevent from unbounded recursion, we set the max depth for parser options. + // By ensuring that the max depth limit is enforced, we can safely use recursion in + // GetTypeFromParsedTypeName to get arrays of arrays and generics of generics. + MaxNodes = 10 + }; + + if (!TypeName.TryParse(typeName.AsSpan(), out TypeName parsed, _options)) + { + // we can throw any exception, log the information etc + throw new InvalidOperationException($"Invalid type name: '{typeName}'"); + } + + if (parsed.AssemblyName is not null) + { + // The attackers may create such a payload, + // where "typeName" passed to BindToType contains the assembly name + // and "assemblyName" passed to this method contains something else + // (some garbage or a different assembly name). Example: + // typeName: System.Int32, MyHackyDll.dll + // assemblyName: mscorlib.dll + throw new InvalidOperationException($"Type name '{typeName}' contained assembly name."); + } + + return GetTypeFromParsedTypeName(parsed); + } + + private Type? GetTypeFromParsedTypeName(TypeName parsed) + { + if (TryGetTypeFromFullName(parsed.FullName, out Type type)) + { + return type; + } + else if (parsed.IsArray) + { + TypeName arrayElementTypeName = parsed.GetElementType(); + Type arrayElementType = GetTypeFromParsedTypeName(arrayElementTypeName); // recursive call allows for creating arrays of arrays etc + + return parsed.IsSZArray + ? arrayElementType.MakeArrayType() + : arrayElementType.MakeArrayType(parsed.GetArrayRank()); + } + else if (parsed.IsConstructedGenericType) + { + TypeName genericTypeDefinitionName = parsed.GetGenericTypeDefinition(); + Type genericTypeDefinition = GetTypeFromParsedTypeName(genericTypeDefinitionName); + Debug.Assert(genericTypeDefinition.IsGenericTypeDefinition); + + ImmutableArray genericArgs = parsed.GetGenericArguments(); + Type[] typeArguments = new Type[genericArgs.Length]; + for (int i = 0; i < genericArgs.Length; i++) + { + typeArguments[i] = GetTypeFromParsedTypeName(genericArgs[i]); // recursive call allows for generics of generics like "List" + } + return genericTypeDefinition.MakeGenericType(typeArguments); + } + + throw new ArgumentException($"{parsed.FullName} is not on the allow list."); + } + + private bool TryGetTypeFromFullName(string fullName, out Type? type) + => _alwaysAllowed.TryGetValue(fullName, out type) + || (_userDefined is not null && _userDefined.TryGetValue(fullName, out type)); + } + + [Serializable] + public class CustomUserDefinedType + { + public int Integer { get; set; } + public string Text { get; set; } + public List ListOfDates { get; set; } + public CustomUserDefinedType[] ArrayOfCustomUserDefinedTypes { get; set; } + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] + public void CanDeserializeCustomUserDefinedType() + { + CustomUserDefinedType parent = new() + { + Integer = 1, + Text = "parent", + ListOfDates = new List() + { + DateTime.Parse("02/06/2024") + }, + ArrayOfCustomUserDefinedTypes = new [] + { + new CustomUserDefinedType() + { + Integer = 2, + Text = "child" + } + } + }; + SampleSerializationBinder binder = new( + allowedTypes: + [ + typeof(CustomUserDefinedType), + typeof(List<>) // using List would require using type forwarding info in dictionary + ]); + + CustomUserDefinedType deserialized = SerializeDeserialize(parent, binder); + + Assert.Equal(parent.Integer, deserialized.Integer); + Assert.Equal(parent.Text, deserialized.Text); + Assert.Equal(parent.ListOfDates.Count, deserialized.ListOfDates.Count); + for (int i = 0; i < deserialized.ListOfDates.Count; i++) + { + Assert.Equal(parent.ListOfDates[i], deserialized.ListOfDates[i]); + } + Assert.Equal(parent.ArrayOfCustomUserDefinedTypes.Length, deserialized.ArrayOfCustomUserDefinedTypes.Length); + for (int i = 0; i < deserialized.ArrayOfCustomUserDefinedTypes.Length; i++) + { + Assert.Equal(parent.ArrayOfCustomUserDefinedTypes[i].Integer, deserialized.ArrayOfCustomUserDefinedTypes[i].Integer); + Assert.Equal(parent.ArrayOfCustomUserDefinedTypes[i].Text, deserialized.ArrayOfCustomUserDefinedTypes[i].Text); + } + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] + public void CanDeserializeDictionaryUsingNonPublicComparerType() + { + Dictionary dictionary = new(StringComparer.CurrentCulture) + { + { "test", 1 } + }; + SampleSerializationBinder binder = new( + allowedTypes: + [ + typeof(Dictionary<,>), // this could be Dictionary to be more strict + StringComparer.CurrentCulture.GetType(), // this type is not public, this is all this test is about + typeof(Globalization.CompareOptions), + typeof(Globalization.CompareInfo), + typeof(KeyValuePair<,>), // this could be KeyValuePair to be more strict + ]); + + Dictionary deserialized = SerializeDeserialize(dictionary, binder); + + Assert.Equal(dictionary, deserialized); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] + public void CanDeserializeArraysOfArrays() + { + int[][] arrayOfArrays = new int[10][]; + for (int i = 0; i < arrayOfArrays.Length; i++) + { + arrayOfArrays[i] = Enumerable.Repeat(i, 10).ToArray(); + } + + SampleSerializationBinder binder = new(); + int[][] deserialized = SerializeDeserialize(arrayOfArrays, binder); + + Assert.Equal(arrayOfArrays.Length, deserialized.Length); + for (int i = 0; i < arrayOfArrays.Length; i++) + { + Assert.Equal(arrayOfArrays[i], deserialized[i]); + } + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] + public void CanDeserializeListOfListOfInt() + { + List> listOfListOfInts = new(10); + for (int i = 0; i < listOfListOfInts.Count; i++) + { + listOfListOfInts[i] = Enumerable.Repeat(i, 10).ToList(); + } + + SampleSerializationBinder binder = new(allowedTypes: + [ + typeof(List<>) + ]); + List> deserialized = SerializeDeserialize(listOfListOfInts, binder); + + Assert.Equal(listOfListOfInts.Count, deserialized.Count); + for (int i = 0; i < listOfListOfInts.Count; i++) + { + Assert.Equal(listOfListOfInts[i], deserialized[i]); + } + } + + static T SerializeDeserialize(T instance, SerializationBinder binder) + { + using MemoryStream bfStream = new(); + BinaryFormatter bf = new() + { + Binder = binder + }; + + bf.Serialize(bfStream, instance); + bfStream.Position = 0; + + return (T)bf.Deserialize(bfStream); + } + } +} diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameTests.cs new file mode 100644 index 00000000000000..53f8e43821bc61 --- /dev/null +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameTests.cs @@ -0,0 +1,748 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Reflection.Emit; +using Xunit; + +namespace System.Reflection.Metadata.Tests +{ + public class TypeNameTests + { + [Theory] + [InlineData(" System.Int32", "System.Int32", "Int32")] + [InlineData(" MyNamespace.MyType+NestedType", "MyNamespace.MyType+NestedType", "NestedType")] + public void SpacesAtTheBeginningAreOK(string input, string expectedFullName, string expectedName) + { + TypeName parsed = TypeName.Parse(input.AsSpan()); + + Assert.Equal(expectedName, parsed.Name); + Assert.Equal(expectedFullName, parsed.FullName); + Assert.Equal(expectedFullName, parsed.AssemblyQualifiedName); + } + + [Fact] + public void LeadingDotIsNotConsumedForFullTypeNamesWithoutNamespace() + { + // This is true only for the public API. + // The internal CoreLib implementation consumes the leading dot for backward compat. + TypeName parsed = TypeName.Parse(".NoNamespace".AsSpan()); + + Assert.Equal("NoNamespace", parsed.Name); + Assert.Equal(".NoNamespace", parsed.FullName); + Assert.Equal(".NoNamespace", parsed.AssemblyQualifiedName); + } + + [Theory] + [InlineData("")] + [InlineData(" ")] + [InlineData(" ")] + public void EmptyStringsAreNotAllowed(string input) + { + Assert.Throws(() => TypeName.Parse(input.AsSpan())); + + Assert.False(TypeName.TryParse(input.AsSpan(), out _)); + } + + [Theory] + [InlineData("Namespace.Containing++Nested")] // a pair of '++' + [InlineData("TypeNameFollowedBySome[] unconsumedCharacters")] + [InlineData("MissingAssemblyName, ")] + [InlineData("ExtraComma, ,")] + [InlineData("ExtraComma, , System.Runtime")] + [InlineData("UsingGenericSyntaxButNotProvidingGenericArgs[[]]")] + [InlineData("ExtraCommaAfterFirstGenericArg`1[[type1, assembly1],]")] + [InlineData("MissingClosingSquareBrackets`1[[type1, assembly1")] // missing ]] + [InlineData("MissingClosingSquareBracket`1[[type1, assembly1]")] // missing ] + [InlineData("MissingClosingSquareBracketsMixedMode`2[[type1, assembly1], type2")] // missing ] + [InlineData("MissingClosingSquareBrackets`2[[type1, assembly1], [type2, assembly2")] // missing ] + [InlineData("MissingClosingSquareBracketsMixedMode`2[type1, [type2, assembly2")] // missing ]] + [InlineData("MissingClosingSquareBracketsMixedMode`2[type1, [type2, assembly2]")] // missing ] + [InlineData("EscapeCharacterAtTheEnd\\")] + [InlineData("EscapeNonSpecialChar\\a")] + [InlineData("EscapeNonSpecialChar\\0")] + [InlineData("DoubleNestingChar++Bla")] + public void InvalidTypeNamesAreNotAllowed(string input) + { + Assert.Throws(() => TypeName.Parse(input.AsSpan())); + + Assert.False(TypeName.TryParse(input.AsSpan(), out _)); + } + + [Theory] + [InlineData("System.Int32&&")] // by-ref to by-ref is currently not supported by CLR + [InlineData("System.Int32[,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,]")] // more than max array rank (32) + public void ParserIsNotEnforcingRuntimeSpecificRules(string input) + { + Assert.True(TypeName.TryParse(input.AsSpan(), out _)); + + if (PlatformDetection.IsNotMonoRuntime) // https://github.com/dotnet/runtime/issues/45033 + { +#if NETCOREAPP + Assert.Throws(() => Type.GetType(input)); +#endif + } + } + + [Theory] + [InlineData("Namespace.Kość", "Namespace.Kość")] + public void UnicodeCharactersAreAllowedByDefault(string input, string expectedFullName) + => Assert.Equal(expectedFullName, TypeName.Parse(input.AsSpan()).FullName); + + [Theory] + [InlineData(typeof(int))] + [InlineData(typeof(Dictionary))] + [InlineData(typeof(int[][]))] + [InlineData(typeof(Assert))] // xUnit assembly + [InlineData(typeof(TypeNameTests))] // test assembly + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1.NestedGeneric_2.NestedNonGeneric_3))] + public void TypeNameCanContainAssemblyName(Type type) + { + AssemblyName expectedAssemblyName = new(type.Assembly.FullName); + + Verify(type, expectedAssemblyName, TypeName.Parse(type.AssemblyQualifiedName.AsSpan())); + + static void Verify(Type type, AssemblyName expectedAssemblyName, TypeName parsed) + { + Assert.Equal(type.AssemblyQualifiedName, parsed.AssemblyQualifiedName); + Assert.Equal(type.FullName, parsed.FullName); + Assert.Equal(type.Name, parsed.Name); + + AssemblyNameInfo parsedAssemblyName = parsed.AssemblyName; + Assert.NotNull(parsedAssemblyName); + + Assert.Equal(expectedAssemblyName.Name, parsedAssemblyName.Name); + Assert.Equal(expectedAssemblyName.Version, parsedAssemblyName.Version); + Assert.Equal(expectedAssemblyName.CultureName, parsedAssemblyName.CultureName); + Assert.Equal(expectedAssemblyName.FullName, parsedAssemblyName.FullName); + + Assert.Equal(default, parsedAssemblyName.Flags); + } + } + + [Theory] + [InlineData(10, "*")] // pointer to pointer + [InlineData(10, "[]")] // array of arrays + [InlineData(100, "*")] + [InlineData(100, "[]")] + public void MaxNodesIsRespected_TooManyDecorators(int maxDepth, string decorator) + { + TypeNameParseOptions options = new() + { + MaxNodes = maxDepth + }; + + string notTooMany = $"System.Int32{string.Join("", Enumerable.Repeat(decorator, maxDepth - 1))}"; + string tooMany = $"System.Int32{string.Join("", Enumerable.Repeat(decorator, maxDepth))}"; + + Assert.Throws(() => TypeName.Parse(tooMany.AsSpan(), options)); + Assert.False(TypeName.TryParse(tooMany.AsSpan(), out _, options)); + + TypeName parsed = TypeName.Parse(notTooMany.AsSpan(), options); + ValidateElementType(maxDepth, parsed, decorator); + + Assert.True(TypeName.TryParse(notTooMany.AsSpan(), out parsed, options)); + ValidateElementType(maxDepth, parsed, decorator); + + static void ValidateElementType(int maxDepth, TypeName parsed, string decorator) + { + for (int i = 0; i < maxDepth - 1; i++) + { + Assert.Equal(decorator == "*", parsed.IsPointer); + Assert.Equal(decorator == "[]", parsed.IsSZArray); + Assert.False(parsed.IsConstructedGenericType); + + parsed = parsed.GetElementType(); + } + } + } + + [Theory] + [InlineData(10)] + [InlineData(100)] + public void MaxNodesIsRespected_TooDeepGenerics(int maxDepth) + { + TypeNameParseOptions options = new() + { + MaxNodes = maxDepth + }; + + string tooDeep = GetName(maxDepth); + string notTooDeep = GetName(maxDepth - 1); + + Assert.Throws(() => TypeName.Parse(tooDeep.AsSpan(), options)); + Assert.False(TypeName.TryParse(tooDeep.AsSpan(), out _, options)); + + TypeName parsed = TypeName.Parse(notTooDeep.AsSpan(), options); + Validate(maxDepth, parsed); + + Assert.True(TypeName.TryParse(notTooDeep.AsSpan(), out parsed, options)); + Validate(maxDepth, parsed); + + static string GetName(int depth) + { + // MakeGenericType is not used here, as it crashes for larger depths + string coreLibName = typeof(object).Assembly.FullName; + string fullName = typeof(int).AssemblyQualifiedName!; + for (int i = 0; i < depth; i++) + { + fullName = $"System.Collections.Generic.List`1[[{fullName}]], {coreLibName}"; + } + return fullName; + } + + static void Validate(int maxDepth, TypeName parsed) + { + for (int i = 0; i < maxDepth - 1; i++) + { + Assert.True(parsed.IsConstructedGenericType); + parsed = parsed.GetGenericArguments()[0]; + } + } + } + + [Theory] + [InlineData(10)] + [InlineData(100)] + public void MaxNodesIsRespected_TooManyGenericArguments(int maxDepth) + { + TypeNameParseOptions options = new() + { + MaxNodes = maxDepth + }; + + string tooMany = GetName(maxDepth); + string notTooMany = GetName(maxDepth - 1); + + Assert.Throws(() => TypeName.Parse(tooMany.AsSpan(), options)); + Assert.False(TypeName.TryParse(tooMany.AsSpan(), out _, options)); + + TypeName parsed = TypeName.Parse(notTooMany.AsSpan(), options); + Validate(parsed, maxDepth); + + Assert.True(TypeName.TryParse(notTooMany.AsSpan(), out parsed, options)); + Validate(parsed, maxDepth); + + static string GetName(int depth) + => $"Some.GenericType`{depth}[{string.Join(",", Enumerable.Repeat("System.Int32", depth))}]"; + + static void Validate(TypeName parsed, int maxDepth) + { + Assert.True(parsed.IsConstructedGenericType); + ImmutableArray genericArgs = parsed.GetGenericArguments(); + Assert.Equal(maxDepth - 1, genericArgs.Length); + Assert.All(genericArgs, arg => Assert.False(arg.IsConstructedGenericType)); + } + } + + public static IEnumerable GenericArgumentsAreSupported_Arguments() + { + yield return new object[] + { + "Generic`1[[A]]", + "Generic`1", + "Generic`1[[A]]", + new string[] { "A" }, + null + }; + yield return new object[] + { + "Generic`1[A]", + "Generic`1", + "Generic`1[[A]]", + new string[] { "A" }, + null + }; + yield return new object[] + { + "Generic`3[[A],[B],[C]]", + "Generic`3", + "Generic`3[[A],[B],[C]]", + new string[] { "A", "B", "C" }, + null + }; + yield return new object[] + { + "Generic`3[A,B,C]", + "Generic`3", + "Generic`3[[A],[B],[C]]", + new string[] { "A", "B", "C" }, + null + }; + yield return new object[] + { + "Generic`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + "Generic`1", + "Generic`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + new string[] { "System.Int32" }, + new AssemblyName[] { new AssemblyName("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") } + }; + yield return new object[] + { + "Generic`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Boolean, mscorlib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + "Generic`2", + "Generic`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Boolean, mscorlib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + new string[] { "System.Int32", "System.Boolean" }, + new AssemblyName[] + { + new AssemblyName("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"), + new AssemblyName("mscorlib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") + } + }; + yield return new object[] + { + "Generic`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089], System.Boolean]", + "Generic`2", + "Generic`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Boolean]]", + new string[] { "System.Int32", "System.Boolean" }, + new AssemblyName[] + { + new AssemblyName("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"), + null + } + }; + yield return new object[] + { + "Generic`2[System.Boolean, [System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + "Generic`2", + "Generic`2[[System.Boolean],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + new string[] { "System.Boolean", "System.Int32" }, + new AssemblyName[] + { + null, + new AssemblyName("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") + } + }; + yield return new object[] + { + "Generic`3[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089], System.Boolean, [System.Byte, other, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + "Generic`3", + "Generic`3[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Boolean],[System.Byte, other, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + new string[] { "System.Int32", "System.Boolean", "System.Byte" }, + new AssemblyName[] + { + new AssemblyName("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"), + null, + new AssemblyName("other, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") + } + }; + yield return new object[] + { + "Generic`3[System.Boolean, [System.Byte, other, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089], System.Int32]", + "Generic`3", + "Generic`3[[System.Boolean],[System.Byte, other, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32]]", + new string[] { "System.Boolean", "System.Byte", "System.Int32" }, + new AssemblyName[] + { + null, + new AssemblyName("other, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"), + null + } + }; + } + + [Theory] + [MemberData(nameof(GenericArgumentsAreSupported_Arguments))] + public void GenericArgumentsAreSupported(string input, string name, string fullName, string[] genericTypesFullNames, AssemblyName[]? assemblyNames) + { + TypeName parsed = TypeName.Parse(input.AsSpan()); + + Assert.Equal(name, parsed.Name); + Assert.Equal(fullName, parsed.FullName); + Assert.True(parsed.IsConstructedGenericType); + Assert.NotNull(parsed.GetGenericTypeDefinition()); + Assert.False(parsed.IsSimple); + + ImmutableArray typeNames = parsed.GetGenericArguments(); + for (int i = 0; i < genericTypesFullNames.Length; i++) + { + TypeName genericArg = typeNames[i]; + Assert.Equal(genericTypesFullNames[i], genericArg.FullName); + Assert.True(genericArg.IsSimple); + Assert.False(genericArg.IsConstructedGenericType); + Assert.Throws(genericArg.GetGenericTypeDefinition); + + if (assemblyNames is not null) + { + if (assemblyNames[i] is null) + { + Assert.Null(genericArg.AssemblyName); + } + else + { + Assert.Equal(assemblyNames[i].FullName, genericArg.AssemblyName.FullName); + Assert.Equal(assemblyNames[i].Name, genericArg.AssemblyName.Name); + } + } + } + } + + public static IEnumerable DecoratorsAreSupported_Arguments() + { + yield return new object[] + { + "TypeName*", "TypeName", false, false, -1, false, true + }; + yield return new object[] + { + "TypeName&", "TypeName", false, false, -1, true, false + }; + yield return new object[] + { + "TypeName[]", "TypeName", true, true, 1, false, false + }; + yield return new object[] + { + "TypeName[*]", "TypeName", true, false, 1, false, false + }; + yield return new object[] + { + "TypeName[,,,]", "TypeName", true, false, 4, false, false + }; + } + + [Theory] + [MemberData(nameof(DecoratorsAreSupported_Arguments))] + public void DecoratorsAreSupported(string input, string typeNameWithoutDecorators, bool isArray, bool isSzArray, int arrayRank, bool isByRef, bool isPointer) + { + TypeName parsed = TypeName.Parse(input.AsSpan()); + + Assert.Equal(input, parsed.FullName); + Assert.Equal(isArray, parsed.IsArray); + Assert.Equal(isSzArray, parsed.IsSZArray); + if (isArray) + { + Assert.Equal(arrayRank, parsed.GetArrayRank()); + } + else + { + Assert.Throws(() => parsed.GetArrayRank()); + } + Assert.Equal(isByRef, parsed.IsByRef); + Assert.Equal(isPointer, parsed.IsPointer); + Assert.False(parsed.IsSimple); + + TypeName elementType = parsed.GetElementType(); + Assert.NotNull(elementType); + Assert.Equal(typeNameWithoutDecorators, elementType.FullName); + Assert.True(elementType.IsSimple); + Assert.False(elementType.IsArray); + Assert.False(elementType.IsSZArray); + Assert.False(elementType.IsByRef); + Assert.False(elementType.IsPointer); + Assert.Throws(elementType.GetElementType); + } + + public static IEnumerable GetAdditionalConstructedTypeData() + { + yield return new object[] { typeof(Dictionary[,], List>[]), 16 }; + + // "Dictionary[,], List>[]" breaks down to complexity 16 like so: + // + // 01: Dictionary[,], List>[] + // 02: `- Dictionary[,], List> + // 03: +- Dictionary`2 + // 04: +- List[,] + // 05: | `- List + // 06: | +- List`1 + // 07: | `- int[] + // 08: | `- int + // 09: `- List + // 10: +- List`1 + // 11: `- int?[][][,] + // 12: `- int?[][] + // 13: `- int?[] + // 14: `- int? + // 15: +- Nullable`1 + // 16: `- int + + yield return new object[] { typeof(int[]).MakePointerType().MakeByRefType(), 4 }; // int[]*& + yield return new object[] { typeof(long).MakeArrayType(31), 2 }; // long[,,,,,,,...] + yield return new object[] { typeof(long).Assembly.GetType("System.Int64[*]"), 2 }; // long[*] + } + + [Theory] + [InlineData(typeof(TypeName), 1)] + [InlineData(typeof(TypeNameTests), 1)] + [InlineData(typeof(object), 1)] + [InlineData(typeof(Assert), 1)] // xunit + [InlineData(typeof(int[]), 2)] + [InlineData(typeof(int[,][]), 3)] + [InlineData(typeof(Nullable<>), 1)] // open generic type treated as elemental + [InlineData(typeof(NestedNonGeneric_0), 2)] // declaring and nested + [InlineData(typeof(NestedGeneric_0), 3)] // declaring, nested and generic arg + [InlineData(typeof(NestedNonGeneric_0.NestedNonGeneric_1), 3)] // declaring, nested 0 and nested 1 + // TypeNameTests+NestedGeneric_0`1+NestedGeneric_1`2[[Int32],[String],[Boolean]] (simplified for brevity) + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1), 6)] // declaring, nested 0 and nested 1 and 3 generic args + [MemberData(nameof(GetAdditionalConstructedTypeData))] + public void GetNodeCountReturnsExpectedValue(Type type, int expected) + { + TypeName parsed = TypeName.Parse(type.AssemblyQualifiedName.AsSpan()); + + Assert.Equal(expected, parsed.GetNodeCount()); + + Assert.Equal(type.Name, parsed.Name); + Assert.Equal(type.FullName, parsed.FullName); + Assert.Equal(type.AssemblyQualifiedName, parsed.AssemblyQualifiedName); + } + + [Fact] + public void IsSimpleReturnsTrueForNestedNonGenericTypes() + { + Assert.True(TypeName.Parse("Containing+Nested".AsSpan()).IsSimple); + Assert.False(TypeName.Parse(typeof(NestedGeneric_0).FullName.AsSpan()).IsSimple); + } + + [Fact] + public void DeclaringTypeThrowsForNonNestedTypes() + { + TypeName nested = TypeName.Parse("Containing+Nested".AsSpan()); + Assert.True(nested.IsNested); + Assert.Equal("Containing", nested.DeclaringType.Name); + + TypeName notNested = TypeName.Parse("NotNested".AsSpan()); + Assert.False(notNested.IsNested); + Assert.Throws(() => notNested.DeclaringType); + } + + [Theory] + [InlineData("SingleDimensionNonZeroIndexed[*]", true)] + [InlineData("SingleDimensionZeroIndexed[]", false)] + [InlineData("MultiDimensional[,,,,,,]", true)] + public void IsVariableBoundArrayTypeReturnsTrueForNonSZArrays(string typeName, bool expected) + { + TypeName parsed = TypeName.Parse(typeName.AsSpan()); + + Assert.True(parsed.IsArray); + Assert.Equal(expected, parsed.IsVariableBoundArrayType); + Assert.NotEqual(expected, parsed.IsSZArray); + Assert.InRange(parsed.GetArrayRank(), 1, 32); + } + + public static IEnumerable GetTypesThatRequireEscaping() + { + if (PlatformDetection.IsReflectionEmitSupported + && !PlatformDetection.IsMonoRuntime) // Mono does not escape Type.Name + { + AssemblyBuilder assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("TypesThatRequireEscaping"), AssemblyBuilderAccess.Run); + ModuleBuilder module = assembly.DefineDynamicModule("TypesThatRequireEscapingModule"); + + yield return new object[] { module.DefineType("TypeNameWith+ThatIsNotNestedType").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith\\TheEscapingCharacter").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith&Ampersand").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith*Asterisk").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith[OpeningSquareBracket").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith]ClosingSquareBracket").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith[]BothSquareBrackets").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith[[]]NestedSquareBrackets").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith,Comma").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith\\[]+*&,AllSpecialCharacters").CreateType() }; + + TypeBuilder containingType = module.DefineType("ContainingTypeWithA+Plus"); + _ = containingType.CreateType(); // containing type must exist! + yield return new object[] { containingType.DefineNestedType("NoSpecialCharacters").CreateType() }; + yield return new object[] { containingType.DefineNestedType("Contains+Plus").CreateType() }; + } + } + + [Theory] + [InlineData(typeof(List))] + [InlineData(typeof(List>))] + [InlineData(typeof(Dictionary))] + [InlineData(typeof(Dictionary>))] + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1))] + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1.NestedGeneric_2))] + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1.NestedGeneric_2.NestedNonGeneric_3))] + [MemberData(nameof(GetTypesThatRequireEscaping))] + public void ParsedNamesMatchSystemTypeNames(Type type) + { + TypeName parsed = TypeName.Parse(type.AssemblyQualifiedName.AsSpan()); + + Assert.Equal(type.Name, parsed.Name); + Assert.Equal(type.FullName, parsed.FullName); + Assert.Equal(type.AssemblyQualifiedName, parsed.AssemblyQualifiedName); + + if (type.IsGenericType) + { + Type genericType = type.GetGenericTypeDefinition(); + TypeName genericTypeName = parsed.GetGenericTypeDefinition(); + Assert.Equal(genericType.Name, genericTypeName.Name); + Assert.Equal(genericType.FullName, genericTypeName.FullName); + Assert.Equal(genericType.AssemblyQualifiedName, genericTypeName.AssemblyQualifiedName); + } + } + + [Theory] + [InlineData("Name`2[[int], [bool]]", "Name`2")] // match + [InlineData("Name`1[[int], [bool]]", "Name`1")] // less than expected + [InlineData("Name`3[[int], [bool]]", "Name`3")] // more than expected + [InlineData("Name[[int], [bool]]", "Name")] // no backtick at all! + public void TheNumberAfterBacktickDoesNotEnforceGenericArgCount(string input, string expectedName) + { + TypeName parsed = TypeName.Parse(input.AsSpan()); + + Assert.True(parsed.IsConstructedGenericType); + Assert.Equal(expectedName, parsed.Name); + Assert.Equal($"{expectedName}[[int],[bool]]", parsed.FullName); + Assert.Equal("int", parsed.GetGenericArguments()[0].Name); + Assert.Equal("bool", parsed.GetGenericArguments()[1].Name); + } + + [Theory] + [InlineData(typeof(int))] + [InlineData(typeof(int?))] + [InlineData(typeof(int[]))] + [InlineData(typeof(int[,]))] + [InlineData(typeof(int[,,,]))] + [InlineData(typeof(List))] + [InlineData(typeof(List>))] + [InlineData(typeof(Dictionary))] + [InlineData(typeof(Dictionary>))] + [InlineData(typeof(NestedNonGeneric_0))] + [InlineData(typeof(NestedNonGeneric_0.NestedNonGeneric_1))] + [InlineData(typeof(NestedGeneric_0))] + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1))] + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1.NestedGeneric_2))] + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1.NestedGeneric_2.NestedNonGeneric_3))] + public void CanImplementGetTypeUsingPublicAPIs_Roundtrip(Type type) + { + Test(type); + Test(type.MakePointerType()); + Test(type.MakePointerType().MakePointerType()); + Test(type.MakeByRefType()); + + if (!type.IsArray) + { + Test(type.MakeArrayType()); // [] + Test(type.MakeArrayType(1)); // [*] + Test(type.MakeArrayType(2)); // [,] + } + + static void Test(Type type) + { + TypeName parsed = TypeName.Parse(type.AssemblyQualifiedName.AsSpan()); + + // ensure that Name, FullName and AssemblyQualifiedName match reflection APIs!! + Assert.Equal(type.Name, parsed.Name); + Assert.Equal(type.FullName, parsed.FullName); + Assert.Equal(type.AssemblyQualifiedName, parsed.AssemblyQualifiedName); + // now load load the type from name + Verify(type, parsed, ignoreCase: false); +#if NETCOREAPP // something weird is going on here + // load using lowercase name + Verify(type, TypeName.Parse(type.AssemblyQualifiedName.ToLower().AsSpan()), ignoreCase: true); + // load using uppercase name + Verify(type, TypeName.Parse(type.AssemblyQualifiedName.ToUpper().AsSpan()), ignoreCase: true); +#endif + + static void Verify(Type type, TypeName typeName, bool ignoreCase) + { + Type afterRoundtrip = GetType(typeName, throwOnError: true, ignoreCase: ignoreCase); + + Assert.NotNull(afterRoundtrip); + Assert.Equal(type, afterRoundtrip); + } + } + +#if NET8_0_OR_GREATER + [RequiresUnreferencedCode("The type might be removed")] + [RequiresDynamicCode("Required by MakeArrayType")] +#else +#pragma warning disable IL2055, IL2057, IL2075, IL2096 +#endif + static Type? GetType(TypeName typeName, bool throwOnError = true, bool ignoreCase = false) + { + if (typeName.IsNested) + { + BindingFlags flagsCopiedFromClr = BindingFlags.NonPublic | BindingFlags.Public; + if (ignoreCase) + { + flagsCopiedFromClr |= BindingFlags.IgnoreCase; + } + return Make(GetType(typeName.DeclaringType, throwOnError, ignoreCase)?.GetNestedType(typeName.Name, flagsCopiedFromClr)); + } + else if (typeName.IsConstructedGenericType) + { + return Make(GetType(typeName.GetGenericTypeDefinition(), throwOnError, ignoreCase)); + } + else if(typeName.IsArray || typeName.IsPointer || typeName.IsByRef) + { + return Make(GetType(typeName.GetElementType(), throwOnError, ignoreCase)); + } + else + { + Assert.True(typeName.IsSimple); + + AssemblyName? assemblyName = typeName.AssemblyName.ToAssemblyName(); + Type? type = assemblyName is null + ? Type.GetType(typeName.FullName, throwOnError, ignoreCase) + : Assembly.Load(assemblyName).GetType(typeName.FullName, throwOnError, ignoreCase); + + return Make(type); + } + + Type? Make(Type? type) + { + if (type is null || typeName.IsSimple) + { + return type; + } + else if (typeName.IsConstructedGenericType) + { + ImmutableArray genericArgs = typeName.GetGenericArguments(); + Type[] genericTypes = new Type[genericArgs.Length]; + for (int i = 0; i < genericArgs.Length; i++) + { + Type? genericArg = GetType(genericArgs[i], throwOnError, ignoreCase); + if (genericArg is null) + { + return null; + } + genericTypes[i] = genericArg; + } + + return type.MakeGenericType(genericTypes); + } + else if (typeName.IsByRef) + { + return type.MakeByRefType(); + } + else if (typeName.IsPointer) + { + return type.MakePointerType(); + } + else if (typeName.IsSZArray) + { + return type.MakeArrayType(); + } + else + { + Assert.True(typeName.IsVariableBoundArrayType); + + return type.MakeArrayType(rank: typeName.GetArrayRank()); + } + } + } +#pragma warning restore IL2055, IL2057, IL2075, IL2096 + } + + public class NestedNonGeneric_0 + { + public class NestedNonGeneric_1 { } + } + + public class NestedGeneric_0 + { + public class NestedGeneric_1 + { + public class NestedGeneric_2 + { + public class NestedNonGeneric_3 { } + } + } + } + } +} diff --git a/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj b/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj index fa48b37d26ab82..f739ac0789ff81 100644 --- a/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj +++ b/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj @@ -25,6 +25,9 @@ Link="Common\Microsoft\Win32\SafeHandles\SafeLibraryHandle.cs" /> + + @@ -36,6 +39,9 @@ + + + diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameParser.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameParser.Mono.cs index 3622b4e27626ac..22a7361d9814e0 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameParser.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameParser.Mono.cs @@ -39,32 +39,31 @@ internal unsafe ref partial struct TypeNameParser return null; } - return new TypeNameParser(typeName) + Metadata.TypeName? parsed = Metadata.TypeNameParser.Parse(typeName, throwOnError: throwOnError); + if (parsed is null) + { + return null; + } + + return new TypeNameParser() { _assemblyResolver = assemblyResolver, _typeResolver = typeResolver, _throwOnError = throwOnError, _ignoreCase = ignoreCase, _stackMark = Unsafe.AsPointer(ref stackMark) - }.Parse(); + }.Resolve(parsed); } - private static bool CheckTopLevelAssemblyQualifiedName() + private Assembly? ResolveAssembly(AssemblyName name) { - return true; - } - - private Assembly? ResolveAssembly(string assemblyName) - { - var name = new AssemblyName(assemblyName); - Assembly? assembly; if (_assemblyResolver is not null) { assembly = _assemblyResolver(name); if (assembly is null && _throwOnError) { - throw new FileNotFoundException(SR.Format(SR.FileNotFound_ResolveAssembly, assemblyName)); + throw new FileNotFoundException(SR.Format(SR.FileNotFound_ResolveAssembly, name.FullName)); } } else @@ -96,13 +95,11 @@ private static bool CheckTopLevelAssemblyQualifiedName() Justification = "TypeNameParser.GetType is marked as RequiresUnreferencedCode.")] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "TypeNameParser.GetType is marked as RequiresUnreferencedCode.")] - private Type? GetType(string typeName, ReadOnlySpan nestedTypeNames, string? assemblyNameIfAny) + private Type? GetType(string escapedTypeName, ReadOnlySpan nestedTypeNames, Metadata.TypeName parsedName) { - Assembly? assembly = (assemblyNameIfAny is not null) ? ResolveAssembly(assemblyNameIfAny) : null; + Assembly? assembly = (parsedName.AssemblyName is not null) ? ResolveAssembly(parsedName.AssemblyName.ToAssemblyName()) : null; // Both the external type resolver and the default type resolvers expect escaped type names - string escapedTypeName = EscapeTypeName(typeName); - Type? type; // Resolve the top level type. @@ -153,7 +150,7 @@ private static bool CheckTopLevelAssemblyQualifiedName() if (_throwOnError) { throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveNestedType, - nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : typeName)); + nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : escapedTypeName)); } return null; } From dd24e9c3ebaf6cda91fc281657878b75428f178c Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Wed, 24 Apr 2024 11:05:14 -0700 Subject: [PATCH 093/248] Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select (#100743) * JIT ARM64-SVE: Add Sve.Abs() and Sve.Add() Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2 * Fix sve scaling in enitIns_R_S/S_R * Revert "Fix sve scaling in enitIns_R_S/S_R" This reverts commit e9fa735738e900bed3c92848aa9ca5ac1f84fbde. * Fix sve scaling in enitIns_R_S/S_R * Restore testing * Use NaturalScale_helper for vector load/stores * wip * Add ConditionalSelect() APIs * Handle ConditionalSelect in JIT * Add test coverage * Update the test cases * jit format * fix merge conflicts * Make predicated/unpredicated work with ConditionalSelect Still some handling around RMW is needed, but this basically works * Misc. changes * jit format * jit format * Handle all the conditions correctly * jit format * fix some spacing * Removed the assert * fix the largest vector size to 64 to fix #100366 * review feedback * wip * Add SVE feature detection for Windows * fix the check for invalid alignment * Revert "Add SVE feature detection for Windows" This reverts commit ed7c781be36f68c95b2acfcaefb88facea954015. * Handle case where Abs() is wrapped in another conditionalSelect * jit format * fix the size comparison * HW_Flag_MaskedPredicatedOnlyOperation * Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask * Fix the condition for lowering * address review feedback for movprfx * Move the special handling of Vector<>.Zero from lowerer to importer * Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation * Add more test coverage for conditionalSelect * Rename test method name * Add more test coverage for conditionalSelect:Abs * jit format * Add logging on test methods * Add the missing movprfx for abs * Add few more scenarios where falseVal is zero * Make sure LoadVector is marked as explicit needing mask * revisit the codegen logic * Remove commented code and add some other comments * jit format --------- Co-authored-by: Alan Hayward --- src/coreclr/jit/codegenlinear.cpp | 2 - src/coreclr/jit/compiler.h | 1 + src/coreclr/jit/emitloongarch64.h | 2 +- src/coreclr/jit/emitriscv64.h | 2 +- src/coreclr/jit/gentree.cpp | 14 +- src/coreclr/jit/gentree.h | 12 +- src/coreclr/jit/hwintrinsic.cpp | 60 ++- src/coreclr/jit/hwintrinsic.h | 29 +- src/coreclr/jit/hwintrinsicarm64.cpp | 20 +- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 123 ++++- src/coreclr/jit/hwintrinsiclistarm64sve.h | 9 +- src/coreclr/jit/liveness.cpp | 4 +- src/coreclr/jit/lowerarmarch.cpp | 67 +++ src/coreclr/jit/lowerxarch.cpp | 4 +- src/coreclr/jit/lsrabuild.cpp | 10 + src/coreclr/jit/ssabuilder.cpp | 14 +- .../Arm/Sve.PlatformNotSupported.cs | 177 +++++++ .../src/System/Runtime/Intrinsics/Arm/Sve.cs | 234 ++++++++++ .../ref/System.Runtime.Intrinsics.cs | 29 +- .../GenerateHWIntrinsicTests_Arm.cs | 63 ++- .../Arm/Shared/SveConditionalSelect.template | 362 +++++++++++++++ .../Arm/Shared/SveLoadMaskedUnOpTest.template | 4 +- .../Shared/_SveBinaryOpTestTemplate.template | 435 ++++++++++++++++++ .../Shared/_SveUnaryOpTestTemplate.template | 391 ++++++++++++++++ 24 files changed, 1994 insertions(+), 74 deletions(-) create mode 100644 src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveConditionalSelect.template create mode 100644 src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveBinaryOpTestTemplate.template create mode 100644 src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveUnaryOpTestTemplate.template diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index 145c074b8fc681..d099fe192fc38a 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -1648,7 +1648,6 @@ void CodeGen::genConsumeRegs(GenTree* tree) // Update the life of the lcl var. genUpdateLife(tree); } -#ifdef TARGET_XARCH #ifdef FEATURE_HW_INTRINSICS else if (tree->OperIs(GT_HWINTRINSIC)) { @@ -1656,7 +1655,6 @@ void CodeGen::genConsumeRegs(GenTree* tree) genConsumeMultiOpOperands(hwintrinsic); } #endif // FEATURE_HW_INTRINSICS -#endif // TARGET_XARCH else if (tree->OperIs(GT_BITCAST, GT_NEG, GT_CAST, GT_LSH, GT_RSH, GT_RSZ, GT_ROR, GT_BSWAP, GT_BSWAP16)) { genConsumeRegs(tree->gtGetOp1()); diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 5b8a04e868836c..7949058066494d 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -3477,6 +3477,7 @@ class Compiler #if defined(TARGET_ARM64) GenTree* gtNewSimdConvertVectorToMaskNode(var_types type, GenTree* node, CorInfoType simdBaseJitType, unsigned simdSize); GenTree* gtNewSimdConvertMaskToVectorNode(GenTreeHWIntrinsic* node, var_types type); + GenTree* gtNewSimdAllTrueMaskNode(CorInfoType simdBaseJitType, unsigned simdSize); #endif //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/emitloongarch64.h b/src/coreclr/jit/emitloongarch64.h index 135f9cf4006735..afaca5b2ba04b8 100644 --- a/src/coreclr/jit/emitloongarch64.h +++ b/src/coreclr/jit/emitloongarch64.h @@ -333,7 +333,7 @@ enum EmitCallType EC_FUNC_TOKEN, // Direct call to a helper/static/nonvirtual/global method // EC_FUNC_TOKEN_INDIR, // Indirect call to a helper/static/nonvirtual/global method - // EC_FUNC_ADDR, // Direct call to an absolute address + // EC_FUNC_ADDR, // Direct call to an absolute address EC_INDIR_R, // Indirect call via register diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 07e603a70afb7c..262f44c9ac4bbd 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -310,7 +310,7 @@ enum EmitCallType EC_FUNC_TOKEN, // Direct call to a helper/static/nonvirtual/global method // EC_FUNC_TOKEN_INDIR, // Indirect call to a helper/static/nonvirtual/global method - // EC_FUNC_ADDR, // Direct call to an absolute address + // EC_FUNC_ADDR, // Direct call to an absolute address // EC_FUNC_VIRTUAL, // Call to a virtual method (using the vtable) EC_INDIR_R, // Indirect call via register diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index c6d6b78c48ca9e..85ce90e94e001d 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -18012,7 +18012,7 @@ bool GenTree::canBeContained() const } else if (OperIsHWIntrinsic() && !isContainableHWIntrinsic()) { - return isEvexEmbeddedMaskingCompatibleHWIntrinsic(); + return isEmbeddedMaskingCompatibleHWIntrinsic(); } return true; @@ -19909,24 +19909,26 @@ bool GenTree::isEvexCompatibleHWIntrinsic() const } //------------------------------------------------------------------------ -// isEvexEmbeddedMaskingCompatibleHWIntrinsic: Checks if the intrinsic is compatible +// isEmbeddedMaskingCompatibleHWIntrinsic : Checks if the intrinsic is compatible // with the EVEX embedded masking form for its intended lowering instruction. // // Return Value: // true if the intrisic node lowering instruction has an EVEX embedded masking // -bool GenTree::isEvexEmbeddedMaskingCompatibleHWIntrinsic() const +bool GenTree::isEmbeddedMaskingCompatibleHWIntrinsic() const { -#if defined(TARGET_XARCH) if (OperIsHWIntrinsic()) { +#if defined(TARGET_XARCH) // TODO-AVX512F-CQ: Expand this to the full set of APIs and make it table driven // using IsEmbMaskingCompatible. For now, however, limit it to some explicit ids // for prototyping purposes. return (AsHWIntrinsic()->GetHWIntrinsicId() == NI_AVX512F_Add); +#elif defined(TARGET_ARM64) + return HWIntrinsicInfo::IsEmbeddedMaskedOperation(AsHWIntrinsic()->GetHWIntrinsicId()) || + HWIntrinsicInfo::IsOptionalEmbeddedMaskedOperation(AsHWIntrinsic()->GetHWIntrinsicId()); +#endif } -#endif // TARGET_XARCH - return false; } diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index c6369121809520..079174f67e939b 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -557,9 +557,9 @@ enum GenTreeFlags : unsigned int GTF_MDARRLOWERBOUND_NONFAULTING = 0x20000000, // GT_MDARR_LOWER_BOUND -- An MD array lower bound operation that cannot fault. Same as GT_IND_NONFAULTING. -#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) +#ifdef FEATURE_HW_INTRINSICS GTF_HW_EM_OP = 0x10000000, // GT_HWINTRINSIC -- node is used as an operand to an embedded mask -#endif // TARGET_XARCH && FEATURE_HW_INTRINSICS +#endif // FEATURE_HW_INTRINSICS }; inline constexpr GenTreeFlags operator ~(GenTreeFlags a) @@ -1465,7 +1465,7 @@ struct GenTree bool isContainableHWIntrinsic() const; bool isRMWHWIntrinsic(Compiler* comp); bool isEvexCompatibleHWIntrinsic() const; - bool isEvexEmbeddedMaskingCompatibleHWIntrinsic() const; + bool isEmbeddedMaskingCompatibleHWIntrinsic() const; #else bool isCommutativeHWIntrinsic() const { @@ -1487,7 +1487,7 @@ struct GenTree return false; } - bool isEvexEmbeddedMaskingCompatibleHWIntrinsic() const + bool isEmbeddedMaskingCompatibleHWIntrinsic() const { return false; } @@ -2226,7 +2226,7 @@ struct GenTree gtFlags &= ~GTF_ICON_HDL_MASK; } -#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) +#ifdef FEATURE_HW_INTRINSICS bool IsEmbMaskOp() { @@ -2240,7 +2240,7 @@ struct GenTree gtFlags |= GTF_HW_EM_OP; } -#endif // TARGET_XARCH && FEATURE_HW_INTRINSICS +#endif // FEATURE_HW_INTRINSICS static bool HandleKindDataIsInvariant(GenTreeFlags flags); diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index 53970ef4a7460b..402cae99b3f631 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -1396,6 +1396,36 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, GenTree* op3 = nullptr; GenTree* op4 = nullptr; + switch (numArgs) + { + case 4: + op4 = getArgForHWIntrinsic(sigReader.GetOp4Type(), sigReader.op4ClsHnd); + op4 = addRangeCheckIfNeeded(intrinsic, op4, mustExpand, immLowerBound, immUpperBound); + op3 = getArgForHWIntrinsic(sigReader.GetOp3Type(), sigReader.op3ClsHnd); + op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd); + op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); + break; + + case 3: + op3 = getArgForHWIntrinsic(sigReader.GetOp3Type(), sigReader.op3ClsHnd); + op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd); + op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); + break; + + case 2: + op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd); + op2 = addRangeCheckIfNeeded(intrinsic, op2, mustExpand, immLowerBound, immUpperBound); + op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); + break; + + case 1: + op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); + break; + + default: + break; + } + switch (numArgs) { case 0: @@ -1407,8 +1437,6 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, case 1: { - op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); - if ((category == HW_Category_MemoryLoad) && op1->OperIs(GT_CAST)) { // Although the API specifies a pointer, if what we have is a BYREF, that's what @@ -1467,10 +1495,6 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, case 2: { - op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd); - op2 = addRangeCheckIfNeeded(intrinsic, op2, mustExpand, immLowerBound, immUpperBound); - op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); - retNode = isScalar ? gtNewScalarHWIntrinsicNode(nodeRetType, op1, op2, intrinsic) : gtNewSimdHWIntrinsicNode(nodeRetType, op1, op2, intrinsic, simdBaseJitType, simdSize); @@ -1524,10 +1548,6 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, case 3: { - op3 = getArgForHWIntrinsic(sigReader.GetOp3Type(), sigReader.op3ClsHnd); - op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd); - op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); - #ifdef TARGET_ARM64 if (intrinsic == NI_AdvSimd_LoadAndInsertScalar) { @@ -1569,12 +1589,6 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, case 4: { - op4 = getArgForHWIntrinsic(sigReader.GetOp4Type(), sigReader.op4ClsHnd); - op4 = addRangeCheckIfNeeded(intrinsic, op4, mustExpand, immLowerBound, immUpperBound); - op3 = getArgForHWIntrinsic(sigReader.GetOp3Type(), sigReader.op3ClsHnd); - op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd); - op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); - assert(!isScalar); retNode = gtNewSimdHWIntrinsicNode(nodeRetType, op1, op2, op3, op4, intrinsic, simdBaseJitType, simdSize); @@ -1591,10 +1605,22 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, } #if defined(TARGET_ARM64) - if (HWIntrinsicInfo::IsMaskedOperation(intrinsic)) + if (HWIntrinsicInfo::IsExplicitMaskedOperation(intrinsic)) { assert(numArgs > 0); GenTree* op1 = retNode->AsHWIntrinsic()->Op(1); + if (intrinsic == NI_Sve_ConditionalSelect) + { + if (op1->IsVectorAllBitsSet()) + { + return retNode->AsHWIntrinsic()->Op(2); + } + else if (op1->IsVectorZero()) + { + return retNode->AsHWIntrinsic()->Op(3); + } + } + if (!varTypeIsMask(op1)) { // Op1 input is a vector. HWInstrinsic requires a mask. diff --git a/src/coreclr/jit/hwintrinsic.h b/src/coreclr/jit/hwintrinsic.h index 5ca302e126f32a..e7bd08d5cb33dc 100644 --- a/src/coreclr/jit/hwintrinsic.h +++ b/src/coreclr/jit/hwintrinsic.h @@ -186,11 +186,18 @@ enum HWIntrinsicFlag : unsigned int HW_Flag_ReturnsPerElementMask = 0x10000, // The intrinsic uses a mask in arg1 to select elements present in the result - HW_Flag_MaskedOperation = 0x20000, + HW_Flag_ExplicitMaskedOperation = 0x20000, // The intrinsic uses a mask in arg1 to select elements present in the result, and must use a low register. HW_Flag_LowMaskedOperation = 0x40000, + // The intrinsic can optionally use a mask in arg1 to select elements present in the result, which is not present in + // the API call + HW_Flag_OptionalEmbeddedMaskedOperation = 0x80000, + + // The intrinsic uses a mask in arg1 to select elements present in the result, which is not present in the API call + HW_Flag_EmbeddedMaskedOperation = 0x100000, + #else #error Unsupported platform #endif @@ -872,7 +879,7 @@ struct HWIntrinsicInfo static bool IsMaskedOperation(NamedIntrinsic id) { const HWIntrinsicFlag flags = lookupFlags(id); - return ((flags & HW_Flag_MaskedOperation) != 0) || IsLowMaskedOperation(id); + return IsLowMaskedOperation(id) || IsOptionalEmbeddedMaskedOperation(id) || IsExplicitMaskedOperation(id); } static bool IsLowMaskedOperation(NamedIntrinsic id) @@ -881,6 +888,24 @@ struct HWIntrinsicInfo return (flags & HW_Flag_LowMaskedOperation) != 0; } + static bool IsOptionalEmbeddedMaskedOperation(NamedIntrinsic id) + { + const HWIntrinsicFlag flags = lookupFlags(id); + return (flags & HW_Flag_OptionalEmbeddedMaskedOperation) != 0; + } + + static bool IsEmbeddedMaskedOperation(NamedIntrinsic id) + { + const HWIntrinsicFlag flags = lookupFlags(id); + return (flags & HW_Flag_EmbeddedMaskedOperation) != 0; + } + + static bool IsExplicitMaskedOperation(NamedIntrinsic id) + { + const HWIntrinsicFlag flags = lookupFlags(id); + return (flags & HW_Flag_ExplicitMaskedOperation) != 0; + } + #endif // TARGET_ARM64 static bool HasSpecialSideEffect(NamedIntrinsic id) diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp index 98342739cb4e0d..07018824458a0b 100644 --- a/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/jit/hwintrinsicarm64.cpp @@ -2222,9 +2222,8 @@ GenTree* Compiler::gtNewSimdConvertVectorToMaskNode(var_types type, assert(varTypeIsSIMD(node)); // ConvertVectorToMask uses cmpne which requires an embedded mask. - GenTree* embeddedMask = gtNewSimdHWIntrinsicNode(TYP_MASK, NI_Sve_CreateTrueMaskAll, simdBaseJitType, simdSize); - return gtNewSimdHWIntrinsicNode(TYP_MASK, embeddedMask, node, NI_Sve_ConvertVectorToMask, simdBaseJitType, - simdSize); + GenTree* trueMask = gtNewSimdAllTrueMaskNode(simdBaseJitType, simdSize); + return gtNewSimdHWIntrinsicNode(TYP_MASK, trueMask, node, NI_Sve_ConvertVectorToMask, simdBaseJitType, simdSize); } //------------------------------------------------------------------------ @@ -2246,4 +2245,19 @@ GenTree* Compiler::gtNewSimdConvertMaskToVectorNode(GenTreeHWIntrinsic* node, va node->GetSimdSize()); } +//------------------------------------------------------------------------ +// gtNewSimdEmbeddedMaskNode: Create an embedded mask +// +// Arguments: +// simdBaseJitType -- the base jit type of the nodes being masked +// simdSize -- the simd size of the nodes being masked +// +// Return Value: +// The mask +// +GenTree* Compiler::gtNewSimdAllTrueMaskNode(CorInfoType simdBaseJitType, unsigned simdSize) +{ + return gtNewSimdHWIntrinsicNode(TYP_MASK, NI_Sve_CreateTrueMaskAll, simdBaseJitType, simdSize); +} + #endif // FEATURE_HW_INTRINSICS diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index 01914951576bfa..0355b4285d486b 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -401,6 +401,100 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) unreached(); } } + else if (intrin.numOperands >= 2 && intrin.op2->IsEmbMaskOp()) + { + // Handle case where op2 is operation that needs embedded mask + GenTree* op2 = intrin.op2; + assert(intrin.id == NI_Sve_ConditionalSelect); + assert(op2->isContained()); + assert(op2->OperIsHWIntrinsic()); + + // Get the registers and intrinsics that needs embedded mask + const HWIntrinsic intrinEmbMask(op2->AsHWIntrinsic()); + instruction insEmbMask = HWIntrinsicInfo::lookupIns(intrinEmbMask.id, intrinEmbMask.baseType); + const bool instrIsRMW = op2->isRMWHWIntrinsic(compiler); + + regNumber maskReg = op1Reg; + regNumber embMaskOp1Reg = REG_NA; + regNumber embMaskOp2Reg = REG_NA; + regNumber falseReg = op3Reg; + + switch (intrinEmbMask.numOperands) + { + case 2: + assert(intrinEmbMask.op2 != nullptr); + embMaskOp2Reg = intrinEmbMask.op2->GetRegNum(); + FALLTHROUGH; + + case 1: + assert(intrinEmbMask.op1 != nullptr); + embMaskOp1Reg = intrinEmbMask.op1->GetRegNum(); + break; + + default: + unreached(); + } + + switch (intrinEmbMask.numOperands) + { + case 1: + assert(!instrIsRMW); + if (targetReg != falseReg) + { + GetEmitter()->emitIns_R_R(INS_sve_movprfx, EA_SCALABLE, targetReg, falseReg); + } + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp1Reg, opt); + break; + + case 2: + + assert(instrIsRMW); + + if (intrin.op3->IsVectorZero()) + { + // If `falseReg` is zero, then move the first operand of `intrinEmbMask` in the + // destination using /Z. + GetEmitter()->emitIns_R_R_R(INS_sve_movprfx, emitSize, targetReg, maskReg, embMaskOp1Reg, opt); + + // Finally, perform the actual "predicated" operation so that `targetReg` is the first operand + // and `embMaskOp2Reg` is the second operand. + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, opt); + } + else if (targetReg != falseReg) + { + // If `targetReg` and `falseReg` are not same, then we need to move it to `targetReg` first + // so the `insEmbMask` operation can be merged on top of it. + + if (falseReg != embMaskOp1Reg) + { + // None of targetReg, embMaskOp1Reg and falseReg are same. In such case, use the + // "unpredicated" version of the instruction and then use "sel" to select the active lanes. + + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, embMaskOp1Reg, embMaskOp2Reg, + opt, INS_SCALABLE_OPTS_UNPREDICATED); + GetEmitter()->emitIns_R_R_R_R(INS_sve_sel, emitSize, targetReg, maskReg, targetReg, + falseReg, opt, INS_SCALABLE_OPTS_UNPREDICATED); + break; + } + else if (targetReg != embMaskOp1Reg) + { + // embMaskOp1Reg is same as `falseReg`, but not same as `targetReg`. Move the + // `embMaskOp1Reg` i.e. `falseReg` in `targetReg`, using "unpredicated movprfx", so the + // subsequent `insEmbMask` operation can be merged on top of it. + GetEmitter()->emitIns_R_R(INS_sve_movprfx, EA_SCALABLE, targetReg, falseReg, opt); + } + + // Finally, perform the actual "predicated" operation so that `targetReg` is the first operand + // and `embMaskOp2Reg` is the second operand. + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, opt); + } + + break; + + default: + unreached(); + } + } else { assert(!hasImmediateOperand); @@ -419,6 +513,14 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) { GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt); } + else if (HWIntrinsicInfo::IsScalable(intrin.id)) + { + assert(!node->IsEmbMaskOp()); + // This generates an unpredicated version + // Predicated should be taken care above `intrin.op2->IsEmbMaskOp()` + GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt, + INS_SCALABLE_OPTS_UNPREDICATED); + } else if (isRMW) { if (targetReg != op1Reg) @@ -437,17 +539,24 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) break; case 3: - assert(isRMW); - if (targetReg != op1Reg) + if (isRMW) { - assert(targetReg != op2Reg); - assert(targetReg != op3Reg); + if (targetReg != op1Reg) + { + assert(targetReg != op2Reg); + assert(targetReg != op3Reg); - GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true); + GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, + /* canSkip */ true); + } + GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op2Reg, op3Reg, opt); + } + else + { + GetEmitter()->emitIns_R_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, op3Reg, opt, + INS_SCALABLE_OPTS_UNPREDICATED); } - GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op2Reg, op3Reg, opt); break; - default: unreached(); } diff --git a/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/coreclr/jit/hwintrinsiclistarm64sve.h index ac110c2a0e1b5b..14b880c8e570e4 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64sve.h +++ b/src/coreclr/jit/hwintrinsiclistarm64sve.h @@ -17,6 +17,9 @@ // SVE Intrinsics // Sve +HARDWARE_INTRINSIC(Sve, Abs, -1, -1, false, {INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_fabs, INS_sve_fabs}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation) +HARDWARE_INTRINSIC(Sve, Add, -1, -1, false, {INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_fadd, INS_sve_fadd}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, ConditionalSelect, -1, 3, true, {INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(Sve, CreateTrueMaskByte, -1, 1, false, {INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) HARDWARE_INTRINSIC(Sve, CreateTrueMaskDouble, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) HARDWARE_INTRINSIC(Sve, CreateTrueMaskInt16, -1, 1, false, {INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) @@ -28,7 +31,7 @@ HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt16, HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt32, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt64, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, LoadVector, -1, 2, true, {INS_sve_ld1b, INS_sve_ld1b, INS_sve_ld1h, INS_sve_ld1h, INS_sve_ld1w, INS_sve_ld1w, INS_sve_ld1d, INS_sve_ld1d, INS_sve_ld1w, INS_sve_ld1d}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVector, -1, 2, true, {INS_sve_ld1b, INS_sve_ld1b, INS_sve_ld1h, INS_sve_ld1h, INS_sve_ld1w, INS_sve_ld1w, INS_sve_ld1d, INS_sve_ld1d, INS_sve_ld1w, INS_sve_ld1d}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) @@ -38,11 +41,11 @@ HARDWARE_INTRINSIC(Sve, LoadVector, // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Special intrinsics that are generated during importing or lowering -HARDWARE_INTRINSIC(Sve, ConvertMaskToVector, -1, 1, true, {INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov}, HW_Category_Helper, HW_Flag_Scalable|HW_Flag_MaskedOperation) +HARDWARE_INTRINSIC(Sve, ConvertMaskToVector, -1, 1, true, {INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov}, HW_Category_Helper, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation) HARDWARE_INTRINSIC(Sve, ConvertVectorToMask, -1, 2, true, {INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne}, HW_Category_Helper, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask|HW_Flag_LowMaskedOperation) - HARDWARE_INTRINSIC(Sve, CreateTrueMaskAll, -1, -1, false, {INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue}, HW_Category_Helper, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask) + #endif // FEATURE_HW_INTRINSIC #undef HARDWARE_INTRINSIC diff --git a/src/coreclr/jit/liveness.cpp b/src/coreclr/jit/liveness.cpp index 521e9891334339..ef3fedf5b31d32 100644 --- a/src/coreclr/jit/liveness.cpp +++ b/src/coreclr/jit/liveness.cpp @@ -1762,8 +1762,8 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR operand->SetUnusedValue(); } - // Special-case PUTARG_STK: since this operator is not considered a value, DCE will not remove - // these nodes. + // Special-case PUTARG_STK: since this operator is not considered a value, DCE will not + // remove these nodes. if (operand->OperIs(GT_PUTARG_STK)) { operand->AsPutArgStk()->gtOp1->SetUnusedValue(); diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index cbdc886ee2802b..7ea9a90d62343e 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -1280,6 +1280,34 @@ GenTree* Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node) break; } + if (HWIntrinsicInfo::IsEmbeddedMaskedOperation(intrinsicId)) + { + LIR::Use use; + if (BlockRange().TryGetUse(node, &use)) + { + GenTree* user = use.User(); + // Wrap the intrinsic in ConditionalSelect only if it is not already inside another ConditionalSelect + if (!user->OperIsHWIntrinsic() || (user->AsHWIntrinsic()->GetHWIntrinsicId() != NI_Sve_ConditionalSelect)) + { + CorInfoType simdBaseJitType = node->GetSimdBaseJitType(); + unsigned simdSize = node->GetSimdSize(); + var_types simdType = Compiler::getSIMDTypeForSize(simdSize); + GenTree* trueMask = comp->gtNewSimdAllTrueMaskNode(simdBaseJitType, simdSize); + GenTree* trueVal = node; + GenTree* falseVal = comp->gtNewZeroConNode(simdType); + + GenTreeHWIntrinsic* condSelNode = + comp->gtNewSimdHWIntrinsicNode(simdType, trueMask, trueVal, falseVal, NI_Sve_ConditionalSelect, + simdBaseJitType, simdSize); + + BlockRange().InsertBefore(node, trueMask); + BlockRange().InsertBefore(node, falseVal); + BlockRange().InsertAfter(node, condSelNode); + use.ReplaceWith(condSelNode); + } + } + } + ContainCheckHWIntrinsic(node); return node->gtNext; } @@ -3275,6 +3303,45 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) } break; + case NI_Sve_ConditionalSelect: + { + assert(intrin.numOperands == 3); + GenTree* op1 = intrin.op1; + GenTree* op2 = intrin.op2; + GenTree* op3 = intrin.op3; + + // Handle op1 + if (op1->IsVectorZero()) + { + // When we are merging with zero, we can specialize + // and avoid instantiating the vector constant. + MakeSrcContained(node, op1); + } + + // Handle op2 + if (op2->OperIsHWIntrinsic()) + { + uint32_t maskSize = genTypeSize(node->GetSimdBaseType()); + uint32_t operSize = genTypeSize(op2->AsHWIntrinsic()->GetSimdBaseType()); + + if ((maskSize == operSize) && IsInvariantInRange(op2, node)) + { + MakeSrcContained(node, op2); + op2->MakeEmbMaskOp(); + } + } + + // Handle op3 + if (op3->IsVectorZero()) + { + // When we are merging with zero, we can specialize + // and avoid instantiating the vector constant. + MakeSrcContained(node, op3); + } + + break; + } + default: unreached(); } diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 5a9b12ca4aa274..0e18c5685066fc 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -2970,7 +2970,7 @@ GenTree* Lowering::LowerHWIntrinsicCndSel(GenTreeHWIntrinsic* node) } //---------------------------------------------------------------------------------------------- -// Lowering::LowerHWIntrinsicCndSel: Lowers an AVX512 TernaryLogic call +// Lowering::LowerHWIntrinsicTernaryLogic: Lowers an AVX512 TernaryLogic call // // Arguments: // node - The hardware intrinsic node. @@ -10137,7 +10137,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) // contained and not a memory operand and know to invoke the special handling // so that the embedded masking can work as expected. - if (op2->isEvexEmbeddedMaskingCompatibleHWIntrinsic()) + if (op2->isEmbeddedMaskingCompatibleHWIntrinsic()) { uint32_t maskSize = genTypeSize(simdBaseType); uint32_t operSize = genTypeSize(op2->AsHWIntrinsic()->GetSimdBaseType()); diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 3ee0f88ee2214f..37fa4320cc6918 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -3489,6 +3489,16 @@ int LinearScan::BuildOperandUses(GenTree* node, regMaskTP candidates) if (numArgs != 1) { +#ifdef TARGET_ARM64 + if (HWIntrinsicInfo::IsScalable(hwintrinsic->GetHWIntrinsicId())) + { + for (size_t argNum = 1; argNum <= numArgs; argNum++) + { + BuildOperandUses(hwintrinsic->Op(argNum), candidates); + } + return (int)numArgs; + } +#endif assert(numArgs == 2); assert(hwintrinsic->Op(2)->isContained()); assert(hwintrinsic->Op(2)->IsCnsIntOrI()); diff --git a/src/coreclr/jit/ssabuilder.cpp b/src/coreclr/jit/ssabuilder.cpp index caba13f3536abc..0a5229e32b8b7c 100644 --- a/src/coreclr/jit/ssabuilder.cpp +++ b/src/coreclr/jit/ssabuilder.cpp @@ -965,8 +965,8 @@ void SsaBuilder::AddPhiArgsToSuccessors(BasicBlock* block) // Walk the statements for phi nodes. for (Statement* const stmt : succ->Statements()) { - // A prefix of the statements of the block are phi definition nodes. If we complete processing - // that prefix, exit. + // A prefix of the statements of the block are phi definition nodes. If we complete + // processing that prefix, exit. if (!stmt->IsPhiDefnStmt()) { break; @@ -988,8 +988,9 @@ void SsaBuilder::AddPhiArgsToSuccessors(BasicBlock* block) { if ((memoryKind == GcHeap) && m_pCompiler->byrefStatesMatchGcHeapStates) { - // We've already propagated the "out" number to the phi shared with ByrefExposed, - // but still need to update bbMemorySsaPhiFunc to be in sync between GcHeap and ByrefExposed. + // We've already propagated the "out" number to the phi shared with + // ByrefExposed, but still need to update bbMemorySsaPhiFunc to be in sync + // between GcHeap and ByrefExposed. assert(memoryKind > ByrefExposed); assert(block->bbMemorySsaNumOut[memoryKind] == block->bbMemorySsaNumOut[ByrefExposed]); assert((succ->bbMemorySsaPhiFunc[ByrefExposed] == succMemoryPhi) || @@ -1009,8 +1010,9 @@ void SsaBuilder::AddPhiArgsToSuccessors(BasicBlock* block) BasicBlock::MemoryPhiArg* curArg = succMemoryPhi; unsigned ssaNum = block->bbMemorySsaNumOut[memoryKind]; bool found = false; - // This is a quadratic algorithm. We might need to consider some switch over to a hash table - // representation for the arguments of a phi node, to make this linear. + // This is a quadratic algorithm. We might need to consider some switch over + // to a hash table representation for the arguments of a phi node, to make this + // linear. while (curArg != nullptr) { if (curArg->m_ssaNum == ssaNum) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs index fbd5ee65ca748f..8d56e32fc863ca 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs @@ -31,6 +31,125 @@ internal Arm64() { } public static new bool IsSupported { [Intrinsic] get { return false; } } } + + /// Abs : Absolute value + + /// + /// svint8_t svabs[_s8]_m(svint8_t inactive, svbool_t pg, svint8_t op) + /// svint8_t svabs[_s8]_x(svbool_t pg, svint8_t op) + /// svint8_t svabs[_s8]_z(svbool_t pg, svint8_t op) + /// + public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svabs[_s16]_m(svint16_t inactive, svbool_t pg, svint16_t op) + /// svint16_t svabs[_s16]_x(svbool_t pg, svint16_t op) + /// svint16_t svabs[_s16]_z(svbool_t pg, svint16_t op) + /// + public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svabs[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// svint32_t svabs[_s32]_x(svbool_t pg, svint32_t op) + /// svint32_t svabs[_s32]_z(svbool_t pg, svint32_t op) + /// + public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svabs[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// svint64_t svabs[_s64]_x(svbool_t pg, svint64_t op) + /// svint64_t svabs[_s64]_z(svbool_t pg, svint64_t op) + /// + public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svabs[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op) + /// svfloat32_t svabs[_f32]_x(svbool_t pg, svfloat32_t op) + /// svfloat32_t svabs[_f32]_z(svbool_t pg, svfloat32_t op) + /// + public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svabs[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op) + /// svfloat64_t svabs[_f64]_x(svbool_t pg, svfloat64_t op) + /// svfloat64_t svabs[_f64]_z(svbool_t pg, svfloat64_t op) + /// + public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); } + + + /// Add : Add + + /// + /// svint8_t svadd[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svadd[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svadd[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svadd[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svadd[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svadd[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svadd[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svadd[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svadd[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svadd[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svadd[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svadd[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint8_t svadd[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svadd[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svadd[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svadd[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svadd[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svadd[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svadd[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svadd[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svadd[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svadd[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svadd[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svadd[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svadd[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svadd[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svadd[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svadd[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svadd[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svadd[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// CreateTrueMaskByte : Set predicate elements to true /// @@ -120,7 +239,65 @@ internal Arm64() { } /// public static unsafe Vector CreateTrueMaskUInt64([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + /// ConditionalSelect : Conditionally select elements + + /// + /// svint8_t svsel[_s8](svbool_t pg, svint8_t op1, svint8_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svsel[_s16](svbool_t pg, svint16_t op1, svint16_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svsel[_s32](svbool_t pg, svint32_t op1, svint32_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// + /// svint64_t svsel[_s64](svbool_t pg, svint64_t op1, svint64_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint8_t svsel[_u8](svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svsel[_u16](svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svsel[_u32](svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svsel[_u64](svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svsel[_f32](svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svsel[_f64](svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// LoadVector : Unextended load diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs index 6ba2a2c67bc8a7..a13957916f49a7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs @@ -29,6 +29,154 @@ internal Arm64() { } } + /// Abs : Absolute value + + /// + /// svint8_t svabs[_s8]_m(svint8_t inactive, svbool_t pg, svint8_t op) + /// ABS Ztied.B, Pg/M, Zop.B + /// MOVPRFX Zresult, Zinactive; ABS Zresult.B, Pg/M, Zop.B + /// svint8_t svabs[_s8]_x(svbool_t pg, svint8_t op) + /// ABS Ztied.B, Pg/M, Ztied.B + /// MOVPRFX Zresult, Zop; ABS Zresult.B, Pg/M, Zop.B + /// svint8_t svabs[_s8]_z(svbool_t pg, svint8_t op) + /// MOVPRFX Zresult.B, Pg/Z, Zop.B; ABS Zresult.B, Pg/M, Zop.B + /// + public static unsafe Vector Abs(Vector value) => Abs(value); + + /// + /// svint16_t svabs[_s16]_m(svint16_t inactive, svbool_t pg, svint16_t op) + /// ABS Ztied.H, Pg/M, Zop.H + /// MOVPRFX Zresult, Zinactive; ABS Zresult.H, Pg/M, Zop.H + /// svint16_t svabs[_s16]_x(svbool_t pg, svint16_t op) + /// ABS Ztied.H, Pg/M, Ztied.H + /// MOVPRFX Zresult, Zop; ABS Zresult.H, Pg/M, Zop.H + /// svint16_t svabs[_s16]_z(svbool_t pg, svint16_t op) + /// MOVPRFX Zresult.H, Pg/Z, Zop.H; ABS Zresult.H, Pg/M, Zop.H + /// + public static unsafe Vector Abs(Vector value) => Abs(value); + + /// + /// svint32_t svabs[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// ABS Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; ABS Zresult.S, Pg/M, Zop.S + /// svint32_t svabs[_s32]_x(svbool_t pg, svint32_t op) + /// ABS Ztied.S, Pg/M, Ztied.S + /// MOVPRFX Zresult, Zop; ABS Zresult.S, Pg/M, Zop.S + /// svint32_t svabs[_s32]_z(svbool_t pg, svint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; ABS Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector Abs(Vector value) => Abs(value); + + /// + /// svint64_t svabs[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// ABS Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; ABS Zresult.D, Pg/M, Zop.D + /// svint64_t svabs[_s64]_x(svbool_t pg, svint64_t op) + /// ABS Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; ABS Zresult.D, Pg/M, Zop.D + /// svint64_t svabs[_s64]_z(svbool_t pg, svint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; ABS Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector Abs(Vector value) => Abs(value); + + /// + /// svfloat32_t svabs[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op) + /// FABS Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; FABS Zresult.S, Pg/M, Zop.S + /// svfloat32_t svabs[_f32]_x(svbool_t pg, svfloat32_t op) + /// FABS Ztied.S, Pg/M, Ztied.S + /// MOVPRFX Zresult, Zop; FABS Zresult.S, Pg/M, Zop.S + /// svfloat32_t svabs[_f32]_z(svbool_t pg, svfloat32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; FABS Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector Abs(Vector value) => Abs(value); + + /// + /// svfloat64_t svabs[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op) + /// FABS Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; FABS Zresult.D, Pg/M, Zop.D + /// svfloat64_t svabs[_f64]_x(svbool_t pg, svfloat64_t op) + /// FABS Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; FABS Zresult.D, Pg/M, Zop.D + /// svfloat64_t svabs[_f64]_z(svbool_t pg, svfloat64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; FABS Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector Abs(Vector value) => Abs(value); + + + /// Add : Add + + /// + /// svint8_t svadd[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svadd[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svadd[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svint16_t svadd[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svadd[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svadd[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svint32_t svadd[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svadd[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svadd[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svint64_t svadd[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svadd[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svadd[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svuint8_t svadd[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svadd[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svadd[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svuint16_t svadd[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svadd[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svadd[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svuint32_t svadd[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svadd[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svadd[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svuint64_t svadd[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svadd[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svadd[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svfloat32_t svadd[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svadd[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svadd[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svfloat64_t svadd[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svadd[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svadd[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// CreateTrueMaskByte : Set predicate elements to true /// @@ -118,7 +266,93 @@ internal Arm64() { } /// public static unsafe Vector CreateTrueMaskUInt64([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskUInt64(pattern); + /// ConditionalSelect : Conditionally select elements + + /// + /// svint8_t svsel[_s8](svbool_t pg, svint8_t op1, svint8_t op2) + /// SEL Zresult.B, Pg, Zop1.B, Zop2.B + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svint16_t svsel[_s16](svbool_t pg, svint16_t op1, svint16_t op2) + /// SEL Zresult.H, Pg, Zop1.H, Zop2.H + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svint32_t svsel[_s32](svbool_t pg, svint32_t op1, svint32_t op2) + /// SEL Zresult.S, Pg, Zop1.S, Zop2.S + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svint64_t svsel[_s64](svbool_t pg, svint64_t op1, svint64_t op2) + /// SEL Zresult.D, Pg, Zop1.D, Zop2.D + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svuint8_t svsel[_u8](svbool_t pg, svuint8_t op1, svuint8_t op2) + /// SEL Zresult.B, Pg, Zop1.B, Zop2.B + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svuint16_t svsel[_u16](svbool_t pg, svuint16_t op1, svuint16_t op2) + /// SEL Zresult.H, Pg, Zop1.H, Zop2.H + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svuint32_t svsel[_u32](svbool_t pg, svuint32_t op1, svuint32_t op2) + /// SEL Zresult.S, Pg, Zop1.S, Zop2.S + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svuint64_t svsel[_u64](svbool_t pg, svuint64_t op1, svuint64_t op2) + /// SEL Zresult.D, Pg, Zop1.D, Zop2.D + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + /// + /// svfloat32_t svsel[_f32](svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// SEL Zresult.S, Pg, Zop1.S, Zop2.S + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svfloat64_t svsel[_f64](svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// SEL Zresult.D, Pg, Zop1.D, Zop2.D + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); /// LoadVector : Unextended load diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index bd7871cdf99065..3980308ca0d20e 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -4171,7 +4171,22 @@ internal Sve() { } internal Arm64() { } public static new bool IsSupported { get { throw null; } } } - + public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector CreateTrueMaskByte([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } public static System.Numerics.Vector CreateTrueMaskDouble([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } public static System.Numerics.Vector CreateTrueMaskInt16([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } @@ -4182,7 +4197,16 @@ internal Arm64() { } public static System.Numerics.Vector CreateTrueMaskUInt16([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } public static System.Numerics.Vector CreateTrueMaskUInt32([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } public static System.Numerics.Vector CreateTrueMaskUInt64([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } - + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, sbyte* address) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, short* address) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, int* address) { throw null; } @@ -4193,7 +4217,6 @@ internal Arm64() { } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, ulong* address) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, float* address) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, double* address) { throw null; } - } public enum SveMaskPattern : byte diff --git a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs index b5f42595ca77e3..a2ebacb1ce8b8c 100644 --- a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs +++ b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs @@ -47,6 +47,16 @@ } }"; +const string SimpleVecOpTest_ValidationLogicForCndSel = @"for (var i = 0; i < RetElementCount; i++) + { + {Op1BaseType} iterResult = (mask[i] != 0) ? {GetIterResult} : falseVal[i]; + if (iterResult != result[i]) + { + succeeded = false; + break; + } + }"; + const string VecPairBinOpTest_ValidationLogic = @" int index = 0; int half = RetElementCount / 2; @@ -107,7 +117,9 @@ ("_TernaryOpTestTemplate.template", "SimpleTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), ("_UnaryOpTestTemplate.template", "SecureHashUnOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), ("_BinaryOpTestTemplate.template", "SecureHashBinOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), - ("_TernaryOpTestTemplate.template", "SecureHashTernOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }) + ("_TernaryOpTestTemplate.template", "SecureHashTernOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), + ("_SveUnaryOpTestTemplate.template", "SveSimpleVecOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic, ["TemplateValidationLogicForCndSel"] = SimpleVecOpTest_ValidationLogicForCndSel }), + ("_SveBinaryOpTestTemplate.template", "SveVecBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic, ["TemplateValidationLogicForCndSel"] = SimpleVecOpTest_ValidationLogicForCndSel }), }; (string templateFileName, Dictionary templateData)[] AdvSimdInputs = new [] @@ -2878,16 +2890,45 @@ (string templateFileName, Dictionary templateData)[] SveInputs = new [] { - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_float", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_double", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_sbyte", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_short", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_int", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_long", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_byte", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_ushort", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_uint", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_ulong", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)-TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "(sbyte)Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)-TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "(short)Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "(int)Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "(long)Helpers.Abs(firstOp[i]) != (long)result[i]", ["GetIterResult"] = "(long)Helpers.Abs(leftOp[i])"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_float", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_double", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_sbyte", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_short", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_int", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_long", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_byte", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_ushort", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_uint", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_ulong", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), }; diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveConditionalSelect.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveConditionalSelect.template new file mode 100644 index 00000000000000..963fa1713eec3b --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveConditionalSelect.template @@ -0,0 +1,362 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using System.Numerics; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new TernaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class TernaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] inArray3; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle inHandle3; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {Op2BaseType}[] inArray2, {Op3BaseType}[] inArray3, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op2BaseType}>(); + int sizeOfinArray3 = inArray3.Length * Unsafe.SizeOf<{Op3BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfinArray3 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException($"Invalid value of alignment: {alignment}, sizeOfinArray1: {sizeOfinArray1}, sizeOfinArray2: {sizeOfinArray2}, sizeOfinArray3: {sizeOfinArray3}, sizeOfoutArray: {sizeOfoutArray}"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.inArray3 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.inHandle3 = GCHandle.Alloc(this.inArray3, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), (uint)sizeOfinArray2); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray3Ptr), ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), (uint)sizeOfinArray3); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray3Ptr => Align((byte*)(inHandle3.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + inHandle3.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op2VectorType}<{Op2BaseType}> _fld2; + public {Op3VectorType}<{Op3BaseType}> _fld3; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3VectorType}<{Op3BaseType}>, byte>(ref testStruct._fld3), ref Unsafe.As<{Op3BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario(TernaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2, _fld3); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int Op2ElementCount = Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>() / sizeof({Op2BaseType}); + private static readonly int Op3ElementCount = Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>() / sizeof({Op3BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + private static {Op3BaseType}[] _data3 = new {Op3BaseType}[Op3ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op2VectorType}<{Op2BaseType}> _fld2; + private {Op3VectorType}<{Op3BaseType}> _fld3; + + private DataTable _dataTable; + + public TernaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3VectorType}<{Op3BaseType}>, byte>(ref _fld3), ref Unsafe.As<{Op3BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + _dataTable = new DataTable(_data1, _data2, _data3, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op3VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + //TODO-SVE: Once register allocation exists for predicates, move loadMask into DataTable + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{RetBaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(loadMask, ({Op2BaseType}*)(_dataTable.inArray2Ptr)), + {LoadIsa}.Load{Op3VectorType}(loadMask, ({Op3BaseType}*)(_dataTable.inArray3Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op2VectorType}<{Op2BaseType}>), typeof({Op3VectorType}<{Op3BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op3VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr); + var op3 = Unsafe.Read<{Op3VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr); + var result = {Isa}.{Method}(op1, op2, op3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2, _fld3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2, test._fld3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, {Op3VectorType}<{Op3BaseType}> op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {Op3BaseType}[] inArray3 = new {Op3BaseType}[Op3ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), op3); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {Op3BaseType}[] inArray3 = new {Op3BaseType}[Op3ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), ref Unsafe.AsRef(op3), (uint)Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {Op2BaseType}[] secondOp, {Op3BaseType}[] thirdOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if ({ValidateIterResult}) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op2VectorType}<{Op2BaseType}>, {Op3VectorType}<{Op3BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveLoadMaskedUnOpTest.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveLoadMaskedUnOpTest.template index 09aaf2f442e136..d5a62e5cda1cf6 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveLoadMaskedUnOpTest.template +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveLoadMaskedUnOpTest.template @@ -64,9 +64,9 @@ namespace JIT.HardwareIntrinsics.Arm { int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op2BaseType}>(); int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); - if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) { - throw new ArgumentException("Invalid value of alignment"); + throw new ArgumentException($"Invalid value of alignment: {alignment}, sizeOfinArray1: {sizeOfinArray1}, sizeOfoutArray: {sizeOfoutArray}"); } this.inArray1 = new byte[alignment * 2]; diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveBinaryOpTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveBinaryOpTestTemplate.template new file mode 100644 index 00000000000000..bd15acab428a09 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveBinaryOpTestTemplate.template @@ -0,0 +1,435 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new {TemplateName}BinaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + // Validates executing the test inside conditional, with op1 as falseValue + test.ConditionalSelect_Op1(); + + // Validates executing the test inside conditional, with op2 as falseValue + test.ConditionalSelect_Op2(); + + // Validates executing the test inside conditional, with op3 as falseValue + test.ConditionalSelect_FalseOp(); + + // Validates executing the test inside conditional, with op3 as zero + test.ConditionalSelect_ZeroOp(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}BinaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {Op2BaseType}[] inArray2, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op2BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException($"Invalid value of alignment: {alignment}, sizeOfinArray1: {sizeOfinArray1}, sizeOfinArray2: {sizeOfinArray2}, sizeOfoutArray: {sizeOfoutArray}"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op2VectorType}<{Op2BaseType}> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}BinaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int Op2ElementCount = Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>() / sizeof({Op2BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _maskData = new {Op1BaseType}[Op1ElementCount]; + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _mask; + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op2VectorType}<{Op2BaseType}> _fld2; + private {Op2VectorType}<{Op2BaseType}> _falseFld; + + private DataTable _dataTable; + + public {TemplateName}BinaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _maskData[i] = ({Op1BaseType})({NextValueOp1} % 2); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _mask), ref Unsafe.As<{Op1BaseType}, byte>(ref _maskData[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref _falseFld), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + _dataTable = new DataTable(_data1, _data2, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{RetBaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(loadMask, ({Op2BaseType}*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op2VectorType}<{Op2BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr); + var result = {Isa}.{Method}(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void ConditionalSelect_Op1() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld1); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld1); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld1); + } + + public void ConditionalSelect_Op2() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op2_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld2); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op2_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld2); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op2_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld2); + } + + public void ConditionalSelect_FalseOp() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _falseFld); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _falseFld); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _falseFld); + } + + public void ConditionalSelect_ZeroOp() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, {Op1VectorType}<{Op1BaseType}>.Zero); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, {Op1VectorType}<{Op1BaseType}>.Zero); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, {Op1VectorType}<{Op1BaseType}>.Zero); + } + + [method: MethodImpl(MethodImplOptions.AggressiveInlining)] + private void ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}> mask, {Op1VectorType}<{Op1BaseType}> op1, {Op1VectorType}<{Op1BaseType}> op2, {Op1VectorType}<{Op1BaseType}> falseOp) + { + var result = Sve.ConditionalSelect(mask, {Isa}.{Method}(op1, op2), falseOp); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateConditionalSelectResult(mask, op1, op2, falseOp, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateConditionalSelectResult({Op1VectorType}<{Op1BaseType}> maskOp, {Op1VectorType}<{Op1BaseType}> leftOp, {Op1VectorType}<{Op1BaseType}> rightOp, {Op1VectorType}<{Op1BaseType}> falseOp, void* output, [CallerMemberName] string method = "") + { + {Op1BaseType}[] mask = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] left = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] right = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] falseVal = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] result = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref mask[0]), maskOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref left[0]), leftOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref right[0]), rightOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref falseVal[0]), falseOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref result[0]), ref Unsafe.AsRef(output), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + bool succeeded = true; + + {TemplateValidationLogicForCndSel} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op2VectorType}<{Op2BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" mask: ({string.Join(", ", mask)})"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" falseOp: ({string.Join(", ", falseVal)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] left, {Op2BaseType}[] right, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op2VectorType}<{Op2BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveUnaryOpTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveUnaryOpTestTemplate.template new file mode 100644 index 00000000000000..557442de4cf0be --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveUnaryOpTestTemplate.template @@ -0,0 +1,391 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new {TemplateName}UnaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + // Validates executing the test inside conditional, with op1 as falseValue + test.ConditionalSelect_Op1(); + + // Validates executing the test inside conditional, with op3 as falseValue + test.ConditionalSelect_FalseOp(); + + // Validates executing the test inside conditional, with op3 as zero + test.ConditionalSelect_ZeroOp(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}UnaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException($"Invalid value of alignment: {alignment}, sizeOfinArray1: {sizeOfinArray1}, sizeOfoutArray: {sizeOfoutArray}"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}UnaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _maskData = new {Op1BaseType}[Op1ElementCount]; + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _mask; + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op1VectorType}<{Op1BaseType}> _falseFld; + + private DataTable _dataTable; + + public {TemplateName}UnaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _maskData[i] = ({Op1BaseType})({NextValueOp1} % 2); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _mask), ref Unsafe.As<{Op1BaseType}, byte>(ref _maskData[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _falseFld), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + _dataTable = new DataTable(_data1, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{RetBaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var result = {Isa}.{Method}(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void ConditionalSelect_Op1() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld1); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld1); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld1); + } + + public void ConditionalSelect_FalseOp() + { + TestLibrary.TestFramework.BeginScenario(nameof(ConditionalSelect_FalseOp)); + ConditionalSelectScenario(_mask, _fld1, _falseFld); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _falseFld); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _falseFld); + } + + public void ConditionalSelect_ZeroOp() + { + TestLibrary.TestFramework.BeginScenario(nameof(ConditionalSelect_ZeroOp)); + ConditionalSelectScenario(_mask, _fld1, {Op1VectorType}<{Op1BaseType}>.Zero); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, {Op1VectorType}<{Op1BaseType}>.Zero); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, {Op1VectorType}<{Op1BaseType}>.Zero); + } + + [method: MethodImpl(MethodImplOptions.AggressiveInlining)] + private void ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}> mask, {Op1VectorType}<{Op1BaseType}> op1, {Op1VectorType}<{Op1BaseType}> falseOp) + { + var result = Sve.ConditionalSelect(mask, {Isa}.{Method}(op1), falseOp); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateConditionalSelectResult(mask, op1, falseOp, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateConditionalSelectResult({Op1VectorType}<{Op1BaseType}> maskOp, {Op1VectorType}<{Op1BaseType}> leftOp, {Op1VectorType}<{Op1BaseType}> falseOp, void* output, [CallerMemberName] string method = "") + { + {Op1BaseType}[] mask = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] left = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] falseVal = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] result = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref mask[0]), maskOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref left[0]), leftOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref falseVal[0]), falseOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref result[0]), ref Unsafe.AsRef(output), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + bool succeeded = true; + + {TemplateValidationLogicForCndSel} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" mask: ({string.Join(", ", mask)})"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" falseOp: ({string.Join(", ", falseVal)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} From 8f1e68aba0bf904a50d581eadbe657fe6fb39986 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 24 Apr 2024 12:02:06 -0700 Subject: [PATCH 094/248] Refresh our "dev-innerloop" pipeline jobs (#101304) --- eng/pipelines/common/platform-matrix.yml | 19 +++++ .../templates/pipeline-with-resources.yml | 3 + eng/pipelines/global-build.yml | 73 ++++--------------- 3 files changed, 37 insertions(+), 58 deletions(-) diff --git a/eng/pipelines/common/platform-matrix.yml b/eng/pipelines/common/platform-matrix.yml index cb3c8b2d0a65e2..2dc00a29da5d35 100644 --- a/eng/pipelines/common/platform-matrix.yml +++ b/eng/pipelines/common/platform-matrix.yml @@ -294,6 +294,25 @@ jobs: helixQueueGroup: ${{ parameters.helixQueueGroup }} ${{ insert }}: ${{ parameters.jobParameters }} +- ${{ if containsValue(parameters.platforms, 'linux_musl_x64_dev_innerloop') }}: + - template: xplat-setup.yml + parameters: + jobTemplate: ${{ parameters.jobTemplate }} + helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }} + variables: ${{ parameters.variables }} + osGroup: linux + osSubgroup: _musl + archType: x64 + targetRid: linux-musl-x64 + platform: linux_musl_x64 + shouldContinueOnError: ${{ parameters.shouldContinueOnError }} + container: linux_musl_x64_dev_innerloop + jobParameters: + runtimeFlavor: ${{ parameters.runtimeFlavor }} + buildConfig: ${{ parameters.buildConfig }} + helixQueueGroup: ${{ parameters.helixQueueGroup }} + ${{ insert }}: ${{ parameters.jobParameters }} + # GCC Linux x64 Build - ${{ if containsValue(parameters.platforms, 'gcc_linux_x64') }}: diff --git a/eng/pipelines/common/templates/pipeline-with-resources.yml b/eng/pipelines/common/templates/pipeline-with-resources.yml index e5e821f60fbc0e..3c9fc538c4845b 100644 --- a/eng/pipelines/common/templates/pipeline-with-resources.yml +++ b/eng/pipelines/common/templates/pipeline-with-resources.yml @@ -68,6 +68,9 @@ extends: linux_x64_dev_innerloop: image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04 + linux_musl_x64_dev_innerloop: + image: mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.19-WithNode + # We use a CentOS Stream 8 image here to test building from source on CentOS Stream 8. SourceBuild_centos_x64: image: mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8 diff --git a/eng/pipelines/global-build.yml b/eng/pipelines/global-build.yml index 2e70a2448cd9d3..d7302fe253b6b9 100644 --- a/eng/pipelines/global-build.yml +++ b/eng/pipelines/global-build.yml @@ -1,6 +1,6 @@ -# The purpose of this pipeline is to exercise local developer workflow in the consolidated -# runtime repo. In particular, it is supposed to run the root "build" script just like any -# normal developer normally would and monitor regressions w.r.t. this fundamental scenario. +# The purpose of this pipeline is to exercise various developer workflows in the repo. +# Primarily, it is meant to cover local (non-cross) build scenarios and +# source-build scenarios that commonly cause build breaks. trigger: none @@ -41,28 +41,6 @@ extends: - stage: Build jobs: - # - # Build with Release config and Debug runtimeConfiguration - # - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: release - platforms: - - windows_x86 - - osx_x64 - - osx_arm64 - jobParameters: - testGroup: innerloop - nameSuffix: Runtime_Debug - buildArgs: -c release -runtimeConfiguration debug - timeoutInMinutes: 120 - condition: - or( - eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), - eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_non_mono_and_wasm.containsChange'], true), - eq(variables['isRollingBuild'], true)) - # # Build with Release config and runtimeConfiguration with MSBuild generator # @@ -83,26 +61,6 @@ extends: eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_non_mono_and_wasm.containsChange'], true), eq(variables['isRollingBuild'], true)) - # - # Build with Debug config and Release runtimeConfiguration - # - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: debug - platforms: - - linux_x64_dev_innerloop - jobParameters: - testGroup: innerloop - nameSuffix: Runtime_Release - buildArgs: -c debug -runtimeConfiguration release - timeoutInMinutes: 120 - condition: - or( - eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), - eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_non_mono_and_wasm.containsChange'], true), - eq(variables['isRollingBuild'], true)) - # # Build with RuntimeFlavor only. This exercise code paths where only RuntimeFlavor is # specified. Catches cases where we depend on Configuration also being specified @@ -124,38 +82,37 @@ extends: eq(variables['isRollingBuild'], true)) # - # Build Mono + Libraries. This exercises the code path where we build libraries without - # first building CoreCLR + # Build Libraries AllConfigurations. This exercises the code path where we build libraries for all + # configurations on a non Windows operating system. # - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/common/global-build-job.yml buildConfig: debug platforms: - - windows_x64 + - linux_x64_dev_innerloop jobParameters: - testGroup: innerloop - nameSuffix: Mono_Libraries - buildArgs: -subset mono+libs /p:RuntimeFlavor=Mono + nameSuffix: Libraries_AllConfigurations + buildArgs: -subset libs -allconfigurations timeoutInMinutes: 120 condition: or( - eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_non_wasm.containsChange'], true), + eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_non_mono_and_wasm.containsChange'], true), eq(variables['isRollingBuild'], true)) # - # Build Libraries AllConfigurations. This exercises the code path where we build libraries for all - # configurations on a non Windows operating system. + # Build native assets on Alpine. This exercises more modern musl libc changes that have a tendendy to break source-build. + # We don't add this as a source-build job as the repo source-build infrastructure isn't set up to run on alpine effectively. # - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: debug + buildConfig: release platforms: - - linux_x64_dev_innerloop + - linux_musl_x64_dev_innerloop jobParameters: - nameSuffix: Libraries_AllConfigurations - buildArgs: -subset libs -allconfigurations + nameSuffix: Musl_Validation + buildArgs: -subset clr.native+libs.native+host.native -c $(_BuildConfig) timeoutInMinutes: 120 condition: or( From ce0ae49e71201a029be97638eb48074359ea76ae Mon Sep 17 00:00:00 2001 From: Koundinya Veluri Date: Wed, 24 Apr 2024 12:27:34 -0700 Subject: [PATCH 095/248] Add managed blocking info for lock and monitor waits (#101192) * Add managed blocking info for lock and monitor waits - Added a managed `ThreadBlockingInfo` struct that is similar to CoreCLR's `DebugBlockingItem` - Updated `Lock`, `Condition`, and `Monitor` to record the info - The `LockOwnerOSThreadId` and `LockOwnerManagedThreadId` properties can be used by debuggers to determine which thread owns a lock that the current thread is waiting on - In CoreCLR, `Monitor` records the info using the `Monitor` object kinds. In NativeAOT, `Lock` and `Condition` are used for `Monitor` waits, so the object kinds would be `Lock/Condition`. For now, Mono's `Monitor` does not record this info. --- .../src/System/Threading/Condition.cs | 4 + .../src/System/Threading/Lock.NativeAot.cs | 6 + src/coreclr/vm/appdomain.cpp | 7 + src/coreclr/vm/corelib.h | 4 + src/coreclr/vm/syncblk.cpp | 17 +- src/coreclr/vm/syncblk.h | 6 + src/coreclr/vm/threaddebugblockinginfo.cpp | 43 +++- src/coreclr/vm/threaddebugblockinginfo.h | 24 ++- .../System.Private.CoreLib.Shared.projitems | 3 +- .../src/System/Threading/Lock.NonNativeAot.cs | 6 + .../src/System/Threading/Lock.cs | 2 + .../System/Threading/ThreadBlockingInfo.cs | 194 ++++++++++++++++++ 12 files changed, 303 insertions(+), 13 deletions(-) create mode 100644 src/libraries/System.Private.CoreLib/src/System/Threading/ThreadBlockingInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs index ba8aba61a0a1b3..2321c5bafe14b7 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs @@ -32,6 +32,8 @@ private static Waiter GetWaiterForCurrentThread() private Waiter? _waitersHead; private Waiter? _waitersTail; + internal Lock AssociatedLock => _lock; + private unsafe void AssertIsInList(Waiter waiter) { Debug.Assert(_waitersHead != null && _waitersTail != null); @@ -106,6 +108,8 @@ public unsafe bool Wait(int millisecondsTimeout, object? associatedObjectForMoni if (!_lock.IsHeldByCurrentThread) throw new SynchronizationLockException(); + using ThreadBlockingInfo.Scope threadBlockingScope = new(this, millisecondsTimeout); + Waiter waiter = GetWaiterForCurrentThread(); AddWaiter(waiter); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs index 8a1c017a508098..9ed8dafac4c1b8 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs @@ -24,6 +24,12 @@ public sealed partial class Lock /// public Lock() => _spinCount = SpinCountNotInitialized; +#pragma warning disable CA1822 // can be marked as static - varies between runtimes + internal ulong OwningOSThreadId => 0; +#pragma warning restore CA1822 + + internal int OwningManagedThreadId => (int)_owningThreadId; + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal bool TryEnterOneShot(int currentManagedThreadId) { diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 59a4783648e2a7..54d395c1d2e353 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1158,6 +1158,13 @@ void SystemDomain::Init() // Finish loading CoreLib now. m_pSystemAssembly->GetDomainAssembly()->EnsureActive(); + + // Set AwareLock's offset of the holding OS thread ID field into ThreadBlockingInfo's static field. That can be used + // when doing managed debugging to get the OS ID of the thread holding the lock. The offset is currently not zero, and + // zero is used in managed code to determine if the static variable has been initialized. + _ASSERTE(AwareLock::GetOffsetOfHoldingOSThreadId() != 0); + CoreLibBinder::GetField(FIELD__THREAD_BLOCKING_INFO__OFFSET_OF_LOCK_OWNER_OS_THREAD_ID) + ->SetStaticValue32(AwareLock::GetOffsetOfHoldingOSThreadId()); } #ifdef _DEBUG diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 65a187d19216f7..d5af8bdb3cb64e 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -583,6 +583,10 @@ END_ILLINK_FEATURE_SWITCH() DEFINE_CLASS(MONITOR, Threading, Monitor) DEFINE_METHOD(MONITOR, ENTER, Enter, SM_Obj_RetVoid) +DEFINE_CLASS(THREAD_BLOCKING_INFO, Threading, ThreadBlockingInfo) +DEFINE_FIELD(THREAD_BLOCKING_INFO, OFFSET_OF_LOCK_OWNER_OS_THREAD_ID, s_monitorObjectOffsetOfLockOwnerOSThreadId) +DEFINE_FIELD(THREAD_BLOCKING_INFO, FIRST, t_first) + DEFINE_CLASS(PARAMETER, Reflection, ParameterInfo) DEFINE_CLASS(PARAMETER_MODIFIER, Reflection, ParameterModifier) diff --git a/src/coreclr/vm/syncblk.cpp b/src/coreclr/vm/syncblk.cpp index 48ede10b35fef0..606137ee8eba75 100644 --- a/src/coreclr/vm/syncblk.cpp +++ b/src/coreclr/vm/syncblk.cpp @@ -2851,15 +2851,9 @@ BOOL SyncBlock::Wait(INT32 timeOut) _ASSERTE ((SyncBlock*)((DWORD_PTR)walk->m_Next->m_WaitSB & ~1)== this); - PendingSync syncState(walk); - - OBJECTREF obj = m_Monitor.GetOwningObject(); - syncState.m_Object = OBJECTREFToObject(obj); - - m_Monitor.IncrementTransientPrecious(); - // While we are in this frame the thread is considered blocked on the - // event of the monitor lock according to the debugger + // event of the monitor lock according to the debugger. DebugBlockingItemHolder + // can trigger a GC, so set it up before accessing the owning object. DebugBlockingItem blockingMonitorInfo; blockingMonitorInfo.dwTimeout = timeOut; blockingMonitorInfo.pMonitor = &m_Monitor; @@ -2867,6 +2861,13 @@ BOOL SyncBlock::Wait(INT32 timeOut) blockingMonitorInfo.type = DebugBlock_MonitorEvent; DebugBlockingItemHolder holder(pCurThread, &blockingMonitorInfo); + PendingSync syncState(walk); + + OBJECTREF obj = m_Monitor.GetOwningObject(); + syncState.m_Object = OBJECTREFToObject(obj); + + m_Monitor.IncrementTransientPrecious(); + GCPROTECT_BEGIN(obj); { GCX_PREEMP(); diff --git a/src/coreclr/vm/syncblk.h b/src/coreclr/vm/syncblk.h index 2ddec753159759..029ee9337d7aab 100644 --- a/src/coreclr/vm/syncblk.h +++ b/src/coreclr/vm/syncblk.h @@ -602,6 +602,12 @@ class AwareLock LIMITED_METHOD_CONTRACT; return m_HoldingThread; } + + static int GetOffsetOfHoldingOSThreadId() + { + LIMITED_METHOD_CONTRACT; + return (int)offsetof(AwareLock, m_HoldingOSThreadId); + } }; #ifdef FEATURE_COMINTEROP diff --git a/src/coreclr/vm/threaddebugblockinginfo.cpp b/src/coreclr/vm/threaddebugblockinginfo.cpp index 8767091566891a..8f4f3831b3518e 100644 --- a/src/coreclr/vm/threaddebugblockinginfo.cpp +++ b/src/coreclr/vm/threaddebugblockinginfo.cpp @@ -72,9 +72,37 @@ VOID ThreadDebugBlockingInfo::VisitBlockingItems(DebugBlockingItemVisitor visito // Holder constructor pushes a blocking item on the blocking info stack #ifndef DACCESS_COMPILE DebugBlockingItemHolder::DebugBlockingItemHolder(Thread *pThread, DebugBlockingItem *pItem) : -m_pThread(pThread) + m_pThread(pThread), m_ppFirstBlockingInfo(nullptr) { - LIMITED_METHOD_CONTRACT; + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; + } + CONTRACTL_END; + + // Try to get the address of the thread-local slot for the managed ThreadBlockingInfo.t_first + EX_TRY + { + FieldDesc *pFD = CoreLibBinder::GetField(FIELD__THREAD_BLOCKING_INFO__FIRST); + m_ppFirstBlockingInfo = (ThreadBlockingInfo **)Thread::GetStaticFieldAddress(pFD); + } + EX_CATCH + { + } + EX_END_CATCH(RethrowTerminalExceptions); + + if (m_ppFirstBlockingInfo != nullptr) + { + // Push info for the managed ThreadBlockingInfo + m_blockingInfo.objectPtr = pItem->pMonitor; + m_blockingInfo.objectKind = (ThreadBlockingInfo::ObjectKind)pItem->type; + m_blockingInfo.timeoutMs = (INT32)pItem->dwTimeout; + m_blockingInfo.next = *m_ppFirstBlockingInfo; + *m_ppFirstBlockingInfo = &m_blockingInfo; + } + pThread->DebugBlockingInfo.PushBlockingItem(pItem); } #endif //DACCESS_COMPILE @@ -84,6 +112,17 @@ m_pThread(pThread) DebugBlockingItemHolder::~DebugBlockingItemHolder() { LIMITED_METHOD_CONTRACT; + m_pThread->DebugBlockingInfo.PopBlockingItem(); + + if (m_ppFirstBlockingInfo != nullptr) + { + // Pop info for the managed ThreadBlockingInfo + _ASSERTE( + m_ppFirstBlockingInfo == + (void *)m_pThread->GetStaticFieldAddrNoCreate(CoreLibBinder::GetField(FIELD__THREAD_BLOCKING_INFO__FIRST))); + _ASSERTE(*m_ppFirstBlockingInfo == &m_blockingInfo); + *m_ppFirstBlockingInfo = m_blockingInfo.next; + } } #endif //DACCESS_COMPILE diff --git a/src/coreclr/vm/threaddebugblockinginfo.h b/src/coreclr/vm/threaddebugblockinginfo.h index 9a2815b3a0c78e..c0d035dd88f01b 100644 --- a/src/coreclr/vm/threaddebugblockinginfo.h +++ b/src/coreclr/vm/threaddebugblockinginfo.h @@ -14,8 +14,8 @@ // Different ways thread can block that the debugger will expose enum DebugBlockingItemType { - DebugBlock_MonitorCriticalSection, - DebugBlock_MonitorEvent, + DebugBlock_MonitorCriticalSection, // maps to ThreadBlockingInfo.ObjectKind.MonitorLock below and in managed code + DebugBlock_MonitorEvent, // maps to ThreadBlockingInfo.ObjectKind.MonitorWait below and in managed code }; typedef DPTR(struct DebugBlockingItem) PTR_DebugBlockingItem; @@ -65,15 +65,35 @@ class ThreadDebugBlockingInfo }; #ifndef DACCESS_COMPILE + +// This is the equivalent of the managed ThreadBlockingInfo (see ThreadBlockingInfo.cs), which is used for tracking blocking +// info from the managed side, similarly to DebugBlockingItem +struct ThreadBlockingInfo +{ + enum class ObjectKind : INT32 + { + MonitorLock, // maps to DebugBlockingItemType::DebugBlock_MonitorCriticalSection + MonitorWait // maps to DebugBlockingItemType::DebugBlock_MonitorEvent + }; + + void *objectPtr; + ObjectKind objectKind; + INT32 timeoutMs; + ThreadBlockingInfo *next; +}; + class DebugBlockingItemHolder { private: Thread *m_pThread; + ThreadBlockingInfo **m_ppFirstBlockingInfo; + ThreadBlockingInfo m_blockingInfo; public: DebugBlockingItemHolder(Thread *pThread, DebugBlockingItem *pItem); ~DebugBlockingItemHolder(); }; + #endif //!DACCESS_COMPILE #endif // __ThreadBlockingInfo__ diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 4dd47c701586ca..fccffa63fa159e 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 @@ -1265,6 +1265,7 @@ + @@ -2786,4 +2787,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.NonNativeAot.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.NonNativeAot.cs index 9386b7ed174601..8a05f1e7fddc70 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.NonNativeAot.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.NonNativeAot.cs @@ -16,6 +16,12 @@ public sealed partial class Lock ///
public Lock() => _spinCount = s_maxSpinCount; + internal ulong OwningOSThreadId => _owningThreadId; + +#pragma warning disable CA1822 // can be marked as static - varies between runtimes + internal int OwningManagedThreadId => 0; +#pragma warning restore CA1822 + private static TryLockResult LazyInitializeOrEnter() => TryLockResult.Spin; private static bool IsSingleProcessor => Environment.IsSingleProcessor; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs index b7961869eac5d2..8658ab6caafb11 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs @@ -477,6 +477,8 @@ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) waitStartTimeTicks = Stopwatch.GetTimestamp(); } + using ThreadBlockingInfo.Scope threadBlockingScope = new(this, timeoutMs); + bool acquiredLock = false; int waitStartTimeMs = timeoutMs < 0 ? 0 : Environment.TickCount; int remainingTimeoutMs = timeoutMs; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadBlockingInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadBlockingInfo.cs new file mode 100644 index 00000000000000..6deed17e8f5dc5 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadBlockingInfo.cs @@ -0,0 +1,194 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace System.Threading +{ + // Tracks some kinds of blocking on the thread, like waiting on locks where it may be useful to know when debugging which + // thread owns the lock. + // + // Notes: + // - The type, some fields, and some other members may be used by debuggers (noted specifically below), so take care when + // renaming them + // - There is a native version of this struct in CoreCLR, used by Monitor to fold in its blocking info here. The struct is + // blittable with sequential layout to support that. + // + // Debuggers may use this info by evaluating expressions to enumerate the blocking infos for a thread. For example: + // - Evaluate "System.Threading.ThreadBlockingInfo.t_first" to obtain the first pointer to a blocking info for the current + // thread + // - While there is a non-null pointer to a blocking info: + // - Evaluate "(*(System.Threading.ThreadBlockingInfo*)ptr).fieldOrProperty", where "ptr" is the blocking info pointer + // value, to get the field and relevant property getter values below + // - Use the _objectKind field value to determine what kind of blocking is occurring + // - Get the LockOwnerOSThreadId and LockOwnerManagedThreadId property getter values. If the blocking is waiting for a + // lock and the lock is currently owned by a thread, one of these properties will return a nonzero value that can be + // used to identify the lock owner thread. + // - Use the _next field value to obtain the next pointer to a blocking info for the thread + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct ThreadBlockingInfo + { +#if CORECLR + // In CoreCLR, for the Monitor object kinds, the object ptr will be a pointer to a native AwareLock object. This + // relative offset indicates the location of the field holding the lock owner OS thread ID (the field is of type + // size_t), and is used to get that info by the LockOwnerOSThreadId property. The offset is not zero currently, so zero + // is used to determine if the static field has been initialized. + // + // This mechanism is used instead of using an FCall in the property getter such that the property can be more easily + // evaluated by a debugger. + private static int s_monitorObjectOffsetOfLockOwnerOSThreadId; +#endif + + // Points to the first (most recent) blocking info for the thread. The _next field points to the next-most-recent + // blocking info for the thread, or null if there are no more. Blocking can be reentrant in some cases, such as on UI + // threads where reentrant waits are used, or if a SynchronizationContext wait override is set. + [ThreadStatic] + private static ThreadBlockingInfo* t_first; // may be used by debuggers + + // This pointer can be used to obtain the object relevant to the blocking. For native object kinds, it points to the + // native object (for Monitor object kinds in CoreCLR, it points to a native AwareLock object). For managed object + // kinds, it points to a stack location containing the managed object reference. + private void* _objectPtr; // may be used by debuggers + + // Indicates the type of object relevant to the blocking + private ObjectKind _objectKind; // may be used by debuggers + + // The timeout in milliseconds for the wait, -1 for infinite timeout + private int _timeoutMs; // may be used by debuggers + + // Points to the next-most-recent blocking info for the thread + private ThreadBlockingInfo* _next; // may be used by debuggers + + private void Push(void* objectPtr, ObjectKind objectKind, int timeoutMs) + { + Debug.Assert(objectPtr != null); + + _objectPtr = objectPtr; + _objectKind = objectKind; + _timeoutMs = timeoutMs; + _next = t_first; + t_first = (ThreadBlockingInfo*)Unsafe.AsPointer(ref this); + } + + private void Pop() + { + Debug.Assert(_objectPtr != null); + Debug.Assert(t_first != null); + Debug.Assert(t_first->_next == _next); + + t_first = _next; + _objectPtr = null; + } + + // If the blocking is associated with a lock of some kind that has thread affinity and tracks the owner's OS thread ID, + // returns the OS thread ID of the thread that currently owns the lock. Otherwise, returns 0. A return value of 0 may + // indicate that the associated lock is currently not owned by a thread, or that the information could not be + // determined. + // + // Calls to native helpers are avoided in the property getter such that it can be more easily evaluated by a debugger. + public ulong LockOwnerOSThreadId // the getter may be used by debuggers + { + get + { + Debug.Assert(_objectPtr != null); + + switch (_objectKind) + { + case ObjectKind.MonitorLock: + case ObjectKind.MonitorWait: + // The Monitor object kinds are only used by CoreCLR, and only the OS thread ID is reported +#if CORECLR + if (s_monitorObjectOffsetOfLockOwnerOSThreadId != 0) + { + return *(nuint*)((nint)_objectPtr + s_monitorObjectOffsetOfLockOwnerOSThreadId); + } +#endif + return 0; + + case ObjectKind.Lock: + return ((Lock)Unsafe.AsRef(_objectPtr)).OwningOSThreadId; + + default: + Debug.Assert(_objectKind == ObjectKind.Condition); +#if NATIVEAOT + return ((Condition)Unsafe.AsRef(_objectPtr)).AssociatedLock.OwningOSThreadId; +#else + return 0; +#endif + } + } + } + + // If the blocking is associated with a lock of some kind that has thread affinity and tracks the owner's managed thread + // ID, returns the managed thread ID of the thread that currently owns the lock. Otherwise, returns 0. A return value of + // 0 may indicate that the associated lock is currently not owned by a thread, or that the information could not be + // determined. + // + // Calls to native helpers are avoided in the property getter such that it can be more easily evaluated by a debugger. + public int LockOwnerManagedThreadId // the getter may be used by debuggers + { + get + { + Debug.Assert(_objectPtr != null); + + switch (_objectKind) + { + case ObjectKind.MonitorLock: + case ObjectKind.MonitorWait: + // The Monitor object kinds are only used by CoreCLR, and only the OS thread ID is reported + return 0; + + case ObjectKind.Lock: + return ((Lock)Unsafe.AsRef(_objectPtr)).OwningManagedThreadId; + + default: + Debug.Assert(_objectKind == ObjectKind.Condition); +#if NATIVEAOT + return ((Condition)Unsafe.AsRef(_objectPtr)).AssociatedLock.OwningManagedThreadId; +#else + return 0; +#endif + } + } + } + + public unsafe ref struct Scope + { + private object? _object; + private ThreadBlockingInfo _blockingInfo; + +#pragma warning disable CS9216 // casting Lock to object + public Scope(Lock lockObj, int timeoutMs) : this(lockObj, ObjectKind.Lock, timeoutMs) { } +#pragma warning restore CS9216 + +#if NATIVEAOT + public Scope(Condition condition, int timeoutMs) : this(condition, ObjectKind.Condition, timeoutMs) { } +#endif + + private Scope(object obj, ObjectKind objectKind, int timeoutMs) + { + _object = obj; + _blockingInfo.Push(Unsafe.AsPointer(ref _object), objectKind, timeoutMs); + } + + public void Dispose() + { + if (_object is not null) + { + _blockingInfo.Pop(); + _object = null; + } + } + } + + public enum ObjectKind // may be used by debuggers + { + MonitorLock, // maps to DebugBlockingItemType::DebugBlock_MonitorCriticalSection in coreclr + MonitorWait, // maps to DebugBlockingItemType::DebugBlock_MonitorEvent in coreclr + Lock, + Condition + } + } +} From 5b4e770daa190ce69f402c1cf92f388b07d3e144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Thu, 25 Apr 2024 06:24:37 +0900 Subject: [PATCH 096/248] Disable most of S.T.Json trimming tests on AOT the right way (#101418) These don't seem to use the source generator, so they're not really "trimming tests" and obviously they don't work. --- .../TrimmingTests/System.Text.Json.TrimmingTests.proj | 4 +++- src/libraries/tests.proj | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/TrimmingTests/System.Text.Json.TrimmingTests.proj b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/TrimmingTests/System.Text.Json.TrimmingTests.proj index 6d9885fed2a91a..37188a8dce70d6 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/TrimmingTests/System.Text.Json.TrimmingTests.proj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/TrimmingTests/System.Text.Json.TrimmingTests.proj @@ -1,7 +1,9 @@ - + + Helper.cs diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 6610727190fb34..7106a44c89e967 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -653,7 +653,6 @@ - Date: Thu, 25 Apr 2024 03:28:40 +0100 Subject: [PATCH 097/248] JIT ARM64-SVE: Add Sve.LoadVector*ZeroExtendTo*() (#101291) * JIT ARM64-SVE: Add Sve.LoadVector*ZeroExtendTo*() Add the following APIs: LoadVectorByteZeroExtendToInt16 LoadVectorByteZeroExtendToInt32 LoadVectorByteZeroExtendToInt64 LoadVectorByteZeroExtendToUInt16 LoadVectorByteZeroExtendToUInt32 LoadVectorByteZeroExtendToUInt64 LoadVectorInt16SignExtendToInt32 LoadVectorInt16SignExtendToInt64 LoadVectorInt16SignExtendToUInt32 LoadVectorInt16SignExtendToUInt64 LoadVectorInt32SignExtendToInt64 LoadVectorInt32SignExtendToUInt64 LoadVectorSByteSignExtendToInt16 LoadVectorSByteSignExtendToInt32 LoadVectorSByteSignExtendToInt64 LoadVectorSByteSignExtendToUInt16 LoadVectorSByteSignExtendToUInt32 LoadVectorSByteSignExtendToUInt64 LoadVectorUInt16ZeroExtendToInt32 LoadVectorUInt16ZeroExtendToInt64 LoadVectorUInt16ZeroExtendToUInt32 LoadVectorUInt16ZeroExtendToUInt64 LoadVectorUInt32ZeroExtendToInt64 LoadVectorUInt32ZeroExtendToUInt64 * cleanup: remove unwatnted comments Remove comments that mentions instuctions that APIs are never mapped to. * fix merge conflict * fix merge conflict * fix spacing * Mark LoadVector*Extend* as having HW_Flag_ExplicitMaskedOperation --------- Co-authored-by: Kunal Pathak --- src/coreclr/jit/emitarm64sve.cpp | 3 + src/coreclr/jit/gentree.cpp | 24 ++ src/coreclr/jit/hwintrinsiclistarm64sve.h | 24 ++ .../Arm/Sve.PlatformNotSupported.cs | 216 +++++++++++++++++ .../src/System/Runtime/Intrinsics/Arm/Sve.cs | 217 ++++++++++++++++++ .../ref/System.Runtime.Intrinsics.cs | 25 ++ .../GenerateHWIntrinsicTests_Arm.cs | 27 ++- 7 files changed, 535 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/emitarm64sve.cpp b/src/coreclr/jit/emitarm64sve.cpp index 1b90b26ba799af..3eadf273290f85 100644 --- a/src/coreclr/jit/emitarm64sve.cpp +++ b/src/coreclr/jit/emitarm64sve.cpp @@ -4349,8 +4349,11 @@ void emitter::emitInsSve_R_R_R(instruction ins, break; case INS_sve_ld1b: + case INS_sve_ld1sb: case INS_sve_ld1h: + case INS_sve_ld1sh: case INS_sve_ld1w: + case INS_sve_ld1sw: case INS_sve_ld1d: return emitIns_R_R_R_I(ins, size, reg1, reg2, reg3, 0, opt); diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 85ce90e94e001d..8076662e183e44 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -26508,6 +26508,30 @@ bool GenTreeHWIntrinsic::OperIsMemoryLoad(GenTree** pAddr) const break; case NI_Sve_LoadVector: + case NI_Sve_LoadVectorByteZeroExtendToInt16: + case NI_Sve_LoadVectorByteZeroExtendToInt32: + case NI_Sve_LoadVectorByteZeroExtendToInt64: + case NI_Sve_LoadVectorByteZeroExtendToUInt16: + case NI_Sve_LoadVectorByteZeroExtendToUInt32: + case NI_Sve_LoadVectorByteZeroExtendToUInt64: + case NI_Sve_LoadVectorInt16SignExtendToInt32: + case NI_Sve_LoadVectorInt16SignExtendToInt64: + case NI_Sve_LoadVectorInt16SignExtendToUInt32: + case NI_Sve_LoadVectorInt16SignExtendToUInt64: + case NI_Sve_LoadVectorInt32SignExtendToInt64: + case NI_Sve_LoadVectorInt32SignExtendToUInt64: + case NI_Sve_LoadVectorSByteSignExtendToInt16: + case NI_Sve_LoadVectorSByteSignExtendToInt32: + case NI_Sve_LoadVectorSByteSignExtendToInt64: + case NI_Sve_LoadVectorSByteSignExtendToUInt16: + case NI_Sve_LoadVectorSByteSignExtendToUInt32: + case NI_Sve_LoadVectorSByteSignExtendToUInt64: + case NI_Sve_LoadVectorUInt16ZeroExtendToInt32: + case NI_Sve_LoadVectorUInt16ZeroExtendToInt64: + case NI_Sve_LoadVectorUInt16ZeroExtendToUInt32: + case NI_Sve_LoadVectorUInt16ZeroExtendToUInt64: + case NI_Sve_LoadVectorUInt32ZeroExtendToInt64: + case NI_Sve_LoadVectorUInt32ZeroExtendToUInt64: addr = Op(2); break; #endif // TARGET_ARM64 diff --git a/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/coreclr/jit/hwintrinsiclistarm64sve.h index 14b880c8e570e4..02fd4992204c0c 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64sve.h +++ b/src/coreclr/jit/hwintrinsiclistarm64sve.h @@ -32,6 +32,30 @@ HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt32, HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt64, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) HARDWARE_INTRINSIC(Sve, LoadVector, -1, 2, true, {INS_sve_ld1b, INS_sve_ld1b, INS_sve_ld1h, INS_sve_ld1h, INS_sve_ld1w, INS_sve_ld1w, INS_sve_ld1d, INS_sve_ld1d, INS_sve_ld1w, INS_sve_ld1d}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToInt16, -1, 2, false, {INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToUInt16, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToUInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorInt16SignExtendToInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorInt16SignExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sh, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorInt16SignExtendToUInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sh, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorInt16SignExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sh, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorInt32SignExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorInt32SignExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sw, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToInt16, -1, 2, false, {INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToUInt16, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToUInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1h, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1h, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToUInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1h, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1h, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs index 8d56e32fc863ca..4b0ccfaecd6def 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs @@ -372,5 +372,221 @@ internal Arm64() { } public static unsafe Vector LoadVector(Vector mask, double* address) { throw new PlatformNotSupportedException(); } + /// LoadVectorByteZeroExtendToInt16 : Load 8-bit data and zero-extend + + /// + /// svint16_t svld1ub_s16(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToInt16(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorByteZeroExtendToInt32 : Load 8-bit data and zero-extend + + /// + /// svint32_t svld1ub_s32(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToInt32(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorByteZeroExtendToInt64 : Load 8-bit data and zero-extend + + /// + /// svint64_t svld1ub_s64(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToInt64(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorByteZeroExtendToUInt16 : Load 8-bit data and zero-extend + + /// + /// svuint16_t svld1ub_u16(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToUInt16(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorByteZeroExtendToUInt32 : Load 8-bit data and zero-extend + + /// + /// svuint32_t svld1ub_u32(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToUInt32(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorByteZeroExtendToUInt64 : Load 8-bit data and zero-extend + + /// + /// svuint64_t svld1ub_u64(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToUInt64(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorInt16SignExtendToInt32 : Load 16-bit data and sign-extend + + /// + /// svint32_t svld1sh_s32(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToInt32(Vector mask, short* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorInt16SignExtendToInt64 : Load 16-bit data and sign-extend + + /// + /// svint64_t svld1sh_s64(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToInt64(Vector mask, short* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorInt16SignExtendToUInt32 : Load 16-bit data and sign-extend + + /// + /// svuint32_t svld1sh_u32(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToUInt32(Vector mask, short* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorInt16SignExtendToUInt64 : Load 16-bit data and sign-extend + + /// + /// svuint64_t svld1sh_u64(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToUInt64(Vector mask, short* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorInt32SignExtendToInt64 : Load 32-bit data and sign-extend + + /// + /// svint64_t svld1sw_s64(svbool_t pg, const int32_t *base) + /// LD1SW Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt32SignExtendToInt64(Vector mask, int* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorInt32SignExtendToUInt64 : Load 32-bit data and sign-extend + + /// + /// svuint64_t svld1sw_u64(svbool_t pg, const int32_t *base) + /// LD1SW Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt32SignExtendToUInt64(Vector mask, int* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorSByteSignExtendToInt16 : Load 8-bit data and sign-extend + + /// + /// svint16_t svld1sb_s16(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToInt16(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorSByteSignExtendToInt32 : Load 8-bit data and sign-extend + + /// + /// svint32_t svld1sb_s32(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToInt32(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorSByteSignExtendToInt64 : Load 8-bit data and sign-extend + + /// + /// svint64_t svld1sb_s64(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToInt64(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorSByteSignExtendToUInt16 : Load 8-bit data and sign-extend + + /// + /// svuint16_t svld1sb_u16(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToUInt16(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorSByteSignExtendToUInt32 : Load 8-bit data and sign-extend + + /// + /// svuint32_t svld1sb_u32(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToUInt32(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorSByteSignExtendToUInt64 : Load 8-bit data and sign-extend + + /// + /// svuint64_t svld1sb_u64(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToUInt64(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorUInt16ZeroExtendToInt32 : Load 16-bit data and zero-extend + + /// + /// svint32_t svld1uh_s32(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToInt32(Vector mask, ushort* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorUInt16ZeroExtendToInt64 : Load 16-bit data and zero-extend + + /// + /// svint64_t svld1uh_s64(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToInt64(Vector mask, ushort* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorUInt16ZeroExtendToUInt32 : Load 16-bit data and zero-extend + + /// + /// svuint32_t svld1uh_u32(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToUInt32(Vector mask, ushort* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorUInt16ZeroExtendToUInt64 : Load 16-bit data and zero-extend + + /// + /// svuint64_t svld1uh_u64(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToUInt64(Vector mask, ushort* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorUInt32ZeroExtendToInt64 : Load 32-bit data and zero-extend + + /// + /// svint64_t svld1uw_s64(svbool_t pg, const uint32_t *base) + /// LD1W Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt32ZeroExtendToInt64(Vector mask, uint* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorUInt32ZeroExtendToUInt64 : Load 32-bit data and zero-extend + + /// + /// svuint64_t svld1uw_u64(svbool_t pg, const uint32_t *base) + /// LD1W Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt32ZeroExtendToUInt64(Vector mask, uint* address) { throw new PlatformNotSupportedException(); } + + } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs index a13957916f49a7..9f17f6b9008ed0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs @@ -426,5 +426,222 @@ internal Arm64() { } /// public static unsafe Vector LoadVector(Vector mask, double* address) => LoadVector(mask, address); + + /// LoadVectorByteZeroExtendToInt16 : Load 8-bit data and zero-extend + + /// + /// svint16_t svld1ub_s16(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToInt16(Vector mask, byte* address) => LoadVectorByteZeroExtendToInt16(mask, address); + + + /// LoadVectorByteZeroExtendToInt32 : Load 8-bit data and zero-extend + + /// + /// svint32_t svld1ub_s32(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToInt32(Vector mask, byte* address) => LoadVectorByteZeroExtendToInt32(mask, address); + + + /// LoadVectorByteZeroExtendToInt64 : Load 8-bit data and zero-extend + + /// + /// svint64_t svld1ub_s64(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToInt64(Vector mask, byte* address) => LoadVectorByteZeroExtendToInt64(mask, address); + + + /// LoadVectorByteZeroExtendToUInt16 : Load 8-bit data and zero-extend + + /// + /// svuint16_t svld1ub_u16(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToUInt16(Vector mask, byte* address) => LoadVectorByteZeroExtendToUInt16(mask, address); + + + /// LoadVectorByteZeroExtendToUInt32 : Load 8-bit data and zero-extend + + /// + /// svuint32_t svld1ub_u32(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToUInt32(Vector mask, byte* address) => LoadVectorByteZeroExtendToUInt32(mask, address); + + + /// LoadVectorByteZeroExtendToUInt64 : Load 8-bit data and zero-extend + + /// + /// svuint64_t svld1ub_u64(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToUInt64(Vector mask, byte* address) => LoadVectorByteZeroExtendToUInt64(mask, address); + + + /// LoadVectorInt16SignExtendToInt32 : Load 16-bit data and sign-extend + + /// + /// svint32_t svld1sh_s32(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToInt32(Vector mask, short* address) => LoadVectorInt16SignExtendToInt32(mask, address); + + + /// LoadVectorInt16SignExtendToInt64 : Load 16-bit data and sign-extend + + /// + /// svint64_t svld1sh_s64(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToInt64(Vector mask, short* address) => LoadVectorInt16SignExtendToInt64(mask, address); + + + /// LoadVectorInt16SignExtendToUInt32 : Load 16-bit data and sign-extend + + /// + /// svuint32_t svld1sh_u32(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToUInt32(Vector mask, short* address) => LoadVectorInt16SignExtendToUInt32(mask, address); + + + /// LoadVectorInt16SignExtendToUInt64 : Load 16-bit data and sign-extend + + /// + /// svuint64_t svld1sh_u64(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToUInt64(Vector mask, short* address) => LoadVectorInt16SignExtendToUInt64(mask, address); + + + /// LoadVectorInt32SignExtendToInt64 : Load 32-bit data and sign-extend + + /// + /// svint64_t svld1sw_s64(svbool_t pg, const int32_t *base) + /// LD1SW Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt32SignExtendToInt64(Vector mask, int* address) => LoadVectorInt32SignExtendToInt64(mask, address); + + + /// LoadVectorInt32SignExtendToUInt64 : Load 32-bit data and sign-extend + + /// + /// svuint64_t svld1sw_u64(svbool_t pg, const int32_t *base) + /// LD1SW Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt32SignExtendToUInt64(Vector mask, int* address) => LoadVectorInt32SignExtendToUInt64(mask, address); + + + /// LoadVectorSByteSignExtendToInt16 : Load 8-bit data and sign-extend + + /// + /// svint16_t svld1sb_s16(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToInt16(Vector mask, sbyte* address) => LoadVectorSByteSignExtendToInt16(mask, address); + + + /// LoadVectorSByteSignExtendToInt32 : Load 8-bit data and sign-extend + + /// + /// svint32_t svld1sb_s32(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToInt32(Vector mask, sbyte* address) => LoadVectorSByteSignExtendToInt32(mask, address); + + + /// LoadVectorSByteSignExtendToInt64 : Load 8-bit data and sign-extend + + /// + /// svint64_t svld1sb_s64(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToInt64(Vector mask, sbyte* address) => LoadVectorSByteSignExtendToInt64(mask, address); + + + /// LoadVectorSByteSignExtendToUInt16 : Load 8-bit data and sign-extend + + /// + /// svuint16_t svld1sb_u16(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToUInt16(Vector mask, sbyte* address) => LoadVectorSByteSignExtendToUInt16(mask, address); + + + /// LoadVectorSByteSignExtendToUInt32 : Load 8-bit data and sign-extend + + /// + /// svuint32_t svld1sb_u32(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToUInt32(Vector mask, sbyte* address) => LoadVectorSByteSignExtendToUInt32(mask, address); + + + /// LoadVectorSByteSignExtendToUInt64 : Load 8-bit data and sign-extend + + /// + /// svuint64_t svld1sb_u64(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToUInt64(Vector mask, sbyte* address) => LoadVectorSByteSignExtendToUInt64(mask, address); + + + /// LoadVectorUInt16ZeroExtendToInt32 : Load 16-bit data and zero-extend + + /// + /// svint32_t svld1uh_s32(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToInt32(Vector mask, ushort* address) => LoadVectorUInt16ZeroExtendToInt32(mask, address); + + + /// LoadVectorUInt16ZeroExtendToInt64 : Load 16-bit data and zero-extend + + /// + /// svint64_t svld1uh_s64(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToInt64(Vector mask, ushort* address) => LoadVectorUInt16ZeroExtendToInt64(mask, address); + + + /// LoadVectorUInt16ZeroExtendToUInt32 : Load 16-bit data and zero-extend + + /// + /// svuint32_t svld1uh_u32(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToUInt32(Vector mask, ushort* address) => LoadVectorUInt16ZeroExtendToUInt32(mask, address); + + + /// LoadVectorUInt16ZeroExtendToUInt64 : Load 16-bit data and zero-extend + + /// + /// svuint64_t svld1uh_u64(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToUInt64(Vector mask, ushort* address) => LoadVectorUInt16ZeroExtendToUInt64(mask, address); + + + /// LoadVectorUInt32ZeroExtendToInt64 : Load 32-bit data and zero-extend + + /// + /// svint64_t svld1uw_s64(svbool_t pg, const uint32_t *base) + /// LD1W Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt32ZeroExtendToInt64(Vector mask, uint* address) => LoadVectorUInt32ZeroExtendToInt64(mask, address); + + + /// LoadVectorUInt32ZeroExtendToUInt64 : Load 32-bit data and zero-extend + + /// + /// svuint64_t svld1uw_u64(svbool_t pg, const uint32_t *base) + /// LD1W Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt32ZeroExtendToUInt64(Vector mask, uint* address) => LoadVectorUInt32ZeroExtendToUInt64(mask, address); + + } } diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 3980308ca0d20e..875d125cb32b50 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -4217,6 +4217,31 @@ internal Arm64() { } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, ulong* address) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, float* address) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, double* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendToInt16(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendToInt32(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendToInt64(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendToUInt16(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendToUInt32(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendToUInt64(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt16SignExtendToInt32(System.Numerics.Vector mask, short* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt16SignExtendToInt64(System.Numerics.Vector mask, short* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt16SignExtendToUInt32(System.Numerics.Vector mask, short* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt16SignExtendToUInt64(System.Numerics.Vector mask, short* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt32SignExtendToInt64(System.Numerics.Vector mask, int* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt32SignExtendToUInt64(System.Numerics.Vector mask, int* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendToInt16(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendToInt32(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendToInt64(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendToUInt16(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendToUInt32(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendToUInt64(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendToInt32(System.Numerics.Vector mask, ushort* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendToInt64(System.Numerics.Vector mask, ushort* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendToUInt32(System.Numerics.Vector mask, ushort* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendToUInt64(System.Numerics.Vector mask, ushort* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendToInt64(System.Numerics.Vector mask, uint* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendToUInt64(System.Numerics.Vector mask, uint* address) { throw null; } + } public enum SveMaskPattern : byte diff --git a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs index a2ebacb1ce8b8c..42096d7b697c73 100644 --- a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs +++ b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs @@ -2907,7 +2907,7 @@ ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), - + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), @@ -2929,6 +2929,31 @@ ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_ushort", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_uint", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_ulong", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorByteZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorByteZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorByteZeroExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorByteZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorByteZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorInt16SignExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorInt16SignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorInt16SignExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorInt16SignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorInt32SignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt32SignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorInt32SignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt32SignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorSByteSignExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorSByteSignExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorSByteSignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorSByteSignExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorSByteSignExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorSByteSignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorUInt16ZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorUInt16ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorUInt16ZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorUInt16ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorUInt32ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorUInt32ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), }; From 5bbd0e1b817c66a1b54130ea039b18a027130e72 Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Thu, 25 Apr 2024 03:53:32 +0100 Subject: [PATCH 098/248] Restrict indentation size in JsonWriterOptions theories. (#101498) --- .../tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs index c776982b56d925..45986cccb9aaa5 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs @@ -7637,7 +7637,7 @@ private static IEnumerable JsonOptions() return from indented in new[] { true, false } from skipValidation in new[] { true, false } from indentCharacter in indented ? new char?[] { null, ' ', '\t' } : [] - from indentSize in indented ? new int?[] { null, 0, 1, 2, 127 } : [] + from indentSize in indented ? new int?[] { null, 0, 1, 2, 3 } : [] from newLine in indented ? new string?[] { null, "\n", "\r\n" } : [] select CreateOptions(indented, indentCharacter, indentSize, skipValidation, newLine); From c028937b775855c05c19f5d6209aabf3775f4103 Mon Sep 17 00:00:00 2001 From: Giridhar Trivedi Date: Thu, 25 Apr 2024 12:39:17 +0530 Subject: [PATCH 099/248] Fix big endian issue in Interlocked test cases (#101429) Fix big indian issue wiht BitConverted as part of intercloked test cases. These were causing failures in runtime_community pipeline --------- Co-authored-by: root --- .../src/System/Threading/Interlocked.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 45ebce76f7b0ee..6e33ce716fd6a1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs @@ -126,7 +126,7 @@ public static unsafe ushort Exchange(ref ushort location1, ushort value) nuint offset = Unsafe.OpportunisticMisalignment(ref location1, sizeof(uint)); ref uint alignedRef = ref Unsafe.As(ref Unsafe.SubtractByteOffset(ref location1, offset)); int bitOffset = - (int)((BitConverter.IsLittleEndian ? offset : sizeof(uint) - offset - sizeof(byte)) * 8); // to bit offset + (int)((BitConverter.IsLittleEndian ? offset : sizeof(uint) - offset - sizeof(ushort)) * 8); // to bit offset Debug.Assert(bitOffset is 0 or 16); uint mask = ~((uint)ushort.MaxValue << bitOffset); uint shiftedValue = (uint)value << bitOffset; @@ -308,7 +308,7 @@ public static unsafe ushort CompareExchange(ref ushort location1, ushort value, nuint offset = Unsafe.OpportunisticMisalignment(ref location1, sizeof(uint)); ref uint alignedRef = ref Unsafe.As(ref Unsafe.SubtractByteOffset(ref location1, offset)); int bitOffset = - (int)((BitConverter.IsLittleEndian ? offset : sizeof(uint) - offset - sizeof(byte)) * 8); // to bit offset + (int)((BitConverter.IsLittleEndian ? offset : sizeof(uint) - offset - sizeof(ushort)) * 8); // to bit offset Debug.Assert(bitOffset is 0 or 16); uint mask = ~((uint)ushort.MaxValue << bitOffset); uint shiftedValue = (uint)value << bitOffset; From 43ba3a8af36541e45faaa7034ea76b5ec11b3777 Mon Sep 17 00:00:00 2001 From: Milos Kotlar Date: Thu, 25 Apr 2024 09:29:54 +0200 Subject: [PATCH 100/248] [mono] Fix `LLVMArgWasmVtypeAsScalar` when a method doesn't set its return value (#101299) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update mini-llvm.c I think we should handle it here, the same way as `LLVMArgVtypeAsScalar`. They differ only in the return type, where the wasm specific one is returning type of the element instead of `int`. * Include TrimmerRootDescriptor only on Apple mobile platforms * Update src/mono/mono/mini/mini-llvm.c --------- Co-authored-by: Radek Doulik Co-authored-by: Aleksey Kliger (λgeek) --- ...tem.Configuration.ConfigurationManager.Tests.csproj | 3 ++- .../tests/System.Data.Common.Tests.csproj | 3 ++- .../System.Diagnostics.FileVersionInfo.Tests.csproj | 3 ++- .../System.Linq/tests/System.Linq.Tests.csproj | 3 ++- .../System.Reflection.MetadataLoadContext.Tests.csproj | 2 +- .../tests/System.Resources.Extensions.Tests.csproj | 3 ++- .../tests/System.Runtime.Loader.Tests.csproj | 2 +- .../System.Globalization.Tests.csproj | 3 ++- ...stem.IO.FileSystem.DisabledFileLocking.Tests.csproj | 3 ++- .../System.IO.FileSystem.Tests.csproj | 3 ++- .../System.Security.Cryptography.Xml.Tests.csproj | 3 ++- .../System.Text.Json.Tests.csproj | 3 ++- src/mono/mono/mini/mini-llvm.c | 10 ++++++++-- 13 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj b/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj index 2a24b7ffaad07f..0a6b23dad7e658 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj +++ b/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj @@ -97,7 +97,8 @@ - + + diff --git a/src/libraries/System.Data.Common/tests/System.Data.Common.Tests.csproj b/src/libraries/System.Data.Common/tests/System.Data.Common.Tests.csproj index ed37aab0c75388..ae85c66d7e8b5f 100644 --- a/src/libraries/System.Data.Common/tests/System.Data.Common.Tests.csproj +++ b/src/libraries/System.Data.Common/tests/System.Data.Common.Tests.csproj @@ -123,6 +123,7 @@ - + + diff --git a/src/libraries/System.Diagnostics.FileVersionInfo/tests/System.Diagnostics.FileVersionInfo.Tests/System.Diagnostics.FileVersionInfo.Tests.csproj b/src/libraries/System.Diagnostics.FileVersionInfo/tests/System.Diagnostics.FileVersionInfo.Tests/System.Diagnostics.FileVersionInfo.Tests.csproj index cdadf742e3d976..fa358a2a90893b 100644 --- a/src/libraries/System.Diagnostics.FileVersionInfo/tests/System.Diagnostics.FileVersionInfo.Tests/System.Diagnostics.FileVersionInfo.Tests.csproj +++ b/src/libraries/System.Diagnostics.FileVersionInfo/tests/System.Diagnostics.FileVersionInfo.Tests/System.Diagnostics.FileVersionInfo.Tests.csproj @@ -52,6 +52,7 @@ - + + diff --git a/src/libraries/System.Linq/tests/System.Linq.Tests.csproj b/src/libraries/System.Linq/tests/System.Linq.Tests.csproj index 33d584fe8f6a15..1e4692999a1743 100644 --- a/src/libraries/System.Linq/tests/System.Linq.Tests.csproj +++ b/src/libraries/System.Linq/tests/System.Linq.Tests.csproj @@ -5,7 +5,8 @@ - + + diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/System.Reflection.MetadataLoadContext.Tests.csproj b/src/libraries/System.Reflection.MetadataLoadContext/tests/System.Reflection.MetadataLoadContext.Tests.csproj index 32518ce3efa431..4feacf3ede60ec 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/System.Reflection.MetadataLoadContext.Tests.csproj +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/System.Reflection.MetadataLoadContext.Tests.csproj @@ -92,7 +92,7 @@ - + diff --git a/src/libraries/System.Resources.Extensions/tests/System.Resources.Extensions.Tests.csproj b/src/libraries/System.Resources.Extensions/tests/System.Resources.Extensions.Tests.csproj index a0533c343614c6..8a197d09368674 100644 --- a/src/libraries/System.Resources.Extensions/tests/System.Resources.Extensions.Tests.csproj +++ b/src/libraries/System.Resources.Extensions/tests/System.Resources.Extensions.Tests.csproj @@ -27,7 +27,8 @@ - + + + diff --git a/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DisabledFileLockingTests/System.IO.FileSystem.DisabledFileLocking.Tests.csproj b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DisabledFileLockingTests/System.IO.FileSystem.DisabledFileLocking.Tests.csproj index b029dd3341a710..614de3d1ce979f 100644 --- a/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DisabledFileLockingTests/System.IO.FileSystem.DisabledFileLocking.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DisabledFileLockingTests/System.IO.FileSystem.DisabledFileLocking.Tests.csproj @@ -34,7 +34,8 @@ - + + diff --git a/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csproj b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csproj index 0e4d3e3770cd61..b4f627b831f2e5 100644 --- a/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csproj @@ -245,6 +245,7 @@ - + + diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj b/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj index 858a44b23608f9..56458c07a5a0f7 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj @@ -75,6 +75,7 @@ - + + 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 1e3c083791c653..9eb2e9a2e63d78 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 @@ -307,6 +307,7 @@ - + + diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 63ffbf994657f0..07bbe7d4e0037a 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -6119,8 +6119,14 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) gboolean src_in_reg = FALSE; gboolean is_simd = mini_class_is_simd (ctx->cfg, mono_class_from_mono_type_internal (sig->ret)); switch (linfo->ret.storage) { - case LLVMArgNormal: src_in_reg = TRUE; break; - case LLVMArgVtypeInReg: case LLVMArgVtypeAsScalar: src_in_reg = is_simd; break; + case LLVMArgNormal: + src_in_reg = TRUE; + break; + case LLVMArgVtypeInReg: + case LLVMArgVtypeAsScalar: + case LLVMArgWasmVtypeAsScalar: + src_in_reg = is_simd; + break; } if (src_in_reg && (!lhs || ctx->is_dead [ins->sreg1])) { /* From c0e3e61c9f75295c5b58fb0836a012d8635e77a4 Mon Sep 17 00:00:00 2001 From: Milos Kotlar Date: Thu, 25 Apr 2024 09:39:48 +0200 Subject: [PATCH 101/248] Add runtime test for static gsharedvt methods (#101489) --- .../JitBlue/Runtime_94467/Runtime_94467.cs | 44 +++++++++++++++++++ .../Runtime_94467/Runtime_94467.csproj | 8 ++++ 2 files changed, 52 insertions(+) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_94467/Runtime_94467.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_94467/Runtime_94467.csproj diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_94467/Runtime_94467.cs b/src/tests/JIT/Regression/JitBlue/Runtime_94467/Runtime_94467.cs new file mode 100644 index 00000000000000..85aa6e62655d2f --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_94467/Runtime_94467.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using Xunit; + +public static class Runtime_94467 +{ + public interface ITypeChecker + { + static abstract bool Test(T value); + } + + public interface IHandler + { + bool Test(T value); + } + + public struct TypeChecker : ITypeChecker + { + public static bool Test(T value) => true; + } + + public class Handler : IHandler where TChecker : ITypeChecker + { + public bool Test(T value) => TChecker.Test(value); + } + + public static IHandler GetHandler() => new Handler(); + + [Fact] + public static int Test() + { + try { + var handler = GetHandler(); + if (handler.Test(true) && handler.Test(true)) + return 100; + else + return 101; + } catch (Exception) { + return -1; + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_94467/Runtime_94467.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_94467/Runtime_94467.csproj new file mode 100644 index 00000000000000..15edd99711a1a4 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_94467/Runtime_94467.csproj @@ -0,0 +1,8 @@ + + + True + + + + + \ No newline at end of file From 127844cf0d4c79e5bb02ced2faac3f44676afa8f Mon Sep 17 00:00:00 2001 From: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Thu, 25 Apr 2024 13:18:43 +0200 Subject: [PATCH 102/248] Fix data race leading to a deadlock when opening QuicStream (#101250) * Fix data race leading to a deadlock. * Remove unwanted change * Code review feedback * Fix hang * Add assert * Fix potential crash * Code review feedback --- .../System/Net/Quic/Internal/ThrowHelper.cs | 27 +++++++++++++++---- .../src/System/Net/Quic/QuicConnection.cs | 23 +++++++++++++--- .../src/System/Net/Quic/QuicStream.cs | 14 +++++++--- 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/ThrowHelper.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/ThrowHelper.cs index 114c39c49c1e5e..bb1cc7d25b7b3e 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/ThrowHelper.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/ThrowHelper.cs @@ -27,13 +27,27 @@ internal static QuicException GetOperationAbortedException(string? message = nul return new QuicException(QuicError.OperationAborted, null, message ?? SR.net_quic_operationaborted); } - internal static bool TryGetStreamExceptionForMsQuicStatus(int status, [NotNullWhen(true)] out Exception? exception) + internal static bool TryGetStreamExceptionForMsQuicStatus(int status, [NotNullWhen(true)] out Exception? exception, bool streamWasSuccessfullyStarted = true, string? message = null) { if (status == QUIC_STATUS_ABORTED) { - // If status == QUIC_STATUS_ABORTED, we will receive an event later, which will complete the task source. - exception = null; - return false; + // Connection has been closed by the peer (either at transport or application level), + if (streamWasSuccessfullyStarted) + { + // we will receive an event later, which will complete the stream with concrete + // information why the connection was aborted. + exception = null; + return false; + } + else + { + // we won't be receiving any event callback for shutdown on this stream, so we don't + // necessarily know which error to report. So we throw an exception which we can distinguish + // at the caller (ConnectionAborted normally has App error code) and throw the correct + // exception from there. + exception = new QuicException(QuicError.ConnectionAborted, null, ""); + return true; + } } else if (status == QUIC_STATUS_INVALID_STATE) { @@ -43,13 +57,16 @@ internal static bool TryGetStreamExceptionForMsQuicStatus(int status, [NotNullWh } else if (StatusFailed(status)) { - exception = GetExceptionForMsQuicStatus(status); + exception = GetExceptionForMsQuicStatus(status, message: message); return true; } exception = null; return false; } + // see TryGetStreamExceptionForMsQuicStatus for explanation + internal static bool IsConnectionAbortedWhenStartingStreamException(Exception ex) => ex is QuicException qe && qe.QuicError == QuicError.ConnectionAborted && qe.ApplicationErrorCode is null; + internal static Exception GetExceptionForMsQuicStatus(int status, long? errorCode = default, string? message = null) { Exception ex = GetExceptionInternal(status, errorCode, message); 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 e568eeb6f97b7a..f266acb265a138 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs @@ -108,6 +108,11 @@ static async ValueTask StartConnectAsync(QuicClientConnectionOpt /// private int _disposed; + /// + /// Completed when connection shutdown is initiated. + /// + private TaskCompletionSource _connectionCloseTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + private readonly ValueTaskSource _connectedTcs = new ValueTaskSource(); private readonly ResettableValueTaskSource _shutdownTcs = new ResettableValueTaskSource() { @@ -424,7 +429,7 @@ public async ValueTask OpenOutboundStreamAsync(QuicStreamType type, await stream.StartAsync(cancellationToken).ConfigureAwait(false); } - catch + catch (Exception ex) { if (stream is not null) { @@ -433,10 +438,16 @@ public async ValueTask OpenOutboundStreamAsync(QuicStreamType type, // Propagate ODE if disposed in the meantime. ObjectDisposedException.ThrowIf(_disposed == 1, this); + + // In case of an incoming race when the connection is closed by the peer just before we open the stream, + // we receive QUIC_STATUS_ABORTED from MsQuic, but we don't know how the connection was closed. We throw + // special exception and handle it here where we can determine the shutdown reason. + bool connectionAbortedByPeer = ThrowHelper.IsConnectionAbortedWhenStartingStreamException(ex); + // Propagate connection error if present. - if (_acceptQueue.Reader.Completion.IsFaulted) + if (_connectionCloseTcs.Task.IsFaulted || connectionAbortedByPeer) { - await _acceptQueue.Reader.Completion.ConfigureAwait(false); + await _connectionCloseTcs.Task.ConfigureAwait(false); } throw; } @@ -534,12 +545,15 @@ private unsafe int HandleEventShutdownInitiatedByTransport(ref SHUTDOWN_INITIATE { Exception exception = ExceptionDispatchInfo.SetCurrentStackTrace(ThrowHelper.GetExceptionForMsQuicStatus(data.Status, (long)data.ErrorCode)); _connectedTcs.TrySetException(exception); + _connectionCloseTcs.TrySetException(exception); _acceptQueue.Writer.TryComplete(exception); return QUIC_STATUS_SUCCESS; } private unsafe int HandleEventShutdownInitiatedByPeer(ref SHUTDOWN_INITIATED_BY_PEER_DATA data) { - _acceptQueue.Writer.TryComplete(ExceptionDispatchInfo.SetCurrentStackTrace(ThrowHelper.GetConnectionAbortedException((long)data.ErrorCode))); + Exception exception = ExceptionDispatchInfo.SetCurrentStackTrace(ThrowHelper.GetConnectionAbortedException((long)data.ErrorCode)); + _connectionCloseTcs.TrySetException(exception); + _acceptQueue.Writer.TryComplete(exception); return QUIC_STATUS_SUCCESS; } private unsafe int HandleEventShutdownComplete() @@ -548,6 +562,7 @@ private unsafe int HandleEventShutdownComplete() _tlsSecret?.WriteSecret(); Exception exception = ExceptionDispatchInfo.SetCurrentStackTrace(_disposed == 1 ? new ObjectDisposedException(GetType().FullName) : ThrowHelper.GetOperationAbortedException()); + _connectionCloseTcs.TrySetException(exception); _acceptQueue.Writer.TryComplete(exception); _connectedTcs.TrySetException(exception); _shutdownTokenSource.Cancel(); diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs index 6af0f5c5c099f3..320ca9dbcda849 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs @@ -162,13 +162,18 @@ internal unsafe QuicStream(MsQuicContextSafeHandle connectionHandle, QuicStreamT try { QUIC_HANDLE* handle; - ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.StreamOpen( + int status = MsQuicApi.Api.StreamOpen( connectionHandle, type == QuicStreamType.Unidirectional ? QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL : QUIC_STREAM_OPEN_FLAGS.NONE, &NativeCallback, (void*)GCHandle.ToIntPtr(context), - &handle), - "StreamOpen failed"); + &handle); + + if (ThrowHelper.TryGetStreamExceptionForMsQuicStatus(status, out Exception? ex, streamWasSuccessfullyStarted: false, message: "StreamOpen failed")) + { + throw ex; + } + _handle = new MsQuicContextSafeHandle(handle, context, SafeHandleType.Stream, connectionHandle); _handle.Disposable = _sendBuffers; } @@ -245,7 +250,8 @@ internal ValueTask StartAsync(CancellationToken cancellationToken = default) int status = MsQuicApi.Api.StreamStart( _handle, QUIC_STREAM_START_FLAGS.SHUTDOWN_ON_FAIL | QUIC_STREAM_START_FLAGS.INDICATE_PEER_ACCEPT); - if (ThrowHelper.TryGetStreamExceptionForMsQuicStatus(status, out Exception? exception)) + + if (ThrowHelper.TryGetStreamExceptionForMsQuicStatus(status, out Exception? exception, streamWasSuccessfullyStarted: false)) { _startedTcs.TrySetException(exception); } From d79bb01433401a144816a386c5411ac4c08b6187 Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Thu, 25 Apr 2024 14:57:14 +0200 Subject: [PATCH 103/248] [browser] enable CI testing with Firefox (#100697) --- .../templates/wasm-library-aot-tests.yml | 5 +- .../common/templates/wasm-library-tests.yml | 4 +- .../runtime-extra-platforms-wasm.yml | 3 +- eng/pipelines/runtime.yml | 3 + eng/testing/BrowserVersions.props | 4 +- eng/testing/WasmRunnerTemplate.cmd | 30 ++++++++-- eng/testing/WasmRunnerTemplate.sh | 17 +++++- eng/testing/tests.browser.targets | 9 +++ eng/testing/tests.wasi.targets | 7 +++ eng/testing/wasm-provisioning.targets | 59 +++++++++++-------- .../tests/System/Net/Configuration.Http.cs | 25 ++++++-- .../System/Net/Configuration.WebSockets.cs | 31 +++++++++- .../HttpClientHandlerTest.Authentication.cs | 2 +- .../HttpClientHandlerTest.RemoteServer.cs | 14 +++-- ...ttpClientHandlerTest.ServerCertificates.cs | 2 +- .../System/Net/Http/HttpClientHandlerTest.cs | 11 +++- .../tests/System/Net/Http/PostScenarioTest.cs | 2 +- .../System/Net/Http/ResponseStreamTest.cs | 13 ++-- .../HttpClientHandlerTest.Headers.cs | 5 ++ .../HttpClientHandlerTest.Http1.cs | 1 + .../FunctionalTests/HttpRequestMessageTest.cs | 1 + .../FunctionalTests/SocketsHttpHandlerTest.cs | 1 + .../tests/ClientWebSocketTestBase.cs | 9 +-- .../tests/ConnectTest.cs | 1 + .../tests/WebSocketCreateTest.cs | 2 +- .../DateTimeFormatInfoNativeCalendarName.cs | 8 +-- src/libraries/sendtohelix-browser.targets | 25 ++++---- src/libraries/sendtohelix-wasi.targets | 4 ++ src/libraries/sendtohelix-wasm.targets | 2 + .../runtime/hybrid-globalization/locales.ts | 12 ++-- src/mono/sample/Directory.Build.props | 18 ++++-- .../sample/wasm/DefaultBrowserSample.targets | 2 +- .../Wasm.Console.Node.Sample.csproj | 2 +- .../console-v8/Wasm.Console.V8.Sample.csproj | 2 +- 34 files changed, 232 insertions(+), 104 deletions(-) diff --git a/eng/pipelines/common/templates/wasm-library-aot-tests.yml b/eng/pipelines/common/templates/wasm-library-aot-tests.yml index 43b90a370450d1..cbafd9c6b35531 100644 --- a/eng/pipelines/common/templates/wasm-library-aot-tests.yml +++ b/eng/pipelines/common/templates/wasm-library-aot-tests.yml @@ -1,7 +1,7 @@ parameters: alwaysRun: false extraBuildArgs: '' - extraHelixArgs: '' + extraHelixArguments: '' isExtraPlatformsBuild: false isWasmOnlyBuild: false buildAOTOnHelix: true @@ -26,7 +26,7 @@ jobs: isExtraPlatformsBuild: ${{ parameters.isExtraPlatformsBuild }} isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }} extraBuildArgs: /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=${{ parameters.buildAOTOnHelix }} /p:RunAOTCompilation=${{ parameters.runAOT }} ${{ parameters.extraBuildArgs }} - extraHelixArgs: /p:NeedsToBuildWasmAppsOnHelix=true ${{ parameters.extraHelixArgs }} + extraHelixArguments: /p:NeedsToBuildWasmAppsOnHelix=true ${{ parameters.extraHelixArguments }} alwaysRun: ${{ parameters.alwaysRun }} shouldRunSmokeOnly: ${{ parameters.shouldRunSmokeOnly }} shouldContinueOnError: ${{ parameters.shouldContinueOnError }} @@ -35,5 +35,6 @@ jobs: - WasmTestOnV8 - ${{ if eq(platform, 'browser_wasm_win') }}: - WasmTestOnChrome + - WasmTestOnFirefox - ${{ if or(eq(platform, 'wasi_wasm_win'), eq(platform, 'wasi_wasm')) }}: - WasmTestOnWasmtime diff --git a/eng/pipelines/common/templates/wasm-library-tests.yml b/eng/pipelines/common/templates/wasm-library-tests.yml index 4a1a5a79a30bfc..f015563fef00e3 100644 --- a/eng/pipelines/common/templates/wasm-library-tests.yml +++ b/eng/pipelines/common/templates/wasm-library-tests.yml @@ -1,7 +1,7 @@ parameters: alwaysRun: false extraBuildArgs: '' - extraHelixArgs: '' + extraHelixArguments: '' isExtraPlatformsBuild: false isWasmOnlyBuild: false nameSuffix: '' @@ -97,5 +97,5 @@ jobs: parameters: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) - extraHelixArguments: /p:BrowserHost=$(_hostedOs) $(_wasmRunSmokeTestsOnlyArg) ${{ parameters.extraHelixArgs }} + extraHelixArguments: /p:BrowserHost=$(_hostedOs) $(_wasmRunSmokeTestsOnlyArg) ${{ parameters.extraHelixArguments }} scenarios: ${{ parameters.scenarios }} diff --git a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml index 2c947a048e0550..d31cad685995d2 100644 --- a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml +++ b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml @@ -199,6 +199,7 @@ jobs: scenarios: - WasmTestOnV8 - WasmTestOnChrome + - WasmTestOnFirefox - WasmTestOnNodeJS # Hybrid Globalization AOT tests @@ -321,4 +322,4 @@ jobs: isExtraPlatformsBuild: ${{ parameters.isExtraPlatformsBuild }} isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }} scenarios: - - WasmTestOnV8 + - WasmTestOnWasmtime diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 6bb44bd64fc242..32f99429ffd692 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -843,6 +843,7 @@ extends: scenarios: - WasmTestOnV8 - WasmTestOnChrome + - WasmTestOnFirefox - template: /eng/pipelines/common/templates/wasm-library-tests.yml parameters: @@ -861,10 +862,12 @@ extends: #- browser_wasm_win nameSuffix: _Threading extraBuildArgs: /p:WasmEnableThreads=true /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) + extraHelixArguments: /p:WasmEnableThreads=true alwaysRun: ${{ variables.isRollingBuild }} shouldRunSmokeOnly: onLibrariesAndIllinkChanges scenarios: - WasmTestOnChrome + - WasmTestOnFirefox #- WasmTestOnNodeJS - this is not supported yet, https://github.com/dotnet/runtime/issues/85592 # EAT Library tests - only run on linux diff --git a/eng/testing/BrowserVersions.props b/eng/testing/BrowserVersions.props index b1e85302a8ed3a..c66b61a6e44042 100644 --- a/eng/testing/BrowserVersions.props +++ b/eng/testing/BrowserVersions.props @@ -8,7 +8,9 @@ 1250580 https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/1250586 12.3.219 - 124.0.2 + 125.0.1 0.34.0 + 125.0.1 + 0.34.0 diff --git a/eng/testing/WasmRunnerTemplate.cmd b/eng/testing/WasmRunnerTemplate.cmd index 0c7f3dc2195d26..e043ce7a34e9f5 100644 --- a/eng/testing/WasmRunnerTemplate.cmd +++ b/eng/testing/WasmRunnerTemplate.cmd @@ -30,7 +30,11 @@ if [%XHARNESS_COMMAND%] == [] ( if /I [%SCENARIO%]==[WasmTestOnChrome] ( set XHARNESS_COMMAND=test-browser ) else ( - set XHARNESS_COMMAND=test + if /I [%SCENARIO%]==[WasmTestOnFirefox] ( + set XHARNESS_COMMAND=test-browser + ) else ( + set XHARNESS_COMMAND=test + ) ) ) @@ -56,11 +60,25 @@ if /I [%XHARNESS_COMMAND%] == [test] ( ) ) ) else ( - if [%BROWSER_PATH%] == [] if not [%HELIX_CORRELATION_PAYLOAD%] == [] ( - set "BROWSER_PATH=--browser-path^=%HELIX_CORRELATION_PAYLOAD%\chrome-win\chrome.exe" - ) - if [%JS_ENGINE_ARGS%] == [] ( - set "JS_ENGINE_ARGS=--browser-arg^=--js-flags^=--stack-trace-limit^=1000" + if /I [%SCENARIO%] == [WasmTestOnChrome] ( + if [%BROWSER_PATH%] == [] if not [%HELIX_CORRELATION_PAYLOAD%] == [] ( + set "BROWSER_PATH=--browser-path^=%HELIX_CORRELATION_PAYLOAD%\chrome-win\chrome.exe" + ) + if [%JS_ENGINE_ARGS%] == [] ( + set "JS_ENGINE_ARGS=--browser-arg^=--js-flags^=--stack-trace-limit^=1000" + ) + ) else ( + if /I [%SCENARIO%] == [WasmTestOnFirefox] ( + if [%BROWSER_PATH%] == [] if not [%HELIX_CORRELATION_PAYLOAD%] == [] ( + set "BROWSER_PATH=--browser-path^=%HELIX_CORRELATION_PAYLOAD%\firefox\firefox.exe" + ) + if [%JS_ENGINE%] == [] ( + set "JS_ENGINE=--browser^=Firefox" + ) + if [%JS_ENGINE_ARGS%] == [] ( + set "JS_ENGINE_ARGS=--browser-arg^=-private-window" + ) + ) ) ) diff --git a/eng/testing/WasmRunnerTemplate.sh b/eng/testing/WasmRunnerTemplate.sh index bd7f1faadf3556..6cf4dc11d4beae 100644 --- a/eng/testing/WasmRunnerTemplate.sh +++ b/eng/testing/WasmRunnerTemplate.sh @@ -26,7 +26,9 @@ else fi if [[ -z "$XHARNESS_COMMAND" ]]; then - if [[ "$SCENARIO" == "WasmTestOnChrome" || "$SCENARIO" == "wasmtestonchrome" ]]; then + if [[ "$SCENARIO" == "WasmTestOnFirefox" || "$SCENARIO" == "wasmtestonfirefox" ]]; then + XHARNESS_COMMAND="test-browser" + elif [[ "$SCENARIO" == "WasmTestOnChrome" || "$SCENARIO" == "wasmtestonchrome" ]]; then XHARNESS_COMMAND="test-browser" else XHARNESS_COMMAND="test" @@ -59,8 +61,17 @@ if [[ "$XHARNESS_COMMAND" == "test" ]]; then fi fi else - if [[ -z "$JS_ENGINE_ARGS" ]]; then - JS_ENGINE_ARGS="--browser-arg=--js-flags=--stack-trace-limit=1000" + if [[ "$SCENARIO" == "WasmTestOnChrome" || "$SCENARIO" == "wasmtestonchrome" ]]; then + if [[ -z "$JS_ENGINE_ARGS" ]]; then + JS_ENGINE_ARGS="--browser-arg=--js-flags=--stack-trace-limit=1000" + fi + elif [[ "$SCENARIO" == "WasmTestOnFirefox" || "$SCENARIO" == "wasmtestonfirefox" ]]; then + if [[ -z "$JS_ENGINE" ]]; then + JS_ENGINE="--browser=Firefox" + fi + if [[ -z "$JS_ENGINE_ARGS" ]]; then + JS_ENGINE_ARGS="--browser-arg=-private-window" + fi fi fi diff --git a/eng/testing/tests.browser.targets b/eng/testing/tests.browser.targets index ccfc96f5211cd1..26a2086c850b5c 100644 --- a/eng/testing/tests.browser.targets +++ b/eng/testing/tests.browser.targets @@ -250,9 +250,18 @@ <_NodeNpmModuleStringTrimmed Include="@(_NodeNpmModuleString->Trim(':'))" /> + WasmTestOnV8 @(_NodeNpmModuleStringTrimmed, ',') + + diff --git a/eng/testing/tests.wasi.targets b/eng/testing/tests.wasi.targets index d147fea218fe4a..989e934dd8412a 100644 --- a/eng/testing/tests.wasi.targets +++ b/eng/testing/tests.wasi.targets @@ -147,6 +147,13 @@ + + WasmTestOnWasmtime + + + diff --git a/eng/testing/wasm-provisioning.targets b/eng/testing/wasm-provisioning.targets index 47076a23770dd3..540fcfb035fa21 100644 --- a/eng/testing/wasm-provisioning.targets +++ b/eng/testing/wasm-provisioning.targets @@ -21,18 +21,30 @@ - - https://ftp.mozilla.org/pub/firefox/releases/$(linux_FirefoxRevision)/linux-x86_64/en-US/firefox-$(linux_FirefoxRevision).tar.bz2 - https://github.com/mozilla/geckodriver/releases/download/v$(linux_GeckoDriverRevision)/geckodriver-v$(linux_GeckoDriverRevision)-linux64.tar.gz - firefox - geckodriver + $(ArtifactsBinDir)firefox\ firefox geckodriver $(ArtifactsBinDir)geckodriver\ + + + https://ftp.mozilla.org/pub/firefox/releases/$(linux_FirefoxRevision)/linux-x86_64/en-US/firefox-$(linux_FirefoxRevision).tar.bz2 + https://github.com/mozilla/geckodriver/releases/download/v$(linux_GeckoDriverRevision)/geckodriver-v$(linux_GeckoDriverRevision)-linux64.tar.gz + firefox + geckodriver $([MSBuild]::NormalizePath($(FirefoxDir), '.install-firefox-$(linux_FirefoxRevision).stamp')) $([MSBuild]::NormalizePath($(GeckoDriverDir), '.install-geckodriver-$(linux_GeckoDriverRevision).stamp')) + $([MSBuild]::NormalizePath($(FirefoxDir), $(FirefoxDirName), $(FirefoxBinaryName))) + $([MSBuild]::NormalizePath($(GeckoDriverDir), $(GeckoDriverDirName), $(GeckoDriverBinaryName))) + + + https://ftp.mozilla.org/pub/firefox/releases/$(win_FirefoxRevision)/win64/en-US/Firefox%20Setup%20$(win_FirefoxRevision).exe + https://github.com/mozilla/geckodriver/releases/download/v$(win_GeckoDriverRevision)/geckodriver-v$(win_GeckoDriverRevision)-win64.zip + firefox.exe + geckodriver.exe + $([MSBuild]::NormalizePath($(FirefoxDir), '.install-firefox-$(win_FirefoxRevision).stamp')) + $([MSBuild]::NormalizePath($(GeckoDriverDir), '.install-geckodriver-$(win_GeckoDriverRevision).stamp')) $([MSBuild]::NormalizePath($(FirefoxDir), $(FirefoxDirName), $(FirefoxBinaryName))) $([MSBuild]::NormalizePath($(GeckoDriverDir), $(GeckoDriverDirName), $(GeckoDriverBinaryName))) @@ -183,7 +195,7 @@ export __SCRIPT_DIR=%24( cd -- "%24( dirname -- "%24{BASH_SOURCE[0]}" )" &> + Condition="!Exists($(FirefoxStampFile)) and '$(InstallFirefoxForTests)' == 'true'"> <_StampFile Include="$(_BrowserStampDir).install-firefox*.stamp" /> @@ -197,24 +209,22 @@ export __SCRIPT_DIR=%24( cd -- "%24( dirname -- "%24{BASH_SOURCE[0]}" )" &> - - - - - <_FirefoxBinaryPath>$([MSBuild]::NormalizePath($(FirefoxDir), $(FirefoxBinaryName))) - + + + + - + - + + Condition="!Exists($(GeckoDriverStampFile)) and '$(InstallFirefoxForTests)' == 'true'"> <_StampFile Include="$(_BrowserStampDir).install-geckodriver*.stamp" /> @@ -228,18 +238,15 @@ export __SCRIPT_DIR=%24( cd -- "%24( dirname -- "%24{BASH_SOURCE[0]}" )" &> - - - - - - <_GeckoDriverBinaryPath>$([MSBuild]::NormalizePath($(GeckoDriverDir), $(GeckoDriverBinaryName))) - + + + + - + - + diff --git a/src/libraries/Common/tests/System/Net/Configuration.Http.cs b/src/libraries/Common/tests/System/Net/Configuration.Http.cs index ae1481c56061c7..460b7893cc635d 100644 --- a/src/libraries/Common/tests/System/Net/Configuration.Http.cs +++ b/src/libraries/Common/tests/System/Net/Configuration.Http.cs @@ -58,12 +58,19 @@ public static partial class Http public static readonly Uri RemoteEchoServer = new Uri("http://" + Host + "/" + EchoHandler); public static readonly Uri SecureRemoteEchoServer = new Uri("https://" + SecureHost + "/" + EchoHandler); public static readonly Uri Http2RemoteEchoServer = new Uri("https://" + Http2Host + "/" + EchoHandler); - public static readonly Uri[] EchoServerList = new Uri[] { RemoteEchoServer, SecureRemoteEchoServer, Http2RemoteEchoServer }; + public static Uri[] GetEchoServerList() + { + if (PlatformDetection.IsFirefox) + { + // https://github.com/dotnet/runtime/issues/101115 + return [RemoteEchoServer]; + } + return [RemoteEchoServer, SecureRemoteEchoServer, Http2RemoteEchoServer]; + } public static readonly Uri RemoteVerifyUploadServer = new Uri("http://" + Host + "/" + VerifyUploadHandler); public static readonly Uri SecureRemoteVerifyUploadServer = new Uri("https://" + SecureHost + "/" + VerifyUploadHandler); public static readonly Uri Http2RemoteVerifyUploadServer = new Uri("https://" + Http2Host + "/" + VerifyUploadHandler); - public static readonly Uri[] VerifyUploadServerList = new Uri[] { RemoteVerifyUploadServer, SecureRemoteVerifyUploadServer, Http2RemoteVerifyUploadServer }; public static readonly Uri RemoteEmptyContentServer = new Uri("http://" + Host + "/" + EmptyContentHandler); public static readonly Uri RemoteDeflateServer = new Uri("http://" + Host + "/" + DeflateHandler); @@ -72,7 +79,7 @@ public static partial class Http public static readonly Uri Http2RemoteGZipServer = new Uri("https://" + Http2Host + "/" + GZipHandler); public static Uri RemoteLoopServer => new Uri("ws://" + RemoteLoopHost + "/" + RemoteLoopHandler); - public static readonly object[][] EchoServers = EchoServerList.Select(x => new object[] { x }).ToArray(); + public static readonly object[][] EchoServers = GetEchoServerList().Select(x => new object[] { x }).ToArray(); public static readonly object[][] VerifyUploadServers = { new object[] { RemoteVerifyUploadServer }, new object[] { SecureRemoteVerifyUploadServer }, new object[] { Http2RemoteVerifyUploadServer } }; public static readonly object[][] CompressedServers = { new object[] { RemoteDeflateServer }, new object[] { RemoteGZipServer }, new object[] { Http2RemoteDeflateServer }, new object[] { Http2RemoteGZipServer } }; @@ -83,9 +90,17 @@ public static partial class Http public static readonly RemoteServer RemoteSecureHttp11Server = new RemoteServer(new Uri("https://" + SecureHost + "/"), HttpVersion.Version11); public static readonly RemoteServer RemoteHttp2Server = new RemoteServer(new Uri("https://" + Http2Host + "/"), new Version(2, 0)); - public static readonly IEnumerable RemoteServers = new RemoteServer[] { RemoteHttp11Server, RemoteSecureHttp11Server, RemoteHttp2Server }; + public static IEnumerable GetRemoteServers() + { + if (PlatformDetection.IsFirefox) + { + // https://github.com/dotnet/runtime/issues/101115 + return new RemoteServer[] { RemoteHttp11Server }; + } + return new RemoteServer[] { RemoteHttp11Server, RemoteSecureHttp11Server, RemoteHttp2Server }; + } - public static readonly IEnumerable RemoteServersMemberData = RemoteServers.Select(s => new object[] { s }); + public static readonly IEnumerable RemoteServersMemberData = GetRemoteServers().Select(s => new object[] { s }); public sealed class RemoteServer { diff --git a/src/libraries/Common/tests/System/Net/Configuration.WebSockets.cs b/src/libraries/Common/tests/System/Net/Configuration.WebSockets.cs index a24512ce3b4a58..c5686be67b4ef9 100644 --- a/src/libraries/Common/tests/System/Net/Configuration.WebSockets.cs +++ b/src/libraries/Common/tests/System/Net/Configuration.WebSockets.cs @@ -22,8 +22,35 @@ public static partial class WebSockets public static readonly Uri RemoteEchoHeadersServer = new Uri("ws://" + Host + "/" + EchoHeadersHandler); public static readonly Uri SecureRemoteEchoHeadersServer = new Uri("wss://" + SecureHost + "/" + EchoHeadersHandler); - public static readonly object[][] EchoServers = { new object[] { RemoteEchoServer }, new object[] { SecureRemoteEchoServer } }; - public static readonly object[][] EchoHeadersServers = { new object[] { RemoteEchoHeadersServer }, new object[] { SecureRemoteEchoHeadersServer } }; + public static object[][] GetEchoServers() + { + if (PlatformDetection.IsFirefox) + { + // https://github.com/dotnet/runtime/issues/101115 + return new object[][] { + new object[] { RemoteEchoServer }, + }; + } + return new object[][] { + new object[] { RemoteEchoServer }, + new object[] { SecureRemoteEchoServer }, + }; + } + + public static object[][] GetEchoHeadersServers() + { + if (PlatformDetection.IsFirefox) + { + // https://github.com/dotnet/runtime/issues/101115 + return new object[][] { + new object[] { RemoteEchoHeadersServer }, + }; + } + return new object[][] { + new object[] { RemoteEchoHeadersServer }, + new object[] { SecureRemoteEchoHeadersServer }, + }; + } } } } diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Authentication.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Authentication.cs index b19c02b52ebc01..430cfeb2d47295 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Authentication.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Authentication.cs @@ -546,7 +546,7 @@ public static IEnumerable ServerUsesWindowsAuthentication_MemberData() public static IEnumerable EchoServersData() { - foreach (Uri serverUri in Configuration.Http.EchoServerList) + foreach (Uri serverUri in Configuration.Http.GetEchoServerList()) { yield return new object[] { serverUri }; } diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs index a264482a5549be..dd9db9bbe1f087 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs @@ -47,7 +47,7 @@ private static IEnumerable GetMethods(params string[] methods) { foreach (string method in methods) { - foreach (Uri serverUri in Configuration.Http.EchoServerList) + foreach (Uri serverUri in Configuration.Http.GetEchoServerList()) { yield return new object[] { method, serverUri }; } @@ -164,6 +164,7 @@ public async Task GetAsync_ServerNeedsAuthAndSetCredential_StatusCodeOK(Configur [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))] [Theory, MemberData(nameof(RemoteServersMemberData))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task GetAsync_ServerNeedsAuthAndNoCredential_StatusCodeUnauthorized(Configuration.Http.RemoteServer remoteServer) { using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer)) @@ -275,7 +276,7 @@ public static IEnumerable RemoteServersHeaderValuesAndUris() public static IEnumerable<(Configuration.Http.RemoteServer remoteServer, Uri uri)> RemoteServersAndHeaderEchoUris() { - foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers) + foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.GetRemoteServers()) { yield return (remoteServer, remoteServer.EchoUri); yield return (remoteServer, remoteServer.RedirectUriForDestinationUri( @@ -464,7 +465,7 @@ public static IEnumerable VerifyUploadServersStreamsAndExpectedData { get { - foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers) // target server + foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.GetRemoteServers()) // target server foreach (bool syncCopy in BoolValues) // force the content copy to happen via Read/Write or ReadAsync/WriteAsync { byte[] data = new byte[1234]; @@ -868,7 +869,7 @@ public async Task SendAsync_SendRequestUsingNoBodyMethodToEchoServerWithContent_ public static IEnumerable SendAsync_SendSameRequestMultipleTimesDirectlyOnHandler_Success_MemberData() { - foreach (var server in Configuration.Http.RemoteServers) + foreach (var server in Configuration.Http.GetRemoteServers()) { yield return new object[] { server, "12345678910", 0 }; yield return new object[] { server, "12345678910", 5 }; @@ -909,7 +910,7 @@ public async Task SendAsync_SendSameRequestMultipleTimesDirectlyOnHandler_Succes public static IEnumerable RemoteServersAndRedirectStatusCodes() { - foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers) + foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.GetRemoteServers()) { yield return new object[] { remoteServer, 300 }; yield return new object[] { remoteServer, 301 }; @@ -1228,7 +1229,7 @@ public async Task DefaultHeaders_SetCredentials_ClearedOnRedirect(Configuration. public static IEnumerable RemoteServersAndCompressionUris() { - foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers) + foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.GetRemoteServers()) { yield return new object[] { remoteServer, remoteServer.GZipUri }; @@ -1329,6 +1330,7 @@ public async Task GetAsync_SetAutomaticDecompression_HeadersRemoved(Configuratio [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))] [Theory] [MemberData(nameof(Http2Servers))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task SendAsync_RequestVersion20_ResponseVersion20IfHttp2Supported(Uri server) { // Sync API supported only up to HTTP/1.1 diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs index eca2101b78edbb..236af85b26035d 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs @@ -116,7 +116,7 @@ public async Task UseCallback_NotSecureConnection_CallbackNotCalled() public static IEnumerable UseCallback_ValidCertificate_ExpectedValuesDuringCallback_Urls() { - foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers) + foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.GetRemoteServers()) { if (remoteServer.IsSecure) { diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs index 0e6faffa6d1622..31d8d9f154fc4f 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs @@ -412,6 +412,7 @@ await LoopbackServer.CreateClientAndServerAsync(async uri => [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/86317", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task PostAsync_ManyDifferentRequestHeaders_SentCorrectly() { if (IsWinHttpHandler && UseVersion >= HttpVersion20.Value) @@ -826,6 +827,7 @@ await TestHelper.WhenAllCompletedOrAnyFailed( [InlineData("7gibberish")] // valid size then gibberish [InlineData("7\v\f")] // unacceptable whitespace [ActiveIssue("https://github.com/dotnet/runtime/issues/86317", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task GetAsync_InvalidChunkSize_ThrowsHttpRequestException(string chunkSize) { if (UseVersion != HttpVersion.Version11) @@ -859,6 +861,7 @@ await LoopbackServer.CreateServerAsync(async (server, url) => [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/86317", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task GetAsync_InvalidChunkTerminator_ThrowsHttpRequestException() { if (UseVersion != HttpVersion.Version11) @@ -888,6 +891,7 @@ await LoopbackServer.CreateClientAndServerAsync(async url => [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/86317", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task GetAsync_InfiniteChunkSize_ThrowsHttpRequestException() { if (UseVersion != HttpVersion.Version11) @@ -1011,9 +1015,9 @@ public async Task ReadAsStreamAsync_HandlerProducesWellBehavedResponseStream(boo return; } - if (enableWasmStreaming && !PlatformDetection.IsBrowser) + if (enableWasmStreaming && !PlatformDetection.IsChromium) { - // enableWasmStreaming makes only sense on Browser platform + // enableWasmStreaming makes only sense on Chrome return; } @@ -1331,7 +1335,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => server => server.AcceptConnectionSendResponseAndCloseAsync()); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsChromium))] [ActiveIssue("https://github.com/dotnet/runtime/issues/65429", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] public async Task ReadAsStreamAsync_StreamingCancellation() { @@ -1425,6 +1429,7 @@ await server.AcceptConnectionAsync(async connection => } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task Dispose_DisposingHandlerCancelsActiveOperationsWithoutResponses() { if (IsWinHttpHandler && UseVersion >= HttpVersion20.Value) diff --git a/src/libraries/Common/tests/System/Net/Http/PostScenarioTest.cs b/src/libraries/Common/tests/System/Net/Http/PostScenarioTest.cs index 488f00639cb0ad..6f465ff0e998c5 100644 --- a/src/libraries/Common/tests/System/Net/Http/PostScenarioTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/PostScenarioTest.cs @@ -135,7 +135,7 @@ public async Task PostUsingNoSpecifiedSemantics_UsesChunkedSemantics(Configurati public static IEnumerable RemoteServersAndLargeContentSizes() { - foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers) + foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.GetRemoteServers()) { yield return new object[] { remoteServer, 5 * 1024 }; yield return new object[] { remoteServer, 63 * 1024 }; diff --git a/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs b/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs index e38204ffc031e3..aaa4b9c9b1c3a8 100644 --- a/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs @@ -21,7 +21,7 @@ public ResponseStreamTest(ITestOutputHelper output) : base(output) { } public static IEnumerable RemoteServersAndReadModes() { - foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers) + foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.GetRemoteServers()) { for (int i = 0; i < 8; i++) { @@ -230,7 +230,7 @@ await client.GetAsync(remoteServer.EchoUri, HttpCompletionOption.ResponseHeaders #if NETCOREAPP - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsChromium))] public async Task BrowserHttpHandler_Streaming() { var WebAssemblyEnableStreamingRequestKey = new HttpRequestOptionsKey("WebAssemblyEnableStreamingRequest"); @@ -287,7 +287,7 @@ public async Task BrowserHttpHandler_Streaming() } [OuterLoop] - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsChromium))] public async Task BrowserHttpHandler_StreamingRequest() { var WebAssemblyEnableStreamingRequestKey = new HttpRequestOptionsKey("WebAssemblyEnableStreamingRequest"); @@ -330,7 +330,7 @@ public async Task BrowserHttpHandler_StreamingRequest() // Duplicate of PostAsync_ThrowFromContentCopy_RequestFails using remote server [OuterLoop] - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsChromium))] [InlineData(false)] [InlineData(true)] public async Task BrowserHttpHandler_StreamingRequest_ThrowFromContentCopy_RequestFails(bool syncFailure) @@ -368,7 +368,7 @@ public static TheoryData CancelRequestReadFunctions }; [OuterLoop] - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsChromium))] [MemberData(nameof(CancelRequestReadFunctions))] public async Task BrowserHttpHandler_StreamingRequest_CancelRequest(bool cancelAsync, Func> readFunc) { @@ -438,7 +438,7 @@ public async Task BrowserHttpHandler_StreamingRequest_Http1Fails() } [OuterLoop] - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsChromium))] public async Task BrowserHttpHandler_StreamingResponse() { var WebAssemblyEnableStreamingResponseKey = new HttpRequestOptionsKey("WebAssemblyEnableStreamingResponse"); @@ -477,6 +477,7 @@ public async Task BrowserHttpHandler_StreamingResponse() [InlineData(TransferType.ContentLength, TransferError.ContentLengthTooLarge)] [InlineData(TransferType.Chunked, TransferError.MissingChunkTerminator)] [InlineData(TransferType.Chunked, TransferError.ChunkSizeTooLarge)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task ReadAsStreamAsync_InvalidServerResponse_ThrowsIOException( TransferType transferType, TransferError transferError) diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs index 4807d9de7842cd..cbd74f8188a20f 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs @@ -26,6 +26,7 @@ public HttpClientHandlerTest_Headers(ITestOutputHelper output) : base(output) { private sealed class DerivedHttpHeaders : HttpHeaders { } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task SendAsync_RequestWithSimpleHeader_ResponseReferencesUnmodifiedRequestHeaders() { const string HeaderKey = "some-header-123", HeaderValue = "this is the expected header value"; @@ -73,6 +74,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task SendAsync_LargeHeaders_CorrectlyWritten() { if (UseVersion == HttpVersion.Version30) @@ -108,6 +110,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task SendAsync_DefaultHeaders_CorrectlyWritten() { const string Version = "2017-04-17"; @@ -169,6 +172,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => [InlineData("Accept-CharSet", "text/plain, text/json", false)] // invalid format for header but added with TryAddWithoutValidation [InlineData("Content-Location", "", false)] // invalid format for header but added with TryAddWithoutValidation [InlineData("Max-Forwards", "NotAnInteger", false)] // invalid format for header but added with TryAddWithoutValidation + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task SendAsync_SpecialHeaderKeyOrValue_Success(string key, string value, bool parsable) { if (PlatformDetection.IsBrowser && (key == "Content-Location" || key == "Date" || key == "Accept-CharSet")) @@ -356,6 +360,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => [Theory] [InlineData(false)] [InlineData(true)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task SendAsync_GetWithValidHostHeader_Success(bool withPort) { if (UseVersion == HttpVersion.Version30) diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http1.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http1.cs index b3949e548e7ccc..b57e3812784599 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http1.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http1.cs @@ -17,6 +17,7 @@ public class HttpClientHandlerTest_Http1 : HttpClientHandlerTestBase public HttpClientHandlerTest_Http1(ITestOutputHelper output) : base(output) { } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotNodeJS))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task SendAsync_HostHeader_First() { // RFC 7230 3.2.2. Field Order diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpRequestMessageTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpRequestMessageTest.cs index 0dd1a485894d6b..d62566f1dd1b4a 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpRequestMessageTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpRequestMessageTest.cs @@ -239,6 +239,7 @@ public void ToString_DefaultAndNonDefaultInstance_DumpAllFields() [InlineData("OPTIONS")] [InlineData("HEAD")] [ActiveIssue("https://github.com/dotnet/runtime/issues/86317", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task HttpRequest_BodylessMethod_NoContentLength(string method) { using (HttpClient client = CreateHttpClient()) diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs index c0eda6ab1a57ed..67604ca426e798 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs @@ -3994,6 +3994,7 @@ public SocketsHttpHandlerTest_HttpClientHandlerTest_Headers_Http11(ITestOutputHe [InlineData("foo", "\tbar\t")] [InlineData("foo", "\t bar \t")] [InlineData("foo ", " \t bar \r\n ")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task ResponseHeaders_ExtraWhitespace_Trimmed(string name, string value) { await LoopbackServer.CreateClientAndServerAsync(async uri => diff --git a/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs b/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs index 0c8b94778a58ea..0dc1775b573454 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs @@ -15,18 +15,13 @@ namespace System.Net.WebSockets.Client.Tests { public class ClientWebSocketTestBase { - public static readonly object[][] EchoServers = System.Net.Test.Common.Configuration.WebSockets.EchoServers; - public static readonly object[][] EchoHeadersServers = System.Net.Test.Common.Configuration.WebSockets.EchoHeadersServers; + public static readonly object[][] EchoServers = System.Net.Test.Common.Configuration.WebSockets.GetEchoServers(); + public static readonly object[][] EchoHeadersServers = System.Net.Test.Common.Configuration.WebSockets.GetEchoHeadersServers(); public static readonly object[][] EchoServersAndBoolean = EchoServers.SelectMany(o => new object[][] { new object[] { o[0], false }, new object[] { o[0], true } }).ToArray(); - public static readonly object[][] SecureEchoServersAndBoolean = new object[][] - { - new object[] { Test.Common.Configuration.WebSockets.SecureRemoteEchoServer, false }, - new object[] { Test.Common.Configuration.WebSockets.SecureRemoteEchoServer, true } - }; public const int TimeOutMilliseconds = 30000; public const int CloseDescriptionMaxLength = 123; diff --git a/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs b/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs index 7f44a7a69349a6..cb5f0f978f761e 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs @@ -254,6 +254,7 @@ public async Task ConnectAsync_CookieHeaders_Success(Uri server) [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))] [ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoServers))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task ConnectAsync_PassNoSubProtocol_ServerRequires_ThrowsWebSocketException(Uri server) { const string AcceptedProtocol = "CustomProtocol"; diff --git a/src/libraries/System.Net.WebSockets/tests/WebSocketCreateTest.cs b/src/libraries/System.Net.WebSockets/tests/WebSocketCreateTest.cs index f8323a20332027..988f8e4eaaa92b 100644 --- a/src/libraries/System.Net.WebSockets/tests/WebSocketCreateTest.cs +++ b/src/libraries/System.Net.WebSockets/tests/WebSocketCreateTest.cs @@ -344,7 +344,7 @@ private static async Task CreateWebSocketStream(Uri echoUri, Socket clie return stream; } - public static readonly object[][] EchoServers = System.Net.Test.Common.Configuration.WebSockets.EchoServers; + public static readonly object[][] EchoServers = System.Net.Test.Common.Configuration.WebSockets.GetEchoServers(); public static readonly object[][] EchoServersAndBoolean = EchoServers.SelectMany(o => new object[][] { new object[] { o[0], false }, diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoNativeCalendarName.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoNativeCalendarName.cs index 86507dc1308f11..377e6d30d597bc 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoNativeCalendarName.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoNativeCalendarName.cs @@ -11,10 +11,10 @@ public class DateTimeFormatInfoNativeCalendarName public static IEnumerable NativeCalendarName_Get_TestData_HybridGlobalization() { // see the comments on the right to check the non-Hybrid result, in this collection it always differs - string islamicName = "islamic-umalqura"; - string gregorianName = "gregory"; - string persianName = "persian"; - string bhuddistName = "buddhist"; + string islamicName = PlatformDetection.IsFirefox ? "UMALQURA" : "islamic-umalqura"; + string gregorianName = PlatformDetection.IsFirefox ? "GREGORIAN" : "gregory"; + string persianName = PlatformDetection.IsFirefox ? "PERSIAN" : "persian"; + string bhuddistName = PlatformDetection.IsFirefox ? "THAI" : "buddhist"; yield return new object[] { new CultureInfo("ar-SA").DateTimeFormat, islamicName }; // التقويم الإسلامي (أم القرى) yield return new object[] { new CultureInfo("am-ET").DateTimeFormat, gregorianName }; // የግሪጎሪያን የቀን አቆጣጠር yield return new object[] { new CultureInfo("bg-BG").DateTimeFormat, gregorianName }; // григориански календар diff --git a/src/libraries/sendtohelix-browser.targets b/src/libraries/sendtohelix-browser.targets index 8b9a4194565772..393b4dd38f1ff2 100644 --- a/src/libraries/sendtohelix-browser.targets +++ b/src/libraries/sendtohelix-browser.targets @@ -32,7 +32,8 @@ <_ShippingPackagesPath>$([MSBuild]::NormalizeDirectory($(ArtifactsDir), 'packages', $(Configuration), 'Shipping')) - $(Scenario)- + $(Scenario)-ST- + $(Scenario)-MT- true - - - - @@ -112,10 +109,6 @@ - - - - @@ -182,7 +175,13 @@ - + <_WasmSampleZipFile Condition="'$(Scenario)' == 'WasmTestOnV8'" Include="$(TestArchiveRoot)runonly/**/*.Console.V8.*.Sample.zip" /> - <_WasmSampleZipFile Condition="'$(Scenario)' == 'WasmTestOnNodeJS'" Include="$(TestArchiveRoot)runonly/**/*.Console.Node.*.Sample.zip" /> + <_WasmSampleZipFile Condition="'$(Scenario)' == 'WasmTestOnNodeJS'" Include="$(TestArchiveRoot)runonly/**/*.Console.Node.*.Sample.zip" /> <_WasmSampleZipFile Condition="'$(Scenario)' == 'WasmTestOnChrome'" Include="$(TestArchiveRoot)runonly/**/*.Browser.*.Sample.zip" /> + - + %(Identity) $(HelixCommand) $(_workItemTimeout) diff --git a/src/libraries/sendtohelix-wasi.targets b/src/libraries/sendtohelix-wasi.targets index f89da35e17e3e8..e634fa0c2ea3f8 100644 --- a/src/libraries/sendtohelix-wasi.targets +++ b/src/libraries/sendtohelix-wasi.targets @@ -104,6 +104,10 @@ + + diff --git a/src/libraries/sendtohelix-wasm.targets b/src/libraries/sendtohelix-wasm.targets index d9c2e3aead0845..10dc71976f62b8 100644 --- a/src/libraries/sendtohelix-wasm.targets +++ b/src/libraries/sendtohelix-wasm.targets @@ -31,6 +31,8 @@ Workloads- NoWorkload- $(WorkItemPrefix)NoWebcil- + $(WorkItemPrefix)ST- + $(WorkItemPrefix)MT- diff --git a/src/mono/browser/runtime/hybrid-globalization/locales.ts b/src/mono/browser/runtime/hybrid-globalization/locales.ts index da6a478d1e3931..0f04519efdfd32 100644 --- a/src/mono/browser/runtime/hybrid-globalization/locales.ts +++ b/src/mono/browser/runtime/hybrid-globalization/locales.ts @@ -37,12 +37,12 @@ export function mono_wasm_get_locale_info (culture: number, cultureLength: numbe const language = localeParts.join("-"); languageName = new Intl.DisplayNames([cultureName], { type: "language" }).of(language); } catch (error) { - if (error instanceof RangeError && error.message === "invalid_argument") { + if (error instanceof RangeError) { // if it failed from this reason then cultureName is in a form "language-script", without region try { languageName = new Intl.DisplayNames([cultureName], { type: "language" }).of(localeName); } catch (error) { - if (error instanceof RangeError && error.message === "invalid_argument" && localeNameOriginal) { + if (error instanceof RangeError && localeNameOriginal) { // handle non-standard or malformed locales by forwarding the locale code, e.g. "xx-u-xx" stringToUTF16(dst, dst + 2 * localeNameOriginal.length, localeNameOriginal); setI32(dstLength, localeNameOriginal.length); @@ -113,8 +113,8 @@ function getFirstDayOfWeek (locale: string) { if (saturdayLocales.includes(locale)) { return 6; } - const sundayLanguages = ["zh", "th", "pt", "mr", "ml", "ko", "kn", "ja", "id", "hi", "he", "gu", "fil", "bn", "am", "ar"]; - const sundayLocales = ["ta-SG", "ta-IN", "sw-KE", "ms-SG", "fr-CA", "es-MX", "en-US", "en-ZW", "en-ZA", "en-WS", "en-VI", "en-UM", "en-TT", "en-SG", "en-PR", "en-PK", "en-PH", "en-MT", "en-MO", "en-MH", "en-KE", "en-JM", "en-IN", "en-IL", "en-HK", "en-GU", "en-DM", "en-CA", "en-BZ", "en-BW", "en-BS", "en-AU", "en-AS", "en-AG"]; + const sundayLanguages = ["th", "pt", "mr", "ml", "ko", "kn", "ja", "id", "hi", "he", "gu", "fil", "bn", "am", "ar", "te"]; + const sundayLocales = ["ta-SG", "ta-IN", "sw-KE", "ms-SG", "fr-CA", "es-MX", "en-US", "en-ZW", "en-ZA", "en-WS", "en-VI", "en-UM", "en-TT", "en-SG", "en-PR", "en-PK", "en-PH", "en-MT", "en-MO", "en-MH", "en-KE", "en-JM", "en-IN", "en-IL", "en-HK", "en-GU", "en-DM", "en-CA", "en-BZ", "en-BW", "en-BS", "en-AS", "en-AG", "zh-Hans-HK", "zh-SG", "zh-HK", "zh-TW"]; // "en-AU" is Monday in chrome, so firefox should be in line const localeLang = locale.split("-")[0]; if (sundayLanguages.includes(localeLang) || sundayLocales.includes(locale)) { return 0; @@ -134,8 +134,8 @@ function getFirstWeekOfYear (locale: string) { } // Firefox does not support it rn but we can make a temporary workaround for it, // that should be removed when it starts being supported: - const firstFourDayWeekLocales = ["pt-PT", "fr-CH", "fr-FR", "fr-BE", "es-ES", "en-SE", "en-NL", "en-JE", "en-IM", "en-IE", "en-GI", "en-GG", "en-GB", "en-FJ", "en-FI", "en-DK", "en-DE", "en-CH", "en-BE", "en-AT", "el-GR"]; - const firstFourDayWeekLanguages = ["sv", "sk", "ru", "pl", "nl", "no", "lt", "it", "hu", "fi", "et", "de", "da", "cs", "ca", "bg"]; + const firstFourDayWeekLocales = ["pt-PT", "fr-CH", "fr-FR", "fr-BE", "es-ES", "en-SE", "en-NL", "en-JE", "en-IM", "en-IE", "en-GI", "en-GG", "en-GB", "en-FJ", "en-FI", "en-DK", "en-DE", "en-CH", "en-BE", "en-AT", "el-GR", "nl-BE", "nl-NL"]; + const firstFourDayWeekLanguages = ["sv", "sk", "ru", "pl", "no", "nb", "lt", "it", "hu", "fi", "et", "de", "da", "cs", "ca", "bg"]; const localeLang = locale.split("-")[0]; if (firstFourDayWeekLocales.includes(locale) || firstFourDayWeekLanguages.includes(localeLang)) { return 2; diff --git a/src/mono/sample/Directory.Build.props b/src/mono/sample/Directory.Build.props index 8780899630286b..2d5011ce41f881 100644 --- a/src/mono/sample/Directory.Build.props +++ b/src/mono/sample/Directory.Build.props @@ -5,14 +5,22 @@ true + - $HARNESS_RUNNER - $XHARNESS_OUT + $HARNESS_RUNNER + $XHARNESS_OUT + $XHARNESS_COMMAND + $XHARNESS_ARGS - - %HARNESS_RUNNER% - %XHARNESS_OUT% + %HARNESS_RUNNER% + %XHARNESS_OUT% + %XHARNESS_COMMAND% + %XHARNESS_ARGS% diff --git a/src/mono/sample/wasm/DefaultBrowserSample.targets b/src/mono/sample/wasm/DefaultBrowserSample.targets index d34e280cf19c6d..af224ce9c48af3 100644 --- a/src/mono/sample/wasm/DefaultBrowserSample.targets +++ b/src/mono/sample/wasm/DefaultBrowserSample.targets @@ -7,7 +7,7 @@ -1 true $(WasmXHarnessArgs) --web-server-use-cop - $(ExecXHarnessCmd) wasm test-browser --app=. --browser=Chrome $(XHarnessBrowserPathArg) $(WasmXHarnessArgs) --html-file=index.html --output-directory=$(XHarnessOutput) -- $(MSBuildProjectName).dll + $(ExecXHarnessVar) wasm $(XHarnessCommandVar) --app=. $(XHarnessBrowserPathArg) $(WasmXHarnessArgsVar) $(WasmXHarnessArgs) --html-file=index.html --output-directory=$(XHarnessOutputVar) -- $(MSBuildProjectName).dll true $(TestArchiveRoot)chromeonly/ $(TestArchiveTestsRoot)$(OSPlatformConfig)/ diff --git a/src/mono/sample/wasm/console-node/Wasm.Console.Node.Sample.csproj b/src/mono/sample/wasm/console-node/Wasm.Console.Node.Sample.csproj index 7234698ff22837..995e1d3650e2ca 100644 --- a/src/mono/sample/wasm/console-node/Wasm.Console.Node.Sample.csproj +++ b/src/mono/sample/wasm/console-node/Wasm.Console.Node.Sample.csproj @@ -6,7 +6,7 @@ true 2 - $(ExecXHarnessCmd) wasm test --app=. --engine=NodeJS --engine-arg=--stack-trace-limit=1000 --js-file=main.mjs --output-directory=$(XHarnessOutput) --expected-exit-code $(ExpectedExitCode) + $(ExecXHarnessVar) wasm test --app=. --engine=NodeJS --engine-arg=--stack-trace-limit=1000 --js-file=main.mjs --output-directory=$(XHarnessOutputVar) --expected-exit-code $(ExpectedExitCode) diff --git a/src/mono/sample/wasm/console-v8/Wasm.Console.V8.Sample.csproj b/src/mono/sample/wasm/console-v8/Wasm.Console.V8.Sample.csproj index 13ed38bfe63e4c..09e9f7bf1a0d2d 100644 --- a/src/mono/sample/wasm/console-v8/Wasm.Console.V8.Sample.csproj +++ b/src/mono/sample/wasm/console-v8/Wasm.Console.V8.Sample.csproj @@ -5,7 +5,7 @@ true true - $(ExecXHarnessCmd) wasm test --app=. --engine=V8 --engine-arg=--stack-trace-limit=1000 --engine-arg=--module --js-file=main.mjs --output-directory=$(XHarnessOutput) -- --run $(MSBuildProjectName).dll + $(ExecXHarnessVar) wasm test --app=. --engine=V8 --engine-arg=--stack-trace-limit=1000 --engine-arg=--module --js-file=main.mjs --output-directory=$(XHarnessOutputVar) -- --run $(MSBuildProjectName).dll From d0dffe1dcfc6dbc9208546ffcb39aa9e6945e783 Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Thu, 25 Apr 2024 14:59:01 +0200 Subject: [PATCH 104/248] [WASI] update WASI SDK to 22 and wasmtime to 19.0.2 (#101392) --- Directory.Build.props | 2 ++ eng/native/gen-buildsys.cmd | 2 +- eng/testing/tests.wasi.targets | 2 +- src/mono/Directory.Build.props | 8 +++++--- src/mono/mono.proj | 2 +- src/mono/mono/tools/offsets-tool/offsets-tool.py | 4 +++- src/mono/wasi/wasi-sdk-version.txt | 2 +- src/mono/wasi/wasi.proj | 2 +- src/mono/wasi/wasmtime-version.txt | 2 +- src/native/libs/Common/pal_error_common.h | 4 ++++ .../System.Globalization.Native/pal_localeNumberData.c | 5 +++++ src/native/libs/System.Native/pal_io.c | 6 ++++++ 12 files changed, 31 insertions(+), 10 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 40c75f103b8be8..c6bae2a825b1bf 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -184,7 +184,9 @@ $([MSBuild]::NormalizePath('$(TestExclusionListTasksDir)', 'TestExclusionListTasks.dll')) $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'coreclr', '$(TargetOS).$(TargetArchitecture).$(RuntimeConfiguration)')) $(CoreCLRToolPath) + $([MSBuild]::NormalizeDirectory($(ArtifactsObjDir), 'wasmtime')) true $([MSBuild]::NormalizeDirectory($(WasmProjectRoot), 'build')) diff --git a/eng/native/gen-buildsys.cmd b/eng/native/gen-buildsys.cmd index f67f17b8d47942..79db6bffae062d 100644 --- a/eng/native/gen-buildsys.cmd +++ b/eng/native/gen-buildsys.cmd @@ -62,7 +62,7 @@ if /i "%__Arch%" == "wasm" ( if /i "%__Os%" == "wasi" ( if "%WASI_SDK_PATH%" == "" ( if not exist "%__repoRoot%\src\mono\wasi\wasi-sdk" ( - echo Error: Should set WASI_SDK_PATH environment variable pointing to emsdk root. + echo Error: Should set WASI_SDK_PATH environment variable pointing to WASI SDK root. exit /B 1 ) diff --git a/eng/testing/tests.wasi.targets b/eng/testing/tests.wasi.targets index 989e934dd8412a..e8f75ee3821bc5 100644 --- a/eng/testing/tests.wasi.targets +++ b/eng/testing/tests.wasi.targets @@ -46,7 +46,7 @@ <_XHarnessArgs Condition="'$(IsFunctionalTest)' == 'true'" >$(_XHarnessArgs) --expected-exit-code=$(ExpectedExitCode) <_XHarnessArgs Condition="'$(WasmXHarnessArgs)' != ''" >$(_XHarnessArgs) $(WasmXHarnessArgs) <_XHarnessArgs Condition="'$(WasmXHarnessTestsTimeout)' != ''" >$(_XHarnessArgs) "--timeout=$(WasmXHarnessTestsTimeout)" - <_XHarnessArgs >$(_XHarnessArgs) --engine-arg=--max-wasm-stack=134217728 + <_XHarnessArgs >$(_XHarnessArgs) --engine-arg=-W --engine-arg=max-wasm-stack=134217728 <_XHarnessArgs Condition="'$(WasmXHarnessArgsCli)' != ''" >$(_XHarnessArgs) $(WasmXHarnessArgsCli) <_InvariantGlobalization Condition="'$(InvariantGlobalization)' == 'true'">--env=DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true diff --git a/src/mono/Directory.Build.props b/src/mono/Directory.Build.props index 12d6fdb34cfc57..d97bf84a1da660 100644 --- a/src/mono/Directory.Build.props +++ b/src/mono/Directory.Build.props @@ -34,10 +34,12 @@ - <_ProvisionWasiSdkDir>$([MSBuild]::NormalizeDirectory($(MSBuildThisFileDirectory), 'wasi', 'wasi-sdk')) - true - $(_ProvisionWasiSdkDir) + + $([MSBuild]::NormalizeDirectory($(MSBuildThisFileDirectory), 'wasi', 'wasi-sdk')) $([MSBuild]::EnsureTrailingSlash('$(WASI_SDK_PATH)').Replace('\', '/')) + true diff --git a/src/mono/mono.proj b/src/mono/mono.proj index 47eeb0937a88fa..0d855362d99211 100644 --- a/src/mono/mono.proj +++ b/src/mono/mono.proj @@ -797,7 +797,7 @@ - + - + https://github.com/dotnet/emsdk - 9d28301f6a5f512db14f242f7403a4bfbcbcc8a4 + 53288f87c588907e8ff01f129786820fe998573c diff --git a/eng/Versions.props b/eng/Versions.props index 5e732a3a2e1871..0fb3f86bcf6fe6 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -235,9 +235,9 @@ Note: when the name is updated, make sure to update dependency name in eng/pipelines/common/xplat-setup.yml like - DarcDependenciesChanged.Microsoft_NET_Workload_Emscripten_Current_Manifest-9_0_100_Transport --> - 9.0.0-preview.4.24222.2 + 9.0.0-preview.5.24223.2 $(MicrosoftNETWorkloadEmscriptenCurrentManifest90100TransportVersion) - 9.0.0-preview.4.24222.2 + 9.0.0-preview.5.24223.2 1.1.87-gba258badda 1.0.0-v3.14.0.5722 From e1bda8a765a5dd3e7ea1e9dfeafa7fe44ae486aa Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 20:45:29 -0500 Subject: [PATCH 124/248] [main] Update dependencies from dotnet/cecil, dotnet/hotreload-utils, dotnet/icu, dotnet/runtime, dotnet/runtime-assets, dotnet/sdk, dotnet/xharness (#101378) * Update dependencies from https://github.com/dotnet/runtime build 20240419.3 Microsoft.DotNet.ILCompiler , Microsoft.NET.Sdk.IL , Microsoft.NETCore.App.Runtime.win-x64 , Microsoft.NETCore.ILAsm , runtime.native.System.IO.Ports , System.Reflection.Metadata , System.Reflection.MetadataLoadContext , System.Text.Json , Microsoft.SourceBuild.Intermediate.runtime.linux-x64 From Version 9.0.0-preview.4.24215.1 -> To Version 9.0.0-preview.4.24219.3 * Update dependencies from https://github.com/dotnet/sdk build 20240421.4 Microsoft.SourceBuild.Intermediate.sdk , Microsoft.DotNet.ApiCompat.Task From Version 9.0.100-preview.4.24215.1 -> To Version 9.0.100-preview.4.24221.4 * Update dependencies from https://github.com/dotnet/icu build 20240422.1 Microsoft.NETCore.Runtime.ICU.Transport From Version 9.0.0-preview.4.24215.1 -> To Version 9.0.0-preview.4.24222.1 * Update dependencies from https://github.com/dotnet/xharness build 20240422.1 Microsoft.DotNet.XHarness.CLI , Microsoft.DotNet.XHarness.TestRunners.Common , Microsoft.DotNet.XHarness.TestRunners.Xunit From Version 9.0.0-prerelease.24208.1 -> To Version 9.0.0-prerelease.24222.1 * Update dependencies from https://github.com/dotnet/runtime-assets build 20240422.1 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 9.0.0-beta.24215.1 -> To Version 9.0.0-beta.24222.1 * Update dependencies from https://github.com/dotnet/hotreload-utils build 20240422.1 Microsoft.DotNet.HotReload.Utils.Generator.BuildTool From Version 9.0.0-alpha.0.24215.1 -> To Version 9.0.0-alpha.0.24222.1 * Update dependencies from https://github.com/dotnet/cecil build 20240422.1 Microsoft.SourceBuild.Intermediate.cecil , Microsoft.DotNet.Cecil From Version 0.11.4-alpha.24215.1 -> To Version 0.11.4-alpha.24222.1 * Fix Enum constraint mismatches * More mismatches * INumber constraint * Update dependencies from https://github.com/dotnet/icu build 20240423.2 Microsoft.NETCore.Runtime.ICU.Transport From Version 9.0.0-preview.4.24215.1 -> To Version 9.0.0-preview.5.24223.2 * Update dependencies from https://github.com/dotnet/xharness build 20240422.1 Microsoft.DotNet.XHarness.CLI , Microsoft.DotNet.XHarness.TestRunners.Common , Microsoft.DotNet.XHarness.TestRunners.Xunit From Version 9.0.0-prerelease.24208.1 -> To Version 9.0.0-prerelease.24222.1 * Update dependencies from https://github.com/dotnet/runtime-assets build 20240422.1 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 9.0.0-beta.24215.1 -> To Version 9.0.0-beta.24222.1 * Update dependencies from https://github.com/dotnet/hotreload-utils build 20240422.1 Microsoft.DotNet.HotReload.Utils.Generator.BuildTool From Version 9.0.0-alpha.0.24215.1 -> To Version 9.0.0-alpha.0.24222.1 * Update dependencies from https://github.com/dotnet/cecil build 20240422.1 Microsoft.SourceBuild.Intermediate.cecil , Microsoft.DotNet.Cecil From Version 0.11.4-alpha.24215.1 -> To Version 0.11.4-alpha.24222.1 * Fix issues with missing generic constraints * Remove constraint from Enum.TryFormat ref * Update ApiCompat suppression files * Update dependencies from https://github.com/dotnet/icu build 20240423.2 Microsoft.NETCore.Runtime.ICU.Transport From Version 9.0.0-preview.4.24215.1 -> To Version 9.0.0-preview.5.24223.2 * Update dependencies from https://github.com/dotnet/xharness build 20240424.1 Microsoft.DotNet.XHarness.CLI , Microsoft.DotNet.XHarness.TestRunners.Common , Microsoft.DotNet.XHarness.TestRunners.Xunit From Version 9.0.0-prerelease.24208.1 -> To Version 9.0.0-prerelease.24224.1 * Update dependencies from https://github.com/dotnet/runtime-assets build 20240422.1 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 9.0.0-beta.24215.1 -> To Version 9.0.0-beta.24222.1 * Update dependencies from https://github.com/dotnet/hotreload-utils build 20240422.1 Microsoft.DotNet.HotReload.Utils.Generator.BuildTool From Version 9.0.0-alpha.0.24215.1 -> To Version 9.0.0-alpha.0.24222.1 * Update dependencies from https://github.com/dotnet/cecil build 20240422.1 Microsoft.SourceBuild.Intermediate.cecil , Microsoft.DotNet.Cecil From Version 0.11.4-alpha.24215.1 -> To Version 0.11.4-alpha.24222.1 --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Jan Kotas Co-authored-by: Eric StJohn --- .config/dotnet-tools.json | 2 +- eng/Version.Details.xml | 128 +++--- eng/Versions.props | 56 +-- global.json | 2 +- .../src/CompatibilitySuppressions.xml | 1 + ...em.Diagnostics.DiagnosticSourceActivity.cs | 2 +- ....Private.CoreLib.ManualShimTypeForwards.cs | 2 +- .../System.Private.CoreLib/src/System/Enum.cs | 2 +- .../ref/System.Runtime.InteropServices.cs | 6 +- .../src/CompatibilitySuppressions.xml | 1 + ...iCompatBaseline.NetCoreAppLatestStable.xml | 60 +++ .../ApiCompatBaseline.netstandard2.0.xml | 378 ++++++++++++++++++ .../ApiCompatBaseline.netstandard2.1.xml | 126 ++++++ 13 files changed, 666 insertions(+), 100 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 78d06c501e8835..1315a20dd66bec 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "9.0.0-prerelease.24208.1", + "version": "9.0.0-prerelease.24224.1", "commands": [ "xharness" ] diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 627f374cb45637..c35213b8ecadb5 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/icu - 0ea0175965771285846b5d077bebe5946036a595 + 88c4ff85536a2397ba3945dd4a7cdc860c584914 https://github.com/dotnet/msquic @@ -58,14 +58,14 @@ a045dd54a4c44723c215d992288160eb1401bb7f - + https://github.com/dotnet/cecil - 861f49c137941b9722a43e5993ccac7716c8528c + 4abe3e63a5d4653ca098c633644432c1395411c1 - + https://github.com/dotnet/cecil - 861f49c137941b9722a43e5993ccac7716c8528c + 4abe3e63a5d4653ca098c633644432c1395411c1 @@ -174,57 +174,57 @@ https://github.com/dotnet/arcade b4f4d40741f161e2c0d96c19c51a4013850ef65f - + https://github.com/dotnet/runtime-assets - 30b6a8d9d3af5681e4caef1ea453619a4b0e9f2e + 6e78861f1f307cd9f0e64a45b1d7884fa4470930 - + https://github.com/dotnet/runtime-assets - 30b6a8d9d3af5681e4caef1ea453619a4b0e9f2e + 6e78861f1f307cd9f0e64a45b1d7884fa4470930 - + https://github.com/dotnet/runtime-assets - 30b6a8d9d3af5681e4caef1ea453619a4b0e9f2e + 6e78861f1f307cd9f0e64a45b1d7884fa4470930 - + https://github.com/dotnet/runtime-assets - 30b6a8d9d3af5681e4caef1ea453619a4b0e9f2e + 6e78861f1f307cd9f0e64a45b1d7884fa4470930 - + https://github.com/dotnet/runtime-assets - 30b6a8d9d3af5681e4caef1ea453619a4b0e9f2e + 6e78861f1f307cd9f0e64a45b1d7884fa4470930 - + https://github.com/dotnet/runtime-assets - 30b6a8d9d3af5681e4caef1ea453619a4b0e9f2e + 6e78861f1f307cd9f0e64a45b1d7884fa4470930 - + https://github.com/dotnet/runtime-assets - 30b6a8d9d3af5681e4caef1ea453619a4b0e9f2e + 6e78861f1f307cd9f0e64a45b1d7884fa4470930 - + https://github.com/dotnet/runtime-assets - 30b6a8d9d3af5681e4caef1ea453619a4b0e9f2e + 6e78861f1f307cd9f0e64a45b1d7884fa4470930 - + https://github.com/dotnet/runtime-assets - 30b6a8d9d3af5681e4caef1ea453619a4b0e9f2e + 6e78861f1f307cd9f0e64a45b1d7884fa4470930 - + https://github.com/dotnet/runtime-assets - 30b6a8d9d3af5681e4caef1ea453619a4b0e9f2e + 6e78861f1f307cd9f0e64a45b1d7884fa4470930 - + https://github.com/dotnet/runtime-assets - 30b6a8d9d3af5681e4caef1ea453619a4b0e9f2e + 6e78861f1f307cd9f0e64a45b1d7884fa4470930 - + https://github.com/dotnet/runtime-assets - 30b6a8d9d3af5681e4caef1ea453619a4b0e9f2e + 6e78861f1f307cd9f0e64a45b1d7884fa4470930 - + https://github.com/dotnet/runtime-assets - 30b6a8d9d3af5681e4caef1ea453619a4b0e9f2e + 6e78861f1f307cd9f0e64a45b1d7884fa4470930 https://github.com/dotnet/llvm-project @@ -282,55 +282,55 @@ https://github.com/dotnet/llvm-project 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/runtime - 85fbd98765c47a867564fff6ae18cc92423cdc66 + 56610095196ac12a397b1acd00835db4d86849b9 - + https://github.com/dotnet/runtime - 85fbd98765c47a867564fff6ae18cc92423cdc66 + 56610095196ac12a397b1acd00835db4d86849b9 - + https://github.com/dotnet/runtime - 85fbd98765c47a867564fff6ae18cc92423cdc66 + 56610095196ac12a397b1acd00835db4d86849b9 - + https://github.com/dotnet/runtime - 85fbd98765c47a867564fff6ae18cc92423cdc66 + 56610095196ac12a397b1acd00835db4d86849b9 - + https://github.com/dotnet/runtime - 85fbd98765c47a867564fff6ae18cc92423cdc66 + 56610095196ac12a397b1acd00835db4d86849b9 - + https://github.com/dotnet/runtime - 85fbd98765c47a867564fff6ae18cc92423cdc66 + 56610095196ac12a397b1acd00835db4d86849b9 - + https://github.com/dotnet/runtime - 85fbd98765c47a867564fff6ae18cc92423cdc66 + 56610095196ac12a397b1acd00835db4d86849b9 - + https://github.com/dotnet/runtime - 85fbd98765c47a867564fff6ae18cc92423cdc66 + 56610095196ac12a397b1acd00835db4d86849b9 - + https://github.com/dotnet/runtime - 85fbd98765c47a867564fff6ae18cc92423cdc66 + 56610095196ac12a397b1acd00835db4d86849b9 - + https://github.com/dotnet/xharness - 50b43ece7daf9f8a88ac16a95a4f8647a4c71c4b + ec633d9ddbdb86dd3d772989889690821f790484 - + https://github.com/dotnet/xharness - 50b43ece7daf9f8a88ac16a95a4f8647a4c71c4b + ec633d9ddbdb86dd3d772989889690821f790484 - + https://github.com/dotnet/xharness - 50b43ece7daf9f8a88ac16a95a4f8647a4c71c4b + ec633d9ddbdb86dd3d772989889690821f790484 https://github.com/dotnet/arcade @@ -352,13 +352,13 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-optimization c54b8e8611d50594cc926fd7c81205871a38be6f - + https://github.com/dotnet/hotreload-utils - 4670b9e37293570f8d93d6af40c4710e2686bf67 + 249050528f8ac9882f04b2c719bda3e5a532b258 - + https://github.com/dotnet/runtime-assets - 30b6a8d9d3af5681e4caef1ea453619a4b0e9f2e + 6e78861f1f307cd9f0e64a45b1d7884fa4470930 https://github.com/dotnet/roslyn @@ -386,14 +386,14 @@ 3027ed4a9186a6924722a1597c8d31a59d411f7c - + https://github.com/dotnet/sdk - cf8c24575410adf397c0823fd7061f9451049ea1 + 1529907f03b73e097a6e4f33fd3c5aea2246f021 - + https://github.com/dotnet/sdk - cf8c24575410adf397c0823fd7061f9451049ea1 + 1529907f03b73e097a6e4f33fd3c5aea2246f021 diff --git a/eng/Versions.props b/eng/Versions.props index 0fb3f86bcf6fe6..8ca09ea0685ae1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -81,7 +81,7 @@ 0.2.0 - 9.0.100-preview.4.24215.1 + 9.0.100-preview.4.24221.4 9.0.0-beta.24219.1 9.0.0-beta.24219.1 @@ -104,10 +104,10 @@ 6.0.0-preview.1.102 - 9.0.0-preview.4.24215.1 + 9.0.0-preview.4.24219.3 6.0.0 - 9.0.0-preview.4.24215.1 + 9.0.0-preview.4.24219.3 6.0.0 1.1.1 @@ -119,39 +119,39 @@ 8.0.0 5.0.0 4.5.5 - 9.0.0-preview.4.24215.1 - 9.0.0-preview.4.24215.1 + 9.0.0-preview.4.24219.3 + 9.0.0-preview.4.24219.3 6.0.0 5.0.0 5.0.0 5.0.0 7.0.0 - 9.0.0-preview.4.24215.1 + 9.0.0-preview.4.24219.3 6.0.0 7.0.0 4.5.4 4.5.0 - 9.0.0-preview.4.24215.1 + 9.0.0-preview.4.24219.3 8.0.0 8.0.0 8.0.0 8.0.0 - 9.0.0-beta.24215.1 - 9.0.0-beta.24215.1 - 9.0.0-beta.24215.1 - 9.0.0-beta.24215.1 - 9.0.0-beta.24215.1 - 9.0.0-beta.24215.1 - 9.0.0-beta.24215.1 - 9.0.0-beta.24215.1 - 9.0.0-beta.24215.1 - 9.0.0-beta.24215.1 - 9.0.0-beta.24215.1 - 9.0.0-beta.24215.1 - 9.0.0-beta.24215.1 - 9.0.0-beta.24215.1 + 9.0.0-beta.24222.1 + 9.0.0-beta.24222.1 + 9.0.0-beta.24222.1 + 9.0.0-beta.24222.1 + 9.0.0-beta.24222.1 + 9.0.0-beta.24222.1 + 9.0.0-beta.24222.1 + 9.0.0-beta.24222.1 + 9.0.0-beta.24222.1 + 9.0.0-beta.24222.1 + 9.0.0-beta.24222.1 + 9.0.0-beta.24222.1 + 9.0.0-beta.24222.1 + 9.0.0-beta.24222.1 1.0.0-prerelease.24219.3 1.0.0-prerelease.24219.3 @@ -179,10 +179,10 @@ 1.4.0 17.4.0-preview-20220707-01 - 9.0.0-prerelease.24208.1 - 9.0.0-prerelease.24208.1 - 9.0.0-prerelease.24208.1 - 9.0.0-alpha.0.24215.1 + 9.0.0-prerelease.24224.1 + 9.0.0-prerelease.24224.1 + 9.0.0-prerelease.24224.1 + 9.0.0-alpha.0.24222.1 3.12.0 4.5.0 6.0.0 @@ -208,11 +208,11 @@ 8.0.0-preview-20230918.1 - 0.11.4-alpha.24215.1 + 0.11.4-alpha.24222.1 - 9.0.0-preview.4.24215.1 + 9.0.0-preview.4.24219.3 - 9.0.0-preview.4.24215.1 + 9.0.0-preview.5.24223.2 2.3.5 9.0.0-alpha.1.24167.3 diff --git a/global.json b/global.json index eb06a253442796..a19b0072e32e2e 100644 --- a/global.json +++ b/global.json @@ -13,6 +13,6 @@ "Microsoft.DotNet.SharedFramework.Sdk": "9.0.0-beta.24219.1", "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.Build.Traversal": "3.4.0", - "Microsoft.NET.Sdk.IL": "9.0.0-preview.4.24215.1" + "Microsoft.NET.Sdk.IL": "9.0.0-preview.4.24219.3" } } diff --git a/src/libraries/System.Collections/src/CompatibilitySuppressions.xml b/src/libraries/System.Collections/src/CompatibilitySuppressions.xml index c313881d43172b..f281317339d43b 100644 --- a/src/libraries/System.Collections/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Collections/src/CompatibilitySuppressions.xml @@ -1,4 +1,5 @@  + CP0001 diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs index 382499070cd1d9..3908224b0a1a13 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs @@ -402,7 +402,7 @@ public abstract class Instrument : Instrument where T : struct public ReadOnlySpan> Tags { get { throw null; } } public T Value { get { throw null; } } } - public delegate void MeasurementCallback(Instrument instrument, T measurement, ReadOnlySpan> tags, object? state); + public delegate void MeasurementCallback(Instrument instrument, T measurement, ReadOnlySpan> tags, object? state) where T : struct; public class Meter : IDisposable { public Counter CreateCounter(string name, string? unit = null, string? description = null) where T : struct { throw null; } diff --git a/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ManualShimTypeForwards.cs b/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ManualShimTypeForwards.cs index 0a93320ccff1eb..ab8473216cd87a 100644 --- a/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ManualShimTypeForwards.cs +++ b/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ManualShimTypeForwards.cs @@ -65,7 +65,7 @@ public ByteEqualityComparer() { } public override int GetHashCode() { throw null; } public override int GetHashCode(byte b) { throw null; } } - public sealed partial class EnumEqualityComparer : System.Collections.Generic.EqualityComparer, System.Runtime.Serialization.ISerializable where T : struct + public sealed partial class EnumEqualityComparer : System.Collections.Generic.EqualityComparer, System.Runtime.Serialization.ISerializable where T : struct, System.Enum { public EnumEqualityComparer() { } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Enum.cs b/src/libraries/System.Private.CoreLib/src/System/Enum.cs index 20fd34bf70d89c..d2b18ed344cc37 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Enum.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Enum.cs @@ -1746,7 +1746,7 @@ bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, Re /// A span containing the character that represents the standard format string that defines the acceptable format of destination. This may be empty, or "g", "d", "f", or "x". /// if the formatting was successful; otherwise, if the destination span wasn't large enough to contain the formatted value. /// The format parameter contains an invalid value. - public static unsafe bool TryFormat(TEnum value, Span destination, out int charsWritten, [StringSyntax(StringSyntaxAttribute.EnumFormat)] ReadOnlySpan format = default) where TEnum : struct, Enum + public static unsafe bool TryFormat(TEnum value, Span destination, out int charsWritten, [StringSyntax(StringSyntaxAttribute.EnumFormat)] ReadOnlySpan format = default) where TEnum : struct { RuntimeType rt = (RuntimeType)typeof(TEnum); Type underlyingType = typeof(TEnum).GetEnumUnderlyingType(); diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs index 3b718d224417c7..f7665833c0a758 100644 --- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs +++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs @@ -362,17 +362,17 @@ public void FinalRelease() { } System.Runtime.InteropServices.Marshalling.VirtualMethodTableInfo System.Runtime.InteropServices.Marshalling.IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableInfoForKey(System.Type type) { throw null; } } [System.Runtime.InteropServices.Marshalling.CustomMarshallerAttribute(typeof(System.Exception), System.Runtime.InteropServices.Marshalling.MarshalMode.UnmanagedToManagedOut, typeof(System.Runtime.InteropServices.Marshalling.ExceptionAsDefaultMarshaller<>))] - public static partial class ExceptionAsDefaultMarshaller where T : struct + public static partial class ExceptionAsDefaultMarshaller where T : unmanaged { public static T ConvertToUnmanaged(System.Exception e) { throw null; } } [System.Runtime.InteropServices.Marshalling.CustomMarshallerAttribute(typeof(System.Exception), System.Runtime.InteropServices.Marshalling.MarshalMode.UnmanagedToManagedOut, typeof(System.Runtime.InteropServices.Marshalling.ExceptionAsHResultMarshaller<>))] - public static partial class ExceptionAsHResultMarshaller where T : struct + public static partial class ExceptionAsHResultMarshaller where T : unmanaged, System.Numerics.INumber { public static T ConvertToUnmanaged(System.Exception e) { throw null; } } [System.Runtime.InteropServices.Marshalling.CustomMarshallerAttribute(typeof(System.Exception), System.Runtime.InteropServices.Marshalling.MarshalMode.UnmanagedToManagedOut, typeof(System.Runtime.InteropServices.Marshalling.ExceptionAsNaNMarshaller<>))] - public static partial class ExceptionAsNaNMarshaller where T : struct + public static partial class ExceptionAsNaNMarshaller where T : unmanaged, System.Numerics.IFloatingPointIeee754 { public static T ConvertToUnmanaged(System.Exception e) { throw null; } } diff --git a/src/libraries/System.Runtime.InteropServices/src/CompatibilitySuppressions.xml b/src/libraries/System.Runtime.InteropServices/src/CompatibilitySuppressions.xml index ebabc977812cb7..b4c6a062718672 100644 --- a/src/libraries/System.Runtime.InteropServices/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Runtime.InteropServices/src/CompatibilitySuppressions.xml @@ -1,4 +1,5 @@  + CP0001 diff --git a/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml b/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml index 09cfe417e3812f..935f4a69d115ad 100644 --- a/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml +++ b/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml @@ -469,4 +469,64 @@ net8.0/System.dll net9.0/System.dll + + CP0021 + T:System.Diagnostics.Metrics.MeasurementCallback`1``0:struct + net8.0/System.Diagnostics.DiagnosticSource.dll + net9.0/System.Diagnostics.DiagnosticSource.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsDefaultMarshaller`1``0:struct + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsDefaultMarshaller`1``0:unmanaged + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsHResultMarshaller`1``0:struct + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsHResultMarshaller`1``0:T:System.Numerics.INumber{`0} + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsHResultMarshaller`1``0:unmanaged + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsNaNMarshaller`1``0:struct + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsNaNMarshaller`1``0:T:System.Numerics.IFloatingPointIeee754{`0} + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsNaNMarshaller`1``0:unmanaged + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Text.Json.Serialization.JsonNumberEnumConverter`1``0:T:System.Enum + net8.0/System.Text.Json.dll + net9.0/System.Text.Json.dll + \ No newline at end of file diff --git a/src/libraries/apicompat/ApiCompatBaseline.netstandard2.0.xml b/src/libraries/apicompat/ApiCompatBaseline.netstandard2.0.xml index e03170246c0a50..939342fce86a04 100644 --- a/src/libraries/apicompat/ApiCompatBaseline.netstandard2.0.xml +++ b/src/libraries/apicompat/ApiCompatBaseline.netstandard2.0.xml @@ -2791,4 +2791,382 @@ netstandard2.0/System.dll net9.0/System.dll + + CP0021 + M:System.Runtime.InteropServices.Marshal.CreateAggregatedObject``1(System.IntPtr,``0)``0:notnull + netstandard2.0/mscorlib.dll + net9.0/mscorlib.dll + + + CP0021 + M:System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate``1(``0)``0:notnull + netstandard2.0/mscorlib.dll + net9.0/mscorlib.dll + + + CP0021 + T:System.Collections.Concurrent.ConcurrentDictionary`2``0:notnull + netstandard2.0/mscorlib.dll + net9.0/mscorlib.dll + + + CP0021 + T:System.Collections.Generic.Dictionary`2``0:notnull + netstandard2.0/mscorlib.dll + net9.0/mscorlib.dll + + + CP0021 + T:System.Collections.ObjectModel.KeyedCollection`2``0:notnull + netstandard2.0/mscorlib.dll + net9.0/mscorlib.dll + + + CP0021 + T:System.Collections.ObjectModel.ReadOnlyDictionary`2``0:notnull + netstandard2.0/mscorlib.dll + net9.0/mscorlib.dll + + + CP0021 + T:System.Tuple`8``7:notnull + netstandard2.0/mscorlib.dll + net9.0/mscorlib.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Runtime.InteropServices.Marshal.CreateAggregatedObject``1(System.IntPtr,``0)``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate``1(``0)``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Concurrent.ConcurrentDictionary`2``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Generic.Dictionary`2``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Generic.SortedDictionary`2``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Generic.SortedList`2``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.ObjectModel.KeyedCollection`2``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.ObjectModel.ReadOnlyDictionary`2``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Tuple`8``7:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Concurrent.ConcurrentDictionary`2``0:notnull + netstandard2.0/System.Collections.Concurrent.dll + net9.0/System.Collections.Concurrent.dll + + + CP0021 + T:System.Collections.Generic.Dictionary`2``0:notnull + netstandard2.0/System.Collections.dll + net9.0/System.Collections.dll + + + CP0021 + T:System.Collections.Generic.SortedDictionary`2``0:notnull + netstandard2.0/System.Collections.dll + net9.0/System.Collections.dll + + + CP0021 + T:System.Collections.Generic.SortedList`2``0:notnull + netstandard2.0/System.Collections.dll + net9.0/System.Collections.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + T:System.Collections.Generic.SortedDictionary`2``0:notnull + netstandard2.0/System.dll + net9.0/System.dll + + + CP0021 + T:System.Collections.Generic.SortedList`2``0:notnull + netstandard2.0/System.dll + net9.0/System.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Linq.dll + net9.0/System.Linq.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/System.Linq.dll + net9.0/System.Linq.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Linq.dll + net9.0/System.Linq.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/System.Linq.dll + net9.0/System.Linq.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + T:System.Collections.ObjectModel.KeyedCollection`2``0:notnull + netstandard2.0/System.ObjectModel.dll + net9.0/System.ObjectModel.dll + + + CP0021 + T:System.Collections.ObjectModel.ReadOnlyDictionary`2``0:notnull + netstandard2.0/System.ObjectModel.dll + net9.0/System.ObjectModel.dll + + + CP0021 + T:System.Tuple`8``7:notnull + netstandard2.0/System.Runtime.dll + net9.0/System.Runtime.dll + + + CP0021 + M:System.Runtime.InteropServices.Marshal.CreateAggregatedObject``1(System.IntPtr,``0)``0:notnull + netstandard2.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + M:System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate``1(``0)``0:notnull + netstandard2.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + \ No newline at end of file diff --git a/src/libraries/apicompat/ApiCompatBaseline.netstandard2.1.xml b/src/libraries/apicompat/ApiCompatBaseline.netstandard2.1.xml index f7c8eb8430ef04..f0ef02d93c1a19 100644 --- a/src/libraries/apicompat/ApiCompatBaseline.netstandard2.1.xml +++ b/src/libraries/apicompat/ApiCompatBaseline.netstandard2.1.xml @@ -877,4 +877,130 @@ netstandard2.1/netstandard.dll net9.0/netstandard.dll + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Runtime.InteropServices.Marshal.CreateAggregatedObject``1(System.IntPtr,``0)``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate``1(``0)``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Concurrent.ConcurrentDictionary`2``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Generic.Dictionary`2``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Generic.SortedDictionary`2``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Generic.SortedList`2``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.ObjectModel.KeyedCollection`2``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.ObjectModel.ReadOnlyDictionary`2``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Tuple`8``7:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + \ No newline at end of file From 264023ee550d71b1609788145dd03e47ed77c943 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Thu, 25 Apr 2024 19:57:34 -0700 Subject: [PATCH 125/248] Fix compact time computation (#100599) --- src/coreclr/gc/gc.cpp | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index e43047cf6e113a..0861a15d274d7c 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -29966,7 +29966,7 @@ void gc_heap::mark_phase (int condemned_gen_number) #endif //MULTIPLE_HEAPS { #ifdef FEATURE_EVENT_TRACE - record_mark_time (gc_time_info[time_plan - 1], current_mark_time, last_mark_time); + record_mark_time (gc_time_info[time_mark_long_weak], current_mark_time, last_mark_time); gc_time_info[time_plan] = last_mark_time; #endif //FEATURE_EVENT_TRACE @@ -33964,26 +33964,12 @@ void gc_heap::plan_phase (int condemned_gen_number) if (gc_t_join.joined()) #endif //MULTIPLE_HEAPS { -#ifdef FEATURE_EVENT_TRACE - if (informational_event_enabled_p) - { - uint64_t current_time = GetHighPrecisionTimeStamp(); - gc_time_info[time_compact] = current_time - gc_time_info[time_compact]; - } -#endif //FEATURE_EVENT_TRACE - #ifdef MULTIPLE_HEAPS for (int i = 0; i < n_heaps; i++) { -#ifdef USE_REGIONS - g_heaps [i]->rearrange_uoh_segments(); -#endif //USE_REGIONS g_heaps [i]->rearrange_heap_segments (TRUE); } #else //MULTIPLE_HEAPS -#ifdef USE_REGIONS - rearrange_uoh_segments(); -#endif //USE_REGIONS rearrange_heap_segments (TRUE); #endif //MULTIPLE_HEAPS @@ -34018,7 +34004,7 @@ void gc_heap::plan_phase (int condemned_gen_number) #endif //MULTIPLE_HEAPS #ifdef FEATURE_EVENT_TRACE - if (informational_event_enabled_p && (condemned_gen_number < (max_generation -1))) + if (informational_event_enabled_p) { uint64_t current_time = GetHighPrecisionTimeStamp(); gc_time_info[time_compact] = current_time - gc_time_info[time_compact]; From 2d335f34af696feda5fc3e80f98c991b3aeb93d0 Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Thu, 25 Apr 2024 20:30:44 -0700 Subject: [PATCH 126/248] [cdac] Read/store globals from contract descriptor (#101450) - Map indirect global values to corresponding values in `pointer_data` array from contract descriptor - Add `[Try]Read`, `[Try]ReadPointer`, `[Try]ReadGlobal` and `[Try]ReadGlobalPointer` to `Target` - Make cDAC implementation of `ISOSDacInterface9.GetBreakingChangeVersion` read value from globals - Create test helpers for mocking out reading from the target and providing a contract descriptor for different bitness/endianness - Add unit tests for reading global values (direct and indirect) --- .../datacontracts/contract-descriptor.md | 4 +- src/coreclr/debug/daccess/cdac.cpp | 30 +- src/coreclr/debug/daccess/cdac.h | 9 +- src/coreclr/debug/daccess/daccess.cpp | 2 +- .../managed/cdacreader/src/Constants.cs | 13 + .../cdacreader/src/Legacy/SOSDacImpl.cs | 3 +- src/native/managed/cdacreader/src/Target.cs | 142 +++++-- .../managed/cdacreader/tests/TargetTests.cs | 358 ++++++++++++++++++ 8 files changed, 507 insertions(+), 54 deletions(-) create mode 100644 src/native/managed/cdacreader/src/Constants.cs create mode 100644 src/native/managed/cdacreader/tests/TargetTests.cs diff --git a/docs/design/datacontracts/contract-descriptor.md b/docs/design/datacontracts/contract-descriptor.md index e63ae11b4ae936..fbd58eb33eb9a5 100644 --- a/docs/design/datacontracts/contract-descriptor.md +++ b/docs/design/datacontracts/contract-descriptor.md @@ -45,7 +45,7 @@ reserved bits should be written as zero. Diagnostic tooling may ignore non-zero The `descriptor` is a pointer to a UTF-8 JSON string described in [data descriptor physical layout](./data_descriptor.md#Physical_JSON_descriptor). The total number of bytes is given by `descriptor_size`. -The auxiliary data for the JSON descriptor is stored at the location `aux_data` in `aux_data_count` pointer-sized slots. +The auxiliary data for the JSON descriptor is stored at the location `pointer_data` in `pointer_data_count` pointer-sized slots. ### Architecture properties @@ -83,7 +83,7 @@ a JSON integer constant. "globals": { "FEATURE_COMINTEROP": 0, - "s_pThreadStore": [ 0 ] // indirect from aux data offset 0 + "s_pThreadStore": [ 0 ] // indirect from pointer data offset 0 }, "contracts": {"Thread": 1, "GCHandle": 1, "ThreadStore": 1} } diff --git a/src/coreclr/debug/daccess/cdac.cpp b/src/coreclr/debug/daccess/cdac.cpp index a4146709ec7233..b7bb7585e6bcf7 100644 --- a/src/coreclr/debug/daccess/cdac.cpp +++ b/src/coreclr/debug/daccess/cdac.cpp @@ -41,27 +41,31 @@ CDAC CDAC::Create(uint64_t descriptorAddr, ICorDebugDataTarget* target) { HMODULE cdacLib; if (!TryLoadCDACLibrary(&cdacLib)) - return CDAC::Invalid(); + return {}; - return CDAC{cdacLib, descriptorAddr, target}; + decltype(&cdac_reader_init) init = reinterpret_cast(::GetProcAddress(cdacLib, "cdac_reader_init")); + _ASSERTE(init != nullptr); + + intptr_t handle; + if (init(descriptorAddr, &ReadFromTargetCallback, target, &handle) != 0) + { + ::FreeLibrary(cdacLib); + return {}; + } + + return CDAC{cdacLib, handle, target}; } -CDAC::CDAC(HMODULE module, uint64_t descriptorAddr, ICorDebugDataTarget* target) - : m_module(module) +CDAC::CDAC(HMODULE module, intptr_t handle, ICorDebugDataTarget* target) + : m_module{module} + , m_cdac_handle{handle} , m_target{target} { - if (m_module == NULL) - { - m_cdac_handle = 0; - return; - } + _ASSERTE(m_module != NULL && m_cdac_handle != 0 && m_target != NULL); m_target->AddRef(); - decltype(&cdac_reader_init) init = reinterpret_cast(::GetProcAddress(m_module, "cdac_reader_init")); decltype(&cdac_reader_get_sos_interface) getSosInterface = reinterpret_cast(::GetProcAddress(m_module, "cdac_reader_get_sos_interface")); - _ASSERTE(init != nullptr && getSosInterface != nullptr); - - init(descriptorAddr, &ReadFromTargetCallback, m_target, &m_cdac_handle); + _ASSERTE(getSosInterface != nullptr); getSosInterface(m_cdac_handle, &m_sos); } diff --git a/src/coreclr/debug/daccess/cdac.h b/src/coreclr/debug/daccess/cdac.h index d5c0eecb0f7373..51078ffcf2e46b 100644 --- a/src/coreclr/debug/daccess/cdac.h +++ b/src/coreclr/debug/daccess/cdac.h @@ -9,12 +9,9 @@ class CDAC final public: // static static CDAC Create(uint64_t descriptorAddr, ICorDebugDataTarget *pDataTarget); - static CDAC Invalid() - { - return CDAC{nullptr, 0, nullptr}; - } - public: + CDAC() = default; + CDAC(const CDAC&) = delete; CDAC& operator=(const CDAC&) = delete; @@ -56,7 +53,7 @@ class CDAC final IUnknown* SosInterface(); private: - CDAC(HMODULE module, uint64_t descriptorAddr, ICorDebugDataTarget* target); + CDAC(HMODULE module, intptr_t handle, ICorDebugDataTarget* target); private: HMODULE m_module; diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp index 971b8b90980b32..37e7d37edd9f9c 100644 --- a/src/coreclr/debug/daccess/daccess.cpp +++ b/src/coreclr/debug/daccess/daccess.cpp @@ -3038,7 +3038,7 @@ class DacStreamManager //---------------------------------------------------------------------------- ClrDataAccess::ClrDataAccess(ICorDebugDataTarget * pTarget, ICLRDataTarget * pLegacyTarget/*=0*/) - : m_cdac{CDAC::Invalid()} + : m_cdac{} { SUPPORTS_DAC_HOST_ONLY; // ctor does no marshalling - don't check with DacCop diff --git a/src/native/managed/cdacreader/src/Constants.cs b/src/native/managed/cdacreader/src/Constants.cs new file mode 100644 index 00000000000000..0fbcaa0a246c73 --- /dev/null +++ b/src/native/managed/cdacreader/src/Constants.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DataContractReader; + +internal static class Constants +{ + internal static class Globals + { + // See src/coreclr/debug/runtimeinfo/datadescriptor.h + internal const string SOSBreakingChangeVersion = nameof(SOSBreakingChangeVersion); + } +} diff --git a/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs b/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs index b0640c44efc98d..261aa034c3f894 100644 --- a/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs +++ b/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs @@ -35,8 +35,7 @@ public SOSDacImpl(Target target) public int GetBreakingChangeVersion() { - // TODO: Return non-hard-coded version - return 4; + return _target.ReadGlobal(Constants.Globals.SOSBreakingChangeVersion); } public unsafe int GetCCWData(ulong ccw, void* data) => HResults.E_NOTIMPL; diff --git a/src/native/managed/cdacreader/src/Target.cs b/src/native/managed/cdacreader/src/Target.cs index 049a9f80ed2265..c2e09d9d0fa116 100644 --- a/src/native/managed/cdacreader/src/Target.cs +++ b/src/native/managed/cdacreader/src/Target.cs @@ -4,6 +4,8 @@ using System; using System.Buffers.Binary; using System.Collections.Generic; +using System.Numerics; +using System.Runtime.CompilerServices; namespace Microsoft.Diagnostics.DataContractReader; @@ -15,7 +17,7 @@ public struct TargetPointer public TargetPointer(ulong value) => Value = value; } -internal sealed unsafe class Target +public sealed unsafe class Target { private const int StackAllocByteThreshold = 1024; @@ -29,7 +31,7 @@ private readonly struct Configuration private readonly Reader _reader; private readonly IReadOnlyDictionary _contracts = new Dictionary(); - private readonly TargetPointer[] _pointerData = []; + private readonly IReadOnlyDictionary _globals = new Dictionary(); public static bool TryCreate(ulong contractDescriptor, delegate* unmanaged readFromTarget, void* readContext, out Target? target) { @@ -49,11 +51,30 @@ private Target(Configuration config, ContractDescriptorParser.ContractDescriptor _config = config; _reader = reader; - // TODO: [cdac] Read globals and types + // TODO: [cdac] Read types // note: we will probably want to store the globals and types into a more usable form _contracts = descriptor.Contracts ?? []; - _pointerData = pointerData; + // Read globals and map indirect values to pointer data + if (descriptor.Globals is not null) + { + Dictionary globals = []; + foreach ((string name, ContractDescriptorParser.GlobalDescriptor global) in descriptor.Globals) + { + ulong value = global.Value; + if (global.Indirect) + { + if (value >= (ulong)pointerData.Length) + throw new InvalidOperationException($"Invalid pointer data index {value}."); + + value = pointerData[value].Value; + } + + globals[name] = (value, global.Type); + } + + _globals = globals; + } } // See docs/design/datacontracts/contract-descriptor.md @@ -81,7 +102,7 @@ private static bool TryReadContractDescriptor( return false; // Flags - uint32_t - if (!TryReadUInt32(address, isLittleEndian, reader, out uint flags)) + if (!TryRead(address, isLittleEndian, reader, out uint flags)) return false; address += sizeof(uint); @@ -92,7 +113,7 @@ private static bool TryReadContractDescriptor( config = new Configuration { IsLittleEndian = isLittleEndian, PointerSize = pointerSize }; // Descriptor size - uint32_t - if (!TryReadUInt32(address, config.IsLittleEndian, reader, out uint descriptorSize)) + if (!TryRead(address, config.IsLittleEndian, reader, out uint descriptorSize)) return false; address += sizeof(uint); @@ -104,7 +125,7 @@ private static bool TryReadContractDescriptor( address += (uint)pointerSize; // Pointer data count - uint32_t - if (!TryReadUInt32(address, config.IsLittleEndian, reader, out uint pointerDataCount)) + if (!TryRead(address, config.IsLittleEndian, reader, out uint pointerDataCount)) return false; address += sizeof(uint); @@ -138,30 +159,33 @@ private static bool TryReadContractDescriptor( return true; } - public uint ReadUInt32(ulong address) + public T Read(ulong address, out T value) where T : unmanaged, IBinaryInteger, IMinMaxValue { - if (!TryReadUInt32(address, out uint value)) - throw new InvalidOperationException($"Failed to read uint32 at 0x{address:x8}."); + if (!TryRead(address, out value)) + throw new InvalidOperationException($"Failed to read {typeof(T)} at 0x{address:x8}."); return value; } - public bool TryReadUInt32(ulong address, out uint value) - => TryReadUInt32(address, _config.IsLittleEndian, _reader, out value); + public bool TryRead(ulong address, out T value) where T : unmanaged, IBinaryInteger, IMinMaxValue + => TryRead(address, _config.IsLittleEndian, _reader, out value); - private static bool TryReadUInt32(ulong address, bool isLittleEndian, Reader reader, out uint value) + private static bool TryRead(ulong address, bool isLittleEndian, Reader reader, out T value) where T : unmanaged, IBinaryInteger, IMinMaxValue { - value = 0; - - Span buffer = stackalloc byte[sizeof(uint)]; + value = default; + Span buffer = stackalloc byte[sizeof(T)]; if (reader.ReadFromTarget(address, buffer) < 0) return false; - value = isLittleEndian - ? BinaryPrimitives.ReadUInt32LittleEndian(buffer) - : BinaryPrimitives.ReadUInt32BigEndian(buffer); + return isLittleEndian + ? T.TryReadLittleEndian(buffer, !IsSigned(), out value) + : T.TryReadBigEndian(buffer, !IsSigned(), out value); + } - return true; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsSigned() where T : struct, INumberBase, IMinMaxValue + { + return T.IsNegative(T.MinValue); } public TargetPointer ReadPointer(ulong address) @@ -183,21 +207,79 @@ private static bool TryReadPointer(ulong address, Configuration config, Reader r if (reader.ReadFromTarget(address, buffer) < 0) return false; - if (config.PointerSize == sizeof(uint)) + if (config.PointerSize == sizeof(uint) + && TryRead(address, config.IsLittleEndian, reader, out uint value32)) { - pointer = new TargetPointer( - config.IsLittleEndian - ? BinaryPrimitives.ReadUInt32LittleEndian(buffer) - : BinaryPrimitives.ReadUInt32BigEndian(buffer)); + pointer = new TargetPointer(value32); + return true; } - else if (config.PointerSize == sizeof(ulong)) + else if (config.PointerSize == sizeof(ulong) + && TryRead(address, config.IsLittleEndian, reader, out ulong value64)) { - pointer = new TargetPointer( - config.IsLittleEndian - ? BinaryPrimitives.ReadUInt64LittleEndian(buffer) - : BinaryPrimitives.ReadUInt64BigEndian(buffer)); + pointer = new TargetPointer(value64); + return true; } + return false; + } + + public T ReadGlobal(string name) where T : struct, INumber + { + if (!TryReadGlobal(name, out T value)) + throw new InvalidOperationException($"Failed to read global {typeof(T)} '{name}'."); + + return value; + } + + public bool TryReadGlobal(string name, out T value) where T : struct, INumber, INumberBase + { + value = default; + if (!_globals.TryGetValue(name, out (ulong Value, string? Type) global)) + return false; + + // TODO: [cdac] Move type validation out of the read such that it does not have to happen for every read + if (global.Type is not null) + { + string? expectedType = Type.GetTypeCode(typeof(T)) switch + { + TypeCode.SByte => "int8", + TypeCode.Byte => "uint8", + TypeCode.Int16 => "int16", + TypeCode.UInt16 => "uint16", + TypeCode.Int32 => "int32", + TypeCode.UInt32 => "uint32", + TypeCode.Int64 => "int64", + TypeCode.UInt64 => "uint64", + _ => null, + }; + if (expectedType is null || global.Type != expectedType) + { + return false; + } + } + + value = T.CreateChecked(global.Value); + return true; + } + + public TargetPointer ReadGlobalPointer(string name) + { + if (!TryReadGlobalPointer(name, out TargetPointer pointer)) + throw new InvalidOperationException($"Failed to read global pointer '{name}'."); + + return pointer; + } + + public bool TryReadGlobalPointer(string name, out TargetPointer pointer) + { + pointer = TargetPointer.Null; + if (!_globals.TryGetValue(name, out (ulong Value, string? Type) global)) + return false; + + if (global.Type is not null && Array.IndexOf(["pointer", "nint", "nuint"], global.Type) == -1) + return false; + + pointer = new TargetPointer(global.Value); return true; } diff --git a/src/native/managed/cdacreader/tests/TargetTests.cs b/src/native/managed/cdacreader/tests/TargetTests.cs new file mode 100644 index 00000000000000..5a8569c1b557cb --- /dev/null +++ b/src/native/managed/cdacreader/tests/TargetTests.cs @@ -0,0 +1,358 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Buffers.Binary; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using Xunit; + +namespace Microsoft.Diagnostics.DataContractReader.UnitTests; + +public unsafe class TargetTests +{ + private const ulong ContractDescriptorAddr = 0xaaaaaaaa; + private const uint JsonDescriptorAddr = 0xdddddddd; + private const uint PointerDataAddr = 0xeeeeeeee; + + private static readonly (string Name, ulong Value, string? Type)[] TestGlobals = + [ + ("value", (ulong)sbyte.MaxValue, null), + ("int8Value", 0x12, "int8"), + ("uint8Value", 0x12, "uint8"), + ("int16Value", 0x1234, "int16"), + ("uint16Value", 0x1234, "uint16"), + ("int32Value", 0x12345678, "int32"), + ("uint32Value", 0x12345678, "uint32"), + ("int64Value", 0x123456789abcdef0, "int64"), + ("uint64Value", 0x123456789abcdef0, "uint64"), + ("nintValue", 0xabcdef0, "nint"), + ("nuintValue", 0xabcdef0, "nuint"), + ("pointerValue", 0xabcdef0, "pointer"), + ]; + + [Theory] + [InlineData(true, true)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(false, false)] + public void ReadGlobalValue(bool isLittleEndian, bool is64Bit) + { + string globalsJson = string.Join(',', TestGlobals.Select(i => $"\"{i.Name}\": {(i.Type is null ? i.Value.ToString() : $"[{i.Value}, \"{i.Type}\"]")}")); + byte[] json = Encoding.UTF8.GetBytes($$""" + { + "version": 0, + "baseline": "empty", + "contracts": {}, + "types": {}, + "globals": { {{globalsJson}} } + } + """); + Span descriptor = stackalloc byte[ContractDescriptor.Size(is64Bit)]; + ContractDescriptor.Fill(descriptor, isLittleEndian, is64Bit, json.Length, 0); + fixed (byte* jsonPtr = json) + { + ReadContext context = new ReadContext + { + ContractDescriptor = (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(descriptor)), + ContractDescriptorLength = descriptor.Length, + JsonDescriptor = jsonPtr, + JsonDescriptorLength = json.Length, + }; + + bool success = Target.TryCreate(ContractDescriptorAddr, &ReadFromTarget, &context, out Target? target); + Assert.True(success); + + ValidateGlobals(target, TestGlobals); + } + } + + [Theory] + [InlineData(true, true)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(false, false)] + public void ReadIndirectGlobalValue(bool isLittleEndian, bool is64Bit) + { + int pointerSize = is64Bit ? sizeof(ulong) : sizeof(uint); + Span pointerData = stackalloc byte[TestGlobals.Length * pointerSize]; + for (int i = 0; i < TestGlobals.Length; i++) + { + var (_, value, _) = TestGlobals[i]; + WritePointer(pointerData.Slice(i * pointerSize), value, isLittleEndian, pointerSize); + } + + string globalsJson = string.Join(',', TestGlobals.Select((g, i) => $"\"{g.Name}\": {(g.Type is null ? $"[{i}]" : $"[[{i}], \"{g.Type}\"]")}")); + byte[] json = Encoding.UTF8.GetBytes($$""" + { + "version": 0, + "baseline": "empty", + "contracts": {}, + "types": {}, + "globals": { {{globalsJson}} } + } + """); + Span descriptor = stackalloc byte[ContractDescriptor.Size(is64Bit)]; + ContractDescriptor.Fill(descriptor, isLittleEndian, is64Bit, json.Length, pointerData.Length / pointerSize); + fixed (byte* jsonPtr = json) + { + ReadContext context = new ReadContext + { + ContractDescriptor = (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(descriptor)), + ContractDescriptorLength = descriptor.Length, + JsonDescriptor = jsonPtr, + JsonDescriptorLength = json.Length, + PointerData = (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(pointerData)), + PointerDataLength = pointerData.Length + }; + + bool success = Target.TryCreate(ContractDescriptorAddr, &ReadFromTarget, &context, out Target? target); + Assert.True(success); + + // Indirect values are pointer-sized, so max 32-bits for a 32-bit target + var expected = is64Bit + ? TestGlobals + : TestGlobals.Select(g => (g.Name, g.Value & 0xffffffff, g.Type)).ToArray(); + + ValidateGlobals(target, expected); + } + } + + private static void WritePointer(Span dest, ulong value, bool isLittleEndian, int pointerSize) + { + if (pointerSize == sizeof(ulong)) + { + if (isLittleEndian) + { + BinaryPrimitives.WriteUInt64LittleEndian(dest, value); + } + else + { + BinaryPrimitives.WriteUInt64BigEndian(dest, value); + } + } + else if (pointerSize == sizeof(uint)) + { + if (isLittleEndian) + { + BinaryPrimitives.WriteUInt32LittleEndian(dest, (uint)value); + } + else + { + BinaryPrimitives.WriteUInt32BigEndian(dest, (uint)value); + } + } + } + + private static void ValidateGlobals( + Target target, + (string Name, ulong Value, string? Type)[] globals, + [CallerMemberName] string caller = "", + [CallerFilePath] string filePath = "", + [CallerLineNumber] int lineNumber = 0) + { + foreach (var (name, value, type) in globals) + { + // Validate that each global can/cannot be read successfully based on its type + // and that it matches the expected value if successfully read + { + bool success = target.TryReadGlobal(name, out sbyte actual); + AssertEqualsWithCallerInfo(type is null || type == "int8", success); + if (success) + AssertEqualsWithCallerInfo((sbyte)value, actual); + } + { + bool success = target.TryReadGlobal(name, out byte actual); + AssertEqualsWithCallerInfo(type is null || type == "uint8", success); + if (success) + AssertEqualsWithCallerInfo(value, actual); + } + { + bool success = target.TryReadGlobal(name, out short actual); + AssertEqualsWithCallerInfo(type is null || type == "int16", success); + if (success) + AssertEqualsWithCallerInfo((short)value, actual); + } + { + bool success = target.TryReadGlobal(name, out ushort actual); + AssertEqualsWithCallerInfo(type is null || type == "uint16", success); + if (success) + AssertEqualsWithCallerInfo(value, actual); + } + { + bool success = target.TryReadGlobal(name, out int actual); + AssertEqualsWithCallerInfo(type is null || type == "int32", success); + if (success) + AssertEqualsWithCallerInfo((int)value, actual); + } + { + bool success = target.TryReadGlobal(name, out uint actual); + AssertEqualsWithCallerInfo(type is null || type == "uint32", success); + if (success) + AssertEqualsWithCallerInfo(value, actual); + } + { + bool success = target.TryReadGlobal(name, out long actual); + AssertEqualsWithCallerInfo(type is null || type == "int64", success); + if (success) + AssertEqualsWithCallerInfo((long)value, actual); + } + { + bool success = target.TryReadGlobal(name, out ulong actual); + AssertEqualsWithCallerInfo(type is null || type == "uint64", success); + if (success) + AssertEqualsWithCallerInfo(value, actual); + } + { + bool success = target.TryReadGlobalPointer(name, out TargetPointer actual); + AssertEqualsWithCallerInfo(type is null || type == "pointer" || type == "nint" || type == "nuint", success); + if (success) + AssertEqualsWithCallerInfo(value, actual.Value); + } + } + + void AssertEqualsWithCallerInfo(T expected, T actual) where T : unmanaged + { + Assert.True(expected.Equals(actual), $"Expected: {expected}. Actual: {actual}. [test case: {caller} in {filePath}:{lineNumber}]"); + } + } + + [UnmanagedCallersOnly] + private static int ReadFromTarget(ulong address, byte* buffer, uint length, void* context) + { + ReadContext* readContext = (ReadContext*)context; + var span = new Span(buffer, (int)length); + + // Populate the span with the requested portion of the contract descriptor + if (address >= ContractDescriptorAddr && address <= ContractDescriptorAddr + (ulong)readContext->ContractDescriptorLength - length) + { + ulong offset = address - ContractDescriptorAddr; + new ReadOnlySpan(readContext->ContractDescriptor + offset, (int)length).CopyTo(span); + return 0; + } + + // Populate the span with the JSON descriptor - this assumes the product will read it all at once. + if (address == JsonDescriptorAddr) + { + new ReadOnlySpan(readContext->JsonDescriptor, readContext->JsonDescriptorLength).CopyTo(span); + return 0; + } + + // Populate the span with the requested portion of the pointer data + if (address >= PointerDataAddr && address <= PointerDataAddr + (ulong)readContext->PointerDataLength - length) + { + ulong offset = address - PointerDataAddr; + new ReadOnlySpan(readContext->PointerData + offset, (int)length).CopyTo(span); + return 0; + } + + return -1; + } + + // Used by ReadFromTarget to return the appropriate bytes + private struct ReadContext + { + public byte* ContractDescriptor; + public int ContractDescriptorLength; + + public byte* JsonDescriptor; + public int JsonDescriptorLength; + + public byte* PointerData; + public int PointerDataLength; + } + + private static class ContractDescriptor + { + public static int Size(bool is64Bit) => is64Bit ? sizeof(ContractDescriptor64) : sizeof(ContractDescriptor32); + + public static void Fill(Span dest, bool isLittleEndian, bool is64Bit, int jsonDescriptorSize, int pointerDataCount) + { + if (is64Bit) + { + ContractDescriptor64.Fill(dest, isLittleEndian, jsonDescriptorSize, pointerDataCount); + } + else + { + ContractDescriptor32.Fill(dest, isLittleEndian, jsonDescriptorSize, pointerDataCount); + } + } + + private struct ContractDescriptor32 + { + public ulong Magic = BitConverter.ToUInt64("DNCCDAC\0"u8); + public uint Flags = 0x2 /*32-bit*/ | 0x1; + public uint DescriptorSize; + public uint Descriptor = JsonDescriptorAddr; + public uint PointerDataCount; + public uint Pad0 = 0; + public uint PointerData = PointerDataAddr; + + public ContractDescriptor32() { } + + public static void Fill(Span dest, bool isLittleEndian, int jsonDescriptorSize, int pointerDataCount) + { + ContractDescriptor32 descriptor = new() + { + DescriptorSize = (uint)jsonDescriptorSize, + PointerDataCount = (uint)pointerDataCount, + }; + if (BitConverter.IsLittleEndian != isLittleEndian) + descriptor.ReverseEndianness(); + + MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref descriptor, 1)).CopyTo(dest); + } + + private void ReverseEndianness() + { + Magic = BinaryPrimitives.ReverseEndianness(Magic); + Flags = BinaryPrimitives.ReverseEndianness(Flags); + DescriptorSize = BinaryPrimitives.ReverseEndianness(DescriptorSize); + Descriptor = BinaryPrimitives.ReverseEndianness(Descriptor); + PointerDataCount = BinaryPrimitives.ReverseEndianness(PointerDataCount); + Pad0 = BinaryPrimitives.ReverseEndianness(Pad0); + PointerData = BinaryPrimitives.ReverseEndianness(PointerData); + } + } + + private struct ContractDescriptor64 + { + public ulong Magic = BitConverter.ToUInt64("DNCCDAC\0"u8); + public uint Flags = 0x1; + public uint DescriptorSize; + public ulong Descriptor = JsonDescriptorAddr; + public uint PointerDataCount; + public uint Pad0 = 0; + public ulong PointerData = PointerDataAddr; + + public ContractDescriptor64() { } + + public static void Fill(Span dest, bool isLittleEndian, int jsonDescriptorSize, int pointerDataCount) + { + ContractDescriptor64 descriptor = new() + { + DescriptorSize = (uint)jsonDescriptorSize, + PointerDataCount = (uint)pointerDataCount, + }; + if (BitConverter.IsLittleEndian != isLittleEndian) + descriptor.ReverseEndianness(); + + MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref descriptor, 1)).CopyTo(dest); + } + + private void ReverseEndianness() + { + Magic = BinaryPrimitives.ReverseEndianness(Magic); + Flags = BinaryPrimitives.ReverseEndianness(Flags); + DescriptorSize = BinaryPrimitives.ReverseEndianness(DescriptorSize); + Descriptor = BinaryPrimitives.ReverseEndianness(Descriptor); + PointerDataCount = BinaryPrimitives.ReverseEndianness(PointerDataCount); + Pad0 = BinaryPrimitives.ReverseEndianness(Pad0); + PointerData = BinaryPrimitives.ReverseEndianness(PointerData); + } + } + } + +} From f5ea326fff2f89ab8188950531c0290d2ae7a827 Mon Sep 17 00:00:00 2001 From: Dan Moseley Date: Thu, 25 Apr 2024 20:53:56 -0700 Subject: [PATCH 127/248] remove nuget (#101584) --- .github/dependabot.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index aea8ab73e1ef04..9a538c12cfa42d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,10 +1,5 @@ version: 2 -registries: - public-nuget: - type: nuget-feed - url: https://api.nuget.org/v3/index.json updates: - - package-ecosystem: "github-actions" directory: "/" schedule: From a45853c4751b5f532cdb38e3db5d4324b5ca878a Mon Sep 17 00:00:00 2001 From: Xu Liangyu Date: Fri, 26 Apr 2024 12:54:46 +0800 Subject: [PATCH 128/248] [LoongArch64] Add some R2R missing codes. (#101480) --- .../tools/Common/Compiler/InstructionSetSupport.cs | 4 ++++ .../Common/Compiler/VectorFieldLayoutAlgorithm.cs | 10 ++++++++++ src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs | 3 ++- .../JitInterface/LoongArch64PassStructInRegister.cs | 6 ------ .../tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs | 1 + .../ReadyToRunDiagnosticsConstants.cs | 1 + src/coreclr/vm/methodtablebuilder.cpp | 6 ++++++ .../Reflection/PortableExecutable/PEHeaderBuilder.cs | 2 +- src/tasks/Crossgen2Tasks/ResolveReadyToRunCompilers.cs | 4 ++++ 9 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs b/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs index a1725f3db9d928..f6c34091bc0fe9 100644 --- a/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs +++ b/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs @@ -97,6 +97,10 @@ public static string GetHardwareIntrinsicId(TargetArchitecture architecture, Typ if (potentialType.Namespace != "System.Runtime.Intrinsics.Arm") return ""; } + else if (architecture == TargetArchitecture.LoongArch64) + { + return ""; + } else if (architecture == TargetArchitecture.RiscV64) { return ""; diff --git a/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs index bb0a5bc71a626c..1f3722ab019bcc 100644 --- a/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs @@ -58,6 +58,11 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp // 16-byte alignment for __m256. alignment = new LayoutInt(16); } + else if (defType.Context.Target.Architecture == TargetArchitecture.LoongArch64) + { + // TODO-LoongArch64: Update alignment to proper value when implement LoongArch64 intrinsic. + alignment = new LayoutInt(16); + } else if (defType.Context.Target.Architecture == TargetArchitecture.RiscV64) { // TODO-RISCV64: Update alignment to proper value when we implement RISC-V intrinsic. @@ -86,6 +91,11 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp // 16-byte alignment for __m256. alignment = new LayoutInt(16); } + else if (defType.Context.Target.Architecture == TargetArchitecture.LoongArch64) + { + // TODO-LoongArch64: Update alignment to proper value when implement LoongArch64 intrinsic. + alignment = new LayoutInt(16); + } else if (defType.Context.Target.Architecture == TargetArchitecture.RiscV64) { // TODO-RISCV64: Update alignment to proper value when we implement RISC-V intrinsic. diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 7719b39aa7e852..ed04f8625d486e 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -415,9 +415,10 @@ private CompilationResult CompileMethodInternal(IMethodNode methodCodeNodeNeedin if (codeSize < _code.Length) { if (_compilation.TypeSystemContext.Target.Architecture != TargetArchitecture.ARM64 + && _compilation.TypeSystemContext.Target.Architecture != TargetArchitecture.LoongArch64 && _compilation.TypeSystemContext.Target.Architecture != TargetArchitecture.RiscV64) { - // For xarch/arm32/RiscV64, the generated code is sometimes smaller than the memory allocated. + // For xarch/arm32/LoongArch64/RiscV64, the generated code is sometimes smaller than the memory allocated. // In that case, trim the codeBlock to the actual value. // // For arm64, the allocation request of `hotCodeSize` also includes the roData size diff --git a/src/coreclr/tools/Common/JitInterface/LoongArch64PassStructInRegister.cs b/src/coreclr/tools/Common/JitInterface/LoongArch64PassStructInRegister.cs index b0c193d0950071..856b9905a1fb43 100644 --- a/src/coreclr/tools/Common/JitInterface/LoongArch64PassStructInRegister.cs +++ b/src/coreclr/tools/Common/JitInterface/LoongArch64PassStructInRegister.cs @@ -29,12 +29,6 @@ public static uint GetLoongArch64PassStructInRegisterFlags(TypeDesc typeDesc) return (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; } - //// The SIMD Intrinsic types are meant to be handled specially and should not be passed as struct registers - if (typeDesc.IsIntrinsic) - { - throw new NotImplementedException("For LoongArch64, SIMD would be implemented later"); - } - MetadataType mdType = typeDesc as MetadataType; Debug.Assert(mdType != null); diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs index 98941b37c185e4..16f82023ad0b57 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs @@ -136,6 +136,7 @@ private static PerfmapTokensForTarget TranslateTargetDetailsToPerfmapConstants(T TargetArchitecture.X64 => PerfMapArchitectureToken.X64, TargetArchitecture.X86 => PerfMapArchitectureToken.X86, TargetArchitecture.RiscV64 => PerfMapArchitectureToken.RiscV64, + TargetArchitecture.LoongArch64 => PerfMapArchitectureToken.LoongArch64, _ => throw new NotImplementedException(details.Architecture.ToString()) }; diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ReadyToRunDiagnosticsConstants.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ReadyToRunDiagnosticsConstants.cs index 395b26f151ee83..281349be80e52e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ReadyToRunDiagnosticsConstants.cs +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ReadyToRunDiagnosticsConstants.cs @@ -20,6 +20,7 @@ public enum PerfMapArchitectureToken : uint X64 = 3, X86 = 4, RiscV64 = 5, + LoongArch64 = 6, } public enum PerfMapOSToken : uint diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 69d2a105ecd8d5..db015d227538e2 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -10051,6 +10051,9 @@ void MethodTableBuilder::CheckForSystemTypes() // The Procedure Call Standard for ARM 64-bit (with SVE support) defaults to // 16-byte alignment for __m256. + pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; + #elif defined(TARGET_LOONGARCH64) + // TODO-LoongArch64: Update alignment to proper value when implement LoongArch64 intrinsic. pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; #elif defined(TARGET_RISCV64) // TODO-RISCV64: Update alignment to proper value when we implement RISC-V intrinsic. @@ -10074,6 +10077,9 @@ void MethodTableBuilder::CheckForSystemTypes() pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; + #elif defined(TARGET_LOONGARCH64) + // TODO-LoongArch64: Update alignment to proper value when implement LoongArch64 intrinsic. + pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; #elif defined(TARGET_RISCV64) // TODO-RISCV64: Update alignment to proper value when we implement RISC-V intrinsic. // RISC-V Vector Extenstion Intrinsic Document diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaderBuilder.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaderBuilder.cs index f93b8bc0716de8..9ddb82d35aa4e3 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaderBuilder.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaderBuilder.cs @@ -105,7 +105,7 @@ public static PEHeaderBuilder CreateLibraryHeader() return new PEHeaderBuilder(imageCharacteristics: Characteristics.ExecutableImage | Characteristics.Dll); } - internal bool Is32Bit => Machine != Machine.Amd64 && Machine != Machine.IA64 && Machine != Machine.Arm64 && Machine != Machine.RiscV64; + internal bool Is32Bit => Machine != Machine.Amd64 && Machine != Machine.IA64 && Machine != Machine.Arm64 && Machine != Machine.LoongArch64 && Machine != Machine.RiscV64; internal int ComputeSizeOfPEHeaders(int sectionCount) => PEBuilder.DosHeaderSize + diff --git a/src/tasks/Crossgen2Tasks/ResolveReadyToRunCompilers.cs b/src/tasks/Crossgen2Tasks/ResolveReadyToRunCompilers.cs index 843333ff3fcbbd..1ec6c1a090a69b 100644 --- a/src/tasks/Crossgen2Tasks/ResolveReadyToRunCompilers.cs +++ b/src/tasks/Crossgen2Tasks/ResolveReadyToRunCompilers.cs @@ -233,6 +233,9 @@ private static bool ExtractTargetPlatformAndArchitecture(string runtimeIdentifie case "riscv64": architecture = Architecture.RiscV64; break; + case "loongarch64": + architecture = Architecture.LoongArch64; + break; default: return false; } @@ -391,6 +394,7 @@ private static string ArchitectureToString(Architecture architecture) Architecture.Arm => "arm", Architecture.Arm64 => "arm64", Architecture.RiscV64 => "riscv64", + Architecture.LoongArch64 => "loongarch64", _ => null }; } From aec52ab4133dc6fd7b728a56ee4760e613853508 Mon Sep 17 00:00:00 2001 From: Xu Liangyu Date: Fri, 26 Apr 2024 15:57:40 +0800 Subject: [PATCH 129/248] [LoongArch64] Enable printing disassembly instructions under release mode for JitDisasm. (#101281) --- src/coreclr/jit/emitloongarch64.cpp | 57 ++++++----------------------- src/coreclr/jit/emitloongarch64.h | 5 --- 2 files changed, 11 insertions(+), 51 deletions(-) diff --git a/src/coreclr/jit/emitloongarch64.cpp b/src/coreclr/jit/emitloongarch64.cpp index 8d8ccbc2a88ed1..63d4e9a975b9b1 100644 --- a/src/coreclr/jit/emitloongarch64.cpp +++ b/src/coreclr/jit/emitloongarch64.cpp @@ -3848,8 +3848,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) } } -#ifdef DEBUG - if (emitComp->opts.disAsm || emitComp->verbose) + if (emitComp->opts.disAsm INDEBUG(|| emitComp->verbose)) { code_t* cp = (code_t*)(*dp + writeableOffset); while ((BYTE*)cp != dstRW) @@ -3859,6 +3858,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) } } +#ifdef DEBUG if (emitComp->compDebugBreak) { // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for @@ -3882,8 +3882,6 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) /*****************************************************************************/ /*****************************************************************************/ -#ifdef DEBUG - // clang-format off static const char* const RegNames[] = { @@ -3964,19 +3962,21 @@ void emitter::emitDisInsName(code_t code, const BYTE* addr, instrDesc* id) { const BYTE* insAdr = addr - writeableOffset; - bool disOpcode = !emitComp->opts.disDiffable; - bool disAddr = emitComp->opts.disAddr; - if (disAddr) +#ifdef DEBUG + if (emitComp->opts.disAddr) { printf(" 0x%llx", insAdr); } printf(" "); - if (disOpcode) + if (!emitComp->opts.disDiffable) { printf("%08X ", code); } +#else + printf(" "); +#endif const int regd = code & 0x1f; const int regj = (code >> 5) & 0x1f; @@ -4540,51 +4540,16 @@ void emitter::emitDispIns( } } +#ifdef DEBUG /***************************************************************************** * * Display a stack frame reference. */ - void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm) { - printf("["); - - if (varx < 0) - printf("TEMP_%02u", -varx); - else - emitComp->gtDispLclVar(+varx, false); - - if (disp < 0) - printf("-0x%02x", -disp); - else if (disp > 0) - printf("+0x%02x", +disp); - - printf("]"); - - if (varx >= 0 && emitComp->opts.varNames) - { - LclVarDsc* varDsc; - const char* varName; - - assert((unsigned)varx < emitComp->lvaCount); - varDsc = emitComp->lvaTable + varx; - varName = emitComp->compLocalVarName(varx, offs); - - if (varName) - { - printf("'%s", varName); - - if (disp < 0) - printf("-%d", -disp); - else if (disp > 0) - printf("+%d", +disp); - - printf("'"); - } - } + NYI_LOONGARCH64("emitDispFrameRef-----unused on LoongArch64."); } - -#endif // DEBUG +#endif // Generate code for a load or store operation with a potentially complex addressing mode // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset] diff --git a/src/coreclr/jit/emitloongarch64.h b/src/coreclr/jit/emitloongarch64.h index afaca5b2ba04b8..bae6d188ca1f79 100644 --- a/src/coreclr/jit/emitloongarch64.h +++ b/src/coreclr/jit/emitloongarch64.h @@ -19,10 +19,6 @@ struct CnsVal bool cnsReloc; }; -#ifdef DEBUG -/************************************************************************/ -/* Debug-only routines to display instructions */ -/************************************************************************/ enum insDisasmFmt { DF_G_INVALID = 0, @@ -108,7 +104,6 @@ code_t emitGetInsMask(int ins); insDisasmFmt emitGetInsFmt(instruction ins); void emitDispInst(instruction ins); void emitDisInsName(code_t code, const BYTE* addr, instrDesc* id); -#endif // DEBUG void emitIns_J_cond_la(instruction ins, BasicBlock* dst, regNumber reg1 = REG_R0, regNumber reg2 = REG_R0); void emitIns_I_la(emitAttr attr, regNumber reg, ssize_t imm); From 99dd60d8886155bb60768c8ef5a5a3225ad95ba4 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Fri, 26 Apr 2024 10:00:38 +0200 Subject: [PATCH 130/248] JIT: Check more invariants on ABI info and fix some arm32 bugs (#101372) - Implicit byref parameters should be passed as a single pointer sized segment - Segments should not point outside the local size - Segments should not overlap each other - Segments should have size > 0 - Segments should be ordered by offset - Fix a bug in the arm32 classifier when structs are split - Fix a bug in the arm32 classifier for odd-sized structs with 8 byte alignment. For example ```csharp [StructLayout(LayoutKind.Sequential, Size = 12)] struct S { public double X; public float Y; } ``` would be considered to take 4 slots before. - Fix a bug in the Swift classifier that would cause the tail segments to have an out-of-bounds size --- src/coreclr/jit/abi.cpp | 3 +++ src/coreclr/jit/codegencommon.cpp | 4 ++++ src/coreclr/jit/lclvars.cpp | 36 +++++++++++++++++++++++++++++++ src/coreclr/jit/targetarm.cpp | 10 ++++----- 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/coreclr/jit/abi.cpp b/src/coreclr/jit/abi.cpp index fd899b899546b1..c6dbd8aa9202fd 100644 --- a/src/coreclr/jit/abi.cpp +++ b/src/coreclr/jit/abi.cpp @@ -415,6 +415,9 @@ ABIPassingInformation SwiftABIClassifier::Classify(Compiler* comp, { ABIPassingSegment newSegment = elemInfo.Segments[j]; newSegment.Offset += lowering->offsets[i]; + // Adjust the tail size if necessary; the lowered sequence can + // pass the tail as a larger type than the tail size. + newSegment.Size = min(newSegment.Size, structLayout->GetSize() - newSegment.Offset); segments.Push(newSegment); } } diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index c8211a7e731440..9f3120d274d57d 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -4185,9 +4185,13 @@ void CodeGen::genHomeSwiftStructParameters(bool handleStack) case 2: loadType = TYP_USHORT; break; + case 3: case 4: loadType = TYP_INT; break; + case 5: + case 6: + case 7: case 8: loadType = TYP_LONG; break; diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index e6645e1f03d8f4..97986eefee4b27 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -1885,6 +1885,42 @@ void Compiler::lvaClassifyParameterABI() } } } + + for (unsigned lclNum = 0; lclNum < info.compArgsCount; lclNum++) + { + const ABIPassingInformation& abiInfo = lvaGetParameterABIInfo(lclNum); + + if (lvaIsImplicitByRefLocal(lclNum)) + { + assert((abiInfo.NumSegments == 1) && (abiInfo.Segments[0].Size == TARGET_POINTER_SIZE)); + } + else + { + for (unsigned i = 0; i < abiInfo.NumSegments; i++) + { + const ABIPassingSegment& segment = abiInfo.Segments[i]; + assert(segment.Size > 0); + assert(segment.Offset + segment.Size <= lvaLclExactSize(lclNum)); + + if (i > 0) + { + assert(segment.Offset > abiInfo.Segments[i - 1].Offset); + } + + for (unsigned j = 0; j < abiInfo.NumSegments; j++) + { + if (i == j) + { + continue; + } + + const ABIPassingSegment& otherSegment = abiInfo.Segments[j]; + assert((segment.Offset + segment.Size <= otherSegment.Offset) || + (segment.Offset >= otherSegment.Offset + otherSegment.Size)); + } + } + } + } #endif // DEBUG } diff --git a/src/coreclr/jit/targetarm.cpp b/src/coreclr/jit/targetarm.cpp index 037578fa67b85c..675fd04230d531 100644 --- a/src/coreclr/jit/targetarm.cpp +++ b/src/coreclr/jit/targetarm.cpp @@ -85,11 +85,11 @@ ABIPassingInformation Arm32Classifier::Classify(Compiler* comp, m_nextIntReg = roundUp(m_nextIntReg, 2); } - unsigned size = type == TYP_STRUCT ? structLayout->GetSize() : genTypeSize(type); - unsigned alignedSize = roundUp(size, alignment); + unsigned size = type == TYP_STRUCT ? structLayout->GetSize() : genTypeSize(type); + unsigned numSlots = (size + 3) / 4; - unsigned numInRegs = min(alignedSize / 4, 4 - m_nextIntReg); - bool anyOnStack = numInRegs < (alignedSize / 4); + unsigned numInRegs = min(numSlots, 4 - m_nextIntReg); + bool anyOnStack = numInRegs < numSlots; // If we already passed anything on stack (due to float args) then we // cannot split an arg. @@ -116,7 +116,7 @@ ABIPassingInformation Arm32Classifier::Classify(Compiler* comp, { m_stackArgSize = roundUp(m_stackArgSize, alignment); unsigned stackSize = size - (numInRegs * 4); - info.Segments[numInRegs] = ABIPassingSegment::OnStack(m_stackArgSize, 0, stackSize); + info.Segments[numInRegs] = ABIPassingSegment::OnStack(m_stackArgSize, numInRegs * 4, stackSize); m_stackArgSize += roundUp(stackSize, 4); // As soon as any int arg goes on stack we cannot put anything else in From 0f508f26cd22fffb7e8ab0ed3f7133ee48f3a6a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Fri, 26 Apr 2024 21:58:39 +0900 Subject: [PATCH 131/248] Allow preinitializing `EventSource` (#101573) We currently don't preinitialize any event sources because they have a finalizer. This is a bit of a problem for places like this: https://github.com/dotnet/runtime/blob/5c01ed22b7468a2bee13b498855dcfcc5ae4da50/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncTaskMethodBuilderT.cs#L229-L232. We know `IsSupported` is false so we eliminate the branch, but we still need a cctor check because we access a static. The cctor check in a generic method that is instantiated many many many times becomes a death by a thousand papercuts. Saves 0.7% in size on the stage2 app with EventSource disabled. --- .../aot/ILCompiler.Compiler/Compiler/TypePreinit.cs | 10 ++++++++-- .../src/ILLink/ILLink.Substitutions.Shared.xml | 1 + .../src/System/Diagnostics/Tracing/EventSource.cs | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs index 19d8ee6efd959b..37a7d0de344893 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs @@ -533,8 +533,14 @@ private Status TryScanMethod(MethodIL methodIL, Value[] parameters, Stack + 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 265035996eee0b..48cab155a9425c 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 @@ -1461,6 +1461,8 @@ public void Dispose() /// True if called from Dispose(), false if called from the finalizer. protected virtual void Dispose(bool disposing) { + // NOTE: If !IsSupported, we use ILLink.Substitutions to nop out the finalizer. + // Do not add any code before this line (or you'd need to delete the substitution). if (!IsSupported) { return; @@ -1504,6 +1506,7 @@ protected virtual void Dispose(bool disposing) /// ~EventSource() { + // NOTE: we nop out this method body if !IsSupported using ILLink.Substitutions. this.Dispose(false); } #endregion From be49b323fa18c8e2d6256ae023bc6336a4f2263a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Fri, 26 Apr 2024 15:42:27 +0200 Subject: [PATCH 132/248] Reenable disabled test on s390x in ParallelForEachAsyncTests.cs (#101527) --- .../tests/ParallelForEachAsyncTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForEachAsyncTests.cs b/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForEachAsyncTests.cs index 01a4dd37908ee7..77c16ddd72c928 100644 --- a/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForEachAsyncTests.cs +++ b/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForEachAsyncTests.cs @@ -459,7 +459,6 @@ await Parallel.ForEachAsync(EnumerableRangeAsync(0, 0), (item, cancellationToken [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [InlineData(false)] [InlineData(true)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/101380", typeof(PlatformDetection), nameof(PlatformDetection.IsS390xProcess))] public async Task AllItemsEnumeratedOnce_For(bool yield) { await Test(yield); From 9892d46d0789329919d9a17f275fd1fff603b76f Mon Sep 17 00:00:00 2001 From: SwapnilGaikwad Date: Fri, 26 Apr 2024 15:02:35 +0100 Subject: [PATCH 133/248] Add support for Sve.UnzipEven/Odd & Sve.ZipHighLow (#101294) * Add support for Sve.UnzipEven/Odd & Sve.ZipHighLow * Rename the test template --------- Co-authored-by: Kunal Pathak --- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 9 + src/coreclr/jit/hwintrinsiclistarm64sve.h | 5 + .../Arm/Sve.PlatformNotSupported.cs | 255 ++++++++++++++ .../src/System/Runtime/Intrinsics/Arm/Sve.cs | 282 +++++++++++++++ .../ref/System.Runtime.Intrinsics.cs | 43 +++ .../GenerateHWIntrinsicTests_Arm.cs | 109 ++++-- .../Shared/_BinaryOp_SveTestTemplate.template | 327 ++++++++++++++++++ 7 files changed, 996 insertions(+), 34 deletions(-) create mode 100644 src/tests/JIT/HardwareIntrinsics/Arm/Shared/_BinaryOp_SveTestTemplate.template diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index edabd7030359f7..462aaa521c6756 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -1443,6 +1443,15 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) break; } + case NI_Sve_UnzipEven: + case NI_Sve_UnzipOdd: + case NI_Sve_ZipHigh: + case NI_Sve_ZipLow: + // Use non-predicated version explicitly + GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt, + INS_SCALABLE_OPTS_UNPREDICATED); + break; + default: unreached(); } diff --git a/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/coreclr/jit/hwintrinsiclistarm64sve.h index 4cc3e86a170ff3..773b3766a28a55 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64sve.h +++ b/src/coreclr/jit/hwintrinsiclistarm64sve.h @@ -64,6 +64,11 @@ HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToUInt64, HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, UnzipEven, -1, 2, true, {INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, UnzipOdd, -1, 2, true, {INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, ZipHigh, -1, 2, true, {INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, ZipLow, -1, 2, true, {INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) + // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs index 918b8664739b62..f23fb1b8ee2c7d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs @@ -806,5 +806,260 @@ internal Arm64() { } public static unsafe Vector LoadVectorUInt32ZeroExtendToUInt64(Vector mask, uint* address) { throw new PlatformNotSupportedException(); } + /// UnzipEven : Concatenate even elements from two inputs + + /// + /// svint8_t svuzp1[_s8](svint8_t op1, svint8_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svuzp1[_s16](svint16_t op1, svint16_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svuzp1[_s32](svint32_t op1, svint32_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svuzp1[_s64](svint64_t op1, svint64_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint8_t svuzp1[_u8](svuint8_t op1, svuint8_t op2) + /// svbool_t svuzp1_b8(svbool_t op1, svbool_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svuzp1[_u16](svuint16_t op1, svuint16_t op2) + /// svbool_t svuzp1_b16(svbool_t op1, svbool_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svuzp1[_u32](svuint32_t op1, svuint32_t op2) + /// svbool_t svuzp1_b32(svbool_t op1, svbool_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svuzp1[_u64](svuint64_t op1, svuint64_t op2) + /// svbool_t svuzp1_b64(svbool_t op1, svbool_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svuzp1[_f32](svfloat32_t op1, svfloat32_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svuzp1[_f64](svfloat64_t op1, svfloat64_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// UnzipOdd : Concatenate odd elements from two inputs + + /// + /// svuint8_t svuzp2[_u8](svuint8_t op1, svuint8_t op2) + /// svbool_t svuzp2_b8(svbool_t op1, svbool_t op2) + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svuzp2[_f64](svfloat64_t op1, svfloat64_t op2) + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svuzp2[_s16](svint16_t op1, svint16_t op2) + /// UZP2 Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svuzp2[_s32](svint32_t op1, svint32_t op2) + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svuzp2[_s64](svint64_t op1, svint64_t op2) + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svuzp2[_s8](svint8_t op1, svint8_t op2) + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svuzp2[_f32](svfloat32_t op1, svfloat32_t op2) + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svuzp2[_u16](svuint16_t op1, svuint16_t op2) + /// svbool_t svuzp2_b16(svbool_t op1, svbool_t op2) + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svuzp2[_u32](svuint32_t op1, svuint32_t op2) + /// svbool_t svuzp2_b32(svbool_t op1, svbool_t op2) + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svuzp2[_u64](svuint64_t op1, svuint64_t op2) + /// svbool_t svuzp2_b64(svbool_t op1, svbool_t op2) + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// ZipHigh : Interleave elements from high halves of two inputs + + /// + /// svuint8_t svzip2[_u8](svuint8_t op1, svuint8_t op2) + /// ZIP2 Zresult.B, Zop1.B, Zop2.B + /// svbool_t svzip2_b8(svbool_t op1, svbool_t op2) + /// ZIP2 Presult.B, Pop1.B, Pop2.B + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svzip2[_f64](svfloat64_t op1, svfloat64_t op2) + /// ZIP2 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svzip2[_s16](svint16_t op1, svint16_t op2) + /// ZIP2 Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svzip2[_s32](svint32_t op1, svint32_t op2) + /// ZIP2 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svzip2[_s64](svint64_t op1, svint64_t op2) + /// ZIP2 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svzip2[_s8](svint8_t op1, svint8_t op2) + /// ZIP2 Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svzip2[_f32](svfloat32_t op1, svfloat32_t op2) + /// ZIP2 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svzip2[_u16](svuint16_t op1, svuint16_t op2) + /// ZIP2 Zresult.H, Zop1.H, Zop2.H + /// svbool_t svzip2_b16(svbool_t op1, svbool_t op2) + /// ZIP2 Presult.H, Pop1.H, Pop2.H + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svzip2[_u32](svuint32_t op1, svuint32_t op2) + /// ZIP2 Zresult.S, Zop1.S, Zop2.S + /// svbool_t svzip2_b32(svbool_t op1, svbool_t op2) + /// ZIP2 Presult.S, Pop1.S, Pop2.S + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svzip2[_u64](svuint64_t op1, svuint64_t op2) + /// ZIP2 Zresult.D, Zop1.D, Zop2.D + /// svbool_t svzip2_b64(svbool_t op1, svbool_t op2) + /// ZIP2 Presult.D, Pop1.D, Pop2.D + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// ZipLow : Interleave elements from low halves of two inputs + + /// + /// svuint8_t svzip1[_u8](svuint8_t op1, svuint8_t op2) + /// ZIP1 Zresult.B, Zop1.B, Zop2.B + /// svbool_t svzip1_b8(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.B, Pop1.B, Pop2.B + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svzip1[_f64](svfloat64_t op1, svfloat64_t op2) + /// ZIP1 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svzip1[_s16](svint16_t op1, svint16_t op2) + /// ZIP1 Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svzip1[_s32](svint32_t op1, svint32_t op2) + /// ZIP1 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svzip1[_s64](svint64_t op1, svint64_t op2) + /// ZIP1 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svzip1[_s8](svint8_t op1, svint8_t op2) + /// ZIP1 Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svzip1[_f32](svfloat32_t op1, svfloat32_t op2) + /// ZIP1 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svzip1[_u16](svuint16_t op1, svuint16_t op2) + /// ZIP1 Zresult.H, Zop1.H, Zop2.H + /// svbool_t svzip1_b16(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.H, Pop1.H, Pop2.H + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svzip1[_u32](svuint32_t op1, svuint32_t op2) + /// ZIP1 Zresult.S, Zop1.S, Zop2.S + /// svbool_t svzip1_b32(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.S, Pop1.S, Pop2.S + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svzip1[_u64](svuint64_t op1, svuint64_t op2) + /// ZIP1 Zresult.D, Zop1.D, Zop2.D + /// svbool_t svzip1_b64(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.D, Pop1.D, Pop2.D + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs index 98f1824f5ecfea..494607f5952c46 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs @@ -861,5 +861,287 @@ internal Arm64() { } public static unsafe Vector LoadVectorUInt32ZeroExtendToUInt64(Vector mask, uint* address) => LoadVectorUInt32ZeroExtendToUInt64(mask, address); + /// UnzipEven : Concatenate even elements from two inputs + + /// + /// svuint8_t svuzp1[_u8](svuint8_t op1, svuint8_t op2) + /// UZP1 Zresult.B, Zop1.B, Zop2.B + /// svbool_t svuzp1_b8(svbool_t op1, svbool_t op2) + /// UZP1 Presult.B, Pop1.B, Pop2.B + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); + + /// + /// svfloat64_t svuzp1[_f64](svfloat64_t op1, svfloat64_t op2) + /// UZP1 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); + + /// + /// svint16_t svuzp1[_s16](svint16_t op1, svint16_t op2) + /// UZP1 Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); + + /// + /// svint32_t svuzp1[_s32](svint32_t op1, svint32_t op2) + /// UZP1 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); + + /// + /// svint64_t svuzp1[_s64](svint64_t op1, svint64_t op2) + /// UZP1 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); + + /// + /// svint8_t svuzp1[_s8](svint8_t op1, svint8_t op2) + /// UZP1 Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); + + /// + /// svfloat32_t svuzp1[_f32](svfloat32_t op1, svfloat32_t op2) + /// UZP1 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); + + /// + /// svuint16_t svuzp1[_u16](svuint16_t op1, svuint16_t op2) + /// UZP1 Zresult.H, Zop1.H, Zop2.H + /// svbool_t svuzp1_b16(svbool_t op1, svbool_t op2) + /// UZP1 Presult.H, Pop1.H, Pop2.H + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); + + /// + /// svuint32_t svuzp1[_u32](svuint32_t op1, svuint32_t op2) + /// UZP1 Zresult.S, Zop1.S, Zop2.S + /// svbool_t svuzp1_b32(svbool_t op1, svbool_t op2) + /// UZP1 Presult.S, Pop1.S, Pop2.S + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); + + /// + /// svuint64_t svuzp1[_u64](svuint64_t op1, svuint64_t op2) + /// UZP1 Zresult.D, Zop1.D, Zop2.D + /// svbool_t svuzp1_b64(svbool_t op1, svbool_t op2) + /// UZP1 Presult.D, Pop1.D, Pop2.D + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); + + + /// UnzipOdd : Concatenate odd elements from two inputs + + /// + /// svuint8_t svuzp2[_u8](svuint8_t op1, svuint8_t op2) + /// UZP2 Zresult.B, Zop1.B, Zop2.B + /// svbool_t svuzp2_b8(svbool_t op1, svbool_t op2) + /// UZP2 Presult.B, Pop1.B, Pop2.B + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + + /// + /// svfloat64_t svuzp2[_f64](svfloat64_t op1, svfloat64_t op2) + /// UZP2 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + + /// + /// svint16_t svuzp2[_s16](svint16_t op1, svint16_t op2) + /// UZP2 Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + + /// + /// svint32_t svuzp2[_s32](svint32_t op1, svint32_t op2) + /// UZP2 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + + /// + /// svint64_t svuzp2[_s64](svint64_t op1, svint64_t op2) + /// UZP2 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + + /// + /// svint8_t svuzp2[_s8](svint8_t op1, svint8_t op2) + /// UZP2 Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + + /// + /// svfloat32_t svuzp2[_f32](svfloat32_t op1, svfloat32_t op2) + /// UZP2 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + + /// + /// svuint16_t svuzp2[_u16](svuint16_t op1, svuint16_t op2) + /// UZP2 Zresult.H, Zop1.H, Zop2.H + /// svbool_t svuzp2_b16(svbool_t op1, svbool_t op2) + /// UZP2 Presult.H, Pop1.H, Pop2.H + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + + /// + /// svuint32_t svuzp2[_u32](svuint32_t op1, svuint32_t op2) + /// UZP2 Zresult.S, Zop1.S, Zop2.S + /// svbool_t svuzp2_b32(svbool_t op1, svbool_t op2) + /// UZP2 Presult.S, Pop1.S, Pop2.S + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + + /// + /// svuint64_t svuzp2[_u64](svuint64_t op1, svuint64_t op2) + /// UZP2 Zresult.D, Zop1.D, Zop2.D + /// svbool_t svuzp2_b64(svbool_t op1, svbool_t op2) + /// UZP2 Presult.D, Pop1.D, Pop2.D + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + /// ZipHigh : Interleave elements from high halves of two inputs + + /// + /// svuint8_t svzip2[_u8](svuint8_t op1, svuint8_t op2) + /// ZIP2 Zresult.B, Zop1.B, Zop2.B + /// svbool_t svzip2_b8(svbool_t op1, svbool_t op2) + /// ZIP2 Presult.B, Pop1.B, Pop2.B + /// + + + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svfloat64_t svzip2[_f64](svfloat64_t op1, svfloat64_t op2) + /// ZIP2 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svint16_t svzip2[_s16](svint16_t op1, svint16_t op2) + /// ZIP2 Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svint32_t svzip2[_s32](svint32_t op1, svint32_t op2) + /// ZIP2 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svint64_t svzip2[_s64](svint64_t op1, svint64_t op2) + /// ZIP2 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svint8_t svzip2[_s8](svint8_t op1, svint8_t op2) + /// ZIP2 Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svfloat32_t svzip2[_f32](svfloat32_t op1, svfloat32_t op2) + /// ZIP2 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svuint16_t svzip2[_u16](svuint16_t op1, svuint16_t op2) + /// ZIP2 Zresult.H, Zop1.H, Zop2.H + /// svbool_t svzip2_b16(svbool_t op1, svbool_t op2) + /// ZIP2 Presult.H, Pop1.H, Pop2.H + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svuint32_t svzip2[_u32](svuint32_t op1, svuint32_t op2) + /// ZIP2 Zresult.S, Zop1.S, Zop2.S + /// svbool_t svzip2_b32(svbool_t op1, svbool_t op2) + /// ZIP2 Presult.S, Pop1.S, Pop2.S + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svuint64_t svzip2[_u64](svuint64_t op1, svuint64_t op2) + /// ZIP2 Zresult.D, Zop1.D, Zop2.D + /// svbool_t svzip2_b64(svbool_t op1, svbool_t op2) + /// ZIP2 Presult.D, Pop1.D, Pop2.D + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + + /// ZipLow : Interleave elements from low halves of two inputs + + /// + /// svuint8_t svzip1[_u8](svuint8_t op1, svuint8_t op2) + /// ZIP1 Zresult.B, Zop1.B, Zop2.B + /// svbool_t svzip1_b8(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.B, Pop1.B, Pop2.B + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svfloat64_t svzip1[_f64](svfloat64_t op1, svfloat64_t op2) + /// ZIP1 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svint16_t svzip1[_s16](svint16_t op1, svint16_t op2) + /// ZIP1 Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svint32_t svzip1[_s32](svint32_t op1, svint32_t op2) + /// ZIP1 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svint64_t svzip1[_s64](svint64_t op1, svint64_t op2) + /// ZIP1 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svint8_t svzip1[_s8](svint8_t op1, svint8_t op2) + /// ZIP1 Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svfloat32_t svzip1[_f32](svfloat32_t op1, svfloat32_t op2) + /// ZIP1 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svuint16_t svzip1[_u16](svuint16_t op1, svuint16_t op2) + /// ZIP1 Zresult.H, Zop1.H, Zop2.H + /// svbool_t svzip1_b16(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.H, Pop1.H, Pop2.H + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svuint32_t svzip1[_u32](svuint32_t op1, svuint32_t op2) + /// ZIP1 Zresult.S, Zop1.S, Zop2.S + /// svbool_t svzip1_b32(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.S, Pop1.S, Pop2.S + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svuint64_t svzip1[_u64](svuint64_t op1, svuint64_t op2) + /// ZIP1 Zresult.D, Zop1.D, Zop2.D + /// svbool_t svzip1_b64(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.D, Pop1.D, Pop2.D + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); } } diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index e2ddb85806910a..e5f394aca8168a 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -4274,6 +4274,49 @@ internal Arm64() { } public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendToInt64(System.Numerics.Vector mask, uint* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendToUInt64(System.Numerics.Vector mask, uint* address) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } } public enum SveMaskPattern : byte diff --git a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs index 91e67daa18b976..e1e048d72ed60a 100644 --- a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs +++ b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs @@ -112,6 +112,7 @@ ("_UnaryOpTestTemplate.template", "SimpleUnOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), ("_UnaryOpTestTemplate.template", "SimpleVecOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), ("_BinaryOpTestTemplate.template", "VecPairBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecPairBinOpTest_ValidationLogic }), + ("_BinaryOp_SveTestTemplate.template", "SveVecPairBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecPairBinOpTest_ValidationLogic }), ("_UnaryOpTestTemplate.template", "VecReduceUnOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecReduceOpTest_ValidationLogic }), ("_BinaryOpTestTemplate.template", "VecBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), ("_TernaryOpTestTemplate.template", "SimpleTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), @@ -2908,16 +2909,16 @@ ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), - ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), - ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), - ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), - ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), - ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), - ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), - ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), - ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), - ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), - ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int32)i, right) != (Int32)result[i]",}), ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int64)i, right) != (Int64)result[i]",}), @@ -2963,30 +2964,70 @@ ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_uint", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_ulong", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorByteZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorByteZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorByteZeroExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorByteZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorByteZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorInt16SignExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorInt16SignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorInt16SignExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorInt16SignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorInt32SignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt32SignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorInt32SignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt32SignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorSByteSignExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorSByteSignExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorSByteSignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorSByteSignExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorSByteSignExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorSByteSignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorUInt16ZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorUInt16ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorUInt16ZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorUInt16ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorUInt32ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary {["TestName"] = "SveLoadVectorUInt32ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt32SignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt32SignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt32SignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt32SignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt32ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt32ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), }; diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_BinaryOp_SveTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_BinaryOp_SveTestTemplate.template new file mode 100644 index 00000000000000..19923127555c1e --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_BinaryOp_SveTestTemplate.template @@ -0,0 +1,327 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new {TemplateName}BinaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}BinaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {Op2BaseType}[] inArray2, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op2BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op2VectorType}<{Op2BaseType}> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}BinaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int Op2ElementCount = Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>() / sizeof({Op2BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op2VectorType}<{Op2BaseType}> _fld2; + + private DataTable _dataTable; + + public {TemplateName}BinaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + _dataTable = new DataTable(_data1, _data2, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + Vector<{Op1BaseType}> loadMask = Sve.CreateTrueMask{Op1BaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(loadMask, ({Op2BaseType}*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op2VectorType}<{Op2BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr); + var result = {Isa}.{Method}(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] left, {Op2BaseType}[] right, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op2VectorType}<{Op2BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} From c5ca516583831091a5659e723db56a689b13be13 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Fri, 26 Apr 2024 12:45:45 -0400 Subject: [PATCH 134/248] Fix regression in RegexGenerator.GetSHA256FieldName (#101606) A previous refactoring deleted the use of the hash. --- .../gen/RegexGenerator.Emitter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs index b2ab52c4c71fac..0a6cb3212cb2fa 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs @@ -5405,7 +5405,7 @@ private static string GetSHA256FieldName(string prefix, string toEncode) { #pragma warning disable CA1850 // SHA256.HashData isn't available on netstandard2.0 using SHA256 sha = SHA256.Create(); - return $"{prefix}{ToHexStringNoDashes(Encoding.UTF8.GetBytes(toEncode))}"; + return $"{prefix}{ToHexStringNoDashes(sha.ComputeHash(Encoding.UTF8.GetBytes(toEncode)))}"; #pragma warning restore CA1850 } From c29b59199057ba0a63e055284f4d3879fd203c48 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 26 Apr 2024 19:05:48 +0200 Subject: [PATCH 135/248] Implement Activity.AddLink (#101381) * implement Activity.AddLink * extend tests * Add remarks to docs required by https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#link --- ...em.Diagnostics.DiagnosticSourceActivity.cs | 1 + .../src/System/Diagnostics/Activity.cs | 19 +++++++++++ .../tests/ActivityTests.cs | 34 +++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs index 3908224b0a1a13..47677b1f612b56 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs @@ -50,6 +50,7 @@ public string? Id public string? TraceStateString { get { throw null; } set { } } public System.Diagnostics.Activity AddBaggage(string key, string? value) { throw null; } public System.Diagnostics.Activity AddEvent(System.Diagnostics.ActivityEvent e) { throw null; } + public System.Diagnostics.Activity AddLink(System.Diagnostics.ActivityLink link) { throw null; } public System.Diagnostics.Activity AddTag(string key, string? value) { throw null; } public System.Diagnostics.Activity AddTag(string key, object? value) { throw null; } public System.Diagnostics.Activity SetTag(string key, object? value) { throw null; } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs index 0605251a93b7a7..3a332ec4f13239 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs @@ -517,6 +517,25 @@ public Activity AddEvent(ActivityEvent e) return this; } + /// + /// Add an to the list. + /// + /// The to add. + /// for convenient chaining. + /// + /// For contexts that are available during span creation, adding links at span creation is preferred to calling later, + /// because head sampling decisions can only consider information present during span creation. + /// + public Activity AddLink(ActivityLink link) + { + if (_links != null || Interlocked.CompareExchange(ref _links, new DiagLinkedList(link), null) != null) + { + _links.Add(link); + } + + return this; + } + /// /// Update the Activity to have baggage with an additional 'key' and value 'value'. /// This shows up in the enumeration as well as the diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs index ae3c138e369714..00cb26017a3846 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs @@ -1597,6 +1597,35 @@ public void TestEvent() Assert.Equal(0, activity.Events.ElementAt(1).Tags.Count()); } + [Fact] + public void AddLinkTest() + { + ActivityContext c1 = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None); + ActivityContext c2 = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None); + + ActivityLink l1 = new ActivityLink(c1); + ActivityLink l2 = new ActivityLink(c2, new ActivityTagsCollection() + { + new KeyValuePair("foo", 99) + }); + + Activity activity = new Activity("LinkTest"); + Assert.True(ReferenceEquals(activity, activity.AddLink(l1))); + Assert.True(ReferenceEquals(activity, activity.AddLink(l2))); + + // Add a duplicate of l1. The implementation doesn't check for duplicates. + Assert.True(ReferenceEquals(activity, activity.AddLink(l1))); + + ActivityLink[] links = activity.Links.ToArray(); + Assert.Equal(3, links.Length); + Assert.Equal(c1, links[0].Context); + Assert.Equal(c2, links[1].Context); + Assert.Equal(c1, links[2].Context); + KeyValuePair tag = links[1].Tags.Single(); + Assert.Equal("foo", tag.Key); + Assert.Equal(99, tag.Value); + } + [Fact] public void TestIsAllDataRequested() { @@ -2163,12 +2192,14 @@ public void EnumerateLinksTest() var context1 = new ActivityContext(ActivityTraceId.CreateRandom(), default, ActivityTraceFlags.None); var context2 = new ActivityContext(ActivityTraceId.CreateRandom(), default, ActivityTraceFlags.None); + var context3 = new ActivityContext(ActivityTraceId.CreateRandom(), default, ActivityTraceFlags.None); a = source.CreateActivity( name: "Root", kind: ActivityKind.Internal, parentContext: default, links: new[] { new ActivityLink(context1), new ActivityLink(context2) }); + a.AddLink(new ActivityLink(context3)); Assert.NotNull(a); @@ -2182,6 +2213,9 @@ public void EnumerateLinksTest() Assert.True(enumerator.MoveNext()); Assert.Equal(context2.TraceId, enumerator.Current.Context.TraceId); values.Add(enumerator.Current); + Assert.True(enumerator.MoveNext()); + Assert.Equal(context3.TraceId, enumerator.Current.Context.TraceId); + values.Add(enumerator.Current); Assert.False(enumerator.MoveNext()); Assert.Equal(a.Links, values); From b8f96afc39bab9fae5065afa26e58c1200935d25 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Fri, 26 Apr 2024 19:59:29 +0200 Subject: [PATCH 136/248] [wasm] Add optimization flags to bitcode compilation (#101538) * [wasm] Add optimization flag to bitcode compilation comping from LD optimization flags. This should also fix the recent size regression. * Document the new property * Update src/mono/browser/build/BrowserWasmApp.targets Co-authored-by: Larry Ewing * Fix the conditions --------- Co-authored-by: Larry Ewing --- src/mono/browser/build/BrowserWasmApp.targets | 3 +++ src/mono/wasi/build/WasiApp.targets | 3 +++ src/mono/wasm/build/WasmApp.Common.targets | 2 ++ 3 files changed, 8 insertions(+) diff --git a/src/mono/browser/build/BrowserWasmApp.targets b/src/mono/browser/build/BrowserWasmApp.targets index 484d3486c5eaa8..d75513604304c6 100644 --- a/src/mono/browser/build/BrowserWasmApp.targets +++ b/src/mono/browser/build/BrowserWasmApp.targets @@ -260,6 +260,8 @@ $(_EmccOptimizationFlagDefault) $(EmccCompileOptimizationFlag) + -O2 + $(WasmCompileOptimizationFlag) -O2 $(WasmCompileOptimizationFlag) $(EmccLinkOptimizationFlag) @@ -406,6 +408,7 @@ + <_BitcodeCompileFlags Include="$(WasmBitcodeCompileOptimizationFlag)" /> <_BitcodeCompileFlags Include="@(_EmccCommonFlags)" /> <_BitcodeCompileFlags Include="$(EmccExtraBitcodeCompilationFlags)" /> diff --git a/src/mono/wasi/build/WasiApp.targets b/src/mono/wasi/build/WasiApp.targets index c5ecf84ad0c73c..cad25a76067295 100644 --- a/src/mono/wasi/build/WasiApp.targets +++ b/src/mono/wasi/build/WasiApp.targets @@ -148,6 +148,8 @@ $(_WasiClangOptimizationFlagDefault) $(WasiClangCompileOptimizationFlag) + -O2 + $(WasiClangCompileOptimizationFlag) -O2 $(WasiClangCompileOptimizationFlag) $(WasiClangLinkOptimizationFlag) @@ -265,6 +267,7 @@ + <_BitcodeCompileFlags Include="@(WasiBitcodeCompileOptimizationFlag)" /> <_BitcodeCompileFlags Include="@(_WasiClangCommonFlags)" /> <_BitcodeCompileFlags Include="$(WasiClangExtraBitcodeCompileFlags)" /> diff --git a/src/mono/wasm/build/WasmApp.Common.targets b/src/mono/wasm/build/WasmApp.Common.targets index f06b9a1261fe5e..e9cda6ccea50e1 100644 --- a/src/mono/wasm/build/WasmApp.Common.targets +++ b/src/mono/wasm/build/WasmApp.Common.targets @@ -44,6 +44,8 @@ - $(EmccLinkOptimizationFlag) - Optimization flag to use for the link step - $(EmccCompileOptimizationFlag) - Optimization flag to use for compiling native files + - $(WasmBitcodeCompileOptimizationFlag) + - Optimization flag to use for compiling bitcode files - $(EmccFlags) - Emcc flags used for both compiling native files, and linking - $(EmccExtraLDFlags) - Extra emcc flags for linking From c652f1095bd8e02b7762b1f6a019db49fab03416 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Fri, 26 Apr 2024 20:00:02 +0200 Subject: [PATCH 137/248] [wasi] Separate payload directories per WorkItemPrefix (#101599) * Separate wasi payload dirs per WorkItemPrefix * Use NormalizeDirectory * Remove debug output * Revert NormalizeDirectory --- src/libraries/sendtohelix-wasi.targets | 6 ++---- src/libraries/sendtohelix-wasm.targets | 16 ++++++++-------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/libraries/sendtohelix-wasi.targets b/src/libraries/sendtohelix-wasi.targets index e634fa0c2ea3f8..8a1902eb378fc5 100644 --- a/src/libraries/sendtohelix-wasi.targets +++ b/src/libraries/sendtohelix-wasi.targets @@ -48,8 +48,8 @@ $(RepoRoot)src\mono\wasi\wasi-sdk\ $([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'src', 'mono', 'wasi', 'build')) - $(HelixDependenciesStagingPath)\wasi-sdk - $(HelixDependenciesStagingPath)\wasmtime + $(HelixDependenciesStagingPath)$(WorkItemPrefix)wasi-sdk + $(HelixDependenciesStagingPath)$(WorkItemPrefix)wasmtime true true @@ -110,8 +110,6 @@ - - diff --git a/src/libraries/sendtohelix-wasm.targets b/src/libraries/sendtohelix-wasm.targets index 10dc71976f62b8..3fce57cf9c4e1b 100644 --- a/src/libraries/sendtohelix-wasm.targets +++ b/src/libraries/sendtohelix-wasm.targets @@ -9,6 +9,14 @@ $([MSBuild]::NormalizeDirectory($(WasmProjectRoot), 'build')) + + Workloads- + NoWorkload- + $(WorkItemPrefix)NoWebcil- + $(WorkItemPrefix)ST- + $(WorkItemPrefix)MT- + + @@ -27,14 +35,6 @@ - - Workloads- - NoWorkload- - $(WorkItemPrefix)NoWebcil- - $(WorkItemPrefix)ST- - $(WorkItemPrefix)MT- - - <_WasmWorkItem Include="$(WorkItemArchiveWildCard)" Exclude="$(HelixCorrelationPayload)" /> From 4c14fb030f7504cf503ea06549fb390b8c2770b8 Mon Sep 17 00:00:00 2001 From: Alan Hayward Date: Fri, 26 Apr 2024 19:14:13 +0100 Subject: [PATCH 138/248] JIT ARM64-SVE: Add Count*BitElements (#101188) * JIT ARM64-SVE: Add Count*BitElements * Generic ValidateResult testing * Fix formatting * Add option to change SVE vector length for current and children processes. TEST_LABEL: ent-arch-aarch64 TEST_IMG: ubuntu/dotnet-build TEST_CMD: safe ./projects/dotnet/test-runtime.sh --scope coreclr,libs Jira: ENTLLT-7328 Change-Id: I727edf8652a5c8648e7008d4ca47e7a4f36d5a1e * Revert "Add option to change SVE vector length for current and children processes." This reverts commit 293755790176a75fb985e50300c4f3e5d1728066. * fix CreateTrueMask --------- Co-authored-by: Swapnil Gaikwad --- src/coreclr/jit/hwintrinsic.h | 14 +- src/coreclr/jit/hwintrinsicarm64.cpp | 4 + src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 18 +- src/coreclr/jit/hwintrinsiclistarm64sve.h | 24 +- src/coreclr/jit/lowerarmarch.cpp | 4 + src/coreclr/jit/lsraarm64.cpp | 4 + .../Arm/Sve.PlatformNotSupported.cs | 159 ++++++++----- .../src/System/Runtime/Intrinsics/Arm/Sve.cs | 214 ++++++++++-------- .../ref/System.Runtime.Intrinsics.cs | 24 +- .../GenerateHWIntrinsicTests_Arm.cs | 5 + .../Arm/Shared/ScalarUnOpTest.template | 1 + 11 files changed, 297 insertions(+), 174 deletions(-) diff --git a/src/coreclr/jit/hwintrinsic.h b/src/coreclr/jit/hwintrinsic.h index e7bd08d5cb33dc..82cf179c742f4f 100644 --- a/src/coreclr/jit/hwintrinsic.h +++ b/src/coreclr/jit/hwintrinsic.h @@ -58,7 +58,6 @@ enum HWIntrinsicCategory : uint8_t HW_Category_ShiftLeftByImmediate, HW_Category_ShiftRightByImmediate, HW_Category_SIMDByIndexedElement, - HW_Category_EnumPattern, // Helper intrinsics // - do not directly correspond to a instruction, such as Vector64.AllBitsSet @@ -232,6 +231,11 @@ enum HWIntrinsicFlag : unsigned int // The intrinsic is an embedded masking incompatible intrinsic HW_Flag_EmbMaskingIncompatible = 0x20000000, +#elif defined(TARGET_ARM64) + + // The intrinsic has an enum operand. Using this implies HW_Flag_HasImmediateOperand. + HW_Flag_HasEnumOperand = 0x1000000, + #endif // TARGET_XARCH HW_Flag_CanBenefitFromConstantProp = 0x80000000, @@ -867,7 +871,7 @@ struct HWIntrinsicInfo static bool HasImmediateOperand(NamedIntrinsic id) { const HWIntrinsicFlag flags = lookupFlags(id); - return (flags & HW_Flag_HasImmediateOperand) != 0; + return ((flags & HW_Flag_HasImmediateOperand) != 0) || HasEnumOperand(id); } static bool IsScalable(NamedIntrinsic id) @@ -906,6 +910,12 @@ struct HWIntrinsicInfo return (flags & HW_Flag_ExplicitMaskedOperation) != 0; } + static bool HasEnumOperand(NamedIntrinsic id) + { + const HWIntrinsicFlag flags = lookupFlags(id); + return (flags & HW_Flag_HasEnumOperand) != 0; + } + #endif // TARGET_ARM64 static bool HasSpecialSideEffect(NamedIntrinsic id) diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp index 07018824458a0b..90dde12bde8220 100644 --- a/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/jit/hwintrinsicarm64.cpp @@ -290,6 +290,10 @@ void HWIntrinsicInfo::lookupImmBounds( case NI_Sve_CreateTrueMaskUInt16: case NI_Sve_CreateTrueMaskUInt32: case NI_Sve_CreateTrueMaskUInt64: + case NI_Sve_Count16BitElements: + case NI_Sve_Count32BitElements: + case NI_Sve_Count64BitElements: + case NI_Sve_Count8BitElements: immLowerBound = (int)SVE_PATTERN_POW2; immUpperBound = (int)SVE_PATTERN_ALL; break; diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index 462aaa521c6756..e9983f700361c5 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -380,7 +380,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) emitShift(intrin.op2, op1Reg); } } - else if (intrin.category == HW_Category_EnumPattern) + else if (HWIntrinsicInfo::HasEnumOperand(intrin.id)) { assert(hasImmediateOperand); @@ -1404,6 +1404,22 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GetEmitter()->emitIns_R_R_R_I(ins, emitSize, targetReg, op1Reg, op2Reg, 0, opt); break; + case NI_Sve_Count16BitElements: + case NI_Sve_Count32BitElements: + case NI_Sve_Count64BitElements: + case NI_Sve_Count8BitElements: + { + // Instruction has an additional immediate to multiply the result by. Use 1. + assert(hasImmediateOperand); + HWIntrinsicImmOpHelper helper(this, intrin.op1, node); + for (helper.EmitBegin(); !helper.Done(); helper.EmitCaseEnd()) + { + const insSvePattern pattern = (insSvePattern)helper.ImmValue(); + GetEmitter()->emitIns_R_PATTERN_I(ins, emitSize, targetReg, pattern, 1, opt); + } + break; + } + case NI_Sve_CreateTrueMaskAll: // Must use the pattern variant, as the non-pattern varient is SVE2.1. GetEmitter()->emitIns_R_PATTERN(ins, emitSize, targetReg, opt, SVE_PATTERN_ALL); diff --git a/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/coreclr/jit/hwintrinsiclistarm64sve.h index 773b3766a28a55..ef9740e4556523 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64sve.h +++ b/src/coreclr/jit/hwintrinsiclistarm64sve.h @@ -20,16 +20,20 @@ HARDWARE_INTRINSIC(Sve, Abs, -1, -1, false, {INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_fabs, INS_sve_fabs}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation) HARDWARE_INTRINSIC(Sve, Add, -1, -1, false, {INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_fadd, INS_sve_fadd}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, ConditionalSelect, -1, 3, true, {INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskByte, -1, 1, false, {INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskDouble, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskInt16, -1, 1, false, {INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskInt32, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskInt64, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskSByte, -1, 1, false, {INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskSingle, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt16, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt32, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt64, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, Count16BitElements, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_cnth, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_SpecialCodeGen|HW_Flag_NoFloatingPointUsed) +HARDWARE_INTRINSIC(Sve, Count32BitElements, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_cntw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_SpecialCodeGen|HW_Flag_NoFloatingPointUsed) +HARDWARE_INTRINSIC(Sve, Count64BitElements, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_cntd, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_SpecialCodeGen|HW_Flag_NoFloatingPointUsed) +HARDWARE_INTRINSIC(Sve, Count8BitElements, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_cntb, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_SpecialCodeGen|HW_Flag_NoFloatingPointUsed) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskByte, -1, 1, false, {INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskDouble, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskInt16, -1, 1, false, {INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskInt32, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskInt64, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskSByte, -1, 1, false, {INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskSingle, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt16, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt32, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt64, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) HARDWARE_INTRINSIC(Sve, CreateWhileLessThanMask16Bit, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_whilelt, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ReturnsPerElementMask) HARDWARE_INTRINSIC(Sve, CreateWhileLessThanMask32Bit, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_whilelt, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ReturnsPerElementMask) HARDWARE_INTRINSIC(Sve, CreateWhileLessThanMask64Bit, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_whilelt, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ReturnsPerElementMask) diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 7ea9a90d62343e..6456b2b972ea9a 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -3295,6 +3295,10 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) case NI_Sve_CreateTrueMaskUInt16: case NI_Sve_CreateTrueMaskUInt32: case NI_Sve_CreateTrueMaskUInt64: + case NI_Sve_Count16BitElements: + case NI_Sve_Count32BitElements: + case NI_Sve_Count64BitElements: + case NI_Sve_Count8BitElements: assert(hasImmediateOperand); assert(varTypeIsIntegral(intrin.op1)); if (intrin.op1->IsCnsIntOrI()) diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp index dfcebf4392c53c..6ea3ad27706cea 100644 --- a/src/coreclr/jit/lsraarm64.cpp +++ b/src/coreclr/jit/lsraarm64.cpp @@ -1464,6 +1464,10 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou case NI_Sve_CreateTrueMaskUInt16: case NI_Sve_CreateTrueMaskUInt32: case NI_Sve_CreateTrueMaskUInt64: + case NI_Sve_Count16BitElements: + case NI_Sve_Count32BitElements: + case NI_Sve_Count64BitElements: + case NI_Sve_Count8BitElements: needBranchTargetReg = !intrin.op1->isContainedIntOrIImmed(); break; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs index f23fb1b8ee2c7d..3b992e440ef6b5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs @@ -31,7 +31,6 @@ internal Arm64() { } public static new bool IsSupported { [Intrinsic] get { return false; } } } - /// Abs : Absolute value /// @@ -150,6 +149,103 @@ internal Arm64() { } public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// ConditionalSelect : Conditionally select elements + + /// + /// svint8_t svsel[_s8](svbool_t pg, svint8_t op1, svint8_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svsel[_s16](svbool_t pg, svint16_t op1, svint16_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svsel[_s32](svbool_t pg, svint32_t op1, svint32_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svsel[_s64](svbool_t pg, svint64_t op1, svint64_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint8_t svsel[_u8](svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svsel[_u16](svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svsel[_u32](svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svsel[_u64](svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svsel[_f32](svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svsel[_f64](svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// Count16BitElements : Count the number of 16-bit elements in a vector + + /// + /// uint64_t svcnth_pat(enum svpattern pattern) + /// CNTH Xresult, pattern + /// + public static unsafe ulong Count16BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// Count32BitElements : Count the number of 32-bit elements in a vector + + /// + /// uint64_t svcntw_pat(enum svpattern pattern) + /// CNTW Xresult, pattern + /// + public static unsafe ulong Count32BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// Count64BitElements : Count the number of 64-bit elements in a vector + + /// + /// uint64_t svcntd_pat(enum svpattern pattern) + /// CNTD Xresult, pattern + /// + public static unsafe ulong Count64BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// Count8BitElements : Count the number of 8-bit elements in a vector + + /// + /// uint64_t svcntb_pat(enum svpattern pattern) + /// CNTB Xresult, pattern + /// + public static unsafe ulong Count8BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + /// CreateTrueMaskByte : Set predicate elements to true /// @@ -456,67 +552,6 @@ internal Arm64() { } public static unsafe Vector CreateWhileLessThanOrEqualMask8Bit(ulong left, ulong right) { throw new PlatformNotSupportedException(); } - /// ConditionalSelect : Conditionally select elements - - /// - /// svint8_t svsel[_s8](svbool_t pg, svint8_t op1, svint8_t op2) - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - /// - /// svint16_t svsel[_s16](svbool_t pg, svint16_t op1, svint16_t op2) - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - /// - /// svint32_t svsel[_s32](svbool_t pg, svint32_t op1, svint32_t op2) - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - /// - /// svint64_t svsel[_s64](svbool_t pg, svint64_t op1, svint64_t op2) - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - /// - /// svuint8_t svsel[_u8](svbool_t pg, svuint8_t op1, svuint8_t op2) - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - /// - /// svuint16_t svsel[_u16](svbool_t pg, svuint16_t op1, svuint16_t op2) - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - /// - /// svuint32_t svsel[_u32](svbool_t pg, svuint32_t op1, svuint32_t op2) - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - /// - /// svuint64_t svsel[_u64](svbool_t pg, svuint64_t op1, svuint64_t op2) - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - /// - /// svfloat32_t svsel[_f32](svbool_t pg, svfloat32_t op1, svfloat32_t op2) - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - /// - /// svfloat64_t svsel[_f64](svbool_t pg, svfloat64_t op1, svfloat64_t op2) - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - /// LoadVector : Unextended load /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs index 494607f5952c46..0f4f57dad8e9bc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs @@ -177,6 +177,131 @@ internal Arm64() { } public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + /// ConditionalSelect : Conditionally select elements + + /// + /// svint8_t svsel[_s8](svbool_t pg, svint8_t op1, svint8_t op2) + /// SEL Zresult.B, Pg, Zop1.B, Zop2.B + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svint16_t svsel[_s16](svbool_t pg, svint16_t op1, svint16_t op2) + /// SEL Zresult.H, Pg, Zop1.H, Zop2.H + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svint32_t svsel[_s32](svbool_t pg, svint32_t op1, svint32_t op2) + /// SEL Zresult.S, Pg, Zop1.S, Zop2.S + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svint64_t svsel[_s64](svbool_t pg, svint64_t op1, svint64_t op2) + /// SEL Zresult.D, Pg, Zop1.D, Zop2.D + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svuint8_t svsel[_u8](svbool_t pg, svuint8_t op1, svuint8_t op2) + /// SEL Zresult.B, Pg, Zop1.B, Zop2.B + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svuint16_t svsel[_u16](svbool_t pg, svuint16_t op1, svuint16_t op2) + /// SEL Zresult.H, Pg, Zop1.H, Zop2.H + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svuint32_t svsel[_u32](svbool_t pg, svuint32_t op1, svuint32_t op2) + /// SEL Zresult.S, Pg, Zop1.S, Zop2.S + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svuint64_t svsel[_u64](svbool_t pg, svuint64_t op1, svuint64_t op2) + /// SEL Zresult.D, Pg, Zop1.D, Zop2.D + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svfloat32_t svsel[_f32](svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// SEL Zresult.S, Pg, Zop1.S, Zop2.S + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svfloat64_t svsel[_f64](svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// SEL Zresult.D, Pg, Zop1.D, Zop2.D + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + + /// Count16BitElements : Count the number of 16-bit elements in a vector + + /// + /// uint64_t svcnth_pat(enum svpattern pattern) + /// CNTH Xresult, pattern + /// + public static unsafe ulong Count16BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => Count16BitElements(pattern); + + + /// Count32BitElements : Count the number of 32-bit elements in a vector + + /// + /// uint64_t svcntw_pat(enum svpattern pattern) + /// CNTW Xresult, pattern + /// + public static unsafe ulong Count32BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => Count32BitElements(pattern); + + + /// Count64BitElements : Count the number of 64-bit elements in a vector + + /// + /// uint64_t svcntd_pat(enum svpattern pattern) + /// CNTD Xresult, pattern + /// + public static unsafe ulong Count64BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => Count64BitElements(pattern); + + + /// Count8BitElements : Count the number of 8-bit elements in a vector + + /// + /// uint64_t svcntb_pat(enum svpattern pattern) + /// CNTB Xresult, pattern + /// + public static unsafe ulong Count8BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => Count8BitElements(pattern); + + /// CreateTrueMaskByte : Set predicate elements to true /// @@ -483,95 +608,6 @@ internal Arm64() { } public static unsafe Vector CreateWhileLessThanOrEqualMask8Bit(ulong left, ulong right) => CreateWhileLessThanOrEqualMask8Bit(left, right); - /// ConditionalSelect : Conditionally select elements - - /// - /// svint8_t svsel[_s8](svbool_t pg, svint8_t op1, svint8_t op2) - /// SEL Zresult.B, Pg, Zop1.B, Zop2.B - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// SEL Presult.B, Pg, Pop1.B, Pop2.B - /// - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); - - /// - /// svint16_t svsel[_s16](svbool_t pg, svint16_t op1, svint16_t op2) - /// SEL Zresult.H, Pg, Zop1.H, Zop2.H - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// SEL Presult.B, Pg, Pop1.B, Pop2.B - /// - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); - - /// - /// svint32_t svsel[_s32](svbool_t pg, svint32_t op1, svint32_t op2) - /// SEL Zresult.S, Pg, Zop1.S, Zop2.S - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// SEL Presult.B, Pg, Pop1.B, Pop2.B - /// - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); - - /// - /// svint64_t svsel[_s64](svbool_t pg, svint64_t op1, svint64_t op2) - /// SEL Zresult.D, Pg, Zop1.D, Zop2.D - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// SEL Presult.B, Pg, Pop1.B, Pop2.B - /// - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); - - /// - /// svuint8_t svsel[_u8](svbool_t pg, svuint8_t op1, svuint8_t op2) - /// SEL Zresult.B, Pg, Zop1.B, Zop2.B - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// SEL Presult.B, Pg, Pop1.B, Pop2.B - /// - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); - - /// - /// svuint16_t svsel[_u16](svbool_t pg, svuint16_t op1, svuint16_t op2) - /// SEL Zresult.H, Pg, Zop1.H, Zop2.H - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// SEL Presult.B, Pg, Pop1.B, Pop2.B - /// - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); - - /// - /// svuint32_t svsel[_u32](svbool_t pg, svuint32_t op1, svuint32_t op2) - /// SEL Zresult.S, Pg, Zop1.S, Zop2.S - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// SEL Presult.B, Pg, Pop1.B, Pop2.B - /// - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); - - /// - /// svuint64_t svsel[_u64](svbool_t pg, svuint64_t op1, svuint64_t op2) - /// SEL Zresult.D, Pg, Zop1.D, Zop2.D - /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) - /// SEL Presult.B, Pg, Pop1.B, Pop2.B - /// - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); - - /// - /// svfloat32_t svsel[_f32](svbool_t pg, svfloat32_t op1, svfloat32_t op2) - /// SEL Zresult.S, Pg, Zop1.S, Zop2.S - /// - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); - - /// - /// svfloat64_t svsel[_f64](svbool_t pg, svfloat64_t op1, svfloat64_t op2) - /// SEL Zresult.D, Pg, Zop1.D, Zop2.D - /// - /// - public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); - - /// LoadVector : Unextended load /// diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index e5f394aca8168a..881100ff95976c 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -4187,6 +4187,20 @@ internal Arm64() { } public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static ulong Count16BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } + public static ulong Count32BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } + public static ulong Count64BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } + public static ulong Count8BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector CreateTrueMaskByte([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } public static System.Numerics.Vector CreateTrueMaskDouble([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } public static System.Numerics.Vector CreateTrueMaskInt16([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } @@ -4229,16 +4243,6 @@ internal Arm64() { } public static System.Numerics.Vector CreateWhileLessThanOrEqualMask8Bit(long left, long right) { throw null; } public static System.Numerics.Vector CreateWhileLessThanOrEqualMask8Bit(uint left, uint right) { throw null; } public static System.Numerics.Vector CreateWhileLessThanOrEqualMask8Bit(ulong left, ulong right) { throw null; } - public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, sbyte* address) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, short* address) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, int* address) { throw null; } diff --git a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs index e1e048d72ed60a..db964d4793e1bb 100644 --- a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs +++ b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs @@ -2920,6 +2920,11 @@ ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count16BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count16BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Int16)));",}), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count32BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count32BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Int32)));",}), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count64BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count64BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Int64)));",}), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count8BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count8BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Byte)));",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int32)i, right) != (Int32)result[i]",}), ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int64)i, right) != (Int64)result[i]",}), ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt32)i, right) != (UInt32)result[i]",}), diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/ScalarUnOpTest.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/ScalarUnOpTest.template index c6fe68908e5627..f057ad4a818680 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/ScalarUnOpTest.template +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/ScalarUnOpTest.template @@ -9,6 +9,7 @@ ******************************************************************************/ using System; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; From cab2d119a785d7d3a4f6461021364e849560fa62 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan <96171496+mkhamoyan@users.noreply.github.com> Date: Fri, 26 Apr 2024 20:18:33 +0200 Subject: [PATCH 139/248] [mono][wasm] Include NativeLibrary items to the NativeFileReference items (#101532) * Include NativeLibary and add test case * Move to common place * Ignore missing NativeLibraries * Move items copying into target --- .../Wasm.Build.Tests/NativeLibraryTests.cs | 31 +++++++++++++++++++ src/mono/wasm/build/WasmApp.Common.targets | 5 +++ 2 files changed, 36 insertions(+) diff --git a/src/mono/wasm/Wasm.Build.Tests/NativeLibraryTests.cs b/src/mono/wasm/Wasm.Build.Tests/NativeLibraryTests.cs index c8cca6cd0774e7..555cfa73fad176 100644 --- a/src/mono/wasm/Wasm.Build.Tests/NativeLibraryTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/NativeLibraryTests.cs @@ -136,5 +136,36 @@ public static int Main() string cryptoInitMsg = "MONO_WASM: Initializing Crypto WebWorker"; Assert.DoesNotContain(cryptoInitMsg, output); } + + [Theory] + [BuildAndRun(aot: false)] + [BuildAndRun(aot: true)] + public void ProjectWithNativeLibrary(BuildArgs buildArgs, RunHost host, string id) + { + string projectName = $"AppUsingNativeLibrary-a"; + buildArgs = buildArgs with { ProjectName = projectName }; + buildArgs = ExpandBuildArgs(buildArgs, extraItems: "\n"); + + if (!_buildContext.TryGetBuildFor(buildArgs, out BuildProduct? _)) + { + InitPaths(id); + if (Directory.Exists(_projectDir)) + Directory.Delete(_projectDir, recursive: true); + + Utils.DirectoryCopy(Path.Combine(BuildEnvironment.TestAssetsPath, "AppUsingNativeLib"), _projectDir); + File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "native-libs", "native-lib.o"), Path.Combine(_projectDir, "native-lib.o")); + } + + BuildProject(buildArgs, + id: id, + new BuildProjectOptions(DotnetWasmFromRuntimePack: false)); + + string output = RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 0, + test: output => {}, + host: host, id: id); + + Assert.Contains("print_line: 100", output); + Assert.Contains("from pinvoke: 142", output); + } } } diff --git a/src/mono/wasm/build/WasmApp.Common.targets b/src/mono/wasm/build/WasmApp.Common.targets index e9cda6ccea50e1..501a98264538c3 100644 --- a/src/mono/wasm/build/WasmApp.Common.targets +++ b/src/mono/wasm/build/WasmApp.Common.targets @@ -297,6 +297,11 @@ <_WasmShouldAOT Condition="'$(_WasmShouldAOT)' == ''">false + + <_ExistingNativeLibrary Include="@(NativeLibrary->Exists())" /> + + + From 2c99786b58009d4422c198e8aeaebc068c4b6245 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Fri, 26 Apr 2024 20:51:10 +0200 Subject: [PATCH 140/248] Revert "FileConfigurationProvider.Dispose should dispose FileProvider when it owns it" (#101609) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Revert "FileConfigurationProvider.Dispose should dispose FileProvider when it…" This reverts commit 63fad3c36fdf36e31ab0dd4c7e32732750390c4a. * Add test to ensure the bug does not come back --- .../src/FileConfigurationExtensions.cs | 10 +-- .../src/FileConfigurationProvider.cs | 5 -- .../src/FileConfigurationSource.cs | 11 ---- .../tests/JsonConfigurationTest.cs | 48 +++------------ .../tests/XmlConfigurationTest.cs | 61 ------------------- 5 files changed, 15 insertions(+), 120 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationExtensions.cs b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationExtensions.cs index 77ac387d096077..f84c5c10eea771 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationExtensions.cs @@ -29,9 +29,6 @@ public static IConfigurationBuilder SetFileProvider(this IConfigurationBuilder b return builder; } - internal static IFileProvider? GetUserDefinedFileProvider(this IConfigurationBuilder builder) - => builder.Properties.TryGetValue(FileProviderKey, out object? provider) ? (IFileProvider)provider : null; - /// /// Gets the default to be used for file-based providers. /// @@ -41,7 +38,12 @@ public static IFileProvider GetFileProvider(this IConfigurationBuilder builder) { ThrowHelper.ThrowIfNull(builder); - return GetUserDefinedFileProvider(builder) ?? new PhysicalFileProvider(AppContext.BaseDirectory ?? string.Empty); + if (builder.Properties.TryGetValue(FileProviderKey, out object? provider)) + { + return (IFileProvider)provider; + } + + return new PhysicalFileProvider(AppContext.BaseDirectory ?? string.Empty); } /// diff --git a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationProvider.cs b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationProvider.cs index c0d8c9f341278a..d226051b1ab838 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationProvider.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationProvider.cs @@ -162,11 +162,6 @@ private void HandleException(ExceptionDispatchInfo info) protected virtual void Dispose(bool disposing) { _changeTokenRegistration?.Dispose(); - - if (Source.OwnsFileProvider) - { - (Source.FileProvider as IDisposable)?.Dispose(); - } } } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationSource.cs b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationSource.cs index 60555b2c672558..d58c265f406a9a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationSource.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationSource.cs @@ -18,11 +18,6 @@ public abstract class FileConfigurationSource : IConfigurationSource /// public IFileProvider? FileProvider { get; set; } - /// - /// Set to true when was not provided by user and can be safely disposed. - /// - internal bool OwnsFileProvider { get; private set; } - /// /// The path to the file. /// @@ -63,11 +58,6 @@ public abstract class FileConfigurationSource : IConfigurationSource /// The . public void EnsureDefaults(IConfigurationBuilder builder) { - if (FileProvider is null && builder.GetUserDefinedFileProvider() is null) - { - OwnsFileProvider = true; - } - FileProvider ??= builder.GetFileProvider(); OnLoadException ??= builder.GetFileLoadExceptionHandler(); } @@ -91,7 +81,6 @@ public void ResolveFileProvider() } if (Directory.Exists(directory)) { - OwnsFileProvider = true; FileProvider = new PhysicalFileProvider(directory); Path = pathToFile; } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Json/tests/JsonConfigurationTest.cs b/src/libraries/Microsoft.Extensions.Configuration.Json/tests/JsonConfigurationTest.cs index 4b08c918fb8981..08d59e30ea6ebc 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Json/tests/JsonConfigurationTest.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Json/tests/JsonConfigurationTest.cs @@ -222,56 +222,26 @@ public void ThrowFormatExceptionWhenFileIsEmpty() Assert.Contains("Could not parse the JSON file.", exception.Message); } - [Theory] - [InlineData(true)] - [InlineData(false)] - public void AddJsonFile_FileProvider_Gets_Disposed_When_It_Was_Not_Created_By_The_User(bool disposeConfigRoot) + [Fact] + public void AddJsonFile_FileProvider_Is_Not_Disposed_When_SourcesGetReloaded() { - string filePath = Path.Combine(Path.GetTempPath(), $"{nameof(AddJsonFile_FileProvider_Gets_Disposed_When_It_Was_Not_Created_By_The_User)}.json"); + string filePath = Path.Combine(Path.GetTempPath(), $"{nameof(AddJsonFile_FileProvider_Is_Not_Disposed_When_SourcesGetReloaded)}.json"); File.WriteAllText(filePath, @"{ ""some"": ""value"" }"); - IConfigurationRoot config = new ConfigurationBuilder().AddJsonFile(filePath, optional: false).Build(); - JsonConfigurationProvider jsonConfigurationProvider = config.Providers.OfType().Single(); - - Assert.NotNull(jsonConfigurationProvider.Source.FileProvider); - PhysicalFileProvider fileProvider = (PhysicalFileProvider)jsonConfigurationProvider.Source.FileProvider; - Assert.False(GetIsDisposed(fileProvider)); - - if (disposeConfigRoot) - { - (config as IDisposable).Dispose(); // disposing ConfigurationRoot - } - else - { - jsonConfigurationProvider.Dispose(); // disposing JsonConfigurationProvider - } - - Assert.True(GetIsDisposed(fileProvider)); - } + IConfigurationBuilder builder = new ConfigurationManager(); - [Fact] - public void AddJsonFile_FileProvider_Is_Not_Disposed_When_It_Is_Owned_By_The_User() - { - string filePath = Path.Combine(Path.GetTempPath(), $"{nameof(AddJsonFile_FileProvider_Is_Not_Disposed_When_It_Is_Owned_By_The_User)}.json"); - File.WriteAllText(filePath, @"{ ""some"": ""value"" }"); + builder.AddJsonFile(filePath, optional: false); - PhysicalFileProvider fileProvider = new(Path.GetDirectoryName(filePath)); - JsonConfigurationProvider configurationProvider = new(new JsonConfigurationSource() - { - Path = filePath, - FileProvider = fileProvider - }); - IConfigurationRoot config = new ConfigurationBuilder().AddJsonFile(configurationProvider.Source.FileProvider, filePath, optional: true, reloadOnChange: false).Build(); + FileConfigurationSource fileConfigurationSource = (FileConfigurationSource)builder.Sources.Last(); + PhysicalFileProvider fileProvider = (PhysicalFileProvider)fileConfigurationSource.FileProvider; Assert.False(GetIsDisposed(fileProvider)); - (config as IDisposable).Dispose(); // disposing ConfigurationRoot that does not own the provider - Assert.False(GetIsDisposed(fileProvider)); + builder.Properties.Add("simplest", "repro"); - configurationProvider.Dispose(); // disposing JsonConfigurationProvider that does not own the provider Assert.False(GetIsDisposed(fileProvider)); - fileProvider.Dispose(); // disposing PhysicalFileProvider itself + fileProvider.Dispose(); Assert.True(GetIsDisposed(fileProvider)); } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/XmlConfigurationTest.cs b/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/XmlConfigurationTest.cs index d248d96d9d464f..4012d775afa5f2 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/XmlConfigurationTest.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/XmlConfigurationTest.cs @@ -3,13 +3,11 @@ using System; using System.IO; -using System.Linq; using System.Security.Cryptography; using System.Security.Cryptography.Xml; using System.Tests; using System.Xml; using Microsoft.Extensions.Configuration.Test; -using Microsoft.Extensions.FileProviders; using Xunit; namespace Microsoft.Extensions.Configuration.Xml.Test @@ -781,64 +779,5 @@ public void LoadKeyValuePairsFromValidEncryptedXml() Assert.Equal("AnotherTestConnectionString", xmlConfigSrc.Get("data.setting:inventory:connectionstring")); Assert.Equal("MySql", xmlConfigSrc.Get("Data.setting:Inventory:Provider")); } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void AddXmlFile_FileProvider_Gets_Disposed_When_It_Was_Not_Created_By_The_User(bool disposeConfigRoot) - { - string filePath = Path.Combine(Path.GetTempPath(), $"{nameof(AddXmlFile_FileProvider_Gets_Disposed_When_It_Was_Not_Created_By_The_User)}.xml"); - File.WriteAllText(filePath, @"Settings"); - - IConfigurationRoot config = new ConfigurationBuilder().AddXmlFile(filePath, optional: false).Build(); - XmlConfigurationProvider xmlConfigurationProvider = config.Providers.OfType().Single(); - - Assert.NotNull(xmlConfigurationProvider.Source.FileProvider); - PhysicalFileProvider fileProvider = (PhysicalFileProvider)xmlConfigurationProvider.Source.FileProvider; - Assert.False(GetIsDisposed(fileProvider)); - - if (disposeConfigRoot) - { - (config as IDisposable).Dispose(); // disposing ConfigurationRoot - } - else - { - xmlConfigurationProvider.Dispose(); // disposing XmlConfigurationProvider - } - - Assert.True(GetIsDisposed(fileProvider)); - } - - [Fact] - public void AddXmlFile_FileProvider_Is_Not_Disposed_When_It_Is_Owned_By_The_User() - { - string filePath = Path.Combine(Path.GetTempPath(), $"{nameof(AddXmlFile_FileProvider_Is_Not_Disposed_When_It_Is_Owned_By_The_User)}.xml"); - File.WriteAllText(filePath, @"Settings"); - - PhysicalFileProvider fileProvider = new(Path.GetDirectoryName(filePath)); - XmlConfigurationProvider configurationProvider = new(new XmlConfigurationSource() - { - Path = filePath, - FileProvider = fileProvider - }); - IConfigurationRoot config = new ConfigurationBuilder().AddXmlFile(configurationProvider.Source.FileProvider, filePath, optional: true, reloadOnChange: false).Build(); - - Assert.False(GetIsDisposed(fileProvider)); - - (config as IDisposable).Dispose(); // disposing ConfigurationRoot that does not own the provider - Assert.False(GetIsDisposed(fileProvider)); - - configurationProvider.Dispose(); // disposing XmlConfigurationProvider - Assert.False(GetIsDisposed(fileProvider)); - - fileProvider.Dispose(); // disposing PhysicalFileProvider itself - Assert.True(GetIsDisposed(fileProvider)); - } - - private static bool GetIsDisposed(PhysicalFileProvider fileProvider) - { - System.Reflection.FieldInfo isDisposedField = typeof(PhysicalFileProvider).GetField("_disposed", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); - return (bool)isDisposedField.GetValue(fileProvider); - } } } From 0f562e911e7248a8aba966ddd27ed02d617225af Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 26 Apr 2024 11:54:58 -0700 Subject: [PATCH 141/248] Improve tests/profiler/multiple/multiple.cs (#101607) - Add volatile for a field accessed by multiple threads without synchronization - Improve logging - Delete test supression against closed issue - Revert timeout increase that tried to work around a hang that was fixed since then --- src/tests/profiler/common/ProfilerTestRunner.cs | 14 ++++++++------ src/tests/profiler/multiple/multiple.cs | 7 +------ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/tests/profiler/common/ProfilerTestRunner.cs b/src/tests/profiler/common/ProfilerTestRunner.cs index d78a1221b42213..2dfc2530c59d65 100644 --- a/src/tests/profiler/common/ProfilerTestRunner.cs +++ b/src/tests/profiler/common/ProfilerTestRunner.cs @@ -135,9 +135,9 @@ public static int Run(string profileePath, if (!verifier.HasPassingOutput) { - FailFastWithMessage("Profiler tests are expected to contain the text \'" + verifier.SuccessPhrase + "\' in the console output " + - "of the profilee app to indicate a passing test. Usually it is printed from the Shutdown() method of the profiler implementation. This " + - "text was not found in the output above."); + FailFastWithMessage($"Profiler tests are expected to contain the text '{verifier.SuccessPhrase}' in the console output " + + $"of the profilee app to indicate a passing test. Usually it is printed from the Shutdown() method of the profiler implementation. This " + + $"text was not found in the output above. Profilee returned exit code {process.ExitCode}."); } if (process.ExitCode != 100) @@ -195,14 +195,16 @@ private static void FailFastWithMessage(string error) /// class ProfileeOutputVerifier { + private volatile bool _hasPassingOutput; + public string SuccessPhrase = "PROFILER TEST PASSES"; - public bool HasPassingOutput { get; private set; } + public bool HasPassingOutput => _hasPassingOutput; public void WriteLine(string message) { if (message != null && message.Contains(SuccessPhrase)) { - HasPassingOutput = true; + _hasPassingOutput = true; } } @@ -210,7 +212,7 @@ public void WriteLine(string format, params object[] args) { if (string.Format(format,args).Contains(SuccessPhrase)) { - HasPassingOutput = true; + _hasPassingOutput = true; } } } diff --git a/src/tests/profiler/multiple/multiple.cs b/src/tests/profiler/multiple/multiple.cs index 0d686ae0691a94..a0952687021bf0 100644 --- a/src/tests/profiler/multiple/multiple.cs +++ b/src/tests/profiler/multiple/multiple.cs @@ -35,7 +35,7 @@ public static int RunTest(String[] args) } Console.WriteLine("Waiting for profilers to all detach"); - if (!_profilerDone.WaitOne(TimeSpan.FromMinutes(10))) + if (!_profilerDone.WaitOne(TimeSpan.FromMinutes(5))) { throw new Exception("Test timed out waiting for the profilers to set the callback, test will fail."); } @@ -45,11 +45,6 @@ public static int RunTest(String[] args) public static int Main(string[] args) { - // failing on MacOs 12 https://github.com/dotnet/runtime/issues/64765 - if (OperatingSystem.IsMacOS()) - { - return 100; - } if (args.Length > 0 && args[0].Equals("RunTest", StringComparison.OrdinalIgnoreCase)) { return RunTest(args); From 1a811ea83965a3ce41ae573a6265b557d7662113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulus=20P=C3=A4rssinen?= Date: Fri, 26 Apr 2024 22:27:36 +0300 Subject: [PATCH 142/248] Update link to dotnet-format tool (#101619) * Update link to dotnet-format tool * It now lives in dotnet/sdk * Link to official docs instead Co-authored-by: Jan Kotas --------- Co-authored-by: Jan Kotas --- docs/coding-guidelines/coding-style.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/coding-guidelines/coding-style.md b/docs/coding-guidelines/coding-style.md index 075155a9ee63d8..32dd1ec8bb65e5 100644 --- a/docs/coding-guidelines/coding-style.md +++ b/docs/coding-guidelines/coding-style.md @@ -36,7 +36,7 @@ The general rule we follow is "use Visual Studio defaults". An [EditorConfig](https://editorconfig.org "EditorConfig homepage") file (`.editorconfig`) has been provided at the root of the runtime repository, enabling C# auto-formatting conforming to the above guidelines. -We also use the [dotnet-format Tool](https://github.com/dotnet/format) to ensure the code base maintains a consistent style over time, the tool automatically fixes the code base to conform to the guidelines outlined above. +We also use the [dotnet-format tool](https://learn.microsoft.com/dotnet/core/tools/dotnet-format) to ensure the code base maintains a consistent style over time, the tool automatically fixes the code base to conform to the guidelines outlined above. ### Example File: From dd87633a81b5094c5afb9690b4aa050d47e19771 Mon Sep 17 00:00:00 2001 From: Aman Khalid Date: Fri, 26 Apr 2024 20:46:26 +0000 Subject: [PATCH 143/248] JIT: Remove HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION (#101611) --- src/coreclr/jit/block.h | 21 --------------------- src/coreclr/jit/fgehopt.cpp | 10 ---------- src/coreclr/jit/fgprofile.cpp | 11 ----------- src/coreclr/jit/flowgraph.cpp | 20 +++----------------- src/coreclr/jit/jit.h | 5 ++--- 5 files changed, 5 insertions(+), 62 deletions(-) diff --git a/src/coreclr/jit/block.h b/src/coreclr/jit/block.h index 168f29cca084dd..37c97bfdca6485 100644 --- a/src/coreclr/jit/block.h +++ b/src/coreclr/jit/block.h @@ -1256,27 +1256,6 @@ struct BasicBlock : private LIR::Range this->scaleBBWeight(BB_ZERO_WEIGHT); } - // makeBlockHot() - // This is used to override any profiling data - // and force a block to be in the hot region. - // We only call this method for handler entry point - // and only when HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION is 1. - // Doing this helps fgReorderBlocks() by telling - // it to try to move these blocks into the hot region. - // Note that we do this strictly as an optimization, - // not for correctness. fgDetermineFirstColdBlock() - // will find all handler entry points and ensure that - // for now we don't place them in the cold section. - // - void makeBlockHot() - { - if (this->bbWeight == BB_ZERO_WEIGHT) - { - this->RemoveFlags(BBF_RUN_RARELY | BBF_PROF_WEIGHT); - this->bbWeight = 1; - } - } - bool isMaxBBWeight() const { return (bbWeight >= BB_MAX_WEIGHT); diff --git a/src/coreclr/jit/fgehopt.cpp b/src/coreclr/jit/fgehopt.cpp index a26eaf0bfa8b3d..743559717e47cb 100644 --- a/src/coreclr/jit/fgehopt.cpp +++ b/src/coreclr/jit/fgehopt.cpp @@ -1229,16 +1229,6 @@ PhaseStatus Compiler::fgCloneFinally() block->setBBProfileWeight(blockWeight * originalScale); JITDUMP("Set weight of " FMT_BB " to " FMT_WT "\n", block->bbNum, block->bbWeight); -#if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION - // Handle a special case -- some handler entries can't have zero profile count. - // - if (bbIsHandlerBeg(block) && block->isRunRarely()) - { - JITDUMP("Suppressing zero count for " FMT_BB " as it is a handler entry\n", block->bbNum); - block->makeBlockHot(); - } -#endif - BasicBlock* const clonedBlock = blockMap[block]; clonedBlock->setBBProfileWeight(blockWeight * clonedScale); JITDUMP("Set weight of " FMT_BB " to " FMT_WT "\n", clonedBlock->bbNum, clonedBlock->bbWeight); diff --git a/src/coreclr/jit/fgprofile.cpp b/src/coreclr/jit/fgprofile.cpp index 05f97ffd14ef59..10fdd6035e0b3f 100644 --- a/src/coreclr/jit/fgprofile.cpp +++ b/src/coreclr/jit/fgprofile.cpp @@ -3018,21 +3018,10 @@ PhaseStatus Compiler::fgIncorporateProfileData() // // Notes: // Does inlinee scaling. -// Handles handler entry special case. // void Compiler::fgSetProfileWeight(BasicBlock* block, weight_t profileWeight) { block->setBBProfileWeight(profileWeight); - -#if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION - // Handle a special case -- some handler entries can't have zero profile count. - // - if (this->bbIsHandlerBeg(block) && block->isRunRarely()) - { - JITDUMP("Suppressing zero count for " FMT_BB " as it is a handler entry\n", block->bbNum); - block->makeBlockHot(); - } -#endif } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 6ab0977c55c252..8b73d10aa8dc1d 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -3083,17 +3083,12 @@ bool Compiler::fgFuncletsAreCold() // // Notes: // Walk the basic blocks list to determine the first block to place in the -// cold section. This would be the first of a series of rarely executed blocks +// cold section. This would be the first of a series of rarely executed blocks // such that no succeeding blocks are in a try region or an exception handler // or are rarely executed. // PhaseStatus Compiler::fgDetermineFirstColdBlock() { - // Since we may need to create a new transition block - // we assert that it is OK to create new blocks. - // - assert(fgPredsComputed); - assert(fgSafeBasicBlockCreation); assert(fgFirstColdBlock == nullptr); if (!opts.compProcedureSplitting) @@ -3134,15 +3129,6 @@ PhaseStatus Compiler::fgDetermineFirstColdBlock() for (lblk = nullptr, block = fgFirstBB; block != nullptr; lblk = block, block = block->Next()) { - bool blockMustBeInHotSection = false; - -#if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION - if (bbIsHandlerBeg(block)) - { - blockMustBeInHotSection = true; - } -#endif // HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION - // Make note of if we're in the funclet section, // so we can stop the search early. if (block == fgFirstFuncletBB) @@ -3156,7 +3142,7 @@ PhaseStatus Compiler::fgDetermineFirstColdBlock() // We have a candidate for first cold block // Is this a hot block? - if (blockMustBeInHotSection || (block->isRunRarely() == false)) + if (!block->isRunRarely()) { // We have to restart the search for the first cold block firstColdBlock = nullptr; @@ -3195,7 +3181,7 @@ PhaseStatus Compiler::fgDetermineFirstColdBlock() } // Is this a cold block? - if (!blockMustBeInHotSection && block->isRunRarely()) + if (block->isRunRarely()) { // // If the last block that was hot was a BBJ_COND diff --git a/src/coreclr/jit/jit.h b/src/coreclr/jit/jit.h index cc8c8cb717d9ab..11cd55699dc99f 100644 --- a/src/coreclr/jit/jit.h +++ b/src/coreclr/jit/jit.h @@ -470,9 +470,8 @@ class GlobalJitOptions /*****************************************************************************/ -#define CSE_INTO_HANDLERS 0 -#define DUMP_FLOWGRAPHS DEBUG // Support for creating Xml Flowgraph reports in *.fgx files -#define HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION 0 // if 1 we must have all handler entry points in the Hot code section +#define CSE_INTO_HANDLERS 0 +#define DUMP_FLOWGRAPHS DEBUG // Support for creating Xml Flowgraph reports in *.fgx files /*****************************************************************************/ From a0beed4fa56aaf4d3cb2f02b5cdb68f8929e1a60 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 26 Apr 2024 13:54:43 -0700 Subject: [PATCH 144/248] Handle case where falseValue is contained (#101515) * Handle case where falseValue is contained * Handle cases where Abs() is wrapped in conditional with AllBitsSet mask * Add a missing case for Abs() handling * jit format * Review comments * Review feedback * Another review feedback --- src/coreclr/jit/gentree.h | 27 ++++++++++++ src/coreclr/jit/hwintrinsic.cpp | 2 +- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 48 ++++++++++++++++++++- 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index 079174f67e939b..2f3a2a7b2f573b 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -1770,6 +1770,7 @@ struct GenTree inline bool IsVectorZero() const; inline bool IsVectorCreate() const; inline bool IsVectorAllBitsSet() const; + inline bool IsMaskAllBitsSet() const; inline bool IsVectorConst(); inline uint64_t GetIntegralVectorConstElement(size_t index, var_types simdBaseType); @@ -9238,6 +9239,32 @@ inline bool GenTree::IsVectorAllBitsSet() const return false; } +inline bool GenTree::IsMaskAllBitsSet() const +{ +#ifdef TARGET_ARM64 + static_assert_no_msg(AreContiguous(NI_Sve_CreateTrueMaskByte, NI_Sve_CreateTrueMaskDouble, + NI_Sve_CreateTrueMaskInt16, NI_Sve_CreateTrueMaskInt32, + NI_Sve_CreateTrueMaskInt64, NI_Sve_CreateTrueMaskSByte, + NI_Sve_CreateTrueMaskSingle, NI_Sve_CreateTrueMaskUInt16, + NI_Sve_CreateTrueMaskUInt32, NI_Sve_CreateTrueMaskUInt64)); + + if (OperIsHWIntrinsic()) + { + NamedIntrinsic id = AsHWIntrinsic()->GetHWIntrinsicId(); + if (id == NI_Sve_ConvertMaskToVector) + { + GenTree* op1 = AsHWIntrinsic()->Op(1); + assert(op1->OperIsHWIntrinsic()); + id = op1->AsHWIntrinsic()->GetHWIntrinsicId(); + } + return ((id == NI_Sve_CreateTrueMaskAll) || + ((id >= NI_Sve_CreateTrueMaskByte) && (id <= NI_Sve_CreateTrueMaskUInt64))); + } + +#endif + return false; +} + //------------------------------------------------------------------- // IsVectorConst: returns true if this node is a HWIntrinsic that represents a constant. // diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index 96060b2beacb7d..3187c3e5c2e044 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -1622,7 +1622,7 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, GenTree* op1 = retNode->AsHWIntrinsic()->Op(1); if (intrinsic == NI_Sve_ConditionalSelect) { - if (op1->IsVectorAllBitsSet()) + if (op1->IsVectorAllBitsSet() || op1->IsMaskAllBitsSet()) { return retNode->AsHWIntrinsic()->Op(2); } diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index e9983f700361c5..c38afb87a83340 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -406,8 +406,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // Handle case where op2 is operation that needs embedded mask GenTree* op2 = intrin.op2; assert(intrin.id == NI_Sve_ConditionalSelect); - assert(op2->isContained()); assert(op2->OperIsHWIntrinsic()); + assert(op2->isContained()); // Get the registers and intrinsics that needs embedded mask const HWIntrinsic intrinEmbMask(op2->AsHWIntrinsic()); @@ -439,10 +439,54 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) { case 1: assert(!instrIsRMW); + if (targetReg != falseReg) { - GetEmitter()->emitIns_R_R(INS_sve_movprfx, EA_SCALABLE, targetReg, falseReg); + // If targetReg is not the same as `falseReg` then need to move + // the `falseReg` to `targetReg`. + + if (intrin.op3->isContained()) + { + assert(intrin.op3->IsVectorZero()); + if (intrin.op1->isContained()) + { + // We already skip importing ConditionalSelect if op1 == trueAll, however + // if we still see it here, it is because we wrapped the predicated instruction + // inside ConditionalSelect. + // As such, no need to move the `falseReg` to `targetReg` + // because the predicated instruction will eventually set it. + assert(intrin.op1->IsMaskAllBitsSet()); + } + else + { + // If falseValue is zero, just zero out those lanes of targetReg using `movprfx` + // and /Z + GetEmitter()->emitIns_R_R_R(INS_sve_movprfx, emitSize, targetReg, maskReg, targetReg, + opt); + } + } + else if (targetReg == embMaskOp1Reg) + { + // target != falseValue, but we do not want to overwrite target with `embMaskOp1Reg`. + // We will first do the predicate operation and then do conditionalSelect inactive + // elements from falseValue + + // We cannot use use `movprfx` here to move falseReg to targetReg because that will + // overwrite the value of embMaskOp1Reg which is present in targetReg. + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp1Reg, opt); + + GetEmitter()->emitIns_R_R_R_R(INS_sve_sel, emitSize, targetReg, maskReg, targetReg, + falseReg, opt, INS_SCALABLE_OPTS_UNPREDICATED); + break; + } + else + { + // At this point, target != embMaskOp1Reg != falseReg, so just go ahead + // and move the falseReg unpredicated into targetReg. + GetEmitter()->emitIns_R_R(INS_sve_movprfx, EA_SCALABLE, targetReg, falseReg); + } } + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp1Reg, opt); break; From cdfc8f255ddda5f6578e55fabb3b7382e6770730 Mon Sep 17 00:00:00 2001 From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com> Date: Fri, 26 Apr 2024 15:25:05 -0700 Subject: [PATCH 145/248] Create separate attribute for warning behavior differences (#101220) To help track differences in the warning behavior of the trimming related tools, this modifies how adds UnexpectedWarning, and requires an issue link to be provided when there is a ProducedBy argument to the constructor. To enforce that either both a ProducedBy and IssueLink is provided or neither, the ProducedBy property is removed and is provided as the second to last argument, and IssueLink is provided as the last argument. ExpectedWarning means that the correct behavior is to warn. Any attributes that expect it only from a subset of the tools must provide an issue link. (These are mostly blank strings now, though) UnexpectedWarning means that this warning is not the correct behavior. These attributes always include a ProducedBy anrdshould link to an issue. Changes Look for a Tool attribute argument in the second to last position of ExpectedWarning and Unexpected warning when a ProducedBy property is not found. Find a replace existing ExpectedWarnings to use the new constructors. Adds issue links within AttributedMembersAccessedViaReflection.cs and in some places in ArrayDataFlow.cs --- .../TestCasesRunner/ResultChecker.cs | 25 +- .../TestChecker.cs | 69 ++- .../DataFlowTests.g.cs | 6 - .../Assertions/ExpectedWarningAttribute.cs | 25 +- .../Assertions/UnexpectedWarningAttribute.cs | 26 ++ .../CoreLink/InvalidIsTrimmableAttribute.cs | 2 +- .../AnnotatedMembersAccessedViaReflection.cs | 98 ++--- ...notatedMembersAccessedViaUnsafeAccessor.cs | 14 +- .../DataFlow/ArrayDataFlow.cs | 147 +++---- .../DataFlow/AssemblyQualifiedNameDataflow.cs | 5 +- .../DataFlow/AttributeConstructorDataflow.cs | 4 +- .../DataFlow/AttributeFieldDataflow.cs | 2 +- .../DataFlow/AttributePropertyDataflow.cs | 6 +- .../DataFlow/ByRefDataflow.cs | 30 +- ...pilerGeneratedCodeAccessedViaReflection.cs | 234 ++++------ .../DataFlow/CompilerGeneratedCodeDataflow.cs | 16 +- ...ompilerGeneratedCodeInPreservedAssembly.cs | 4 +- ...ratedCodeInPreservedAssemblyWithWarning.cs | 4 +- .../DataFlow/ComplexTypeHandling.cs | 2 +- .../DataFlow/ConstructedTypesDataFlow.cs | 12 +- .../DataFlow/ConstructorDataFlow.cs | 12 +- .../DataFlow/DynamicObjects.cs | 20 +- .../DataFlow/ExceptionalDataFlow.cs | 236 ++++------- .../DataFlow/ExponentialDataFlow.cs | 46 +- .../DataFlow/FeatureCheckDataFlow.cs | 117 +++-- .../DataFlow/FeatureGuardAttributeDataFlow.cs | 44 +- .../DataFlow/FieldDataFlow.cs | 13 +- .../DataFlow/GenericParameterDataFlow.cs | 36 +- .../GenericParameterWarningLocation.cs | 154 +++---- .../DataFlow/GetTypeDataFlow.cs | 6 +- .../DataFlow/InlineArrayDataflow.cs | 4 +- .../DataFlow/LocalDataFlow.cs | 49 +-- .../DataFlow/MakeGenericDataFlow.cs | 6 +- .../DataFlow/MakeGenericDataflowIntrinsics.cs | 8 +- .../DataFlow/MethodByRefParameterDataFlow.cs | 12 +- .../DataFlow/MethodByRefReturnDataFlow.cs | 14 +- .../DataFlow/MethodOutParameterDataFlow.cs | 4 +- .../DataFlow/MethodParametersDataFlow.cs | 6 +- .../DataFlow/MethodReturnParameterDataFlow.cs | 6 +- .../DataFlow/MethodThisDataFlow.cs | 2 +- .../DataFlow/PropertyDataFlow.cs | 105 ++--- .../DataFlow/RefFieldDataFlow.cs | 84 ++-- .../DataFlow/TypeBaseTypeDataFlow.cs | 5 +- .../DataFlow/UnresolvedMembers.cs | 16 +- ...odHierarchyDataflowAnnotationValidation.cs | 52 +-- .../Extensibility/CustomWarningUsage.cs | 2 +- .../LinkXml/LinkXmlErrorCases.cs | 10 +- .../Logging/SourceLines.cs | 8 +- .../Reflection/ActivatorCreateInstance.cs | 10 +- .../ExpressionPropertyMethodInfo.cs | 4 +- .../Reflection/MethodsUsedViaReflection.cs | 2 +- .../Reflection/ObjectGetType.cs | 4 +- .../TypeHierarchyReflectionWarnings.cs | 16 +- .../Reflection/TypeUsedViaReflection.cs | 12 +- .../RequiresCapability/BasicRequires.cs | 56 +-- ...flectionAccessFromCompilerGeneratedCode.cs | 64 ++- .../RequiresAccessedThrough.cs | 82 ++-- .../RequiresAttributeMismatch.cs | 316 +++++++------- .../RequiresInCompilerGeneratedCode.cs | 400 +++++++++--------- .../RequiresCapability/RequiresOnAttribute.cs | 48 +-- .../RequiresCapability/RequiresOnClass.cs | 282 ++++++------ .../RequiresOnStaticConstructor.cs | 26 +- .../RequiresOnVirtualsAndInterfaces.cs | 72 ++-- .../RequiresCapability/RequiresViaDataflow.cs | 26 +- .../RequiresCapability/RequiresViaXml.cs | 2 +- .../RequiresWithCopyAssembly.cs | 16 +- .../SingleFile/SingleFileIntrinsics.cs | 12 +- .../FeatureGuardSubstitutions.cs | 26 +- .../FeatureGuardSubstitutionsDisabled.cs | 4 +- .../Substitutions/ResourceSubstitutions.cs | 2 +- ...dundantSuppressionsFeatureSubstitutions.cs | 2 +- .../DetectRedundantSuppressionsFromXML.cs | 6 +- .../DetectRedundantSuppressionsInAssembly.cs | 2 +- ...dantSuppressionsInCompilerGeneratedCode.cs | 8 +- ...tRedundantSuppressionsInMembersAndTypes.cs | 34 +- ...uppressionsInMembersAndTypesUsingTarget.cs | 8 +- .../DetectRedundantSuppressionsInModule.cs | 2 +- ...SuppressWarningsInCompilerGeneratedCode.cs | 16 +- .../TestCasesRunner/ResultChecker.cs | 28 +- 79 files changed, 1642 insertions(+), 1754 deletions(-) create mode 100644 src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/UnexpectedWarningAttribute.cs diff --git a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ResultChecker.cs b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ResultChecker.cs index 770bc1e97dfa2b..a6eb6007661f62 100644 --- a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ResultChecker.cs +++ b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ResultChecker.cs @@ -159,6 +159,8 @@ protected virtual void AdditionalChecking (TrimmedTestCaseResult linkResult, Ass private static bool IsProducedByNativeAOT (CustomAttribute attr) { + if (attr.ConstructorArguments.Count > 2 && attr.ConstructorArguments[^2].Type.Name == "Tool") + return ((Tool)attr.ConstructorArguments[^2].Value).HasFlag(Tool.NativeAot); var producedBy = attr.GetPropertyValue ("ProducedBy"); return producedBy is null ? true : ((Tool) producedBy).HasFlag (Tool.NativeAot); } @@ -227,12 +229,29 @@ private void VerifyLoggedMessages (AssemblyDefinition original, TrimmingTestLogg } break; - case nameof (ExpectedWarningAttribute): { + case nameof (ExpectedWarningAttribute) or nameof(UnexpectedWarningAttribute): { var expectedWarningCode = (string) attr.GetConstructorArgumentValue (0); if (!expectedWarningCode.StartsWith ("IL")) { - Assert.Fail ($"The warning code specified in {nameof (ExpectedWarningAttribute)} must start with the 'IL' prefix. Specified value: '{expectedWarningCode}'."); + Assert.Fail ($"The warning code specified in {attr.AttributeType.Name} must start with the 'IL' prefix. Specified value: '{expectedWarningCode}'."); } - var expectedMessageContains = ((CustomAttributeArgument[]) attr.GetConstructorArgumentValue (1)).Select (a => (string) a.Value).ToArray (); + IEnumerable expectedMessageContains = attr.Constructor.Parameters switch + { + // ExpectedWarningAttribute(string warningCode, params string[] expectedMessages) + // ExpectedWarningAttribute(string warningCode, string[] expectedMessages, Tool producedBy, string issueLink) + [_, { ParameterType.IsArray: true }, ..] + => ((CustomAttributeArgument[])attr.ConstructorArguments[1].Value) + .Select(caa => (string)caa.Value), + // ExpectedWarningAttribute(string warningCode, string expectedMessage1, string expectedMessage2, Tool producedBy, string issueLink) + [_, { ParameterType.Name: "String" }, { ParameterType.Name: "String" }, { ParameterType.Name: "Tool" }, _] + => [(string)attr.GetConstructorArgumentValue(1), (string)attr.GetConstructorArgumentValue(2)], + // ExpectedWarningAttribute(string warningCode, string expectedMessage, Tool producedBy, string issueLink) + [_, { ParameterType.Name: "String" }, { ParameterType.Name: "Tool" }, _] + => [(string)attr.GetConstructorArgumentValue(1)], + // ExpectedWarningAttribute(string warningCode, Tool producedBy, string issueLink) + [_, { ParameterType.Name: "Tool" }, _] + => [], + _ => throw new UnreachableException(), + }; string fileName = (string) attr.GetPropertyValue ("FileName")!; int? sourceLine = (int?) attr.GetPropertyValue ("SourceLine"); int? sourceColumn = (int?) attr.GetPropertyValue ("SourceColumn"); diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs index 7631b802fbcc87..c50d24f136051d 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text.RegularExpressions; @@ -66,7 +67,7 @@ public void Check (bool allowMissingWarnings) } if (message.Length > 0) { - Assert.Fail(message); + Assert.Fail (message); } } @@ -207,51 +208,62 @@ private void ValidateDiagnostics (CSharpSyntaxNode memberSyntax, SyntaxList arg.Key.StartsWith ('#')).Count () - 2; + if (args.TryGetValue ($"#{toolArg}", out var maybeProducedBy) && TryGetProducedBy (maybeProducedBy, out Tool producedByTool)) { + return producedByTool.HasFlag (Tool.Analyzer); + } return true; default: return false; } - static Tool GetProducedBy (ExpressionSyntax expression) + static bool TryGetProducedBy (ExpressionSyntax expression, out Tool producedBy) { - var producedBy = (Tool) 0x0; + producedBy = (Tool) 0x0; switch (expression) { - case BinaryExpressionSyntax binaryExpressionSyntax: + case BinaryExpressionSyntax binaryExpressionSyntax when binaryExpressionSyntax.Kind () == SyntaxKind.BitwiseOrExpression: if (!Enum.TryParse ((binaryExpressionSyntax.Left as MemberAccessExpressionSyntax)!.Name.Identifier.ValueText, out var besProducedBy)) - throw new ArgumentException ("Expression must be a ProducedBy value", nameof (expression)); + return false; producedBy |= besProducedBy; producedBy |= GetProducedBy (binaryExpressionSyntax.Right); break; case MemberAccessExpressionSyntax memberAccessExpressionSyntax: if (!Enum.TryParse (memberAccessExpressionSyntax.Name.Identifier.ValueText, out var maeProducedBy)) - throw new ArgumentException ("Expression must be a ProducedBy value", nameof (expression)); + return false; producedBy |= maeProducedBy; break; default: - break; + return false; } - return producedBy; + return true; + } + + static Tool GetProducedBy (ExpressionSyntax expression) + { + return TryGetProducedBy (expression, out var tool) ? tool : throw new ArgumentException ("Expression must be a ProducedBy value", nameof (expression)); } } bool TryValidateExpectedDiagnostic (AttributeSyntax attribute, List diagnostics, [NotNullWhen (true)] out int? matchIndex, [NotNullWhen (false)] out string? missingDiagnosticMessage) { - switch (attribute.Name.ToString ()) { - case "ExpectedWarning": + switch (attribute.Name.ToString () + "Attribute") { + case nameof (ExpectedWarningAttribute): + case nameof (UnexpectedWarningAttribute): return TryValidateExpectedWarningAttribute (attribute!, diagnostics, out matchIndex, out missingDiagnosticMessage); - case "LogContains": + case nameof (LogContainsAttribute): return TryValidateLogContainsAttribute (attribute!, diagnostics, out matchIndex, out missingDiagnosticMessage); default: throw new InvalidOperationException ($"Unsupported attribute type {attribute.Name}"); @@ -268,10 +280,29 @@ private bool TryValidateExpectedWarningAttribute (AttributeSyntax attribute, Lis if (!expectedWarningCode.StartsWith ("IL")) throw new InvalidOperationException ($"Expected warning code should start with \"IL\" prefix."); - List expectedMessages = args - .Where (arg => arg.Key.StartsWith ("#") && arg.Key != "#0") - .Select (arg => LinkerTestBase.GetStringFromExpression (arg.Value, _semanticModel)) - .ToList (); + List expectedMessages = ((IMethodSymbol) (_semanticModel.GetSymbolInfo (attribute).Symbol!)).Parameters switch { + // ExpectedWarningAttribute(string warningCode, params string[] expectedMessages) + [_, { IsParams: true }] + => args + .Where (arg => arg.Key.StartsWith ('#') && arg.Key != "#0") + .Select (arg => LinkerTestBase.GetStringFromExpression (arg.Value, _semanticModel)) + .ToList (), + // ExpectedWarningAttribute(string warningCode, string[] expectedMessages, Tool producedBy, string issueLink) + [_, { Type.TypeKind: TypeKind.Array }, _, _] + => ((CollectionExpressionSyntax) args["#1"]).Elements + .Select (arg => LinkerTestBase.GetStringFromExpression (((ExpressionElementSyntax) arg).Expression, _semanticModel)) + .ToList (), + // ExpectedWarningAttribute(string warningCode, string expectedMessage, Tool producedBy, string issueLink) + [_, { Type.SpecialType: SpecialType.System_String }, _, _] + => [LinkerTestBase.GetStringFromExpression (args["#1"], _semanticModel)], + // ExpectedWarningAttribute(string warningCode, string expectedMessage1, string expectedMessage2, Tool producedBy, string issueLink) + [_, { Type.SpecialType: SpecialType.System_String }, { Type.SpecialType: SpecialType.System_String }, _, _] + => [LinkerTestBase.GetStringFromExpression (args["#1"], _semanticModel), LinkerTestBase.GetStringFromExpression (args["#2"], _semanticModel)], + // ExpectedWarningAttribute(string warningCode, Tool producedBy, string issueLink) + [_, _, _] + => [], + _ => throw new UnreachableException (), + }; for (int i = 0; i < diagnostics.Count; i++) { if (Matches (diagnostics[i])) { @@ -318,7 +349,7 @@ private void ValidateLogDoesNotContainAttribute (AttributeSyntax attribute, IRea Assert.False (args.ContainsKey ("#1")); _ = LinkerTestBase.GetStringFromExpression (arg, _semanticModel); if (LogContains (attribute, diagnosticMessages, out var matchIndex, out var findText)) { - Assert.Fail($"LogDoesNotContain failure: Text\n\"{findText}\"\nfound in diagnostic:\n {diagnosticMessages[(int) matchIndex]}"); + Assert.Fail ($"LogDoesNotContain failure: Text\n\"{findText}\"\nfound in diagnostic:\n {diagnosticMessages[(int) matchIndex]}"); } } diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs index 0a390275ea81c4..5c3bd5a9d6654f 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs @@ -19,12 +19,6 @@ public Task GenericParameterDataFlowMarking () return RunTest (allowMissingWarnings: true); } - [Fact] - public Task MakeGenericDataflowIntrinsics () - { - return RunTest (allowMissingWarnings: true); - } - [Fact] public Task MethodByRefParameterDataFlow () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedWarningAttribute.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedWarningAttribute.cs index 648241200ef16a..19b785adabcc06 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedWarningAttribute.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedWarningAttribute.cs @@ -9,8 +9,27 @@ namespace Mono.Linker.Tests.Cases.Expectations.Assertions AttributeTargets.Assembly | AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Event, AllowMultiple = true, Inherited = false)] + /// + /// An attribute applied to a member to indicate that a warning is expected in ideal behavior, and is present in all tools + /// public class ExpectedWarningAttribute : EnableLoggerAttribute { + public ExpectedWarningAttribute (string warningCode, string[] messageContains, Tool producedBy, string issueLinkOrReason) + { + } + + public ExpectedWarningAttribute (string warningCode, string messageContains, Tool producedBy, string issueLinkOrReason) + { + } + + public ExpectedWarningAttribute (string warningCode, string messageContains, string messageContains2, Tool producedBy, string issueLinkOrReason) + { + } + + public ExpectedWarningAttribute (string warningCode, Tool producedBy, string issueLinkOrReason) + { + } + public ExpectedWarningAttribute (string warningCode, params string[] messageContains) { } @@ -19,12 +38,6 @@ public ExpectedWarningAttribute (string warningCode, params string[] messageCont public int SourceLine { get; set; } public int SourceColumn { get; set; } - /// - /// Property used by the result checkers of trimmer and analyzers to determine whether - /// the tool should have produced the specified warning on the annotated member. - /// - public Tool ProducedBy { get; set; } = Tool.TrimmerAnalyzerAndNativeAot; - public bool CompilerGeneratedCode { get; set; } } } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/UnexpectedWarningAttribute.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/UnexpectedWarningAttribute.cs new file mode 100644 index 00000000000000..d745b61f3a1675 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/UnexpectedWarningAttribute.cs @@ -0,0 +1,26 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; + +namespace Mono.Linker.Tests.Cases.Expectations.Assertions +{ + [AttributeUsage ( + AttributeTargets.Assembly | AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Event, + AllowMultiple = true, + Inherited = false)] + /// + /// An attribute applied to a member to indicate that a warning is raised in tests, but should not be present in ideal behavior + /// + public class UnexpectedWarningAttribute : ExpectedWarningAttribute + { + public UnexpectedWarningAttribute (string warningCode, string[] messageContains, Tool producedBy, string issueLinkOrReason) + : base (warningCode, messageContains, producedBy, issueLinkOrReason) { } + public UnexpectedWarningAttribute (string warningCode, string messageContains, Tool producedBy, string issueLinkOrReason) + : base (warningCode, messageContains, producedBy, issueLinkOrReason) { } + public UnexpectedWarningAttribute (string warningCode, string messageContains, string messageContains2, Tool producedBy, string issueLinkOrReason) + : base (warningCode, messageContains, messageContains2, producedBy, issueLinkOrReason) { } + public UnexpectedWarningAttribute (string warningCode, Tool producedBy, string issueLinkOrReason) + : base (warningCode, producedBy, issueLinkOrReason) { } + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InvalidIsTrimmableAttribute.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InvalidIsTrimmableAttribute.cs index 35463fd52d442f..57b000fe3d377e 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InvalidIsTrimmableAttribute.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InvalidIsTrimmableAttribute.cs @@ -29,4 +29,4 @@ public static void Unused () { } } -} \ No newline at end of file +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaReflection.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaReflection.cs index d3fcbf32df47e5..f071090462b2e4 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaReflection.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaReflection.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; +using System.Reflection; using System.Runtime.InteropServices; using Mono.Linker.Tests.Cases.DataFlow; using Mono.Linker.Tests.Cases.Expectations.Assertions; @@ -54,8 +55,8 @@ static void ReflectionReadOnly () typeof (AnnotatedField).GetField ("_annotatedField").GetValue (null); } - // DynamicDependency is not supported yet in the analyzer https://github.com/dotnet/runtime/issues/83080 - [ExpectedWarning ("IL2110", nameof (_annotatedField), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // DynamicDependency is not supported yet in the analyzer + [ExpectedWarning ("IL2110", nameof (_annotatedField), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] [DynamicDependency (DynamicallyAccessedMemberTypes.PublicFields, typeof (AnnotatedField))] static void DynamicDependency () { @@ -67,8 +68,8 @@ static void DynamicDependencySuppressedByRUC () { } - // DynamicDependency is not supported yet in the analyzer https://github.com/dotnet/runtime/issues/83080 - [ExpectedWarning ("IL2110", nameof (_annotatedField), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // DynamicDependency is not supported yet in the analyzer + [ExpectedWarning ("IL2110", nameof (_annotatedField), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] [DynamicDependency (nameof (_annotatedField), typeof (AnnotatedField))] static void DynamicDependencyByName () { @@ -128,8 +129,7 @@ static void PotentialWriteAccess (ref Type type) { } - // https://github.com/dotnet/linker/issues/3172 - [ExpectedWarning ("IL2110", nameof (AnnotatedField._annotatedField), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2110", nameof (AnnotatedField._annotatedField), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/3172")] static void LdToken () { Expression a = () => PotentialWriteAccess (ref _annotatedField); @@ -177,7 +177,7 @@ void LdftnOnLambda () { var _ = new Action ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] - () => MethodWithAnnotatedThisParameter ()); + () => MethodWithAnnotatedThisParameter ()); } [ExpectedWarning ("IL2111")] @@ -233,8 +233,8 @@ static void AnnotatedAttributeConstructor () { } - // DynamicDependency is not supported yet in the analyzer https://github.com/dotnet/runtime/issues/83080 - [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // DynamicDependency is not supported yet in the analyzer + [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] [DynamicDependency (DynamicallyAccessedMemberTypes.PublicMethods, typeof (AnnotatedMethodParameters))] static void DynamicDependency () { @@ -246,8 +246,8 @@ static void DynamicDependencySuppressedByRUC () { } - // DynamicDependency is not supported yet in the analyzer https://github.com/dotnet/runtime/issues/83080 - [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // DynamicDependency is not supported yet in the analyzer + [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] [DynamicDependency (nameof (MethodWithSingleAnnotatedParameter), typeof (AnnotatedMethodParameters))] static void DynamicDependencyByName () { @@ -278,7 +278,7 @@ static void LdftnSuppressedByRequiresUnreferencedCode () } [ExpectedWarning ("IL2111")] - static void + static void LdftnOnLambda () { var _ = new Action ( @@ -299,7 +299,7 @@ static void LdftnOnLambdaTriggersLamdaAnalysis () { var _ = new Action ( [ExpectedWarning ("IL2067", nameof (type), nameof (DataFlowTypeExtensions.RequiresAll))] - (Type type) => { type.RequiresAll (); }); + (Type type) => { type.RequiresAll (); }); } static void LdftnOnLocalMethodTriggersLocalMethodAnalysis () @@ -332,8 +332,8 @@ static void Ldvirtftn () [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter))] [ExpectedWarning ("IL2111", nameof (IWithAnnotatedMethod.AnnotatedMethod))] [ExpectedWarning ("IL2111", nameof (IWithAnnotatedMethod.AnnotatedMethod))] - [ExpectedWarning ("IL2118", nameof (LdftnOnLambdaTriggersLamdaAnalysis), ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", nameof (LdftnOnLocalMethodTriggersLocalMethodAnalysis), ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", nameof (LdftnOnLambdaTriggersLamdaAnalysis), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [ExpectedWarning ("IL2118", nameof (LdftnOnLocalMethodTriggersLocalMethodAnalysis), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] static void DynamicallyAccessedMembersAll1 () { typeof (AnnotatedMethodParameters).RequiresAll (); @@ -346,16 +346,15 @@ static void DynamicallyAccessedMembersAll1 () [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter))] [ExpectedWarning ("IL2111", nameof (IWithAnnotatedMethod.AnnotatedMethod))] [ExpectedWarning ("IL2111", nameof (IWithAnnotatedMethod.AnnotatedMethod))] - [ExpectedWarning ("IL2118", nameof (LdftnOnLambdaTriggersLamdaAnalysis), ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", nameof (LdftnOnLocalMethodTriggersLocalMethodAnalysis), ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", nameof (LdftnOnLambdaTriggersLamdaAnalysis), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [ExpectedWarning ("IL2118", nameof (LdftnOnLocalMethodTriggersLocalMethodAnalysis), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] static void DynamicallyAccessedMembersAll2 () { typeof (AnnotatedMethodParameters).RequiresAll (); } - // https://github.com/dotnet/linker/issues/3172 - [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2067", nameof (MethodWithSingleAnnotatedParameter), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/3172")] + [UnexpectedWarning ("IL2067", nameof (MethodWithSingleAnnotatedParameter), Tool.Analyzer, "https://github.com/dotnet/linker/issues/3172")] static void LdToken () { Expression> _ = (Type t) => MethodWithSingleAnnotatedParameter (t); @@ -420,8 +419,7 @@ static void ReflectionOnVirtualSuppressedByRUC () typeof (AnnotatedMethodReturnValue).GetMethod (nameof (VirtualMethodWithAnnotatedReturnValue)).Invoke (null, null); } - // DynamicDependency is not supported yet in the analyzer https://github.com/dotnet/runtime/issues/83080 - [ExpectedWarning ("IL2111", nameof (VirtualMethodWithAnnotatedReturnValue), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2111", nameof (VirtualMethodWithAnnotatedReturnValue), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] [DynamicDependency (DynamicallyAccessedMemberTypes.PublicMethods, typeof (AnnotatedMethodReturnValue))] static void DynamicDependency () { @@ -443,8 +441,7 @@ static void DynamicDependencyByNameOnInstance () { } - // DynamicDependency is not supported yet in the analyzer https://github.com/dotnet/runtime/issues/83080 - [ExpectedWarning ("IL2111", nameof (VirtualMethodWithAnnotatedReturnValue), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2111", nameof (VirtualMethodWithAnnotatedReturnValue), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] [DynamicDependency (nameof (VirtualMethodWithAnnotatedReturnValue), typeof (AnnotatedMethodReturnValue))] static void DynamicDependencyByNameOnVirtual () { @@ -483,8 +480,7 @@ static void LdTokenOnStatic () Expression _ = () => StaticMethodWithAnnotatedReturnValue (); } - // https://github.com/dotnet/linker/issues/3172 - [ExpectedWarning ("IL2111", nameof (VirtualMethodWithAnnotatedReturnValue), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2111", nameof (VirtualMethodWithAnnotatedReturnValue), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/3172")] static void LdTokenOnVirtual () { Expression> _ = (a) => a.VirtualMethodWithAnnotatedReturnValue (); @@ -527,7 +523,7 @@ class AnnotatedProperty public virtual Type VirtualProperty4WithAnnotation { get => null; set { value.ToString (); } } public static Type Property5WithAnnotationOnMembers { - [ExpectedWarning ("IL2078", nameof (Property5WithAnnotationOnMembers) + ".get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2078", nameof (Property5WithAnnotationOnMembers) + ".get", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101191")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicEvents)] get; [param: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicEvents)] @@ -596,13 +592,13 @@ static void AnnotatedAttributeProperty () } // DynamicDependency is not supported yet in the analyzer https://github.com/dotnet/runtime/issues/83080 - [ExpectedWarning ("IL2111", nameof (Property1WithAnnotation) + ".set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2111", nameof (VirtualProperty3WithAnnotationGetterOnly) + ".get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2111", nameof (VirtualProperty4WithAnnotation) + ".get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2111", nameof (VirtualProperty4WithAnnotation) + ".set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2111", nameof (Property5WithAnnotationOnMembers) + ".set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2111", nameof (VirtualProperty6WithAnnotationOnMembers) + ".get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2111", nameof (VirtualProperty6WithAnnotationOnMembers) + ".set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2111", nameof (Property1WithAnnotation) + ".set", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] + [ExpectedWarning ("IL2111", nameof (VirtualProperty3WithAnnotationGetterOnly) + ".get", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] + [ExpectedWarning ("IL2111", nameof (VirtualProperty4WithAnnotation) + ".get", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] + [ExpectedWarning ("IL2111", nameof (VirtualProperty4WithAnnotation) + ".set", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] + [ExpectedWarning ("IL2111", nameof (Property5WithAnnotationOnMembers) + ".set", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] + [ExpectedWarning ("IL2111", nameof (VirtualProperty6WithAnnotationOnMembers) + ".get", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] + [ExpectedWarning ("IL2111", nameof (VirtualProperty6WithAnnotationOnMembers) + ".set", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] [DynamicDependency (DynamicallyAccessedMemberTypes.PublicProperties, typeof (AnnotatedProperty))] static void DynamicDependency () { @@ -685,15 +681,15 @@ static void DynamicallyAccessedMembersAll2 () typeof (AnnotatedProperty).RequiresAll (); } - // Analyzer doesn't produce this warning https://github.com/dotnet/linker/issues/2628 - [ExpectedWarning ("IL2110", nameof (Property1WithAnnotation), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // Analyzer doesn't produce this warning + [ExpectedWarning ("IL2110", nameof (Property1WithAnnotation), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2628")] static void DynamicallyAccessedFields () { typeof (AnnotatedProperty).RequiresNonPublicFields (); } - // Action delegate is not handled correctly https://github.com/dotnet/runtime/issues/84918 - [ExpectedWarning ("IL2111", nameof (Property1WithAnnotation), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // Analyzer doesn't recognize Linq.Expressions + [ExpectedWarning ("IL2111", nameof (Property1WithAnnotation) + ".set", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101148")] static void LdToken () { Expression> _ = () => Property1WithAnnotation; @@ -835,8 +831,7 @@ static void DynamicallyAccessedMembersAll2 () typeof (AnnotationOnGenerics).RequiresAll (); } - // https://github.com/dotnet/linker/issues/3172 - [ExpectedWarning ("IL2111", "GenericWithAnnotatedMethod", "AnnotatedMethod", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2111", ["GenericWithAnnotatedMethod", "AnnotatedMethod"], Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/3172")] static void LdToken () { // Note that this should warn even though the code looks "Correct" @@ -867,13 +862,13 @@ struct ValueWithAnnotatedField public Type _typeField; } - // Analyzer doesn't take into account interop attributes https://github.com/dotnet/linker/issues/2562 - [ExpectedWarning ("IL2110", nameof (ValueWithAnnotatedField._typeField), ProducedBy = Tool.Trimmer)] + // Analyzer doesn't take into account interop attributes + [ExpectedWarning ("IL2110", nameof (ValueWithAnnotatedField._typeField), Tool.Trimmer, "https://github.com/dotnet/linker/issues/2562")] [DllImport ("nonexistent")] static extern ValueWithAnnotatedField GetValueWithAnnotatedField (); - // Analyzer doesn't take into account interop attributes https://github.com/dotnet/linker/issues/2562 - [ExpectedWarning ("IL2110", nameof (ValueWithAnnotatedField._typeField), ProducedBy = Tool.Trimmer)] + // Analyzer doesn't take into account interop attributes + [ExpectedWarning ("IL2110", nameof (ValueWithAnnotatedField._typeField), Tool.Trimmer, "https://github.com/dotnet/linker/issues/2562")] [DllImport ("nonexistent")] static extern void AcceptValueWithAnnotatedField (ValueWithAnnotatedField value); @@ -899,29 +894,28 @@ class DelegateCreation static void TestField () { var d = new UnannotatedDelegate (field); - d(typeof(int)); + d (typeof (int)); } static void TestProperty () { var d = new UnannotatedDelegate (Property); - d(typeof(int)); + d (typeof (int)); } [ExpectedWarning ("IL2111")] static void TestLambda () { var d = new UnannotatedDelegate ( - ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type t) => - { }); - d(typeof(int)); + ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type t) => { }); + d (typeof (int)); } [ExpectedWarning ("IL2111", "LocalMethod")] static void TestLocalMethod () { var d = new UnannotatedDelegate (LocalMethod); - d(typeof(int)); + d (typeof (int)); void LocalMethod ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) @@ -931,14 +925,14 @@ void LocalMethod ( static void TestMethodReturnValue () { var d = new UnannotatedDelegate (MethodReturnValue ()); - d(typeof(int)); + d (typeof (int)); } static void TestEvent () { var d = new UnannotatedDelegate (Event); - d(typeof(int)); + d (typeof (int)); } public static void Test () diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaUnsafeAccessor.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaUnsafeAccessor.cs index 9b8cd8959651b0..eb016da603f4c6 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaUnsafeAccessor.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaUnsafeAccessor.cs @@ -54,7 +54,7 @@ private static void MethodWithAnnotationMismatch ([DynamicallyAccessedMembers (D private static Type FieldWithAnnotationMismatch; } - [ExpectedWarning ("IL2111", ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2111", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/101195")] [UnsafeAccessor (UnsafeAccessorKind.StaticMethod)] extern static void MethodWithAnnotatedParameter (Target target, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type); @@ -63,23 +63,23 @@ private static void MethodWithAnnotationMismatch ([DynamicallyAccessedMembers (D [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] extern static Type StaticMethodWithAnnotatedReturnValue (Target target); - [ExpectedWarning ("IL2111", ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2111", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/101195")] [UnsafeAccessor (UnsafeAccessorKind.Method)] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] extern static Type VirtualMethodWithAnnotatedReturnValue (Target target); - [ExpectedWarning ("IL2110", ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2110", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/101195")] [UnsafeAccessor (UnsafeAccessorKind.StaticField)] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] extern static ref Type AnnotatedField (Target target); - [ExpectedWarning ("IL2111", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2067", ProducedBy = Tool.NativeAot)] + [UnexpectedWarning ("IL2111", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/101195")] + [ExpectedWarning ("IL2067", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101195")] [UnsafeAccessor (UnsafeAccessorKind.StaticMethod)] extern static void MethodWithAnnotationMismatch (Target target, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] Type type); - [ExpectedWarning ("IL2110", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2078", ProducedBy = Tool.NativeAot)] + [UnexpectedWarning ("IL2110", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/101195")] + [ExpectedWarning ("IL2078", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101195")] [UnsafeAccessor (UnsafeAccessorKind.StaticField)] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] extern static ref Type FieldWithAnnotationMismatch (Target target); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ArrayDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ArrayDataFlow.cs index 1fc103037b3886..b819d459758530 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ArrayDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ArrayDataFlow.cs @@ -117,13 +117,10 @@ static void TestArraySetElementOneElementMix () arr[0].RequiresAll (); } - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "")] // https://github.com/dotnet/linker/issues/2737 - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] static void TestArraySetElementOneElementMerged () { Type[] arr = new Type[1]; @@ -210,14 +207,9 @@ static void TestGetElementAtUnknownIndex (int i = 0) arr[i].RequiresPublicFields (); } - // https://github.com/dotnet/runtime/issues/93416 tracks the discrepancy between - // the analyzer and ILLink/ILCompiler. - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (GetMethods), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetFields), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/93416")] + [ExpectedWarning ("IL2072", [nameof (GetMethods), nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "https://github.com/dotnet/runtime/issues/93416")] + [ExpectedWarning ("IL2072", [nameof (GetFields), nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "https://github.com/dotnet/runtime/issues/93416")] static void TestGetMergedArrayElement (bool b = true) { Type[] arr = new Type[] { GetMethods () }; @@ -227,8 +219,8 @@ static void TestGetMergedArrayElement (bool b = true) arr[0].RequiresAll (); } - // Trimmer code doesnt handle locals from different branches separetely, therefore merges incorrectly GetMethods with Unknown producing both warnings - [ExpectedWarning ("IL2072", nameof (ArrayDataFlow.GetMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // Trimmer code doesn't handle locals from different branches separately, therefore merges incorrectly GetMethods with Unknown producing both warnings + [UnexpectedWarning ("IL2072", nameof (ArrayDataFlow.GetMethods), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/93416")] [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll))] static void TestMergedArrayElementWithUnknownIndex (int i) { @@ -252,9 +244,9 @@ static void TestArrayResetStoreUnknownIndex (int i = 0) } // https://github.com/dotnet/linker/issues/2680 - analyzer doesn't reset array in this case - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "")] // https://github.com/dotnet/linker/issues/2680 - analyzer doesn't reset array in this case - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "")] static void TestArrayResetGetElementOnByRefArray (int i = 0) { Type[] arr = new Type[] { typeof (TestType), typeof (TestType) }; @@ -286,7 +278,7 @@ static void TestArrayResetAfterCall () static void TakesTypesArray (Type[] types) { } // https://github.com/dotnet/linker/issues/2680 - // [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields))] + // [ExpectedSharedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields))] static void TestArrayResetAfterAssignment () { Type[] arr = new Type[] { typeof (TestType) }; @@ -344,9 +336,9 @@ public static void Test () TestAddressOfElement (); } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "")] // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] static void TestArrayWithInitializerOneElementStaticType () { Type[,] arr = new Type[,] { { typeof (TestType) } }; @@ -354,9 +346,9 @@ static void TestArrayWithInitializerOneElementStaticType () arr[0, 1].RequiresPublicMethods (); // Should warn - unknown value at this index } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "")] // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] static void TestArrayWithInitializerOneElementParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type type) { Type[,] arr = new Type[,] { { type } }; @@ -364,11 +356,11 @@ static void TestArrayWithInitializerOneElementParameter ([DynamicallyAccessedMem arr[0, 1].RequiresPublicMethods (); // Should warn - unknown value at this index } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "")] // Below are because we do not handle Multi dimensional arrays - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] static void TestArrayWithInitializerMultipleElementsStaticType () { Type[,] arr = new Type[,] { { typeof (TestType), typeof (TestType), typeof (TestType) } }; @@ -379,13 +371,13 @@ static void TestArrayWithInitializerMultipleElementsStaticType () } // Bug - // [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "")] // Below are because we do not handle Multi dimensional arrays - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] static void TestArrayWithInitializerMultipleElementsMix<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties)] TProperties> ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type typeAll) { @@ -397,9 +389,9 @@ static void TestArrayWithInitializerMultipleElementsStaticType () arr[0, 3].RequiresPublicMethods (); // Should warn - unknown value at this index } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "")] // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] static void TestArraySetElementOneElementStaticType () { Type[,] arr = new Type[1, 1]; @@ -408,9 +400,9 @@ static void TestArraySetElementOneElementStaticType () arr[0, 1].RequiresPublicMethods (); // Should warn - unknown value at this index } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "")] // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] static void TestArraySetElementOneElementParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type type) { Type[,] arr = new Type[1, 1]; @@ -419,11 +411,11 @@ static void TestArraySetElementOneElementParameter ([DynamicallyAccessedMembers arr[0, 1].RequiresPublicMethods (); // Should warn - unknown value at this index } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "")] // Below are because we do not handle Multi dimensional arrays - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] static void TestArraySetElementMultipleElementsStaticType () { Type[,] arr = new Type[1, 3]; @@ -437,13 +429,13 @@ static void TestArraySetElementMultipleElementsStaticType () } // Bug - // [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "")] // Below are because we do not handle Multi dimensional arrays - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] static void TestArraySetElementMultipleElementsMix<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties)] TProperties> ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type typeAll) { @@ -459,13 +451,13 @@ static void TestArraySetElementMultipleElementsStaticType () } // Bug - // [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "")] // Below are because we do not handle Multi dimensional arrays - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] static void TestArraySetElementAndInitializerMultipleElementsMix<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties)] TProperties> ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type typeAll) { @@ -479,16 +471,16 @@ static void TestArraySetElementMultipleElementsStaticType () arr[0, 3].RequiresPublicMethods (); // Should warn - unknown value at this index } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "")] static void TestGetElementAtUnknownIndex (int i = 0) { Type[,] arr = new Type[,] { { typeof (TestType) } }; arr[0, i].RequiresPublicFields (); } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "")] // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), Tool.Trimmer | Tool.NativeAot, "")] static void TestArrayResetStoreUnknownIndex (int i = 0) { Type[,] arr = new Type[,] { { typeof (TestType) } }; @@ -500,11 +492,11 @@ static void TestArrayResetStoreUnknownIndex (int i = 0) } // https://github.com/dotnet/linker/issues/2680 - analyzer doesn't reset array in this case - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "")] // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), Tool.Trimmer | Tool.NativeAot, "")] // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "")] static void TestArrayResetGetElementOnByRefArray (int i = 0) { Type[,] arr = new Type[,] { { typeof (TestType) } }; @@ -519,9 +511,9 @@ static void TestArrayResetGetElementOnByRefArray (int i = 0) static void TakesTypeByRef (ref Type type) { } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "")] // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), Tool.Trimmer | Tool.NativeAot, "")] static void TestArrayResetAfterCall () { Type[,] arr = new Type[,] { { typeof (TestType) } }; @@ -537,9 +529,9 @@ static void TestArrayResetAfterCall () static void TakesTypesArray (Type[,] types) { } // https://github.com/dotnet/linker/issues/2680 - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "")] // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), Tool.Trimmer | Tool.NativeAot, "")] static void TestArrayResetAfterAssignment () { Type[,] arr = new Type[,] { { typeof (TestType) } }; @@ -553,7 +545,7 @@ static void TestArrayResetAfterAssignment () arr[0, 0].RequiresPublicFields (); // Should warn } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "")] static void TestAddressOfElement () { Type[,] arr = new Type[,] { { typeof (TestType) } }; @@ -566,13 +558,10 @@ static void TestAddressOfElement () class WriteCapturedArrayElement { - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "")] // https://github.com/dotnet/linker/issues/2737 - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] static void TestNullCoalesce () { Type[] arr = new Type[1]; @@ -590,11 +579,9 @@ static void TestNullCoalescingAssignment () arr[0].RequiresAll (); } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "")] // https://github.com/dotnet/linker/issues/2746 - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] static void TestNullCoalescingAssignmentToEmpty () { Type[] arr = new Type[1]; @@ -604,10 +591,8 @@ static void TestNullCoalescingAssignmentToEmpty () [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll))] // https://github.com/dotnet/linker/issues/2746 (ILLink produces incomplete set of IL2072 warnings) - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "")] static void TestNullCoalescingAssignmentComplex () { Type[] arr = new Type[1]; @@ -702,7 +687,7 @@ static void TestNullCoalesce (bool b = false) arr2[0].RequiresPublicFields (); } - [ExpectedWarning ("IL2087", nameof (T), nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2087", [nameof (T), nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "")] [ExpectedWarning ("IL2087", nameof (U), nameof (DataFlowTypeExtensions.RequiresPublicFields))] // Missing warnings for 'V' possibly assigned to arr or arr2 because write to temp // array isn't reflected back in the local variables. https://github.com/dotnet/linker/issues/2158 @@ -710,8 +695,8 @@ static void TestNullCoalesce (bool b = false) // possible assignment of arr2 to arr, without overwriting index '0'. And it produces a warning // for each possible value, unlike ILLink/ILCompiler, which produce an unknown value for a merged // array value: https://github.com/dotnet/runtime/issues/93416 - [ExpectedWarning ("IL2087", nameof (U), nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2087", [nameof (U), nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] static void TestNullCoalescingAssignment (bool b = true) { Type[]? arr = new Type[1] { typeof (T) }; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AssemblyQualifiedNameDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AssemblyQualifiedNameDataflow.cs index f2c0f5185f5cf2..c6dbd60598c608 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AssemblyQualifiedNameDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AssemblyQualifiedNameDataflow.cs @@ -58,10 +58,7 @@ static void TestConstructors () RequireNothing (type); } - [ExpectedWarning ("IL2105", - "Type 'System.Invalid.TypeName' was not found in the caller assembly nor in the base library. " + - "Type name strings used for dynamically accessing a type should be assembly qualified.", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2105", "Type 'System.Invalid.TypeName' was not found in the caller assembly nor in the base library. " + "Type name strings used for dynamically accessing a type should be assembly qualified.", Tool.Trimmer | Tool.NativeAot, "")] static void TestUnqualifiedTypeNameWarns () { RequirePublicConstructors ("System.Invalid.TypeName"); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeConstructorDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeConstructorDataflow.cs index 4611e06773df85..5f54d6dd471262 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeConstructorDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeConstructorDataflow.cs @@ -9,7 +9,7 @@ [assembly: KeptAttributeAttribute (typeof (AttributeConstructorDataflow.KeepsPublicPropertiesAttribute))] // https://github.com/dotnet/linker/issues/2273 -[assembly: ExpectedWarning ("IL2026", "--ClassWithKeptPublicProperties--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] +[assembly: ExpectedWarning ("IL2026", "--ClassWithKeptPublicProperties--", Tool.Trimmer | Tool.NativeAot, "")] [assembly: AttributeConstructorDataflow.KeepsPublicProperties (typeof (AttributeConstructorDataflow.ClassWithKeptPublicProperties))] namespace Mono.Linker.Tests.Cases.DataFlow @@ -27,7 +27,7 @@ class AttributeConstructorDataflow [KeepsPublicFields (null, null)] [TypeArray (new Type[] { typeof (AttributeConstructorDataflow) })] // https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "")] public static void Main () { typeof (AttributeConstructorDataflow).GetMethod ("Main").GetCustomAttribute (typeof (KeepsPublicConstructorAttribute)); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeFieldDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeFieldDataflow.cs index e581797e234742..4807f7c039771d 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeFieldDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeFieldDataflow.cs @@ -41,7 +41,7 @@ public static void TestKeepsPublicMethods () [Kept] [KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))] // Trimmer/NativeAot only for now - https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "")] [KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributeFieldDataflow+ClassWithKeptPublicMethods")] public static void TestKeepsPublicMethodsString () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributePropertyDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributePropertyDataflow.cs index f953784dc37537..a6c254a00ab4c4 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributePropertyDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributePropertyDataflow.cs @@ -56,7 +56,7 @@ public static void TestKeepsPublicMethods () [Kept] [KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))] // Trimmer/NativeAot only for now - https://github.com/dotnet/runtime/issues/95118 - [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethodsKeptByName--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethodsKeptByName--", Tool.Trimmer | Tool.NativeAot, "")] [KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributesOnMethod+ClassWithKeptPublicMethodsKeptByName")] public static void TestKeepsPublicMethodsByName () { @@ -212,7 +212,7 @@ class AttributeWithConditionalExpression [Kept] [KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))] // Trimmer/NativeAot only for now - https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "")] [KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethods" : null)] public static void Test () { @@ -224,7 +224,7 @@ public static void Test () // where the owning symbol is not a method. [Kept] [KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))] - [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "")] [KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethods" : null)] public static int field; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ByRefDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ByRefDataflow.cs index d00af37b2bebb1..08cb41710cb151 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ByRefDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ByRefDataflow.cs @@ -46,12 +46,12 @@ public static void Main () [Kept] // Trimmer and analyzer use different formats for ref parameters: https://github.com/dotnet/linker/issues/2406 - [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(Type&)", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(ref Type)", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2069", nameof (s_typeWithPublicParameterlessConstructor), "parameter 'type'", nameof (MethodWithRefParameter), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(Type&)", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(ref Type)", Tool.Analyzer, "")] + [ExpectedWarning ("IL2069", [nameof (s_typeWithPublicParameterlessConstructor), "parameter 'type'", nameof (MethodWithRefParameter)], Tool.Trimmer | Tool.NativeAot, "")] // MethodWithRefParameter (ref x) - [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(Type&)", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(ref Type)", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(Type&)", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(ref Type)", Tool.Analyzer, "")] public static void PassRefToField () { MethodWithRefParameter (ref s_typeWithPublicParameterlessConstructor); @@ -61,8 +61,8 @@ public static void PassRefToField () [Kept] // Trimmer and analyzer use different formats for ref parameters: https://github.com/dotnet/linker/issues/2406 - [ExpectedWarning ("IL2067", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(Type&)", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2067", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(ref Type)", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2067", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(Type&)", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2067", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(ref Type)", Tool.Analyzer, "")] public static void PassRefToParameter (Type parameter) { MethodWithRefParameter (ref parameter); @@ -182,8 +182,8 @@ static void TwoOutRefs ( [Kept] // https://github.com/dotnet/runtime/issues/85464 - [ExpectedWarning ("IL2069", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2069", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "")] public static void Test () { TwoOutRefs (out _publicMethodsField, out _publicPropertiesField); @@ -243,13 +243,13 @@ static void TestLocalAssignment (bool b = true) } [Kept] - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", [nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", [nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", [nameof (GetTypeWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", [nameof (GetTypeWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "")] // ILLink/ILCompiler produce different warning code: https://github.com/dotnet/linker/issues/2737 - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "")] static void TestArrayElementReferenceAssignment (bool b = true) { var arr1 = new Type[] { GetUnknownType () }; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs index cb609bc5906025..17924d0f3a2437 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs @@ -39,10 +39,8 @@ public static IEnumerable BaseIteratorWithCorrectDataflow () } } - [ExpectedWarning ("IL2120", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2120", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2120", ["<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "MoveNext"], Tool.Trimmer, "")] + [ExpectedWarning ("IL2120", ["<" + nameof (BaseIteratorWithCorrectDataflow) + ">", ""], Tool.Trimmer, "")] [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] class IteratorStateMachines : BaseTypeWithIteratorStateMachines { @@ -52,22 +50,17 @@ public static IEnumerable IteratorWithoutDataflow () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", - ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", - ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL2119", "<" + nameof (IteratorCallsMethodWithRequires) + ">", "MoveNext", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2119", "<" + nameof (IteratorCallsMethodWithRequires) + ">", "MoveNext", Tool.Trimmer, "", CompilerGeneratedCode = true)] public static IEnumerable IteratorCallsMethodWithRequires () { yield return 0; MethodWithRequires (); } - [ExpectedWarning ("IL2119", "<" + nameof (IteratorWithCorrectDataflow) + ">", "MoveNext", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2119", "", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2119", "<" + nameof (IteratorWithCorrectDataflow) + ">", "MoveNext", Tool.Trimmer, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2119", "", Tool.Trimmer, "", CompilerGeneratedCode = true)] public static IEnumerable IteratorWithCorrectDataflow () { var t_IteratorWithCorrectDataflow = GetAll (); @@ -75,10 +68,8 @@ public static IEnumerable IteratorWithCorrectDataflow () t_IteratorWithCorrectDataflow.RequiresAll (); } - [ExpectedWarning ("IL2119", "<" + nameof (IteratorWithIntegerDataflow) + ">", "MoveNext", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2119", "", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2119", "<" + nameof (IteratorWithIntegerDataflow) + ">", "MoveNext", Tool.Trimmer, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2119", "", Tool.Trimmer, "", CompilerGeneratedCode = true)] public static IEnumerable IteratorWithIntegerDataflow () { int integerLocal = 0; @@ -87,10 +78,8 @@ public static IEnumerable IteratorWithIntegerDataflow () types[integerLocal].RequiresPublicMethods (); } - [ExpectedWarning ("IL2119", "<" + nameof (IteratorWithProblematicDataflow) + ">", "MoveNext", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2119", "", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2119", "<" + nameof (IteratorWithProblematicDataflow) + ">", "MoveNext", Tool.Trimmer, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2119", "", Tool.Trimmer, "", CompilerGeneratedCode = true)] [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true)] public static IEnumerable IteratorWithProblematicDataflow () { @@ -99,25 +88,22 @@ public static IEnumerable IteratorWithProblematicDataflow () t_IteratorWithProblematicDataflow.RequiresAll (); } - [ExpectedWarning ("IL2112", nameof (RUCTypeWithIterators) + "()", "--RUCTypeWithIterators--", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // warning about .ctor + [ExpectedWarning ("IL2112", nameof (RUCTypeWithIterators) + "()", "--RUCTypeWithIterators--", Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] // warning about .ctor [RequiresUnreferencedCode ("--RUCTypeWithIterators--")] class RUCTypeWithIterators { - [ExpectedWarning ("IL2112", nameof (StaticIteratorCallsMethodWithRequires) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2112", nameof (StaticIteratorCallsMethodWithRequires) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static IEnumerable StaticIteratorCallsMethodWithRequires () { yield return 0; MethodWithRequires (); } - [ExpectedWarning ("IL2112", nameof (InstanceIteratorCallsMethodWithRequires) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2112", nameof (InstanceIteratorCallsMethodWithRequires) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public IEnumerable InstanceIteratorCallsMethodWithRequires () { yield return 0; @@ -125,32 +111,23 @@ public IEnumerable InstanceIteratorCallsMethodWithRequires () } } - [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithProblematicDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (IteratorCallsMethodWithRequires) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithCorrectDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithIntegerDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithProblematicDataflow) + ">", "MoveNext", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (IteratorCallsMethodWithRequires) + ">", "MoveNext", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithCorrectDataflow) + ">", "MoveNext", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithIntegerDataflow) + ">", "MoveNext", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "MoveNext", Tool.Trimmer, "")] [ExpectedWarning ("IL2026", nameof (RUCTypeWithIterators) + "()", "--RUCTypeWithIterators--")] // Expect to see warnings about RUC on type, for all static state machine members. [ExpectedWarning ("IL2026", nameof (RUCTypeWithIterators.StaticIteratorCallsMethodWithRequires) + "()", "--RUCTypeWithIterators--")] [ExpectedWarning ("IL2026", nameof (RUCTypeWithIterators.InstanceIteratorCallsMethodWithRequires) + "()")] - [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithCorrectDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithProblematicDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithCorrectDataflow) + ">", "", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithProblematicDataflow) + ">", "", Tool.Trimmer, "")] // Technically the access to IteratorWithIntegerDataflow should warn about access to the integer // field integerLocal, but our heuristics only warn if the field type satisfies the // "IsTypeInterestingForDatafllow" check. This is likely good enough because in most cases the // compiler-generated code will have other hoisted fields with types that _are_ interesting for dataflow. - [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithIntegerDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithIntegerDataflow) + ">", "", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "", Tool.Trimmer, "")] public static void Test (IteratorStateMachines test = null) { typeof (IteratorStateMachines).RequiresAll (); @@ -166,8 +143,8 @@ public static async Task AsyncWithoutDataflow () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static async Task AsyncCallsMethodWithRequires () { MethodWithRequires (); @@ -186,16 +163,11 @@ public static async Task AsyncWithProblematicDataflow () t_AsyncWithProblematicDataflow.RequiresAll (); } - [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithProblematicDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncCallsMethodWithRequires) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithCorrectDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithCorrectDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithProblematicDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithProblematicDataflow) + ">", "MoveNext", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (AsyncCallsMethodWithRequires) + ">", "MoveNext", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithCorrectDataflow) + ">", "MoveNext", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithCorrectDataflow) + ">", "", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithProblematicDataflow) + ">", "", Tool.Trimmer, "")] public static void Test () { typeof (AsyncStateMachines).RequiresAll (); @@ -210,8 +182,8 @@ public static async IAsyncEnumerable AsyncIteratorWithoutDataflow () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static async IAsyncEnumerable AsyncIteratorCallsMethodWithRequires () { yield return await MethodAsync (); @@ -233,16 +205,11 @@ public static async IAsyncEnumerable AsyncIteratorWithProblematicDataflow ( t.RequiresAll (); } - [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithProblematicDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorCallsMethodWithRequires) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithCorrectDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithCorrectDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithProblematicDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithProblematicDataflow) + ">", "MoveNext", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorCallsMethodWithRequires) + ">", "MoveNext", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithCorrectDataflow) + ">", "MoveNext", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithCorrectDataflow) + ">", "", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithProblematicDataflow) + ">", "", Tool.Trimmer, "")] public static void Test () { typeof (AsyncIteratorStateMachines).RequiresAll (); @@ -262,10 +229,9 @@ static void LambdaCallsMethodWithRequires () { var lambda = [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL2119", "<" + nameof (LambdaCallsMethodWithRequires) + ">", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2119", "<" + nameof (LambdaCallsMethodWithRequires) + ">", Tool.Trimmer, "")] () => MethodWithRequires (); lambda (); } @@ -273,8 +239,7 @@ static void LambdaCallsMethodWithRequires () static void LambdaWithCorrectDataflow () { var lambda = - [ExpectedWarning ("IL2119", "<" + nameof (LambdaWithCorrectDataflow) + ">", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2119", "<" + nameof (LambdaWithCorrectDataflow) + ">", Tool.Trimmer, "")] () => { var t = GetAll (); t.RequiresAll (); @@ -295,8 +260,7 @@ static void LambdaWithCorrectParameter () static void LambdaWithProblematicDataflow () { var lambda = - [ExpectedWarning ("IL2119", "<" + nameof (LambdaWithProblematicDataflow) + ">", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2119", "<" + nameof (LambdaWithProblematicDataflow) + ">", Tool.Trimmer, "")] [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll))] () => { var t = GetWithPublicMethods (); @@ -309,8 +273,7 @@ static void LambdaWithCapturedTypeToDAM () { var t = GetWithPublicMethods (); var lambda = - [ExpectedWarning ("IL2119", "<" + nameof (LambdaWithCapturedTypeToDAM) + ">", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2119", "<" + nameof (LambdaWithCapturedTypeToDAM) + ">", Tool.Trimmer, "")] [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll))] () => { t.RequiresAll (); @@ -337,29 +300,27 @@ static void LambdaCallsPInvokeTakingObject () { var lambda = [ExpectedWarning ("IL2050")] - [ExpectedWarning ("IL2119", "<" + nameof (LambdaCallsPInvokeTakingObject) + ">", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2119", "<" + nameof (LambdaCallsPInvokeTakingObject) + ">", Tool.Trimmer, "")] () => MethodTakingObject (null); lambda (); } - [ExpectedWarning ("IL2112", nameof (RUCTypeWithLambdas) + "()", "--RUCTypeWithLambdas--", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", nameof (RUCTypeWithLambdas) + "()", "--RUCTypeWithLambdas--", Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] [RequiresUnreferencedCode ("--RUCTypeWithLambdas--")] class RUCTypeWithLambdas { - [ExpectedWarning ("IL2112", nameof (MethodWithLambdas), "--RUCTypeWithLambdas--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", [nameof (MethodWithLambdas), "--RUCTypeWithLambdas--"], Tool.Trimmer | Tool.NativeAot, "")] public void MethodWithLambdas () { var lambda = - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] () => MethodWithRequires (); int i = 0; var lambdaWithCapturedState = - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] () => { i++; MethodWithRequires (); @@ -370,16 +331,11 @@ public void MethodWithLambdas () } } - [ExpectedWarning ("IL2118", "<" + nameof (LambdaCallsPInvokeTakingObject) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (LambdaCallsMethodWithRequires) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithCorrectDataflow) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithProblematicDataflow) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithCapturedTypeToDAM) + ">", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", "<" + nameof (LambdaCallsPInvokeTakingObject) + ">", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (LambdaCallsMethodWithRequires) + ">", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithCorrectDataflow) + ">", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithProblematicDataflow) + ">", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithCapturedTypeToDAM) + ">", Tool.Trimmer, "")] [ExpectedWarning ("IL2026", nameof (RUCTypeWithLambdas) + "()", "--RUCTypeWithLambdas--")] [ExpectedWarning ("IL2026", nameof (RUCTypeWithLambdas.MethodWithLambdas) + "()", "--RUCTypeWithLambdas--")] public static void Test (Lambdas test = null) @@ -402,18 +358,16 @@ static void LocalFunctionWithoutDataflow () static void LocalFunctionCallsMethodWithRequires () { [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionCallsMethodWithRequires) + ">", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionCallsMethodWithRequires) + ">", Tool.Trimmer, "")] void LocalFunction () => MethodWithRequires (); LocalFunction (); } static void LocalFunctionWithCorrectDataflow () { - [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionWithCorrectDataflow) + ">", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionWithCorrectDataflow) + ">", Tool.Trimmer, "")] void LocalFunction () { var t = GetAll (); @@ -425,8 +379,7 @@ void LocalFunction () static void LocalFunctionWithProblematicDataflow () { [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll))] - [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionWithProblematicDataflow) + ">", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionWithProblematicDataflow) + ">", Tool.Trimmer, "")] void LocalFunction () { var t = GetWithPublicMethods (); @@ -438,8 +391,7 @@ void LocalFunction () static void LocalFunctionWithCapturedTypeToDAM () { var t = GetAll (); - [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionWithCapturedTypeToDAM) + ">", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionWithCapturedTypeToDAM) + ">", Tool.Trimmer, "")] void LocalFunction () { t.RequiresAll (); @@ -464,32 +416,29 @@ static void LocalFunctionCallsPInvokeTakingPrimitiveType () static void LocalFunctionCallsPInvokeTakingObject () { [ExpectedWarning ("IL2050")] - [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionCallsPInvokeTakingObject) + ">", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionCallsPInvokeTakingObject) + ">", Tool.Trimmer, "")] void LocalFunction () => MethodTakingObject (null); LocalFunction (); } - [ExpectedWarning ("IL2112", nameof (RUCTypeWithLocalFunctions) + "()", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", nameof (RUCTypeWithLocalFunctions) + "()", Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] [RequiresUnreferencedCode ("--RUCTypeWithLocalFunctions--")] class RUCTypeWithLocalFunctions { - [ExpectedWarning ("IL2112", nameof (MethodWithLocalFunctions), "--RUCTypeWithLocalFunctions--", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", nameof (MethodWithLocalFunctions), "--RUCTypeWithLocalFunctions--", Tool.Trimmer | Tool.NativeAot, "")] public void MethodWithLocalFunctions () { - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] void LocalFunction () => MethodWithRequires (); - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void StaticLocalFunction () => MethodWithRequires (); int i = 0; - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] void LocalFunctionWithCapturedState () { i++; @@ -502,16 +451,11 @@ void LocalFunctionWithCapturedState () } } - [ExpectedWarning ("IL2118", nameof (LocalFunctionCallsPInvokeTakingObject), - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", nameof (LocalFunctionCallsMethodWithRequires), - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", nameof (LocalFunctionWithCorrectDataflow), - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", nameof (LocalFunctionWithProblematicDataflow), - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", nameof (LocalFunctionWithCapturedTypeToDAM), - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", nameof (LocalFunctionCallsPInvokeTakingObject), Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", nameof (LocalFunctionCallsMethodWithRequires), Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", nameof (LocalFunctionWithCorrectDataflow), Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", nameof (LocalFunctionWithProblematicDataflow), Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", nameof (LocalFunctionWithCapturedTypeToDAM), Tool.Trimmer, "")] // Expect RUC warnings for static, compiler-generated code warnings for instance. [ExpectedWarning ("IL2026", nameof (RUCTypeWithLocalFunctions) + "()", "--RUCTypeWithLocalFunctions--")] [ExpectedWarning ("IL2026", nameof (RUCTypeWithLocalFunctions.MethodWithLocalFunctions) + "()")] @@ -648,7 +592,7 @@ static void TestLocalFunctionThroughDelegate () Action a = LocalFunction; a (null); - void LocalFunction ([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type) + void LocalFunction ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { } } @@ -658,7 +602,7 @@ static void TestGenericLocalFunctionThroughDelegate () Action a = LocalFunction; a (); - void LocalFunction <[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () + void LocalFunction<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { } } @@ -685,10 +629,10 @@ static void Lambda () a (typeof (string)); } - static void LambdaOnGeneric<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T> () + static void LambdaOnGeneric<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { Action a = () => { - typeof(T).GetMethods (); + typeof (T).GetMethods (); }; a (); @@ -698,23 +642,23 @@ static void LocalFunction () { LocalFunctionInner (typeof (string)); - static void LocalFunctionInner ([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type) + static void LocalFunctionInner ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { type.GetMethods (); } } - static void LocalFunctionOnGeneric<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() + static void LocalFunctionOnGeneric<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { LocalFunctionInner (); static void LocalFunctionInner () { - typeof(T).GetMethods (); + typeof (T).GetMethods (); } } - static IEnumerable IteratorOnGeneric<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() + static IEnumerable IteratorOnGeneric<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { yield return 0; } @@ -730,8 +674,8 @@ static void LocalFunctionInner () await Task.Delay (100); } - [ExpectedWarning ("IL2118", "<" + nameof (LambdaOnGeneric) + ">", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (LocalFunctionOnGeneric) + ">", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", "<" + nameof (LambdaOnGeneric) + ">", Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", "<" + nameof (LocalFunctionOnGeneric) + ">", Tool.Trimmer, "")] public static void Test () { typeof (DAMReflectionAccessToCompilerGeneratedCode).RequiresAll (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs index bae9341ecde8bf..e0bb05872b8445 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs @@ -38,10 +38,8 @@ static IEnumerable FlowAcrossYieldReturn () } // Trimmer tracks all assignments of hoisted locals, so this produces warnings. - [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresPublicFields), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresPublicMethods), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2072", [nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresPublicMethods)], Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static IEnumerable NoFlowAcrossYieldReturn () { Type t = GetWithPublicMethods (); @@ -227,10 +225,8 @@ static async void FlowAcrossAwait () } // Trimmer tracks all assignments of hoisted locals, so this produces warnings. - [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresPublicFields), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresPublicMethods), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async void NoFlowAcrossAwait () { Type t = GetWithPublicMethods (); @@ -447,7 +443,7 @@ public static void ReadCapturedParameterAfterWrite (Type tParameter = null) void LocalFunction () => tParameter.RequiresPublicMethods (); } - [ExpectedWarning ("IL2072", "tParameter", nameof (GetWithPublicFields), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", ["tParameter", nameof (GetWithPublicFields)], Tool.Analyzer, "")] public static void ReadCapturedParameterAfterWriteMismatch ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type tParameter = null) { tParameter = GetWithPublicFields (); @@ -576,7 +572,7 @@ public static void ReadCapturedParameterAfterWrite (Type tParameter = null) lambda (); } - [ExpectedWarning ("IL2072", "tParameter", nameof (GetWithPublicFields), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", ["tParameter", nameof (GetWithPublicFields)], Tool.Analyzer, "")] public static void ReadCapturedParameterAfterWriteMismatch ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type tParameter = null) { tParameter = GetWithPublicFields (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.cs index 2cd0f49317f17b..83ae5834cdc96b 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.cs @@ -42,7 +42,7 @@ public static void WithLocalFunctionInner () // Analyzer doesn't implement constant propagation and branch removal, so it reaches this code // NativeAOT behavioral difference: // https://github.com/dotnet/runtime/issues/85161 - [ExpectedWarning ("IL2026", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Analyzer | Tool.NativeAot, "")] void LocalWithWarning () { // No warning @@ -64,7 +64,7 @@ public static void WithLocalFunction () // Analyzer doesn't implement constant propagation and branch removal, so it reaches this code // NativeAOT behavioral difference: // https://github.com/dotnet/runtime/issues/85161 - [ExpectedWarning ("IL2026", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Analyzer | Tool.NativeAot, "")] void LocalWithWarning () { Requires (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssemblyWithWarning.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssemblyWithWarning.cs index 2023c19aaa85b1..58af92cb3e179b 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssemblyWithWarning.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssemblyWithWarning.cs @@ -38,7 +38,7 @@ public static void WithLocalFunctionInner () } // https://github.com/dotnet/linker/issues/2937 - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] void LocalWithWarning () { // Warning! @@ -55,7 +55,7 @@ public static void WithLocalFunction () } // https://github.com/dotnet/linker/issues/2937 - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] void LocalWithWarning () { // No warning diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ComplexTypeHandling.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ComplexTypeHandling.cs index ad29941cae2ce8..36d22c3ff904c2 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ComplexTypeHandling.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ComplexTypeHandling.cs @@ -151,7 +151,7 @@ public ArrayCreateInstanceByNameElement () } [Kept] - [ExpectedWarning ("IL2032", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/82447 + [ExpectedWarning ("IL2032", Tool.NativeAot, "")] // https://github.com/dotnet/runtime/issues/82447 static void TestArrayCreateInstanceByName () { Activator.CreateInstance ("test", "Mono.Linker.Tests.Cases.DataFlow.ComplexTypeHandling+ArrayCreateInstanceByNameElement[]"); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructedTypesDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructedTypesDataFlow.cs index abeed77e1bc0ed..d2dbbc2f416977 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructedTypesDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructedTypesDataFlow.cs @@ -21,7 +21,7 @@ public static void Main () class DeconstructedVariable { // https://github.com/dotnet/linker/issues/3158 - [ExpectedWarning ("IL2077", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2077", Tool.Trimmer | Tool.NativeAot, "")] static void DeconstructVariableNoAnnotation ((Type type, object instance) input) { var (type, instance) = input; @@ -31,7 +31,7 @@ static void DeconstructVariableNoAnnotation ((Type type, object instance) input) static (Type type, object instance) GetInput (int unused) => (typeof (string), null); // https://github.com/dotnet/linker/issues/3158 - [ExpectedWarning ("IL2077", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2077", Tool.Trimmer | Tool.NativeAot, "")] static void DeconstructVariableFlowCapture (bool b = true) { // This creates a control-flow graph where the tuple elements assigned to @@ -51,8 +51,8 @@ static void DeconstructVariableFlowCapture (bool b = true) static ref Type AnnotatedProperty => ref annotatedfield; // https://github.com/dotnet/linker/issues/3158 - [ExpectedWarning ("IL2062", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2078", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2078", Tool.Trimmer | Tool.NativeAot, "")] static void DeconstructVariablePropertyReference ((Type type, object instance) input) { object instance; @@ -72,7 +72,7 @@ record TypeAndInstance ( // For analyzer, this is currently // https://github.com/dotnet/linker/issues/3158 // But it's possible that with that fixed there won't be a warning from the analyzer anyway (depends on the implementation) - [ExpectedWarning ("IL2067", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2067", Tool.Trimmer | Tool.NativeAot, "")] static void DeconstructRecordWithAnnotation (TypeAndInstance value) { var (type, instance) = value; @@ -119,7 +119,7 @@ static void DeconstructRecordManualWithAnnotation (TypeAndInstanceRecordManual v } // https://github.com/dotnet/linker/issues/3158 - [ExpectedWarning ("IL2067", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2067", Tool.Trimmer | Tool.NativeAot, "")] static void DeconstructRecordManualWithMismatchAnnotation (TypeAndInstanceRecordManual value) { var (type, instance) = value; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructorDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructorDataFlow.cs index fe0d1af1f62c7c..f1a3788aaa11bd 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructorDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructorDataFlow.cs @@ -39,13 +39,11 @@ public DataFlowInConstructor () [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type annotatedField = GetUnknown (); - [ExpectedWarning ("IL2074", nameof (GetUnknown), nameof (AnnotatedProperty), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/93277 + [ExpectedWarning ("IL2074", nameof (GetUnknown), nameof (AnnotatedProperty), Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] // https://github.com/dotnet/runtime/issues/93277 [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type AnnotatedProperty { get; } = GetUnknown (); - [ExpectedWarning ("IL2074", nameof (GetUnknown), nameof (AnnotatedPropertyWithSetter), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/93277 + [ExpectedWarning ("IL2074", nameof (GetUnknown), nameof (AnnotatedPropertyWithSetter), Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] // https://github.com/dotnet/runtime/issues/93277 [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type AnnotatedPropertyWithSetter { get; set; } = GetUnknown (); @@ -81,12 +79,10 @@ public DataFlowInConstructor () int PropertyWithThrowStatementInInitializer { get; } = string.Empty.Length == 0 ? throw new Exception() : 0; - [ExpectedWarning ("IL2067", nameof (TryGetUnknown), nameof (RequireAll), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // https://github.com/dotnet/linker/issues/2158 + [ExpectedWarning ("IL2067", nameof (TryGetUnknown), nameof (RequireAll), Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] // https://github.com/dotnet/linker/issues/2158 int fieldWithLocalReferenceInInitializer = TryGetUnknown (out var type) ? RequireAll (type) : 0; - [ExpectedWarning ("IL2067", nameof (TryGetUnknown), nameof (RequireAll), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // https://github.com/dotnet/linker/issues/2158 + [ExpectedWarning ("IL2067", nameof (TryGetUnknown), nameof (RequireAll), Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] // https://github.com/dotnet/linker/issues/2158 int PropertyWithLocalReferenceInInitializer { get; } = TryGetUnknown (out var type) ? RequireAll (type) : 0; public static void Test () diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/DynamicObjects.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/DynamicObjects.cs index d048bec91e5d29..01a5ecb9cb3657 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/DynamicObjects.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/DynamicObjects.cs @@ -29,7 +29,7 @@ public static void Main () class InvocationOnDynamicType { [ExpectedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] // https://github.com/dotnet/runtime/issues/94427 static void DynamicArgument () { dynamic dynamicObject = "Some string"; @@ -48,15 +48,15 @@ static void MethodWithDynamicParameterDoNothing (dynamic arg) } [ExpectedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] // https://github.com/dotnet/runtime/issues/94427 static void MethodWithDynamicParameter (dynamic arg) { arg.MethodWithDynamicParameter (arg); } // Roslyn codegen no longer produces a call to Binder.InvokeConstructor. - // [ExpectedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.InvokeConstructor")] - // [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + // [ExpectedSharedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.InvokeConstructor")] + // [ExpectedWarning ("IL3050", Tool.NativeAot, "")] // https://github.com/dotnet/runtime/issues/94427 // static void ObjectCreationDynamicArgument () // { // dynamic dynamicObject = "Some string"; @@ -81,14 +81,14 @@ public static void Test () class DynamicMemberReference { [ExpectedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.GetMember")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] // https://github.com/dotnet/runtime/issues/94427 static void Read (dynamic d) { var x = d.Member; } [ExpectedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.SetMember")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] // https://github.com/dotnet/runtime/issues/94427 static void Write (dynamic d) { d.Member = 0; @@ -104,14 +104,14 @@ public static void Test () class DynamicIndexerAccess { [ExpectedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.GetIndex")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] // https://github.com/dotnet/runtime/issues/94427 static void Read (dynamic d) { var x = d[0]; } [ExpectedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.SetIndex")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] // https://github.com/dotnet/runtime/issues/94427 static void Write (dynamic d) { d[0] = 0; @@ -129,7 +129,7 @@ class DynamicInRequiresUnreferencedCodeClass [RequiresUnreferencedCode("message")] class ClassWithRequires { - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] // https://github.com/dotnet/runtime/issues/94427 public static void MethodWithDynamicArg (dynamic arg) { arg.DynamicInvocation (); @@ -154,7 +154,7 @@ static void MethodWithRequires () } [ExpectedWarning ("IL2026", nameof (MethodWithRequires))] - [ExpectedWarning ("IL3050", nameof (MethodWithRequires), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (MethodWithRequires), Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { MethodWithRequires (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExceptionalDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExceptionalDataFlow.cs index beaf3237c7c4d3..8cc5bf9b6c1a7e 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExceptionalDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExceptionalDataFlow.cs @@ -46,10 +46,8 @@ public static void Main () ExceptionFilterWithException (); } - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void TryFlowsToFinally () { @@ -109,12 +107,9 @@ public static void MultipleTryExits () // On each path, only one state is possible, but we conservatively merge the (non-exceptional) // finally states for each path and expect the warnings to reflect this merged state. [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicEvents) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicEvents) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] @@ -124,12 +119,9 @@ public static void MultipleTryExits () [ExpectedWarning ("IL2073", nameof (MultipleFinallyPaths) + "()", nameof (GetWithPublicEvents) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2073", nameof (MultipleFinallyPaths) + "()", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2073", nameof (MultipleFinallyPaths) + "()", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2073", nameof (MultipleFinallyPaths) + "()", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2073", nameof (MultipleFinallyPaths) + "()", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2073", nameof (MultipleFinallyPaths) + "()", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2073", nameof (MultipleFinallyPaths) + "()", nameof (GetWithPublicProperties) + "()", Tool.Trimmer | Tool.NativeAot, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] public static Type MultipleFinallyPaths () { @@ -160,14 +152,11 @@ public static Type MultipleFinallyPaths () throw new Exception (); } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void FinallyChain () { @@ -184,16 +173,12 @@ public static void FinallyChain () } } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] - + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicProperties) + "()")] @@ -218,10 +203,8 @@ public static void FinallyChainWithPostFinallyState () RequireAll4 (t); } - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void TryFlowsToCatch () { @@ -235,10 +218,8 @@ public static void TryFlowsToCatch () } } - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void CatchFlowsToFinally () { @@ -253,8 +234,7 @@ public static void CatchFlowsToFinally () } } - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void CatchFlowsToAfterTry () { @@ -268,8 +248,7 @@ public static void CatchFlowsToAfterTry () RequireAll (t); } - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void CatchFlowsToAfterFinally () { @@ -303,20 +282,17 @@ public class Exception2 : Exception { } [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicFields) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll5) + "(Type)", nameof (GetWithPublicEvents) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll6) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll6) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll6) + "(Type)", nameof (GetWithPublicFields) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll6) + "(Type)", nameof (GetWithPublicProperties) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll6) + "(Type)", nameof (GetWithPublicEvents) + "()")] @@ -326,26 +302,16 @@ public class Exception2 : Exception { } [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicConstructors) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll5) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll5) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll7) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll7) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll7) + "(Type)", nameof (GetWithPublicEvents) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicEvents) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll5) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll5) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll7) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll7) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll7) + "(Type)", nameof (GetWithPublicEvents) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicEvents) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void TryFlowsToMultipleCatchAndFinally () { @@ -370,20 +336,15 @@ public static void TryFlowsToMultipleCatchAndFinally () } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicConstructors) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicEvents) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicEvents) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicConstructors) + "()")] public static void NestedWithFinally () @@ -408,17 +369,14 @@ public static void NestedWithFinally () } } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicEvents) + "()")] @@ -446,22 +404,16 @@ public static void ControlFlowsOutOfMultipleFinally () } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicConstructors) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicEvents) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicEvents) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicConstructors) + "()")] public static void NestedWithCatch () @@ -488,8 +440,7 @@ public static void NestedWithCatch () [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void CatchInTry () { try { @@ -510,11 +461,10 @@ public static void CatchInTry () [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] // The bug was producing this warning: - // [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicConstructors) + "()")] + // [ExpectedSharedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicConstructors) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void CatchInTryWithFinally () { Type t = GetWithPublicConstructors (); @@ -540,12 +490,10 @@ public static void CatchInTryWithFinally () } } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicConstructors) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicConstructors) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicConstructors) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicConstructors) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] static void CatchInFinally () { @@ -565,8 +513,7 @@ static void CatchInFinally () { [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void TestCatchesHaveSeparateState () { Type t = GetWithPublicMethods (); @@ -581,8 +528,7 @@ public static void TestCatchesHaveSeparateState () } [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] public static void FinallyWithBranchToFirstBlock () { Type t = GetWithPublicMethods (); @@ -596,8 +542,7 @@ public static void FinallyWithBranchToFirstBlock () } [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] public static void FinallyWithBranchToFirstBlockAndEnclosingTryCatchState () { try { @@ -619,8 +564,7 @@ public static void FinallyWithBranchToFirstBlockAndEnclosingTryCatchState () } [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] public static void CatchWithBranchToFirstBlock () { Type t = GetWithPublicMethods (); @@ -634,8 +578,7 @@ public static void CatchWithBranchToFirstBlock () } [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] public static void CatchWithBranchToFirstBlockAndReassignment () { Type t = GetWithPublicMethods (); @@ -651,10 +594,8 @@ public static void CatchWithBranchToFirstBlockAndReassignment () [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void CatchWithNonSimplePredecessor () { @@ -676,10 +617,8 @@ public static void CatchWithNonSimplePredecessor () [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void FinallyWithNonSimplePredecessor () { @@ -701,10 +640,8 @@ public static void FinallyWithNonSimplePredecessor () [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void FinallyInTryWithPredecessor () { @@ -724,20 +661,17 @@ public static void FinallyInTryWithPredecessor () } } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void NestedFinally () { Type t = GetWithPublicMethods (); @@ -760,10 +694,8 @@ public static void NestedFinally () [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicFields) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void ChangeInFinallyNestedInFinally () { Type t = GetWithPublicMethods (); @@ -780,20 +712,17 @@ public static void ChangeInFinallyNestedInFinally () RequireAll4 (t); // fields only } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void NestedFinallyWithPredecessor () { Type t = GetWithPublicMethods (); @@ -811,11 +740,9 @@ public static void NestedFinallyWithPredecessor () } } - [ExpectedWarning ("IL2072", nameof (RequireAllTrue) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAllTrue) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAllTrue) + "(Type)", nameof (GetWithPublicFields) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()")] public static void ExceptionFilter () { @@ -833,8 +760,7 @@ public static void ExceptionFilter () [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void ExceptionFilterStateChange () { Type t = GetWithPublicMethods (); @@ -872,12 +798,9 @@ public static void ExceptionFilterStateChange () [ExpectedWarning ("IL2072", nameof (RequireAll6) + "(Type)", nameof (GetWithPublicProperties) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void ExceptionMultipleFilters () { Type t = GetWithPublicMethods (); @@ -908,8 +831,7 @@ public static void ExceptionMultipleFilters () [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties))] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods), Tool.Trimmer | Tool.NativeAot, "")] public static void ExceptionFilterWithBranch () { Type t = GetWithPublicMethods (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExponentialDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExponentialDataFlow.cs index 2f749beae0f813..a7715c507f2a32 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExponentialDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExponentialDataFlow.cs @@ -58,7 +58,7 @@ class GenericTypeWithRequires<[DynamicallyAccessedMembers (DynamicallyAccessedMe { } - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", Tool.Analyzer, "")] [ExpectedWarning ("IL2090", "'T'")] public static void Test () { @@ -94,32 +94,32 @@ class GenericTypeWithRequires< { } - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] // The way we track arrays causes the analyzer to track exponentially many // ArrayValues in the ValueSet for the pattern in this method, hitting the limit. // When this happens, we replace the ValueSet with an unknown value, producing // this warning. - [ExpectedWarning ("IL2055", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2055", Tool.Analyzer, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] public static void Test () { Type[] types = new Type[20] { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureCheckDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureCheckDataFlow.cs index 8c8c3baf5ab5c6..ab94f5052d4294 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureCheckDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureCheckDataFlow.cs @@ -40,8 +40,8 @@ public static void Main () class CallFeatureUnguarded { [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer | Tool.NativeAot, "")] static void Unguarded () { RequiresUnreferencedCode (); @@ -50,8 +50,8 @@ static void Unguarded () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer | Tool.NativeAot, "")] static void UnguardedIf () { if (!TestFeatures.IsUnreferencedCodeSupported) { @@ -62,8 +62,8 @@ static void UnguardedIf () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer | Tool.NativeAot, "")] static void UnguardedElse () { if (TestFeatures.IsUnreferencedCodeSupported) @@ -99,8 +99,8 @@ static void UnguardedTernary () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer | Tool.NativeAot, "")] static void UnguardedThrow () { if (TestFeatures.IsUnreferencedCodeSupported) @@ -114,8 +114,8 @@ static void UnguardedThrow () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer | Tool.NativeAot, "")] static void UnguardedReturn () { if (TestFeatures.IsUnreferencedCodeSupported) @@ -205,8 +205,8 @@ public static void Test () GuardedDoesNotReturnIfFalseCtor (); } - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer, "")] static void GuardedIf () { if (TestFeatures.IsUnreferencedCodeSupported) { @@ -216,8 +216,8 @@ static void GuardedIf () } } - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer, "")] static void GuardedElse () { if (!TestFeatures.IsUnreferencedCodeSupported) @@ -248,8 +248,8 @@ static void GuardedTernary () var b = !TestFeatures.IsUnreferencedCodeSupported ? true : RequiresUnreferencedCodeBool (); } - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer, "")] static void GuardedThrow () { if (!TestFeatures.IsUnreferencedCodeSupported) @@ -262,8 +262,8 @@ static void GuardedThrow () RequiresAssemblyFiles (); } - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer, "")] static void GuardedReturn () { if (!TestFeatures.IsUnreferencedCodeSupported) @@ -277,7 +277,7 @@ static void GuardedReturn () } // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] static void GuardedAssert () { Debug.Assert (TestFeatures.IsUnreferencedCodeSupported); @@ -286,7 +286,7 @@ static void GuardedAssert () } // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] static void GuardedDoesNotReturnIfTrue () { DoesNotReturnIfTrue (!TestFeatures.IsUnreferencedCodeSupported); @@ -295,7 +295,7 @@ static void GuardedDoesNotReturnIfTrue () } // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] static void GuardedDoesNotReturnIfFalse () { DoesNotReturnIfFalse (TestFeatures.IsUnreferencedCodeSupported); @@ -304,7 +304,7 @@ static void GuardedDoesNotReturnIfFalse () } // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] static void GuardedDoesNotReturn () { if (!TestFeatures.IsUnreferencedCodeSupported) @@ -314,7 +314,7 @@ static void GuardedDoesNotReturn () } // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] static void GuardedDoesNotReturnIfFalseCtor () { new DoesNotReturnIfFalseCtor (TestFeatures.IsUnreferencedCodeSupported); @@ -326,8 +326,8 @@ static void GuardedDoesNotReturnIfFalseCtor () class FeatureCheckBooleanExpressions { // Trimmer/NativeAot aren't able to optimize away the branch in this case. - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.NativeAot, "")] static void And () { if (TestFeatures.IsUnreferencedCodeSupported && RuntimeFeature.IsDynamicCodeSupported) { @@ -337,7 +337,7 @@ static void And () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] static void AndNot () { if (!TestFeatures.IsUnreferencedCodeSupported && !RuntimeFeature.IsDynamicCodeSupported) @@ -348,8 +348,8 @@ static void AndNot () } // Trimmer/NativeAot aren't able to optimize away the branch in this case. - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.NativeAot, "")] static void NotAnd () { if (!(TestFeatures.IsUnreferencedCodeSupported && RuntimeFeature.IsDynamicCodeSupported)) @@ -360,7 +360,7 @@ static void NotAnd () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] static void Or () { if (TestFeatures.IsUnreferencedCodeSupported || RuntimeFeature.IsDynamicCodeSupported) { @@ -370,8 +370,8 @@ static void Or () } // Trimmer/NativeAot aren't able to optimize away the branch in this case. - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.NativeAot, "")] static void OrNot () { if (!TestFeatures.IsUnreferencedCodeSupported || !RuntimeFeature.IsDynamicCodeSupported) @@ -382,7 +382,7 @@ static void OrNot () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] static void NotOr () { if (!(TestFeatures.IsUnreferencedCodeSupported || RuntimeFeature.IsDynamicCodeSupported)) @@ -477,7 +477,7 @@ static void IsNotFalse () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] static void Contradiction () { if (TestFeatures.IsUnreferencedCodeSupported && !TestFeatures.IsUnreferencedCodeSupported) { @@ -532,7 +532,7 @@ static void CallTestDynamicCodeGuarded () RequiresDynamicCode (); } - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] static void CallTestDynamicCodeUnguarded () { RequiresDynamicCode (); @@ -545,7 +545,7 @@ static void CallTestAssemblyFilesGuarded () } } - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer | Tool.NativeAot, "")] static void CallTestAssemblyFilesUnguarded () { RequiresAssemblyFiles (); @@ -564,9 +564,9 @@ public static void Test () class FeatureCheckCombinations { - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer, "")] // Trimmer warns because IsDynamicCodeSupported is not a constant, so the call is reachable. - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Analyzer | Tool.Trimmer)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Analyzer | Tool.Trimmer, "")] static void MeetFeaturesEmptyIntersection (bool b = true) { if (b) { @@ -582,7 +582,7 @@ static void MeetFeaturesEmptyIntersection (bool b = true) // Shows that ILLink has the same branch removal as NativeAot for this pattern, when // the branches both use a feature check that's substituted by ILLink. - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer, "")] static void MeetFeaturesEmptyIntersection_IdenticalBranches (bool b = true) { if (b) { @@ -596,7 +596,7 @@ static void MeetFeaturesEmptyIntersection_IdenticalBranches (bool b = true) RequiresDynamicCode (); } - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer, "")] static void MeetFeaturesIntersection (bool b = true) { if (b) { @@ -622,7 +622,7 @@ static void IntroduceFeature () } } - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer, "")] static void RemoveFeature () { if (TestFeatures.IsUnreferencedCodeSupported) { @@ -787,7 +787,7 @@ static void NestedTryInCheckInFinally () [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInTryNoCatch () { try { Debug.Assert (TestFeatures.IsUnreferencedCodeSupported); @@ -828,7 +828,7 @@ static void AssertInCatch () { [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1))] // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInFinally () { try { RequiresUnreferencedCode0 (); @@ -843,8 +843,8 @@ static void AssertInFinally () { [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2))] // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInTryNestedInTry () { try { @@ -885,8 +885,8 @@ static void AssertInTryWithCatchNestedInTry () [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1))] // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInTryNestedInFinally () { try { @@ -925,8 +925,8 @@ static void AssertInTryWithCatchNestedInFinally () [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2))] // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInFinallyNestedInTry () { try { try { @@ -944,8 +944,8 @@ static void AssertInFinallyNestedInTry () { [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2))] // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInFinallyWithCatchNestedInTry () { try { try { @@ -965,8 +965,8 @@ static void AssertInFinallyWithCatchNestedInTry () { [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1))] // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInFinallyNestedInFinally () { try { @@ -985,8 +985,8 @@ static void AssertInFinallyNestedInFinally () [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1))] // Trimmer/NativeAot doesn't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInFinallyWithCatchNestedInFinally () { try { @@ -1056,8 +1056,7 @@ static IEnumerable GuardInIterator () } } - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer, - CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer, "", CompilerGeneratedCode = true)] static IEnumerable StateFlowsAcrossYield () { if (!TestFeatures.IsUnreferencedCodeSupported) @@ -1076,8 +1075,7 @@ static async Task GuardInAsync () } } - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot, - CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async Task StateFlowsAcrossAwait () { if (!TestFeatures.IsUnreferencedCodeSupported) @@ -1097,8 +1095,7 @@ static async IAsyncEnumerable GuardInAsyncIterator () } } - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot, - CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async IAsyncEnumerable StateFlowsAcrossAwaitAndYield () { if (!TestFeatures.IsUnreferencedCodeSupported) diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureGuardAttributeDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureGuardAttributeDataFlow.cs index f4daacec7a0e1d..6b0e605ac7730d 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureGuardAttributeDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureGuardAttributeDataFlow.cs @@ -65,7 +65,7 @@ static void TestIndirectGuard () // // The analyzer doesn't do constant propagation of the boolean, so it doesn't know that // the return value is always false when TestFeatures.IsUnreferencedCodeSupported is false. - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool AndGuard => TestFeatures.IsUnreferencedCodeSupported && OtherCondition (); @@ -138,7 +138,7 @@ static void TestIsNotFalseGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool IfReturnTrueGuard { get { @@ -148,7 +148,7 @@ static bool IfReturnTrueGuard { } } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool ElseReturnTrueGuard { get { @@ -199,7 +199,7 @@ static void TestAssertNotReturnFalseGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool AssertReturnTrueGuard { get { @@ -229,7 +229,7 @@ static void TestThrowGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool TernaryIfGuard => TestFeatures.IsUnreferencedCodeSupported ? true : false; @@ -239,7 +239,7 @@ static void TestTernaryIfGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool TernaryElseGuard => !TestFeatures.IsUnreferencedCodeSupported ? false : true; @@ -275,7 +275,7 @@ public static void Test () } class InvalidGuardBodies { - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool ReturnTrueGuard => true; @@ -285,7 +285,7 @@ static void TestReturnTrueGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool OtherConditionGuard => OtherCondition (); @@ -295,7 +295,7 @@ static void TestOtherConditionGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool OrGuard => TestFeatures.IsUnreferencedCodeSupported || OtherCondition (); @@ -305,7 +305,7 @@ static void TestOrGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool NotGuard => !TestFeatures.IsUnreferencedCodeSupported; @@ -315,7 +315,7 @@ static void TestNotGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool EqualsFalseGuard => TestFeatures.IsUnreferencedCodeSupported == false; @@ -325,7 +325,7 @@ static void TestEqualsFalseGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool FalseEqualsGuard => false == TestFeatures.IsUnreferencedCodeSupported; @@ -335,7 +335,7 @@ static void TestFalseEqualsGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool NotEqualsTrueGuard => TestFeatures.IsUnreferencedCodeSupported != true; @@ -345,7 +345,7 @@ static void TestNotEqualsTrueGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool TrueNotEqualsGuard => true != TestFeatures.IsUnreferencedCodeSupported; @@ -355,7 +355,7 @@ static void TestTrueNotEqualsGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool IsNotTrueGuard => TestFeatures.IsUnreferencedCodeSupported is not true; @@ -365,7 +365,7 @@ static void TestIsNotTrueGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool IsFalseGuard => TestFeatures.IsUnreferencedCodeSupported is false; @@ -375,7 +375,7 @@ static void TestIsFalseGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool IfReturnFalseGuard { get { @@ -391,7 +391,7 @@ static void TestIfReturnFalseGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool ElseReturnFalseGuard { get { @@ -408,7 +408,7 @@ static void TestElseReturnFalseGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool AssertNotReturnTrueGuard { get { @@ -443,7 +443,7 @@ public static void Test () } class InvalidFeatureGuards { - [ExpectedWarning ("IL4001", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4001", Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static int NonBooleanProperty => 0; @@ -454,7 +454,7 @@ static void TestNonBooleanProperty () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4001", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4001", Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] bool NonStaticProperty => true; @@ -476,7 +476,7 @@ static void TestSetOnlyProperty () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4001", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4001", Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool GetAndSetProperty { get => true; set => throw null; } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs index 26e880378057a3..46f9e9844c3564 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs @@ -230,24 +230,21 @@ class AccessReturnedInstanceField static AccessReturnedInstanceField GetInstance ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type unused) => null; - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (GetInstance), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // https://github.com/dotnet/linker/issues/2832 + [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (GetInstance), Tool.Trimmer | Tool.NativeAot, "")] // https://github.com/dotnet/linker/issues/2832 [ExpectedWarning ("IL2077", nameof (field), nameof (DataFlowTypeExtensions.RequiresAll))] static void TestRead () { GetInstance (GetUnknownType ()).field.RequiresAll (); } - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (GetInstance), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // https://github.com/dotnet/linker/issues/2832 + [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (GetInstance), Tool.Trimmer | Tool.NativeAot, "")] // https://github.com/dotnet/linker/issues/2832 [ExpectedWarning ("IL2074", nameof (GetUnknownType), nameof (field))] static void TestWrite () { GetInstance (GetUnknownType ()).field = GetUnknownType (); } - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (GetInstance), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // https://github.com/dotnet/linker/issues/2832 + [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (GetInstance), Tool.Trimmer | Tool.NativeAot, "")] // https://github.com/dotnet/linker/issues/2832 [ExpectedWarning ("IL2074", nameof (GetUnknownType), nameof (field))] static void TestNullCoalescingAssignment () { @@ -341,13 +338,13 @@ static void RequirePublicFields ( { } - [ExpectedWarning ("IL2077", ProducedBy = Tool.Analyzer)] // https://github.com/dotnet/runtime/issues/101211 + [ExpectedWarning ("IL2077", Tool.Analyzer, "")] // https://github.com/dotnet/runtime/issues/101211 static void TestFlowOutOfField () { RequirePublicFields (unsupportedTypeInstance); } - [ExpectedWarning ("IL2074", ProducedBy = Tool.Analyzer)] // https://github.com/dotnet/runtime/issues/101211 + [ExpectedWarning ("IL2074", Tool.Analyzer, "")] // https://github.com/dotnet/runtime/issues/101211 public static void Test () { var t = GetUnsupportedTypeInstance (); unsupportedTypeInstance = t; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs index e7b96db55e6893..2cbd62f6d43432 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs @@ -408,7 +408,7 @@ class TypeGenericRequirementsOnMembers<[DynamicallyAccessedMembers (DynamicallyA { public TypeRequiresPublicFields PublicFieldsField; - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType public TypeRequiresPublicMethods PublicMethodsField; public TypeRequiresPublicFields PublicFieldsProperty { @@ -417,23 +417,23 @@ public TypeRequiresPublicFields PublicFieldsProperty { } public TypeRequiresPublicMethods PublicMethodsProperty { - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType get => null; - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType set { } } - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer, CompilerGeneratedCode = true)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "", CompilerGeneratedCode = true)] // NativeAOT_StorageSpaceType public TypeRequiresPublicMethods PublicMethodsImplicitGetter => null; public void PublicFieldsMethodParameter (TypeRequiresPublicFields param) { } - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType public void PublicMethodsMethodParameter (TypeRequiresPublicMethods param) { } public TypeRequiresPublicFields PublicFieldsMethodReturnValue () { return null; } - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType public TypeRequiresPublicMethods PublicMethodsMethodReturnValue () { return null; } public void PublicFieldsMethodLocalVariable () @@ -442,7 +442,7 @@ public void PublicFieldsMethodLocalVariable () } // The analyzer matches NativeAot behavior for local variables - it doesn't warn on generic types of local variables. - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType public void PublicMethodsMethodLocalVariable () { TypeRequiresPublicMethods t = null; @@ -711,17 +711,15 @@ public static void StaticPartialInstantiation () } [ExpectedWarning ("IL2091", - nameof (TOuter), + [nameof (TOuter), "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter", "TMethods", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams()", - ProducedBy = Tool.Analyzer)] + "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams()"], Tool.Analyzer, "")] [ExpectedWarning ("IL2091", - "'TOuter'", + ["'TOuter'", "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter", "'TMethods'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams"], Tool.Trimmer | Tool.NativeAot, "")] public static void StaticPartialInstantiationUnrecognized () { StaticRequiresMultipleGenericParams (); @@ -833,10 +831,10 @@ static void TestNoWarningsInRUCMethod () [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // StaticMethodRequiresPublicMethods [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // StaticMethodRequiresPublicMethods [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // RUCTypeRequiresPublicFields ctor - [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = Tool.Trimmer)] // RUCTypeRequiresPublicFields local, // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = Tool.Trimmer)] // InstanceMethod, // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", Tool.Trimmer, "")] // RUCTypeRequiresPublicFields local, // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", Tool.Trimmer, "")] // InstanceMethod, // NativeAOT_StorageSpaceType [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // InstanceMethodRequiresPublicMethods - [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = Tool.Trimmer)] // VirtualMethod, // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", Tool.Trimmer, "")] // VirtualMethod, // NativeAOT_StorageSpaceType [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // VirtualMethodRequiresPublicMethods static void TestNoWarningsInRUCType () { @@ -908,9 +906,9 @@ static void TestGenericParameterFlowsToDelegateMethodDeclaringType () [ExpectedWarning ("IL2091", nameof (DelegateMethodTypeRequiresFields))] // NativeAOT_StorageSpaceType: illink warns about the type of 'instance' local variable - [ExpectedWarning ("IL2091", nameof (DelegateMethodTypeRequiresFields), ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2091", nameof (DelegateMethodTypeRequiresFields), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType: illink warns about the declaring type of 'InstanceMethod' on ldftn - [ExpectedWarning ("IL2091", nameof (DelegateMethodTypeRequiresFields), ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2091", nameof (DelegateMethodTypeRequiresFields), Tool.Trimmer, "")] static void TestGenericParameterFlowsToDelegateMethodDeclaringTypeInstance () { var instance = new DelegateMethodTypeRequiresFields (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterWarningLocation.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterWarningLocation.cs index d3aa2e17ac021b..560560df1223d0 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterWarningLocation.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterWarningLocation.cs @@ -190,11 +190,11 @@ interface IWithTwo< static void MethodWithSpecificType (TypeWithPublicMethods one, IWithTwo two) { } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void MethodWithOneMismatch (TypeWithPublicMethods one) { } - [ExpectedWarning ("IL2091", nameof (IWithTwo), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", nameof (TypeWithPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (IWithTwo), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeWithPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void MethodWithTwoMismatches< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -205,11 +205,11 @@ static void MethodWithTwoMismatches< static TypeWithPublicMethods MethodWithMatchingReturn<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () => null; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static TypeWithPublicMethods MethodWithOneMismatchReturn () => null; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static IWithTwo MethodWithTwoMismatchesInReturn< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -217,7 +217,7 @@ static IWithTwo MethodWithTwoMismatchesInReturn< class ConstructorWithOneMatchAndOneMismatch<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods> { - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType public ConstructorWithOneMatchAndOneMismatch (IWithTwo two) { } } @@ -252,11 +252,11 @@ interface IWithTwo< static void MethodWithSpecificType (TypeWithPublicMethods one, IWithTwo two) { } - [ExpectedWarning ("IL2091", ProducedBy = Tool.NativeAot | Tool.Trimmer)] + [ExpectedWarning ("IL2091", Tool.NativeAot | Tool.Trimmer, "")] static void MethodWithOneMismatch (TypeWithPublicMethods one) { } - [ExpectedWarning ("IL2091", nameof (IWithTwo), ProducedBy = Tool.NativeAot | Tool.Trimmer)] - [ExpectedWarning ("IL2091", nameof (TypeWithPublicMethods), ProducedBy = Tool.NativeAot | Tool.Trimmer)] + [ExpectedWarning ("IL2091", nameof (IWithTwo), Tool.NativeAot | Tool.Trimmer, "")] + [ExpectedWarning ("IL2091", nameof (TypeWithPublicMethods), Tool.NativeAot | Tool.Trimmer, "")] static void MethodWithTwoMismatches< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -267,11 +267,11 @@ static void MethodWithTwoMismatches< static TypeWithPublicMethods MethodWithMatchingReturn<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () => null; - [ExpectedWarning ("IL2091", ProducedBy = Tool.NativeAot | Tool.Trimmer)] + [ExpectedWarning ("IL2091", Tool.NativeAot | Tool.Trimmer, "")] static TypeWithPublicMethods MethodWithOneMismatchReturn () => null; - [ExpectedWarning ("IL2091", ProducedBy = Tool.NativeAot | Tool.Trimmer)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.NativeAot | Tool.Trimmer)] + [ExpectedWarning ("IL2091", Tool.NativeAot | Tool.Trimmer, "")] + [ExpectedWarning ("IL2091", Tool.NativeAot | Tool.Trimmer, "")] static IWithTwo MethodWithTwoMismatchesInReturn< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -279,7 +279,7 @@ static IWithTwo MethodWithTwoMismatchesInReturn< class ConstructorWithOneMatchAndOneMismatch<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods> { - [ExpectedWarning ("IL2091", ProducedBy = Tool.NativeAot | Tool.Trimmer)] + [ExpectedWarning ("IL2091", Tool.NativeAot | Tool.Trimmer, "")] public ConstructorWithOneMatchAndOneMismatch (IWithTwo two) { } } @@ -325,10 +325,10 @@ public static void Test () class MultipleReferencesToTheSameType<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> { - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static TypeWithPublicMethods _field1; static TypeWithPublicMethods _field2; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static TypeWithPublicMethods _field3; public static void Test () @@ -343,8 +343,8 @@ class TwoMismatchesInOne< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> { - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static IWithTwo _field; public static void Test () @@ -388,10 +388,10 @@ class OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemb class MultipleReferencesToTheSameType<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> { - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static TypeWithPublicMethods _field1; static TypeWithPublicMethods _field2; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static TypeWithPublicMethods _field3; } @@ -399,8 +399,8 @@ class TwoMismatchesInOne< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> { - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static IWithTwo _field; } @@ -450,12 +450,12 @@ public static void Test () class MultipleReferencesToTheSameType<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> { // The warning is generated on the backing field - [ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "", CompilerGeneratedCode = true)] // NativeAOT_StorageSpaceType static TypeWithPublicMethods Property1 { - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType get; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType set; } @@ -465,12 +465,12 @@ static TypeWithPublicMethods Property2 { } // The warning is generated on the backing field - [ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "", CompilerGeneratedCode = true)] // NativeAOT_StorageSpaceType static TypeWithPublicMethods Property3 { - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType get; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType set; } @@ -487,14 +487,14 @@ class TwoMismatchesInOne< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> { // The warnings are generated on the backing field - [ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "", CompilerGeneratedCode = true)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "", CompilerGeneratedCode = true)] // NativeAOT_StorageSpaceType static IWithTwo Property { // Getter is trimmed and doesn't produce any warning get; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType set; } @@ -554,7 +554,7 @@ static void MethodWithTwo< static MethodBody GetInstance () => null; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // return type // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // return type // NativeAOT_StorageSpaceType static TypeWithPublicMethods GetInstanceForTypeWithPublicMethods () => null; class TypeOf @@ -578,8 +578,8 @@ static void SpecificType () } // Analyzer doesn't warn on typeof - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void MultipleReferencesToTheSameType< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -590,8 +590,8 @@ static void MultipleReferencesToTheSameType< } // Analyzer doesn't warn on typeof - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -694,8 +694,8 @@ static void TwoMismatchesInOneStatement< IWithTwo.Method (); } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // local variable // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // local variable // NativeAOT_StorageSpaceType static void InstanceMethodMismatch () { TypeWithPublicMethods instance = GetInstanceForTypeWithPublicMethods (); @@ -746,8 +746,8 @@ static void TwoMismatchesInOneStatement< _ = IWithTwo.Field; } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // access to the field // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // access to the field // NativeAOT_StorageSpaceType static void InstanceFieldMismatch () { TypeWithPublicMethods instance = GetInstanceForTypeWithPublicMethods (); @@ -779,8 +779,8 @@ static void SpecificType () TypeWithPublicMethods t = null; } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void MultipleReferencesToTheSameType< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -790,8 +790,8 @@ static void MultipleReferencesToTheSameType< TypeWithPublicMethods t3 = null; // Warn } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -952,9 +952,9 @@ static void SpecificType () // ldtoken owningtype // In order to call the right Expression APIs. [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void MultipleReferencesToTheSameMethod< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -969,9 +969,9 @@ static void MultipleReferencesToTheSameMethod< // ldtoken owningtype // In order to call the right Expression APIs. [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -1007,8 +1007,8 @@ static void SpecificType () // ldtoken field // ldtoken owningtype // In order to call the right Expression APIs. - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void MultipleReferencesToTheSameField< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -1024,8 +1024,8 @@ static void MultipleReferencesToTheSameField< // ldtoken field // ldtoken owningtype // In order to call the right Expression APIs. - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -1061,8 +1061,8 @@ static void SpecificType () // ldtoken method (getter) // ldtoken owningtype // In order to call the right Expression APIs. - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void MultipleReferencesToTheSameProperty< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -1078,8 +1078,8 @@ static void MultipleReferencesToTheSameProperty< // ldtoken method (getter) // ldtoken owningtype // In order to call the right Expression APIs. - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -1155,8 +1155,8 @@ static void SpecificType () bool a = _value is TypeWithPublicMethods; } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void MultipleReferencesToTheSameMethod< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -1166,8 +1166,8 @@ static void MultipleReferencesToTheSameMethod< bool a3 = _value is TypeWithPublicMethods; // Warn } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -1200,8 +1200,8 @@ static void SpecificType () object a = _value as TypeWithPublicMethods; } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void MultipleReferencesToTheSameMethod< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -1211,8 +1211,8 @@ static void MultipleReferencesToTheSameMethod< object a3 = _value as TypeWithPublicMethods; // Warn } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -1251,8 +1251,8 @@ static void SpecificType () } } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void MultipleReferencesToTheSameType< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -1273,8 +1273,8 @@ static void MultipleReferencesToTheSameType< } } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -1314,8 +1314,8 @@ static void SpecificType () } } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void MultipleReferencesToTheSameType< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -1336,8 +1336,8 @@ static void MultipleReferencesToTheSameType< } } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -1373,14 +1373,14 @@ class AnnotatedString static void MethodWithAnnotatedParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] string typeName) { } // Analyzer: https://github.com/dotnet/runtime/issues/95118 - [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")] static void AnnotatedParameter () { MethodWithAnnotatedParameter ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]"); } // Analyzer: https://github.com/dotnet/runtime/issues/95118 - [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] static string AnnotatedReturnValue () { @@ -1391,7 +1391,7 @@ static string AnnotatedReturnValue () static string _annotatedField; // Analyzer: https://github.com/dotnet/runtime/issues/95118 - [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")] static void AnnotatedField () { _annotatedField = "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]"; @@ -1408,7 +1408,7 @@ public static void Test () class TypeGetType { // Analyzer: https://github.com/dotnet/runtime/issues/95118 - [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")] static void SpecificType () { Type.GetType ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]"); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs index d99b7557a257a3..c5361f835534c9 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs @@ -169,8 +169,8 @@ public void Method1 () { } public void Method2 () { } // https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2026", "--Method1--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--Method2--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--Method1--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "--Method2--", Tool.Trimmer | Tool.NativeAot, "")] public static void Test () { Type.GetType ("Mono.Linker.Tests.Cases.DataFlow." + nameof (GetTypeDataFlow) + "+" + nameof (TypeWithWarnings)).RequiresPublicMethods (); @@ -185,7 +185,7 @@ class OverConstTypeName public void Method1 () { } // https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2026", "--Method1--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--Method1--", Tool.Trimmer | Tool.NativeAot, "")] public static void Test () { Type.GetType (s_ConstTypeName).RequiresPublicMethods (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InlineArrayDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InlineArrayDataflow.cs index c7725fcdf2617c..5915bb2d45384c 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InlineArrayDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InlineArrayDataflow.cs @@ -14,7 +14,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow [ExpectedNoWarnings] public class InlineArrayDataflow { - public static void Main() + public static void Main () { AccessPrimitiveTypeArray (); AccessUnannotatedTypeArray (); @@ -63,7 +63,7 @@ struct AnnotatedTypeArray } // Currently tracking of annotations on inline array values is not implemented - [ExpectedWarning("IL2065", "GetProperty")] + [ExpectedWarning ("IL2065", "GetProperty")] static void AccessAnnotatedTypeArray () { AnnotatedTypeArray a = new AnnotatedTypeArray (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/LocalDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/LocalDataFlow.cs index 788312c2c262df..71b08b3a6af17e 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/LocalDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/LocalDataFlow.cs @@ -218,8 +218,7 @@ public static void TestBranchMergeCatch () nameof (LocalDataFlow) + "." + nameof (GetWithPublicFields) + "()")] // ILLink produces extraneous warnings [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields) + "(String)", - nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer)] + nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", Tool.Trimmer, "")] public static void TestBranchMergeFinally () { string str = GetWithPublicMethods (); @@ -235,8 +234,7 @@ public static void TestBranchMergeFinally () } // Analyzer gets this right (no warning), but trimmer merges all branches going forward. - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields) + "(String)", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields) + "(String)", Tool.Trimmer, "")] public static void TestBranchGoto () { string str = GetWithPublicMethods (); @@ -249,8 +247,7 @@ public static void TestBranchGoto () } // Analyzer gets this right (no warning), but trimmer merges all branches going forward. - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields), - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields), Tool.Trimmer, "")] public static void TestBranchIf () { string str = GetWithPublicMethods (); @@ -261,8 +258,7 @@ public static void TestBranchIf () } // Analyzer gets this right (no warning), but trimmer merges all branches going forward. - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields), - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields), Tool.Trimmer, "")] public static void TestBranchIfElse () { string str; @@ -278,18 +274,12 @@ public static void TestBranchIfElse () } // Analyzer gets this right (no warning), but trimmer merges all branches going forward. - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresNonPublicMethods) + "(String)", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicMethods) + "(String)", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicMethods) + "(String)", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicConstructors) + "(String)", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicConstructors) + "(String)", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicConstructors) + "(String)", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresNonPublicMethods) + "(String)", Tool.Trimmer, "")] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicMethods) + "(String)", Tool.Trimmer, "")] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicMethods) + "(String)", Tool.Trimmer, "")] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicConstructors) + "(String)", Tool.Trimmer, "")] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicConstructors) + "(String)", Tool.Trimmer, "")] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicConstructors) + "(String)", Tool.Trimmer, "")] public static void TestBranchSwitch () { string str = null; @@ -315,8 +305,7 @@ public static void TestBranchSwitch () // Analyzer gets this right (no warning), but trimmer merges all branches going forward. [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields), - nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer)] + nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", Tool.Trimmer, "")] public static void TestBranchTry () { string str = GetWithPublicMethods (); @@ -332,8 +321,7 @@ public static void TestBranchTry () // Analyzer gets this right (no warning), but trimmer merges all branches going forward. [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields), - nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer)] + nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", Tool.Trimmer, "")] public static void TestBranchCatch () { string str = GetWithPublicMethods (); @@ -348,8 +336,7 @@ public static void TestBranchCatch () // Analyzer gets this right (no warning), but trimmer merges all branches going forward. [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields), - nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer)] + nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", Tool.Trimmer, "")] public static void TestBranchFinally () { string str = GetWithPublicMethods (); @@ -365,8 +352,7 @@ public static void TestBranchFinally () // Analyzer gets this right, but ILLink doesn't consider backwards branches. [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicMethods) + "(String)", - nameof (LocalDataFlow) + "." + nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + nameof (LocalDataFlow) + "." + nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] public static void TestBackwardsEdgeLoop () { string str = GetWithPublicMethods (); @@ -382,8 +368,7 @@ public static void TestBackwardsEdgeLoop () // Analyzer gets this right, but ILLink doesn't consider backwards branches. [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicMethods) + "(String)", - nameof (LocalDataFlow) + "." + nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + nameof (LocalDataFlow) + "." + nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] public static void TestBackwardsEdgeGoto () { string str = null; @@ -440,8 +425,8 @@ public virtual void VirtualMethod () // https://github.com/dotnet/linker/issues/2273 // Analyzer doesn't see through foreach over array at all - will not warn - [ExpectedWarning ("IL2063", ProducedBy = Tool.Trimmer)] // The types loaded from the array don't have annotations, so the "return" should warn - [ExpectedWarning ("IL2073", ProducedBy = Tool.Analyzer)] // Analyzer tracks resultType as the value from IEnumerable.Current.get() + [ExpectedWarning ("IL2063", Tool.Trimmer, "")] // The types loaded from the array don't have annotations, so the "return" should warn + [ExpectedWarning ("IL2073", Tool.Analyzer, "")] // Analyzer tracks resultType as the value from IEnumerable.Current.get() [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] public static Type TestBackwardEdgeWithLdElem (Type[] types = null) { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs index 50451dcd3f1e4e..32342ee39eecbc 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs @@ -126,7 +126,7 @@ static void TestWithRequirementsFromParam ( } // https://github.com/dotnet/linker/issues/2428 - // [ExpectedWarning ("IL2071", "'T'")] + // [ExpectedSharedWarning ("IL2071", "'T'")] [ExpectedWarning ("IL2070", "'this'")] static void TestWithRequirementsFromParamWithMismatch ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) @@ -141,7 +141,7 @@ static void TestWithRequirementsFromGenericParam< } // https://github.com/dotnet/linker/issues/2428 - // [ExpectedWarning ("IL2091", "'T'")] + // [ExpectedSharedWarning ("IL2091", "'T'")] [ExpectedWarning ("IL2090", "'this'")] // Note that this actually produces a warning which should not be possible to produce right now static void TestWithRequirementsFromGenericParamWithMismatch< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TInput> () @@ -551,7 +551,7 @@ static void TestWithArrayUnknownIndexSet (int indexToSet) } // https://github.com/dotnet/linker/issues/2158 - analyzer doesn't work the same as ILLink, it simply doesn't handle refs - [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod), Tool.Trimmer | Tool.NativeAot, "")] static void TestWithArrayUnknownIndexSetByRef (int indexToSet) { Type[] types = new Type[1]; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataflowIntrinsics.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataflowIntrinsics.cs index 4fe39ab6da1ca4..b1a67bd42dbdfe 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataflowIntrinsics.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataflowIntrinsics.cs @@ -34,10 +34,10 @@ public static void Test () public static void TestRecognizedGenericIntrinsic () => typeof (Gen<>).MakeGenericType (typeof (T)); [ExpectedWarning ("IL2055", nameof (Type.MakeGenericType))] - [ExpectedWarning ("IL3050", nameof (Type.MakeGenericType), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (Type.MakeGenericType), Tool.Analyzer | Tool.NativeAot, "")] public static void TestUnknownOwningType () => GrabUnknownType ().MakeGenericType (typeof (object)); - [ExpectedWarning ("IL3050", nameof (Type.MakeGenericType), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (Type.MakeGenericType), Tool.Analyzer | Tool.NativeAot, "")] public static void TestUnknownArgument () => typeof (Gen<>).MakeGenericType (GrabUnknownType ()); } @@ -62,10 +62,10 @@ public static void Test () public static void TestRecognizedGenericIntrinsic () => typeof (MakeGenericMethod).GetMethod (nameof (Gen)).MakeGenericMethod (typeof (T)); [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] - [ExpectedWarning ("IL3050", nameof (MethodInfo.MakeGenericMethod), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (MethodInfo.MakeGenericMethod), Tool.Analyzer | Tool.NativeAot, "")] public static void TestUnknownOwningMethod () => GrabUnknownMethod ().MakeGenericMethod (typeof (object)); - [ExpectedWarning ("IL3050", nameof (MethodInfo.MakeGenericMethod), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (MethodInfo.MakeGenericMethod), Tool.Analyzer | Tool.NativeAot, "")] public static void TestUnknownArgument () => typeof (MakeGenericMethod).GetMethod (nameof (Gen)).MakeGenericMethod (GrabUnknownType()); } } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefParameterDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefParameterDataFlow.cs index 7ea036c5c39bbd..4396d6c26e3b2f 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefParameterDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefParameterDataFlow.cs @@ -123,7 +123,7 @@ static void TestReadFromRefParameter_MismatchOnOutput_PassedTwice () // https://github.com/dotnet/linker/issues/2632 // This second warning should not be generated, the value of typeWithMethods should have PublicMethods // after the call with out parameter. - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Analyzer, "")] static void TestReadFromRefParameter_MismatchOnInput () { Type typeWithMethods = GetTypeWithFields (); @@ -136,7 +136,7 @@ static void TestReadFromRefParameter_MismatchOnInput () // https://github.com/dotnet/linker/issues/2632 // This third warning should not be generated, the value of typeWithMethods should have PublicMethods // after the call with ref parameter. - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Analyzer, "")] static void TestReadFromRefParameter_MismatchOnInput_PassedTwice () { Type typeWithMethods = GetTypeWithFields (); @@ -269,7 +269,7 @@ static void TestPassingRefProperty_OutParameter () TryGetAnnotatedValueOut (out TypeWithMethodsProperty); } - [ExpectedWarning ("IL2072", nameof (TryGetAnnotatedValue), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (TryGetAnnotatedValue), Tool.Trimmer | Tool.NativeAot, "")] static void TestPassingRefProperty_Mismatch () { TryGetAnnotatedValue (ref TypeWithFieldsProperty); @@ -316,8 +316,8 @@ static void TestPassingRefIndexer_OutParameter () } // https://github.com/dotnet/linker/issues/2158 - [ExpectedWarning ("IL2068", nameof (TryGetAnnotatedValue), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (TryGetAnnotatedValue), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2068", nameof (TryGetAnnotatedValue), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (TryGetAnnotatedValue), Tool.Trimmer | Tool.NativeAot, "")] static void TestPassingRefIndexer_Mismatch () { var indexer = new RefIndexer_PublicFields (); @@ -325,7 +325,7 @@ static void TestPassingRefIndexer_Mismatch () } // https://github.com/dotnet/linker/issues/2158 - [ExpectedWarning ("IL2068", nameof (TryGetAnnotatedValue), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2068", nameof (TryGetAnnotatedValue), Tool.Trimmer | Tool.NativeAot, "")] static void TestPassingRefIndexer_OutParameter_Mismatch () { var indexer = new RefIndexer_PublicFields (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefReturnDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefReturnDataFlow.cs index 7220a83d3ce2dd..99978295d67570 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefReturnDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefReturnDataFlow.cs @@ -43,7 +43,7 @@ public static void Main () // Correct behavior in the trimming tools, but needs to be added in analyzer // Bug link: https://github.com/dotnet/linker/issues/2158 - [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", Tool.Trimmer | Tool.NativeAot, "")] static void AssignToAnnotatedTypeReference () { ref Type typeShouldHaveAllMethods = ref ReturnAnnotatedTypeReferenceAsAnnotated (); @@ -53,7 +53,7 @@ static void AssignToAnnotatedTypeReference () // Same as above for IL analysis, but this looks different to the Roslyn analyzer. // https://github.com/dotnet/linker/issues/2158 - [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", Tool.Trimmer | Tool.NativeAot, "")] static void AssignDirectlyToAnnotatedTypeReference () { ReturnAnnotatedTypeReferenceAsAnnotated () = typeof (TestTypeWithRequires); @@ -61,7 +61,7 @@ static void AssignDirectlyToAnnotatedTypeReference () } // https://github.com/dotnet/linker/issues/2158 - [ExpectedWarning ("IL2073", nameof (GetWithPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2073", nameof (GetWithPublicFields), Tool.Trimmer | Tool.NativeAot, "")] static void AssignToCapturedAnnotatedTypeReference () { // In this testcase, the Roslyn analyzer sees an assignment to a flow-capture reference. @@ -69,7 +69,7 @@ static void AssignToCapturedAnnotatedTypeReference () } [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (ReturnAnnotatedTypeWithRequirements))] - [ExpectedWarning ("IL2073", nameof (ReturnAnnotatedTypeWithRequirements), nameof (GetWithPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2073", nameof (ReturnAnnotatedTypeWithRequirements), nameof (GetWithPublicFields), Tool.Trimmer | Tool.NativeAot, "")] static void AssignToAnnotatedTypeReferenceWithRequirements () { ReturnAnnotatedTypeWithRequirements (GetWithPublicMethods ()) = GetWithPublicFields (); @@ -80,7 +80,7 @@ static void AssignToAnnotatedTypeReferenceWithRequirements () [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] static ref Type AnnotatedTypeReferenceAsAnnotatedProperty => ref _annotatedField; - [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", Tool.Trimmer | Tool.NativeAot, "")] static void AssignToAnnotatedTypeReferenceProperty () { ref Type typeShouldHaveAllMethods = ref AnnotatedTypeReferenceAsAnnotatedProperty; @@ -89,7 +89,7 @@ static void AssignToAnnotatedTypeReferenceProperty () } // https://github.com/dotnet/linker/issues/2158 - [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", Tool.Trimmer | Tool.NativeAot, "")] static void AssignDirectlyToAnnotatedTypeReferenceProperty () { AnnotatedTypeReferenceAsAnnotatedProperty = typeof (TestTypeWithRequires); @@ -97,7 +97,7 @@ static void AssignDirectlyToAnnotatedTypeReferenceProperty () } // https://github.com/dotnet/linker/issues/2158 - [ExpectedWarning ("IL2073", nameof (GetWithPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2073", nameof (GetWithPublicFields), Tool.Trimmer | Tool.NativeAot, "")] static void AssignToCapturedAnnotatedTypeReferenceProperty () { AnnotatedTypeReferenceAsAnnotatedProperty = GetWithPublicMethods () ?? GetWithPublicFields (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodOutParameterDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodOutParameterDataFlow.cs index 582c86ee012b4b..22f7bd5e8b1274 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodOutParameterDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodOutParameterDataFlow.cs @@ -76,7 +76,7 @@ static void TestInitializedReadFromOutParameter_MismatchOnOutput_PassedTwice () // https://github.com/dotnet/linker/issues/2632 // This warning should not be generated, the value of typeWithMethods should have PublicMethods // after the call with out parameter. - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Analyzer, "")] static void TestInitializedReadFromOutParameter_MismatchOnInput () { Type typeWithMethods = GetTypeWithFields (); @@ -89,7 +89,7 @@ static void TestInitializedReadFromOutParameter_MismatchOnInput () // https://github.com/dotnet/linker/issues/2632 // This warning should not be generated, the value of typeWithMethods should have PublicMethods // after the call with out parameter. - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Analyzer, "")] static void TestInitializedReadFromOutParameter_MismatchOnInput_PassedTwice () { Type typeWithMethods = GetTypeWithFields (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodParametersDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodParametersDataFlow.cs index 0c6c1d02d8c10c..aa2783332e429e 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodParametersDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodParametersDataFlow.cs @@ -142,8 +142,6 @@ private void TwoAnnotatedParameters ( type2.RequiresPublicConstructors (); } - // TODO: https://github.com/dotnet/linker/issues/2273 - // (Dataflow analysis is not supported by the analyzer yet) [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions) + "." + nameof (DataFlowTypeExtensions.RequiresPublicConstructors) + "(Type)", "'type'")] @@ -246,7 +244,7 @@ class UnsupportedType () static UnsupportedType GetUnsupportedTypeInstance () => null; [ExpectedWarning ("IL2098", nameof (UnsupportedType))] - [ExpectedWarning ("IL2067", ProducedBy = Tool.Analyzer)] // https://github.com/dotnet/runtime/issues/101211 + [ExpectedWarning ("IL2067", Tool.Analyzer, "")] // https://github.com/dotnet/runtime/issues/101211 static void RequirePublicMethods ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] UnsupportedType unsupportedTypeInstance) @@ -261,7 +259,7 @@ static void RequirePublicFields ( { } - [ExpectedWarning ("IL2072", ProducedBy = Tool.Analyzer)] // https://github.com/dotnet/runtime/issues/101211 + [ExpectedWarning ("IL2072", Tool.Analyzer, "")] // https://github.com/dotnet/runtime/issues/101211 public static void Test () { var t = GetUnsupportedTypeInstance (); RequirePublicMethods (t); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodReturnParameterDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodReturnParameterDataFlow.cs index 4bd9257124654b..8f3adcbdaa0889 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodReturnParameterDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodReturnParameterDataFlow.cs @@ -190,7 +190,7 @@ class AnnotationOnUnsupportedReturnType { class UnsupportedType { - [ExpectedWarning ("IL2082", ProducedBy = Tool.Analyzer)] // https://github.com/dotnet/runtime/issues/101211 + [UnexpectedWarning ("IL2082", Tool.Analyzer, "")] // https://github.com/dotnet/runtime/issues/101211 public UnsupportedType () { RequirePublicFields (this); } @@ -202,7 +202,7 @@ public UnsupportedType () { // Linker and NativeAot should not produce IL2073 // They produce dataflow warnings despite the invalid annotations. // https://github.com/dotnet/runtime/issues/101211 - [ExpectedWarning ("IL2073", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2073", Tool.Trimmer | Tool.NativeAot, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] static UnsupportedType GetWithPublicMethods () { return GetUnsupportedTypeInstance (); @@ -215,7 +215,7 @@ static void RequirePublicFields ( { } - [ExpectedWarning ("IL2072", ProducedBy = Tool.Analyzer)] // https://github.com/dotnet/runtime/issues/101211 + [ExpectedWarning ("IL2072", Tool.Analyzer, "")] // https://github.com/dotnet/runtime/issues/101211 static void TestMethodReturnValue () { var t = GetWithPublicMethods (); RequirePublicFields (t); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodThisDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodThisDataFlow.cs index 28dc0669d2aa02..50ae6925bdb4ef 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodThisDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodThisDataFlow.cs @@ -122,7 +122,7 @@ static void RequirePublicFields ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] UnsupportedType unsupportedTypeInstance) { } - [ExpectedWarning ("IL2075", nameof (UnsupportedType), nameof (UnsupportedType.GetMethod), ProducedBy = Tool.Analyzer)] // BUG + [ExpectedWarning ("IL2075", nameof (UnsupportedType), nameof (UnsupportedType.GetMethod), Tool.Analyzer, "")] // BUG static void TestMethodThisParameter () { var t = GetUnsupportedTypeInstance (); t.GetMethod ("foo"); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs index 1a8930c8a7c8e0..76a1a48a06425c 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs @@ -215,8 +215,7 @@ static Type PropertyWithSimpleGetter { // is highly unlikely to be done by anybody. If it happens, the analyzer will produce warnings which the trimming tools will not // but those warnings are not really wrong, so it's better if the developer fixes them anyway. [ExpectedWarning ("IL2077", nameof (DataFlowTypeExtensions) + "." + nameof (DataFlowTypeExtensions.RequiresPublicConstructors) + "(Type)", - nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWhichLooksLikeCompilerGenerated_Field), - ProducedBy = Tool.Analyzer)] + nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWhichLooksLikeCompilerGenerated_Field), Tool.Analyzer, "")] public void TestPropertyWhichLooksLikeCompilerGenerated () { // If the property was correctly recognized both the property getter and the backing field should get the annotation. @@ -231,8 +230,7 @@ public void TestPropertyWhichLooksLikeCompilerGenerated () static Type PropertyWhichLooksLikeCompilerGenerated { // See above comment about fake compiler generated backing fields - this warning is expected from the analyzer [ExpectedWarning ("IL2078", nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWhichLooksLikeCompilerGenerated) + ".get", - nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWhichLooksLikeCompilerGenerated_Field), - ProducedBy = Tool.Analyzer)] + nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWhichLooksLikeCompilerGenerated_Field), Tool.Analyzer, "")] get { return PropertyWhichLooksLikeCompilerGenerated_Field; } @@ -272,17 +270,14 @@ public void TestPropertyWithDifferentBackingFields () // Analyzer doesn't try to detect backing fields of properties: https://github.com/dotnet/linker/issues/2273 [ExpectedWarning ("IL2042", - "Mono.Linker.Tests.Cases.DataFlow.PropertyDataFlow.TestAutomaticPropagationType.PropertyWithDifferentBackingFields", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + "Mono.Linker.Tests.Cases.DataFlow.PropertyDataFlow.TestAutomaticPropagationType.PropertyWithDifferentBackingFields", Tool.Trimmer | Tool.NativeAot, "")] [ExpectedWarning ("IL2078", nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWithDifferentBackingFields) + ".get", - "Type", - ProducedBy = Tool.Analyzer)] + "Type", Tool.Analyzer, "")] [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] Type PropertyWithDifferentBackingFields { [ExpectedWarning ("IL2078", - nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWithDifferentBackingFields) + ".get", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWithDifferentBackingFields) + ".get", Tool.Trimmer | Tool.NativeAot, "")] get { return PropertyWithDifferentBackingFields_GetterField; } @@ -299,25 +294,22 @@ public void TestPropertyWithExistingAttributes () } // Analyzer doesn't try to detect backing fields of properties: https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2056", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes_Field", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2056", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes_Field", Tool.Trimmer | Tool.NativeAot, "")] [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] [CompilerGenerated] Type PropertyWithExistingAttributes_Field; - [ExpectedWarning ("IL2043", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.get", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2043", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.set", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2043", ["PropertyWithExistingAttributes", "PropertyWithExistingAttributes.get"], Tool.Analyzer, "")] + [ExpectedWarning ("IL2043", [ "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.set"], Tool.Analyzer, "")] [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] Type PropertyWithExistingAttributes { // On property/accessor mismatch, ILLink warns on accessor and analyzer warns on property https://github.com/dotnet/linker/issues/2654 - [ExpectedWarning ("IL2043", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.get", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2043", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.get", Tool.Trimmer | Tool.NativeAot, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] get { return PropertyWithExistingAttributes_Field; } // On property/accessor mismatch, ILLink warns on accessor and analyzer warns on property https://github.com/dotnet/linker/issues/2654 - [ExpectedWarning ("IL2043", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.set", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2043", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.set", Tool.Trimmer | Tool.NativeAot, "")] [param: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] set { PropertyWithExistingAttributes_Field = value; } } @@ -337,25 +329,22 @@ public void TestPropertyWithConflictingAttributes () } // Analyzer doesn't try to detect backing fields of properties: https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2056", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes_Field", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2056", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes_Field", Tool.Trimmer | Tool.NativeAot, "")] [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicConstructors)] [CompilerGenerated] Type PropertyWithConflictingAttributes_Field; - [ExpectedWarning ("IL2043", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.get", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2043", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.set", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2043", ["PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.get"], Tool.Analyzer, "")] + [ExpectedWarning ("IL2043", ["PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.set"], Tool.Analyzer, "")] [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] Type PropertyWithConflictingAttributes { // On property/accessor mismatch, ILLink warns on accessor and analyzer warns on property https://github.com/dotnet/linker/issues/2654 - [ExpectedWarning ("IL2043", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.get", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2043", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.get", Tool.Trimmer | Tool.NativeAot, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicConstructors)] get { return PropertyWithConflictingAttributes_Field; } // On property/accessor mismatch, ILLink warns on accessor and analyzer warns on property https://github.com/dotnet/linker/issues/2654 - [ExpectedWarning ("IL2043", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.set", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2043", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.set", Tool.Trimmer | Tool.NativeAot, "")] [param: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicConstructors)] set { PropertyWithConflictingAttributes_Field = value; } } @@ -382,8 +371,7 @@ public void TestPropertyWithConflictingNoneAttributes () Type PropertyWithConflictingNoneAttributes { // See above comment about fake compiler generated backing fields - this warning is expected from analyzer [ExpectedWarning ("IL2078", nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWithConflictingNoneAttributes) + ".get", - nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWithConflictingNoneAttributes_Field), - ProducedBy = Tool.Analyzer)] + nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWithConflictingNoneAttributes_Field), Tool.Analyzer, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.None)] get { return PropertyWithConflictingNoneAttributes_Field; } @@ -399,8 +387,8 @@ public void TestPropertyWithIndexerWithMatchingAnnotations ([DynamicallyAccessed } // Trimmer and analyzer handle formatting of indexers differently. - [ExpectedWarning ("IL2067", nameof (PropertyWithIndexer) + ".Item.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2067", nameof (PropertyWithIndexer) + ".this[Int32].set", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2067", nameof (PropertyWithIndexer) + ".Item.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2067", nameof (PropertyWithIndexer) + ".this[Int32].set", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions) + "." + nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors) + "(Type)")] [LogDoesNotContain ("'Value passed to parameter 'index' of method 'Mono.Linker.Tests.Cases.DataFlow.PropertyDataFlow.TestAutomaticPropagationType.PropertyWithIndexer.Item.set'")] public void TestPropertyWithIndexerWithoutMatchingAnnotations (Type myType) @@ -418,8 +406,8 @@ public class PropertyWithIndexer [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] public Type this[int index] { // Trimmer and analyzer handle formatting of indexers differently. - [ExpectedWarning ("IL2063", nameof (PropertyWithIndexer) + ".Item.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2063", nameof (PropertyWithIndexer) + ".this[Int32].get", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2063", nameof (PropertyWithIndexer) + ".Item.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2063", nameof (PropertyWithIndexer) + ".this[Int32].get", Tool.Analyzer, "")] get => Property_Field[index]; set => Property_Field[index] = value; } @@ -482,8 +470,7 @@ class WriteToGetOnlyProperty public Type GetOnlyProperty { get; } // Analyzer doesn't warn about compiler-generated backing field of property: https://github.com/dotnet/runtime/issues/93277 - [ExpectedWarning ("IL2074", nameof (WriteToGetOnlyProperty), nameof (GetUnknownType), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2074", nameof (WriteToGetOnlyProperty), nameof (GetUnknownType), Tool.Trimmer | Tool.NativeAot, "")] public WriteToGetOnlyProperty () { GetOnlyProperty = GetUnknownType (); @@ -562,10 +549,8 @@ class WriteCapturedGetOnlyProperty Type GetOnlyProperty { get; } // Analyzer doesn't warn about compiler-generated backing field of property: https://github.com/dotnet/runtime/issues/93277 - [ExpectedWarning ("IL2074", nameof (WriteCapturedGetOnlyProperty), nameof (GetUnknownType), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2074", nameof (WriteCapturedGetOnlyProperty), nameof (GetTypeWithPublicConstructors), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2074", nameof (WriteCapturedGetOnlyProperty), nameof (GetUnknownType), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2074", nameof (WriteCapturedGetOnlyProperty), nameof (GetTypeWithPublicConstructors), Tool.Trimmer | Tool.NativeAot, "")] public WriteCapturedGetOnlyProperty () { GetOnlyProperty = GetUnknownType () ?? GetTypeWithPublicConstructors (); @@ -677,15 +662,15 @@ Type this[Index idx] { set => throw new NotImplementedException (); } - [ExpectedWarning ("IL2072", "this[Index].get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", "Item.get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", ["this[Index].get", nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", ["Item.get", nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Trimmer | Tool.NativeAot, "")] static void TestRead (ExplicitIndexerAccess instance = null) { instance[new Index (1)].RequiresAll (); } - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "this[Index].set", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "Item.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", [nameof (GetTypeWithPublicConstructors), "this[Index].set"], Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", [nameof (GetTypeWithPublicConstructors), "Item.set"], Tool.Trimmer | Tool.NativeAot, "")] static void TestWrite (ExplicitIndexerAccess instance = null) { instance[^1] = GetTypeWithPublicConstructors (); @@ -708,22 +693,22 @@ Type this[int idx] { int Length => throw new NotImplementedException (); - [ExpectedWarning ("IL2072", "this[Int32].get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", "Item.get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", ["this[Int32].get", nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", ["Item.get", nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Trimmer | Tool.NativeAot, "")] static void TestRead (ImplicitIndexerAccess instance = null) { instance[new Index (1)].RequiresAll (); } - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "this[Int32].set", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "Item.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", [nameof (GetTypeWithPublicConstructors), "this[Int32].set"], Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", [nameof (GetTypeWithPublicConstructors), "Item.set"], Tool.Trimmer | Tool.NativeAot, "")] static void TestWrite (ImplicitIndexerAccess instance = null) { instance[^1] = GetTypeWithPublicConstructors (); } - [ExpectedWarning ("IL2072", nameof (GetUnknownType), "this[Int32].set", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetUnknownType), "Item.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", [nameof (GetUnknownType), "this[Int32].set"], Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", [nameof (GetUnknownType), "Item.set"], Tool.Trimmer | Tool.NativeAot, "")] static void TestNullCoalescingAssignment (ImplicitIndexerAccess instance = null) { instance[new Index (1)] ??= GetUnknownType (); @@ -747,8 +732,8 @@ int this[[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicField get => throw new NotImplementedException (); } - [ExpectedWarning ("IL2067", "this[Type].get", nameof (ParamDoesNotMeetRequirements), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2067", "Item.get", nameof (ParamDoesNotMeetRequirements), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2067", ["this[Type].get", nameof (ParamDoesNotMeetRequirements)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2067", ["Item.get", nameof (ParamDoesNotMeetRequirements)], Tool.Trimmer | Tool.NativeAot, "")] static void ParamDoesNotMeetRequirements (Type t) { var x = new IndexWithTypeWithDam (); @@ -761,8 +746,8 @@ static void ParamDoesMeetRequirements ([DynamicallyAccessedMembers (DynamicallyA _ = x[t]; } - [ExpectedWarning ("IL2087", "this[Type].get", nameof (TypeParamDoesNotMeetRequirements), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2087", "Item.get", nameof (TypeParamDoesNotMeetRequirements), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2087", ["this[Type].get", nameof (TypeParamDoesNotMeetRequirements)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2087", ["Item.get", nameof (TypeParamDoesNotMeetRequirements)], Tool.Trimmer | Tool.NativeAot, "")] static void TypeParamDoesNotMeetRequirements () { var x = new IndexWithTypeWithDam (); @@ -802,8 +787,8 @@ Type this[[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFiel [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] static Type fieldWithMethods; - [ExpectedWarning ("IL2067", "this[Type].get", nameof (ParamDoesNotMeetRequirements), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2067", "Item.get", nameof (ParamDoesNotMeetRequirements), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2067", ["this[Type].get", nameof (ParamDoesNotMeetRequirements)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2067", ["Item.get", nameof (ParamDoesNotMeetRequirements)], Tool.Trimmer | Tool.NativeAot, "")] static void ParamDoesNotMeetRequirements (Type t) { var x = new IndexWithTypeWithDam (); @@ -816,8 +801,8 @@ static void ParamDoesMeetRequirements ([DynamicallyAccessedMembers (DynamicallyA fieldWithMethods = x[t]; } - [ExpectedWarning ("IL2087", "this[Type].get", nameof (TypeParamDoesNotMeetRequirements), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2087", "Item.get", nameof (TypeParamDoesNotMeetRequirements), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2087", ["this[Type].get", nameof (TypeParamDoesNotMeetRequirements)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2087", ["Item.get", nameof (TypeParamDoesNotMeetRequirements)], Tool.Trimmer | Tool.NativeAot, "")] static void TypeParamDoesNotMeetRequirements () { var x = new IndexWithTypeWithDam (); @@ -839,16 +824,16 @@ static void KnownTypeDoesMeetRequirements () fieldWithMethods = x[t]; } - [ExpectedWarning ("IL2067", "this[Type].set", nameof (t), "idx", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2067", "Item.set", nameof (t), "idx", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2067", ["this[Type].set", nameof (t), "idx"], Tool.Analyzer, "")] + [ExpectedWarning ("IL2067", ["Item.set", nameof (t), "idx"], Tool.Trimmer | Tool.NativeAot, "")] static void ValueMeetsRequirementsIndexDoesNot (Type t) { var x = new IndexWithTypeWithDam (); x[t] = fieldWithMethods; } - [ExpectedWarning ("IL2067", "this[Type].set", nameof (tUnannotated), "value", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2067", "Item.set", nameof (tUnannotated), "value", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2067", ["this[Type].set", nameof (tUnannotated), "value"], Tool.Analyzer, "")] + [ExpectedWarning ("IL2067", ["Item.set", nameof (tUnannotated), "value"], Tool.Trimmer | Tool.NativeAot, "")] static void ValueDoesNotMeetRequirementsIndexDoes ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] Type t, Type tUnannotated) { var x = new IndexWithTypeWithDam (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/RefFieldDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/RefFieldDataFlow.cs index 415dff13582ba6..983fc35c0b11eb 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/RefFieldDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/RefFieldDataFlow.cs @@ -14,10 +14,10 @@ class RefFieldDataFlow { [Kept] // Bug for the IL2069's here: https://github.com/dotnet/runtime/issues/85464 - [ExpectedWarning ("IL2069", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2069", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2069", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2069", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "")] public static void Main () { RefFieldWithMethods withMethods = new (ref fieldWithMethods); @@ -96,11 +96,11 @@ static void AssignRefToLocals< tmf = typeof (TF); // This is a hole that doesn't warn but assigns a misannotated value to target.T } - [ExpectedWarning ("IL2089", "RefFieldWithMethods", "T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2089", "RefFieldWithFields", "T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2089", "RefFieldWithMethodsAndFields", "T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2089", "RefFieldWithMethodsAndFields", "T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2089", "RefFieldWithFields", "T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2089", "RefFieldWithMethods", "T", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2089", "RefFieldWithFields", "T", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2089", "RefFieldWithMethodsAndFields", "T", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2089", "RefFieldWithMethodsAndFields", "T", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2089", "RefFieldWithFields", "T", Tool.Trimmer | Tool.NativeAot, "")] static void AssignRefLocals< T, [DAM (DAMT.PublicMethods)] TM, @@ -176,13 +176,13 @@ static void AssignParameters (scoped RefFieldWithMethods target, // ILLink doesn't recognize ldind.ref // https://github.com/dotnet/runtime/issues/85465 // IL2064's are bugs - shouldn't be unknown values - [ExpectedWarning ("IL2064", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2064", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2064", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2064", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2064", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2069", "RefFieldWithMethods.T", "param", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2069", "RefFieldWithMethods.T", "paramWithFields", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2064", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2064", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2064", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2064", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2064", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2069", "RefFieldWithMethods.T", "param", Tool.Analyzer, "")] + [ExpectedWarning ("IL2069", "RefFieldWithMethods.T", "paramWithFields", Tool.Analyzer, "")] static void AssignRefParameters< T, [DAM (DAMT.PublicMethods)] TM, @@ -233,15 +233,15 @@ static void AssignFields (RefFieldWithMethods target, UnannotatedField unannotat [ExpectedWarning ("IL2079", "RefFieldWithMethods.T", "RefFieldUnannotated.T")] [ExpectedWarning ("IL2079", "RefFieldWithMethods.T", "RefFieldWithFields.T")] - [ExpectedWarning ("IL2079", "RefFieldWithMethods.T", "RefFieldUnannotated.T", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2079", "RefFieldWithMethods.T", "RefFieldWithFields.T", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2079", "RefFieldWithMethods.T", "RefFieldUnannotated.T", Tool.Analyzer, "")] + [ExpectedWarning ("IL2079", "RefFieldWithMethods.T", "RefFieldWithFields.T", Tool.Analyzer, "")] // IL2064's are bugs - shouldn't be unknown values // https://github.com/dotnet/runtime/issues/85465 - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = unannotated.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withMethods.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withFields.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withMethodsAndFields.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withMethodsAndFields.T; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = unannotated.T; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = withMethods.T; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = withFields.T; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = withMethodsAndFields.T; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = withMethodsAndFields.T; static void AssignRefFields ( RefFieldWithMethods target, RefFieldUnannotated unannotated, @@ -265,14 +265,14 @@ static void AssignRefFields ( [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "GetRefWithFields")] [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "GetRefUnannotated")] [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "GetRefWithFields")] - [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "GetRefUnannotated", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "GetRefWithFields", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "GetRefUnannotated", Tool.Analyzer, "")] + [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "GetRefWithFields", Tool.Analyzer, "")] // IL2064's are bugs - shouldn't be unknown values // https://github.com/dotnet/runtime/issues/85465 - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = t; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = t; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = t; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = t; static void AssignRefReturns< T, [DAM (DAMT.PublicMethods)] TM, @@ -348,26 +348,26 @@ static void AssignProperties (RefFieldWithMethods target, } // target.T = x.T - [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropUnannotated.T", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropWithFields.T", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropUnannotated.T", Tool.Analyzer, "")] + [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropWithFields.T", Tool.Analyzer, "")] // target.T = t; - [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropUnannotated.T", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropWithFields.T", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropUnannotated.T", Tool.Analyzer, "")] + [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropWithFields.T", Tool.Analyzer, "")] // target.T = ref x.T [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropUnannotated.T")] [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropWithFields.T")] // ref Type t = ref x.T; target.T = t; // IL2064's are bugs - shouldn't be unknown values // https://github.com/dotnet/runtime/issues/85465 - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = unannotated.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withMethods.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withFields.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withMethodsAndFieldswithMtho.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withMethods.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = unannotated.T; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = withMethods.T; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = withFields.T; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = withMethodsAndFieldswithMtho.T; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = withMethods.T; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = t; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = t; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = t; + [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "")] // target.T = t; static void AssignRefProperties (RefFieldWithMethods target, RefPropUnannotated unannotated = null, RefPropWithMethods withMethods = null, diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs index 8fc0362921be41..2933e51ba7768c 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs @@ -59,8 +59,7 @@ static void TestAllPropagated ([DynamicallyAccessedMembers (DynamicallyAccessedM class AllPropagatedWithDerivedClass { // https://github.com/dotnet/linker/issues/2673 - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll) + "(Type)", nameof (TestSystemTypeBase.BaseType) + ".get", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll) + "(Type)", nameof (TestSystemTypeBase.BaseType) + ".get", Tool.Analyzer, "")] static void TestAllPropagated ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] TestSystemTypeBase derivedType) { derivedType.BaseType.RequiresAll (); @@ -284,7 +283,7 @@ static void EnumerateInterfacesOnBaseTypes ([DynamicallyAccessedMembers (Dynamic } [ExpectedWarning ("IL2070")] - [ExpectedWarning ("IL2075", ProducedBy = Tool.Analyzer)] // ILLink doesn't implement backward branches data flow yet + [ExpectedWarning ("IL2075", Tool.Analyzer, "")] // ILLink doesn't implement backward branches data flow yet static void EnumerateInterfacesOnBaseTypes_Unannotated (Type type) { Type? t = type; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnresolvedMembers.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnresolvedMembers.cs index e32c8727f91e09..130f7ade7aa150 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnresolvedMembers.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnresolvedMembers.cs @@ -45,9 +45,9 @@ static void MethodWithUnresolvedGenericArgument< { } [Kept] - [ExpectedWarning ("IL2066", "TypeWithUnresolvedGenericArgument", ProducedBy = Tool.Trimmer | Tool.Analyzer)] // Local variable type - [ExpectedWarning ("IL2066", "TypeWithUnresolvedGenericArgument", ProducedBy = Tool.Trimmer | Tool.Analyzer)] // Called method declaring type - [ExpectedWarning ("IL2066", nameof (MethodWithUnresolvedGenericArgument), ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2066", "TypeWithUnresolvedGenericArgument", Tool.Trimmer | Tool.Analyzer, "")] // Local variable type + [ExpectedWarning ("IL2066", "TypeWithUnresolvedGenericArgument", Tool.Trimmer | Tool.Analyzer, "")] // Called method declaring type + [ExpectedWarning ("IL2066", nameof (MethodWithUnresolvedGenericArgument), Tool.Trimmer | Tool.Analyzer, "")] static void UnresolvedGenericArgument () { var a = new TypeWithUnresolvedGenericArgument (); @@ -77,7 +77,7 @@ public AttributeWithRequirements ( } [Kept] - [ExpectedWarning ("IL2062", nameof (AttributeWithRequirements), ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2062", nameof (AttributeWithRequirements), Tool.Trimmer | Tool.Analyzer, "")] [KeptAttributeAttribute (typeof (AttributeWithRequirements))] [AttributeWithRequirements (typeof (Dependencies.UnresolvedType))] static void UnresolvedAttributeArgument () @@ -85,7 +85,7 @@ static void UnresolvedAttributeArgument () } [Kept] - [ExpectedWarning ("IL2062", nameof (AttributeWithRequirements.PropertyWithRequirements), ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2062", nameof (AttributeWithRequirements.PropertyWithRequirements), Tool.Trimmer | Tool.Analyzer, "")] [KeptAttributeAttribute (typeof (AttributeWithRequirements))] [AttributeWithRequirements (typeof (EmptyType), PropertyWithRequirements = typeof (Dependencies.UnresolvedType))] static void UnresolvedAttributePropertyValue () @@ -93,7 +93,7 @@ static void UnresolvedAttributePropertyValue () } [Kept] - [ExpectedWarning ("IL2064", nameof (AttributeWithRequirements.FieldWithRequirements), ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2064", nameof (AttributeWithRequirements.FieldWithRequirements), Tool.Trimmer | Tool.Analyzer, "")] [KeptAttributeAttribute (typeof (AttributeWithRequirements))] [AttributeWithRequirements (typeof (EmptyType), FieldWithRequirements = typeof (Dependencies.UnresolvedType))] static void UnresolvedAttributeFieldValue () @@ -104,14 +104,14 @@ static void UnresolvedAttributeFieldValue () static Dependencies.UnresolvedType _unresolvedField; [Kept] - [ExpectedWarning ("IL2072", nameof (Object.GetType), ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (Object.GetType), Tool.Trimmer | Tool.Analyzer, "")] static void UnresolvedObjectGetType () { RequirePublicMethods (_unresolvedField.GetType ()); } [Kept] - [ExpectedWarning ("IL2072", nameof (Object.GetType), ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (Object.GetType), Tool.Trimmer | Tool.Analyzer, "")] static void UnresolvedMethodParameter () { RequirePublicMethods (typeof (Dependencies.UnresolvedType)); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/VirtualMethodHierarchyDataflowAnnotationValidation.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/VirtualMethodHierarchyDataflowAnnotationValidation.cs index 4b73a662347916..7cd16f88aaee6d 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/VirtualMethodHierarchyDataflowAnnotationValidation.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/VirtualMethodHierarchyDataflowAnnotationValidation.cs @@ -633,24 +633,24 @@ class ImplIDamOnAllMissing : IDamOnAll // NativeAOT doesn't validate overrides when accessed through reflection because it's a direct call (non-virtual) // So it doesn't matter that the annotations are not in-sync since the access will validate // the annotations on the implementation method - it doesn't even see the base method in this case. - [ExpectedWarning ("IL2092", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2093", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2092", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2093", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] public static Type AbstractMethod (Type type) => null; // NativeAOT doesn't validate overrides when accessed through reflection because it's a direct call (non-virtual) - [ExpectedWarning ("IL2092", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2093", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2092", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2093", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] public static Type VirtualMethod (Type type) => null; } class ImplIDamOnAllMismatch : IDamOnAll { // NativeAOT doesn't validate overrides when accessed through reflection because it's a direct call (non-virtual) - [ExpectedWarning ("IL2092", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2093", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2092", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2093", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] public static Type AbstractMethod <[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] @@ -660,9 +660,9 @@ public static Type AbstractMethod { return null; } // NativeAOT doesn't validate overrides when accessed through reflection because it's a direct call (non-virtual) - [ExpectedWarning ("IL2092", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2093", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2092", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2093", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] public static Type VirtualMethod <[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] @@ -706,9 +706,9 @@ class ImplIDamOnNoneMatch : IDamOnNone class ImplIDamOnNoneMismatch : IDamOnNone { // NativeAOT doesn't validate overrides when accessed through reflection because it's a direct call (non-virtual) - [ExpectedWarning ("IL2092", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2093", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2092", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2093", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] public static Type AbstractMethod <[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] @@ -718,9 +718,9 @@ public static Type AbstractMethod { return null; } // NativeAOT doesn't validate overrides when accessed through reflection because it's a direct call (non-virtual) - [ExpectedWarning ("IL2092", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2093", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2092", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2093", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] public static Type VirtualMethod <[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] @@ -749,7 +749,7 @@ class BaseInPreservedScope class ImplIAnnotatedMethodsMismatch : Library.IAnnotatedMethods { // NativeAOT doesn't always validate static overrides when accessed through reflection because it's a direct call (non-virtual) - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] public static void GenericWithMethodsStatic () { } [ExpectedWarning ("IL2092")] @@ -771,7 +771,7 @@ public void ParamWithMethods (Type t) { } class ImplIUnannotatedMethodsMismatch : Library.IUnannotatedMethods { // NativeAOT doesn't always validate static overrides when accessed through reflection because it's a direct call (non-virtual) - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] public static void GenericStatic<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { } [ExpectedWarning ("IL2092")] @@ -947,7 +947,7 @@ interface IBaseWithDefault interface IDerivedWithDefault : IBaseWithDefault { [ExpectedWarning ("IL2092")] - [ExpectedWarning ("IL2092", ProducedBy = Tool.Analyzer)] // https://github.com/dotnet/linker/issues/3121 + [ExpectedWarning ("IL2092", Tool.Analyzer, "")] // https://github.com/dotnet/linker/issues/3121 void IBaseWithDefault.DefaultMethod ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { } } @@ -969,9 +969,9 @@ interface IGvmBase class ImplIGvmBase : IGvmBase { // NativeAOT doesn't validate overrides when it can resolve them as direct calls - [ExpectedWarning ("IL2092", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2093", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2092", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2093", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] public Type UnannotatedGvm<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) => null; @@ -1045,8 +1045,8 @@ public override void MethodWithRequires ([DynamicallyAccessedMembers (Dynamicall [ExpectedWarning ("IL2026", nameof (DerivedTypeWithRequires_BaseMethodWithRequires))] [ExpectedWarning ("IL2026", nameof (DerivedTypeWithRequires_BaseMethodWithRequires.MethodWithRequires))] - [ExpectedWarning ("IL3050", nameof (DerivedTypeWithRequires_BaseMethodWithRequires), ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", nameof (DerivedTypeWithRequires_BaseMethodWithRequires.MethodWithRequires), ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3050", nameof (DerivedTypeWithRequires_BaseMethodWithRequires), Tool.NativeAot | Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", nameof (DerivedTypeWithRequires_BaseMethodWithRequires.MethodWithRequires), Tool.NativeAot | Tool.Analyzer, "")] static void Test_DerivedTypeWithRequires_BaseMethodWithRequires () { new DerivedTypeWithRequires_BaseMethodWithRequires ().MethodWithRequires (typeof (int)); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Extensibility/CustomWarningUsage.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Extensibility/CustomWarningUsage.cs index 063038c93eadde..941f6c59e543fa 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Extensibility/CustomWarningUsage.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Extensibility/CustomWarningUsage.cs @@ -10,7 +10,7 @@ namespace Mono.Linker.Tests.Cases.Extensibility [ExpectedNoWarnings] public class CustomWarningUsage { - [ExpectedWarning ("IL2026", "--RUCMethod--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--RUCMethod--", Tool.Analyzer, "")] public static void Main () { new KnownTypeThatShouldWarn (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkXml/LinkXmlErrorCases.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkXml/LinkXmlErrorCases.cs index 074216595ed306..467831cbb69fcd 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkXml/LinkXmlErrorCases.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkXml/LinkXmlErrorCases.cs @@ -17,13 +17,13 @@ namespace Mono.Linker.Tests.Cases.LinkXml [ExpectedWarning ("IL2017", "NonExistentProperty", "TypeWithNoProperties", FileName = "LinkXmlErrorCases.xml", SourceLine = 21, SourceColumn = 8)] [ExpectedWarning ("IL2018", "SetOnlyProperty", "TypeWithProperties", FileName = "LinkXmlErrorCases.xml", SourceLine = 25, SourceColumn = 8)] [ExpectedWarning ("IL2019", "GetOnlyProperty", "TypeWithProperties", FileName = "LinkXmlErrorCases.xml", SourceLine = 26, SourceColumn = 8)] - [ExpectedWarning ("IL2025", "Method", FileName = "LinkXmlErrorCases.xml", SourceLine = 39, SourceColumn = 8, ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2025", "Event", FileName = "LinkXmlErrorCases.xml", SourceLine = 40, SourceColumn = 8, ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2025", "Field", FileName = "LinkXmlErrorCases.xml", SourceLine = 41, SourceColumn = 8, ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2025", "Property", FileName = "LinkXmlErrorCases.xml", SourceLine = 42, SourceColumn = 8, ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2025", "Method", Tool.Trimmer, "", FileName = "LinkXmlErrorCases.xml", SourceLine = 39, SourceColumn = 8)] + [ExpectedWarning ("IL2025", "Event", Tool.Trimmer, "", FileName = "LinkXmlErrorCases.xml", SourceLine = 40, SourceColumn = 8)] + [ExpectedWarning ("IL2025", "Field", Tool.Trimmer, "", FileName = "LinkXmlErrorCases.xml", SourceLine = 41, SourceColumn = 8)] + [ExpectedWarning ("IL2025", "Property", Tool.Trimmer, "", FileName = "LinkXmlErrorCases.xml", SourceLine = 42, SourceColumn = 8)] // NativeAOT doesn't support wildcard * and will skip usages of it, including if they would warn // https://github.com/dotnet/runtime/issues/80466 - [ExpectedWarning ("IL2100", FileName = "LinkXmlErrorCases.xml", SourceLine = 50, SourceColumn = 4, ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2100", Tool.Trimmer, "", FileName = "LinkXmlErrorCases.xml", SourceLine = 50, SourceColumn = 4)] class LinkXmlErrorCases { public static void Main () diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Logging/SourceLines.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Logging/SourceLines.cs index 4da189cced1f87..e6f445dfaca24b 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Logging/SourceLines.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Logging/SourceLines.cs @@ -31,16 +31,16 @@ static Type GetUnknownType () // Analyzer test infrastructure doesn't support ExpectedWarning at the top-level. // This is OK because the test is meant to validate that the ILLink infrastructure produces the right line numbers, // and we have separate tests to check the line number of analyzer warnings. - [ExpectedWarning ("IL2074", nameof (SourceLines) + "." + nameof (type), nameof (SourceLines) + "." + nameof (GetUnknownType) + "()", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2074", nameof (SourceLines) + "." + nameof (type), nameof (SourceLines) + "." + nameof (GetUnknownType) + "()", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2074", nameof (SourceLines) + "." + nameof (type), nameof (SourceLines) + "." + nameof (GetUnknownType) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2074", nameof (SourceLines) + "." + nameof (type), nameof (SourceLines) + "." + nameof (GetUnknownType) + "()", Tool.Analyzer, "")] static void UnrecognizedReflectionPattern () { type = GetUnknownType (); // IL2074 type = GetUnknownType (); // IL2074 } - [ExpectedWarning ("IL2091", "LocalFunction()", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2089", nameof (SourceLines) + "." + nameof (type), "TOuterMethod", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2091", "LocalFunction()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2089", nameof (SourceLines) + "." + nameof (type), "TOuterMethod", Tool.Analyzer, "")] static IEnumerable GenericMethodIteratorWithRequirement<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TOuterMethod> () { LocalFunction (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ActivatorCreateInstance.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ActivatorCreateInstance.cs index a14030d90ad164..4aca2d51861850 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ActivatorCreateInstance.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ActivatorCreateInstance.cs @@ -171,8 +171,8 @@ public FromParameterOnStaticMethodTypeB (int arg) { } } // Small formatting difference - [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, Object[])", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, params Object[])", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, Object[])", Tool.Trimmer, "")] + [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, params Object[])", Tool.Analyzer, "")] [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance), nameof (CultureInfo))] [Kept] private void FromParameterOnInstanceMethod ( @@ -197,8 +197,8 @@ public FromParameterOnInstanceMethodType (int arg, int arg2) { } [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type)")] // Small formatting difference - [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, Object[])", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, params Object[])", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, Object[])", Tool.Trimmer, "")] + [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, params Object[])", Tool.Analyzer, "")] [Kept] private static void FromParameterWithNonPublicConstructors ( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] @@ -375,7 +375,7 @@ private static void WithAssemblyAndNoValueTypeName () [Kept] // Analyzer doesn't handle assembly resolution - [ExpectedWarning ("IL2061", nameof (Activator) + "." + nameof (Activator.CreateInstance), "NonExistingAssembly", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2061", nameof (Activator) + "." + nameof (Activator.CreateInstance), "NonExistingAssembly", Tool.Trimmer, "")] private static void WithNonExistingAssemblyName () { Activator.CreateInstance ("NonExistingAssembly", "Mono.Linker.Tests.Cases.Reflection.ActivatorCreateInstance+WithAssemblyNameParameterless1"); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyMethodInfo.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyMethodInfo.cs index 5fa8b48caddcbe..fadd361a58cef2 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyMethodInfo.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyMethodInfo.cs @@ -84,11 +84,11 @@ public int InstancePropertyViaReflection { [Kept] // https://github.com/dotnet/linker/issues/2669 - [ExpectedWarning ("IL2026", nameof (StaticPropertyExpressionAccess), ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", nameof (StaticPropertyExpressionAccess), Tool.Trimmer, "")] [ExpectedWarning ("IL2026", nameof (StaticPropertyViaReflection))] [ExpectedWarning ("IL2026", nameof (StaticPropertyViaRuntimeMethod))] // https://github.com/dotnet/linker/issues/2669 - [ExpectedWarning ("IL2026", nameof (InstancePropertyExpressionAccess), ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", nameof (InstancePropertyExpressionAccess), Tool.Trimmer, "")] [ExpectedWarning ("IL2026", nameof (InstancePropertyViaReflection))] public static void Test () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodsUsedViaReflection.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodsUsedViaReflection.cs index c91fb020f7feae..01717db24f5662 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodsUsedViaReflection.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodsUsedViaReflection.cs @@ -338,7 +338,7 @@ private void PrivateMethodWithRUC () { } [Kept] // https://github.com/dotnet/linker/issues/2638 - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", Tool.Trimmer, "")] public static void Test () { BindingFlags left = BindingFlags.Instance | BindingFlags.Static; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ObjectGetType.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ObjectGetType.cs index 5d21f678b1dbd5..af03ac42590ff7 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ObjectGetType.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ObjectGetType.cs @@ -297,7 +297,7 @@ public void UnusedMethod () { } [Kept] // https://github.com/dotnet/runtime/issues/93718 // This should not warn - [ExpectedWarning ("IL2075", "GetMethod", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2075", "GetMethod", Tool.Trimmer | Tool.NativeAot, "")] static void TestStruct (BasicAnnotatedStruct instance) { instance.GetType ().GetMethod ("UsedMethod"); @@ -1409,7 +1409,7 @@ public void Method () { } [Kept] // https://github.com/dotnet/runtime/issues/93719 - [ExpectedWarning ("IL2075", nameof (Type.GetType), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2075", nameof (Type.GetType), Tool.Trimmer | Tool.NativeAot, "")] public static void Test () { foreach (var instance in GetInstances ()) { 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 13ecc2ec29068c..c1f0b37ebaab54 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchyReflectionWarnings.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchyReflectionWarnings.cs @@ -250,7 +250,7 @@ public event MyEventHandler RUCEvent { [Kept] [ExpectedWarning ("IL2112", nameof (AnnotatedPublicEvents), "--RUC on add_RUCEvent--")] // https://github.com/dotnet/runtime/issues/100499 - [ExpectedWarning ("IL2112", nameof (AnnotatedPublicEvents), "--RUC on add_RUCEvent--", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2112", [nameof (AnnotatedPublicEvents), "--RUC on add_RUCEvent--"], Tool.Trimmer, "")] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] [RequiresUnreferencedCode ("--RUC on add_RUCEvent--")] add { } @@ -313,7 +313,7 @@ class DerivedFromAnnotatedPublicParameterlessConstructor : AnnotatedPublicParame [Kept] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] [ExpectedWarning ("IL2112", "--RUC on DerivedFromAnnotatedPublicParameterlessConstructor()--")] - [ExpectedWarning ("IL2112", "--RUC on DerivedFromAnnotatedPublicParameterlessConstructor()--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "--RUC on DerivedFromAnnotatedPublicParameterlessConstructor()--", Tool.Trimmer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("--RUC on DerivedFromAnnotatedPublicParameterlessConstructor()--")] public DerivedFromAnnotatedPublicParameterlessConstructor () { } @@ -704,7 +704,7 @@ public class Base // https://github.com/dotnet/runtime/issues/86580 // Compare to the case above - the only difference is the type of the field // and it causes different warnings to be produced. - // [ExpectedWarning ("IL2112", "--RUCOnVirtualMethodDerivedAnnotated.Base.RUCVirtualMethod--")] + // [ExpectedSharedWarning ("IL2112", "--RUCOnVirtualMethodDerivedAnnotated.Base.RUCVirtualMethod--")] public virtual void RUCVirtualMethod () { } } @@ -712,7 +712,7 @@ public virtual void RUCVirtualMethod () { } [KeptMember (".ctor()")] [KeptBaseType (typeof (Base))] // https://github.com/dotnet/runtime/issues/86580 - [ExpectedWarning ("IL2113", "--RUCOnVirtualMethodDerivedAnnotated.Base.RUCVirtualMethod--", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2113", "--RUCOnVirtualMethodDerivedAnnotated.Base.RUCVirtualMethod--", Tool.Trimmer, "")] public class Derived : Base { [Kept] @@ -756,7 +756,7 @@ public virtual void VirtualMethodWithRequires () { } [KeptBaseType (typeof (AnnotatedBase))] [KeptMember (".ctor()")] // https://github.com/dotnet/runtime/issues/86580 - [ExpectedWarning ("IL2113", "--AnnotatedBase.VirtualMethodWithRequires--", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2113", "--AnnotatedBase.VirtualMethodWithRequires--", Tool.Trimmer, "")] class Derived : AnnotatedBase { [Kept] @@ -956,7 +956,7 @@ static void LocalFunctionWithDAMInner ([DynamicallyAccessedMembers(DynamicallyAc [Kept] [KeptAttributeAttribute (typeof (IteratorStateMachineAttribute))] - [ExpectedWarning ("IL2119", nameof (IteratorWithGenericDAM), CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2119", nameof (IteratorWithGenericDAM), Tool.Trimmer, "", CompilerGeneratedCode = true)] static IEnumerable IteratorWithGenericDAM< [KeptAttributeAttribute(typeof(DynamicallyAccessedMembersAttribute))] [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T> () @@ -968,7 +968,7 @@ static IEnumerable IteratorWithGenericDAM< [Kept] [KeptAttributeAttribute (typeof (AsyncStateMachineAttribute))] [KeptAttributeAttribute (typeof (DebuggerStepThroughAttribute))] - [ExpectedWarning ("IL2119", nameof (AsyncWithGenericDAM), CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2119", nameof (AsyncWithGenericDAM), Tool.Trimmer, "", CompilerGeneratedCode = true)] static async Task AsyncWithGenericDAM< [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() @@ -979,7 +979,7 @@ static async Task AsyncWithGenericDAM< [Kept] [KeptAttributeAttribute (typeof (AsyncIteratorStateMachineAttribute))] - [ExpectedWarning("IL2119", nameof(AsyncIteratorWithGenericDAM), CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + [ExpectedWarning("IL2119", nameof(AsyncIteratorWithGenericDAM), Tool.Trimmer, "", CompilerGeneratedCode = true)] static async IAsyncEnumerable AsyncIteratorWithGenericDAM< [KeptAttributeAttribute(typeof(DynamicallyAccessedMembersAttribute))] [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs index 352be76d77910b..981ad6227ceb8d 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs @@ -331,9 +331,9 @@ public class OverloadWith5ParametersWithIgnoreCase { } [Kept] // Small difference in formatting between analyzer/NativeAOT/linker - [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2096", "'System.Type.GetType(String,Func`2,Func`4,Boolean,Boolean)'", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", Tool.Trimmer, "")] + [ExpectedWarning ("IL2096", "'System.Type.GetType(String,Func`2,Func`4,Boolean,Boolean)'", Tool.NativeAot, "")] + [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", Tool.Analyzer, "")] static void TestTypeOverloadWith5ParametersWithIgnoreCase () { const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+OverloadWith5ParametersWithIgnoreCase"; @@ -384,9 +384,9 @@ static void TestUnknownIgnoreCase3Params (int num) [Kept] // Small difference in formatting between analyzer/NativeAOT/linker - [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2096", "'System.Type.GetType(String,Func`2,Func`4,Boolean,Boolean)'", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", Tool.Trimmer, "")] + [ExpectedWarning ("IL2096", "'System.Type.GetType(String,Func`2,Func`4,Boolean,Boolean)'", Tool.NativeAot, "")] + [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", Tool.Analyzer, "")] static void TestUnknownIgnoreCase5Params (int num) { const string reflectionTypeKeptString = "mono.linker.tests.cases.reflection.TypeUsedViaReflection+CaseUnknown2, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs index d9536b9358109a..453f5661502ff2 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs @@ -28,8 +28,8 @@ public static void Main () } [ExpectedWarning ("IL2026", "Message for --RequiresWithMessageOnly--.")] - [ExpectedWarning ("IL3002", "Message for --RequiresWithMessageOnly--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --RequiresWithMessageOnly--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message for --RequiresWithMessageOnly--.", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Message for --RequiresWithMessageOnly--.", Tool.Analyzer | Tool.NativeAot, "")] static void TestRequiresWithMessageOnlyOnMethod () { RequiresWithMessageOnly (); @@ -43,8 +43,8 @@ static void RequiresWithMessageOnly () } [ExpectedWarning ("IL2026", "Message for --RequiresWithMessageAndUrl--.", "https://helpurl")] - [ExpectedWarning ("IL3002", "Message for --RequiresWithMessageAndUrl--.", "https://helpurl", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --RequiresWithMessageAndUrl--.", "https://helpurl", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message for --RequiresWithMessageAndUrl--.", "https://helpurl", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Message for --RequiresWithMessageAndUrl--.", "https://helpurl", Tool.Analyzer | Tool.NativeAot, "")] static void TestRequiresWithMessageAndUrlOnMethod () { RequiresWithMessageAndUrl (); @@ -58,8 +58,8 @@ static void RequiresWithMessageAndUrl () } [ExpectedWarning ("IL2026", "Message for --ConstructorRequires--.")] - [ExpectedWarning ("IL3002", "Message for --ConstructorRequires--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --ConstructorRequires--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message for --ConstructorRequires--.", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Message for --ConstructorRequires--.", Tool.Analyzer | Tool.NativeAot, "")] static void TestRequiresOnConstructor () { new ConstructorRequires (); @@ -77,10 +77,10 @@ public ConstructorRequires () [ExpectedWarning ("IL2026", "Message for --getter PropertyRequires--.")] [ExpectedWarning ("IL2026", "Message for --setter PropertyRequires--.")] - [ExpectedWarning ("IL3002", "Message for --getter PropertyRequires--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "Message for --setter PropertyRequires--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --getter PropertyRequires--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --setter PropertyRequires--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message for --getter PropertyRequires--.", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "Message for --setter PropertyRequires--.", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Message for --getter PropertyRequires--.", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Message for --setter PropertyRequires--.", Tool.Analyzer | Tool.NativeAot, "")] static void TestRequiresOnPropertyGetterAndSetter () { _ = PropertyRequires; @@ -107,8 +107,8 @@ static void WarningMessageWithoutEndingPeriod () } [ExpectedWarning ("IL2026", "Adds a trailing period to this message.")] - [ExpectedWarning ("IL3002", "Adds a trailing period to this message.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Adds a trailing period to this message.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Adds a trailing period to this message.", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Adds a trailing period to this message.", Tool.Analyzer | Tool.NativeAot, "")] static void TestThatTrailingPeriodIsAddedToMessage () { WarningMessageWithoutEndingPeriod (); @@ -123,8 +123,8 @@ static void WarningMessageEndsWithPeriod () [LogDoesNotContain ("Does not add a period to this message..")] [ExpectedWarning ("IL2026", "Does not add a period to this message.")] - [ExpectedWarning ("IL3002", "Does not add a period to this message.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Does not add a period to this message.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Does not add a period to this message.", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Does not add a period to this message.", Tool.Analyzer | Tool.NativeAot, "")] static void TestThatTrailingPeriodIsNotDuplicatedInWarningMessage () { WarningMessageEndsWithPeriod (); @@ -157,11 +157,11 @@ static event EventHandler EventToTestAdd { static event EventHandler AnnotatedEvent; [ExpectedWarning ("IL2026", "--EventToTestRemove.remove--")] - [ExpectedWarning ("IL3002", "--EventToTestRemove.remove--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--EventToTestRemove.remove--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--EventToTestRemove.remove--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--EventToTestRemove.remove--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--EventToTestAdd.add--")] - [ExpectedWarning ("IL3002", "--EventToTestAdd.add--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--EventToTestAdd.add--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--EventToTestAdd.add--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--EventToTestAdd.add--", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { EventToTestRemove -= (sender, e) => { }; @@ -181,8 +181,8 @@ public static void GenericTypeWithStaticMethodWhichRequires () { } } [ExpectedWarning ("IL2026", "--GenericTypeWithStaticMethodWhichRequires--")] - [ExpectedWarning ("IL3002", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--GenericTypeWithStaticMethodWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--GenericTypeWithStaticMethodWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] public static void GenericTypeWithStaticMethodViaLdftn () { var _ = new Action (GenericWithStaticMethod.GenericTypeWithStaticMethodWhichRequires); @@ -208,8 +208,8 @@ static void Requires () { } [RequiresAssemblyFiles ("--PropertyRequires--")] static int PropertyRequires { get; set; } - [ExpectedWarning ("IL3002", "--PropertyRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--PropertyRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--PropertyRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--PropertyRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestProperty () { var a = PropertyRequires; @@ -219,11 +219,11 @@ static void TestProperty () [RequiresAssemblyFiles ("--EventRequires--")] static event EventHandler EventRequires; - [ExpectedWarning ("IL3002", "--EventRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--EventRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--EventRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--EventRequires--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--RequiresOnEventLambda--")] - [ExpectedWarning ("IL3002", "--RequiresOnEventLambda--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--RequiresOnEventLambda--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--RequiresOnEventLambda--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--RequiresOnEventLambda--", Tool.Analyzer | Tool.NativeAot, "")] static void TestEvent () { EventRequires += (object sender, EventArgs e) => throw new NotImplementedException (); @@ -237,7 +237,7 @@ static void TestEvent () EventRequires (null, null); // no warning on invocation } - [ExpectedWarning("IL3002", "--Requires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning("IL3002", "--Requires--", Tool.Analyzer | Tool.NativeAot, "")] public static void Test() { Requires (); @@ -251,7 +251,7 @@ class DynamicCodeOnly [RequiresDynamicCode ("--Requires--")] static void Requires () { } - [ExpectedWarning ("IL3050", "--Requires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--Requires--", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { Requires (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs index 2b2c0438c1d01d..71af8ce1374138 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs @@ -24,10 +24,9 @@ public static void Main () class ReflectionAccessFromStateMachine { [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", Tool.Trimmer, "", CompilerGeneratedCode = true)] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations), CompilerGeneratedCode = true)] static IEnumerable TestIterator () { @@ -45,10 +44,9 @@ static IEnumerable TestIteratorWithRUC () } [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", Tool.Trimmer, "", CompilerGeneratedCode = true)] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations), CompilerGeneratedCode = true)] static async void TestAsync () { @@ -66,11 +64,11 @@ static async void TestAsyncWithRUC () } [ExpectedWarning ("IL2026", "--TestIteratorWithRUC--")] - [ExpectedWarning ("IL3002", "--TestIteratorWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--TestIteratorWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--TestIteratorWithRUC--", Tool.NativeAot | Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--TestIteratorWithRUC--", Tool.NativeAot | Tool.Analyzer, "")] [ExpectedWarning ("IL2026", "--TestAsyncWithRUC--")] - [ExpectedWarning ("IL3002", "--TestAsyncWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--TestAsyncWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--TestAsyncWithRUC--", Tool.NativeAot | Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--TestAsyncWithRUC--", Tool.NativeAot | Tool.Analyzer, "")] public static void Test () { TestIterator ().GetEnumerator ().MoveNext (); // Must actually use the enumerator, otherwise NativeAOT will trim the implementation @@ -85,10 +83,9 @@ class ReflectionAccessFromLocalFunction static void TestLocalFunction () { [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", Tool.Trimmer, "")] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations))] void LocalFunction () { @@ -98,8 +95,8 @@ void LocalFunction () } [ExpectedWarning ("IL2026", "--LocalFunction--")] - [ExpectedWarning ("IL3002", "--LocalFunction--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--LocalFunction--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--LocalFunction--", Tool.NativeAot | Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--LocalFunction--", Tool.NativeAot | Tool.Analyzer, "")] static void TestLocalFunctionWithRUC () { [RequiresUnreferencedCode ("--LocalFunction--")] @@ -125,8 +122,8 @@ void LocalFunction () } [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRUC--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "")] public static void Test () { TestLocalFunction (); @@ -141,10 +138,9 @@ static void TestLambda () { var lambda = [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", Tool.Trimmer, "")] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations))] () => { typeof (TypeWithMethodWithRequires).RequiresAll (); @@ -153,8 +149,8 @@ static void TestLambda () } [ExpectedWarning ("IL2026", "--TestLambdaInMethodWithRUC--")] - [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "")] static void TestLambdaWithRUC () { var lambda = @@ -168,8 +164,8 @@ static void TestLambdaWithRUC () } [ExpectedWarning ("IL2026", "--TestLambdaWithRUCLdftn--")] - [ExpectedWarning ("IL3002", "--TestLambdaWithRUCLdftn--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--TestLambdaWithRUCLdftn--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--TestLambdaWithRUCLdftn--", Tool.NativeAot | Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--TestLambdaWithRUCLdftn--", Tool.NativeAot | Tool.Analyzer, "")] static void TestLambdaWithRUCLdftn () { var lambda = @@ -196,8 +192,8 @@ static void TestLambdaInMethodWithRUC () } [ExpectedWarning ("IL2026", "--TestLambdaInMethodWithRUC--")] - [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "")] public static void Test () { TestLambda (); @@ -224,8 +220,8 @@ public static void MethodWithRequires () public static void MethodWithAnnotations ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type t) { } [ExpectedWarning ("IL2026", "--MethodWithLocalFunctionWithRUC.LocalFunction--")] - [ExpectedWarning ("IL3002", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithLocalFunctionWithRUC.LocalFunction--", Tool.NativeAot | Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--MethodWithLocalFunctionWithRUC.LocalFunction--", Tool.NativeAot | Tool.Analyzer, "")] public static void MethodWithLocalFunctionWithRUC () { [RequiresUnreferencedCode ("--MethodWithLocalFunctionWithRUC.LocalFunction--")] @@ -239,8 +235,8 @@ void LocalFunction () public static void MethodWithLocalFunctionCallsRUC () { [ExpectedWarning ("IL2026", "--MethodWithRUC--")] - [ExpectedWarning ("IL3002", "--MethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--MethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "")] void LocalFunction () => MethodWithRUC (); LocalFunction (); } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAccessedThrough.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAccessedThrough.cs index 727463e800801e..8a43183e35ec68 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 @@ -43,8 +43,8 @@ static void RequiresOnlyThroughReflection () // https://github.com/dotnet/linker/issues/2739 - the discussion there explains why (at least for now) we don't produce // RAF and RDC warnings from the analyzer in these cases. [ExpectedWarning ("IL2026", "--RequiresOnlyThroughReflection--")] - [ExpectedWarning ("IL3002", "--RequiresOnlyThroughReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--RequiresOnlyThroughReflection--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--RequiresOnlyThroughReflection--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--RequiresOnlyThroughReflection--", Tool.NativeAot, "")] static void TestRequiresOnlyThroughReflection () { typeof (RequiresAccessedThrough) @@ -62,8 +62,8 @@ public static void RequiresOnlyThroughReflection () } [ExpectedWarning ("IL2026", "--GenericType.RequiresOnlyThroughReflection--")] - [ExpectedWarning ("IL3002", "--GenericType.RequiresOnlyThroughReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--GenericType.RequiresOnlyThroughReflection--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--GenericType.RequiresOnlyThroughReflection--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--GenericType.RequiresOnlyThroughReflection--", Tool.NativeAot, "")] public static void Test () { typeof (AccessedThroughReflectionOnGenericType) @@ -75,7 +75,7 @@ public static void Test () class AccessThroughSpecialAttribute { // https://github.com/dotnet/linker/issues/1873 - // [ExpectedWarning ("IL2026", "--DebuggerProxyType.Method--")] + // [ExpectedSharedWarning ("IL2026", "--DebuggerProxyType.Method--")] [DebuggerDisplay ("Some{*}value")] class TypeWithDebuggerDisplay { @@ -104,12 +104,12 @@ public PInvokeReturnType () { } } // https://github.com/mono/linker/issues/2116 - [ExpectedWarning ("IL2026", "--PInvokeReturnType.ctor--", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", "--PInvokeReturnType.ctor--", Tool.Trimmer, "")] [DllImport ("nonexistent")] static extern PInvokeReturnType PInvokeReturnsType (); // Analyzer doesn't support IL2050 yet - [ExpectedWarning ("IL2050", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2050", Tool.Trimmer | Tool.NativeAot, "")] public static void Test () { PInvokeReturnsType (); @@ -136,8 +136,8 @@ class NewConstraintTestAnnotatedType [ExpectedWarning ("IL2026", "--NewConstraintTestType.ctor--")] [ExpectedWarning ("IL2026", "--NewConstraintTestAnnotatedType--")] - [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () where T : new() { GenericMethod (); @@ -156,8 +156,8 @@ public static void DoNothing () { } [ExpectedWarning ("IL2026", "--NewConstraintTestType.ctor--")] [ExpectedWarning ("IL2026", "--NewConstraintTestAnnotatedType--")] - [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] public static void TestNewConstraintOnTypeParameter () where T : new() { _ = new NewConstraintOnTypeParameter (); @@ -166,8 +166,8 @@ public static void DoNothing () { } } [ExpectedWarning ("IL2026", "--AnnotatedMethod--")] - [ExpectedWarning ("IL3002", "--AnnotatedMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AnnotatedMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AnnotatedMethod--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AnnotatedMethod--", Tool.Analyzer | Tool.NativeAot, "")] public static void TestNewConstraintOnTypeParameterInAnnotatedMethod () { AnnotatedMethod (); @@ -191,8 +191,8 @@ public static void TestNewConstraintOnTypeParameterInAnnotatedType () [RequiresUnreferencedCode ("--AnnotatedType--")] class AnnotatedType { - [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] public static void Method () { _ = new NewConstraintOnTypeParameter (); @@ -202,8 +202,8 @@ public static void Method () [ExpectedWarning ("IL2026", "--NewConstraintTestType.ctor--")] [ExpectedWarning ("IL2026", "--NewConstraintTestAnnotatedType--")] - [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] public static void TestNewConstraintOnTypeParameterOfStaticType () where T : new() { NewConstraintOnTypeParameterOfStaticType.DoNothing (); @@ -224,11 +224,11 @@ static bool PropertyWithLdToken { } [ExpectedWarning ("IL2026", "--PropertyWithLdToken.get--")] - [ExpectedWarning ("IL2026", "--PropertyWithLdToken.get--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--PropertyWithLdToken.get--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--PropertyWithLdToken.get--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--PropertyWithLdToken.get--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--PropertyWithLdToken.get--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--PropertyWithLdToken.get--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--PropertyWithLdToken.get--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--PropertyWithLdToken.get--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--PropertyWithLdToken.get--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--PropertyWithLdToken.get--", Tool.NativeAot, "")] static void TestPropertyLdToken () { Expression> getter = () => PropertyWithLdToken; @@ -242,8 +242,8 @@ static void MethodWithLdToken () } [ExpectedWarning ("IL2026", "--MethodWithLdToken--")] - [ExpectedWarning ("IL3002", "--MethodWithLdToken--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithLdToken--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithLdToken--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithLdToken--", Tool.Analyzer | Tool.NativeAot, "")] static void TestMethodLdToken () { Expression e = () => MethodWithLdToken (); @@ -257,7 +257,7 @@ class FieldWithLdTokenType } [ExpectedWarning ("IL2026", "--FieldWithLdToken--")] - [ExpectedWarning ("IL3050", "--FieldWithLdToken--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--FieldWithLdToken--", Tool.Analyzer | Tool.NativeAot, "")] static void TestFieldLdToken () { Expression> f = () => FieldWithLdTokenType.Field; @@ -281,16 +281,16 @@ static void MethodWithDelegate () } [ExpectedWarning ("IL2026", "--MethodWithDelegate--")] - [ExpectedWarning ("IL3002", "--MethodWithDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithDelegate--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithDelegate--", Tool.Analyzer | Tool.NativeAot, "")] static void TestMethodWithDelegate () { Action a = MethodWithDelegate; } [ExpectedWarning ("IL2026", "--LambdaThroughDelegate--")] - [ExpectedWarning ("IL3002", "--LambdaThroughDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--LambdaThroughDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--LambdaThroughDelegate--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--LambdaThroughDelegate--", Tool.Analyzer | Tool.NativeAot, "")] static void LambdaThroughDelegate () { Action a = @@ -303,8 +303,8 @@ static void LambdaThroughDelegate () } [ExpectedWarning ("IL2026", "--LocalFunctionThroughDelegate--")] - [ExpectedWarning ("IL3002", "--LocalFunctionThroughDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--LocalFunctionThroughDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--LocalFunctionThroughDelegate--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--LocalFunctionThroughDelegate--", Tool.Analyzer | Tool.NativeAot, "")] static void LocalFunctionThroughDelegate () { Action a = Local; @@ -341,15 +341,15 @@ private Target (int i) { } private static void MethodRequires () { } } - [ExpectedWarning ("IL2026", "--Target.MethodRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--Target.MethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--Target.MethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--Target.MethodRequires--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--Target.MethodRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--Target.MethodRequires--", Tool.NativeAot, "")] [UnsafeAccessor (UnsafeAccessorKind.StaticMethod)] extern static void MethodRequires (Target target); - [ExpectedWarning ("IL2026", "--Target..ctor--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--Target..ctor--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--Target..ctor--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--Target..ctor--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--Target..ctor--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--Target..ctor--", Tool.NativeAot, "")] [UnsafeAccessor (UnsafeAccessorKind.Constructor)] extern static Target Constructor (int i); @@ -367,22 +367,22 @@ private void InstanceMethod () { } private int InstanceField; } - [ExpectedWarning ("IL2026", "--TargetWitRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--TargetWitRequires--", Tool.Trimmer | Tool.NativeAot, "")] [UnsafeAccessor (UnsafeAccessorKind.Constructor)] extern static TargetWithRequires TargetRequiresConstructor (); - [ExpectedWarning ("IL2026", "--TargetWitRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--TargetWitRequires--", Tool.Trimmer | Tool.NativeAot, "")] [UnsafeAccessor (UnsafeAccessorKind.StaticMethod, Name = "StaticMethod")] extern static void TargetRequiresStaticMethod (TargetWithRequires target); // For trimmer this is a reflection access to an instance method - and as such it must warn (since it's in theory possible // to invoke the method via reflection on a null instance) // For NativeAOT this is a direct call to an instance method (there's no reflection involved) and as such it doesn't need to warn - [ExpectedWarning ("IL2026", "--TargetWitRequires--", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", "--TargetWitRequires--", Tool.Trimmer, "")] [UnsafeAccessor (UnsafeAccessorKind.Method, Name = "InstanceMethod")] extern static void TargetRequiresInstanceMethod (TargetWithRequires target); - [ExpectedWarning ("IL2026", "--TargetWitRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--TargetWitRequires--", Tool.Trimmer | Tool.NativeAot, "")] [UnsafeAccessor (UnsafeAccessorKind.StaticField, Name = "StaticField")] extern static ref int TargetRequiresStaticField (TargetWithRequires target); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs index 4653f445cabb39..94249d6af5b6f0 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs @@ -26,87 +26,87 @@ class RequiresAttributeMismatch // The analyzer matches this behavior, treating the get/set methods as annotated if the property is annotated, // and warning only on the get/set methods. [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set")] - [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.get")] - [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.set")] - [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.set")] - [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualMethod()")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualMethod()")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualMethod()")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedClassWithRequires.VirtualMethod()")] - [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "DerivedClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "DerivedClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "IBaseWithRequires.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "IBaseWithRequires.PropertyAnnotationInAccesor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set")] - [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "IBaseWithRequires.Method()")] - [ExpectedWarning ("IL3002", "IBaseWithRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "IBaseWithRequires.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "IBaseWithRequires.Method()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "IBaseWithRequires.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.Method()")] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "ImplementationClassWithRequires.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.Method()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "ImplementationClassWithRequires.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3002", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationClassWithRequiresInSource.Method()")] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "ImplementationClassWithRequiresInSource.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.Method()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "ImplementationClassWithRequiresInSource.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.set", Tool.NativeAot, "")] public static void Main () { @@ -174,8 +174,8 @@ class DerivedClassWithRequires : BaseClassWithoutRequires [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] [ExpectedWarning ("IL2046", "DerivedClassWithRequires.VirtualMethod()", "BaseClassWithoutRequires.VirtualMethod()")] - [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualMethod()", "BaseClassWithoutRequires.VirtualMethod()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "DerivedClassWithRequires.VirtualMethod()", "BaseClassWithoutRequires.VirtualMethod()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualMethod()", "BaseClassWithoutRequires.VirtualMethod()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "DerivedClassWithRequires.VirtualMethod()", "BaseClassWithoutRequires.VirtualMethod()", Tool.Analyzer | Tool.NativeAot, "")] public override void VirtualMethod () { } @@ -183,8 +183,8 @@ public override void VirtualMethod () private string name; public override string VirtualPropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message")] [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] @@ -194,9 +194,9 @@ public override string VirtualPropertyAnnotationInAccesor { [RequiresAssemblyFiles ("Message")] public override string VirtualPropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithoutRequires.VirtualPropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithoutRequires.VirtualPropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithoutRequires.VirtualPropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithoutRequires.VirtualPropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -237,8 +237,8 @@ public static void Test() class DerivedClassWithoutRequires : BaseClassWithRequires { [ExpectedWarning ("IL2046", "DerivedClassWithoutRequires.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()")] - [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "DerivedClassWithoutRequires.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "DerivedClassWithoutRequires.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", Tool.Analyzer | Tool.NativeAot, "")] public override void VirtualMethod () { } @@ -246,24 +246,24 @@ public override void VirtualMethod () private string name; public override string VirtualPropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] get { return name; } set { name = value; } } public override string VirtualPropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] set; } public override string VirtualPropertyAnnotationInPropertyAndAccessor { [ExpectedWarning ("IL2046", "VirtualPropertyAnnotationInPropertyAndAccessor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInPropertyAndAccessor", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInPropertyAndAccessor", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -271,8 +271,8 @@ public override string VirtualPropertyAnnotationInPropertyAndAccessor { class DerivedClassWithAllWarnings : BaseClassWithRequires { [ExpectedWarning ("IL2046", "DerivedClassWithAllWarnings.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()")] - [ExpectedWarning ("IL3003", "DerivedClassWithAllWarnings.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "DerivedClassWithAllWarnings.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithAllWarnings.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "DerivedClassWithAllWarnings.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", Tool.Analyzer | Tool.NativeAot, "")] public override void VirtualMethod () { } @@ -282,12 +282,12 @@ public override void VirtualMethod () [RequiresAssemblyFiles ("Message")] public override string VirtualPropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3051", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3051", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] get { return name; } [RequiresAssemblyFiles ("Message")] [RequiresUnreferencedCode ("Message")] [ExpectedWarning ("IL2046", "VirtualPropertyAnnotationInAccesor.set", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.set")] - [ExpectedWarning ("IL3003", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.set", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.set", Tool.Analyzer | Tool.NativeAot, "")] set { name = value; } } @@ -304,7 +304,7 @@ public override string VirtualPropertyAnnotationInProperty { public override string VirtualPropertyAnnotationInPropertyAndAccessor { [ExpectedWarning ("IL2046", "VirtualPropertyAnnotationInPropertyAndAccessor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3003", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", Tool.Analyzer | Tool.NativeAot, "")] get; [RequiresAssemblyFiles ("Message")] [RequiresUnreferencedCode ("Message")] @@ -357,8 +357,8 @@ class ImplementationClassWithRequires : IBaseWithoutRequires [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] [ExpectedWarning ("IL2046", "ImplementationClassWithRequires.Method()", "IBaseWithoutRequires.Method()")] - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.Method()", "IBaseWithoutRequires.Method()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithRequires.Method()", "IBaseWithoutRequires.Method()", Tool.Analyzer | Tool.NativeAot, "")] public void Method () { } @@ -366,8 +366,8 @@ public void Method () private string name; public string PropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message")] [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] @@ -376,23 +376,23 @@ public string PropertyAnnotationInAccesor { } [RequiresAssemblyFiles ("Message")] - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", Tool.Analyzer, "")] public string PropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", Tool.NativeAot | Tool.Analyzer, "")] get; - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", Tool.NativeAot | Tool.Analyzer, "")] set; } [RequiresAssemblyFiles ("Message")] - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", Tool.Analyzer, "")] public string PropertyAnnotationInPropertyAndAccessor { [RequiresAssemblyFiles ("Message")] [RequiresUnreferencedCode ("Message")] [ExpectedWarning ("IL2046", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -403,12 +403,12 @@ class ExplicitImplementationClassWithRequires : IBaseWithoutRequires [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] // ILLink member string format includes namespace of explicit interface method. - [ExpectedWarning ("IL2046", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2046", "ExplicitImplementationClassWithRequires.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithRequires.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3051", "IBaseWithoutRequires.Method()", "ExplicitImplementationClassWithRequires.IBaseWithoutRequires.Method()", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2046", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", Tool.NativeAot, "")] + [ExpectedWarning ("IL2046", "ExplicitImplementationClassWithRequires.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", Tool.Analyzer, "")] + [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithRequires.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", Tool.Analyzer, "")] + [ExpectedWarning ("IL3051", "IBaseWithoutRequires.Method()", "ExplicitImplementationClassWithRequires.IBaseWithoutRequires.Method()", Tool.Analyzer, "")] void IBaseWithoutRequires.Method () { } @@ -416,8 +416,8 @@ void IBaseWithoutRequires.Method () private string name; string IBaseWithoutRequires.PropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message")] [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] @@ -426,23 +426,23 @@ string IBaseWithoutRequires.PropertyAnnotationInAccesor { } [RequiresAssemblyFiles ("Message")] - [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", Tool.Analyzer, "")] string IBaseWithoutRequires.PropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] set; } [RequiresAssemblyFiles ("Message")] - [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", Tool.Analyzer, "")] string IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor { [RequiresAssemblyFiles ("Message")] [RequiresUnreferencedCode ("Message")] [ExpectedWarning ("IL2046", "PropertyAnnotationInPropertyAndAccessor.get", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor.get", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor.get", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -450,8 +450,8 @@ string IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor { class ImplementationClassWithoutRequires : IBaseWithRequires { [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequires.Method()", "IBaseWithRequires.Method()")] - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.Method()", "IBaseWithRequires.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequires.Method()", "IBaseWithRequires.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.Method()", "IBaseWithRequires.Method()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequires.Method()", "IBaseWithRequires.Method()", Tool.Analyzer | Tool.NativeAot, "")] public void Method () { } @@ -459,28 +459,28 @@ public void Method () private string name; public string PropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequires.PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequires.PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequires.PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] get { return name; } set { name = value; } } - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", Tool.Analyzer, "")] public string PropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] set; } - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", Tool.Analyzer, "")] public string PropertyAnnotationInPropertyAndAccessor { [RequiresAssemblyFiles ("Message")] [RequiresUnreferencedCode ("Message")] [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.get")] get; [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.set", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set")] - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.set", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.set", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -488,12 +488,12 @@ public string PropertyAnnotationInPropertyAndAccessor { class ExplicitImplementationClassWithoutRequires : IBaseWithRequires { // ILLink member string format includes namespace of explicit interface method. - [ExpectedWarning ("IL2046", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.Method()", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3003", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3051", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2046", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.IBaseWithRequires.Method()", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3003", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.IBaseWithRequires.Method()", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3051", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.IBaseWithRequires.Method()", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2046", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.Method()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3003", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.Method()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.Method()", Tool.NativeAot, "")] + [ExpectedWarning ("IL2046", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.IBaseWithRequires.Method()", Tool.Analyzer, "")] + [ExpectedWarning ("IL3003", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.IBaseWithRequires.Method()", Tool.Analyzer, "")] + [ExpectedWarning ("IL3051", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.IBaseWithRequires.Method()", Tool.Analyzer, "")] void IBaseWithRequires.Method () { } @@ -501,26 +501,26 @@ void IBaseWithRequires.Method () private string name; string IBaseWithRequires.PropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] get { return name; } set { name = value; } } - [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", Tool.Analyzer, "")] string IBaseWithRequires.PropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] set; } - [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", Tool.Analyzer, "")] string IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor { - [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", Tool.Analyzer | Tool.NativeAot, "")] get; [ExpectedWarning ("IL2046", "PropertyAnnotationInPropertyAndAccessor.set", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set")] - [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor.set", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor.set", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -528,8 +528,8 @@ string IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor { class ImplementationClassWithoutRequiresInSource : ReferenceInterfaces.IBaseWithRequiresInReference { [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequiresInSource.Method()", "IBaseWithRequiresInReference.Method()")] - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.Method()", "IBaseWithRequiresInReference.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequiresInSource.Method()", "IBaseWithRequiresInReference.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.Method()", "IBaseWithRequiresInReference.Method()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequiresInSource.Method()", "IBaseWithRequiresInReference.Method()", Tool.Analyzer | Tool.NativeAot, "")] public void Method () { } @@ -537,17 +537,17 @@ public void Method () private string name; public string PropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithRequiresInReference.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithRequiresInReference.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithRequiresInReference.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithRequiresInReference.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithRequiresInReference.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] get { return name; } set { name = value; } } - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInProperty", "IBaseWithRequiresInReference.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInProperty", "IBaseWithRequiresInReference.PropertyAnnotationInProperty", Tool.Analyzer, "")] public string PropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInProperty.get", "IBaseWithRequiresInReference.PropertyAnnotationInProperty.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInProperty.get", "IBaseWithRequiresInReference.PropertyAnnotationInProperty.get", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInProperty.set", "IBaseWithRequiresInReference.PropertyAnnotationInProperty.set", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInProperty.set", "IBaseWithRequiresInReference.PropertyAnnotationInProperty.set", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -555,8 +555,8 @@ public string PropertyAnnotationInProperty { class ImplementationClassWithRequiresInSource : ReferenceInterfaces.IBaseWithoutRequiresInReference { [ExpectedWarning ("IL2046", "ImplementationClassWithRequiresInSource.Method()", "IBaseWithoutRequiresInReference.Method()")] - [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.Method()", "IBaseWithoutRequiresInReference.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithRequiresInSource.Method()", "IBaseWithoutRequiresInReference.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.Method()", "IBaseWithoutRequiresInReference.Method()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithRequiresInSource.Method()", "IBaseWithoutRequiresInReference.Method()", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message")] [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] @@ -567,8 +567,8 @@ public void Method () private string name; public string PropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithoutRequiresInReference.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithoutRequiresInReference.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithoutRequiresInReference.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithoutRequiresInReference.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithoutRequiresInReference.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message")] [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] @@ -576,12 +576,12 @@ public string PropertyAnnotationInAccesor { set { name = value; } } - [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty", "IBaseWithoutRequiresInReference.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty", "IBaseWithoutRequiresInReference.PropertyAnnotationInProperty", Tool.Analyzer, "")] [RequiresAssemblyFiles ("Message")] public string PropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty", "IBaseWithoutRequiresInReference.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty", "IBaseWithoutRequiresInReference.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty", "IBaseWithoutRequiresInReference.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty", "IBaseWithoutRequiresInReference.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -589,23 +589,23 @@ public string PropertyAnnotationInProperty { class StaticInterfaceMethods { [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] public static void Test () { typeof (IRequires).RequiresPublicMethods (); @@ -650,13 +650,13 @@ public static void AbstractMethod () { } class ImplIRequiresMismatching : IRequires { [ExpectedWarning ("IL2046", "ImplIRequiresMismatching.VirtualMethod", "IRequires.VirtualMethod")] - [ExpectedWarning ("IL3003", "ImplIRequiresMismatching.VirtualMethod", "IRequires.VirtualMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplIRequiresMismatching.VirtualMethod", "IRequires.VirtualMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplIRequiresMismatching.VirtualMethod", "IRequires.VirtualMethod", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplIRequiresMismatching.VirtualMethod", "IRequires.VirtualMethod", Tool.Analyzer | Tool.NativeAot, "")] public static void VirtualMethod () { } [ExpectedWarning ("IL2046", "ImplIRequiresMismatching.AbstractMethod", "IRequires.AbstractMethod")] - [ExpectedWarning ("IL3003", "ImplIRequiresMismatching.AbstractMethod", "IRequires.AbstractMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplIRequiresMismatching.AbstractMethod", "IRequires.AbstractMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplIRequiresMismatching.AbstractMethod", "IRequires.AbstractMethod", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplIRequiresMismatching.AbstractMethod", "IRequires.AbstractMethod", Tool.Analyzer | Tool.NativeAot, "")] public static void AbstractMethod () { } } class ImplINoRequiresMatching : INoRequires @@ -669,16 +669,16 @@ public static void AbstractMethod () { } class ImplINoRequiresMismatching : INoRequires { [ExpectedWarning ("IL2046", "ImplINoRequiresMismatching.VirtualMethod", "INoRequires.VirtualMethod")] - [ExpectedWarning ("IL3003", "ImplINoRequiresMismatching.VirtualMethod", "INoRequires.VirtualMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplINoRequiresMismatching.VirtualMethod", "INoRequires.VirtualMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplINoRequiresMismatching.VirtualMethod", "INoRequires.VirtualMethod", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplINoRequiresMismatching.VirtualMethod", "INoRequires.VirtualMethod", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.VirtualMethod--")] [RequiresAssemblyFiles ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.VirtualMethod--")] [RequiresDynamicCode ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.VirtualMethod--")] public static void VirtualMethod () { } [ExpectedWarning ("IL2046", "ImplINoRequiresMismatching.AbstractMethod", "INoRequires.AbstractMethod")] - [ExpectedWarning ("IL3003", "ImplINoRequiresMismatching.AbstractMethod", "INoRequires.AbstractMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplINoRequiresMismatching.AbstractMethod", "INoRequires.AbstractMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplINoRequiresMismatching.AbstractMethod", "INoRequires.AbstractMethod", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplINoRequiresMismatching.AbstractMethod", "INoRequires.AbstractMethod", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.AbstractMethod--")] [RequiresAssemblyFiles ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.AbstractMethod--")] [RequiresDynamicCode ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.AbstractMethod--")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs index 3def1ee762beaf..a2f38e46486ad1 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs @@ -50,8 +50,8 @@ public static void Main () class WarnInIteratorBody { [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static IEnumerable TestCallBeforeYieldReturn () { MethodWithRequires (); @@ -59,8 +59,8 @@ static IEnumerable TestCallBeforeYieldReturn () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static IEnumerable TestCallAfterYieldReturn () { yield return 0; @@ -68,8 +68,8 @@ static IEnumerable TestCallAfterYieldReturn () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] static IEnumerable TestReflectionAccess () { yield return 0; @@ -80,15 +80,15 @@ static IEnumerable TestReflectionAccess () } #if !RELEASE - [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] #else // In release mode, the compiler optimizes away the unused Action (and reference to MethodWithRequires) #endif - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer, "")] static IEnumerable TestLdftn () { yield return 0; @@ -98,8 +98,8 @@ static IEnumerable TestLdftn () // Cannot annotate fields either with RUC nor RAF therefore the warning persists [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static IEnumerable TestLazyDelegate () @@ -110,8 +110,8 @@ static IEnumerable TestLazyDelegate () } [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] static IEnumerable TestDynamicallyAccessedMethod () { typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); @@ -167,8 +167,8 @@ static IEnumerable TestLdftn () // Cannot annotate fields either with RUC nor RAF therefore the warning persists [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static IEnumerable TestLazyDelegate () @@ -234,8 +234,8 @@ public static void Test () class WarnInAsyncBody { [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async void TestCallBeforeYieldReturn () { MethodWithRequires (); @@ -243,8 +243,8 @@ static async void TestCallBeforeYieldReturn () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async void TestCallAfterYieldReturn () { await MethodAsync (); @@ -252,8 +252,8 @@ static async void TestCallAfterYieldReturn () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] static async void TestReflectionAccess () { await MethodAsync (); @@ -264,13 +264,13 @@ static async void TestReflectionAccess () } #if !RELEASE - [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] #endif - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer, "")] static async void TestLdftn () { await MethodAsync (); @@ -278,8 +278,8 @@ static async void TestLdftn () } [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static async void TestLazyDelegate () @@ -289,8 +289,8 @@ static async void TestLazyDelegate () } [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] static async void TestDynamicallyAccessedMethod () { typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); @@ -344,8 +344,8 @@ static async void TestLdftn () // Cannot annotate fields either with RUC nor RAF therefore the warning persists [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static async void TestLazyDelegate () @@ -409,8 +409,8 @@ public static void Test () class WarnInAsyncIteratorBody { [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async IAsyncEnumerable TestCallBeforeYieldReturn () { await MethodAsync (); @@ -419,8 +419,8 @@ static async IAsyncEnumerable TestCallBeforeYieldReturn () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async IAsyncEnumerable TestCallAfterYieldReturn () { yield return 0; @@ -429,8 +429,8 @@ static async IAsyncEnumerable TestCallAfterYieldReturn () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] static async IAsyncEnumerable TestReflectionAccess () { yield return 0; @@ -443,13 +443,13 @@ static async IAsyncEnumerable TestReflectionAccess () } #if !RELEASE - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] #endif - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer, "")] static async IAsyncEnumerable TestLdftn () { await MethodAsync (); @@ -458,8 +458,8 @@ static async IAsyncEnumerable TestLdftn () } [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static async IAsyncEnumerable TestLazyDelegate () @@ -470,8 +470,8 @@ static async IAsyncEnumerable TestLazyDelegate () } [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] static async IAsyncEnumerable TestDynamicallyAccessedMethod () { typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); @@ -530,8 +530,8 @@ static async IAsyncEnumerable TestLdftn () // Cannot annotate fields either with RUC nor RAF therefore the warning persists [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static async IAsyncEnumerable TestLazyDelegate () @@ -604,14 +604,14 @@ static void TestCall () LocalFunction (); [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] void LocalFunction () => MethodWithRequires (); } [ExpectedWarning ("IL2026", "--LocalFunctionWithRequires--")] - [ExpectedWarning ("IL3002", "--LocalFunctionWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--LocalFunctionWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--LocalFunctionWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--LocalFunctionWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestLocalFunctionWithRequires () { LocalFunction (); @@ -633,8 +633,8 @@ static void TestCallWithClosure (int p = 0) LocalFunction (); [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] void LocalFunction () { p++; @@ -657,8 +657,8 @@ static void TestReflectionAccess () LocalFunction (); [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "")] void LocalFunction () => typeof (RequiresInCompilerGeneratedCode) .GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic) .Invoke (null, new object[] { }); @@ -669,13 +669,13 @@ static void TestLdftn () LocalFunction (); #if !RELEASE - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "")] #endif - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer, "")] void LocalFunction () { var action = new Action (MethodWithRequires); @@ -683,8 +683,8 @@ void LocalFunction () } [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static void TestLazyDelegate () @@ -702,8 +702,8 @@ static void TestDynamicallyAccessedMethod () LocalFunction (); [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "")] void LocalFunction () => typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); } @@ -788,8 +788,8 @@ void LocalFunction () } [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static void TestLazyDelegate () @@ -919,7 +919,7 @@ public static void TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction class DynamicallyAccessedLocalFunctionUnusedShouldWarn { - [ExpectedWarning ("IL2118", nameof (TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction), "LocalFunction", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", [nameof (TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction), "LocalFunction"], Tool.Trimmer, "")] public static void TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction () { typeof (DynamicallyAccessedLocalFunctionUnusedShouldWarn).RequiresNonPublicMethods (); @@ -949,8 +949,8 @@ public static void TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction } [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] static void TestSuppressionOnLocalFunction () { LocalFunction (); // This will produce a warning since the local function has Requires on it @@ -966,8 +966,8 @@ void LocalFunction (Type unknownType = null) } [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] static void TestSuppressionOnLocalFunctionWithAssignment () { LocalFunction (); // This will produce a warning since the local function has Requires on it @@ -986,8 +986,8 @@ void LocalFunction (Type unknownType = null) static Type typeWithNonPublicMethods; [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] static void TestSuppressionOnLocalFunctionWithNestedLocalFunction () { LocalFunction (); // This will produce a warning since the local function has Requires on it @@ -1001,9 +1001,9 @@ void LocalFunction () // ILLink doesn't have enough information to associate the Requires on LocalFunction // with this nested local function. - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] void NestedLocalFunction () => MethodWithRequires (); } } @@ -1028,8 +1028,8 @@ void LocalFunction (Type unknownType = null) class TestSuppressionOnOuterWithSameName { [ExpectedWarning ("IL2026", nameof (Outer) + "()")] - [ExpectedWarning ("IL3002", nameof (Outer) + "()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", nameof (Outer) + "()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", nameof (Outer) + "()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", nameof (Outer) + "()", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { Outer (); @@ -1051,8 +1051,8 @@ static void Outer (int i) LocalFunction (); [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] void LocalFunction () => MethodWithRequires (); } } @@ -1093,14 +1093,14 @@ static void WarnInNonNestedLocalFunctionTest () LocalFunction (); [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void LocalFunction () => MethodWithRequires (); } [ExpectedWarning ("IL2026", "--MethodWithNonNestedLocalFunction--")] - [ExpectedWarning ("IL3002", "--MethodWithNonNestedLocalFunction--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithNonNestedLocalFunction--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithNonNestedLocalFunction--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithNonNestedLocalFunction--", Tool.Analyzer | Tool.NativeAot, "")] static void SuppressInNonNestedLocalFunctionTest () { MethodWithNonNestedLocalFunction (); @@ -1122,16 +1122,16 @@ static void TestCall () { Action lambda = [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] () => MethodWithRequires (); lambda (); } [ExpectedWarning ("IL2026", "--LambdaWithRequires--")] - [ExpectedWarning ("IL3002", "--LambdaWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--LambdaWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--LambdaWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--LambdaWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestLambdaWithRequires () { Action lambda = @@ -1147,14 +1147,14 @@ static void TestCallUnused () { Action _ = [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] () => MethodWithRequires (); } [ExpectedWarning ("IL2026", "--LambdaWithRequires--")] - [ExpectedWarning ("IL3002", "--LambdaWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--LambdaWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--LambdaWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--LambdaWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestLambdaWithRequiresUnused () { Action _ = @@ -1168,8 +1168,8 @@ static void TestCallWithClosure (int p = 0) { Action lambda = [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] () => { p++; MethodWithRequires (); @@ -1182,13 +1182,13 @@ static void TestCallWithClosureUnused (int p = 0) { Action _ = #if !RELEASE - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "")] #endif - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer, "")] () => { p++; MethodWithRequires (); @@ -1199,8 +1199,8 @@ static void TestReflectionAccess () { Action _ = [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "")] () => { typeof (RequiresInCompilerGeneratedCode) .GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic) @@ -1212,21 +1212,21 @@ static void TestLdftn () { Action _ = #if !RELEASE - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "")] #endif - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer, "")] () => { var action = new Action (MethodWithRequires); }; } [ExpectedWarning ("IL2026", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static void TestLazyDelegate () @@ -1240,8 +1240,8 @@ static void TestDynamicallyAccessedMethod () { Action _ = [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "")] () => { typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); }; @@ -1330,8 +1330,8 @@ static void TestLdftn () } [ExpectedWarning ("IL2026", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static void TestLazyDelegate () @@ -1383,8 +1383,8 @@ static void TestGenericTypeParameterRequirement () } [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] static void TestSuppressionOnLambda () { var lambda = @@ -1397,8 +1397,8 @@ static void TestSuppressionOnLambda () } [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] static void TestSuppressionOnLambdaWithNestedLambda () { var lambda = @@ -1411,9 +1411,9 @@ static void TestSuppressionOnLambdaWithNestedLambda () // an IL reference to the generated lambda method, unlike local functions. // However, we don't make this association, for consistency with local functions. var nestedLambda = - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", Tool.NativeAot | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot | Tool.NativeAot, "")] () => MethodWithRequires (); }; @@ -1440,8 +1440,8 @@ static void TestSuppressionOnOuterAndLambda () class TestSuppressionOnOuterWithSameName { [ExpectedWarning ("IL2026", nameof (Outer) + "()")] - [ExpectedWarning ("IL3002", nameof (Outer) + "()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", nameof (Outer) + "()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", nameof (Outer) + "()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", nameof (Outer) + "()", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { Outer (); @@ -1462,8 +1462,8 @@ static void Outer (int i) { var lambda = [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] () => MethodWithRequires (); lambda (); @@ -1503,8 +1503,8 @@ static async void TestIteratorLocalFunctionInAsync () await MethodAsync (); [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] IEnumerable LocalFunction () { yield return 0; @@ -1543,8 +1543,8 @@ IEnumerable IteratorLocalFunction () yield return 1; [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] void LocalFunction () => MethodWithRequires (); } } @@ -1561,8 +1561,8 @@ IEnumerable IteratorLocalFunction () } [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] void LocalFunction () => MethodWithRequires (); } @@ -1754,8 +1754,8 @@ static IEnumerable TestDynamicallyAccessedMethodViaGenericMethodParameterIn #endif [ExpectedWarning ("IL2026", "--IteratorLocalFunction--")] - [ExpectedWarning ("IL3002", "--IteratorLocalFunction--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--IteratorLocalFunction--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--IteratorLocalFunction--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--IteratorLocalFunction--", Tool.Analyzer | Tool.NativeAot, "")] static void TestLocalFunctionInIteratorLocalFunction () { IteratorLocalFunction (); @@ -1771,16 +1771,16 @@ IEnumerable IteratorLocalFunction () yield return 1; // Trimmer doesn't try to associate LocalFunction with IteratorLocalFunction - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "")] void LocalFunction () => MethodWithRequires (); } } [ExpectedWarning ("IL2026", "--IteratorLocalFunction--")] - [ExpectedWarning ("IL3002", "--IteratorLocalFunction--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--IteratorLocalFunction--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--IteratorLocalFunction--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--IteratorLocalFunction--", Tool.Analyzer | Tool.NativeAot, "")] static void TestLocalFunctionCalledFromIteratorLocalFunctionAndMethod () { IteratorLocalFunction (); @@ -1798,8 +1798,8 @@ IEnumerable IteratorLocalFunction () } [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] void LocalFunction () => MethodWithRequires (); } @@ -1847,8 +1847,8 @@ static async void TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress () } [ExpectedWarning ("IL2026", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static IEnumerable TestIteratorOnlyReferencedViaReflectionWhichShouldWarn () { yield return 0; @@ -1856,8 +1856,8 @@ static IEnumerable TestIteratorOnlyReferencedViaReflectionWhichShouldWarn ( } [ExpectedWarning ("IL2026", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async void TestAsyncOnlyReferencedViaReflectionWhichShouldWarn () { await MethodAsync (); @@ -1865,26 +1865,24 @@ static async void TestAsyncOnlyReferencedViaReflectionWhichShouldWarn () } [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--")] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--")] - [ExpectedWarning ("IL3002", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2118", nameof (StateMachinesOnlyReferencedViaReflection), "<" + nameof (TestAsyncOnlyReferencedViaReflectionWhichShouldWarn) + ">", "MoveNext()", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", nameof (StateMachinesOnlyReferencedViaReflection), "<" + nameof (TestIteratorOnlyReferencedViaReflectionWhichShouldWarn) + ">", "MoveNext()", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] + [ExpectedWarning ("IL2118", [nameof (StateMachinesOnlyReferencedViaReflection), "<" + nameof (TestAsyncOnlyReferencedViaReflectionWhichShouldWarn) + ">", "MoveNext()"], Tool.Trimmer, "")] + [ExpectedWarning ("IL2118", [nameof (StateMachinesOnlyReferencedViaReflection), "<" + nameof (TestIteratorOnlyReferencedViaReflectionWhichShouldWarn) + ">", "MoveNext()"], Tool.Trimmer, "")] static void TestAll () { typeof (StateMachinesOnlyReferencedViaReflection).RequiresAll (); } [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--")] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--")] - [ExpectedWarning ("IL3002", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] // NonPublicMethods doesn't warn for members emitted into compiler-generated state machine types. static void TestNonPublicMethods () { @@ -1901,8 +1899,8 @@ public static void Test () class LocalFunctionsReferencedViaReflection { [ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestLocalFunctionWithRequires () { LocalFunction (); @@ -1922,8 +1920,8 @@ static void TestLocalFunctionWithRequiresOnlyAccessedViaReflection () } [ExpectedWarning ("IL2026", "LocalFunction")] - [ExpectedWarning ("IL3002", "LocalFunction", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "LocalFunction", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "LocalFunction", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "LocalFunction", Tool.Analyzer | Tool.NativeAot, "")] static void TestLocalFunctionWithClosureWithRequires (int p = 0) { LocalFunction (); @@ -1974,16 +1972,15 @@ void LocalFunction () // Warnings for Reflection access to methods with Requires [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureInMethodWithRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection), - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", Tool.NativeAot, "")] + [ExpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection), Tool.Trimmer, "")] static void TestAll () { typeof (LocalFunctionsReferencedViaReflection).RequiresAll (); @@ -1991,16 +1988,15 @@ static void TestAll () // Warnings for Reflection access to methods with Requires [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureInMethodWithRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), "<" + nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection) + ">", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", Tool.NativeAot, "")] + [ExpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), "<" + nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection) + ">", Tool.Trimmer, "")] static void TestNonPublicMethods () { typeof (LocalFunctionsReferencedViaReflection).RequiresNonPublicMethods (); @@ -2016,8 +2012,8 @@ public static void Test () class LambdasReferencedViaReflection { [ExpectedWarning ("IL2026", "--TestLambdaWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLambdaWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLambdaWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLambdaWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestLambdaWithRequires () { var lambda = @@ -2030,8 +2026,8 @@ static void TestLambdaWithRequires () } [ExpectedWarning ("IL2026", "Lambda")] - [ExpectedWarning ("IL3002", "Lambda", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Lambda", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Lambda", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Lambda", Tool.Analyzer | Tool.NativeAot, "")] static void TestLambdaWithClosureWithRequires (int p = 0) { var lambda = @@ -2071,11 +2067,11 @@ static void TestLambdaWithClosureInMethodWithRequires (int p = 0) // Warnings for Reflection access to methods with Requires [ExpectedWarning ("IL2026", "--TestLambdaInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestLambdaWithClosureInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLambdaWithClosureInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLambdaWithClosureInMethodWithRequires--", Tool.NativeAot, "")] static void TestAll () { typeof (LambdasReferencedViaReflection).RequiresAll (); @@ -2083,11 +2079,11 @@ static void TestAll () // Warnings for Reflection access to methods with Requires [ExpectedWarning ("IL2026", "--TestLambdaInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestLambdaWithClosureInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLambdaWithClosureInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLambdaWithClosureInMethodWithRequires--", Tool.NativeAot, "")] static void TestNonPublicMethods () { typeof (LambdasReferencedViaReflection).RequiresNonPublicMethods (); @@ -2123,8 +2119,8 @@ static async Task AsyncMethodCallingRequires (Type type) } [ExpectedWarning ("IL2026", "ParentSuppression")] - [ExpectedWarning ("IL3002", "ParentSuppression", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "ParentSuppression", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ParentSuppression", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "ParentSuppression", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { AsyncMethodCallingRequires (typeof (object)); @@ -2152,8 +2148,8 @@ static async Task AsyncMethodCallingRequires () } [ExpectedWarning ("IL2026", "ParentSuppression")] - [ExpectedWarning ("IL3002", "ParentSuppression", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "ParentSuppression", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ParentSuppression", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "ParentSuppression", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { AsyncMethodCallingRequires (); @@ -2192,8 +2188,8 @@ static async IAsyncEnumerable CreateAsync () } [ExpectedWarning ("IL2026", "ParentSuppression")] - [ExpectedWarning ("IL3002", "ParentSuppression", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "ParentSuppression", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ParentSuppression", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "ParentSuppression", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { AsyncEnumMethodCallingRequires (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnAttribute.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnAttribute.cs index 8710ed0e45cf82..a8f5ab60dd0578 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnAttribute.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnAttribute.cs @@ -61,16 +61,16 @@ public bool PropertyWhichRequires { } [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] class GenericTypeWithAttributedParameter<[AttributeWhichRequires] T> { public static void TestMethod () { } } [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] static void GenericMethodWithAttributedParameter<[AttributeWhichRequires] T> () { } static void TestRequiresOnAttributeOnGenericParameter () @@ -80,11 +80,11 @@ static void TestRequiresOnAttributeOnGenericParameter () } [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] [AttributeWhichRequires] [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)] class TypeWithAttributeWhichRequires @@ -92,31 +92,31 @@ class TypeWithAttributeWhichRequires } [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] [AttributeWhichRequires] [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)] static void MethodWithAttributeWhichRequires () { } [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] [AttributeWhichRequires] [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)] static int _fieldWithAttributeWhichRequires; [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] [AttributeWhichRequires] [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)] static bool PropertyWithAttributeWhichRequires { get; set; } @@ -129,8 +129,8 @@ static void MethodWithAttributeWhichRequires () { } static void MethodWhichRequiresWithAttributeWhichRequires () { } [ExpectedWarning ("IL2026", "--MethodWhichRequiresWithAttributeWhichRequires--")] - [ExpectedWarning ("IL3002", "--MethodWhichRequiresWithAttributeWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWhichRequiresWithAttributeWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWhichRequiresWithAttributeWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWhichRequiresWithAttributeWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestMethodWhichRequiresWithAttributeWhichRequires () { MethodWhichRequiresWithAttributeWhichRequires (); @@ -152,8 +152,8 @@ public void MethodWhichRequires () { } } [ExpectedWarning ("IL2026", "--TypeWithMethodWhichRequires--")] - [ExpectedWarning ("IL3002", "--TypeWithMethodWhichRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWhichRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWhichRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TypeWithMethodWhichRequires--", Tool.NativeAot, "")] [AttributeWhichMarksPublicMethods (typeof(TypeWithMethodWhichRequires))] static void ShouldWarn() { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs index f1faf7684750f3..dc9a49597e7d9b 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs @@ -59,7 +59,7 @@ public static void NestedStaticMethod () { } // This warning doesn't get suppressed since the declaring type NestedClass is not annotated with Requires [ExpectedWarning ("IL2026", "RequiresOnClass.RequiresOnMethod.MethodWithRequires()", "MethodWithRequires")] - [ExpectedWarning ("IL3050", "RequiresOnClass.RequiresOnMethod.MethodWithRequires()", "MethodWithRequires", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.RequiresOnMethod.MethodWithRequires()", "MethodWithRequires", Tool.Analyzer | Tool.NativeAot, "")] public static void CallMethodWithRequires () => RequiresOnMethod.MethodWithRequires (); } @@ -101,7 +101,7 @@ private class DerivedWithoutRequires : ClassWithRequires { // This method contains implicit call to ClassWithRequires.ctor() [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] public DerivedWithoutRequires () { } public static void StaticMethodInInheritedClass () { } @@ -155,7 +155,7 @@ static StaticCtor () } [ExpectedWarning ("IL2026", "RequiresOnClass.StaticCtor.StaticCtor()", "Message for --StaticCtor--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.StaticCtor.StaticCtor()", "Message for --StaticCtor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.StaticCtor.StaticCtor()", "Message for --StaticCtor--", Tool.Analyzer | Tool.NativeAot, "")] static void TestStaticCctorRequires () { _ = new StaticCtor (); @@ -174,14 +174,14 @@ static StaticCtorTriggeredByFieldAccess () } [ExpectedWarning ("IL2026", "StaticCtorTriggeredByFieldAccess.field", "Message for --StaticCtorTriggeredByFieldAccess--")] - [ExpectedWarning ("IL3050", "StaticCtorTriggeredByFieldAccess.field", "Message for --StaticCtorTriggeredByFieldAccess--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "StaticCtorTriggeredByFieldAccess.field", "Message for --StaticCtorTriggeredByFieldAccess--", Tool.Analyzer | Tool.NativeAot, "")] static void TestStaticCtorMarkingIsTriggeredByFieldAccessWrite () { StaticCtorTriggeredByFieldAccess.field = 1; } [ExpectedWarning ("IL2026", "StaticCtorTriggeredByFieldAccess.field", "Message for --StaticCtorTriggeredByFieldAccess--")] - [ExpectedWarning ("IL3050", "StaticCtorTriggeredByFieldAccess.field", "Message for --StaticCtorTriggeredByFieldAccess--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "StaticCtorTriggeredByFieldAccess.field", "Message for --StaticCtorTriggeredByFieldAccess--", Tool.Analyzer | Tool.NativeAot, "")] static void TestStaticCtorMarkingTriggeredOnSecondAccessWrite () { StaticCtorTriggeredByFieldAccess.field = 2; @@ -209,7 +209,7 @@ class StaticCCtorTriggeredByFieldAccessRead } [ExpectedWarning ("IL2026", "StaticCCtorTriggeredByFieldAccessRead.field", "Message for --StaticCCtorTriggeredByFieldAccessRead--")] - [ExpectedWarning ("IL3050", "StaticCCtorTriggeredByFieldAccessRead.field", "Message for --StaticCCtorTriggeredByFieldAccessRead--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "StaticCCtorTriggeredByFieldAccessRead.field", "Message for --StaticCCtorTriggeredByFieldAccessRead--", Tool.Analyzer | Tool.NativeAot, "")] static void TestStaticCtorMarkingIsTriggeredByFieldAccessRead () { var _ = StaticCCtorTriggeredByFieldAccessRead.field; @@ -229,7 +229,7 @@ public void TriggerStaticCtorMarking () } [ExpectedWarning ("IL2026", "StaticCtorTriggeredByCtorCalls.StaticCtorTriggeredByCtorCalls()")] - [ExpectedWarning ("IL3050", "StaticCtorTriggeredByCtorCalls.StaticCtorTriggeredByCtorCalls()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "StaticCtorTriggeredByCtorCalls.StaticCtorTriggeredByCtorCalls()", Tool.Analyzer | Tool.NativeAot, "")] static void TestStaticCtorTriggeredByCtorCall () { new StaticCtorTriggeredByCtorCalls (); @@ -243,7 +243,7 @@ class ClassWithInstanceField } [ExpectedWarning ("IL2026", "ClassWithInstanceField.ClassWithInstanceField()")] - [ExpectedWarning ("IL3050", "ClassWithInstanceField.ClassWithInstanceField()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "ClassWithInstanceField.ClassWithInstanceField()", Tool.Analyzer | Tool.NativeAot, "")] static void TestInstanceFieldCallDontWarn () { ClassWithInstanceField instance = new ClassWithInstanceField (); @@ -260,7 +260,7 @@ public ClassWithInstanceFieldWhichInitsDangerousClass () { } } [ExpectedWarning ("IL2026", "Calling the constructor is dangerous")] - [ExpectedWarning ("IL3050", "Calling the constructor is dangerous", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "Calling the constructor is dangerous", Tool.Analyzer | Tool.NativeAot, "")] static void TestInstanceFieldSuppression () { _ = new ClassWithInstanceFieldWhichInitsDangerousClass (); @@ -310,7 +310,7 @@ public class DerivedNestedClass : ClassWithRequires { // This method contains implicit call to ClassWithRequires.ctor() [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] public DerivedNestedClass () { } public static void NestedStaticMethod () { } @@ -389,14 +389,14 @@ public int Method (int a) } [ExpectedWarning ("IL2026", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestRequiresInClassAccessedByStaticMethod () { ClassWithRequires.StaticMethod (); } [ExpectedWarning ("IL2026", "RequiresOnClass.ClassWithRequires", "--ClassWithRequires--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires", "--ClassWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires", "--ClassWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestRequiresInClassAccessedByCctor () { var classObject = new ClassWithRequires (); @@ -408,12 +408,12 @@ static void TestRequiresInParentClassAccesedByStaticMethod () } [ExpectedWarning ("IL2026", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] // Although we suppress the warning from RequiresOnMethod.MethodWithRequires () we still get a warning because we call CallRequiresMethod() which is an static method on a type with RUC [ExpectedWarning ("IL2026", "RequiresOnClass.ClassWithRequires.CallMethodWithRequires()", "--ClassWithRequires--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.CallMethodWithRequires()", "--ClassWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.CallMethodWithRequires()", "--ClassWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ClassWithRequires.Instance", "--ClassWithRequires--")] - [ExpectedWarning ("IL3050", "ClassWithRequires.Instance", "--ClassWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "ClassWithRequires.Instance", "--ClassWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestRequiresOnBaseButNotOnDerived () { var a = new DerivedWithoutRequires (); // Must instantiate to force checks on the base type (otherwise base type is non-interesting) @@ -429,7 +429,7 @@ static void TestRequiresOnBaseButNotOnDerived () } [ExpectedWarning ("IL2026", "RequiresOnClass.DerivedWithRequires.StaticMethodInInheritedClass()", "--DerivedWithRequires--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.DerivedWithRequires.StaticMethodInInheritedClass()", "--DerivedWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.DerivedWithRequires.StaticMethodInInheritedClass()", "--DerivedWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestRequiresOnDerivedButNotOnBase () { DerivedWithRequires.StaticMethodInInheritedClass (); @@ -439,9 +439,9 @@ static void TestRequiresOnDerivedButNotOnBase () } [ExpectedWarning ("IL2026", "RequiresOnClass.DerivedWithRequires2.StaticMethodInInheritedClass()", "--DerivedWithRequires2--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.DerivedWithRequires2.StaticMethodInInheritedClass()", "--DerivedWithRequires2--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.DerivedWithRequires2.StaticMethodInInheritedClass()", "--DerivedWithRequires2--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestRequiresOnBaseAndDerived () { DerivedWithRequires2.StaticMethodInInheritedClass (); @@ -452,7 +452,7 @@ static void TestRequiresOnBaseAndDerived () } [ExpectedWarning ("IL2026", "RequiresOnClass.ClassWithRequires.TestSuppressions(", "Type[])")] - [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.TestSuppressions(", "Type[])", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.TestSuppressions(", "Type[])", Tool.Analyzer | Tool.NativeAot, "")] static void TestSuppressionsOnClass () { ClassWithRequires.TestSuppressions (new[] { typeof (ClassWithRequires) }); @@ -496,11 +496,11 @@ class MemberTypesWithRequires } [ExpectedWarning ("IL2026", "MemberTypesWithRequires.field")] - [ExpectedWarning ("IL3050", "MemberTypesWithRequires.field", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "MemberTypesWithRequires.field", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "MemberTypesWithRequires.Property.set")] - [ExpectedWarning ("IL3050", "MemberTypesWithRequires.Property.set", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "MemberTypesWithRequires.Property.set", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "MemberTypesWithRequires.Event.remove")] - [ExpectedWarning ("IL3050", "MemberTypesWithRequires.Event.remove", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "MemberTypesWithRequires.Event.remove", Tool.Analyzer | Tool.NativeAot, "")] static void TestOtherMemberTypesWithRequires () { MemberTypesWithRequires.field = 1; @@ -519,25 +519,25 @@ static void TestNameOfDoesntWarn () class ReflectionAccessOnMethod { [ExpectedWarning ("IL2026", "BaseWithRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "BaseWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseWithRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "BaseWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseWithoutRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseWithoutRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "DerivedWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "InterfaceWithoutRequires.Method(Int32)")] - [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method(Int32)", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method(Int32)", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "InterfaceWithoutRequires.Method()")] - [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationWithRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationWithRequiresOnType.Method(Int32)")] - [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method(Int32)", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method(Int32)", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()")] - [ExpectedWarning ("IL3050", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()", Tool.NativeAot, "")] static void TestDAMAccess () { // Warns because BaseWithoutRequiresOnType.Method has Requires on the method @@ -563,17 +563,17 @@ static void TestDAMAccess () } [ExpectedWarning ("IL2026", "BaseWithRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "BaseWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseWithoutRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "InterfaceWithoutRequires.Method(Int32)")] - [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method(Int32)", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method(Int32)", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "InterfaceWithoutRequires.Method()")] - [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationWithRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationWithRequiresOnType.Method(Int32)")] - [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method(Int32)", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method(Int32)", Tool.NativeAot, "")] static void TestDirectReflectionAccess () { // Requires on the method itself @@ -609,7 +609,7 @@ public BaseWithRequires () { } class DerivedWithoutRequires : BaseWithRequires { [ExpectedWarning ("IL2026", "--BaseWithRequires--")] // The body has direct call to the base.ctor() - [ExpectedWarning ("IL3050", "--BaseWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--BaseWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] public DerivedWithoutRequires () { } } @@ -631,15 +631,15 @@ public DerivedWithRequiresOnBaseWithoutRequires () { } } [ExpectedWarning ("IL2026", "BaseWithRequires.BaseWithRequires()")] - [ExpectedWarning ("IL3050", "BaseWithRequires.BaseWithRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithRequires.BaseWithRequires()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseWithRequires.BaseWithRequires()")] - [ExpectedWarning ("IL3050", "BaseWithRequires.BaseWithRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithRequires.BaseWithRequires()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()")] - [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()")] - [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()")] - [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", Tool.NativeAot, "")] static void TestDAMAccess () { // Warns because the type has Requires @@ -656,11 +656,11 @@ static void TestDAMAccess () } [ExpectedWarning ("IL2026", "BaseWithRequires.BaseWithRequires()")] - [ExpectedWarning ("IL3050", "BaseWithRequires.BaseWithRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithRequires.BaseWithRequires()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()")] - [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()")] - [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", Tool.NativeAot, "")] static void TestDirectReflectionAccess () { typeof (BaseWithRequires).GetConstructor (Type.EmptyTypes); @@ -708,15 +708,15 @@ class DerivedWithRequires : WithRequires } [ExpectedWarning ("IL2026", "WithRequires.StaticField")] - [ExpectedWarning ("IL3050", "WithRequires.StaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticField", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticField")] - [ExpectedWarning ("IL3050", "WithRequires.StaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticField", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticField")] - [ExpectedWarning ("IL3050", "WithRequires.StaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticField", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.PrivateStaticField")] - [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticField", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticField")] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticField", Tool.NativeAot, "")] static void TestDAMAccess () { typeof (WithRequires).RequiresPublicFields (); @@ -727,11 +727,11 @@ static void TestDAMAccess () } [ExpectedWarning ("IL2026", "WithRequires.StaticField")] - [ExpectedWarning ("IL3050", "WithRequires.StaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticField", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.PrivateStaticField")] - [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticField", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticField")] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticField", Tool.NativeAot, "")] static void TestDirectReflectionAccess () { typeof (WithRequires).GetField (nameof (WithRequires.StaticField)); @@ -742,17 +742,17 @@ static void TestDirectReflectionAccess () typeof (DerivedWithRequires).GetField (nameof (DerivedWithRequires.DerivedStaticField)); } - [ExpectedWarning ("IL2026", "WithRequires.StaticField", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticField", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticField", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticField", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticField", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "WithRequires.StaticField", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticField", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticField", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticField", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticField", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticField", Tool.NativeAot, "")] [DynamicDependency (nameof (WithRequires.StaticField), typeof (WithRequires))] [DynamicDependency (nameof (WithRequires.InstanceField), typeof (WithRequires))] // Doesn't warn [DynamicDependency (DynamicallyAccessedMemberTypes.PublicFields, typeof (DerivedWithoutRequires))] // Doesn't warn - [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticField", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticField", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticField", Tool.NativeAot, "")] [DynamicDependency (DynamicallyAccessedMemberTypes.PublicFields, typeof (DerivedWithRequires))] static void TestDynamicDependencyAccess () { @@ -768,13 +768,13 @@ class BaseForDAMAnnotatedClass [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] [RequiresUnreferencedCode ("This class is dangerous")] [RequiresDynamicCode ("This class is dangerous")] - [ExpectedWarning ("IL2113", "BaseForDAMAnnotatedClass.baseField", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2113", "BaseForDAMAnnotatedClass.baseField", Tool.Trimmer | Tool.NativeAot, "")] class DAMAnnotatedClass : BaseForDAMAnnotatedClass { - [ExpectedWarning ("IL2112", "DAMAnnotatedClass.publicField", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "DAMAnnotatedClass.publicField", Tool.Trimmer | Tool.NativeAot, "")] public static int publicField; - [ExpectedWarning ("IL2112", "DAMAnnotatedClass.privatefield", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "DAMAnnotatedClass.privatefield", Tool.Trimmer | Tool.NativeAot, "")] static int privatefield; } @@ -786,7 +786,7 @@ static void TestDAMOnTypeAccess (DAMAnnotatedClass instance) [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] class DAMAnnotatedClassAccessedFromRUCScope { - [ExpectedWarning ("IL2112", "DAMAnnotatedClassAccessedFromRUCScope.RUCMethod", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "DAMAnnotatedClassAccessedFromRUCScope.RUCMethod", Tool.Trimmer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("--RUCMethod--")] public static void RUCMethod () { } } @@ -807,14 +807,14 @@ class GenericTypeWithRequires } [ExpectedWarning ("IL2026", "NonGenericField", "--GenericTypeWithRequires--")] - [ExpectedWarning ("IL3050", "NonGenericField", "--GenericTypeWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "NonGenericField", "--GenericTypeWithRequires--", Tool.NativeAot, "")] static void TestDAMAccessOnOpenGeneric () { typeof (GenericTypeWithRequires<>).RequiresPublicFields (); } [ExpectedWarning ("IL2026", "NonGenericField", "--GenericTypeWithRequires--")] - [ExpectedWarning ("IL3050", "NonGenericField", "--GenericTypeWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "NonGenericField", "--GenericTypeWithRequires--", Tool.NativeAot, "")] static void TestDAMAccessOnInstantiatedGeneric () { typeof (GenericTypeWithRequires).RequiresPublicFields (); @@ -846,11 +846,11 @@ class WithRequires } [ExpectedWarning ("IL2026", "StaticEvent.add")] - [ExpectedWarning ("IL3050", "StaticEvent.add", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "StaticEvent.add", Tool.NativeAot, "")] // https://github.com/dotnet/runtime/issues/100499 - [ExpectedWarning ("IL2026", "StaticEvent.add", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", "StaticEvent.add", Tool.Trimmer, "")] [ExpectedWarning ("IL2026", "StaticEvent.remove")] - [ExpectedWarning ("IL3050", "StaticEvent.remove", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "StaticEvent.remove", Tool.NativeAot, "")] static void TestDirectReflectionAccess () { typeof (WithRequires).GetEvent (nameof (WithRequires.StaticEvent)); @@ -894,41 +894,41 @@ class DerivedWithRequires : WithRequires } [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.PrivateStaticProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.PrivateStaticProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.get")] - [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.set")] - [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.get")] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.set")] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.set", Tool.NativeAot, "")] static void TestDAMAccess () { typeof (WithRequires).RequiresPublicProperties (); @@ -939,25 +939,25 @@ static void TestDAMAccess () } [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.PrivateStaticProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.PrivateStaticProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.get")] - [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.set")] - [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.get")] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.set")] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.set", Tool.NativeAot, "")] static void TestDirectReflectionAccess () { typeof (WithRequires).GetProperty (nameof (WithRequires.StaticProperty)); @@ -968,37 +968,37 @@ static void TestDirectReflectionAccess () typeof (DerivedWithRequires).GetProperty (nameof (DerivedWithRequires.DerivedStaticProperty)); } - [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", Tool.NativeAot, "")] [DynamicDependency (nameof (WithRequires.StaticProperty), typeof (WithRequires))] [DynamicDependency (nameof (WithRequires.InstanceProperty), typeof (WithRequires))] // Doesn't warn [DynamicDependency (DynamicallyAccessedMemberTypes.PublicProperties, typeof (DerivedWithoutRequires))] // Doesn't warn - [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.set", Tool.NativeAot, "")] [DynamicDependency (DynamicallyAccessedMemberTypes.PublicProperties, typeof (DerivedWithRequires))] static void TestDynamicDependencyAccess () { @@ -1014,21 +1014,21 @@ class BaseForDAMAnnotatedClass [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] [RequiresUnreferencedCode ("This class is dangerous")] [RequiresDynamicCode ("This class is dangerous")] - [ExpectedWarning ("IL2113", "BaseForDAMAnnotatedClass.baseProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2113", "BaseForDAMAnnotatedClass.baseProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2113", "BaseForDAMAnnotatedClass.baseProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2113", "BaseForDAMAnnotatedClass.baseProperty.set", Tool.Trimmer | Tool.NativeAot, "")] class DAMAnnotatedClass : BaseForDAMAnnotatedClass { public static int publicProperty { - [ExpectedWarning ("IL2112", "DAMAnnotatedClass.publicProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "DAMAnnotatedClass.publicProperty.get", Tool.Trimmer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL2112", "DAMAnnotatedClass.publicProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "DAMAnnotatedClass.publicProperty.set", Tool.Trimmer | Tool.NativeAot, "")] set; } static int privateProperty { - [ExpectedWarning ("IL2112", "DAMAnnotatedClass.privateProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "DAMAnnotatedClass.privateProperty.get", Tool.Trimmer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL2112", "DAMAnnotatedClass.privateProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "DAMAnnotatedClass.privateProperty.set", Tool.Trimmer | Tool.NativeAot, "")] set; } } @@ -1064,7 +1064,7 @@ public int PropertyOnAttribute { [AttributeWithRequires (PropertyOnAttribute = 42)] [ExpectedWarning ("IL2026", "AttributeWithRequires.AttributeWithRequires()")] - [ExpectedWarning ("IL3050", "AttributeWithRequires.AttributeWithRequires()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "AttributeWithRequires.AttributeWithRequires()", Tool.Analyzer | Tool.NativeAot, "")] static void KeepFieldOnAttributeInner () { } static void KeepFieldOnAttribute () @@ -1114,7 +1114,7 @@ public static void Test () { } } [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { TestClass.Test (); @@ -1142,7 +1142,7 @@ public class ClassWithRequires // https://github.com/dotnet/linker/issues/3142 // Instance fields get generic warnings but static fields don't. - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] public RequiresAll instanceField; [RequiresOnCtor] @@ -1150,7 +1150,7 @@ public class ClassWithRequires // https://github.com/dotnet/linker/issues/3140 // Instance fields get attribute warnings but static fields don't. - [ExpectedWarning ("IL2026", "--RequiresOnCtorAttribute--", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", "--RequiresOnCtorAttribute--", Tool.Trimmer, "")] [RequiresOnCtor] public int instanceFieldWithAttribute; @@ -1212,7 +1212,7 @@ public class GenericAnnotatedWithWarningWithRequires<[DynamicallyAccessedMembers [ExpectedWarning ("IL2026", "--GenericClassWithWarningWithRequires--")] [ExpectedWarning ("IL2026", "--ClassWithWarningWithRequires--")] [ExpectedWarning ("IL2026", "--GenericAnnotatedWithWarningWithRequires--")] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] public static void Test (ClassWithRequires inst = null) { var f = ClassWithRequires.field; @@ -1244,7 +1244,7 @@ public static void Method () { } } [ExpectedWarning ("IL2026", "--ConstClassWithRequires--", nameof (ConstClassWithRequires.Method))] - [ExpectedWarning ("IL3050", "--ConstClassWithRequires--", nameof (ConstClassWithRequires.Method), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--ConstClassWithRequires--", nameof (ConstClassWithRequires.Method), Tool.Analyzer | Tool.NativeAot, "")] static void TestClassWithRequires () { var a = ConstClassWithRequires.Message; @@ -1263,7 +1263,7 @@ public static void Method () { } } [ExpectedWarning ("IL2026", "--ConstClassWithRequiresUsingField--", nameof (ConstClassWithRequiresUsingField.Method))] - [ExpectedWarning ("IL3050", "--ConstClassWithRequiresUsingField--", nameof (ConstClassWithRequiresUsingField.Method), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--ConstClassWithRequiresUsingField--", nameof (ConstClassWithRequiresUsingField.Method), Tool.Analyzer | Tool.NativeAot, "")] static void TestClassUsingFieldInAttribute () { ConstClassWithRequiresUsingField.Method (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnStaticConstructor.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnStaticConstructor.cs index 98fbe6876f0aef..cfd8bfd9145f37 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnStaticConstructor.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnStaticConstructor.cs @@ -30,8 +30,8 @@ public static void Main () class StaticCtor { [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2116", "StaticCtor..cctor()")] [RequiresUnreferencedCode ("Message for --TestStaticCtor--")] static StaticCtor () @@ -48,8 +48,8 @@ static void TestStaticCctorRequires () [RequiresUnreferencedCode ("Message for --StaticCtorOnTypeWithRequires--")] class StaticCtorOnTypeWithRequires { - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static StaticCtorOnTypeWithRequires () => MethodWithRequires (); } @@ -70,8 +70,8 @@ static void TestRunClassConstructorOnTypeWithRequires () class StaticCtorForRunClassConstructorWithRequires { [ExpectedWarning ("IL2116")] - [ExpectedWarning ("IL3004", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3056", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3004", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3056", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message for --StaticCtorOnTypeWithRequires--")] [RequiresAssemblyFiles ("Message for --StaticCtorOnTypeWithRequires--")] [RequiresDynamicCode ("Message for --StaticCtorOnTypeWithRequires--")] @@ -118,8 +118,8 @@ static void TestStaticCtorMarkingIsTriggeredByFieldAccessOnExplicitLayout () class StaticCtorTriggeredByMethodCall { [ExpectedWarning ("IL2116", "StaticCtorTriggeredByMethodCall..cctor()")] - [ExpectedWarning ("IL3004", "StaticCtorTriggeredByMethodCall..cctor()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3056", "StaticCtorTriggeredByMethodCall..cctor()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3004", "StaticCtorTriggeredByMethodCall..cctor()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3056", "StaticCtorTriggeredByMethodCall..cctor()", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message for --StaticCtorTriggeredByMethodCall.Cctor--")] [RequiresAssemblyFiles ("Message for --StaticCtorTriggeredByMethodCall.Cctor--")] [RequiresDynamicCode ("Message for --StaticCtorTriggeredByMethodCall.Cctor--")] @@ -137,8 +137,8 @@ public void TriggerStaticCtorMarking () [ExpectedWarning ("IL2026", "--StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--")] - [ExpectedWarning ("IL3002", "--StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--", Tool.Analyzer | Tool.NativeAot, "")] static void TestStaticCtorTriggeredByMethodCall () { new StaticCtorTriggeredByMethodCall ().TriggerStaticCtorMarking (); @@ -146,9 +146,9 @@ static void TestStaticCtorTriggeredByMethodCall () class TypeIsBeforeFieldInit { - [ExpectedWarning ("IL2026", "Message from --TypeIsBeforeFieldInit.AnnotatedMethod--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", "Message from --TypeIsBeforeFieldInit.AnnotatedMethod--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "Message from --TypeIsBeforeFieldInit.AnnotatedMethod--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "Message from --TypeIsBeforeFieldInit.AnnotatedMethod--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", "Message from --TypeIsBeforeFieldInit.AnnotatedMethod--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "Message from --TypeIsBeforeFieldInit.AnnotatedMethod--", Tool.Analyzer, "")] public static int field = AnnotatedMethod (); [RequiresUnreferencedCode ("Message from --TypeIsBeforeFieldInit.AnnotatedMethod--")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs index b9ac10e61c11aa..4623dd6355fc1f 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs @@ -46,8 +46,8 @@ public override void VirtualMethodRequires () } [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestCallOnBase () { var tmp = new BaseType (); @@ -55,8 +55,8 @@ static void TestCallOnBase () } [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestCallOnOverride () { var tmp = new TypeWhichOverridesMethod (); @@ -64,8 +64,8 @@ static void TestCallOnOverride () } [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestCallOnOverrideViaBase () { BaseType tmp = new TypeWhichOverridesMethod (); @@ -73,11 +73,11 @@ static void TestCallOnOverrideViaBase () } [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TypeWhichOverridesMethod.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWhichOverridesMethod.VirtualMethodRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TypeWhichOverridesMethod.VirtualMethodRequires--", Tool.NativeAot, "")] static void TestDirectReflectionAccess () { BaseType tmp = new TypeWhichOverridesMethod (); @@ -90,11 +90,11 @@ static void TestDirectReflectionAccess () } [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TypeWhichOverridesMethod.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWhichOverridesMethod.VirtualMethodRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TypeWhichOverridesMethod.VirtualMethodRequires--", Tool.NativeAot, "")] static void TestAnnotatedReflectionAccess() { CallMethodWithRequiresOnInstance(new TypeWhichOverridesMethod ()); @@ -133,8 +133,8 @@ public override int VirtualPropertyRequires { } [ExpectedWarning ("IL2026", "--PropertyBaseType.VirtualPropertyRequires--")] - [ExpectedWarning ("IL3002", "--PropertyBaseType.VirtualPropertyRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--PropertyBaseType.VirtualPropertyRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--PropertyBaseType.VirtualPropertyRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--PropertyBaseType.VirtualPropertyRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void CallOnDerived () { var tmp = new TypeWhichOverridesProperty (); @@ -171,8 +171,8 @@ public void MethodWithRequires () } [ExpectedWarning ("IL2026", "--IRequires.MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--IRequires.MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--IRequires.MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--IRequires.MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--IRequires.MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestCallViaInterface () { IRequires inst = new ImplementationClass (); @@ -180,8 +180,8 @@ static void TestCallViaInterface () } [ExpectedWarning ("IL2026", "--ImplementationClass.RequiresMethod--")] - [ExpectedWarning ("IL3002", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--ImplementationClass.RequiresMethod--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--ImplementationClass.RequiresMethod--", Tool.Analyzer | Tool.NativeAot, "")] static void TestCallViaImplementationClass () { ImplementationClass inst = new ImplementationClass (); @@ -189,8 +189,8 @@ static void TestCallViaImplementationClass () } [ExpectedWarning ("IL2026", "--ImplementationClass.RequiresMethod--")] - [ExpectedWarning ("IL3002", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--ImplementationClass.RequiresMethod--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--ImplementationClass.RequiresMethod--", Tool.NativeAot, "")] static void TestDirectReflectionAccess () { typeof (ImplementationClass).GetMethod ("MethodWithRequires").Invoke (new ImplementationClass (), Array.Empty ()); @@ -202,8 +202,8 @@ static void TestDirectReflectionAccess () } [ExpectedWarning ("IL2026", "--ImplementationClass.RequiresMethod--")] - [ExpectedWarning ("IL3002", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--ImplementationClass.RequiresMethod--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--ImplementationClass.RequiresMethod--", Tool.NativeAot, "")] static void TestAnnotatedReflectionAccess () { CallMethodWithRequiresOnInstance (new ImplementationClass ()); @@ -240,8 +240,8 @@ public override DerivedReturnType GetRequires () } [ExpectedWarning ("IL2026", "--CovariantReturnDerived.GetRequires--")] - [ExpectedWarning ("IL3002", "--CovariantReturnDerived.GetRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--CovariantReturnDerived.GetRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--CovariantReturnDerived.GetRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--CovariantReturnDerived.GetRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void CallOnDerived () { var tmp = new CovariantReturnDerived (); @@ -276,8 +276,8 @@ public override DerivedReturnType GetRequires () } [ExpectedWarning ("IL2026", "--CovariantReturnViaLdftn.Derived.GetRequires--")] - [ExpectedWarning ("IL3002", "--CovariantReturnViaLdftn.Derived.GetRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--CovariantReturnViaLdftn.Derived.GetRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--CovariantReturnViaLdftn.Derived.GetRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--CovariantReturnViaLdftn.Derived.GetRequires--", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { var tmp = new Derived (); @@ -305,12 +305,12 @@ public virtual void RUCMethod () { } [ExpectedWarning ("IL2026", "Message for --NewSlotVirtual.Base.RUCMethod--")] // Reflection triggered warnings are not produced by analyzer for RDC/RAS - [ExpectedWarning ("IL3002", "Message for --NewSlotVirtual.Base.RUCMethod--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --NewSlotVirtual.Base.RUCMethod--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message for --NewSlotVirtual.Base.RUCMethod--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Message for --NewSlotVirtual.Base.RUCMethod--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "Message for --NewSlotVirtual.Derived.RUCMethod--")] // Reflection triggered warnings are not produced by analyzer for RDC/RAS - [ExpectedWarning ("IL3002", "Message for --NewSlotVirtual.Derived.RUCMethod--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --NewSlotVirtual.Derived.RUCMethod--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message for --NewSlotVirtual.Derived.RUCMethod--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Message for --NewSlotVirtual.Derived.RUCMethod--", Tool.NativeAot, "")] public static void Test () { typeof (Derived).RequiresPublicMethods (); @@ -343,11 +343,11 @@ public static void AbstractMethod () { } } [ExpectedWarning ("IL2026", "--StaticInterfaces.IRequires.VirtualMethod--")] - [ExpectedWarning ("IL3002", "--StaticInterfaces.IRequires.VirtualMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--StaticInterfaces.IRequires.VirtualMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--StaticInterfaces.IRequires.VirtualMethod--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--StaticInterfaces.IRequires.VirtualMethod--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--StaticInterfaces.IRequires.AbstractMethod--")] - [ExpectedWarning ("IL3002", "--StaticInterfaces.IRequires.AbstractMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--StaticInterfaces.IRequires.AbstractMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--StaticInterfaces.IRequires.AbstractMethod--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--StaticInterfaces.IRequires.AbstractMethod--", Tool.Analyzer | Tool.NativeAot, "")] static void UseRequiresMethods () where T : IRequires { T.AbstractMethod (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaDataflow.cs index bec62cf5dbc49c..36720cf6a486c6 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaDataflow.cs @@ -60,11 +60,11 @@ public override void VirtualMethodRequires () } [ExpectedWarning ("IL2026", "TypeWhichOverridesMethod.VirtualMethodRequires()", "--TypeWhichOverridesMethod.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "TypeWhichOverridesMethod.VirtualMethodRequires()", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "TypeWhichOverridesMethod.VirtualMethodRequires()", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "TypeWhichOverridesMethod.VirtualMethodRequires()", "--TypeWhichOverridesMethod.VirtualMethodRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "TypeWhichOverridesMethod.VirtualMethodRequires()", "--TypeWhichOverridesMethod.VirtualMethodRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", Tool.NativeAot, "")] static void TestOverriddenVirtualMethod () { MethodWithAnnotatedParameter (typeof (TypeWhichOverridesMethod)); @@ -93,8 +93,8 @@ public TypeWithPublicMethods () { } } [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] - [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", Tool.NativeAot, "")] static void TestAccessOnGenericType () { new TypeWithPublicMethods (); @@ -103,8 +103,8 @@ static void TestAccessOnGenericType () static void MethodWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { } [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] - [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", Tool.NativeAot, "")] static void TestAccessOnGenericMethod () { MethodWithPublicMethods (); @@ -113,8 +113,8 @@ static void TestAccessOnGenericMethod () static void MethodWithPublicMethodsInference<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> (T instance) { } [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] - [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", Tool.NativeAot, "")] static void TestAccessOnGenericMethodWithInferenceOnMethod () { MethodWithPublicMethodsInference (new TypeWithRequiresMethod ()); @@ -138,9 +138,9 @@ 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)] + [ExpectedWarning ("IL2026", "--RequiresInDynamicDependency--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--RequiresInDynamicDependency--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--RequiresInDynamicDependency--", Tool.NativeAot, "")] [DynamicDependency ("RequiresInDynamicDependency")] public static void Test () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaXml.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaXml.cs index ab0ecd81cab7ed..eb0c4fcde0a1af 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaXml.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaXml.cs @@ -17,7 +17,7 @@ class RequiresViaXml // The second attribute is added through link attribute XML [RequiresUnreferencedCode ("Message for --MethodWithDuplicateRequiresAttribute--")] - [ExpectedWarning ("IL2027", "RequiresUnreferencedCodeAttribute", nameof (MethodWithDuplicateRequiresAttribute), ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2027", "RequiresUnreferencedCodeAttribute", nameof (MethodWithDuplicateRequiresAttribute), Tool.Trimmer, "")] static void MethodWithDuplicateRequiresAttribute () { } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresWithCopyAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresWithCopyAssembly.cs index 91485b261a5fdc..e935d941878588 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresWithCopyAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresWithCopyAssembly.cs @@ -29,11 +29,11 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class RequiresWithCopyAssembly { [ExpectedWarning ("IL2026", "--IDerivedInterface.MethodInDerivedInterface--")] - [ExpectedWarning ("IL3002", "--IDerivedInterface.MethodInDerivedInterface--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--IDerivedInterface.MethodInDerivedInterface--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--IDerivedInterface.MethodInDerivedInterface--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--IDerivedInterface.MethodInDerivedInterface--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--IBaseInterface.MethodInBaseInterface--")] - [ExpectedWarning ("IL3002", "--IBaseInterface.MethodInBaseInterface--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--IBaseInterface.MethodInBaseInterface--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--IBaseInterface.MethodInBaseInterface--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--IBaseInterface.MethodInBaseInterface--", Tool.NativeAot, "")] public static void Main () { TestRequiresInMethodFromCopiedAssembly (); @@ -42,8 +42,8 @@ public static void Main () } [ExpectedWarning ("IL2026", "--Method--")] - [ExpectedWarning ("IL3002", "--Method--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--Method--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--Method--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--Method--", Tool.Analyzer | Tool.NativeAot, "")] static void TestRequiresInMethodFromCopiedAssembly () { var tmp = new RequiresInCopyAssembly (); @@ -51,8 +51,8 @@ static void TestRequiresInMethodFromCopiedAssembly () } [ExpectedWarning ("IL2026", "--MethodCalledThroughReflection--")] - [ExpectedWarning ("IL3002", "--MethodCalledThroughReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodCalledThroughReflection--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodCalledThroughReflection--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodCalledThroughReflection--", Tool.NativeAot, "")] static void TestRequiresThroughReflectionInMethodFromCopiedAssembly () { typeof (RequiresInCopyAssembly) diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/SingleFile/SingleFileIntrinsics.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/SingleFile/SingleFileIntrinsics.cs index 5273af0230c104..617e286e1e641d 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/SingleFile/SingleFileIntrinsics.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/SingleFile/SingleFileIntrinsics.cs @@ -27,7 +27,7 @@ public static void Main () TestAssemblyGetFilesSuppressedByRAF (); } - [ExpectedWarning("IL3000", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning("IL3000", Tool.Analyzer | Tool.NativeAot, "")] static void TestAssemblyLocation() { var a = typeof (SingleFileIntrinsics).Assembly.Location; @@ -39,7 +39,7 @@ static void TestAssemblyLocationSuppressedByRAF() var a = typeof (SingleFileIntrinsics).Assembly.Location; } - [ExpectedWarning ("IL3000", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3000", Tool.Analyzer | Tool.NativeAot, "")] static void TestAssemblyNameCodeBase() { var a = typeof (SingleFileIntrinsics).Assembly.GetName ().CodeBase; @@ -51,7 +51,7 @@ static void TestAssemblyNameCodeBaseSuppressedByRAF () var a = typeof (SingleFileIntrinsics).Assembly.GetName ().CodeBase; } - [ExpectedWarning ("IL3000", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3000", Tool.Analyzer | Tool.NativeAot, "")] static void TestAssemblyNameEscapedCodeBase () { var a = typeof (SingleFileIntrinsics).Assembly.GetName ().EscapedCodeBase; @@ -63,7 +63,7 @@ static void TestAssemblyNameEscapedCodeBaseSuppressedByRAF () var a = typeof (SingleFileIntrinsics).Assembly.GetName ().EscapedCodeBase; } - [ExpectedWarning ("IL3001", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3001", Tool.Analyzer | Tool.NativeAot, "")] static void TestAssemblyGetFile() { var a = typeof (SingleFileIntrinsics).Assembly.GetFile ("unknown"); @@ -75,8 +75,8 @@ static void TestAssemblyGetFileSuppressedByRAF () var a = typeof (SingleFileIntrinsics).Assembly.GetFile ("unknown"); } - [ExpectedWarning ("IL3001", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3001", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3001", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3001", Tool.Analyzer | Tool.NativeAot, "")] static void TestAssemblyGetFiles () { var a = typeof (SingleFileIntrinsics).Assembly.GetFiles (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutions.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutions.cs index e34f2b4bbfd3fc..b4723f3505437f 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutions.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutions.cs @@ -93,8 +93,8 @@ static void TestGuardAssemblyFiles () RequiresAssemblyFiles (); } - [ExpectedWarning ("IL4000", nameof (RequiresDynamicCodeAttribute), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresDynamicCodeAttribute), Tool.Analyzer, "")] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof (RequiresDynamicCodeAttribute))] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool GuardDynamicCodeAndUnreferencedCode => RuntimeFeature.IsDynamicCodeSupported && TestFeatures.IsUnreferencedCodeSupported; @@ -152,7 +152,7 @@ static void TestIndirectGuard () [FeatureSwitchDefinition ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.DefineFeatureGuard.FeatureSwitch")] static bool FeatureSwitch => AppContext.TryGetSwitch ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.DefineFeatureGuard.FeatureSwitch", out bool isEnabled) && isEnabled; - [ExpectedWarning ("IL2026", ProducedBy = Tool.Analyzer)] // Analyzer doesn't respect FeatureSwitchDefinition or feature settings + [ExpectedWarning ("IL2026", Tool.Analyzer, "")] // Analyzer doesn't respect FeatureSwitchDefinition or feature settings [ExpectedInstructionSequence (new[] { "nop", "ldc.i4.0", @@ -169,7 +169,7 @@ static void TestFeatureSwitch () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureSwitchDefinition ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.DefineFeatureGuard.FeatureSwitchAndGuard")] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool FeatureSwitchAndGuard => AppContext.TryGetSwitch ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.DefineFeatureGuard.FeatureSwitchAndGuard", out bool isEnabled) && isEnabled; @@ -264,7 +264,7 @@ public static void Test () [Kept] class FeatureGuardPrecedence { - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureSwitchDefinition ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.FeatureGuardPrecedence.GuardAndSwitch")] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool GuardAndSwitch => AppContext.TryGetSwitch ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.FeatureGuardPrecedence.GuardAndSwitch", out bool isEnabled) && isEnabled; @@ -281,7 +281,7 @@ class FeatureGuardPrecedence { "ret" })] // ILLink/ILCompiler ignore FeatureGuard on properties that also have FeatureSwitchDefinition - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "")] static void TestSwitchWinsOverGuard () { if (GuardAndSwitch) @@ -291,7 +291,7 @@ static void TestSwitchWinsOverGuard () [Kept] [KeptAttributeAttribute (typeof (FeatureSwitchDefinitionAttribute))] [KeptAttributeAttribute (typeof (FeatureGuardAttribute))] - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureSwitchDefinition ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.FeatureGuardPrecedence.GuardAndSwitchNotSet")] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool GuardAndSwitchNotSet { @@ -301,7 +301,7 @@ static bool GuardAndSwitchNotSet { [Kept] // No IL modifications because feature is not set, and FeatureGuard is ignored due to FeatureSwitchDefinition. - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "")] static void TestSwitchNotSetWinsOverGuard () { if (GuardAndSwitchNotSet) @@ -322,7 +322,7 @@ static void TestSwitchNotSetWinsOverGuard () "nop", "ret" })] - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "")] static void TestXmlWinsOverGuard () { if (GuardWithXml) @@ -331,7 +331,7 @@ static void TestXmlWinsOverGuard () [KeptAttributeAttribute (typeof (FeatureSwitchDefinitionAttribute))] [KeptAttributeAttribute (typeof (FeatureGuardAttribute))] - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureSwitchDefinition ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.FeatureGuardPrecedence.SwitchWithXml")] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool SwitchWithXml => AppContext.TryGetSwitch ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.FeatureGuardPrecedence.SwitchWithXml", out bool isEnabled) && isEnabled; @@ -348,7 +348,7 @@ static void TestXmlWinsOverGuard () "nop", "ret" })] - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "")] static void TestXmlWinsOverSwitch () { if (SwitchWithXml) RequiresUnreferencedCode (); @@ -356,7 +356,7 @@ static void TestXmlWinsOverSwitch () { [KeptAttributeAttribute (typeof (FeatureSwitchDefinitionAttribute))] [KeptAttributeAttribute (typeof (FeatureGuardAttribute))] - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureSwitchDefinition ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardPrecedence.GuardAndSwitchWithXml")] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool GuardAndSwitchWithXml => AppContext.TryGetSwitch ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.FeatureGuardPrecedence.GuardAndSwitchWithXml", out bool isEnabled) && isEnabled; @@ -373,7 +373,7 @@ static void TestXmlWinsOverSwitch () { "nop", "ret" })] - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "")] static void TestXmlWinsOverGuardAndSwitch () { if (GuardAndSwitchWithXml) RequiresUnreferencedCode (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutionsDisabled.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutionsDisabled.cs index 198595d79394df..725f849d9093c2 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutionsDisabled.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutionsDisabled.cs @@ -25,7 +25,7 @@ public static void Main () } [Kept] - [ExpectedWarning ("IL4000", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", Tool.Analyzer, "")] [KeptAttributeAttribute (typeof (FeatureGuardAttribute))] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool GuardUnreferencedCode { @@ -46,7 +46,7 @@ static void TestGuard () static bool FeatureSwitch => throw null; [Kept] - [ExpectedWarning ("IL2026", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", Tool.Analyzer, "")] // Feature switches are still substituted when feature guard substitutions are disabled [ExpectBodyModified] static void TestFeatureSwitch () diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/ResourceSubstitutions.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/ResourceSubstitutions.cs index 9bdf9075dae9bc..d52432adfb10db 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/ResourceSubstitutions.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/ResourceSubstitutions.cs @@ -15,4 +15,4 @@ public static void Main () { } } -} \ No newline at end of file +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFeatureSubstitutions.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFeatureSubstitutions.cs index 2f271f000919f2..ac8cf603419363 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFeatureSubstitutions.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFeatureSubstitutions.cs @@ -43,7 +43,7 @@ class ReportRedundantSuppressionWhenTrimmerIncompatibleCodeDisabled // With feature switched to false, the trimming tools see only the 'else' branch. // The 'else' branch contains trimmer-compatible code, the trimming tools identifies the suppression as redundant. - [ExpectedWarning ("IL2121", "IL2072", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2072", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2072")] public static void Test () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFromXML.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFromXML.cs index 4d669f696fc225..aab9f007288864 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFromXML.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFromXML.cs @@ -8,8 +8,8 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression { [SkipKeptItemsValidation] [ExpectedNoWarnings] - [ExpectedWarning ("IL2121", "IL2026", ProducedBy = Tool.Trimmer, FileName = "DetectRedundantSuppressionsFromXML.xml", SourceLine = 7)] - [ExpectedWarning ("IL2121", "IL2109", ProducedBy = Tool.Trimmer, FileName = "DetectRedundantSuppressionsFromXML.xml", SourceLine = 12)] + [ExpectedWarning ("IL2121", "IL2026", Tool.Trimmer, "", FileName = "DetectRedundantSuppressionsFromXML.xml", SourceLine = 7)] + [ExpectedWarning ("IL2121", "IL2109", Tool.Trimmer, "", FileName = "DetectRedundantSuppressionsFromXML.xml", SourceLine = 12)] [SetupLinkAttributesFile ("DetectRedundantSuppressionsFromXML.xml")] public class DetectRedundantSuppressionsFromXML { @@ -32,4 +32,4 @@ static void DoNotTriggerWarning () { } class DoNotTriggerWarningType { } } } -} \ No newline at end of file +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInAssembly.cs index b1b985278a0a56..38995365302402 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInAssembly.cs @@ -4,7 +4,7 @@ using System.Diagnostics.CodeAnalysis; using Mono.Linker.Tests.Cases.Expectations.Assertions; -[assembly: ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] +[assembly: ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [assembly: UnconditionalSuppressMessage ("Test", "IL2071:Redundant suppression, warning is not issued in this assembly")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInCompilerGeneratedCode.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInCompilerGeneratedCode.cs index a707584bef3655..54082fccd74e5a 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInCompilerGeneratedCode.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInCompilerGeneratedCode.cs @@ -34,7 +34,7 @@ public class RedundantSuppressionOnLocalMethod { public static void Test () { - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] void LocalMethod () { @@ -52,7 +52,7 @@ public static void Test () Enumerable (); } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] static IEnumerable Enumerable () { @@ -63,7 +63,7 @@ static IEnumerable Enumerable () public class RedundantSuppressionInAsyncBody { - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public static async void Test () { @@ -71,7 +71,7 @@ public static async void Test () await MethodAsync (); } - [ExpectedWarning ("IL2121", "IL2070", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2070", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2070")] static async Task MethodAsync () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypes.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypes.cs index 56998d29aee59a..884ceb4a6c81b5 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypes.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypes.cs @@ -50,7 +50,7 @@ public static string TrimmerCompatibleMethod () return "test"; } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public class RedundantSuppressionOnType { @@ -62,7 +62,7 @@ public static void Test () public class RedundantSuppressionOnMethod { - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public static void Test () { @@ -77,7 +77,7 @@ public static void Test () NestedType.TrimmerCompatibleMethod (); } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public class NestedType { @@ -96,7 +96,7 @@ public static void Test () } public static string TrimmerCompatibleProperty { - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] get { return TrimmerCompatibleMethod (); @@ -112,7 +112,7 @@ public static void Test () TrimmerCompatibleProperty = "test"; } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public static string TrimmerCompatibleProperty { get { @@ -131,7 +131,7 @@ public static void Test () var property = TrimmerCompatibleProperty; } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public static string TrimmerCompatibleProperty { get { @@ -147,7 +147,7 @@ public static void Test () TrimmerCompatibleProperty = "test"; } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public static string TrimmerCompatibleProperty { set { @@ -163,7 +163,7 @@ public static void Test () typeof (RedundantSuppressionOnPropertyAccessedByReflection).GetProperty ("TrimmerCompatibleProperty"); } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public static string TrimmerCompatibleProperty { get { @@ -185,7 +185,7 @@ static void EventSubscriber (object sender, EventArgs e) } public static event EventHandler TrimmerCompatibleEvent { - [ExpectedWarning ("IL2121", "IL2072", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2072", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2072")] add { TrimmerCompatibleMethod (); } remove { } @@ -204,7 +204,7 @@ static void EventSubscriber (object sender, EventArgs e) } - [ExpectedWarning ("IL2121", "IL2072", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2072", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2072")] public static event EventHandler TrimmerCompatibleEvent { add { TrimmerCompatibleMethod (); } @@ -219,7 +219,7 @@ public static void Test () typeof (RedundantSuppressionOnEventAccessedByReflection).GetEvent ("TrimmerCompatibleEvent"); } - [ExpectedWarning ("IL2121", "IL2072", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2072", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2072")] public static event EventHandler TrimmerCompatibleEvent { add { TrimmerCompatibleMethod (); } @@ -227,15 +227,15 @@ public static event EventHandler TrimmerCompatibleEvent { } } - [ExpectedWarning ("IL2121", "IL2072", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2072", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2072")] - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public class MultipleRedundantSuppressions { - [ExpectedWarning ("IL2121", "IL2072", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2072", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2072")] - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public static void Test () { @@ -245,7 +245,7 @@ public static void Test () public class RedundantAndUsedSuppressions { - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] [UnconditionalSuppressMessage ("Test", "IL2072")] public static void Test () @@ -317,7 +317,7 @@ public static void Test () MethodMarkedRUC (); } - [ExpectedWarning ("IL2121", "IL2072", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2072", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2072")] [RequiresUnreferencedCode ("Test")] public static void MethodMarkedRUC () diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypesUsingTarget.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypesUsingTarget.cs index 5991e418197f08..6b6c3df46f5bf2 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypesUsingTarget.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypesUsingTarget.cs @@ -37,7 +37,7 @@ public static string TrimmerCompatibleMethod () return "test"; } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] public class RedundantSuppressionOnType { public static void Test () @@ -48,7 +48,7 @@ public static void Test () public class RedundantSuppressionOnMethod { - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] public static void Test () { TrimmerCompatibleMethod (); @@ -62,7 +62,7 @@ public static void Test () NestedType.TrimmerCompatibleMethod (); } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] public class NestedType { public static void TrimmerCompatibleMethod () @@ -80,7 +80,7 @@ public static void Test () } public static string TrimmerCompatibleProperty { - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] get { return TrimmerCompatibleMethod (); } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInModule.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInModule.cs index 9dc15690107d39..da7717bc6c14b7 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInModule.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInModule.cs @@ -4,7 +4,7 @@ using System.Diagnostics.CodeAnalysis; using Mono.Linker.Tests.Cases.Expectations.Assertions; -[assembly: ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] +[assembly: ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [module: UnconditionalSuppressMessage ("Test", "IL2071:Redundant suppression, warning is not issued in this assembly")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCompilerGeneratedCode.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCompilerGeneratedCode.cs index 5e3d6023c3b1fa..8506a09edb66c6 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCompilerGeneratedCode.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCompilerGeneratedCode.cs @@ -278,7 +278,7 @@ static void TestCallRUCMethodInLtftnLocalFunction () class DynamicallyAccessedLocalFunction { - [ExpectedWarning ("IL2118", "LocalFunction", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", "LocalFunction", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2026")] public static void TestCallRUCMethodInDynamicallyAccessedLocalFunction () { @@ -426,7 +426,7 @@ static void TestGenericTypeParameterRequirement () class DynamicallyAccessedLambda { - [ExpectedWarning ("IL2118", nameof (TestCallRUCMethodInDynamicallyAccessedLambda), ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", nameof (TestCallRUCMethodInDynamicallyAccessedLambda), Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2026")] public static void TestCallRUCMethodInDynamicallyAccessedLambda () { @@ -440,7 +440,7 @@ public static void TestCallRUCMethodInDynamicallyAccessedLambda () class DynamicallyAccessedLambdaUnused { - [ExpectedWarning ("IL2118", nameof (TestCallRUCMethodInDynamicallyAccessedLambda), ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", nameof (TestCallRUCMethodInDynamicallyAccessedLambda), Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2026")] public static void TestCallRUCMethodInDynamicallyAccessedLambda () { @@ -454,7 +454,7 @@ static void TestSuppressionOnLambda () { var lambda = // https://github.com/dotnet/roslyn/issues/59746 - [ExpectedWarning ("IL2026", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", Tool.Analyzer, "")] [UnconditionalSuppressMessage ("Test", "IL2026")] () => RequiresUnreferencedCodeMethod (); @@ -466,7 +466,7 @@ static void TestSuppressionOnOuterAndLambda () { var lambda = // https://github.com/dotnet/roslyn/issues/59746 - [ExpectedWarning ("IL2026", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", Tool.Analyzer, "")] [UnconditionalSuppressMessage ("Test", "IL2026")] (Type unknownType) => { RequiresUnreferencedCodeMethod (); @@ -577,8 +577,8 @@ static IEnumerable TestDynamicallyAccessedMethodViaGenericMethodParameterIn static event EventHandler TestEvent; // https://github.com/dotnet/runtime/issues/82956 - the suppression is ignored - [ExpectedWarning ("IL2026", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2121", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2121", Tool.Trimmer, "", CompilerGeneratedCode = true)] static void TestLambdaInLocalFunction () { LocalFunction (); @@ -595,7 +595,7 @@ void LocalFunction () // https://github.com/dotnet/runtime/issues/82956 - the suppression is ignored // https://github.com/dotnet/roslyn/issues/59746 [ExpectedWarning ("IL2026", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL2121", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", Tool.Trimmer, "", CompilerGeneratedCode = true)] static void TestLocalFunctionInLambda () { TestEvent += diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs index 2f05eab1e4c666..8b4dd418554a5a 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs @@ -223,7 +223,7 @@ void VerifyExitCode (TrimmedTestCaseResult linkResult, AssemblyDefinition origin Assert.AreEqual (expectedExitCode, linkResult.ExitCode, $"Expected exit code {expectedExitCode} but got {linkResult.ExitCode}. Output was:\n{FormatLinkerOutput()}"); } else { if (linkResult.ExitCode != 0) { - Assert.Fail($"Linker exited with an unexpected non-zero exit code of {linkResult.ExitCode} and output:\n{FormatLinkerOutput()}"); + Assert.Fail ($"Linker exited with an unexpected non-zero exit code of {linkResult.ExitCode} and output:\n{FormatLinkerOutput()}"); } } @@ -734,6 +734,9 @@ void VerifyKeptAllTypesAndMembersInAssembly (AssemblyDefinition linked) static bool IsProducedByLinker (CustomAttribute attr) { + if (attr.Constructor.Parameters.Count > 2 && attr.ConstructorArguments[^2].Type.Name == "Tool") { + return ((Tool)attr.ConstructorArguments[^2].Value).HasFlag (Tool.Trimmer) == true; + } var producedBy = attr.GetPropertyValue ("ProducedBy"); return producedBy is null ? true : ((Tool) producedBy).HasFlag (Tool.Trimmer); } @@ -794,12 +797,29 @@ void VerifyLoggedMessages (AssemblyDefinition original, TrimmingTestLogger logge } break; - case nameof (ExpectedWarningAttribute): { + case nameof (ExpectedWarningAttribute) or nameof(UnexpectedWarningAttribute): { var expectedWarningCode = (string) attr.GetConstructorArgumentValue (0); if (!expectedWarningCode.StartsWith ("IL")) { - Assert.Fail ($"The warning code specified in {nameof (ExpectedWarningAttribute)} must start with the 'IL' prefix. Specified value: '{expectedWarningCode}'."); + Assert.Fail ($"The warning code specified in {attr.AttributeType.Name} must start with the 'IL' prefix. Specified value: '{expectedWarningCode}'."); } - var expectedMessageContains = ((CustomAttributeArgument[]) attr.GetConstructorArgumentValue (1)).Select (a => (string) a.Value).ToArray (); + IEnumerable expectedMessageContains = attr.Constructor.Parameters switch + { + // ExpectedWarningAttribute(string warningCode, params string[] expectedMessages) + // ExpectedWarningAttribute(string warningCode, string[] expectedMessages, Tool producedBy, string issueLink) + [_, { ParameterType.IsArray: true }, ..] + => ((CustomAttributeArgument[])attr.ConstructorArguments[1].Value) + .Select(caa => (string)caa.Value), + // ExpectedWarningAttribute(string warningCode, string expectedMessage1, string expectedMessage2, Tool producedBy, string issueLink) + [_, { ParameterType.Name: "String" }, { ParameterType.Name: "String" }, { ParameterType.Name: "Tool" }, _] + => [(string)attr.GetConstructorArgumentValue(1), (string)attr.GetConstructorArgumentValue(2)], + // ExpectedWarningAttribute(string warningCode, string expectedMessage, Tool producedBy, string issueLink) + [_, { ParameterType.Name: "String" }, { ParameterType.Name: "Tool" }, _] + => [(string)attr.GetConstructorArgumentValue(1)], + // ExpectedWarningAttribute(string warningCode, Tool producedBy, string issueLink) + [_, { ParameterType.Name: "Tool" }, _] + => [], + _ => throw new UnreachableException(), + }; string fileName = (string) attr.GetPropertyValue ("FileName"); int? sourceLine = (int?) attr.GetPropertyValue ("SourceLine"); int? sourceColumn = (int?) attr.GetPropertyValue ("SourceColumn"); From 6f549af4151409467ccf4d2d39ac11716b68d63c Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Fri, 26 Apr 2024 21:28:09 -0400 Subject: [PATCH 146/248] [mono] UnsafeAccessor: Add support for non-generic method instance (#101442) * Support non generic instance * Create helper function for shared code * Use an existing API * Add an assert --------- Co-authored-by: Larry Ewing --- src/mono/mono/metadata/class.c | 2 +- src/mono/mono/metadata/marshal-lightweight.c | 73 ++++++++++++++++--- src/mono/mono/metadata/unsafe-accessor.c | 22 ++---- src/mono/mono/mini/method-to-ir.c | 2 +- .../UnsafeAccessorsTests.Generics.cs | 4 - 5 files changed, 72 insertions(+), 31 deletions(-) diff --git a/src/mono/mono/metadata/class.c b/src/mono/mono/metadata/class.c index 6045628bf49e7f..01888dfbabd57b 100644 --- a/src/mono/mono/metadata/class.c +++ b/src/mono/mono/metadata/class.c @@ -5264,7 +5264,7 @@ mono_class_get_fields_internal (MonoClass *klass, gpointer *iter) * mono_class_get_methods: * \param klass the \c MonoClass to act on * - * This routine is an iterator routine for retrieving the fields in a class. + * This routine is an iterator routine for retrieving the methods in a class. * * You must pass a \c gpointer that points to zero and is treated as an opaque handle to * iterate over all of the elements. When no more values are diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index 6399b315cfd208..245b5dbe572507 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -2371,6 +2371,44 @@ emit_missing_method_error (MonoMethodBuilder *mb, MonoError *failure, const char } } +static MonoMethodSignature * +update_signature (MonoMethod *accessor_method) +{ + MonoClass *accessor_method_class_instance = accessor_method->klass; + MonoClass *accessor_method_class = mono_class_get_generic_type_definition (accessor_method_class_instance); + + const char *accessor_method_name = accessor_method->name; + + gpointer iter = NULL; + MonoMethod *m = NULL; + while ((m = mono_class_get_methods (accessor_method_class, &iter))) { + if (!m) + continue; + + if (strcmp (m->name, accessor_method_name)) + continue; + + return mono_metadata_signature_dup_full (get_method_image (m), mono_method_signature_internal (m)); + } + g_assert_not_reached (); +} + +static MonoMethod * +inflate_method (MonoClass *klass, MonoMethod *method, MonoMethod *accessor_method, MonoError *error) +{ + MonoMethod *result = method; + MonoGenericContext context = { NULL, NULL }; + if (mono_class_is_ginst (klass)) + context.class_inst = mono_class_get_generic_class (klass)->context.class_inst; + if (accessor_method->is_inflated) + context.method_inst = mono_method_get_context (accessor_method)->method_inst; + if ((context.class_inst != NULL) || (context.method_inst != NULL)) + result = mono_class_inflate_generic_method_checked (method, &context, error); + mono_error_assert_ok (error); + + return result; +} + static void emit_unsafe_accessor_ctor_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_method, MonoMethodSignature *sig, MonoGenericContext *ctx, MonoUnsafeAccessorKind kind, const char *member_name) { @@ -2389,12 +2427,17 @@ emit_unsafe_accessor_ctor_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_m return; } - MonoMethodSignature *member_sig = ctor_sig_from_accessor_sig (mb, sig, ctx); - MonoClass *target_class = mono_class_from_mono_type_internal (target_type); ERROR_DECL(find_method_error); - MonoClass *in_class = mono_class_is_ginst (target_class) ? mono_class_get_generic_class (target_class)->container_class : target_class; + if (accessor_method->is_inflated) { + sig = update_signature(accessor_method); + } + + MonoMethodSignature *member_sig = ctor_sig_from_accessor_sig (mb, sig, ctx); + + MonoClass *in_class = mono_class_get_generic_type_definition (target_class); + MonoMethod *target_method = mono_unsafe_accessor_find_ctor (in_class, member_sig, target_class, find_method_error); if (!is_ok (find_method_error) || target_method == NULL) { if (mono_error_get_error_code (find_method_error) == MONO_ERROR_GENERIC) @@ -2404,6 +2447,9 @@ emit_unsafe_accessor_ctor_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_m mono_error_cleanup (find_method_error); return; } + + target_method = inflate_method (target_class, target_method, accessor_method, find_method_error); + g_assert (target_method->klass == target_class); emit_unsafe_accessor_ldargs (mb, sig, 0); @@ -2425,11 +2471,9 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor mono_mb_emit_exception_full (mb, "System", "BadImageFormatException", "Invalid usage of UnsafeAccessorAttribute."); return; } - gboolean hasthis = kind == MONO_UNSAFE_ACCESSOR_METHOD; - MonoType *target_type = sig->params[0]; - - MonoMethodSignature *member_sig = method_sig_from_accessor_sig (mb, hasthis, sig, ctx); + MonoType *target_type = sig->params[0]; + gboolean hasthis = kind == MONO_UNSAFE_ACCESSOR_METHOD; MonoClass *target_class = mono_class_from_mono_type_internal (target_type); if (hasthis && m_class_is_valuetype (target_class) && !m_type_is_byref (target_type)) { @@ -2438,7 +2482,14 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor } ERROR_DECL(find_method_error); - MonoClass *in_class = mono_class_is_ginst (target_class) ? mono_class_get_generic_class (target_class)->container_class : target_class; + if (accessor_method->is_inflated) { + sig = update_signature(accessor_method); + } + + MonoMethodSignature *member_sig = method_sig_from_accessor_sig (mb, hasthis, sig, ctx); + + MonoClass *in_class = mono_class_get_generic_type_definition (target_class); + MonoMethod *target_method = NULL; if (!ctor_as_method) target_method = mono_unsafe_accessor_find_method (in_class, member_name, member_sig, target_class, find_method_error); @@ -2452,11 +2503,15 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor mono_error_cleanup (find_method_error); return; } + + target_method = inflate_method (target_class, target_method, accessor_method, find_method_error); + if (!hasthis && target_method->klass != target_class) { emit_missing_method_error (mb, find_method_error, member_name); return; } - g_assert (target_method->klass == target_class); // are instance methods allowed to be looked up using inheritance? + + g_assert (target_method->klass == target_class); emit_unsafe_accessor_ldargs (mb, sig, !hasthis ? 1 : 0); diff --git a/src/mono/mono/metadata/unsafe-accessor.c b/src/mono/mono/metadata/unsafe-accessor.c index e7287a00c46175..584b2914658699 100644 --- a/src/mono/mono/metadata/unsafe-accessor.c +++ b/src/mono/mono/metadata/unsafe-accessor.c @@ -14,7 +14,7 @@ #include "mono/metadata/class-internals.h" #include "mono/utils/mono-error-internals.h" #include "mono/metadata/unsafe-accessor.h" - +#include static MonoMethod * @@ -134,7 +134,10 @@ find_method_slow (MonoClass *klass, const char *name, const char *qname, const c return precise_match; } mono_error_set_generic_error (error, "System.Reflection", "AmbiguousMatchException", "Ambiguity in binding of UnsafeAccessorAttribute."); - return NULL; + result->i = -1; + result->m = NULL; + result->matched = FALSE; + return result; } matched = TRUE; result->i = i; @@ -176,23 +179,10 @@ find_method_in_class_unsafe_accessor (MonoClass *klass, const char *name, const if (!is_ok(error) && mono_error_get_error_code (error) == MONO_ERROR_GENERIC) return NULL; - int mcount = mono_class_get_method_count (klass); g_assert (result != NULL); if (result->matched) { - if (result->i < mcount) - return mono_class_get_method_by_index (from_class, result->i); - else if (result->m != NULL) { - // FIXME: metadata-update: hack - // it's from a metadata-update, probably - MonoMethod * m = mono_class_inflate_generic_method_full_checked ( - result->m, from_class, mono_class_get_context (from_class), error); - mono_error_assert_ok (error); - g_assert (m != NULL); - g_assert (m->klass == from_class); - g_assert (m->is_inflated); - return m; - } + return result->m; } g_free (result); diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index c8a4fade7d30fa..40905c0ceb48f5 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -7864,7 +7864,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b UNVERIFIED; if (!cfg->gshared) - g_assert (!mono_method_check_context_used (cmethod)); + g_assertf (!mono_method_check_context_used (cmethod), "cmethod is %s", mono_method_get_full_name (cmethod)); CHECK_STACK (n); diff --git a/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs b/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs index e4fb9593dd3ed6..fd867ef222b693 100644 --- a/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs +++ b/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs @@ -140,7 +140,6 @@ sealed class Derived2 : GenericBase } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_InheritanceMethodResolution() { string expect = "abc"; @@ -230,7 +229,6 @@ sealed class Accessors } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_CallCtor() { Console.WriteLine($"Running {nameof(Verify_Generic_CallCtor)}"); @@ -312,7 +310,6 @@ public static void Verify_Generic_GenericTypeNonGenericInstanceMethod() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_GenericTypeGenericInstanceMethod() { Console.WriteLine($"Running {nameof(Verify_Generic_GenericTypeGenericInstanceMethod)}"); @@ -366,7 +363,6 @@ public static void Verify_Generic_GenericTypeNonGenericStaticMethod() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_GenericTypeGenericStaticMethod() { Console.WriteLine($"Running {nameof(Verify_Generic_GenericTypeGenericStaticMethod)}"); From dad01daffc3fa4e257abe8e33cb9f80fbaff71d7 Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Fri, 26 Apr 2024 21:31:59 -0400 Subject: [PATCH 147/248] Intrinsify SpanHelper API's (#101622) --- src/mono/mono/mini/intrinsics.c | 37 ++++++++++++++++++++++++++++++++- src/mono/mono/mini/mini-llvm.c | 32 +++++++++++++++++++++------- src/mono/mono/mini/mini-ops.h | 1 + 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index 4835a84e2c9115..2c629adf59662f 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -283,7 +283,7 @@ llvm_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign } } - if (in_corlib && !strcmp (m_class_get_name (cmethod->klass), "Buffer")) { + if (in_corlib && !strcmp (m_class_get_name (cmethod->klass), "SpanHelpers")) { if (!strcmp (cmethod->name, "Memmove") && fsig->param_count == 3 && m_type_is_byref (fsig->params [0]) && m_type_is_byref (fsig->params [1]) && !cmethod->is_inflated) { MonoBasicBlock *end_bb; NEW_BBLOCK (cfg, end_bb); @@ -304,6 +304,41 @@ llvm_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign ins->sreg3 = args [2]->dreg; // i32/i64 len MONO_ADD_INS (cfg->cbb, ins); MONO_START_BB (cfg, end_bb); + } else if (!strcmp (cmethod->name, "ClearWithoutReferences") && fsig->param_count == 2 && m_type_is_byref (fsig->params [0]) && !cmethod->is_inflated) { + MonoBasicBlock *end_bb; + NEW_BBLOCK (cfg, end_bb); + + // do nothing if len == 0 (even if src is null) + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, 0); + MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, end_bb); + + // throw NRE if src is null + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [0]->dreg, 0); + MONO_EMIT_NEW_COND_EXC (cfg, EQ, "NullReferenceException"); + + MONO_INST_NEW (cfg, ins, OP_MEMSET_ZERO); + ins->sreg1 = args [0]->dreg; // i1* dst + ins->sreg2 = args [1]->dreg; // i32/i64 len + MONO_ADD_INS (cfg->cbb, ins); + MONO_START_BB (cfg, end_bb); + } else if (!strcmp (cmethod->name, "Fill") && fsig->param_count == 3 && m_type_is_byref (fsig->params [0]) && !cmethod->is_inflated) { + MonoBasicBlock *end_bb; + NEW_BBLOCK (cfg, end_bb); + + // do nothing if len == 0 (even if src is null) + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, 0); + MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, end_bb); + + // throw NRE if src is null + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [0]->dreg, 0); + MONO_EMIT_NEW_COND_EXC (cfg, EQ, "NullReferenceException"); + + MONO_INST_NEW (cfg, ins, OP_MEMSET); + ins->sreg1 = args [0]->dreg; // i1* dst + ins->sreg2 = args [1]->dreg; // i8 value + ins->sreg3 = args [2]->dreg; // i32/i64 len + MONO_ADD_INS (cfg->cbb, ins); + MONO_START_BB (cfg, end_bb); } } diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 07bbe7d4e0037a..0c0f4e0cb1f2e7 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -1427,15 +1427,18 @@ convert (EmitContext *ctx, LLVMValueRef v, LLVMTypeRef dtype) } static void -emit_memset (EmitContext *ctx, LLVMValueRef v, LLVMValueRef size, int alignment) +emit_memset (EmitContext *ctx, LLVMValueRef dest, LLVMValueRef val, LLVMValueRef size, int alignment) { LLVMValueRef args [5]; int aindex = 0; - args [aindex ++] = v; - args [aindex ++] = LLVMConstInt (LLVMInt8Type (), 0, FALSE); + args [aindex ++] = dest; + if (val) + args [aindex ++] = val; + else + args [aindex ++] = LLVMConstInt (LLVMInt8Type (), 0, FALSE); args [aindex ++] = size; - args [aindex ++] = LLVMConstInt (LLVMInt1Type (), 0, FALSE); + args [aindex ++] = LLVMConstInt (LLVMInt1Type (), 0, FALSE); // is_volatile call_intrins (ctx, INTRINS_MEMSET, args, ""); } @@ -6159,7 +6162,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) * load it into registers. */ LLVMValueRef buf = build_alloca_llvm_type_name (ctx, pointer_type (ret_type), 0, "ret_buf"); - emit_memset (ctx, buf, LLVMSizeOf (ret_type), 1); + emit_memset (ctx, buf, NULL, LLVMSizeOf (ret_type), 1); int width = mono_type_size (sig->ret, NULL); LLVMValueRef args [] = { @@ -7000,7 +7003,7 @@ MONO_RESTORE_WARNING v = mono_llvm_build_alloca (builder, LLVMInt8Type (), const_int32 (size), MONO_ARCH_FRAME_ALIGNMENT, ""); if (ins->flags & MONO_INST_INIT) - emit_memset (ctx, v, const_int32 (size), MONO_ARCH_FRAME_ALIGNMENT); + emit_memset (ctx, v, NULL, const_int32 (size), MONO_ARCH_FRAME_ALIGNMENT); values [ins->dreg] = v; break; @@ -7013,7 +7016,7 @@ MONO_RESTORE_WARNING v = mono_llvm_build_alloca (builder, LLVMInt8Type (), size, MONO_ARCH_FRAME_ALIGNMENT, ""); if (ins->flags & MONO_INST_INIT) - emit_memset (ctx, v, size, MONO_ARCH_FRAME_ALIGNMENT); + emit_memset (ctx, v, NULL, size, MONO_ARCH_FRAME_ALIGNMENT); values [ins->dreg] = v; break; } @@ -7231,6 +7234,19 @@ MONO_RESTORE_WARNING call_intrins (ctx, INTRINS_MEMMOVE, args, ""); break; } + case OP_MEMSET_ZERO: { + LLVMValueRef dest = convert (ctx, values [ins->sreg1], pointer_type (LLVMInt8Type ())); + LLVMValueRef size = convert (ctx, values [ins->sreg2], LLVMInt64Type ()); + emit_memset (ctx, dest, NULL, size, MONO_ARCH_FRAME_ALIGNMENT); + break; + } + case OP_MEMSET: { + LLVMValueRef dest = convert (ctx, values [ins->sreg1], pointer_type (LLVMInt8Type ())); + LLVMValueRef val = convert (ctx, values [ins->sreg2], LLVMInt8Type ()); + LLVMValueRef size = convert (ctx, values [ins->sreg3], LLVMInt64Type ()); + emit_memset (ctx, dest, val, size, MONO_ARCH_FRAME_ALIGNMENT); + break; + } case OP_NOT_REACHED: LLVMBuildUnreachable (builder); has_terminator = TRUE; @@ -7863,7 +7879,7 @@ MONO_RESTORE_WARNING addresses [ins->dreg] = create_address (ctx, build_named_alloca (ctx, m_class_get_byval_arg (klass), "vzero"), etype); } LLVMValueRef ptr = build_ptr_cast (builder, addresses [ins->dreg]->value, pointer_type (LLVMInt8Type ())); - emit_memset (ctx, ptr, const_int32 (mono_class_value_size (klass, NULL)), 0); + emit_memset (ctx, ptr, NULL, const_int32 (mono_class_value_size (klass, NULL)), 0); break; } case OP_DUMMY_VZERO: diff --git a/src/mono/mono/mini/mini-ops.h b/src/mono/mono/mini/mini-ops.h index ec82dd5de8a8c2..edf7d1b3930db4 100644 --- a/src/mono/mono/mini/mini-ops.h +++ b/src/mono/mono/mini/mini-ops.h @@ -775,6 +775,7 @@ MINI_OP(OP_LDELEMA2D, "ldelema2d", NONE, NONE, NONE) MINI_OP(OP_MEMCPY, "memcpy", NONE, NONE, NONE) /* inlined small memset with constant length */ MINI_OP(OP_MEMSET, "memset", NONE, NONE, NONE) +MINI_OP(OP_MEMSET_ZERO, "memset_zero", NONE, IREG, IREG) /* * A RuntimeType object, the result ldtoken+GetTypeFromHandle. * inst_p0 is a MonoClass. From 09b983ed0d04fd61ee35a739d080f4e8fc04de1b Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Fri, 26 Apr 2024 22:47:39 -0700 Subject: [PATCH 148/248] Allow JIT to know if dynamic pgo is active (#101575) When dynamic PGO is active we would like for all methods to have some profile data, so we don't have to handle a mixture of profiled and unprofiled methods during or after inlining. But to reduce profiling overhead, the JIT will not instrument methods that have straight-line control flow, or flow where all branches lead to throws (aka "minimal profiling"). When the JIT tries to recover profile data for these methods it won't get any data back. SO there is a fairly high volume of these profiled/unprofiled mixtures today and they lead to various poor decisions in the JIT. This change enables the JIT to see if dynamic PGO is active. The JIT does not yet do anything with the information. A subsequent change will have the JIT synthesize data for methods with no profile data in this case. We could also solve this by creating a placeholder PGO schema for theswith no data, but it seems simpler and less resource intensive to have the runtime tell the JIT that dynamic PGO is active. This also changes the JIT GUID for the new API surface. Contributes to #93020. --- src/coreclr/inc/corjit.h | 3 ++- src/coreclr/inc/icorjitinfoimpl_generated.h | 3 ++- src/coreclr/inc/jiteeversionguid.h | 10 +++++----- .../jit/ICorJitInfo_wrapper_generated.hpp | 5 +++-- src/coreclr/jit/compiler.cpp | 7 +++++-- src/coreclr/jit/compiler.h | 1 + .../tools/Common/JitInterface/CorInfoImpl.cs | 3 ++- .../Common/JitInterface/CorInfoImpl_generated.cs | 6 +++--- .../JitInterface/ThunkGenerator/ThunkInput.txt | 2 +- .../aot/jitinterface/jitinterface_generated.h | 7 ++++--- .../tools/superpmi/superpmi-shared/agnostic.h | 1 + .../superpmi/superpmi-shared/methodcontext.cpp | 16 +++++++++++----- .../superpmi/superpmi-shared/methodcontext.h | 4 ++-- .../superpmi-shim-collector/icorjitinfo.cpp | 7 ++++--- .../icorjitinfo_generated.cpp | 5 +++-- .../icorjitinfo_generated.cpp | 5 +++-- .../tools/superpmi/superpmi/icorjitinfo.cpp | 5 +++-- src/coreclr/vm/jitinterface.cpp | 7 +++++-- src/coreclr/vm/jitinterface.h | 3 ++- 19 files changed, 62 insertions(+), 38 deletions(-) diff --git a/src/coreclr/inc/corjit.h b/src/coreclr/inc/corjit.h index 4c012a7b263bf7..18a5be23fdde2d 100644 --- a/src/coreclr/inc/corjit.h +++ b/src/coreclr/inc/corjit.h @@ -452,7 +452,8 @@ class ICorJitInfo : public ICorDynamicInfo uint32_t * pCountSchemaItems, // OUT: pointer to the count of schema items in `pSchema` array. uint8_t ** pInstrumentationData, // OUT: `*pInstrumentationData` is set to the address of the instrumentation data // (pointer will not remain valid after jit completes). - PgoSource * pPgoSource // OUT: value describing source of pgo data + PgoSource * pPgoSource, // OUT: value describing source of pgo data + bool * pDynamicPgo // OUT: dynamic PGO is enabled (valid even when return value is failure) ) = 0; // Allocate a profile buffer for use in the current process diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 98b47dced2beb0..5572a044b9b0aa 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -711,7 +711,8 @@ JITINTERFACE_HRESULT getPgoInstrumentationResults( ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, - ICorJitInfo::PgoSource* pgoSource) override; + ICorJitInfo::PgoSource* pPgoSource, + bool* pDynamicPgo) override; JITINTERFACE_HRESULT allocPgoInstrumentationBySchema( CORINFO_METHOD_HANDLE ftnHnd, diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 743abdaff86aea..79b6397a9111e2 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 = { /* 8f046bcb-ca5f-4692-9277-898b71cb7938 */ - 0x8f046bcb, - 0xca5f, - 0x4692, - {0x92, 0x77, 0x89, 0x8b, 0x71, 0xcb, 0x79, 0x38} +constexpr GUID JITEEVersionIdentifier = { /* 32d71f8e-c1f5-41cb-88cc-4e8504cabf40 */ + 0x32d71f8e, + 0xc1f5, + 0x41cb, + {0x88, 0xcc, 0x4e, 0x85, 0x04, 0xca, 0xbf, 0x40} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index 85db2ec5efffa5..e001c56c26dcbd 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -1666,10 +1666,11 @@ JITINTERFACE_HRESULT WrapICorJitInfo::getPgoInstrumentationResults( ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, - ICorJitInfo::PgoSource* pgoSource) + ICorJitInfo::PgoSource* pPgoSource, + bool* pDynamicPgo) { API_ENTER(getPgoInstrumentationResults); - JITINTERFACE_HRESULT temp = wrapHnd->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pgoSource); + JITINTERFACE_HRESULT temp = wrapHnd->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, pDynamicPgo); API_LEAVE(getPgoInstrumentationResults); return temp; } diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index d0bda29cb30891..60f306307b90cd 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -2791,11 +2791,13 @@ void Compiler::compInitOptions(JitFlags* jitFlags) fgPgoHaveWeights = false; fgPgoSynthesized = false; fgPgoConsistent = false; + fgPgoDynamic = false; if (jitFlags->IsSet(JitFlags::JIT_FLAG_BBOPT)) { - fgPgoQueryResult = info.compCompHnd->getPgoInstrumentationResults(info.compMethodHnd, &fgPgoSchema, - &fgPgoSchemaCount, &fgPgoData, &fgPgoSource); + fgPgoQueryResult = + info.compCompHnd->getPgoInstrumentationResults(info.compMethodHnd, &fgPgoSchema, &fgPgoSchemaCount, + &fgPgoData, &fgPgoSource, &fgPgoDynamic); // a failed result that also has a non-NULL fgPgoSchema // indicates that the ILSize for the method no longer matches @@ -2818,6 +2820,7 @@ void Compiler::compInitOptions(JitFlags* jitFlags) fgPgoData = nullptr; fgPgoSchema = nullptr; fgPgoDisabled = true; + fgPgoDynamic = false; } #ifdef DEBUG // Optionally, enable use of profile data for only some methods. diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 7949058066494d..deb7b97943dc81 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -6285,6 +6285,7 @@ class Compiler unsigned fgPgoInlineeNoPgoSingleBlock; bool fgPgoHaveWeights; bool fgPgoSynthesized; + bool fgPgoDynamic; bool fgPgoConsistent; #ifdef DEBUG diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index ed04f8625d486e..31a5dd68927bd1 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -4261,7 +4261,7 @@ public static void ComputeJitPgoInstrumentationSchema(Func objec } private HRESULT getPgoInstrumentationResults(CORINFO_METHOD_STRUCT_* ftnHnd, ref PgoInstrumentationSchema* pSchema, ref uint countSchemaItems, byte** pInstrumentationData, - ref PgoSource pPgoSource) + ref PgoSource pPgoSource, ref bool pDynamicPgo) { MethodDesc methodDesc = HandleToObject(ftnHnd); @@ -4308,6 +4308,7 @@ private HRESULT getPgoInstrumentationResults(CORINFO_METHOD_STRUCT_* ftnHnd, ref countSchemaItems = pgoResults.countSchemaItems; *pInstrumentationData = pgoResults.pInstrumentationData; pPgoSource = PgoSource.Static; + pDynamicPgo = false; return pgoResults.hr; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index 481c22864356c1..e4ef2264da2556 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -2489,12 +2489,12 @@ private static void _reportFatalError(IntPtr thisHandle, IntPtr* ppException, Co } [UnmanagedCallersOnly] - private static HRESULT _getPgoInstrumentationResults(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* ftnHnd, PgoInstrumentationSchema** pSchema, uint* pCountSchemaItems, byte** pInstrumentationData, PgoSource* pgoSource) + private static HRESULT _getPgoInstrumentationResults(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* ftnHnd, PgoInstrumentationSchema** pSchema, uint* pCountSchemaItems, byte** pInstrumentationData, PgoSource* pPgoSource, bool* pDynamicPgo) { var _this = GetThis(thisHandle); try { - return _this.getPgoInstrumentationResults(ftnHnd, ref *pSchema, ref *pCountSchemaItems, pInstrumentationData, ref *pgoSource); + return _this.getPgoInstrumentationResults(ftnHnd, ref *pSchema, ref *pCountSchemaItems, pInstrumentationData, ref *pPgoSource, ref *pDynamicPgo); } catch (Exception ex) { @@ -2764,7 +2764,7 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[165] = (delegate* unmanaged)&_logMsg; callbacks[166] = (delegate* unmanaged)&_doAssert; callbacks[167] = (delegate* unmanaged)&_reportFatalError; - callbacks[168] = (delegate* unmanaged)&_getPgoInstrumentationResults; + callbacks[168] = (delegate* unmanaged)&_getPgoInstrumentationResults; callbacks[169] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; callbacks[170] = (delegate* unmanaged)&_recordCallSite; callbacks[171] = (delegate* unmanaged)&_recordRelocation; diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 86674ab2b59244..2b78b23547432c 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -331,7 +331,7 @@ FUNCTIONS bool logMsg(unsigned level, const char* fmt, va_list args) int doAssert(const char* szFile, int iLine, const char* szExpr) void reportFatalError(CorJitResult result) - JITINTERFACE_HRESULT getPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t**pInstrumentationData, ICorJitInfo::PgoSource* pgoSource) + JITINTERFACE_HRESULT getPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t**pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource, bool* pDynamicPgo) JITINTERFACE_HRESULT allocPgoInstrumentationBySchema(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, uint32_t countSchemaItems, uint8_t** pInstrumentationData) void recordCallSite(uint32_t instrOffset, CORINFO_SIG_INFO* callSig, CORINFO_METHOD_HANDLE methodHandle) void recordRelocation(void* location, void* locationRW, void* target, uint16_t fRelocType, int32_t addlDelta) diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index db1d0a721d1f15..905ddd41d82b5e 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -179,7 +179,7 @@ struct JitInterfaceCallbacks bool (* logMsg)(void * thisHandle, CorInfoExceptionClass** ppException, unsigned level, const char* fmt, va_list args); int (* doAssert)(void * thisHandle, CorInfoExceptionClass** ppException, const char* szFile, int iLine, const char* szExpr); void (* reportFatalError)(void * thisHandle, CorInfoExceptionClass** ppException, CorJitResult result); - JITINTERFACE_HRESULT (* getPgoInstrumentationResults)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, ICorJitInfo::PgoSource* pgoSource); + JITINTERFACE_HRESULT (* getPgoInstrumentationResults)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource, bool* pDynamicPgo); JITINTERFACE_HRESULT (* allocPgoInstrumentationBySchema)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, uint32_t countSchemaItems, uint8_t** pInstrumentationData); void (* recordCallSite)(void * thisHandle, CorInfoExceptionClass** ppException, uint32_t instrOffset, CORINFO_SIG_INFO* callSig, CORINFO_METHOD_HANDLE methodHandle); void (* recordRelocation)(void * thisHandle, CorInfoExceptionClass** ppException, void* location, void* locationRW, void* target, uint16_t fRelocType, int32_t addlDelta); @@ -1843,10 +1843,11 @@ class JitInterfaceWrapper : public ICorJitInfo ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, - ICorJitInfo::PgoSource* pgoSource) + ICorJitInfo::PgoSource* pPgoSource, + bool* pDynamicPgo) { CorInfoExceptionClass* pException = nullptr; - JITINTERFACE_HRESULT temp = _callbacks->getPgoInstrumentationResults(_thisHandle, &pException, ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pgoSource); + JITINTERFACE_HRESULT temp = _callbacks->getPgoInstrumentationResults(_thisHandle, &pException, ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, pDynamicPgo); if (pException != nullptr) throw pException; return temp; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h index 104a7ae1fabd39..4e34350894ec79 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h @@ -519,6 +519,7 @@ struct Agnostic_GetPgoInstrumentationResults DWORD dataByteCount; DWORD result; DWORD pgoSource; + DWORD dynamicPgo; }; struct Agnostic_GetProfilingHandle diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 05ad1c23a6a2c9..4219aca7ca118b 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -5724,6 +5724,7 @@ void MethodContext::recGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd UINT32* pCountSchemaItems, BYTE** pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource, + bool* pDynamicPgo, HRESULT result) { if (GetPgoInstrumentationResults == nullptr) @@ -5754,6 +5755,7 @@ void MethodContext::recGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd value.dataByteCount = (unsigned)maxOffset; value.result = (DWORD)result; value.pgoSource = (DWORD)*pPgoSource; + value.dynamicPgo = (DWORD)*pDynamicPgo; DWORDLONG key = CastHandle(ftnHnd); GetPgoInstrumentationResults->Add(key, value); @@ -5761,8 +5763,8 @@ void MethodContext::recGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd } void MethodContext::dmpGetPgoInstrumentationResults(DWORDLONG key, const Agnostic_GetPgoInstrumentationResults& value) { - printf("GetPgoInstrumentationResults key ftn-%016" PRIX64 ", value res-%08X schemaCnt-%u profileBufSize-%u source-%u schema{", - key, value.result, value.countSchemaItems, value.dataByteCount, value.pgoSource); + printf("GetPgoInstrumentationResults key ftn-%016" PRIX64 ", value res-%08X schemaCnt-%u profileBufSize-%u source-%u dynamic-%u schema{", + key, value.result, value.countSchemaItems, value.dataByteCount, value.pgoSource, value.dynamicPgo); if (value.countSchemaItems > 0) { @@ -5838,7 +5840,8 @@ HRESULT MethodContext::repGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftn ICorJitInfo::PgoInstrumentationSchema** pSchema, UINT32* pCountSchemaItems, BYTE** pInstrumentationData, - ICorJitInfo::PgoSource* pPgoSource) + ICorJitInfo::PgoSource* pPgoSource, + bool* pDynamicPgo) { DWORDLONG key = CastHandle(ftnHnd); Agnostic_GetPgoInstrumentationResults tempValue = LookupByKeyOrMiss(GetPgoInstrumentationResults, key, ": key %016" PRIX64 "", key); @@ -5848,6 +5851,7 @@ HRESULT MethodContext::repGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftn *pCountSchemaItems = (UINT32)tempValue.countSchemaItems; *pInstrumentationData = (BYTE*)GetPgoInstrumentationResults->GetBuffer(tempValue.data_index); *pPgoSource = (ICorJitInfo::PgoSource)tempValue.pgoSource; + *pDynamicPgo = (bool)tempValue.dynamicPgo; ICorJitInfo::PgoInstrumentationSchema* pOutSchema = (ICorJitInfo::PgoInstrumentationSchema*)AllocJitTempBuffer(tempValue.countSchemaItems * sizeof(ICorJitInfo::PgoInstrumentationSchema)); @@ -7183,7 +7187,8 @@ int MethodContext::dumpMethodIdentityInfoToBuffer(char* buff, int len, bool igno UINT32 schemaCount = 0; BYTE* schemaData = nullptr; ICorJitInfo::PgoSource pgoSource = ICorJitInfo::PgoSource::Unknown; - HRESULT pgoHR = repGetPgoInstrumentationResults(pInfo->ftn, &schema, &schemaCount, &schemaData, &pgoSource); + bool dynamicPgo = false; + HRESULT pgoHR = repGetPgoInstrumentationResults(pInfo->ftn, &schema, &schemaCount, &schemaData, &pgoSource, &dynamicPgo); size_t minOffset = (size_t) ~0; size_t maxOffset = 0; @@ -7281,7 +7286,8 @@ bool MethodContext::hasPgoData(bool& hasEdgeProfile, bool& hasClassProfile, bool ICorJitInfo::PgoInstrumentationSchema* schema = nullptr; UINT32 schemaCount = 0; BYTE* schemaData = nullptr; - HRESULT pgoHR = repGetPgoInstrumentationResults(info.ftn, &schema, &schemaCount, &schemaData, &pgoSource); + bool dynamicPgo; + HRESULT pgoHR = repGetPgoInstrumentationResults(info.ftn, &schema, &schemaCount, &schemaData, &pgoSource, &dynamicPgo); if (SUCCEEDED(pgoHR)) { diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index a530d2f58385be..2af344894e97d8 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -711,9 +711,9 @@ class MethodContext HRESULT repAllocPgoInstrumentationBySchema(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, UINT32 countSchemaItems, BYTE** pInstrumentationData); bool repAllocPgoInstrumentationBySchemaRecorded(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, UINT32 countSchemaItems, BYTE** pInstrumentationData); - void recGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, UINT32* pCountSchemaItems, BYTE** pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource, HRESULT result); + void recGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, UINT32* pCountSchemaItems, BYTE** pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource, bool* pDynamicPgo, HRESULT result); void dmpGetPgoInstrumentationResults(DWORDLONG key, const Agnostic_GetPgoInstrumentationResults& value); - HRESULT repGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, UINT32* pCountSchemaItems, BYTE** pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource); + HRESULT repGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, UINT32* pCountSchemaItems, BYTE** pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource, bool* pDynamicPgo); void recIsMoreSpecificType(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2, bool result); void dmpIsMoreSpecificType(DLDL key, DWORD value); diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index d39379089794f5..ac8efbddcfeec5 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -1947,11 +1947,12 @@ HRESULT interceptor_ICJI::getPgoInstrumentationResults(CORINFO_METHOD_HANDLE PgoInstrumentationSchema **pSchema, // pointer to the schema table which describes the instrumentation results (pointer will not remain valid after jit completes) uint32_t * pCountSchemaItems, // pointer to the count schema items uint8_t ** pInstrumentationData, // pointer to the actual instrumentation data (pointer will not remain valid after jit completes) - PgoSource* pPgoSource) + PgoSource* pPgoSource, + bool* pDynamicPgo) { mc->cr->AddCall("getPgoInstrumentationResults"); - HRESULT temp = original_ICorJitInfo->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource); - mc->recGetPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, temp); + HRESULT temp = original_ICorJitInfo->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, pDynamicPgo); + mc->recGetPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, pDynamicPgo, temp); return temp; } diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp index eebb80ab6b9dfa..a365cdb111e228 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -1374,10 +1374,11 @@ JITINTERFACE_HRESULT interceptor_ICJI::getPgoInstrumentationResults( ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, - ICorJitInfo::PgoSource* pgoSource) + ICorJitInfo::PgoSource* pPgoSource, + bool* pDynamicPgo) { mcs->AddCall("getPgoInstrumentationResults"); - return original_ICorJitInfo->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pgoSource); + return original_ICorJitInfo->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, pDynamicPgo); } JITINTERFACE_HRESULT interceptor_ICJI::allocPgoInstrumentationBySchema( diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp index 6a2ca48d87cd79..0d80993f52b676 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -1206,9 +1206,10 @@ JITINTERFACE_HRESULT interceptor_ICJI::getPgoInstrumentationResults( ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, - ICorJitInfo::PgoSource* pgoSource) + ICorJitInfo::PgoSource* pPgoSource, + bool* pDynamicPgo) { - return original_ICorJitInfo->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pgoSource); + return original_ICorJitInfo->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, pDynamicPgo); } JITINTERFACE_HRESULT interceptor_ICJI::allocPgoInstrumentationBySchema( diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index 08814336a74b1f..b263c1cafdebc9 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -1806,11 +1806,12 @@ HRESULT MyICJI::getPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, PgoInstrumentationSchema **pSchema, // pointer to the schema table which describes the instrumentation results (pointer will not remain valid after jit completes) uint32_t * pCountSchemaItems, // pointer to the count schema items uint8_t ** pInstrumentationData, // pointer to the actual instrumentation data (pointer will not remain valid after jit completes) - PgoSource* pPgoSource) + PgoSource* pPgoSource, + bool* pDynamicPgo) { jitInstance->mc->cr->AddCall("getPgoInstrumentationResults"); - return jitInstance->mc->repGetPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource); + return jitInstance->mc->repGetPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, pDynamicPgo); } // Associates a native call site, identified by its offset in the native code stream, with diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index dd61fff1cf8870..d1926bd979434a 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -12111,7 +12111,8 @@ HRESULT CEEJitInfo::getPgoInstrumentationResults( PgoInstrumentationSchema **pSchema, // pointer to the schema table which describes the instrumentation results (pointer will not remain valid after jit completes) uint32_t * pCountSchemaItems, // pointer to the count schema items uint8_t ** pInstrumentationData, // pointer to the actual instrumentation data (pointer will not remain valid after jit completes) - PgoSource * pPgoSource // source of pgo data + PgoSource * pPgoSource, // source of pgo data + bool * pDynamicPgo // true if Dynamic PGO is enabled ) { CONTRACTL { @@ -12124,6 +12125,7 @@ HRESULT CEEJitInfo::getPgoInstrumentationResults( *pCountSchemaItems = 0; *pInstrumentationData = NULL; *pPgoSource = PgoSource::Unknown; + *pDynamicPgo = g_pConfig->TieredPGO(); JIT_TO_EE_TRANSITION(); @@ -14417,7 +14419,8 @@ HRESULT CEEInfo::getPgoInstrumentationResults( PgoInstrumentationSchema **pSchema, // pointer to the schema table which describes the instrumentation results (pointer will not remain valid after jit completes) uint32_t * pCountSchemaItems, // pointer to the count schema items uint8_t ** pInstrumentationData, // pointer to the actual instrumentation data (pointer will not remain valid after jit completes) - PgoSource * pPgoSource + PgoSource * pPgoSource, + bool * pDynamicPgo ) { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 754d04d5554279..a8266d6b79b275 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -643,7 +643,8 @@ class CEEJitInfo : public CEEInfo PgoInstrumentationSchema** pSchema, /* OUT */ uint32_t* pCountSchemaItems, /* OUT */ uint8_t**pInstrumentationData, /* OUT */ - PgoSource *pPgoSource /* OUT */ + PgoSource *pPgoSource, /* OUT */ + bool* pDynamicPgo /* OUT */ ) override final; void recordCallSite( From e1928e425ce45e8305fbd5edbef1a17e54c8d86f Mon Sep 17 00:00:00 2001 From: Katelyn Gadd Date: Fri, 26 Apr 2024 23:30:07 -0700 Subject: [PATCH 149/248] [wasm] Disable interp pgo recording by default since it adds startup overhead (#101566) * Disable interp pgo recording by default since it adds startup overhead * Make withRuntimeOptions not trample existing runtime options --- src/mono/browser/runtime/loader/run.ts | 11 ++++++++--- src/mono/mono/utils/options-def.h | 2 +- src/mono/sample/wasm/browser-bench/main.js | 5 ----- .../testassets/WasmBasicTestApp/App/wwwroot/main.js | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/mono/browser/runtime/loader/run.ts b/src/mono/browser/runtime/loader/run.ts index 5c5010a2a5356f..0bd2dd60d80852 100644 --- a/src/mono/browser/runtime/loader/run.ts +++ b/src/mono/browser/runtime/loader/run.ts @@ -158,6 +158,10 @@ export class HostBuilder implements DotnetHostBuilder { interpreterPgo: value, interpreterPgoSaveDelay: autoSaveDelay }); + if (monoConfig.runtimeOptions) + monoConfig.runtimeOptions.push("--interp-pgo-recording"); + else + monoConfig.runtimeOptions = ["--interp-pgo-recording"]; return this; } catch (err) { mono_exit(1, err); @@ -268,9 +272,10 @@ export class HostBuilder implements DotnetHostBuilder { withRuntimeOptions (runtimeOptions: string[]): DotnetHostBuilder { try { mono_assert(runtimeOptions && Array.isArray(runtimeOptions), "must be array of strings"); - deep_merge_config(monoConfig, { - runtimeOptions - }); + if (monoConfig.runtimeOptions) + monoConfig.runtimeOptions.push(...runtimeOptions); + else + monoConfig.runtimeOptions = runtimeOptions; return this; } catch (err) { mono_exit(1, err); diff --git a/src/mono/mono/utils/options-def.h b/src/mono/mono/utils/options-def.h index 8cdbc942e1b851..3af994cb325b2b 100644 --- a/src/mono/mono/utils/options-def.h +++ b/src/mono/mono/utils/options-def.h @@ -61,7 +61,7 @@ DEFINE_BOOL(wasm_exceptions, "wasm-exceptions", FALSE, "Enable codegen for WASM DEFINE_BOOL(aot_lazy_assembly_load, "aot-lazy-assembly-load", FALSE, "Load assemblies referenced by AOT images lazily") #if HOST_BROWSER -DEFINE_BOOL(interp_pgo_recording, "interp-pgo-recording", TRUE, "Record interpreter tiering information for automatic PGO") +DEFINE_BOOL(interp_pgo_recording, "interp-pgo-recording", FALSE, "Record interpreter tiering information for automatic PGO") #else DEFINE_BOOL(interp_pgo_recording, "interp-pgo-recording", FALSE, "Record interpreter tiering information for automatic PGO") DEFINE_BOOL(wasm_gc_safepoints, "wasm-gc-safepoints", FALSE, "Use GC safepoints on WASM") diff --git a/src/mono/sample/wasm/browser-bench/main.js b/src/mono/sample/wasm/browser-bench/main.js index 0f1a6530491250..71e4a677ddcc7e 100644 --- a/src/mono/sample/wasm/browser-bench/main.js +++ b/src/mono/sample/wasm/browser-bench/main.js @@ -225,11 +225,6 @@ try { // console to see statistics on how much code it generated and whether any new opcodes // are causing traces to fail to compile .withRuntimeOptions(["--jiterpreter-stats-enabled"]) - // We enable interpreter PGO so that you can exercise it in local tests, i.e. - // run browser-bench one, then refresh the tab to measure the performance improvement - // on the second run of browser-bench. The overall speed of the benchmarks won't - // improve much, but the time spent generating code during the run will go down - .withInterpreterPgo(true, 30) .withElementOnExit() .withExitCodeLogging() .create(); diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js index 7df0706d568193..3eb9e50aedeb32 100644 --- a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js @@ -37,7 +37,7 @@ switch (testCase) { let alreadyFailed = []; dotnet.withDiagnosticTracing(true).withResourceLoader((type, name, defaultUri, integrity, behavior) => { if (type === "dotnetjs") { - // loadBootResource could return string with unqualified name of resource. + // loadBootResource could return string with unqualified name of resource. // It assumes that we resolve it with document.baseURI // we test it here return `_framework/${name}`; @@ -131,8 +131,8 @@ try { } }); const iterationCount = params.get("iterationCount") ?? 70; - for (let i = 0; i < iterationCount; i++) { - exports.InterpPgoTest.Greeting(); + for (let i = 0; i < iterationCount; i++) { + exports.InterpPgoTest.Greeting(); }; await INTERNAL.interp_pgo_save_data(); exit(0); From 81c1d87dd777eddc4eff38d433077e2f20cdba79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Sowi=C5=84ski?= Date: Sat, 27 Apr 2024 11:46:16 +0200 Subject: [PATCH 150/248] [RISC-V] Use common CodeGen::genHomeRegisterParams (#101288) * Code review from #101114 * Use common genHomeRegisterParams on RISC-V * Make passSlot integer-only because we know hardware floating-point calling convention passes in registers only * Make a RISC-V specific routine for homing stack parts of split parameters. * Move genHomeStackPartOfSplitParameter out of genHomeSwiftStructParameters, share stack segment homing with Swift code --- src/coreclr/jit/abi.cpp | 14 +- src/coreclr/jit/abi.h | 4 +- src/coreclr/jit/codegen.h | 2 + src/coreclr/jit/codegencommon.cpp | 154 ++++++---- src/coreclr/jit/codegenriscv64.cpp | 443 ----------------------------- src/coreclr/jit/targetriscv64.cpp | 62 ++-- 6 files changed, 141 insertions(+), 538 deletions(-) diff --git a/src/coreclr/jit/abi.cpp b/src/coreclr/jit/abi.cpp index c6dbd8aa9202fd..7a594f77f39121 100644 --- a/src/coreclr/jit/abi.cpp +++ b/src/coreclr/jit/abi.cpp @@ -258,14 +258,16 @@ bool ABIPassingInformation::HasExactlyOneStackSegment() const // bool ABIPassingInformation::IsSplitAcrossRegistersAndStack() const { - bool anyReg = false; - bool anyStack = false; - for (unsigned i = 0; i < NumSegments; i++) + if (NumSegments < 2) + return false; + + bool isFirstInReg = Segments[0].IsPassedInRegister(); + for (unsigned i = 1; i < NumSegments; i++) { - anyReg |= Segments[i].IsPassedInRegister(); - anyStack |= Segments[i].IsPassedOnStack(); + if (isFirstInReg != Segments[i].IsPassedInRegister()) + return true; } - return anyReg && anyStack; + return false; } //----------------------------------------------------------------------------- diff --git a/src/coreclr/jit/abi.h b/src/coreclr/jit/abi.h index ac0ad5090dcf2b..37268ce3effd9f 100644 --- a/src/coreclr/jit/abi.h +++ b/src/coreclr/jit/abi.h @@ -51,8 +51,8 @@ struct ABIPassingInformation // - On loongarch64/riscv64, structs can be passed in two registers or // can be split out over register and stack, giving // multiple register segments and a struct segment. - unsigned NumSegments = 0; - ABIPassingSegment* Segments = nullptr; + unsigned NumSegments; + ABIPassingSegment* Segments; ABIPassingInformation(unsigned numSegments = 0, ABIPassingSegment* segments = nullptr) : NumSegments(numSegments) diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index 441db5f6b50d47..2a2ede6bae9ac0 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -284,7 +284,9 @@ class CodeGen final : public CodeGenInterface void genEnregisterOSRArgsAndLocals(); #endif + void genHomeStackSegment(unsigned lclNum, const ABIPassingSegment& seg, regNumber initReg, bool* pInitRegZeroed); void genHomeSwiftStructParameters(bool handleStack); + void genHomeStackPartOfSplitParameter(regNumber initReg, bool* initRegStillZeroed); void genCheckUseBlockInit(); #if defined(UNIX_AMD64_ABI) && defined(FEATURE_SIMD) diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 9f3120d274d57d..c3608402d27ec2 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -2802,7 +2802,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ -#if !defined(TARGET_RISCV64) struct RegNode; struct RegNodeEdge @@ -3346,8 +3345,6 @@ void CodeGen::genHomeRegisterParams(regNumber initReg, bool* initRegStillZeroed) } } -#endif - // ----------------------------------------------------------------------------- // genGetParameterHomingTempRegisterCandidates: Get the registers that are // usable during register homing. @@ -4122,15 +4119,69 @@ void CodeGen::genEnregisterOSRArgsAndLocals() } } +#if defined(SWIFT_SUPPORT) || defined(TARGET_RISCV64) +//----------------------------------------------------------------------------- +// genHomeSwiftStructParameters: Move the incoming segment to the local stack frame. +// +// Arguments: +// lclNum - Number of local variable to home +// seg - Stack segment of the local variable to home +// initReg - Scratch register to use if needed +// initRegStillZeroed - Set to false if the scratch register was needed +// +void CodeGen::genHomeStackSegment(unsigned lclNum, + const ABIPassingSegment& seg, + regNumber initReg, + bool* initRegStillZeroed) +{ + var_types loadType = TYP_UNDEF; + switch (seg.Size) + { + case 1: + loadType = TYP_UBYTE; + break; + case 2: + loadType = TYP_USHORT; + break; + case 3: + case 4: + loadType = TYP_INT; + break; + case 5: + case 6: + case 7: + case 8: + loadType = TYP_LONG; + break; + default: + assert(!"Unexpected segment size for struct parameter not passed implicitly by ref"); + return; + } + emitAttr size = emitTypeSize(loadType); + + int loadOffset = + -(isFramePointerUsed() ? genCallerSPtoFPdelta() : genCallerSPtoInitialSPdelta()) + (int)seg.GetStackOffset(); +#ifdef TARGET_XARCH + GetEmitter()->emitIns_R_AR(ins_Load(loadType), size, initReg, genFramePointerReg(), loadOffset); +#else + genInstrWithConstant(ins_Load(loadType), size, initReg, genFramePointerReg(), loadOffset, initReg); +#endif + GetEmitter()->emitIns_S_R(ins_Store(loadType), size, initReg, lclNum, seg.Offset); + + if (initRegStillZeroed) + *initRegStillZeroed = false; +} +#endif // defined(SWIFT_SUPPORT) || defined(TARGET_RISCV64) + #ifdef SWIFT_SUPPORT //----------------------------------------------------------------------------- // genHomeSwiftStructParameters: -// Reassemble Swift struct parameters if necessary. +// Reassemble Swift struct parameters if necessary. // -// Parameters: -// handleStack - If true, reassemble the segments that were passed on the stack. -// If false, reassemble the segments that were passed in registers. +// Arguments: +// handleStack - If true, reassemble the segments that were passed on the stack. +// If false, reassemble the segments that were passed in registers. // void CodeGen::genHomeSwiftStructParameters(bool handleStack) { @@ -4176,59 +4227,54 @@ void CodeGen::genHomeSwiftStructParameters(bool handleStack) } else { - var_types loadType = TYP_UNDEF; - switch (seg.Size) - { - case 1: - loadType = TYP_UBYTE; - break; - case 2: - loadType = TYP_USHORT; - break; - case 3: - case 4: - loadType = TYP_INT; - break; - case 5: - case 6: - case 7: - case 8: - loadType = TYP_LONG; - break; - default: - assert(!"Unexpected segment size for struct parameter not passed implicitly by ref"); - continue; - } + // We can use REG_SCRATCH as a temporary register here as we ensured that during LSRA build. + genHomeStackSegment(lclNum, seg, REG_SCRATCH, nullptr); + } + } + } +} +#endif - int offset; - if (isFramePointerUsed()) - { - offset = -genCallerSPtoFPdelta(); - } - else - { - offset = -genCallerSPtoInitialSPdelta(); - } +//----------------------------------------------------------------------------- +// genHomeStackPartOfSplitParameter: Home the tail (stack) portion of a split parameter next to where the head +// (register) portion is homed. +// +// Arguments: +// initReg - scratch register to use if needed +// initRegStillZeroed - set to false if scratch register was needed +// +// Notes: +// No-op on platforms where argument registers are already homed to form a contiguous space with incoming stack. +// +void CodeGen::genHomeStackPartOfSplitParameter(regNumber initReg, bool* initRegStillZeroed) +{ +#ifdef TARGET_RISCV64 + unsigned lclNum = 0; + for (; lclNum < compiler->info.compArgsCount; lclNum++) + { + LclVarDsc* var = compiler->lvaGetDesc(lclNum); + if (!var->lvIsSplit || !var->lvOnFrame) + continue; - offset += (int)seg.GetStackOffset(); + JITDUMP("Homing stack part of split parameter V%02u\n", lclNum); - // Move the incoming segment to the local stack frame. We can - // use REG_SCRATCH as a temporary register here as we ensured - // that during LSRA build. -#ifdef TARGET_XARCH - GetEmitter()->emitIns_R_AR(ins_Load(loadType), emitTypeSize(loadType), REG_SCRATCH, - genFramePointerReg(), offset); -#else - genInstrWithConstant(ins_Load(loadType), emitTypeSize(loadType), REG_SCRATCH, genFramePointerReg(), - offset, REG_SCRATCH); -#endif + assert(varTypeIsStruct(var)); + assert(!compiler->lvaIsImplicitByRefLocal(lclNum)); + const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(lclNum); + assert(abiInfo.NumSegments == 2); + assert(abiInfo.Segments[0].GetRegister() == REG_ARG_LAST); + const ABIPassingSegment& seg = abiInfo.Segments[1]; - GetEmitter()->emitIns_S_R(ins_Store(loadType), emitTypeSize(loadType), REG_SCRATCH, lclNum, seg.Offset); - } + genHomeStackSegment(lclNum, seg, initReg, initRegStillZeroed); + + for (lclNum += 1; lclNum < compiler->info.compArgsCount; lclNum++) + { + assert(!compiler->lvaGetDesc(lclNum)->lvIsSplit); // There should be only one split parameter } + break; } -} #endif +} /*----------------------------------------------------------------------------- * @@ -5547,6 +5593,8 @@ void CodeGen::genFnProlog() { compiler->lvaUpdateArgsWithInitialReg(); + genHomeStackPartOfSplitParameter(initReg, &initRegZeroed); + if ((intRegState.rsCalleeRegArgMaskLiveIn | floatRegState.rsCalleeRegArgMaskLiveIn) != RBM_NONE) { genHomeRegisterParams(initReg, &initRegZeroed); diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index b7c119be94987c..0fa8bdb5874f40 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -7962,449 +7962,6 @@ void CodeGen::genPopCalleeSavedRegisters(bool jmpEpilog) } } -void CodeGen::genHomeRegisterParams(regNumber initReg, bool* initRegStillZeroed) -{ - *initRegStillZeroed = false; - assert(!(intRegState.rsCalleeRegArgMaskLiveIn & floatRegState.rsCalleeRegArgMaskLiveIn)); - - regMaskTP regArgMaskLive = intRegState.rsCalleeRegArgMaskLiveIn | floatRegState.rsCalleeRegArgMaskLiveIn; - -#ifdef DEBUG - if (verbose) - { - printf("*************** In genFnPrologCalleeRegArgs() RISCV64:0x%llx.\n", regArgMaskLive); - } -#endif - - // We should be generating the prolog block when we are called - assert(compiler->compGeneratingProlog); - - // We expect to have some registers of the type we are doing, that are LiveIn, otherwise we don't need to be called. - noway_assert(regArgMaskLive != 0); - - unsigned varNum; - unsigned regArgNum = 0; - // Process any rearrangements including circular dependencies. - regNumber regArg[MAX_REG_ARG + MAX_FLOAT_REG_ARG]; - regNumber regArgInit[MAX_REG_ARG + MAX_FLOAT_REG_ARG]; - emitAttr regArgAttr[MAX_REG_ARG + MAX_FLOAT_REG_ARG]; - - for (int i = 0; i < MAX_REG_ARG + MAX_FLOAT_REG_ARG; i++) - { - regArg[i] = REG_NA; - -#ifdef DEBUG - regArgInit[i] = REG_NA; - regArgAttr[i] = EA_UNKNOWN; -#endif - } - - for (varNum = 0; varNum < compiler->lvaCount; ++varNum) - { - LclVarDsc* varDsc = compiler->lvaTable + varNum; - - // Is this variable a register arg? - if (!varDsc->lvIsParam) - { - continue; - } - - if (!varDsc->lvIsRegArg) - { - continue; - } - - if (varDsc->lvIsInReg()) - { - assert(genIsValidIntReg(varDsc->GetArgReg()) || genIsValidFloatReg(varDsc->GetArgReg())); - assert(!(genIsValidIntReg(varDsc->GetOtherArgReg()) || genIsValidFloatReg(varDsc->GetOtherArgReg()))); - if (varDsc->GetArgInitReg() != varDsc->GetArgReg()) - { - if (genIsValidIntReg(varDsc->GetArgInitReg())) - { - if (varDsc->GetArgInitReg() > REG_ARG_LAST) - { - bool isSkip; - instruction ins; - emitAttr size; - if (genIsValidIntReg(varDsc->GetArgReg())) - { - ins = INS_mov; - if (varDsc->TypeGet() == TYP_INT) - { - size = EA_4BYTE; - isSkip = false; - } - else - { - size = EA_PTRSIZE; - isSkip = true; - } - } - else - { - ins = INS_fmv_x_d; - size = EA_PTRSIZE; - isSkip = true; - } - GetEmitter()->emitIns_Mov(ins, size, varDsc->GetArgInitReg(), varDsc->GetArgReg(), isSkip); - regArgMaskLive &= ~genRegMask(varDsc->GetArgReg()); - } - else - { - if (genIsValidIntReg(varDsc->GetArgReg())) - { - assert(isValidIntArgReg(varDsc->GetArgReg(), compiler->info.compCallConv)); - regArg[varDsc->GetArgReg() - REG_ARG_FIRST] = varDsc->GetArgReg(); - regArgInit[varDsc->GetArgReg() - REG_ARG_FIRST] = varDsc->GetArgInitReg(); - regArgAttr[varDsc->GetArgReg() - REG_ARG_FIRST] = - varDsc->TypeGet() == TYP_INT ? EA_4BYTE : EA_PTRSIZE; - } - else - { - assert(isValidFloatArgReg(varDsc->GetArgReg())); - regArg[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = varDsc->GetArgReg(); - regArgInit[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = varDsc->GetArgInitReg(); - regArgAttr[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = - varDsc->TypeGet() == TYP_FLOAT ? EA_4BYTE : EA_PTRSIZE; - } - regArgNum++; - } - } - else - { - assert(genIsValidFloatReg(varDsc->GetArgInitReg())); - if (genIsValidIntReg(varDsc->GetArgReg())) - { - emitAttr size = (varDsc->TypeGet() == TYP_FLOAT) ? EA_4BYTE : EA_PTRSIZE; - GetEmitter()->emitIns_Mov(size, varDsc->GetArgInitReg(), varDsc->GetArgReg(), false); - regArgMaskLive &= ~genRegMask(varDsc->GetArgReg()); - } - else if (varDsc->GetArgInitReg() > REG_ARG_FP_LAST) - { - GetEmitter()->emitIns_Mov(INS_fsgnj_d, EA_PTRSIZE, varDsc->GetArgInitReg(), varDsc->GetArgReg(), - true); - regArgMaskLive &= ~genRegMask(varDsc->GetArgReg()); - } - else - { - assert(isValidFloatArgReg(varDsc->GetArgReg())); - regArg[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = varDsc->GetArgReg(); - regArgInit[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = varDsc->GetArgInitReg(); - regArgAttr[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = - varDsc->TypeGet() == TYP_FLOAT ? EA_4BYTE : EA_PTRSIZE; - regArgNum++; - } - } - } - else - { - // TODO-RISCV64: should delete this by optimization "struct {long a; int32_t b;};" - // liking AMD64_ABI within morph. - if (genIsValidIntReg(varDsc->GetArgReg()) && (varDsc->TypeGet() == TYP_INT)) - { - GetEmitter()->emitIns_Mov(INS_mov, EA_4BYTE, varDsc->GetArgInitReg(), varDsc->GetArgReg(), false); - } - regArgMaskLive &= ~genRegMask(varDsc->GetArgReg()); - } -#ifdef USING_SCOPE_INFO - psiMoveToReg(varNum); -#endif // USING_SCOPE_INFO - if (!varDsc->lvLiveInOutOfHndlr) - { - continue; - } - } - - // When we have a promoted struct we have two possible LclVars that can represent the incoming argument - // in the regArgTab[], either the original TYP_STRUCT argument or the introduced lvStructField. - // We will use the lvStructField if we have a TYPE_INDEPENDENT promoted struct field otherwise - // use the original TYP_STRUCT argument. - // - if (varDsc->lvPromoted || varDsc->lvIsStructField) - { - LclVarDsc* parentVarDsc = varDsc; - if (varDsc->lvIsStructField) - { - assert(!varDsc->lvPromoted); - parentVarDsc = &compiler->lvaTable[varDsc->lvParentLcl]; - } - - Compiler::lvaPromotionType promotionType = compiler->lvaGetPromotionType(parentVarDsc); - - if (promotionType == Compiler::PROMOTION_TYPE_INDEPENDENT) - { - // For register arguments that are independent promoted structs we put the promoted field varNum - // in the regArgTab[] - if (varDsc->lvPromoted) - { - continue; - } - } - else - { - // For register arguments that are not independent promoted structs we put the parent struct varNum - // in the regArgTab[] - if (varDsc->lvIsStructField) - { - continue; - } - } - } - - var_types storeType = TYP_UNDEF; - int slotSize = TARGET_POINTER_SIZE; - - if (varTypeIsStruct(varDsc)) - { - if (emitter::isFloatReg(varDsc->GetArgReg())) - { - storeType = varDsc->lvIs4Field1 ? TYP_FLOAT : TYP_DOUBLE; - } - else - { - assert(emitter::isGeneralRegister(varDsc->GetArgReg())); - if (varDsc->lvIs4Field1) - { - storeType = TYP_INT; - } - else - { - storeType = varDsc->GetLayout()->GetGCPtrType(0); - } - } - slotSize = (int)EA_SIZE(emitActualTypeSize(storeType)); - -#if FEATURE_MULTIREG_ARGS - // Must be <= MAX_PASS_MULTIREG_BYTES or else it wouldn't be passed in registers - noway_assert(varDsc->lvSize() <= MAX_PASS_MULTIREG_BYTES); -#endif - } - else // Not a struct type - { - storeType = compiler->mangleVarArgsType(genActualType(varDsc->TypeGet())); - if (emitter::isFloatReg(varDsc->GetArgReg()) != varTypeIsFloating(storeType)) - { - assert(varTypeIsFloating(storeType)); - storeType = storeType == TYP_DOUBLE ? TYP_I_IMPL : TYP_INT; - } - } - emitAttr size = emitActualTypeSize(storeType); - - regNumber srcRegNum = varDsc->GetArgReg(); - - // Stack argument - if the ref count is 0 don't care about it - if (!varDsc->lvOnFrame) - { - noway_assert(varDsc->lvRefCnt() == 0); - regArgMaskLive &= ~genRegMask(varDsc->GetArgReg()); - if (varDsc->GetOtherArgReg() < REG_STK) - { - regArgMaskLive &= ~genRegMask(varDsc->GetOtherArgReg()); - } - } - else - { - assert(srcRegNum != varDsc->GetOtherArgReg()); - - regNumber tmpReg = REG_NA; - - bool FPbased; - int baseOffset = compiler->lvaFrameAddress(varNum, &FPbased); - - // First store the `varDsc->GetArgReg()` on stack. - if (emitter::isValidSimm12(baseOffset)) - { - GetEmitter()->emitIns_S_R(ins_Store(storeType), size, srcRegNum, varNum, 0); - } - else - { - assert(tmpReg == REG_NA); - - tmpReg = REG_RA; - // Prepare tmpReg to possible future use - GetEmitter()->emitLoadImmediate(EA_PTRSIZE, tmpReg, baseOffset); - GetEmitter()->emitIns_R_R_R(INS_add, EA_PTRSIZE, tmpReg, tmpReg, FPbased ? REG_FPBASE : REG_SPBASE); - GetEmitter()->emitIns_S_R_R(ins_Store(storeType), size, srcRegNum, tmpReg, varNum, 0); - } - - regArgMaskLive &= ~genRegMask(srcRegNum); - - // Then check if varDsc is a struct arg - if (varTypeIsStruct(varDsc)) - { - if (emitter::isFloatReg(varDsc->GetOtherArgReg())) - { - srcRegNum = varDsc->GetOtherArgReg(); - storeType = varDsc->lvIs4Field2 ? TYP_FLOAT : TYP_DOUBLE; - size = EA_SIZE(emitActualTypeSize(storeType)); - - slotSize = slotSize < (int)size ? (int)size : slotSize; - } - else if (emitter::isGeneralRegister(varDsc->GetOtherArgReg())) - { - if (varDsc->lvIs4Field2) - { - storeType = TYP_INT; - } - else - { - storeType = varDsc->GetLayout()->GetGCPtrType(1); - } - - srcRegNum = varDsc->GetOtherArgReg(); - size = emitActualTypeSize(storeType); - - slotSize = slotSize < (int)EA_SIZE(size) ? (int)EA_SIZE(size) : slotSize; - } - baseOffset += slotSize; - - // if the struct passed by two register, then store the second register `varDsc->GetOtherArgReg()`. - if (srcRegNum == varDsc->GetOtherArgReg()) - { - GetEmitter()->emitIns_S_R_R(ins_Store(storeType), size, srcRegNum, tmpReg, varNum, slotSize); - regArgMaskLive &= ~genRegMask(srcRegNum); // maybe do this later is better! - } - else if (varDsc->lvIsSplit) - { - // the struct is a split struct. - assert(varDsc->GetArgReg() == REG_ARG_LAST && varDsc->GetOtherArgReg() == REG_STK); - - // For the RISCV64's ABI, the split struct arg will be passed via `A7` and a stack slot on caller. - // But if the `A7` is stored on stack on the callee side, the whole split struct should be - // stored continuous on the stack on the callee side. - // So, after we save `A7` on the stack in prolog, it has to copy the stack slot of the split struct - // which was passed by the caller. Here we load the stack slot to `REG_SCRATCH`, and save it - // on the stack following the `A7` in prolog. - if (emitter::isValidSimm12(genTotalFrameSize())) - { - GetEmitter()->emitIns_R_R_I(INS_ld, size, REG_SCRATCH, REG_SPBASE, genTotalFrameSize()); - } - else - { - assert(!EA_IS_RELOC(size)); - GetEmitter()->emitLoadImmediate(size, REG_SCRATCH, genTotalFrameSize()); - GetEmitter()->emitIns_R_R_R(INS_add, size, REG_SCRATCH, REG_SCRATCH, REG_SPBASE); - GetEmitter()->emitIns_R_R_I(INS_ld, size, REG_SCRATCH, REG_SCRATCH, 0); - } - - GetEmitter()->emitIns_S_R_R(ins_Store(storeType), size, REG_SCRATCH, tmpReg, varNum, slotSize); - } - } - -#ifdef USING_SCOPE_INFO - { - psiMoveToStack(varNum); - } -#endif // USING_SCOPE_INFO - } - } - - if (regArgNum > 0) - { - for (int i = MAX_REG_ARG + MAX_FLOAT_REG_ARG - 1; i >= 0; i--) - { - if (regArg[i] != REG_NA && !isValidIntArgReg(regArgInit[i], compiler->info.compCallConv) && - !isValidFloatArgReg(regArgInit[i])) - { - assert(regArg[i] != regArgInit[i]); - assert(isValidIntArgReg(regArg[i], compiler->info.compCallConv) || isValidFloatArgReg(regArg[i])); - - GetEmitter()->emitIns_Mov(regArgAttr[i], regArgInit[i], regArg[i], false); - - regArgMaskLive &= ~genRegMask(regArg[i]); - regArg[i] = REG_NA; - regArgNum -= 1; - } - } - } - - if (regArgNum > 0) - { - for (int i = MAX_REG_ARG + MAX_FLOAT_REG_ARG - 1; i >= 0; i--) - { - if (regArg[i] != REG_NA) - { - assert(regArg[i] != regArgInit[i]); - - // regArg indexes list - unsigned indexList[MAX_REG_ARG + MAX_FLOAT_REG_ARG]; - int count = 0; // Number of nodes in list - bool loop = false; // List has a loop - - for (unsigned cur = i; regArg[cur] != REG_NA; count++) - { - if (cur == i && count > 0) - { - loop = true; - break; - } - - indexList[count] = cur; - - for (int count2 = 0; count2 < count; count2++) - { - // The list could not have backlinks except last to first case which handled above. - assert(cur != indexList[count2] && "Attempt to move several values on same register."); - } - assert(cur < MAX_REG_ARG + MAX_FLOAT_REG_ARG); - assert(isValidIntArgReg(regArg[cur], compiler->info.compCallConv) || - isValidFloatArgReg(regArg[cur])); - - if (isValidIntArgReg(regArgInit[cur], compiler->info.compCallConv)) - { - cur = regArgInit[cur] - REG_ARG_FIRST; - } - else if (isValidFloatArgReg(regArgInit[cur])) - { - cur = regArgInit[cur] - REG_ARG_FP_FIRST + MAX_REG_ARG; - } - else - { - assert(!"Argument register is neither valid float nor valid int argument register"); - } - } - - if (loop) - { - unsigned tmpArg = indexList[count - 1]; - - GetEmitter()->emitIns_Mov(regArgAttr[tmpArg], rsGetRsvdReg(), regArg[tmpArg], false); - count--; // Decrease count to not access last node which regArgInit points to start node i - assert(count > 0); - } - - for (int cur = count - 1; cur >= 0; cur--) - { - unsigned tmpArg = indexList[cur]; - - GetEmitter()->emitIns_Mov(regArgAttr[tmpArg], regArgInit[tmpArg], regArg[tmpArg], false); - - regArgMaskLive &= ~genRegMask(regArg[tmpArg]); - regArg[tmpArg] = REG_NA; - regArgNum--; - assert(regArgNum >= 0); - }; - - if (loop) - { - unsigned tmpArg = indexList[count]; // count was decreased for loop case - - GetEmitter()->emitIns_Mov(regArgAttr[i], regArg[tmpArg], rsGetRsvdReg(), false); - - regArgMaskLive &= ~genRegMask(regArg[tmpArg]); - regArg[tmpArg] = REG_NA; - regArgNum--; - } - assert(regArgNum >= 0); - } - } - } - - assert(regArgNum == 0); - assert(!regArgMaskLive); -} - #ifdef PROFILING_SUPPORTED //----------------------------------------------------------------------------------- // genProfilingEnterCallback: Generate the profiling function enter callback. diff --git a/src/coreclr/jit/targetriscv64.cpp b/src/coreclr/jit/targetriscv64.cpp index 29f71dc76d8fa2..581087b5cc63f8 100644 --- a/src/coreclr/jit/targetriscv64.cpp +++ b/src/coreclr/jit/targetriscv64.cpp @@ -36,6 +36,7 @@ RiscV64Classifier::RiscV64Classifier(const ClassifierInfo& info) , m_intRegs(intArgRegs, ArrLen(intArgRegs)) , m_floatRegs(fltArgRegs, ArrLen(fltArgRegs)) { + assert(!m_info.IsVarArgs); // TODO: varargs currently not supported on RISC-V } //----------------------------------------------------------------------------- @@ -57,8 +58,6 @@ ABIPassingInformation RiscV64Classifier::Classify(Compiler* comp, ClassLayout* structLayout, WellKnownArg /*wellKnownParam*/) { - assert(!m_info.IsVarArgs); // TODO: varargs currently not supported on RISC-V - StructFloatFieldInfoFlags flags = STRUCT_NO_FLOAT_FIELD; unsigned intFields = 0, floatFields = 0; unsigned passedSize; @@ -93,36 +92,13 @@ ABIPassingInformation RiscV64Classifier::Classify(Compiler* comp, } else { - assert(genTypeSize(type) <= TARGET_POINTER_SIZE); - - if (varTypeIsFloating(type)) - floatFields = 1; - passedSize = genTypeSize(type); + assert(passedSize <= TARGET_POINTER_SIZE); + floatFields = varTypeIsFloating(type) ? 1 : 0; } assert((floatFields > 0) || (intFields == 0)); - auto PassSlot = [this](bool inFloatReg, unsigned offset, unsigned size) -> ABIPassingSegment { - assert(size > 0); - assert(size <= TARGET_POINTER_SIZE); - if (inFloatReg) - { - return ABIPassingSegment::InRegister(m_floatRegs.Dequeue(), offset, size); - } - else if (m_intRegs.Count() > 0) - { - return ABIPassingSegment::InRegister(m_intRegs.Dequeue(), offset, size); - } - else - { - assert((m_stackArgSize % TARGET_POINTER_SIZE) == 0); - ABIPassingSegment seg = ABIPassingSegment::OnStack(m_stackArgSize, offset, size); - m_stackArgSize += TARGET_POINTER_SIZE; - return seg; - } - }; - if ((floatFields > 0) && (m_floatRegs.Count() >= floatFields) && (m_intRegs.Count() >= intFields)) { // Hardware floating-point calling convention @@ -151,27 +127,45 @@ ABIPassingInformation RiscV64Classifier::Classify(Compiler* comp, bool isSecondFloat = (flags & (STRUCT_FLOAT_FIELD_ONLY_TWO | STRUCT_FLOAT_FIELD_SECOND)) != 0; assert(isFirstFloat || isSecondFloat); - return {2, new (comp, CMK_ABI) ABIPassingSegment[]{PassSlot(isFirstFloat, 0, firstSize), - PassSlot(isSecondFloat, offset, secondSize)}}; + regNumber firstReg = (isFirstFloat ? m_floatRegs : m_intRegs).Dequeue(); + regNumber secondReg = (isSecondFloat ? m_floatRegs : m_intRegs).Dequeue(); + + return {2, new (comp, CMK_ABI) + ABIPassingSegment[]{ABIPassingSegment::InRegister(firstReg, 0, firstSize), + ABIPassingSegment::InRegister(secondReg, offset, secondSize)}}; } } else { // Integer calling convention + auto passSlot = [this](unsigned offset, unsigned size) -> ABIPassingSegment { + assert(size > 0); + assert(size <= TARGET_POINTER_SIZE); + if (m_intRegs.Count() > 0) + { + return ABIPassingSegment::InRegister(m_intRegs.Dequeue(), offset, size); + } + else + { + assert((m_stackArgSize % TARGET_POINTER_SIZE) == 0); + ABIPassingSegment seg = ABIPassingSegment::OnStack(m_stackArgSize, offset, size); + m_stackArgSize += TARGET_POINTER_SIZE; + return seg; + } + }; + if (passedSize <= TARGET_POINTER_SIZE) { - return ABIPassingInformation::FromSegment(comp, PassSlot(false, 0, passedSize)); + return ABIPassingInformation::FromSegment(comp, passSlot(0, passedSize)); } else { assert(varTypeIsStruct(type)); return {2, new (comp, CMK_ABI) - ABIPassingSegment[]{PassSlot(false, 0, TARGET_POINTER_SIZE), - PassSlot(false, TARGET_POINTER_SIZE, passedSize - TARGET_POINTER_SIZE)}}; + ABIPassingSegment[]{passSlot(0, TARGET_POINTER_SIZE), + passSlot(TARGET_POINTER_SIZE, passedSize - TARGET_POINTER_SIZE)}}; } } - - unreached(); } #endif // TARGET_RISCV64 From 95306c760c08d922a1d4a7a0979c16fb40c4ac3f Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Sat, 27 Apr 2024 11:03:46 -0700 Subject: [PATCH 151/248] Remove dead code in PGO scenarios. (#101648) --- src/coreclr/vm/jitinterface.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index d1926bd979434a..394b87a1873965 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -12075,23 +12075,6 @@ HRESULT CEEJitInfo::allocPgoInstrumentationBySchema( JIT_TO_EE_TRANSITION(); - // We need to know the code size. Typically we can get the code size - // from m_ILHeader. For dynamic methods, m_ILHeader will be NULL, so - // for that case we need to use DynamicResolver to get the code size. - - unsigned codeSize = 0; - if (m_pMethodBeingCompiled->IsDynamicMethod()) - { - unsigned stackSize, ehSize; - CorInfoOptions options; - DynamicResolver * pResolver = m_pMethodBeingCompiled->AsDynamicMethodDesc()->GetResolver(); - pResolver->GetCodeInfo(&codeSize, &stackSize, &options, &ehSize); - } - else - { - codeSize = m_ILHeader->GetCodeSize(); - } - #ifdef FEATURE_PGO hr = PgoManager::allocPgoInstrumentationBySchema(m_pMethodBeingCompiled, pSchema, countSchemaItems, pInstrumentationData); #else From b9464f1a937232529baacac677bdb4617baf5fc7 Mon Sep 17 00:00:00 2001 From: t-mustafin <66252296+t-mustafin@users.noreply.github.com> Date: Sat, 27 Apr 2024 21:37:27 +0300 Subject: [PATCH 152/248] [RISC-V] Fix FEATURE_MULTIREG_RETURN definition (#101642) --- src/coreclr/clrdefinitions.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index 4201c06692eeb5..1970b6c33c7544 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -16,6 +16,7 @@ elseif (CLR_CMAKE_TARGET_ARCH_ARM) add_definitions(-DFEATURE_EMULATE_SINGLESTEP) elseif (CLR_CMAKE_TARGET_ARCH_RISCV64) add_definitions(-DFEATURE_EMULATE_SINGLESTEP) + add_compile_definitions($<$>>:FEATURE_MULTIREG_RETURN>) endif (CLR_CMAKE_TARGET_ARCH_ARM64) if (CLR_CMAKE_TARGET_UNIX) From d96ce1a023732b8159ae756ee33534a2e00f5da6 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sat, 27 Apr 2024 11:45:51 -0700 Subject: [PATCH 153/248] [main] Update dependencies from dotnet/arcade (#101329) * Update dependencies from https://github.com/dotnet/arcade build 20240419.5 Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XliffTasks , Microsoft.DotNet.XUnitAssert , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 9.0.0-beta.24219.1 -> To Version 9.0.0-beta.24219.5 * Update dependencies from https://github.com/dotnet/arcade build 20240419.5 Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XliffTasks , Microsoft.DotNet.XUnitAssert , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 9.0.0-beta.24219.1 -> To Version 9.0.0-beta.24219.5 * Update dependencies from https://github.com/dotnet/arcade build 20240419.5 Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XliffTasks , Microsoft.DotNet.XUnitAssert , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 9.0.0-beta.24219.1 -> To Version 9.0.0-beta.24219.5 * Update dependencies from https://github.com/dotnet/arcade build 20240423.1 Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XliffTasks , Microsoft.DotNet.XUnitAssert , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 9.0.0-beta.24219.1 -> To Version 9.0.0-beta.24223.1 * Update dependencies from https://github.com/dotnet/arcade build 20240423.8 Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XliffTasks , Microsoft.DotNet.XUnitAssert , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 9.0.0-beta.24219.1 -> To Version 9.0.0-beta.24223.8 * Update dependencies from https://github.com/dotnet/arcade build 20240423.8 Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XliffTasks , Microsoft.DotNet.XUnitAssert , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 9.0.0-beta.24219.1 -> To Version 9.0.0-beta.24223.8 * Update dependencies from https://github.com/dotnet/arcade build 20240423.8 Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XliffTasks , Microsoft.DotNet.XUnitAssert , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 9.0.0-beta.24219.1 -> To Version 9.0.0-beta.24223.8 * Update dependencies from https://github.com/dotnet/arcade build 20240424.2 Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XliffTasks , Microsoft.DotNet.XUnitAssert , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 9.0.0-beta.24219.1 -> To Version 9.0.0-beta.24224.2 * Update dependencies from https://github.com/dotnet/arcade build 20240426.3 Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XliffTasks , Microsoft.DotNet.XUnitAssert , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 9.0.0-beta.24219.1 -> To Version 9.0.0-beta.24226.3 --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Larry Ewing --- eng/Version.Details.xml | 84 ++--- eng/Versions.props | 32 +- eng/common/core-templates/job/job.yml | 266 ++++++++++++++ eng/common/core-templates/job/onelocbuild.yml | 121 +++++++ .../job/publish-build-assets.yml | 172 ++++++++++ .../core-templates/job/source-build.yml | 80 +++++ .../job/source-index-stage1.yml | 73 ++++ .../core-templates/jobs/codeql-build.yml | 33 ++ eng/common/core-templates/jobs/jobs.yml | 119 +++++++ .../core-templates/jobs/source-build.yml | 50 +++ .../post-build/common-variables.yml | 24 ++ .../core-templates/post-build/post-build.yml | 298 ++++++++++++++++ .../post-build/setup-maestro-vars.yml | 74 ++++ .../post-build/trigger-subscription.yml | 13 + .../steps/add-build-to-channel.yml | 13 + .../steps/component-governance.yml | 14 + .../core-templates/steps/generate-sbom.yml | 54 +++ .../steps/publish-build-artifacts.yml | 20 ++ .../core-templates/steps/publish-logs.yml | 59 ++++ .../steps/publish-pipeline-artifacts.yml | 20 ++ .../core-templates/steps/retain-build.yml | 28 ++ .../core-templates/steps/send-to-helix.yml | 93 +++++ .../core-templates/steps/source-build.yml | 134 ++++++++ .../variables/pool-providers.yml | 8 + eng/common/cross/toolchain.cmake | 20 ++ eng/common/sdk-task.ps1 | 2 +- eng/common/template-guidance.md | 137 ++++++++ eng/common/templates-official/job/job.yml | 324 ++++-------------- .../templates-official/job/onelocbuild.yml | 115 +------ .../job/publish-build-assets.yml | 162 +-------- .../templates-official/job/source-build.yml | 70 +--- .../job/source-index-stage1.yml | 70 +--- .../templates-official/jobs/codeql-build.yml | 32 +- eng/common/templates-official/jobs/jobs.yml | 100 +----- .../templates-official/jobs/source-build.yml | 49 +-- .../post-build/common-variables.yml | 28 +- .../post-build/post-build.yml | 289 +--------------- .../post-build/setup-maestro-vars.yml | 74 +--- .../steps/add-build-to-channel.yml | 18 +- .../steps/component-governance.yml | 18 +- .../steps/generate-sbom.yml | 51 +-- .../steps/publish-build-artifacts.yml | 41 +++ .../templates-official/steps/publish-logs.yml | 54 +-- .../steps/publish-pipeline-artifacts.yml | 26 ++ .../templates-official/steps/retain-build.yml | 33 +- .../steps/send-to-helix.yml | 98 +----- .../templates-official/steps/source-build.yml | 134 +------- eng/common/templates/job/execute-sdl.yml | 139 -------- eng/common/templates/job/job.yml | 314 ++++------------- eng/common/templates/job/onelocbuild.yml | 112 +----- .../templates/job/publish-build-assets.yml | 158 +-------- eng/common/templates/job/source-build.yml | 69 +--- .../templates/job/source-index-stage1.yml | 70 +--- eng/common/templates/jobs/codeql-build.yml | 32 +- eng/common/templates/jobs/jobs.yml | 100 +----- eng/common/templates/jobs/source-build.yml | 49 +-- .../templates/post-build/common-variables.yml | 28 +- .../templates/post-build/post-build.yml | 286 +--------------- .../post-build/setup-maestro-vars.yml | 74 +--- .../templates/steps/add-build-to-channel.yml | 18 +- eng/common/templates/steps/build-reason.yml | 12 - .../templates/steps/component-governance.yml | 18 +- eng/common/templates/steps/execute-codeql.yml | 32 -- eng/common/templates/steps/execute-sdl.yml | 88 ----- eng/common/templates/steps/generate-sbom.yml | 51 +-- .../steps/publish-build-artifacts.yml | 40 +++ eng/common/templates/steps/publish-logs.yml | 54 +-- .../steps/publish-pipeline-artifacts.yml | 34 ++ eng/common/templates/steps/retain-build.yml | 33 +- eng/common/templates/steps/run-on-unix.yml | 7 - eng/common/templates/steps/run-on-windows.yml | 7 - .../steps/run-script-ifequalelse.yml | 33 -- eng/common/templates/steps/send-to-helix.yml | 98 +----- eng/common/templates/steps/source-build.yml | 134 +------- eng/common/templates/steps/telemetry-end.yml | 102 ------ .../templates/steps/telemetry-start.yml | 241 ------------- .../templates/variables/pool-providers.yml | 54 +-- .../templates/variables/sdl-variables.yml | 7 - eng/common/tools.ps1 | 4 +- global.json | 6 +- 80 files changed, 2459 insertions(+), 3872 deletions(-) create mode 100644 eng/common/core-templates/job/job.yml create mode 100644 eng/common/core-templates/job/onelocbuild.yml create mode 100644 eng/common/core-templates/job/publish-build-assets.yml create mode 100644 eng/common/core-templates/job/source-build.yml create mode 100644 eng/common/core-templates/job/source-index-stage1.yml create mode 100644 eng/common/core-templates/jobs/codeql-build.yml create mode 100644 eng/common/core-templates/jobs/jobs.yml create mode 100644 eng/common/core-templates/jobs/source-build.yml create mode 100644 eng/common/core-templates/post-build/common-variables.yml create mode 100644 eng/common/core-templates/post-build/post-build.yml create mode 100644 eng/common/core-templates/post-build/setup-maestro-vars.yml create mode 100644 eng/common/core-templates/post-build/trigger-subscription.yml create mode 100644 eng/common/core-templates/steps/add-build-to-channel.yml create mode 100644 eng/common/core-templates/steps/component-governance.yml create mode 100644 eng/common/core-templates/steps/generate-sbom.yml create mode 100644 eng/common/core-templates/steps/publish-build-artifacts.yml create mode 100644 eng/common/core-templates/steps/publish-logs.yml create mode 100644 eng/common/core-templates/steps/publish-pipeline-artifacts.yml create mode 100644 eng/common/core-templates/steps/retain-build.yml create mode 100644 eng/common/core-templates/steps/send-to-helix.yml create mode 100644 eng/common/core-templates/steps/source-build.yml create mode 100644 eng/common/core-templates/variables/pool-providers.yml create mode 100644 eng/common/template-guidance.md create mode 100644 eng/common/templates-official/steps/publish-build-artifacts.yml create mode 100644 eng/common/templates-official/steps/publish-pipeline-artifacts.yml delete mode 100644 eng/common/templates/job/execute-sdl.yml delete mode 100644 eng/common/templates/steps/build-reason.yml delete mode 100644 eng/common/templates/steps/execute-codeql.yml delete mode 100644 eng/common/templates/steps/execute-sdl.yml create mode 100644 eng/common/templates/steps/publish-build-artifacts.yml create mode 100644 eng/common/templates/steps/publish-pipeline-artifacts.yml delete mode 100644 eng/common/templates/steps/run-on-unix.yml delete mode 100644 eng/common/templates/steps/run-on-windows.yml delete mode 100644 eng/common/templates/steps/run-script-ifequalelse.yml delete mode 100644 eng/common/templates/steps/telemetry-end.yml delete mode 100644 eng/common/templates/steps/telemetry-start.yml delete mode 100644 eng/common/templates/variables/sdl-variables.yml diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index c35213b8ecadb5..9bcdac9884a810 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -92,87 +92,87 @@ - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 https://github.com/dotnet/runtime-assets @@ -332,9 +332,9 @@ https://github.com/dotnet/xharness ec633d9ddbdb86dd3d772989889690821f790484 - + https://github.com/dotnet/arcade - b4f4d40741f161e2c0d96c19c51a4013850ef65f + 97e2f41e909dcabb1103fe98ba4540a246662187 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index 8ca09ea0685ae1..0ff857849146a1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -83,22 +83,22 @@ 9.0.100-preview.4.24221.4 - 9.0.0-beta.24219.1 - 9.0.0-beta.24219.1 - 9.0.0-beta.24219.1 - 9.0.0-beta.24219.1 - 2.6.7-beta.24219.1 - 9.0.0-beta.24219.1 - 2.6.7-beta.24219.1 - 9.0.0-beta.24219.1 - 9.0.0-beta.24219.1 - 9.0.0-beta.24219.1 - 9.0.0-beta.24219.1 - 9.0.0-beta.24219.1 - 9.0.0-beta.24219.1 - 9.0.0-beta.24219.1 - 9.0.0-beta.24219.1 - 9.0.0-beta.24219.1 + 9.0.0-beta.24226.3 + 9.0.0-beta.24226.3 + 9.0.0-beta.24226.3 + 9.0.0-beta.24226.3 + 2.6.7-beta.24226.3 + 9.0.0-beta.24226.3 + 2.6.7-beta.24226.3 + 9.0.0-beta.24226.3 + 9.0.0-beta.24226.3 + 9.0.0-beta.24226.3 + 9.0.0-beta.24226.3 + 9.0.0-beta.24226.3 + 9.0.0-beta.24226.3 + 9.0.0-beta.24226.3 + 9.0.0-beta.24226.3 + 9.0.0-beta.24226.3 1.4.0 diff --git a/eng/common/core-templates/job/job.yml b/eng/common/core-templates/job/job.yml new file mode 100644 index 00000000000000..dc3bd560a50e24 --- /dev/null +++ b/eng/common/core-templates/job/job.yml @@ -0,0 +1,266 @@ +parameters: +# Job schema parameters - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job + cancelTimeoutInMinutes: '' + condition: '' + container: '' + continueOnError: false + dependsOn: '' + displayName: '' + pool: '' + steps: [] + strategy: '' + timeoutInMinutes: '' + variables: [] + workspace: '' + templateContext: {} + +# Job base template specific parameters + # See schema documentation - https://github.com/dotnet/arcade/blob/master/Documentation/AzureDevOps/TemplateSchema.md + # publishing defaults + artifacts: '' + enableMicrobuild: false + enablePublishBuildArtifacts: false + enablePublishBuildAssets: false + enablePublishTestResults: false + enablePublishUsingPipelines: false + enableBuildRetry: false + disableComponentGovernance: '' + componentGovernanceIgnoreDirectories: '' + mergeTestResults: false + testRunTitle: '' + testResultsFormat: '' + name: '' + preSteps: [] + artifactPublishSteps: [] + runAsPublic: false + +# Sbom related params + enableSbom: true + PackageVersion: 9.0.0 + BuildDropPath: '$(Build.SourcesDirectory)/artifacts' + +# 1es specific parameters + is1ESPipeline: '' + +jobs: +- job: ${{ parameters.name }} + + ${{ if ne(parameters.cancelTimeoutInMinutes, '') }}: + cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }} + + ${{ if ne(parameters.condition, '') }}: + condition: ${{ parameters.condition }} + + ${{ if ne(parameters.container, '') }}: + container: ${{ parameters.container }} + + ${{ if ne(parameters.continueOnError, '') }}: + continueOnError: ${{ parameters.continueOnError }} + + ${{ if ne(parameters.dependsOn, '') }}: + dependsOn: ${{ parameters.dependsOn }} + + ${{ if ne(parameters.displayName, '') }}: + displayName: ${{ parameters.displayName }} + + ${{ if ne(parameters.pool, '') }}: + pool: ${{ parameters.pool }} + + ${{ if ne(parameters.strategy, '') }}: + strategy: ${{ parameters.strategy }} + + ${{ if ne(parameters.timeoutInMinutes, '') }}: + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} + + ${{ if ne(parameters.templateContext, '') }}: + templateContext: ${{ parameters.templateContext }} + + variables: + - ${{ if ne(parameters.enableTelemetry, 'false') }}: + - name: DOTNET_CLI_TELEMETRY_PROFILE + value: '$(Build.Repository.Uri)' + - ${{ if eq(parameters.enableRichCodeNavigation, 'true') }}: + - name: EnableRichCodeNavigation + value: 'true' + # Retry signature validation up to three times, waiting 2 seconds between attempts. + # See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu3028#retry-untrusted-root-failures + - name: NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY + value: 3,2000 + - ${{ each variable in parameters.variables }}: + # handle name-value variable syntax + # example: + # - name: [key] + # value: [value] + - ${{ if ne(variable.name, '') }}: + - name: ${{ variable.name }} + value: ${{ variable.value }} + + # handle variable groups + - ${{ if ne(variable.group, '') }}: + - group: ${{ variable.group }} + + # handle template variable syntax + # example: + # - template: path/to/template.yml + # parameters: + # [key]: [value] + - ${{ if ne(variable.template, '') }}: + - template: ${{ variable.template }} + ${{ if ne(variable.parameters, '') }}: + parameters: ${{ variable.parameters }} + + # handle key-value variable syntax. + # example: + # - [key]: [value] + - ${{ if and(eq(variable.name, ''), eq(variable.group, ''), eq(variable.template, '')) }}: + - ${{ each pair in variable }}: + - name: ${{ pair.key }} + value: ${{ pair.value }} + + # DotNet-HelixApi-Access provides 'HelixApiAccessToken' for internal builds + - ${{ if and(eq(parameters.enableTelemetry, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - group: DotNet-HelixApi-Access + + ${{ if ne(parameters.workspace, '') }}: + workspace: ${{ parameters.workspace }} + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if ne(parameters.preSteps, '') }}: + - ${{ each preStep in parameters.preSteps }}: + - ${{ preStep }} + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if eq(parameters.enableMicrobuild, 'true') }}: + - task: MicroBuildSigningPlugin@4 + displayName: Install MicroBuild plugin + inputs: + signType: $(_SignType) + zipSources: false + feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json + env: + TeamName: $(_TeamName) + MicroBuildOutputFolderOverride: '$(Agent.TempDirectory)' + continueOnError: ${{ parameters.continueOnError }} + condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) + + - ${{ if and(eq(parameters.runAsPublic, 'false'), eq(variables['System.TeamProject'], 'internal')) }}: + - task: NuGetAuthenticate@1 + + - ${{ if and(ne(parameters.artifacts.download, 'false'), ne(parameters.artifacts.download, '')) }}: + - task: DownloadPipelineArtifact@2 + inputs: + buildType: current + artifactName: ${{ coalesce(parameters.artifacts.download.name, 'Artifacts_$(Agent.OS)_$(_BuildConfig)') }} + targetPath: ${{ coalesce(parameters.artifacts.download.path, 'artifacts') }} + itemPattern: ${{ coalesce(parameters.artifacts.download.pattern, '**') }} + + - ${{ each step in parameters.steps }}: + - ${{ step }} + + - ${{ if eq(parameters.enableRichCodeNavigation, true) }}: + - task: RichCodeNavIndexer@0 + displayName: RichCodeNav Upload + inputs: + languages: ${{ coalesce(parameters.richCodeNavigationLanguage, 'csharp') }} + environment: ${{ coalesce(parameters.richCodeNavigationEnvironment, 'internal') }} + richNavLogOutputDirectory: $(Build.SourcesDirectory)/artifacts/bin + uploadRichNavArtifacts: ${{ coalesce(parameters.richCodeNavigationUploadArtifacts, false) }} + continueOnError: true + + - template: /eng/common/core-templates/steps/component-governance.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + ${{ if eq(parameters.disableComponentGovernance, '') }}: + ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/dotnet/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/microsoft/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: + disableComponentGovernance: false + ${{ else }}: + disableComponentGovernance: true + ${{ else }}: + disableComponentGovernance: ${{ parameters.disableComponentGovernance }} + componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} + + - ${{ if eq(parameters.enableMicrobuild, 'true') }}: + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - task: MicroBuildCleanup@1 + displayName: Execute Microbuild cleanup tasks + condition: and(always(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} + env: + TeamName: $(_TeamName) + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: + - template: /eng/common/core-templates/steps/generate-sbom.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + PackageVersion: ${{ parameters.packageVersion}} + BuildDropPath: ${{ parameters.buildDropPath }} + IgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} + publishArtifacts: false + + # Publish test results + - ${{ if and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')) }}: + - ${{ if eq(parameters.testResultsFormat, 'xunit') }}: + - task: PublishTestResults@2 + displayName: Publish XUnit Test Results + inputs: + testResultsFormat: 'xUnit' + testResultsFiles: '*.xml' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' + testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit + mergeTestResults: ${{ parameters.mergeTestResults }} + continueOnError: true + condition: always() + - ${{ if eq(parameters.testResultsFormat, 'vstest') }}: + - task: PublishTestResults@2 + displayName: Publish TRX Test Results + inputs: + testResultsFormat: 'VSTest' + testResultsFiles: '*.trx' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' + testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx + mergeTestResults: ${{ parameters.mergeTestResults }} + continueOnError: true + condition: always() + + # gather artifacts + - ${{ if ne(parameters.artifacts.publish, '') }}: + - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: + - task: CopyFiles@2 + displayName: Gather binaries for publish to artifacts + inputs: + SourceFolder: 'artifacts/bin' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/bin' + - task: CopyFiles@2 + displayName: Gather packages for publish to artifacts + inputs: + SourceFolder: 'artifacts/packages' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/packages' + - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: + - task: CopyFiles@2 + displayName: Gather logs for publish to artifacts + inputs: + SourceFolder: 'artifacts/log' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/log' + + - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: + - task: CopyFiles@2 + displayName: Gather logs for publish to artifacts + inputs: + SourceFolder: 'artifacts/log/$(_BuildConfig)' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' + - ${{ if eq(parameters.enableBuildRetry, 'true') }}: + - task: CopyFiles@2 + displayName: Gather buildconfiguration for build retry + inputs: + SourceFolder: '$(Build.SourcesDirectory)/eng/common/BuildConfiguration' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/eng/common/BuildConfiguration' + + - ${{ each step in parameters.artifactPublishSteps }}: + - ${{ step }} diff --git a/eng/common/core-templates/job/onelocbuild.yml b/eng/common/core-templates/job/onelocbuild.yml new file mode 100644 index 00000000000000..00feec8ebbc3ab --- /dev/null +++ b/eng/common/core-templates/job/onelocbuild.yml @@ -0,0 +1,121 @@ +parameters: + # Optional: dependencies of the job + dependsOn: '' + + # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool + pool: '' + + CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex + GithubPat: $(BotAccount-dotnet-bot-repo-PAT) + + SourcesDirectory: $(Build.SourcesDirectory) + CreatePr: true + AutoCompletePr: false + ReusePr: true + UseLfLineEndings: true + UseCheckedInLocProjectJson: false + SkipLocProjectJsonGeneration: false + LanguageSet: VS_Main_Languages + LclSource: lclFilesInRepo + LclPackageId: '' + RepoType: gitHub + GitHubOrg: dotnet + MirrorRepo: '' + MirrorBranch: main + condition: '' + JobNameSuffix: '' + is1ESPipeline: '' +jobs: +- job: OneLocBuild${{ parameters.JobNameSuffix }} + + dependsOn: ${{ parameters.dependsOn }} + + displayName: OneLocBuild${{ parameters.JobNameSuffix }} + + variables: + - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat + - name: _GenerateLocProjectArguments + value: -SourcesDirectory ${{ parameters.SourcesDirectory }} + -LanguageSet "${{ parameters.LanguageSet }}" + -CreateNeutralXlfs + - ${{ if eq(parameters.UseCheckedInLocProjectJson, 'true') }}: + - name: _GenerateLocProjectArguments + value: ${{ variables._GenerateLocProjectArguments }} -UseCheckedInLocProjectJson + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + ${{ if ne(parameters.pool, '') }}: + pool: ${{ parameters.pool }} + ${{ if eq(parameters.pool, '') }}: + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: $(DncEngInternalBuildPool) + image: 1es-windows-2022 + os: windows + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if ne(parameters.SkipLocProjectJsonGeneration, 'true') }}: + - task: Powershell@2 + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/generate-locproject.ps1 + arguments: $(_GenerateLocProjectArguments) + displayName: Generate LocProject.json + condition: ${{ parameters.condition }} + + - task: OneLocBuild@2 + displayName: OneLocBuild + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + inputs: + locProj: eng/Localize/LocProject.json + outDir: $(Build.ArtifactStagingDirectory) + lclSource: ${{ parameters.LclSource }} + lclPackageId: ${{ parameters.LclPackageId }} + isCreatePrSelected: ${{ parameters.CreatePr }} + isAutoCompletePrSelected: ${{ parameters.AutoCompletePr }} + ${{ if eq(parameters.CreatePr, true) }}: + isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} + ${{ if eq(parameters.RepoType, 'gitHub') }}: + isShouldReusePrSelected: ${{ parameters.ReusePr }} + packageSourceAuth: patAuth + patVariable: ${{ parameters.CeapexPat }} + ${{ if eq(parameters.RepoType, 'gitHub') }}: + repoType: ${{ parameters.RepoType }} + gitHubPatVariable: "${{ parameters.GithubPat }}" + ${{ if ne(parameters.MirrorRepo, '') }}: + isMirrorRepoSelected: true + gitHubOrganization: ${{ parameters.GitHubOrg }} + mirrorRepo: ${{ parameters.MirrorRepo }} + mirrorBranch: ${{ parameters.MirrorBranch }} + condition: ${{ parameters.condition }} + + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish Localization Files + pathToPublish: '$(Build.ArtifactStagingDirectory)/loc' + publishLocation: Container + artifactName: Loc + condition: ${{ parameters.condition }} + + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish LocProject.json + pathToPublish: '$(Build.SourcesDirectory)/eng/Localize/' + publishLocation: Container + artifactName: Loc + condition: ${{ parameters.condition }} \ No newline at end of file diff --git a/eng/common/core-templates/job/publish-build-assets.yml b/eng/common/core-templates/job/publish-build-assets.yml new file mode 100644 index 00000000000000..8fe9299542c531 --- /dev/null +++ b/eng/common/core-templates/job/publish-build-assets.yml @@ -0,0 +1,172 @@ +parameters: + configuration: 'Debug' + + # Optional: condition for the job to run + condition: '' + + # Optional: 'true' if future jobs should run even if this job fails + continueOnError: false + + # Optional: dependencies of the job + dependsOn: '' + + # Optional: Include PublishBuildArtifacts task + enablePublishBuildArtifacts: false + + # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool + pool: {} + + # Optional: should run as a public build even in the internal project + # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. + runAsPublic: false + + # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing + publishUsingPipelines: false + + # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing + publishAssetsImmediately: false + + artifactsPublishingAdditionalParameters: '' + + signingValidationAdditionalParameters: '' + + is1ESPipeline: '' + +jobs: +- job: Asset_Registry_Publish + + dependsOn: ${{ parameters.dependsOn }} + timeoutInMinutes: 150 + + ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: + displayName: Publish Assets + ${{ else }}: + displayName: Publish to Build Asset Registry + + variables: + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - group: Publish-Build-Assets + - group: AzureDevOps-Artifact-Feeds-Pats + - name: runCodesignValidationInjection + value: false + # unconditional - needed for logs publishing (redactor tool version) + - template: /eng/common/core-templates/post-build/common-variables.yml + + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Publishing-Internal + image: windows.vs2019.amd64 + os: windows + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - checkout: self + fetchDepth: 3 + clean: true + + - task: DownloadBuildArtifacts@0 + displayName: Download artifact + inputs: + artifactName: AssetManifests + downloadPath: '$(Build.StagingDirectory)/Download' + checkDownloadedFiles: true + condition: ${{ parameters.condition }} + continueOnError: ${{ parameters.continueOnError }} + + - task: NuGetAuthenticate@1 + + - task: PowerShell@2 + displayName: Publish Build Assets + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task PublishBuildAssets -restore -msbuildEngine dotnet + /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' + /p:BuildAssetRegistryToken=$(MaestroAccessToken) + /p:MaestroApiEndpoint=https://maestro.dot.net + /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} + /p:OfficialBuildId=$(Build.BuildNumber) + condition: ${{ parameters.condition }} + continueOnError: ${{ parameters.continueOnError }} + + - task: powershell@2 + displayName: Create ReleaseConfigs Artifact + inputs: + targetType: inline + script: | + New-Item -Path "$(Build.StagingDirectory)/ReleaseConfigs" -ItemType Directory -Force + $filePath = "$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt" + Add-Content -Path $filePath -Value $(BARBuildId) + Add-Content -Path $filePath -Value "$(DefaultChannels)" + Add-Content -Path $filePath -Value $(IsStableBuild) + + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish ReleaseConfigs Artifact + pathToPublish: '$(Build.StagingDirectory)/ReleaseConfigs' + publishLocation: Container + artifactName: ReleaseConfigs + + - task: powershell@2 + displayName: Check if SymbolPublishingExclusionsFile.txt exists + inputs: + targetType: inline + script: | + $symbolExclusionfile = "$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt" + if(Test-Path -Path $symbolExclusionfile) + { + Write-Host "SymbolExclusionFile exists" + Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]true" + } + else{ + Write-Host "Symbols Exclusion file does not exist" + Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]false" + } + + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish SymbolPublishingExclusionsFile Artifact + condition: eq(variables['SymbolExclusionFile'], 'true') + pathToPublish: '$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' + publishLocation: Container + artifactName: ReleaseConfigs + + - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: PowerShell@2 + displayName: Publish Using Darc + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 + arguments: -BuildId $(BARBuildId) + -PublishingInfraVersion 3 + -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' + -MaestroToken '$(MaestroApiAccessToken)' + -WaitPublishingFinish true + -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' + -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' + + - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: + - template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + JobLabel: 'Publish_Artifacts_Logs' diff --git a/eng/common/core-templates/job/source-build.yml b/eng/common/core-templates/job/source-build.yml new file mode 100644 index 00000000000000..c0ce4b3c861861 --- /dev/null +++ b/eng/common/core-templates/job/source-build.yml @@ -0,0 +1,80 @@ +parameters: + # This template adds arcade-powered source-build to CI. The template produces a server job with a + # default ID 'Source_Build_Complete' to put in a dependency list if necessary. + + # Specifies the prefix for source-build jobs added to pipeline. Use this if disambiguation needed. + jobNamePrefix: 'Source_Build' + + # Defines the platform on which to run the job. By default, a linux-x64 machine, suitable for + # managed-only repositories. This is an object with these properties: + # + # name: '' + # The name of the job. This is included in the job ID. + # targetRID: '' + # The name of the target RID to use, instead of the one auto-detected by Arcade. + # nonPortable: false + # Enables non-portable mode. This means a more specific RID (e.g. fedora.32-x64 rather than + # linux-x64), and compiling against distro-provided packages rather than portable ones. + # skipPublishValidation: false + # Disables publishing validation. By default, a check is performed to ensure no packages are + # published by source-build. + # container: '' + # A container to use. Runs in docker. + # pool: {} + # A pool to use. Runs directly on an agent. + # buildScript: '' + # Specifies the build script to invoke to perform the build in the repo. The default + # './build.sh' should work for typical Arcade repositories, but this is customizable for + # difficult situations. + # jobProperties: {} + # A list of job properties to inject at the top level, for potential extensibility beyond + # container and pool. + platform: {} + + is1ESPipeline: '' + +jobs: +- job: ${{ parameters.jobNamePrefix }}_${{ parameters.platform.name }} + displayName: Source-Build (${{ parameters.platform.name }}) + + ${{ each property in parameters.platform.jobProperties }}: + ${{ property.key }}: ${{ property.value }} + + ${{ if ne(parameters.platform.container, '') }}: + container: ${{ parameters.platform.container }} + + ${{ if eq(parameters.platform.pool, '') }}: + # The default VM host AzDO pool. This should be capable of running Docker containers: almost all + # source-build builds run in Docker, including the default managed platform. + # /eng/common/core-templates/variables/pool-providers.yml can't be used here (some customers declare variables already), so duplicate its logic + ${{ if eq(parameters.is1ESPipeline, 'true') }}: + pool: + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] + demands: ImageOverride -equals build.ubuntu.2004.amd64 + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] + image: 1es-mariner-2 + os: linux + ${{ else }}: + pool: + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] + demands: ImageOverride -equals Build.Ubuntu.2204.Amd64.Open + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] + demands: ImageOverride -equals Build.Ubuntu.2204.Amd64 + ${{ if ne(parameters.platform.pool, '') }}: + pool: ${{ parameters.platform.pool }} + + workspace: + clean: all + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - template: /eng/common/core-templates/steps/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + platform: ${{ parameters.platform }} diff --git a/eng/common/core-templates/job/source-index-stage1.yml b/eng/common/core-templates/job/source-index-stage1.yml new file mode 100644 index 00000000000000..9c6e5ae3c3e45a --- /dev/null +++ b/eng/common/core-templates/job/source-index-stage1.yml @@ -0,0 +1,73 @@ +parameters: + runAsPublic: false + sourceIndexPackageVersion: 1.0.1-20240129.2 + sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json + sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" + preSteps: [] + binlogPath: artifacts/log/Debug/Build.binlog + condition: '' + dependsOn: '' + pool: '' + is1ESPipeline: '' + +jobs: +- job: SourceIndexStage1 + dependsOn: ${{ parameters.dependsOn }} + condition: ${{ parameters.condition }} + variables: + - name: SourceIndexPackageVersion + value: ${{ parameters.sourceIndexPackageVersion }} + - name: SourceIndexPackageSource + value: ${{ parameters.sourceIndexPackageSource }} + - name: BinlogPath + value: ${{ parameters.binlogPath }} + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - group: source-dot-net stage1 variables + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + ${{ if ne(parameters.pool, '') }}: + pool: ${{ parameters.pool }} + ${{ if eq(parameters.pool, '') }}: + pool: + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: $(DncEngPublicBuildPool) + image: windows.vs2022.amd64.open + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + name: $(DncEngInternalBuildPool) + image: windows.vs2022.amd64 + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ each preStep in parameters.preSteps }}: + - ${{ preStep }} + + - task: UseDotNet@2 + displayName: Use .NET 8 SDK + inputs: + packageType: sdk + version: 8.0.x + installationPath: $(Agent.TempDirectory)/dotnet + workingDirectory: $(Agent.TempDirectory) + + - script: | + $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools + $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools + displayName: Download Tools + # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. + workingDirectory: $(Agent.TempDirectory) + + - script: ${{ parameters.sourceIndexBuildCommand }} + displayName: Build Repository + + - script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i $(BinlogPath) -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output + displayName: Process Binlog into indexable sln + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - script: $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) + displayName: Upload stage1 artifacts to source index + env: + BLOB_CONTAINER_URL: $(source-dot-net-stage1-blob-container-url) diff --git a/eng/common/core-templates/jobs/codeql-build.yml b/eng/common/core-templates/jobs/codeql-build.yml new file mode 100644 index 00000000000000..f2144252cc65c8 --- /dev/null +++ b/eng/common/core-templates/jobs/codeql-build.yml @@ -0,0 +1,33 @@ +parameters: + # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md + continueOnError: false + # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job + jobs: [] + # Optional: if specified, restore and use this version of Guardian instead of the default. + overrideGuardianVersion: '' + is1ESPipeline: '' + +jobs: +- template: /eng/common/core-templates/jobs/jobs.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + enableMicrobuild: false + enablePublishBuildArtifacts: false + enablePublishTestResults: false + enablePublishBuildAssets: false + enablePublishUsingPipelines: false + enableTelemetry: true + + variables: + - group: Publish-Build-Assets + # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in + # sync with the packages.config file. + - name: DefaultGuardianVersion + value: 0.109.0 + - name: GuardianPackagesConfigFile + value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config + - name: GuardianVersion + value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} + + jobs: ${{ parameters.jobs }} + diff --git a/eng/common/core-templates/jobs/jobs.yml b/eng/common/core-templates/jobs/jobs.yml new file mode 100644 index 00000000000000..ea69be4341c62f --- /dev/null +++ b/eng/common/core-templates/jobs/jobs.yml @@ -0,0 +1,119 @@ +parameters: + # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md + continueOnError: false + + # Optional: Include PublishBuildArtifacts task + enablePublishBuildArtifacts: false + + # Optional: Enable publishing using release pipelines + enablePublishUsingPipelines: false + + # Optional: Enable running the source-build jobs to build repo from source + enableSourceBuild: false + + # Optional: Parameters for source-build template. + # See /eng/common/core-templates/jobs/source-build.yml for options + sourceBuildParameters: [] + + graphFileGeneration: + # Optional: Enable generating the graph files at the end of the build + enabled: false + # Optional: Include toolset dependencies in the generated graph files + includeToolset: false + + # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job + jobs: [] + + # Optional: Override automatically derived dependsOn value for "publish build assets" job + publishBuildAssetsDependsOn: '' + + # Optional: Publish the assets as soon as the publish to BAR stage is complete, rather doing so in a separate stage. + publishAssetsImmediately: false + + # Optional: If using publishAssetsImmediately and additional parameters are needed, can be used to send along additional parameters (normally sent to post-build.yml) + artifactsPublishingAdditionalParameters: '' + signingValidationAdditionalParameters: '' + + # Optional: should run as a public build even in the internal project + # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. + runAsPublic: false + + enableSourceIndex: false + sourceIndexParams: {} + + artifacts: {} + is1ESPipeline: '' + +# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, +# and some (Microbuild) should only be applied to non-PR cases for internal builds. + +jobs: +- ${{ each job in parameters.jobs }}: + - ${{ if eq(parameters.is1ESPipeline, 'true') }}: + - template: /eng/common/templates-official/job/job.yml + parameters: + # pass along parameters + ${{ each parameter in parameters }}: + ${{ if ne(parameter.key, 'jobs') }}: + ${{ parameter.key }}: ${{ parameter.value }} + + # pass along job properties + ${{ each property in job }}: + ${{ if ne(property.key, 'job') }}: + ${{ property.key }}: ${{ property.value }} + + name: ${{ job.job }} + + - ${{ else }}: + - template: /eng/common/templates/job/job.yml + parameters: + # pass along parameters + ${{ each parameter in parameters }}: + ${{ if ne(parameter.key, 'jobs') }}: + ${{ parameter.key }}: ${{ parameter.value }} + + # pass along job properties + ${{ each property in job }}: + ${{ if ne(property.key, 'job') }}: + ${{ property.key }}: ${{ property.value }} + + name: ${{ job.job }} + +- ${{ if eq(parameters.enableSourceBuild, true) }}: + - template: /eng/common/core-templates/jobs/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + allCompletedJobId: Source_Build_Complete + ${{ each parameter in parameters.sourceBuildParameters }}: + ${{ parameter.key }}: ${{ parameter.value }} + +- ${{ if eq(parameters.enableSourceIndex, 'true') }}: + - template: ../job/source-index-stage1.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + runAsPublic: ${{ parameters.runAsPublic }} + ${{ each parameter in parameters.sourceIndexParams }}: + ${{ parameter.key }}: ${{ parameter.value }} + +- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: + - template: ../job/publish-build-assets.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + continueOnError: ${{ parameters.continueOnError }} + dependsOn: + - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: + - ${{ each job in parameters.publishBuildAssetsDependsOn }}: + - ${{ job.job }} + - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: + - ${{ each job in parameters.jobs }}: + - ${{ job.job }} + - ${{ if eq(parameters.enableSourceBuild, true) }}: + - Source_Build_Complete + + runAsPublic: ${{ parameters.runAsPublic }} + publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} + publishAssetsImmediately: ${{ parameters.publishAssetsImmediately }} + enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + signingValidationAdditionalParameters: ${{ parameters.signingValidationAdditionalParameters }} diff --git a/eng/common/core-templates/jobs/source-build.yml b/eng/common/core-templates/jobs/source-build.yml new file mode 100644 index 00000000000000..d8e5d008522682 --- /dev/null +++ b/eng/common/core-templates/jobs/source-build.yml @@ -0,0 +1,50 @@ +parameters: + # This template adds arcade-powered source-build to CI. A job is created for each platform, as + # well as an optional server job that completes when all platform jobs complete. + + # The name of the "join" job for all source-build platforms. If set to empty string, the job is + # not included. Existing repo pipelines can use this job depend on all source-build jobs + # completing without maintaining a separate list of every single job ID: just depend on this one + # server job. By default, not included. Recommended name if used: 'Source_Build_Complete'. + allCompletedJobId: '' + + # See /eng/common/core-templates/job/source-build.yml + jobNamePrefix: 'Source_Build' + + # This is the default platform provided by Arcade, intended for use by a managed-only repo. + defaultManagedPlatform: + name: 'Managed' + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream9' + + # Defines the platforms on which to run build jobs. One job is created for each platform, and the + # object in this array is sent to the job template as 'platform'. If no platforms are specified, + # one job runs on 'defaultManagedPlatform'. + platforms: [] + + is1ESPipeline: '' + +jobs: + +- ${{ if ne(parameters.allCompletedJobId, '') }}: + - job: ${{ parameters.allCompletedJobId }} + displayName: Source-Build Complete + pool: server + dependsOn: + - ${{ each platform in parameters.platforms }}: + - ${{ parameters.jobNamePrefix }}_${{ platform.name }} + - ${{ if eq(length(parameters.platforms), 0) }}: + - ${{ parameters.jobNamePrefix }}_${{ parameters.defaultManagedPlatform.name }} + +- ${{ each platform in parameters.platforms }}: + - template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobNamePrefix: ${{ parameters.jobNamePrefix }} + platform: ${{ platform }} + +- ${{ if eq(length(parameters.platforms), 0) }}: + - template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobNamePrefix: ${{ parameters.jobNamePrefix }} + platform: ${{ parameters.defaultManagedPlatform }} diff --git a/eng/common/core-templates/post-build/common-variables.yml b/eng/common/core-templates/post-build/common-variables.yml new file mode 100644 index 00000000000000..b9ede10bf099ae --- /dev/null +++ b/eng/common/core-templates/post-build/common-variables.yml @@ -0,0 +1,24 @@ +variables: + - group: Publish-Build-Assets + + # Whether the build is internal or not + - name: IsInternalBuild + value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} + + # Default Maestro++ API Endpoint and API Version + - name: MaestroApiEndPoint + value: "https://maestro.dot.net" + - name: MaestroApiAccessToken + value: $(MaestroAccessToken) + - name: MaestroApiVersion + value: "2020-02-20" + + - name: SourceLinkCLIVersion + value: 3.0.0 + - name: SymbolToolVersion + value: 1.0.1 + - name: BinlogToolVersion + value: 1.0.11 + + - name: runCodesignValidationInjection + value: false diff --git a/eng/common/core-templates/post-build/post-build.yml b/eng/common/core-templates/post-build/post-build.yml new file mode 100644 index 00000000000000..ed1e6692f739b2 --- /dev/null +++ b/eng/common/core-templates/post-build/post-build.yml @@ -0,0 +1,298 @@ +parameters: + # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. + # Publishing V1 is no longer supported + # Publishing V2 is no longer supported + # Publishing V3 is the default + - name: publishingInfraVersion + displayName: Which version of publishing should be used to promote the build definition? + type: number + default: 3 + values: + - 3 + + - name: BARBuildId + displayName: BAR Build Id + type: number + default: 0 + + - name: PromoteToChannelIds + displayName: Channel to promote BARBuildId to + type: string + default: '' + + - name: enableSourceLinkValidation + displayName: Enable SourceLink validation + type: boolean + default: false + + - name: enableSigningValidation + displayName: Enable signing validation + type: boolean + default: true + + - name: enableSymbolValidation + displayName: Enable symbol validation + type: boolean + default: false + + - name: enableNugetValidation + displayName: Enable NuGet validation + type: boolean + default: true + + - name: publishInstallersAndChecksums + displayName: Publish installers and checksums + type: boolean + default: true + + - name: SDLValidationParameters + type: object + default: + enable: false + publishGdn: false + continueOnError: false + params: '' + artifactNames: '' + downloadArtifacts: true + + # These parameters let the user customize the call to sdk-task.ps1 for publishing + # symbols & general artifacts as well as for signing validation + - name: symbolPublishingAdditionalParameters + displayName: Symbol publishing additional parameters + type: string + default: '' + + - name: artifactsPublishingAdditionalParameters + displayName: Artifact publishing additional parameters + type: string + default: '' + + - name: signingValidationAdditionalParameters + displayName: Signing validation additional parameters + type: string + default: '' + + # Which stages should finish execution before post-build stages start + - name: validateDependsOn + type: object + default: + - build + + - name: publishDependsOn + type: object + default: + - Validate + + # Optional: Call asset publishing rather than running in a separate stage + - name: publishAssetsImmediately + type: boolean + default: false + + - name: is1ESPipeline + type: boolean + default: false + +stages: +- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: + - stage: Validate + dependsOn: ${{ parameters.validateDependsOn }} + displayName: Validate Build Assets + variables: + - template: /eng/common/core-templates/post-build/common-variables.yml + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobs: + - job: + displayName: NuGet Validation + condition: and(succeededOrFailed(), eq( ${{ parameters.enableNugetValidation }}, 'true')) + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + name: $(DncEngInternalBuildPool) + image: 1es-windows-2022 + os: windows + + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: PackageArtifacts + checkDownloadedFiles: true + + - task: PowerShell@2 + displayName: Validate + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1 + arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ + -ToolDestinationPath $(Agent.BuildDirectory)/Extract/ + + - job: + displayName: Signing Validation + condition: and( eq( ${{ parameters.enableSigningValidation }}, 'true'), ne( variables['PostBuildSign'], 'true')) + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + name: $(DncEngInternalBuildPool) + image: 1es-windows-2022 + os: windows + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: PackageArtifacts + checkDownloadedFiles: true + itemPattern: | + ** + !**/Microsoft.SourceBuild.Intermediate.*.nupkg + + # This is necessary whenever we want to publish/restore to an AzDO private feed + # Since sdk-task.ps1 tries to restore packages we need to do this authentication here + # otherwise it'll complain about accessing a private feed. + - task: NuGetAuthenticate@1 + displayName: 'Authenticate to AzDO Feeds' + + # Signing validation will optionally work with the buildmanifest file which is downloaded from + # Azure DevOps above. + - task: PowerShell@2 + displayName: Validate + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task SigningValidation -restore -msbuildEngine vs + /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' + /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' + ${{ parameters.signingValidationAdditionalParameters }} + + - template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + StageLabel: 'Validation' + JobLabel: 'Signing' + BinlogToolVersion: $(BinlogToolVersion) + + - job: + displayName: SourceLink Validation + condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + name: $(DncEngInternalBuildPool) + image: 1es-windows-2022 + os: windows + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: DownloadBuildArtifacts@0 + displayName: Download Blob Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: BlobArtifacts + checkDownloadedFiles: true + + - task: PowerShell@2 + displayName: Validate + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1 + arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/ + -ExtractPath $(Agent.BuildDirectory)/Extract/ + -GHRepoName $(Build.Repository.Name) + -GHCommit $(Build.SourceVersion) + -SourcelinkCliVersion $(SourceLinkCLIVersion) + continueOnError: true + +- ${{ if ne(parameters.publishAssetsImmediately, 'true') }}: + - stage: publish_using_darc + ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: + dependsOn: ${{ parameters.publishDependsOn }} + ${{ else }}: + dependsOn: ${{ parameters.validateDependsOn }} + displayName: Publish using Darc + variables: + - template: /eng/common/core-templates/post-build/common-variables.yml + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobs: + - job: + displayName: Publish Using Darc + timeoutInMinutes: 120 + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + name: NetCore1ESPool-Publishing-Internal + image: windows.vs2019.amd64 + os: windows + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: NuGetAuthenticate@1 + + - task: PowerShell@2 + displayName: Publish Using Darc + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 + arguments: -BuildId $(BARBuildId) + -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} + -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' + -MaestroToken '$(MaestroApiAccessToken)' + -WaitPublishingFinish true + -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' + -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' diff --git a/eng/common/core-templates/post-build/setup-maestro-vars.yml b/eng/common/core-templates/post-build/setup-maestro-vars.yml new file mode 100644 index 00000000000000..8d56b5726793f8 --- /dev/null +++ b/eng/common/core-templates/post-build/setup-maestro-vars.yml @@ -0,0 +1,74 @@ +parameters: + BARBuildId: '' + PromoteToChannelIds: '' + is1ESPipeline: '' + +steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: + - task: DownloadBuildArtifacts@0 + displayName: Download Release Configs + inputs: + buildType: current + artifactName: ReleaseConfigs + checkDownloadedFiles: true + + - task: PowerShell@2 + name: setReleaseVars + displayName: Set Release Configs Vars + inputs: + targetType: inline + pwsh: true + script: | + try { + if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { + $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt + + $BarId = $Content | Select -Index 0 + $Channels = $Content | Select -Index 1 + $IsStableBuild = $Content | Select -Index 2 + + $AzureDevOpsProject = $Env:System_TeamProject + $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId + $AzureDevOpsBuildId = $Env:Build_BuildId + } + else { + $buildApiEndpoint = "${Env:MaestroApiEndPoint}/api/builds/${Env:BARBuildId}?api-version=${Env:MaestroApiVersion}" + + $apiHeaders = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' + $apiHeaders.Add('Accept', 'application/json') + $apiHeaders.Add('Authorization',"Bearer ${Env:MAESTRO_API_TOKEN}") + + $buildInfo = try { Invoke-WebRequest -Method Get -Uri $buildApiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } + + $BarId = $Env:BARBuildId + $Channels = $Env:PromoteToMaestroChannels -split "," + $Channels = $Channels -join "][" + $Channels = "[$Channels]" + + $IsStableBuild = $buildInfo.stable + $AzureDevOpsProject = $buildInfo.azureDevOpsProject + $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId + $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId + } + + Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" + Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" + Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" + + Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" + Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" + Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" + } + catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + exit 1 + } + env: + MAESTRO_API_TOKEN: $(MaestroApiAccessToken) + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} diff --git a/eng/common/core-templates/post-build/trigger-subscription.yml b/eng/common/core-templates/post-build/trigger-subscription.yml new file mode 100644 index 00000000000000..da669030daf6e9 --- /dev/null +++ b/eng/common/core-templates/post-build/trigger-subscription.yml @@ -0,0 +1,13 @@ +parameters: + ChannelId: 0 + +steps: +- task: PowerShell@2 + displayName: Triggering subscriptions + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/trigger-subscriptions.ps1 + arguments: -SourceRepo $(Build.Repository.Uri) + -ChannelId ${{ parameters.ChannelId }} + -MaestroApiAccessToken $(MaestroAccessToken) + -MaestroApiEndPoint $(MaestroApiEndPoint) + -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/core-templates/steps/add-build-to-channel.yml b/eng/common/core-templates/steps/add-build-to-channel.yml new file mode 100644 index 00000000000000..f67a210d62f3e5 --- /dev/null +++ b/eng/common/core-templates/steps/add-build-to-channel.yml @@ -0,0 +1,13 @@ +parameters: + ChannelId: 0 + +steps: +- task: PowerShell@2 + displayName: Add Build to Channel + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/add-build-to-channel.ps1 + arguments: -BuildId $(BARBuildId) + -ChannelId ${{ parameters.ChannelId }} + -MaestroApiAccessToken $(MaestroApiAccessToken) + -MaestroApiEndPoint $(MaestroApiEndPoint) + -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/core-templates/steps/component-governance.yml b/eng/common/core-templates/steps/component-governance.yml new file mode 100644 index 00000000000000..df449a34c11207 --- /dev/null +++ b/eng/common/core-templates/steps/component-governance.yml @@ -0,0 +1,14 @@ +parameters: + disableComponentGovernance: false + componentGovernanceIgnoreDirectories: '' + is1ESPipeline: false + +steps: +- ${{ if eq(parameters.disableComponentGovernance, 'true') }}: + - script: echo "##vso[task.setvariable variable=skipComponentGovernanceDetection]true" + displayName: Set skipComponentGovernanceDetection variable +- ${{ if ne(parameters.disableComponentGovernance, 'true') }}: + - task: ComponentGovernanceComponentDetection@0 + continueOnError: true + inputs: + ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} \ No newline at end of file diff --git a/eng/common/core-templates/steps/generate-sbom.yml b/eng/common/core-templates/steps/generate-sbom.yml new file mode 100644 index 00000000000000..d938b60e1bb534 --- /dev/null +++ b/eng/common/core-templates/steps/generate-sbom.yml @@ -0,0 +1,54 @@ +# BuildDropPath - The root folder of the drop directory for which the manifest file will be generated. +# PackageName - The name of the package this SBOM represents. +# PackageVersion - The version of the package this SBOM represents. +# ManifestDirPath - The path of the directory where the generated manifest files will be placed +# IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. + +parameters: + PackageVersion: 9.0.0 + BuildDropPath: '$(Build.SourcesDirectory)/artifacts' + PackageName: '.NET' + ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom + IgnoreDirectories: '' + sbomContinueOnError: true + is1ESPipeline: false + # disable publishArtifacts if some other step is publishing the artifacts (like job.yml). + publishArtifacts: true + +steps: +- task: PowerShell@2 + displayName: Prep for SBOM generation in (Non-linux) + condition: or(eq(variables['Agent.Os'], 'Windows_NT'), eq(variables['Agent.Os'], 'Darwin')) + inputs: + filePath: ./eng/common/generate-sbom-prep.ps1 + arguments: ${{parameters.manifestDirPath}} + +# Chmodding is a workaround for https://github.com/dotnet/arcade/issues/8461 +- script: | + chmod +x ./eng/common/generate-sbom-prep.sh + ./eng/common/generate-sbom-prep.sh ${{parameters.manifestDirPath}} + displayName: Prep for SBOM generation in (Linux) + condition: eq(variables['Agent.Os'], 'Linux') + continueOnError: ${{ parameters.sbomContinueOnError }} + +- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 + displayName: 'Generate SBOM manifest' + continueOnError: ${{ parameters.sbomContinueOnError }} + inputs: + PackageName: ${{ parameters.packageName }} + BuildDropPath: ${{ parameters.buildDropPath }} + PackageVersion: ${{ parameters.packageVersion }} + ManifestDirPath: ${{ parameters.manifestDirPath }} + ${{ if ne(parameters.IgnoreDirectories, '') }}: + AdditionalComponentDetectorArgs: '--IgnoreDirectories ${{ parameters.IgnoreDirectories }}' + +- ${{ if eq(parameters.publishArtifacts, 'true')}}: + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish SBOM manifest + continueOnError: ${{parameters.sbomContinueOnError}} + targetPath: '${{ parameters.manifestDirPath }}' + artifactName: $(ARTIFACT_NAME) + diff --git a/eng/common/core-templates/steps/publish-build-artifacts.yml b/eng/common/core-templates/steps/publish-build-artifacts.yml new file mode 100644 index 00000000000000..f24ce346684e60 --- /dev/null +++ b/eng/common/core-templates/steps/publish-build-artifacts.yml @@ -0,0 +1,20 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false +- name: args + type: object + default: {} +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - template: /eng/common/templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + ${{ each parameter in parameters.args }}: + ${{ parameter.key }}: ${{ parameter.value }} +- ${{ else }}: + - template: /eng/common/templates-official/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + ${{ each parameter in parameters.args }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/core-templates/steps/publish-logs.yml b/eng/common/core-templates/steps/publish-logs.yml new file mode 100644 index 00000000000000..8c5ea77b586d27 --- /dev/null +++ b/eng/common/core-templates/steps/publish-logs.yml @@ -0,0 +1,59 @@ +parameters: + StageLabel: '' + JobLabel: '' + CustomSensitiveDataList: '' + # A default - in case value from eng/common/core-templates/post-build/common-variables.yml is not passed + BinlogToolVersion: '1.0.11' + is1ESPipeline: false + +steps: +- task: Powershell@2 + displayName: Prepare Binlogs to Upload + inputs: + targetType: inline + script: | + New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ + Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ + continueOnError: true + condition: always() + +- task: PowerShell@2 + displayName: Redact Logs + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/redact-logs.ps1 + # For now this needs to have explicit list of all sensitive data. Taken from eng/publishing/v3/publish.yml + # Sensitive data can as well be added to $(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' + # If the file exists - sensitive data for redaction will be sourced from it + # (single entry per line, lines starting with '# ' are considered comments and skipped) + arguments: -InputPath '$(Build.SourcesDirectory)/PostBuildLogs' + -BinlogToolVersion ${{parameters.BinlogToolVersion}} + -TokensFilePath '$(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' + '$(publishing-dnceng-devdiv-code-r-build-re)' + '$(MaestroAccessToken)' + '$(dn-bot-all-orgs-artifact-feeds-rw)' + '$(akams-client-id)' + '$(akams-client-secret)' + '$(microsoft-symbol-server-pat)' + '$(symweb-symbol-server-pat)' + '$(dn-bot-all-orgs-build-rw-code-rw)' + ${{parameters.CustomSensitiveDataList}} + continueOnError: true + condition: always() + +- task: CopyFiles@2 + displayName: Gather post build logs + inputs: + SourceFolder: '$(Build.SourcesDirectory)/PostBuildLogs' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/PostBuildLogs' + +- template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish Logs + pathToPublish: '$(Build.ArtifactStagingDirectory)/PostBuildLogs' + publishLocation: Container + artifactName: PostBuildLogs + continueOnError: true + condition: always() diff --git a/eng/common/core-templates/steps/publish-pipeline-artifacts.yml b/eng/common/core-templates/steps/publish-pipeline-artifacts.yml new file mode 100644 index 00000000000000..2efec04dc2c163 --- /dev/null +++ b/eng/common/core-templates/steps/publish-pipeline-artifacts.yml @@ -0,0 +1,20 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false + +- name: args + type: object + default: {} + +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - template: /eng/common/templates/steps/publish-pipeline-artifacts.yml + parameters: + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} +- ${{ else }}: + - template: /eng/common/templates-official/steps/publish-pipeline-artifacts.yml + parameters: + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/core-templates/steps/retain-build.yml b/eng/common/core-templates/steps/retain-build.yml new file mode 100644 index 00000000000000..83d97a26a01ff9 --- /dev/null +++ b/eng/common/core-templates/steps/retain-build.yml @@ -0,0 +1,28 @@ +parameters: + # Optional azure devops PAT with build execute permissions for the build's organization, + # only needed if the build that should be retained ran on a different organization than + # the pipeline where this template is executing from + Token: '' + # Optional BuildId to retain, defaults to the current running build + BuildId: '' + # Azure devops Organization URI for the build in the https://dev.azure.com/ format. + # Defaults to the organization the current pipeline is running on + AzdoOrgUri: '$(System.CollectionUri)' + # Azure devops project for the build. Defaults to the project the current pipeline is running on + AzdoProject: '$(System.TeamProject)' + +steps: + - task: powershell@2 + inputs: + targetType: 'filePath' + filePath: eng/common/retain-build.ps1 + pwsh: true + arguments: > + -AzdoOrgUri: ${{parameters.AzdoOrgUri}} + -AzdoProject ${{parameters.AzdoProject}} + -Token ${{coalesce(parameters.Token, '$env:SYSTEM_ACCESSTOKEN') }} + -BuildId ${{coalesce(parameters.BuildId, '$env:BUILD_ID')}} + displayName: Enable permanent build retention + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + BUILD_ID: $(Build.BuildId) \ No newline at end of file diff --git a/eng/common/core-templates/steps/send-to-helix.yml b/eng/common/core-templates/steps/send-to-helix.yml new file mode 100644 index 00000000000000..68fa739c4ab215 --- /dev/null +++ b/eng/common/core-templates/steps/send-to-helix.yml @@ -0,0 +1,93 @@ +# Please remember to update the documentation if you make changes to these parameters! +parameters: + HelixSource: 'pr/default' # required -- sources must start with pr/, official/, prodcon/, or agent/ + HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/' + HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number + HelixTargetQueues: '' # required -- semicolon-delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues + HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group + HelixProjectPath: 'eng/common/helixpublish.proj' # optional -- path to the project file to build relative to BUILD_SOURCESDIRECTORY + HelixProjectArguments: '' # optional -- arguments passed to the build command + HelixConfiguration: '' # optional -- additional property attached to a job + HelixPreCommands: '' # optional -- commands to run before Helix work item execution + HelixPostCommands: '' # optional -- commands to run after Helix work item execution + WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects + WorkItemCommand: '' # optional -- a command to execute on the payload; requires WorkItemDirectory; incompatible with XUnitProjects + WorkItemTimeout: '' # optional -- a timeout in TimeSpan.Parse-ready value (e.g. 00:02:00) for the work item command; requires WorkItemDirectory; incompatible with XUnitProjects + CorrelationPayloadDirectory: '' # optional -- a directory to zip up and send to Helix as a correlation payload + XUnitProjects: '' # optional -- semicolon-delimited list of XUnitProjects to parse and send to Helix; requires XUnitRuntimeTargetFramework, XUnitPublishTargetFramework, XUnitRunnerVersion, and IncludeDotNetCli=true + XUnitWorkItemTimeout: '' # optional -- the workitem timeout in seconds for all workitems created from the xUnit projects specified by XUnitProjects + XUnitPublishTargetFramework: '' # optional -- framework to use to publish your xUnit projects + XUnitRuntimeTargetFramework: '' # optional -- framework to use for the xUnit console runner + XUnitRunnerVersion: '' # optional -- version of the xUnit nuget package you wish to use on Helix; required for XUnitProjects + IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion + DotNetCliPackageType: '' # optional -- either 'sdk', 'runtime' or 'aspnetcore-runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json + DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json + WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." + IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set + HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting https://helix.int-dot.net ) + Creator: '' # optional -- if the build is external, use this to specify who is sending the job + DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO + condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() + continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false + +steps: + - powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 $env:BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"' + displayName: ${{ parameters.DisplayNamePrefix }} (Windows) + env: + BuildConfig: $(_BuildConfig) + HelixSource: ${{ parameters.HelixSource }} + HelixType: ${{ parameters.HelixType }} + HelixBuild: ${{ parameters.HelixBuild }} + HelixConfiguration: ${{ parameters.HelixConfiguration }} + HelixTargetQueues: ${{ parameters.HelixTargetQueues }} + HelixAccessToken: ${{ parameters.HelixAccessToken }} + HelixPreCommands: ${{ parameters.HelixPreCommands }} + HelixPostCommands: ${{ parameters.HelixPostCommands }} + WorkItemDirectory: ${{ parameters.WorkItemDirectory }} + WorkItemCommand: ${{ parameters.WorkItemCommand }} + WorkItemTimeout: ${{ parameters.WorkItemTimeout }} + CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} + XUnitProjects: ${{ parameters.XUnitProjects }} + XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} + XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} + XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} + XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} + IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} + DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} + DotNetCliVersion: ${{ parameters.DotNetCliVersion }} + WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} + HelixBaseUri: ${{ parameters.HelixBaseUri }} + Creator: ${{ parameters.Creator }} + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} + - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog + displayName: ${{ parameters.DisplayNamePrefix }} (Unix) + env: + BuildConfig: $(_BuildConfig) + HelixSource: ${{ parameters.HelixSource }} + HelixType: ${{ parameters.HelixType }} + HelixBuild: ${{ parameters.HelixBuild }} + HelixConfiguration: ${{ parameters.HelixConfiguration }} + HelixTargetQueues: ${{ parameters.HelixTargetQueues }} + HelixAccessToken: ${{ parameters.HelixAccessToken }} + HelixPreCommands: ${{ parameters.HelixPreCommands }} + HelixPostCommands: ${{ parameters.HelixPostCommands }} + WorkItemDirectory: ${{ parameters.WorkItemDirectory }} + WorkItemCommand: ${{ parameters.WorkItemCommand }} + WorkItemTimeout: ${{ parameters.WorkItemTimeout }} + CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} + XUnitProjects: ${{ parameters.XUnitProjects }} + XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} + XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} + XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} + XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} + IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} + DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} + DotNetCliVersion: ${{ parameters.DotNetCliVersion }} + WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} + HelixBaseUri: ${{ parameters.HelixBaseUri }} + Creator: ${{ parameters.Creator }} + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} diff --git a/eng/common/core-templates/steps/source-build.yml b/eng/common/core-templates/steps/source-build.yml new file mode 100644 index 00000000000000..bdd725b496f91b --- /dev/null +++ b/eng/common/core-templates/steps/source-build.yml @@ -0,0 +1,134 @@ +parameters: + # This template adds arcade-powered source-build to CI. + + # This is a 'steps' template, and is intended for advanced scenarios where the existing build + # infra has a careful build methodology that must be followed. For example, a repo + # (dotnet/runtime) might choose to clone the GitHub repo only once and store it as a pipeline + # artifact for all subsequent jobs to use, to reduce dependence on a strong network connection to + # GitHub. Using this steps template leaves room for that infra to be included. + + # Defines the platform on which to run the steps. See 'eng/common/core-templates/job/source-build.yml' + # for details. The entire object is described in the 'job' template for simplicity, even though + # the usage of the properties on this object is split between the 'job' and 'steps' templates. + platform: {} + is1ESPipeline: false + +steps: +# Build. Keep it self-contained for simple reusability. (No source-build-specific job variables.) +- script: | + set -x + df -h + + # If building on the internal project, the artifact feeds variable may be available (usually only if needed) + # In that case, call the feed setup script to add internal feeds corresponding to public ones. + # In addition, add an msbuild argument to copy the WIP from the repo to the target build location. + # This is because SetupNuGetSources.sh will alter the current NuGet.config file, and we need to preserve those + # changes. + internalRestoreArgs= + if [ '$(dn-bot-dnceng-artifact-feeds-rw)' != '$''(dn-bot-dnceng-artifact-feeds-rw)' ]; then + # Temporarily work around https://github.com/dotnet/arcade/issues/7709 + chmod +x $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh + $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh $(Build.SourcesDirectory)/NuGet.config $(dn-bot-dnceng-artifact-feeds-rw) + internalRestoreArgs='/p:CopyWipIntoInnerSourceBuildRepo=true' + + # The 'Copy WIP' feature of source build uses git stash to apply changes from the original repo. + # This only works if there is a username/email configured, which won't be the case in most CI runs. + git config --get user.email + if [ $? -ne 0 ]; then + git config user.email dn-bot@microsoft.com + git config user.name dn-bot + fi + fi + + # If building on the internal project, the internal storage variable may be available (usually only if needed) + # In that case, add variables to allow the download of internal runtimes if the specified versions are not found + # in the default public locations. + internalRuntimeDownloadArgs= + if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then + internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://dotnetbuilds.blob.core.windows.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://dotnetbuilds.blob.core.windows.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' + fi + + buildConfig=Release + # Check if AzDO substitutes in a build config from a variable, and use it if so. + if [ '$(_BuildConfig)' != '$''(_BuildConfig)' ]; then + buildConfig='$(_BuildConfig)' + fi + + officialBuildArgs= + if [ '${{ and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}' = 'True' ]; then + officialBuildArgs='/p:DotNetPublishUsingPipelines=true /p:OfficialBuildId=$(BUILD.BUILDNUMBER)' + fi + + targetRidArgs= + if [ '${{ parameters.platform.targetRID }}' != '' ]; then + targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' + fi + + runtimeOsArgs= + if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then + runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' + fi + + baseOsArgs= + if [ '${{ parameters.platform.baseOS }}' != '' ]; then + baseOsArgs='/p:BaseOS=${{ parameters.platform.baseOS }}' + fi + + publishArgs= + if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then + publishArgs='--publish' + fi + + assetManifestFileName=SourceBuild_RidSpecific.xml + if [ '${{ parameters.platform.name }}' != '' ]; then + assetManifestFileName=SourceBuild_${{ parameters.platform.name }}.xml + fi + + ${{ coalesce(parameters.platform.buildScript, './build.sh') }} --ci \ + --configuration $buildConfig \ + --restore --build --pack $publishArgs -bl \ + $officialBuildArgs \ + $internalRuntimeDownloadArgs \ + $internalRestoreArgs \ + $targetRidArgs \ + $runtimeOsArgs \ + $baseOsArgs \ + /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ + /p:ArcadeBuildFromSource=true \ + /p:DotNetBuildSourceOnly=true \ + /p:DotNetBuildRepo=true \ + /p:AssetManifestFileName=$assetManifestFileName + displayName: Build + +# Upload build logs for diagnosis. +- task: CopyFiles@2 + displayName: Prepare BuildLogs staging directory + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: | + **/*.log + **/*.binlog + artifacts/sb/prebuilt-report/** + TargetFolder: '$(Build.StagingDirectory)/BuildLogs' + CleanTargetFolder: true + continueOnError: true + condition: succeededOrFailed() + +- template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish BuildLogs + targetPath: '$(Build.StagingDirectory)/BuildLogs' + artifactName: BuildLogs_SourceBuild_${{ parameters.platform.name }}_Attempt$(System.JobAttempt) + continueOnError: true + condition: succeededOrFailed() + +# Manually inject component detection so that we can ignore the source build upstream cache, which contains +# a nupkg cache of input packages (a local feed). +# This path must match the upstream cache path in property 'CurrentRepoSourceBuiltNupkgCacheDir' +# in src\Microsoft.DotNet.Arcade.Sdk\tools\SourceBuild\SourceBuildArcade.targets +- task: ComponentGovernanceComponentDetection@0 + displayName: Component Detection (Exclude upstream cache) + inputs: + ignoreDirectories: '$(Build.SourcesDirectory)/artifacts/sb/src/artifacts/obj/source-built-upstream-cache' diff --git a/eng/common/core-templates/variables/pool-providers.yml b/eng/common/core-templates/variables/pool-providers.yml new file mode 100644 index 00000000000000..41053d382a2e10 --- /dev/null +++ b/eng/common/core-templates/variables/pool-providers.yml @@ -0,0 +1,8 @@ +parameters: + is1ESPipeline: false + +variables: + - ${{ if eq(parameters.is1ESPipeline, 'true') }}: + - template: /eng/common/templates-official/variables/pool-providers.yml + - ${{ else }}: + - template: /eng/common/templates/variables/pool-providers.yml \ No newline at end of file diff --git a/eng/common/cross/toolchain.cmake b/eng/common/cross/toolchain.cmake index 3762640fdcf792..9a4e285a5ae3f0 100644 --- a/eng/common/cross/toolchain.cmake +++ b/eng/common/cross/toolchain.cmake @@ -382,6 +382,26 @@ if(TARGET_ARCH_NAME MATCHES "^(arm|armel|x86)$") endif() endif() +# Set C++ standard library options if specified +set(CLR_CMAKE_CXX_STANDARD_LIBRARY "" CACHE STRING "Standard library flavor to link against. Only supported with the Clang compiler.") +if (CLR_CMAKE_CXX_STANDARD_LIBRARY) + add_compile_options($<$:--stdlib=${CLR_CMAKE_CXX_STANDARD_LIBRARY}>) + add_link_options($<$:--stdlib=${CLR_CMAKE_CXX_STANDARD_LIBRARY}>) +endif() + +option(CLR_CMAKE_CXX_STANDARD_LIBRARY_STATIC "Statically link against the C++ standard library" OFF) +if(CLR_CMAKE_CXX_STANDARD_LIBRARY_STATIC) + add_link_options($<$:-static-libstdc++>) +endif() + +set(CLR_CMAKE_CXX_ABI_LIBRARY "" CACHE STRING "C++ ABI implementation library to link against. Only supported with the Clang compiler.") +if (CLR_CMAKE_CXX_ABI_LIBRARY) + # The user may specify the ABI library with the 'lib' prefix, like 'libstdc++'. Strip the prefix here so the linker finds the right library. + string(REGEX REPLACE "^lib(.+)" "\\1" CLR_CMAKE_CXX_ABI_LIBRARY ${CLR_CMAKE_CXX_ABI_LIBRARY}) + # We need to specify this as a linker-backend option as Clang will filter this option out when linking to libc++. + add_link_options("LINKER:-l${CLR_CMAKE_CXX_ABI_LIBRARY}") +endif() + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/eng/common/sdk-task.ps1 b/eng/common/sdk-task.ps1 index 091023970f1c9c..aab40de3fd9aca 100644 --- a/eng/common/sdk-task.ps1 +++ b/eng/common/sdk-task.ps1 @@ -64,7 +64,7 @@ try { $GlobalJson.tools | Add-Member -Name "vs" -Value (ConvertFrom-Json "{ `"version`": `"16.5`" }") -MemberType NoteProperty } if( -not ($GlobalJson.tools.PSObject.Properties.Name -match "xcopy-msbuild" )) { - $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.8.5" -MemberType NoteProperty + $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.10.0-pre.4.0" -MemberType NoteProperty } if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") { $xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true diff --git a/eng/common/template-guidance.md b/eng/common/template-guidance.md new file mode 100644 index 00000000000000..c114bc28dcb95d --- /dev/null +++ b/eng/common/template-guidance.md @@ -0,0 +1,137 @@ +# Overview + +Arcade provides templates for public (`/templates`) and 1ES pipeline templates (`/templates-official`) scenarios. Pipelines which are required to be managed by 1ES pipeline templates should reference `/templates-offical`, all other pipelines may reference `/templates`. + +## How to use + +Basic guidance is: + +- 1ES Pipeline Template or 1ES Microbuild template runs should reference `eng/common/templates-official`. Any internal production-graded pipeline should use these templates. + +- All other runs should reference `eng/common/templates`. + +See [azure-pipelines.yml](../../azure-pipelines.yml) (templates-official example) or [azure-pipelines-pr.yml](../../azure-pipelines-pr.yml) (templates example) for examples. + +#### The `templateIs1ESManaged` parameter + +The `templateIs1ESManaged` is available on most templates and affects which of the variants is used for nested templates. See [Development Notes](#development-notes) below for more information on the `templateIs1ESManaged1 parameter. + +- For templates under `job/`, `jobs/`, `steps`, or `post-build/`, this parameter must be explicitly set. + +## Multiple outputs + +1ES pipeline templates impose a policy where every publish artifact execution results in additional security scans being injected into your pipeline. When using `templates-official/jobs/jobs.yml`, Arcade reduces the number of additional security injections by gathering all publishing outputs into the [Build.ArtifactStagingDirectory](https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#build-variables-devops-services), and utilizing the [outputParentDirectory](https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-docs/1es-pipeline-templates/features/outputs#multiple-outputs) feature of 1ES pipeline templates. When implementing your pipeline, if you ensure publish artifacts are located in the `$(Build.ArtifactStagingDirectory)`, and utilize the 1ES provided template context, then you can reduce the number of security scans for your pipeline. + +Example: +``` yaml +# azure-pipelines.yml +extends: + template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate + parameters: + stages: + - stage: build + jobs: + - template: /eng/common/templates-official/jobs/jobs.yml@self + parameters: + # 1ES makes use of outputs to reduce security task injection overhead + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Publish logs from source' + continueOnError: true + condition: always() + targetPath: $(Build.ArtifactStagingDirectory)/artifacts/log + artifactName: Logs + jobs: + - job: Windows + steps: + - script: echo "friendly neighborhood" > artifacts/marvel/spiderman.txt + # copy build outputs to artifact staging directory for publishing + - task: CopyFiles@2 + displayName: Gather build output + inputs: + SourceFolder: '$(Build.SourcesDirectory)/artifacts/marvel' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/marvel' +``` + +Note: Multiple outputs are ONLY applicable to 1ES PT publishing (only usable when referencing `templates-official`). + +# Development notes + +**Folder / file structure** + +``` text +eng\common\ + [templates || templates-official]\ + job\ + job.yml (shim + artifact publishing logic) + onelocbuild.yml (shim) + publish-build-assets.yml (shim) + source-build.yml (shim) + source-index-stage1.yml (shim) + jobs\ + codeql-build.yml (shim) + jobs.yml (shim) + source-build.yml (shim) + post-build\ + post-build.yml (shim) + trigger-subscription.yml (shim) + common-variabls.yml (shim) + setup-maestro-vars.yml (shim) + steps\ + publish-build-artifacts.yml (logic) + publish-pipeline-artifacts.yml (logic) + add-build-channel.yml (shim) + component-governance.yml (shim) + generate-sbom.yml (shim) + publish-logs.yml (shim) + retain-build.yml (shim) + send-to-helix.yml (shim) + source-build.yml (shim) + variables\ + pool-providers.yml (logic + redirect) # templates/variables/pool-providers.yml will redirect to templates-official/variables/pool-providers.yml if you are running in the internal project + sdl-variables.yml (logic) + core-templates\ + job\ + job.yml (logic) + onelocbuild.yml (logic) + publish-build-assets.yml (logic) + source-build.yml (logic) + source-index-stage1.yml (logic) + jobs\ + codeql-build.yml (logic) + jobs.yml (logic) + source-build.yml (logic) + post-build\ + common-variabls.yml (logic) + post-build.yml (logic) + setup-maestro-vars.yml (logic) + trigger-subscription.yml (logic) + steps\ + add-build-to-channel.yml (logic) + component-governance.yml (logic) + generate-sbom.yml (logic) + publish-build-artifacts.yml (redirect) + publish-logs.yml (logic) + publish-pipeline-artifacts.yml (redirect) + retain-build.yml (logic) + send-to-helix.yml (logic) + source-build.yml (logic) + variables\ + pool-providers.yml (redirect) +``` + +In the table above, a file is designated as "shim", "logic", or "redirect". + +- shim - represents a yaml file which is an intermediate step between pipeline logic and .Net Core Engineering's templates (`core-templates`) and defines the `is1ESPipeline` parameter value. + +- logic - represents actual base template logic. + +- redirect- represents a file in `core-templates` which redirects to the "logic" file in either `templates` or `templates-official`. + +Logic for Arcade's templates live **primarily** in the `core-templates` folder. The exceptions to the location of the logic files are around artifact publishing, which is handled differently between 1es pipeline templates and standard templates. `templates` and `templates-official` provide shim entry points which redirect to `core-templates` while also defining the `is1ESPipeline` parameter. If a shim is referenced in `templates`, then `is1ESPipeline` is set to `false`. If a shim is referenced in `templates-official`, then `is1ESPipeline` is set to `true`. + +Within `templates` and `templates-official`, the templates at the "stages", and "jobs" / "job" level have been replaced with shims. Templates at the "steps" and "variables" level are typically too granular to be replaced with shims and instead persist logic which is directly applicable to either scenario. + +Within `core-templates`, there are a handful of places where logic is dependent on which shim entry point was used. In those places, we redirect back to the respective logic file in `templates` or `templates-official`. diff --git a/eng/common/templates-official/job/job.yml b/eng/common/templates-official/job/job.yml index 761acc5eb624c6..4724e9aaa80910 100644 --- a/eng/common/templates-official/job/job.yml +++ b/eng/common/templates-official/job/job.yml @@ -1,264 +1,62 @@ -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - -parameters: -# Job schema parameters - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - cancelTimeoutInMinutes: '' - condition: '' - container: '' - continueOnError: false - dependsOn: '' - displayName: '' - pool: '' - steps: [] - strategy: '' - timeoutInMinutes: '' - variables: [] - workspace: '' - templateContext: '' - -# Job base template specific parameters - # See schema documentation - https://github.com/dotnet/arcade/blob/master/Documentation/AzureDevOps/TemplateSchema.md - artifacts: '' - enableMicrobuild: false - enablePublishBuildArtifacts: false - enablePublishBuildAssets: false - enablePublishTestResults: false - enablePublishUsingPipelines: false - enableBuildRetry: false - disableComponentGovernance: '' - componentGovernanceIgnoreDirectories: '' - mergeTestResults: false - testRunTitle: '' - testResultsFormat: '' - name: '' - preSteps: [] - runAsPublic: false -# Sbom related params - enableSbom: true - PackageVersion: 7.0.0 - BuildDropPath: '$(Build.SourcesDirectory)/artifacts' - jobs: -- job: ${{ parameters.name }} - - ${{ if ne(parameters.cancelTimeoutInMinutes, '') }}: - cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }} - - ${{ if ne(parameters.condition, '') }}: - condition: ${{ parameters.condition }} - - ${{ if ne(parameters.container, '') }}: - container: ${{ parameters.container }} - - ${{ if ne(parameters.continueOnError, '') }}: - continueOnError: ${{ parameters.continueOnError }} - - ${{ if ne(parameters.dependsOn, '') }}: - dependsOn: ${{ parameters.dependsOn }} - - ${{ if ne(parameters.displayName, '') }}: - displayName: ${{ parameters.displayName }} - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - - ${{ if ne(parameters.strategy, '') }}: - strategy: ${{ parameters.strategy }} - - ${{ if ne(parameters.timeoutInMinutes, '') }}: - timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - - ${{ if ne(parameters.templateContext, '') }}: - templateContext: ${{ parameters.templateContext }} - - variables: - - ${{ if ne(parameters.enableTelemetry, 'false') }}: - - name: DOTNET_CLI_TELEMETRY_PROFILE - value: '$(Build.Repository.Uri)' - - ${{ if eq(parameters.enableRichCodeNavigation, 'true') }}: - - name: EnableRichCodeNavigation - value: 'true' - # Retry signature validation up to three times, waiting 2 seconds between attempts. - # See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu3028#retry-untrusted-root-failures - - name: NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY - value: 3,2000 - - ${{ each variable in parameters.variables }}: - # handle name-value variable syntax - # example: - # - name: [key] - # value: [value] - - ${{ if ne(variable.name, '') }}: - - name: ${{ variable.name }} - value: ${{ variable.value }} - - # handle variable groups - - ${{ if ne(variable.group, '') }}: - - group: ${{ variable.group }} - - # handle template variable syntax - # example: - # - template: path/to/template.yml - # parameters: - # [key]: [value] - - ${{ if ne(variable.template, '') }}: - - template: ${{ variable.template }} - ${{ if ne(variable.parameters, '') }}: - parameters: ${{ variable.parameters }} - - # handle key-value variable syntax. - # example: - # - [key]: [value] - - ${{ if and(eq(variable.name, ''), eq(variable.group, ''), eq(variable.template, '')) }}: - - ${{ each pair in variable }}: - - name: ${{ pair.key }} - value: ${{ pair.value }} - - # DotNet-HelixApi-Access provides 'HelixApiAccessToken' for internal builds - - ${{ if and(eq(parameters.enableTelemetry, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: DotNet-HelixApi-Access - - ${{ if ne(parameters.workspace, '') }}: - workspace: ${{ parameters.workspace }} - - steps: - - ${{ if ne(parameters.preSteps, '') }}: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - task: MicroBuildSigningPlugin@4 - displayName: Install MicroBuild plugin - inputs: - signType: $(_SignType) - zipSources: false - feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json - env: - TeamName: $(_TeamName) - MicroBuildOutputFolderOverride: '$(Agent.TempDirectory)' - continueOnError: ${{ parameters.continueOnError }} - condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - - - ${{ if and(eq(parameters.runAsPublic, 'false'), eq(variables['System.TeamProject'], 'internal')) }}: - - task: NuGetAuthenticate@1 - - - ${{ if and(ne(parameters.artifacts.download, 'false'), ne(parameters.artifacts.download, '')) }}: - - task: DownloadPipelineArtifact@2 - inputs: - buildType: current - artifactName: ${{ coalesce(parameters.artifacts.download.name, 'Artifacts_$(Agent.OS)_$(_BuildConfig)') }} - targetPath: ${{ coalesce(parameters.artifacts.download.path, 'artifacts') }} - itemPattern: ${{ coalesce(parameters.artifacts.download.pattern, '**') }} - - - ${{ each step in parameters.steps }}: - - ${{ step }} - - - ${{ if eq(parameters.enableRichCodeNavigation, true) }}: - - task: RichCodeNavIndexer@0 - displayName: RichCodeNav Upload - inputs: - languages: ${{ coalesce(parameters.richCodeNavigationLanguage, 'csharp') }} - environment: ${{ coalesce(parameters.richCodeNavigationEnvironment, 'internal') }} - richNavLogOutputDirectory: $(Build.SourcesDirectory)/artifacts/bin - uploadRichNavArtifacts: ${{ coalesce(parameters.richCodeNavigationUploadArtifacts, false) }} - continueOnError: true - - - template: /eng/common/templates-official/steps/component-governance.yml - parameters: - ${{ if eq(parameters.disableComponentGovernance, '') }}: - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/dotnet/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/microsoft/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: - disableComponentGovernance: false - ${{ else }}: - disableComponentGovernance: true - ${{ else }}: - disableComponentGovernance: ${{ parameters.disableComponentGovernance }} - componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: MicroBuildCleanup@1 - displayName: Execute Microbuild cleanup tasks - condition: and(always(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - env: - TeamName: $(_TeamName) - - - ${{ if ne(parameters.artifacts.publish, '') }}: - - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: - - task: CopyFiles@2 - displayName: Gather binaries for publish to artifacts - inputs: - SourceFolder: 'artifacts/bin' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/bin' - - task: CopyFiles@2 - displayName: Gather packages for publish to artifacts - inputs: - SourceFolder: 'artifacts/packages' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/packages' - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish pipeline artifacts - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} - continueOnError: true - condition: always() - - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: - - task: 1ES.PublishPipelineArtifact@1 - inputs: - targetPath: 'artifacts/log' - artifactName: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)_Attempt$(System.JobAttempt)') }} - displayName: 'Publish logs' - continueOnError: true - condition: always() - - - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} - continueOnError: true - condition: always() - - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'xunit')) }}: - - task: PublishTestResults@2 - displayName: Publish XUnit Test Results - inputs: - testResultsFormat: 'xUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'vstest')) }}: - - task: PublishTestResults@2 - displayName: Publish TRX Test Results - inputs: - testResultsFormat: 'VSTest' - testResultsFiles: '*.trx' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: - - template: /eng/common/templates-official/steps/generate-sbom.yml - parameters: - PackageVersion: ${{ parameters.packageVersion}} - BuildDropPath: ${{ parameters.buildDropPath }} - IgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableBuildRetry, 'true') }}: - - task: 1ES.PublishPipelineArtifact@1 - inputs: - targetPath: '$(Build.SourcesDirectory)\eng\common\BuildConfiguration' - artifactName: 'BuildConfiguration' - displayName: 'Publish build retry configuration' - continueOnError: true \ No newline at end of file +- template: /eng/common/core-templates/job/job.yml + parameters: + is1ESPipeline: true + + # publish artifacts + # for 1ES managed templates, use the templateContext.output to handle multiple outputs. + templateContext: + outputParentDirectory: $(Build.ArtifactStagingDirectory) + outputs: + - ${{ if ne(parameters.artifacts.publish, '') }}: + - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: + - output: buildArtifacts + displayName: Publish pipeline artifacts + PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' + ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} + condition: always() + continueOnError: true + - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: + - output: pipelineArtifact + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts/log' + artifactName: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)_Attempt$(System.JobAttempt)') }} + displayName: 'Publish logs' + continueOnError: true + condition: always() + + - ${{ if eq(parameters.enablePublishBuildArtifacts, true) }}: + - output: buildArtifacts + displayName: Publish Logs + PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' + publishLocation: Container + ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} + continueOnError: true + condition: always() + + - ${{ if eq(parameters.enableBuildRetry, 'true') }}: + - output: pipelineArtifact + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts/eng/common/BuildConfiguration' + artifactName: 'BuildConfiguration' + displayName: 'Publish build retry configuration' + continueOnError: true + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: + - output: pipelineArtifact + displayName: Publish SBOM manifest + continueOnError: true + targetPath: $(Build.ArtifactStagingDirectory)/sbom + artifactName: $(ARTIFACT_NAME) + + # add any outputs provided via root yaml + - ${{ if ne(parameters.templateContext.outputs, '') }}: + - ${{ each output in parameters.templateContext.outputs }}: + - ${{ output }} + + # add any remaining templateContext properties + ${{ each context in parameters.templateContext }}: + ${{ if and(ne(context.key, 'outputParentDirectory'), ne(context.key, 'outputs')) }}: + ${{ context.key }}: ${{ context.value }} + + ${{ each parameter in parameters }}: + ${{ if and(ne(parameter.key, 'templateContext'), ne(parameter.key, 'is1ESPipeline')) }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/onelocbuild.yml b/eng/common/templates-official/job/onelocbuild.yml index 52b4d05d3f8dd6..0f0c514b912dfc 100644 --- a/eng/common/templates-official/job/onelocbuild.yml +++ b/eng/common/templates-official/job/onelocbuild.yml @@ -1,112 +1,7 @@ -parameters: - # Optional: dependencies of the job - dependsOn: '' - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: '' - - CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex - GithubPat: $(BotAccount-dotnet-bot-repo-PAT) - - SourcesDirectory: $(Build.SourcesDirectory) - CreatePr: true - AutoCompletePr: false - ReusePr: true - UseLfLineEndings: true - UseCheckedInLocProjectJson: false - SkipLocProjectJsonGeneration: false - LanguageSet: VS_Main_Languages - LclSource: lclFilesInRepo - LclPackageId: '' - RepoType: gitHub - GitHubOrg: dotnet - MirrorRepo: '' - MirrorBranch: main - condition: '' - JobNameSuffix: '' - jobs: -- job: OneLocBuild${{ parameters.JobNameSuffix }} - - dependsOn: ${{ parameters.dependsOn }} - - displayName: OneLocBuild${{ parameters.JobNameSuffix }} - - variables: - - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat - - name: _GenerateLocProjectArguments - value: -SourcesDirectory ${{ parameters.SourcesDirectory }} - -LanguageSet "${{ parameters.LanguageSet }}" - -CreateNeutralXlfs - - ${{ if eq(parameters.UseCheckedInLocProjectJson, 'true') }}: - - name: _GenerateLocProjectArguments - value: ${{ variables._GenerateLocProjectArguments }} -UseCheckedInLocProjectJson - - template: /eng/common/templates-official/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 - os: windows - - steps: - - ${{ if ne(parameters.SkipLocProjectJsonGeneration, 'true') }}: - - task: Powershell@2 - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/generate-locproject.ps1 - arguments: $(_GenerateLocProjectArguments) - displayName: Generate LocProject.json - condition: ${{ parameters.condition }} - - - task: OneLocBuild@2 - displayName: OneLocBuild - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - locProj: eng/Localize/LocProject.json - outDir: $(Build.ArtifactStagingDirectory) - lclSource: ${{ parameters.LclSource }} - lclPackageId: ${{ parameters.LclPackageId }} - isCreatePrSelected: ${{ parameters.CreatePr }} - isAutoCompletePrSelected: ${{ parameters.AutoCompletePr }} - ${{ if eq(parameters.CreatePr, true) }}: - isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - isShouldReusePrSelected: ${{ parameters.ReusePr }} - packageSourceAuth: patAuth - patVariable: ${{ parameters.CeapexPat }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - repoType: ${{ parameters.RepoType }} - gitHubPatVariable: "${{ parameters.GithubPat }}" - ${{ if ne(parameters.MirrorRepo, '') }}: - isMirrorRepoSelected: true - gitHubOrganization: ${{ parameters.GitHubOrg }} - mirrorRepo: ${{ parameters.MirrorRepo }} - mirrorBranch: ${{ parameters.MirrorBranch }} - condition: ${{ parameters.condition }} - - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish Localization Files - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/loc' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} +- template: /eng/common/core-templates/job/onelocbuild.yml + parameters: + is1ESPipeline: true - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish LocProject.json - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/Localize/' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} \ No newline at end of file + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/publish-build-assets.yml b/eng/common/templates-official/job/publish-build-assets.yml index 38340d3e38614a..d667a70e8de743 100644 --- a/eng/common/templates-official/job/publish-build-assets.yml +++ b/eng/common/templates-official/job/publish-build-assets.yml @@ -1,159 +1,7 @@ -parameters: - configuration: 'Debug' - - # Optional: condition for the job to run - condition: '' - - # Optional: 'true' if future jobs should run even if this job fails - continueOnError: false - - # Optional: dependencies of the job - dependsOn: '' - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: {} - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishUsingPipelines: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishAssetsImmediately: false - - artifactsPublishingAdditionalParameters: '' - - signingValidationAdditionalParameters: '' - jobs: -- job: Asset_Registry_Publish - - dependsOn: ${{ parameters.dependsOn }} - timeoutInMinutes: 150 - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - displayName: Publish Assets - ${{ else }}: - displayName: Publish to Build Asset Registry - - variables: - - template: /eng/common/templates-official/variables/pool-providers.yml - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: Publish-Build-Assets - - group: AzureDevOps-Artifact-Feeds-Pats - - name: runCodesignValidationInjection - value: false - # unconditional - needed for logs publishing (redactor tool version) - - template: /eng/common/templates-official/post-build/common-variables.yml - - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: NetCore1ESPool-Publishing-Internal - image: windows.vs2019.amd64 - os: windows - steps: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - checkout: self - fetchDepth: 3 - clean: true - - - task: DownloadBuildArtifacts@0 - displayName: Download artifact - inputs: - artifactName: AssetManifests - downloadPath: '$(Build.StagingDirectory)/Download' - checkDownloadedFiles: true - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: NuGetAuthenticate@1 - - - task: PowerShell@2 - displayName: Publish Build Assets - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishBuildAssets -restore -msbuildEngine dotnet - /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' - /p:BuildAssetRegistryToken=$(MaestroAccessToken) - /p:MaestroApiEndpoint=https://maestro.dot.net - /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} - /p:OfficialBuildId=$(Build.BuildNumber) - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: powershell@2 - displayName: Create ReleaseConfigs Artifact - inputs: - targetType: inline - script: | - New-Item -Path "$(Build.StagingDirectory)/ReleaseConfigs" -ItemType Directory -Force - $filePath = "$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt" - Add-Content -Path $filePath -Value $(BARBuildId) - Add-Content -Path $filePath -Value "$(DefaultChannels)" - Add-Content -Path $filePath -Value $(IsStableBuild) - - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish ReleaseConfigs Artifact - inputs: - PathtoPublish: '$(Build.StagingDirectory)/ReleaseConfigs' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - task: powershell@2 - displayName: Check if SymbolPublishingExclusionsFile.txt exists - inputs: - targetType: inline - script: | - $symbolExclusionfile = "$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt" - if(Test-Path -Path $symbolExclusionfile) - { - Write-Host "SymbolExclusionFile exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]true" - } - else{ - Write-Host "Symbols Exclusion file does not exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]false" - } - - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish SymbolPublishingExclusionsFile Artifact - condition: eq(variables['SymbolExclusionFile'], 'true') - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - - template: /eng/common/templates-official/post-build/setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: PowerShell@2 - displayName: Publish Using Darc - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion 3 - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' - -MaestroToken '$(MaestroApiAccessToken)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' +- template: /eng/common/core-templates/job/publish-build-assets.yml + parameters: + is1ESPipeline: true - - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: - - template: /eng/common/templates-official/steps/publish-logs.yml - parameters: - JobLabel: 'Publish_Artifacts_Logs' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/source-build.yml b/eng/common/templates-official/job/source-build.yml index 2180e97a284f84..1a480034b678eb 100644 --- a/eng/common/templates-official/job/source-build.yml +++ b/eng/common/templates-official/job/source-build.yml @@ -1,67 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. The template produces a server job with a - # default ID 'Source_Build_Complete' to put in a dependency list if necessary. - - # Specifies the prefix for source-build jobs added to pipeline. Use this if disambiguation needed. - jobNamePrefix: 'Source_Build' - - # Defines the platform on which to run the job. By default, a linux-x64 machine, suitable for - # managed-only repositories. This is an object with these properties: - # - # name: '' - # The name of the job. This is included in the job ID. - # targetRID: '' - # The name of the target RID to use, instead of the one auto-detected by Arcade. - # nonPortable: false - # Enables non-portable mode. This means a more specific RID (e.g. fedora.32-x64 rather than - # linux-x64), and compiling against distro-provided packages rather than portable ones. - # skipPublishValidation: false - # Disables publishing validation. By default, a check is performed to ensure no packages are - # published by source-build. - # container: '' - # A container to use. Runs in docker. - # pool: {} - # A pool to use. Runs directly on an agent. - # buildScript: '' - # Specifies the build script to invoke to perform the build in the repo. The default - # './build.sh' should work for typical Arcade repositories, but this is customizable for - # difficult situations. - # jobProperties: {} - # A list of job properties to inject at the top level, for potential extensibility beyond - # container and pool. - platform: {} - jobs: -- job: ${{ parameters.jobNamePrefix }}_${{ parameters.platform.name }} - displayName: Source-Build (${{ parameters.platform.name }}) - - ${{ each property in parameters.platform.jobProperties }}: - ${{ property.key }}: ${{ property.value }} - - ${{ if ne(parameters.platform.container, '') }}: - container: ${{ parameters.platform.container }} - - ${{ if eq(parameters.platform.pool, '') }}: - # The default VM host AzDO pool. This should be capable of running Docker containers: almost all - # source-build builds run in Docker, including the default managed platform. - # /eng/common/templates-official/variables/pool-providers.yml can't be used here (some customers declare variables already), so duplicate its logic - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] - demands: ImageOverride -equals build.ubuntu.2004.amd64 - - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] - image: 1es-mariner-2 - os: linux - - ${{ if ne(parameters.platform.pool, '') }}: - pool: ${{ parameters.platform.pool }} - - workspace: - clean: all +- template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: true - steps: - - template: /eng/common/templates-official/steps/source-build.yml - parameters: - platform: ${{ parameters.platform }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/source-index-stage1.yml b/eng/common/templates-official/job/source-index-stage1.yml index 53a9ef51fd82d2..6d5ead316f92b5 100644 --- a/eng/common/templates-official/job/source-index-stage1.yml +++ b/eng/common/templates-official/job/source-index-stage1.yml @@ -1,67 +1,7 @@ -parameters: - runAsPublic: false - sourceIndexPackageVersion: 1.0.1-20240129.2 - sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json - sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" - preSteps: [] - binlogPath: artifacts/log/Debug/Build.binlog - condition: '' - dependsOn: '' - pool: '' - jobs: -- job: SourceIndexStage1 - dependsOn: ${{ parameters.dependsOn }} - condition: ${{ parameters.condition }} - variables: - - name: SourceIndexPackageVersion - value: ${{ parameters.sourceIndexPackageVersion }} - - name: SourceIndexPackageSource - value: ${{ parameters.sourceIndexPackageSource }} - - name: BinlogPath - value: ${{ parameters.binlogPath }} - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: source-dot-net stage1 variables - - template: /eng/common/templates-official/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $(DncEngPublicBuildPool) - image: windows.vs2022.amd64.open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $(DncEngInternalBuildPool) - image: windows.vs2022.amd64 - - steps: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - task: UseDotNet@2 - displayName: Use .NET 8 SDK - inputs: - packageType: sdk - version: 8.0.x - installationPath: $(Agent.TempDirectory)/dotnet - workingDirectory: $(Agent.TempDirectory) - - - script: | - $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - displayName: Download Tools - # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. - workingDirectory: $(Agent.TempDirectory) - - - script: ${{ parameters.sourceIndexBuildCommand }} - displayName: Build Repository - - - script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i $(BinlogPath) -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output - displayName: Process Binlog into indexable sln +- template: /eng/common/core-templates/job/source-index-stage1.yml + parameters: + is1ESPipeline: true - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - script: $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) - displayName: Upload stage1 artifacts to source index - env: - BLOB_CONTAINER_URL: $(source-dot-net-stage1-blob-container-url) + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/jobs/codeql-build.yml b/eng/common/templates-official/jobs/codeql-build.yml index b68d3c2f31990f..a726322ecfe016 100644 --- a/eng/common/templates-official/jobs/codeql-build.yml +++ b/eng/common/templates-official/jobs/codeql-build.yml @@ -1,31 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - jobs: -- template: /eng/common/templates-official/jobs/jobs.yml +- template: /eng/common/core-templates/jobs/codeql-build.yml parameters: - enableMicrobuild: false - enablePublishBuildArtifacts: false - enablePublishTestResults: false - enablePublishBuildAssets: false - enablePublishUsingPipelines: false - enableTelemetry: true + is1ESPipeline: true - variables: - - group: Publish-Build-Assets - # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in - # sync with the packages.config file. - - name: DefaultGuardianVersion - value: 0.109.0 - - name: GuardianPackagesConfigFile - value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config - - name: GuardianVersion - value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} - - jobs: ${{ parameters.jobs }} - + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/jobs/jobs.yml b/eng/common/templates-official/jobs/jobs.yml index 857a0f8ba43e84..007deddaea0f53 100644 --- a/eng/common/templates-official/jobs/jobs.yml +++ b/eng/common/templates-official/jobs/jobs.yml @@ -1,97 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: Enable publishing using release pipelines - enablePublishUsingPipelines: false - - # Optional: Enable running the source-build jobs to build repo from source - enableSourceBuild: false - - # Optional: Parameters for source-build template. - # See /eng/common/templates-official/jobs/source-build.yml for options - sourceBuildParameters: [] - - graphFileGeneration: - # Optional: Enable generating the graph files at the end of the build - enabled: false - # Optional: Include toolset dependencies in the generated graph files - includeToolset: false - - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - - # Optional: Override automatically derived dependsOn value for "publish build assets" job - publishBuildAssetsDependsOn: '' - - # Optional: Publish the assets as soon as the publish to BAR stage is complete, rather doing so in a separate stage. - publishAssetsImmediately: false - - # Optional: If using publishAssetsImmediately and additional parameters are needed, can be used to send along additional parameters (normally sent to post-build.yml) - artifactsPublishingAdditionalParameters: '' - signingValidationAdditionalParameters: '' - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - enableSourceIndex: false - sourceIndexParams: {} - -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - jobs: -- ${{ each job in parameters.jobs }}: - - template: ../job/job.yml - parameters: - # pass along parameters - ${{ each parameter in parameters }}: - ${{ if ne(parameter.key, 'jobs') }}: - ${{ parameter.key }}: ${{ parameter.value }} - - # pass along job properties - ${{ each property in job }}: - ${{ if ne(property.key, 'job') }}: - ${{ property.key }}: ${{ property.value }} - - name: ${{ job.job }} - -- ${{ if eq(parameters.enableSourceBuild, true) }}: - - template: /eng/common/templates-official/jobs/source-build.yml - parameters: - allCompletedJobId: Source_Build_Complete - ${{ each parameter in parameters.sourceBuildParameters }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if eq(parameters.enableSourceIndex, 'true') }}: - - template: ../job/source-index-stage1.yml - parameters: - runAsPublic: ${{ parameters.runAsPublic }} - ${{ each parameter in parameters.sourceIndexParams }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: - - template: ../job/publish-build-assets.yml - parameters: - continueOnError: ${{ parameters.continueOnError }} - dependsOn: - - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.publishBuildAssetsDependsOn }}: - - ${{ job.job }} - - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.jobs }}: - - ${{ job.job }} - - ${{ if eq(parameters.enableSourceBuild, true) }}: - - Source_Build_Complete +- template: /eng/common/core-templates/jobs/jobs.yml + parameters: + is1ESPipeline: true - runAsPublic: ${{ parameters.runAsPublic }} - publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} - publishAssetsImmediately: ${{ parameters.publishAssetsImmediately }} - enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - signingValidationAdditionalParameters: ${{ parameters.signingValidationAdditionalParameters }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/jobs/source-build.yml b/eng/common/templates-official/jobs/source-build.yml index 2076f4e25b43c6..483e7b611f346b 100644 --- a/eng/common/templates-official/jobs/source-build.yml +++ b/eng/common/templates-official/jobs/source-build.yml @@ -1,46 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. A job is created for each platform, as - # well as an optional server job that completes when all platform jobs complete. - - # The name of the "join" job for all source-build platforms. If set to empty string, the job is - # not included. Existing repo pipelines can use this job depend on all source-build jobs - # completing without maintaining a separate list of every single job ID: just depend on this one - # server job. By default, not included. Recommended name if used: 'Source_Build_Complete'. - allCompletedJobId: '' - - # See /eng/common/templates-official/job/source-build.yml - jobNamePrefix: 'Source_Build' - - # This is the default platform provided by Arcade, intended for use by a managed-only repo. - defaultManagedPlatform: - name: 'Managed' - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream9' - - # Defines the platforms on which to run build jobs. One job is created for each platform, and the - # object in this array is sent to the job template as 'platform'. If no platforms are specified, - # one job runs on 'defaultManagedPlatform'. - platforms: [] - jobs: +- template: /eng/common/core-templates/jobs/source-build.yml + parameters: + is1ESPipeline: true -- ${{ if ne(parameters.allCompletedJobId, '') }}: - - job: ${{ parameters.allCompletedJobId }} - displayName: Source-Build Complete - pool: server - dependsOn: - - ${{ each platform in parameters.platforms }}: - - ${{ parameters.jobNamePrefix }}_${{ platform.name }} - - ${{ if eq(length(parameters.platforms), 0) }}: - - ${{ parameters.jobNamePrefix }}_${{ parameters.defaultManagedPlatform.name }} - -- ${{ each platform in parameters.platforms }}: - - template: /eng/common/templates-official/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ platform }} - -- ${{ if eq(length(parameters.platforms), 0) }}: - - template: /eng/common/templates-official/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ parameters.defaultManagedPlatform }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/post-build/common-variables.yml b/eng/common/templates-official/post-build/common-variables.yml index b9ede10bf099ae..c32fc49233f8fd 100644 --- a/eng/common/templates-official/post-build/common-variables.yml +++ b/eng/common/templates-official/post-build/common-variables.yml @@ -1,24 +1,8 @@ variables: - - group: Publish-Build-Assets +- template: /eng/common/core-templates/post-build/common-variables.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: true - # Whether the build is internal or not - - name: IsInternalBuild - value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} - - # Default Maestro++ API Endpoint and API Version - - name: MaestroApiEndPoint - value: "https://maestro.dot.net" - - name: MaestroApiAccessToken - value: $(MaestroAccessToken) - - name: MaestroApiVersion - value: "2020-02-20" - - - name: SourceLinkCLIVersion - value: 3.0.0 - - name: SymbolToolVersion - value: 1.0.1 - - name: BinlogToolVersion - value: 1.0.11 - - - name: runCodesignValidationInjection - value: false + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/post-build/post-build.yml b/eng/common/templates-official/post-build/post-build.yml index da1f40958b450d..2364c0fd4a527e 100644 --- a/eng/common/templates-official/post-build/post-build.yml +++ b/eng/common/templates-official/post-build/post-build.yml @@ -1,285 +1,8 @@ -parameters: - # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. - # Publishing V1 is no longer supported - # Publishing V2 is no longer supported - # Publishing V3 is the default - - name: publishingInfraVersion - displayName: Which version of publishing should be used to promote the build definition? - type: number - default: 3 - values: - - 3 - - - name: BARBuildId - displayName: BAR Build Id - type: number - default: 0 - - - name: PromoteToChannelIds - displayName: Channel to promote BARBuildId to - type: string - default: '' - - - name: enableSourceLinkValidation - displayName: Enable SourceLink validation - type: boolean - default: false - - - name: enableSigningValidation - displayName: Enable signing validation - type: boolean - default: true - - - name: enableSymbolValidation - displayName: Enable symbol validation - type: boolean - default: false - - - name: enableNugetValidation - displayName: Enable NuGet validation - type: boolean - default: true - - - name: publishInstallersAndChecksums - displayName: Publish installers and checksums - type: boolean - default: true - - - name: SDLValidationParameters - type: object - default: - enable: false - publishGdn: false - continueOnError: false - params: '' - artifactNames: '' - downloadArtifacts: true - - # These parameters let the user customize the call to sdk-task.ps1 for publishing - # symbols & general artifacts as well as for signing validation - - name: symbolPublishingAdditionalParameters - displayName: Symbol publishing additional parameters - type: string - default: '' - - - name: artifactsPublishingAdditionalParameters - displayName: Artifact publishing additional parameters - type: string - default: '' - - - name: signingValidationAdditionalParameters - displayName: Signing validation additional parameters - type: string - default: '' - - # Which stages should finish execution before post-build stages start - - name: validateDependsOn - type: object - default: - - build - - - name: publishDependsOn - type: object - default: - - Validate - - # Optional: Call asset publishing rather than running in a separate stage - - name: publishAssetsImmediately - type: boolean - default: false - stages: -- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - - stage: Validate - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Validate Build Assets - variables: - - template: common-variables.yml - - template: /eng/common/templates-official/variables/pool-providers.yml - jobs: - - job: - displayName: NuGet Validation - condition: and(succeededOrFailed(), eq( ${{ parameters.enableNugetValidation }}, 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 - os: windows - - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1 - arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ - -ToolDestinationPath $(Agent.BuildDirectory)/Extract/ - - - job: - displayName: Signing Validation - condition: and( eq( ${{ parameters.enableSigningValidation }}, 'true'), ne( variables['PostBuildSign'], 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 - os: windows - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - itemPattern: | - ** - !**/Microsoft.SourceBuild.Intermediate.*.nupkg - - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@1 - displayName: 'Authenticate to AzDO Feeds' - - # Signing validation will optionally work with the buildmanifest file which is downloaded from - # Azure DevOps above. - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task SigningValidation -restore -msbuildEngine vs - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' - /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' - ${{ parameters.signingValidationAdditionalParameters }} - - - template: ../steps/publish-logs.yml - parameters: - StageLabel: 'Validation' - JobLabel: 'Signing' - BinlogToolVersion: $(BinlogToolVersion) - - - job: - displayName: SourceLink Validation - condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 - os: windows - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: BlobArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1 - arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/ - -ExtractPath $(Agent.BuildDirectory)/Extract/ - -GHRepoName $(Build.Repository.Name) - -GHCommit $(Build.SourceVersion) - -SourcelinkCliVersion $(SourceLinkCLIVersion) - continueOnError: true - -- ${{ if ne(parameters.publishAssetsImmediately, 'true') }}: - - stage: publish_using_darc - ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - dependsOn: ${{ parameters.publishDependsOn }} - ${{ else }}: - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Publish using Darc - variables: - - template: common-variables.yml - - template: /eng/common/templates-official/variables/pool-providers.yml - jobs: - - job: - displayName: Publish Using Darc - timeoutInMinutes: 120 - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: NetCore1ESPool-Publishing-Internal - image: windows.vs2019.amd64 - os: windows - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: NuGetAuthenticate@1 +- template: /eng/common/core-templates/post-build/post-build.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: true - - task: PowerShell@2 - displayName: Publish Using Darc - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' - -MaestroToken '$(MaestroApiAccessToken)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/post-build/setup-maestro-vars.yml b/eng/common/templates-official/post-build/setup-maestro-vars.yml index 0c87f149a4ad77..024397d8786452 100644 --- a/eng/common/templates-official/post-build/setup-maestro-vars.yml +++ b/eng/common/templates-official/post-build/setup-maestro-vars.yml @@ -1,70 +1,8 @@ -parameters: - BARBuildId: '' - PromoteToChannelIds: '' - steps: - - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Release Configs - inputs: - buildType: current - artifactName: ReleaseConfigs - checkDownloadedFiles: true - - - task: PowerShell@2 - name: setReleaseVars - displayName: Set Release Configs Vars - inputs: - targetType: inline - pwsh: true - script: | - try { - if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { - $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt - - $BarId = $Content | Select -Index 0 - $Channels = $Content | Select -Index 1 - $IsStableBuild = $Content | Select -Index 2 - - $AzureDevOpsProject = $Env:System_TeamProject - $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId - $AzureDevOpsBuildId = $Env:Build_BuildId - } - else { - $buildApiEndpoint = "${Env:MaestroApiEndPoint}/api/builds/${Env:BARBuildId}?api-version=${Env:MaestroApiVersion}" - - $apiHeaders = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' - $apiHeaders.Add('Accept', 'application/json') - $apiHeaders.Add('Authorization',"Bearer ${Env:MAESTRO_API_TOKEN}") - - $buildInfo = try { Invoke-WebRequest -Method Get -Uri $buildApiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } - - $BarId = $Env:BARBuildId - $Channels = $Env:PromoteToMaestroChannels -split "," - $Channels = $Channels -join "][" - $Channels = "[$Channels]" - - $IsStableBuild = $buildInfo.stable - $AzureDevOpsProject = $buildInfo.azureDevOpsProject - $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId - $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId - } - - Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" - Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" - Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" +- template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: true - Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" - Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" - Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" - } - catch { - Write-Host $_ - Write-Host $_.Exception - Write-Host $_.ScriptStackTrace - exit 1 - } - env: - MAESTRO_API_TOKEN: $(MaestroApiAccessToken) - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/steps/add-build-to-channel.yml b/eng/common/templates-official/steps/add-build-to-channel.yml index f67a210d62f3e5..543dea8c6969a6 100644 --- a/eng/common/templates-official/steps/add-build-to-channel.yml +++ b/eng/common/templates-official/steps/add-build-to-channel.yml @@ -1,13 +1,7 @@ -parameters: - ChannelId: 0 - steps: -- task: PowerShell@2 - displayName: Add Build to Channel - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/add-build-to-channel.ps1 - arguments: -BuildId $(BARBuildId) - -ChannelId ${{ parameters.ChannelId }} - -MaestroApiAccessToken $(MaestroApiAccessToken) - -MaestroApiEndPoint $(MaestroApiEndPoint) - -MaestroApiVersion $(MaestroApiVersion) +- template: /eng/common/core-templates/steps/add-build-to-channel.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/component-governance.yml b/eng/common/templates-official/steps/component-governance.yml index 0ecec47b0c9177..30bb3985ca2bf4 100644 --- a/eng/common/templates-official/steps/component-governance.yml +++ b/eng/common/templates-official/steps/component-governance.yml @@ -1,13 +1,7 @@ -parameters: - disableComponentGovernance: false - componentGovernanceIgnoreDirectories: '' - steps: -- ${{ if eq(parameters.disableComponentGovernance, 'true') }}: - - script: "echo ##vso[task.setvariable variable=skipComponentGovernanceDetection]true" - displayName: Set skipComponentGovernanceDetection variable -- ${{ if ne(parameters.disableComponentGovernance, 'true') }}: - - task: ComponentGovernanceComponentDetection@0 - continueOnError: true - inputs: - ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} \ No newline at end of file +- template: /eng/common/core-templates/steps/component-governance.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/generate-sbom.yml b/eng/common/templates-official/steps/generate-sbom.yml index 488b560e8ba4eb..9a89a4706d94e4 100644 --- a/eng/common/templates-official/steps/generate-sbom.yml +++ b/eng/common/templates-official/steps/generate-sbom.yml @@ -1,48 +1,7 @@ -# BuildDropPath - The root folder of the drop directory for which the manifest file will be generated. -# PackageName - The name of the package this SBOM represents. -# PackageVersion - The version of the package this SBOM represents. -# ManifestDirPath - The path of the directory where the generated manifest files will be placed -# IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. - -parameters: - PackageVersion: 7.0.0 - BuildDropPath: '$(Build.SourcesDirectory)/artifacts' - PackageName: '.NET' - ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom - IgnoreDirectories: '' - sbomContinueOnError: true - steps: -- task: PowerShell@2 - displayName: Prep for SBOM generation in (Non-linux) - condition: or(eq(variables['Agent.Os'], 'Windows_NT'), eq(variables['Agent.Os'], 'Darwin')) - inputs: - filePath: ./eng/common/generate-sbom-prep.ps1 - arguments: ${{parameters.manifestDirPath}} - -# Chmodding is a workaround for https://github.com/dotnet/arcade/issues/8461 -- script: | - chmod +x ./eng/common/generate-sbom-prep.sh - ./eng/common/generate-sbom-prep.sh ${{parameters.manifestDirPath}} - displayName: Prep for SBOM generation in (Linux) - condition: eq(variables['Agent.Os'], 'Linux') - continueOnError: ${{ parameters.sbomContinueOnError }} - -- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 - displayName: 'Generate SBOM manifest' - continueOnError: ${{ parameters.sbomContinueOnError }} - inputs: - PackageName: ${{ parameters.packageName }} - BuildDropPath: ${{ parameters.buildDropPath }} - PackageVersion: ${{ parameters.packageVersion }} - ManifestDirPath: ${{ parameters.manifestDirPath }} - ${{ if ne(parameters.IgnoreDirectories, '') }}: - AdditionalComponentDetectorArgs: '--IgnoreDirectories ${{ parameters.IgnoreDirectories }}' - -- task: 1ES.PublishPipelineArtifact@1 - displayName: Publish SBOM manifest - continueOnError: ${{parameters.sbomContinueOnError}} - inputs: - targetPath: '${{parameters.manifestDirPath}}' - artifactName: $(ARTIFACT_NAME) +- template: /eng/common/core-templates/steps/generate-sbom.yml + parameters: + is1ESPipeline: true + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/publish-build-artifacts.yml b/eng/common/templates-official/steps/publish-build-artifacts.yml new file mode 100644 index 00000000000000..100a3fc98493cd --- /dev/null +++ b/eng/common/templates-official/steps/publish-build-artifacts.yml @@ -0,0 +1,41 @@ +parameters: +- name: displayName + type: string + default: 'Publish to Build Artifact' + +- name: condition + type: string + default: succeeded() + +- name: artifactName + type: string + +- name: pathToPublish + type: string + +- name: continueOnError + type: boolean + default: false + +- name: publishLocation + type: string + default: 'Container' + +- name: is1ESPipeline + type: boolean + default: true + +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates-official cannot be referenced from a non-1ES managed template': error +- task: 1ES.PublishBuildArtifacts@1 + displayName: ${{ parameters.displayName }} + condition: ${{ parameters.condition }} + ${{ if parameters.continueOnError }}: + continueOnError: ${{ parameters.continueOnError }} + inputs: + PublishLocation: ${{ parameters.publishLocation }} + PathtoPublish: ${{ parameters.pathToPublish }} + ${{ if parameters.artifactName }}: + ArtifactName: ${{ parameters.artifactName }} + diff --git a/eng/common/templates-official/steps/publish-logs.yml b/eng/common/templates-official/steps/publish-logs.yml index 84b2f559c56e40..579fd531e94c38 100644 --- a/eng/common/templates-official/steps/publish-logs.yml +++ b/eng/common/templates-official/steps/publish-logs.yml @@ -1,49 +1,7 @@ -parameters: - StageLabel: '' - JobLabel: '' - CustomSensitiveDataList: '' - # A default - in case value from eng/common/templates-official/post-build/common-variables.yml is not passed - BinlogToolVersion: '1.0.11' - steps: -- task: Powershell@2 - displayName: Prepare Binlogs to Upload - inputs: - targetType: inline - script: | - New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - continueOnError: true - condition: always() - -- task: PowerShell@2 - displayName: Redact Logs - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/redact-logs.ps1 - # For now this needs to have explicit list of all sensitive data. Taken from eng/publishing/v3/publish.yml - # Sensitive data can as well be added to $(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' - # If the file exists - sensitive data for redaction will be sourced from it - # (single entry per line, lines starting with '# ' are considered comments and skipped) - arguments: -InputPath '$(Build.SourcesDirectory)/PostBuildLogs' - -BinlogToolVersion ${{parameters.BinlogToolVersion}} - -TokensFilePath '$(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' - '$(publishing-dnceng-devdiv-code-r-build-re)' - '$(MaestroAccessToken)' - '$(dn-bot-all-orgs-artifact-feeds-rw)' - '$(akams-client-id)' - '$(akams-client-secret)' - '$(microsoft-symbol-server-pat)' - '$(symweb-symbol-server-pat)' - '$(dn-bot-all-orgs-build-rw-code-rw)' - ${{parameters.CustomSensitiveDataList}} - continueOnError: true - condition: always() - -- task: 1ES.PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/PostBuildLogs' - PublishLocation: Container - ArtifactName: PostBuildLogs - continueOnError: true - condition: always() +- template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/publish-pipeline-artifacts.yml b/eng/common/templates-official/steps/publish-pipeline-artifacts.yml new file mode 100644 index 00000000000000..15d74a9d91616d --- /dev/null +++ b/eng/common/templates-official/steps/publish-pipeline-artifacts.yml @@ -0,0 +1,26 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: true + +- name: args + type: object + default: {} + +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates-official cannot be referenced from a non-1ES managed template': error +- task: 1ES.PublishPipelineArtifact@1 + displayName: ${{ coalesce(parameters.args.displayName, 'Publish to Build Artifact') }} + ${{ if parameters.args.condition }}: + condition: ${{ parameters.args.condition }} + ${{ else }}: + condition: succeeded() + ${{ if parameters.args.continueOnError }}: + continueOnError: ${{ parameters.args.continueOnError }} + inputs: + targetPath: ${{ parameters.args.targetPath }} + ${{ if parameters.args.artifactName }}: + artifactName: ${{ parameters.args.artifactName }} + ${{ if parameters.args.properties }}: + properties: ${{ properties.args.properties }} \ No newline at end of file diff --git a/eng/common/templates-official/steps/retain-build.yml b/eng/common/templates-official/steps/retain-build.yml index 83d97a26a01ff9..5594551508a3cf 100644 --- a/eng/common/templates-official/steps/retain-build.yml +++ b/eng/common/templates-official/steps/retain-build.yml @@ -1,28 +1,7 @@ -parameters: - # Optional azure devops PAT with build execute permissions for the build's organization, - # only needed if the build that should be retained ran on a different organization than - # the pipeline where this template is executing from - Token: '' - # Optional BuildId to retain, defaults to the current running build - BuildId: '' - # Azure devops Organization URI for the build in the https://dev.azure.com/ format. - # Defaults to the organization the current pipeline is running on - AzdoOrgUri: '$(System.CollectionUri)' - # Azure devops project for the build. Defaults to the project the current pipeline is running on - AzdoProject: '$(System.TeamProject)' - steps: - - task: powershell@2 - inputs: - targetType: 'filePath' - filePath: eng/common/retain-build.ps1 - pwsh: true - arguments: > - -AzdoOrgUri: ${{parameters.AzdoOrgUri}} - -AzdoProject ${{parameters.AzdoProject}} - -Token ${{coalesce(parameters.Token, '$env:SYSTEM_ACCESSTOKEN') }} - -BuildId ${{coalesce(parameters.BuildId, '$env:BUILD_ID')}} - displayName: Enable permanent build retention - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - BUILD_ID: $(Build.BuildId) \ No newline at end of file +- template: /eng/common/core-templates/steps/retain-build.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/send-to-helix.yml b/eng/common/templates-official/steps/send-to-helix.yml index 68fa739c4ab215..6500f21bf845ce 100644 --- a/eng/common/templates-official/steps/send-to-helix.yml +++ b/eng/common/templates-official/steps/send-to-helix.yml @@ -1,93 +1,7 @@ -# Please remember to update the documentation if you make changes to these parameters! -parameters: - HelixSource: 'pr/default' # required -- sources must start with pr/, official/, prodcon/, or agent/ - HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/' - HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number - HelixTargetQueues: '' # required -- semicolon-delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues - HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group - HelixProjectPath: 'eng/common/helixpublish.proj' # optional -- path to the project file to build relative to BUILD_SOURCESDIRECTORY - HelixProjectArguments: '' # optional -- arguments passed to the build command - HelixConfiguration: '' # optional -- additional property attached to a job - HelixPreCommands: '' # optional -- commands to run before Helix work item execution - HelixPostCommands: '' # optional -- commands to run after Helix work item execution - WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects - WorkItemCommand: '' # optional -- a command to execute on the payload; requires WorkItemDirectory; incompatible with XUnitProjects - WorkItemTimeout: '' # optional -- a timeout in TimeSpan.Parse-ready value (e.g. 00:02:00) for the work item command; requires WorkItemDirectory; incompatible with XUnitProjects - CorrelationPayloadDirectory: '' # optional -- a directory to zip up and send to Helix as a correlation payload - XUnitProjects: '' # optional -- semicolon-delimited list of XUnitProjects to parse and send to Helix; requires XUnitRuntimeTargetFramework, XUnitPublishTargetFramework, XUnitRunnerVersion, and IncludeDotNetCli=true - XUnitWorkItemTimeout: '' # optional -- the workitem timeout in seconds for all workitems created from the xUnit projects specified by XUnitProjects - XUnitPublishTargetFramework: '' # optional -- framework to use to publish your xUnit projects - XUnitRuntimeTargetFramework: '' # optional -- framework to use for the xUnit console runner - XUnitRunnerVersion: '' # optional -- version of the xUnit nuget package you wish to use on Helix; required for XUnitProjects - IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion - DotNetCliPackageType: '' # optional -- either 'sdk', 'runtime' or 'aspnetcore-runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." - IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set - HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting https://helix.int-dot.net ) - Creator: '' # optional -- if the build is external, use this to specify who is sending the job - DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO - condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() - continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false - steps: - - powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 $env:BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"' - displayName: ${{ parameters.DisplayNamePrefix }} (Windows) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog - displayName: ${{ parameters.DisplayNamePrefix }} (Unix) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} +- template: /eng/common/core-templates/steps/send-to-helix.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/source-build.yml b/eng/common/templates-official/steps/source-build.yml index 53ed57b6d48abc..8f92c49e7b06fc 100644 --- a/eng/common/templates-official/steps/source-build.yml +++ b/eng/common/templates-official/steps/source-build.yml @@ -1,131 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. - - # This is a 'steps' template, and is intended for advanced scenarios where the existing build - # infra has a careful build methodology that must be followed. For example, a repo - # (dotnet/runtime) might choose to clone the GitHub repo only once and store it as a pipeline - # artifact for all subsequent jobs to use, to reduce dependence on a strong network connection to - # GitHub. Using this steps template leaves room for that infra to be included. - - # Defines the platform on which to run the steps. See 'eng/common/templates-official/job/source-build.yml' - # for details. The entire object is described in the 'job' template for simplicity, even though - # the usage of the properties on this object is split between the 'job' and 'steps' templates. - platform: {} - steps: -# Build. Keep it self-contained for simple reusability. (No source-build-specific job variables.) -- script: | - set -x - df -h - - # If building on the internal project, the artifact feeds variable may be available (usually only if needed) - # In that case, call the feed setup script to add internal feeds corresponding to public ones. - # In addition, add an msbuild argument to copy the WIP from the repo to the target build location. - # This is because SetupNuGetSources.sh will alter the current NuGet.config file, and we need to preserve those - # changes. - internalRestoreArgs= - if [ '$(dn-bot-dnceng-artifact-feeds-rw)' != '$''(dn-bot-dnceng-artifact-feeds-rw)' ]; then - # Temporarily work around https://github.com/dotnet/arcade/issues/7709 - chmod +x $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh - $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh $(Build.SourcesDirectory)/NuGet.config $(dn-bot-dnceng-artifact-feeds-rw) - internalRestoreArgs='/p:CopyWipIntoInnerSourceBuildRepo=true' - - # The 'Copy WIP' feature of source build uses git stash to apply changes from the original repo. - # This only works if there is a username/email configured, which won't be the case in most CI runs. - git config --get user.email - if [ $? -ne 0 ]; then - git config user.email dn-bot@microsoft.com - git config user.name dn-bot - fi - fi - - # If building on the internal project, the internal storage variable may be available (usually only if needed) - # In that case, add variables to allow the download of internal runtimes if the specified versions are not found - # in the default public locations. - internalRuntimeDownloadArgs= - if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then - internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://dotnetbuilds.blob.core.windows.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://dotnetbuilds.blob.core.windows.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' - fi - - buildConfig=Release - # Check if AzDO substitutes in a build config from a variable, and use it if so. - if [ '$(_BuildConfig)' != '$''(_BuildConfig)' ]; then - buildConfig='$(_BuildConfig)' - fi - - officialBuildArgs= - if [ '${{ and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}' = 'True' ]; then - officialBuildArgs='/p:DotNetPublishUsingPipelines=true /p:OfficialBuildId=$(BUILD.BUILDNUMBER)' - fi - - targetRidArgs= - if [ '${{ parameters.platform.targetRID }}' != '' ]; then - targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' - fi - - runtimeOsArgs= - if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then - runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' - fi - - baseOsArgs= - if [ '${{ parameters.platform.baseOS }}' != '' ]; then - baseOsArgs='/p:BaseOS=${{ parameters.platform.baseOS }}' - fi - - publishArgs= - if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then - publishArgs='--publish' - fi - - assetManifestFileName=SourceBuild_RidSpecific.xml - if [ '${{ parameters.platform.name }}' != '' ]; then - assetManifestFileName=SourceBuild_${{ parameters.platform.name }}.xml - fi - - ${{ coalesce(parameters.platform.buildScript, './build.sh') }} --ci \ - --configuration $buildConfig \ - --restore --build --pack $publishArgs -bl \ - $officialBuildArgs \ - $internalRuntimeDownloadArgs \ - $internalRestoreArgs \ - $targetRidArgs \ - $runtimeOsArgs \ - $baseOsArgs \ - /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ - /p:ArcadeBuildFromSource=true \ - /p:DotNetBuildSourceOnly=true \ - /p:DotNetBuildRepo=true \ - /p:AssetManifestFileName=$assetManifestFileName - displayName: Build - -# Upload build logs for diagnosis. -- task: CopyFiles@2 - displayName: Prepare BuildLogs staging directory - inputs: - SourceFolder: '$(Build.SourcesDirectory)' - Contents: | - **/*.log - **/*.binlog - artifacts/sb/prebuilt-report/** - TargetFolder: '$(Build.StagingDirectory)/BuildLogs' - CleanTargetFolder: true - continueOnError: true - condition: succeededOrFailed() - -- task: 1ES.PublishPipelineArtifact@1 - displayName: Publish BuildLogs - inputs: - targetPath: '$(Build.StagingDirectory)/BuildLogs' - artifactName: BuildLogs_SourceBuild_${{ parameters.platform.name }}_Attempt$(System.JobAttempt) - continueOnError: true - condition: succeededOrFailed() +- template: /eng/common/core-templates/steps/source-build.yml + parameters: + is1ESPipeline: true -# Manually inject component detection so that we can ignore the source build upstream cache, which contains -# a nupkg cache of input packages (a local feed). -# This path must match the upstream cache path in property 'CurrentRepoSourceBuiltNupkgCacheDir' -# in src\Microsoft.DotNet.Arcade.Sdk\tools\SourceBuild\SourceBuildArcade.targets -- task: ComponentGovernanceComponentDetection@0 - displayName: Component Detection (Exclude upstream cache) - inputs: - ignoreDirectories: '$(Build.SourcesDirectory)/artifacts/sb/src/artifacts/obj/source-built-upstream-cache' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml deleted file mode 100644 index 7870f93bc17652..00000000000000 --- a/eng/common/templates/job/execute-sdl.yml +++ /dev/null @@ -1,139 +0,0 @@ -parameters: - enable: 'false' # Whether the SDL validation job should execute or not - overrideParameters: '' # Optional: to override values for parameters. - additionalParameters: '' # Optional: parameters that need user specific values eg: '-SourceToolsList @("abc","def") -ArtifactToolsList @("ghi","jkl")' - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - # Optional: if true, publish the '.gdn' folder as a pipeline artifact. This can help with in-depth - # diagnosis of problems with specific tool configurations. - publishGuardianDirectoryToPipeline: false - # The script to run to execute all SDL tools. Use this if you want to use a script to define SDL - # parameters rather than relying on YAML. It may be better to use a local script, because you can - # reproduce results locally without piecing together a command based on the YAML. - executeAllSdlToolsScript: 'eng/common/sdl/execute-all-sdl-tools.ps1' - # There is some sort of bug (has been reported) in Azure DevOps where if this parameter is named - # 'continueOnError', the parameter value is not correctly picked up. - # This can also be remedied by the caller (post-build.yml) if it does not use a nested parameter - sdlContinueOnError: false # optional: determines whether to continue the build if the step errors; - # optional: determines if build artifacts should be downloaded. - downloadArtifacts: true - # optional: determines if this job should search the directory of downloaded artifacts for - # 'tar.gz' and 'zip' archive files and extract them before running SDL validation tasks. - extractArchiveArtifacts: false - dependsOn: '' # Optional: dependencies of the job - artifactNames: '' # Optional: patterns supplied to DownloadBuildArtifacts - # Usage: - # artifactNames: - # - 'BlobArtifacts' - # - 'Artifacts_Windows_NT_Release' - # Optional: download a list of pipeline artifacts. 'downloadArtifacts' controls build artifacts, - # not pipeline artifacts, so doesn't affect the use of this parameter. - pipelineArtifactNames: [] - -jobs: -- job: Run_SDL - dependsOn: ${{ parameters.dependsOn }} - displayName: Run SDL tool - condition: and(succeededOrFailed(), eq( ${{ parameters.enable }}, 'true')) - variables: - - group: DotNet-VSTS-Bot - - name: AzDOProjectName - value: ${{ parameters.AzDOProjectName }} - - name: AzDOPipelineId - value: ${{ parameters.AzDOPipelineId }} - - name: AzDOBuildId - value: ${{ parameters.AzDOBuildId }} - - template: /eng/common/templates/variables/sdl-variables.yml - - name: GuardianVersion - value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} - - template: /eng/common/templates/variables/pool-providers.yml - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - checkout: self - clean: true - - # If the template caller didn't provide an AzDO parameter, set them all up as Maestro vars. - - ${{ if not(and(parameters.AzDOProjectName, parameters.AzDOPipelineId, parameters.AzDOBuildId)) }}: - - template: /eng/common/templates/post-build/setup-maestro-vars.yml - - - ${{ if ne(parameters.downloadArtifacts, 'false')}}: - - ${{ if ne(parameters.artifactNames, '') }}: - - ${{ each artifactName in parameters.artifactNames }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Build Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: ${{ artifactName }} - downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - checkDownloadedFiles: true - - ${{ if eq(parameters.artifactNames, '') }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Build Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - downloadType: specific files - itemPattern: "**" - downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - checkDownloadedFiles: true - - - ${{ each artifactName in parameters.pipelineArtifactNames }}: - - task: DownloadPipelineArtifact@2 - displayName: Download Pipeline Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: ${{ artifactName }} - downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - checkDownloadedFiles: true - - - powershell: eng/common/sdl/trim-assets-version.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts - displayName: Trim the version from the NuGet packages - continueOnError: ${{ parameters.sdlContinueOnError }} - - - powershell: eng/common/sdl/extract-artifact-packages.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts\BlobArtifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts\BlobArtifacts - displayName: Extract Blob Artifacts - continueOnError: ${{ parameters.sdlContinueOnError }} - - - powershell: eng/common/sdl/extract-artifact-packages.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts\PackageArtifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts\PackageArtifacts - displayName: Extract Package Artifacts - continueOnError: ${{ parameters.sdlContinueOnError }} - - - ${{ if ne(parameters.extractArchiveArtifacts, 'false') }}: - - powershell: eng/common/sdl/extract-artifact-archives.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts - displayName: Extract Archive Artifacts - continueOnError: ${{ parameters.sdlContinueOnError }} - - - template: /eng/common/templates/steps/execute-sdl.yml - parameters: - overrideGuardianVersion: ${{ parameters.overrideGuardianVersion }} - executeAllSdlToolsScript: ${{ parameters.executeAllSdlToolsScript }} - overrideParameters: ${{ parameters.overrideParameters }} - additionalParameters: ${{ parameters.additionalParameters }} - publishGuardianDirectoryToPipeline: ${{ parameters.publishGuardianDirectoryToPipeline }} - sdlContinueOnError: ${{ parameters.sdlContinueOnError }} diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index a3277bf15c51ff..1cf9a6d48127b6 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -1,259 +1,61 @@ -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - -parameters: -# Job schema parameters - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - cancelTimeoutInMinutes: '' - condition: '' - container: '' - continueOnError: false - dependsOn: '' - displayName: '' - pool: '' - steps: [] - strategy: '' - timeoutInMinutes: '' - variables: [] - workspace: '' - templateContext: '' - -# Job base template specific parameters - # See schema documentation - https://github.com/dotnet/arcade/blob/master/Documentation/AzureDevOps/TemplateSchema.md - artifacts: '' - enableMicrobuild: false +parameters: enablePublishBuildArtifacts: false - enablePublishBuildAssets: false - enablePublishTestResults: false - enablePublishUsingPipelines: false - enableBuildRetry: false - disableComponentGovernance: '' - componentGovernanceIgnoreDirectories: '' - mergeTestResults: false - testRunTitle: '' - testResultsFormat: '' - name: '' - preSteps: [] - runAsPublic: false -# Sbom related params - enableSbom: true - PackageVersion: 7.0.0 - BuildDropPath: '$(Build.SourcesDirectory)/artifacts' jobs: -- job: ${{ parameters.name }} - - ${{ if ne(parameters.cancelTimeoutInMinutes, '') }}: - cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }} - - ${{ if ne(parameters.condition, '') }}: - condition: ${{ parameters.condition }} - - ${{ if ne(parameters.container, '') }}: - container: ${{ parameters.container }} - - ${{ if ne(parameters.continueOnError, '') }}: - continueOnError: ${{ parameters.continueOnError }} - - ${{ if ne(parameters.dependsOn, '') }}: - dependsOn: ${{ parameters.dependsOn }} - - ${{ if ne(parameters.displayName, '') }}: - displayName: ${{ parameters.displayName }} - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - - ${{ if ne(parameters.strategy, '') }}: - strategy: ${{ parameters.strategy }} - - ${{ if ne(parameters.timeoutInMinutes, '') }}: - timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - - ${{ if ne(parameters.templateContext, '') }}: - templateContext: ${{ parameters.templateContext }} - - variables: - - ${{ if ne(parameters.enableTelemetry, 'false') }}: - - name: DOTNET_CLI_TELEMETRY_PROFILE - value: '$(Build.Repository.Uri)' - - ${{ if eq(parameters.enableRichCodeNavigation, 'true') }}: - - name: EnableRichCodeNavigation - value: 'true' - # Retry signature validation up to three times, waiting 2 seconds between attempts. - # See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu3028#retry-untrusted-root-failures - - name: NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY - value: 3,2000 - - ${{ each variable in parameters.variables }}: - # handle name-value variable syntax - # example: - # - name: [key] - # value: [value] - - ${{ if ne(variable.name, '') }}: - - name: ${{ variable.name }} - value: ${{ variable.value }} - - # handle variable groups - - ${{ if ne(variable.group, '') }}: - - group: ${{ variable.group }} - - # handle template variable syntax - # example: - # - template: path/to/template.yml - # parameters: - # [key]: [value] - - ${{ if ne(variable.template, '') }}: - - template: ${{ variable.template }} - ${{ if ne(variable.parameters, '') }}: - parameters: ${{ variable.parameters }} - - # handle key-value variable syntax. - # example: - # - [key]: [value] - - ${{ if and(eq(variable.name, ''), eq(variable.group, ''), eq(variable.template, '')) }}: - - ${{ each pair in variable }}: - - name: ${{ pair.key }} - value: ${{ pair.value }} - - # DotNet-HelixApi-Access provides 'HelixApiAccessToken' for internal builds - - ${{ if and(eq(parameters.enableTelemetry, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: DotNet-HelixApi-Access - - ${{ if ne(parameters.workspace, '') }}: - workspace: ${{ parameters.workspace }} - - steps: - - ${{ if ne(parameters.preSteps, '') }}: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - task: MicroBuildSigningPlugin@3 - displayName: Install MicroBuild plugin - inputs: - signType: $(_SignType) - zipSources: false - feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json - env: - TeamName: $(_TeamName) - continueOnError: ${{ parameters.continueOnError }} - condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - - - ${{ if and(eq(parameters.runAsPublic, 'false'), eq(variables['System.TeamProject'], 'internal')) }}: - - task: NuGetAuthenticate@1 - - - ${{ if and(ne(parameters.artifacts.download, 'false'), ne(parameters.artifacts.download, '')) }}: - - task: DownloadPipelineArtifact@2 - inputs: - buildType: current - artifactName: ${{ coalesce(parameters.artifacts.download.name, 'Artifacts_$(Agent.OS)_$(_BuildConfig)') }} - targetPath: ${{ coalesce(parameters.artifacts.download.path, 'artifacts') }} - itemPattern: ${{ coalesce(parameters.artifacts.download.pattern, '**') }} - - - ${{ each step in parameters.steps }}: - - ${{ step }} - - - ${{ if eq(parameters.enableRichCodeNavigation, true) }}: - - task: RichCodeNavIndexer@0 - displayName: RichCodeNav Upload - inputs: - languages: ${{ coalesce(parameters.richCodeNavigationLanguage, 'csharp') }} - environment: ${{ coalesce(parameters.richCodeNavigationEnvironment, 'internal') }} - richNavLogOutputDirectory: $(Build.SourcesDirectory)/artifacts/bin - uploadRichNavArtifacts: ${{ coalesce(parameters.richCodeNavigationUploadArtifacts, false) }} - continueOnError: true - - - template: /eng/common/templates/steps/component-governance.yml - parameters: - ${{ if eq(parameters.disableComponentGovernance, '') }}: - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/dotnet/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/microsoft/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: - disableComponentGovernance: false - ${{ else }}: - disableComponentGovernance: true - ${{ else }}: - disableComponentGovernance: ${{ parameters.disableComponentGovernance }} - componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: MicroBuildCleanup@1 - displayName: Execute Microbuild cleanup tasks - condition: and(always(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - env: - TeamName: $(_TeamName) - - - ${{ if ne(parameters.artifacts.publish, '') }}: - - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: - - task: CopyFiles@2 - displayName: Gather binaries for publish to artifacts - inputs: - SourceFolder: 'artifacts/bin' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/bin' - - task: CopyFiles@2 - displayName: Gather packages for publish to artifacts - inputs: - SourceFolder: 'artifacts/packages' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/packages' - - task: PublishBuildArtifacts@1 - displayName: Publish pipeline artifacts - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} - continueOnError: true - condition: always() - - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: - - publish: artifacts/log - artifact: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)') }} - displayName: Publish logs - continueOnError: true - condition: always() - - - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: - - task: PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} - continueOnError: true - condition: always() - - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'xunit')) }}: - - task: PublishTestResults@2 - displayName: Publish XUnit Test Results - inputs: - testResultsFormat: 'xUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'vstest')) }}: - - task: PublishTestResults@2 - displayName: Publish TRX Test Results - inputs: - testResultsFormat: 'VSTest' - testResultsFiles: '*.trx' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: - - template: /eng/common/templates/steps/generate-sbom.yml - parameters: - PackageVersion: ${{ parameters.packageVersion}} - BuildDropPath: ${{ parameters.buildDropPath }} - IgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableBuildRetry, 'true') }}: - - publish: $(Build.SourcesDirectory)\eng\common\BuildConfiguration - artifact: BuildConfiguration - displayName: Publish build retry configuration - continueOnError: true +- template: /eng/common/core-templates/job/job.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ if and(ne(parameter.key, 'steps'), ne(parameter.key, 'is1ESPipeline')) }}: + ${{ parameter.key }}: ${{ parameter.value }} + + steps: + - ${{ each step in parameters.steps }}: + - ${{ step }} + + artifactPublishSteps: + - ${{ if ne(parameters.artifacts.publish, '') }}: + - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: false + args: + displayName: Publish pipeline artifacts + pathToPublish: '$(Build.ArtifactStagingDirectory)/artifacts' + publishLocation: Container + artifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} + continueOnError: true + condition: always() + - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: false + args: + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts/log' + artifactName: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)') }} + displayName: 'Publish logs' + continueOnError: true + condition: always() + + - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: false + args: + displayName: Publish Logs + pathToPublish: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' + publishLocation: Container + artifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} + continueOnError: true + condition: always() + + - ${{ if eq(parameters.enableBuildRetry, 'true') }}: + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: false + args: + targetPath: '$(Build.SourcesDirectory)\eng\common\BuildConfiguration' + artifactName: 'BuildConfiguration' + displayName: 'Publish build retry configuration' + continueOnError: true diff --git a/eng/common/templates/job/onelocbuild.yml b/eng/common/templates/job/onelocbuild.yml index 60ab00c4de3acd..ff829dc4c700c6 100644 --- a/eng/common/templates/job/onelocbuild.yml +++ b/eng/common/templates/job/onelocbuild.yml @@ -1,109 +1,7 @@ -parameters: - # Optional: dependencies of the job - dependsOn: '' - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: '' - - CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex - GithubPat: $(BotAccount-dotnet-bot-repo-PAT) - - SourcesDirectory: $(Build.SourcesDirectory) - CreatePr: true - AutoCompletePr: false - ReusePr: true - UseLfLineEndings: true - UseCheckedInLocProjectJson: false - SkipLocProjectJsonGeneration: false - LanguageSet: VS_Main_Languages - LclSource: lclFilesInRepo - LclPackageId: '' - RepoType: gitHub - GitHubOrg: dotnet - MirrorRepo: '' - MirrorBranch: main - condition: '' - JobNameSuffix: '' - jobs: -- job: OneLocBuild${{ parameters.JobNameSuffix }} - - dependsOn: ${{ parameters.dependsOn }} - - displayName: OneLocBuild${{ parameters.JobNameSuffix }} - - variables: - - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat - - name: _GenerateLocProjectArguments - value: -SourcesDirectory ${{ parameters.SourcesDirectory }} - -LanguageSet "${{ parameters.LanguageSet }}" - -CreateNeutralXlfs - - ${{ if eq(parameters.UseCheckedInLocProjectJson, 'true') }}: - - name: _GenerateLocProjectArguments - value: ${{ variables._GenerateLocProjectArguments }} -UseCheckedInLocProjectJson - - template: /eng/common/templates/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - - steps: - - ${{ if ne(parameters.SkipLocProjectJsonGeneration, 'true') }}: - - task: Powershell@2 - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/generate-locproject.ps1 - arguments: $(_GenerateLocProjectArguments) - displayName: Generate LocProject.json - condition: ${{ parameters.condition }} - - - task: OneLocBuild@2 - displayName: OneLocBuild - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - locProj: eng/Localize/LocProject.json - outDir: $(Build.ArtifactStagingDirectory) - lclSource: ${{ parameters.LclSource }} - lclPackageId: ${{ parameters.LclPackageId }} - isCreatePrSelected: ${{ parameters.CreatePr }} - isAutoCompletePrSelected: ${{ parameters.AutoCompletePr }} - ${{ if eq(parameters.CreatePr, true) }}: - isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - isShouldReusePrSelected: ${{ parameters.ReusePr }} - packageSourceAuth: patAuth - patVariable: ${{ parameters.CeapexPat }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - repoType: ${{ parameters.RepoType }} - gitHubPatVariable: "${{ parameters.GithubPat }}" - ${{ if ne(parameters.MirrorRepo, '') }}: - isMirrorRepoSelected: true - gitHubOrganization: ${{ parameters.GitHubOrg }} - mirrorRepo: ${{ parameters.MirrorRepo }} - mirrorBranch: ${{ parameters.MirrorBranch }} - condition: ${{ parameters.condition }} - - - task: PublishBuildArtifacts@1 - displayName: Publish Localization Files - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/loc' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} +- template: /eng/common/core-templates/job/onelocbuild.yml + parameters: + is1ESPipeline: false - - task: PublishBuildArtifacts@1 - displayName: Publish LocProject.json - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/Localize/' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} \ No newline at end of file + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/job/publish-build-assets.yml b/eng/common/templates/job/publish-build-assets.yml index bb42240f865b56..ab2edec2adb541 100644 --- a/eng/common/templates/job/publish-build-assets.yml +++ b/eng/common/templates/job/publish-build-assets.yml @@ -1,155 +1,7 @@ -parameters: - configuration: 'Debug' - - # Optional: condition for the job to run - condition: '' - - # Optional: 'true' if future jobs should run even if this job fails - continueOnError: false - - # Optional: dependencies of the job - dependsOn: '' - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: {} - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishUsingPipelines: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishAssetsImmediately: false - - artifactsPublishingAdditionalParameters: '' - - signingValidationAdditionalParameters: '' - jobs: -- job: Asset_Registry_Publish - - dependsOn: ${{ parameters.dependsOn }} - timeoutInMinutes: 150 - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - displayName: Publish Assets - ${{ else }}: - displayName: Publish to Build Asset Registry - - variables: - - template: /eng/common/templates/variables/pool-providers.yml - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: Publish-Build-Assets - - group: AzureDevOps-Artifact-Feeds-Pats - - name: runCodesignValidationInjection - value: false - # unconditional - needed for logs publishing (redactor tool version) - - template: /eng/common/templates/post-build/common-variables.yml - - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: NetCore1ESPool-Publishing-Internal - demands: ImageOverride -equals windows.vs2019.amd64 - - steps: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - checkout: self - fetchDepth: 3 - clean: true - - - task: DownloadBuildArtifacts@0 - displayName: Download artifact - inputs: - artifactName: AssetManifests - downloadPath: '$(Build.StagingDirectory)/Download' - checkDownloadedFiles: true - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: NuGetAuthenticate@1 - - - task: PowerShell@2 - displayName: Publish Build Assets - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishBuildAssets -restore -msbuildEngine dotnet - /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' - /p:BuildAssetRegistryToken=$(MaestroAccessToken) - /p:MaestroApiEndpoint=https://maestro.dot.net - /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} - /p:OfficialBuildId=$(Build.BuildNumber) - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: powershell@2 - displayName: Create ReleaseConfigs Artifact - inputs: - targetType: inline - script: | - Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value $(BARBuildId) - Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value "$(DefaultChannels)" - Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value $(IsStableBuild) - - - task: PublishBuildArtifacts@1 - displayName: Publish ReleaseConfigs Artifact - inputs: - PathtoPublish: '$(Build.StagingDirectory)/ReleaseConfigs.txt' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - task: powershell@2 - displayName: Check if SymbolPublishingExclusionsFile.txt exists - inputs: - targetType: inline - script: | - $symbolExclusionfile = "$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt" - if(Test-Path -Path $symbolExclusionfile) - { - Write-Host "SymbolExclusionFile exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]true" - } - else{ - Write-Host "Symbols Exclusion file does not exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]false" - } - - - task: PublishBuildArtifacts@1 - displayName: Publish SymbolPublishingExclusionsFile Artifact - condition: eq(variables['SymbolExclusionFile'], 'true') - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - - template: /eng/common/templates/post-build/setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: PowerShell@2 - displayName: Publish Using Darc - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion 3 - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' - -MaestroToken '$(MaestroApiAccessToken)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' +- template: /eng/common/core-templates/job/publish-build-assets.yml + parameters: + is1ESPipeline: false - - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: - - template: /eng/common/templates/steps/publish-logs.yml - parameters: - JobLabel: 'Publish_Artifacts_Logs' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/job/source-build.yml b/eng/common/templates/job/source-build.yml index d7ed209494c7be..e44d47b1d760c4 100644 --- a/eng/common/templates/job/source-build.yml +++ b/eng/common/templates/job/source-build.yml @@ -1,66 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. The template produces a server job with a - # default ID 'Source_Build_Complete' to put in a dependency list if necessary. - - # Specifies the prefix for source-build jobs added to pipeline. Use this if disambiguation needed. - jobNamePrefix: 'Source_Build' - - # Defines the platform on which to run the job. By default, a linux-x64 machine, suitable for - # managed-only repositories. This is an object with these properties: - # - # name: '' - # The name of the job. This is included in the job ID. - # targetRID: '' - # The name of the target RID to use, instead of the one auto-detected by Arcade. - # nonPortable: false - # Enables non-portable mode. This means a more specific RID (e.g. fedora.32-x64 rather than - # linux-x64), and compiling against distro-provided packages rather than portable ones. - # skipPublishValidation: false - # Disables publishing validation. By default, a check is performed to ensure no packages are - # published by source-build. - # container: '' - # A container to use. Runs in docker. - # pool: {} - # A pool to use. Runs directly on an agent. - # buildScript: '' - # Specifies the build script to invoke to perform the build in the repo. The default - # './build.sh' should work for typical Arcade repositories, but this is customizable for - # difficult situations. - # jobProperties: {} - # A list of job properties to inject at the top level, for potential extensibility beyond - # container and pool. - platform: {} - jobs: -- job: ${{ parameters.jobNamePrefix }}_${{ parameters.platform.name }} - displayName: Source-Build (${{ parameters.platform.name }}) - - ${{ each property in parameters.platform.jobProperties }}: - ${{ property.key }}: ${{ property.value }} - - ${{ if ne(parameters.platform.container, '') }}: - container: ${{ parameters.platform.container }} - - ${{ if eq(parameters.platform.pool, '') }}: - # The default VM host AzDO pool. This should be capable of running Docker containers: almost all - # source-build builds run in Docker, including the default managed platform. - # /eng/common/templates/variables/pool-providers.yml can't be used here (some customers declare variables already), so duplicate its logic - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] - demands: ImageOverride -equals Build.Ubuntu.2204.Amd64.Open - - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] - demands: ImageOverride -equals Build.Ubuntu.2204.Amd64 - - ${{ if ne(parameters.platform.pool, '') }}: - pool: ${{ parameters.platform.pool }} - - workspace: - clean: all +- template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: false - steps: - - template: /eng/common/templates/steps/source-build.yml - parameters: - platform: ${{ parameters.platform }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/job/source-index-stage1.yml b/eng/common/templates/job/source-index-stage1.yml index b5a3e5c4a6c847..89f3291593cb78 100644 --- a/eng/common/templates/job/source-index-stage1.yml +++ b/eng/common/templates/job/source-index-stage1.yml @@ -1,67 +1,7 @@ -parameters: - runAsPublic: false - sourceIndexPackageVersion: 1.0.1-20240129.2 - sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json - sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" - preSteps: [] - binlogPath: artifacts/log/Debug/Build.binlog - condition: '' - dependsOn: '' - pool: '' - jobs: -- job: SourceIndexStage1 - dependsOn: ${{ parameters.dependsOn }} - condition: ${{ parameters.condition }} - variables: - - name: SourceIndexPackageVersion - value: ${{ parameters.sourceIndexPackageVersion }} - - name: SourceIndexPackageSource - value: ${{ parameters.sourceIndexPackageSource }} - - name: BinlogPath - value: ${{ parameters.binlogPath }} - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: source-dot-net stage1 variables - - template: /eng/common/templates/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $(DncEngPublicBuildPool) - demands: ImageOverride -equals windows.vs2022.amd64.open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2022.amd64 - - steps: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - task: UseDotNet@2 - displayName: Use .NET 8 SDK - inputs: - packageType: sdk - version: 8.0.x - installationPath: $(Agent.TempDirectory)/dotnet - workingDirectory: $(Agent.TempDirectory) - - - script: | - $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - displayName: Download Tools - # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. - workingDirectory: $(Agent.TempDirectory) - - - script: ${{ parameters.sourceIndexBuildCommand }} - displayName: Build Repository - - - script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i $(BinlogPath) -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output - displayName: Process Binlog into indexable sln +- template: /eng/common/core-templates/job/source-index-stage1.yml + parameters: + is1ESPipeline: false - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - script: $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) - displayName: Upload stage1 artifacts to source index - env: - BLOB_CONTAINER_URL: $(source-dot-net-stage1-blob-container-url) + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/jobs/codeql-build.yml b/eng/common/templates/jobs/codeql-build.yml index f7dc5ea4aaa63c..517f24d6a52ce7 100644 --- a/eng/common/templates/jobs/codeql-build.yml +++ b/eng/common/templates/jobs/codeql-build.yml @@ -1,31 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - jobs: -- template: /eng/common/templates/jobs/jobs.yml +- template: /eng/common/core-templates/jobs/codeql-build.yml parameters: - enableMicrobuild: false - enablePublishBuildArtifacts: false - enablePublishTestResults: false - enablePublishBuildAssets: false - enablePublishUsingPipelines: false - enableTelemetry: true + is1ESPipeline: false - variables: - - group: Publish-Build-Assets - # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in - # sync with the packages.config file. - - name: DefaultGuardianVersion - value: 0.109.0 - - name: GuardianPackagesConfigFile - value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config - - name: GuardianVersion - value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} - - jobs: ${{ parameters.jobs }} - + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/jobs/jobs.yml b/eng/common/templates/jobs/jobs.yml index 289bb2396ce83e..388e9037b3e601 100644 --- a/eng/common/templates/jobs/jobs.yml +++ b/eng/common/templates/jobs/jobs.yml @@ -1,97 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: Enable publishing using release pipelines - enablePublishUsingPipelines: false - - # Optional: Enable running the source-build jobs to build repo from source - enableSourceBuild: false - - # Optional: Parameters for source-build template. - # See /eng/common/templates/jobs/source-build.yml for options - sourceBuildParameters: [] - - graphFileGeneration: - # Optional: Enable generating the graph files at the end of the build - enabled: false - # Optional: Include toolset dependencies in the generated graph files - includeToolset: false - - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - - # Optional: Override automatically derived dependsOn value for "publish build assets" job - publishBuildAssetsDependsOn: '' - - # Optional: Publish the assets as soon as the publish to BAR stage is complete, rather doing so in a separate stage. - publishAssetsImmediately: false - - # Optional: If using publishAssetsImmediately and additional parameters are needed, can be used to send along additional parameters (normally sent to post-build.yml) - artifactsPublishingAdditionalParameters: '' - signingValidationAdditionalParameters: '' - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - enableSourceIndex: false - sourceIndexParams: {} - -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - jobs: -- ${{ each job in parameters.jobs }}: - - template: ../job/job.yml - parameters: - # pass along parameters - ${{ each parameter in parameters }}: - ${{ if ne(parameter.key, 'jobs') }}: - ${{ parameter.key }}: ${{ parameter.value }} - - # pass along job properties - ${{ each property in job }}: - ${{ if ne(property.key, 'job') }}: - ${{ property.key }}: ${{ property.value }} - - name: ${{ job.job }} - -- ${{ if eq(parameters.enableSourceBuild, true) }}: - - template: /eng/common/templates/jobs/source-build.yml - parameters: - allCompletedJobId: Source_Build_Complete - ${{ each parameter in parameters.sourceBuildParameters }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if eq(parameters.enableSourceIndex, 'true') }}: - - template: ../job/source-index-stage1.yml - parameters: - runAsPublic: ${{ parameters.runAsPublic }} - ${{ each parameter in parameters.sourceIndexParams }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: - - template: ../job/publish-build-assets.yml - parameters: - continueOnError: ${{ parameters.continueOnError }} - dependsOn: - - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.publishBuildAssetsDependsOn }}: - - ${{ job.job }} - - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.jobs }}: - - ${{ job.job }} - - ${{ if eq(parameters.enableSourceBuild, true) }}: - - Source_Build_Complete +- template: /eng/common/core-templates/jobs/jobs.yml + parameters: + is1ESPipeline: false - runAsPublic: ${{ parameters.runAsPublic }} - publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} - publishAssetsImmediately: ${{ parameters.publishAssetsImmediately }} - enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - signingValidationAdditionalParameters: ${{ parameters.signingValidationAdditionalParameters }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/jobs/source-build.yml b/eng/common/templates/jobs/source-build.yml index da91481ff1d286..818d4c326dbbf1 100644 --- a/eng/common/templates/jobs/source-build.yml +++ b/eng/common/templates/jobs/source-build.yml @@ -1,46 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. A job is created for each platform, as - # well as an optional server job that completes when all platform jobs complete. - - # The name of the "join" job for all source-build platforms. If set to empty string, the job is - # not included. Existing repo pipelines can use this job depend on all source-build jobs - # completing without maintaining a separate list of every single job ID: just depend on this one - # server job. By default, not included. Recommended name if used: 'Source_Build_Complete'. - allCompletedJobId: '' - - # See /eng/common/templates/job/source-build.yml - jobNamePrefix: 'Source_Build' - - # This is the default platform provided by Arcade, intended for use by a managed-only repo. - defaultManagedPlatform: - name: 'Managed' - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream9' - - # Defines the platforms on which to run build jobs. One job is created for each platform, and the - # object in this array is sent to the job template as 'platform'. If no platforms are specified, - # one job runs on 'defaultManagedPlatform'. - platforms: [] - jobs: +- template: /eng/common/core-templates/jobs/source-build.yml + parameters: + is1ESPipeline: false -- ${{ if ne(parameters.allCompletedJobId, '') }}: - - job: ${{ parameters.allCompletedJobId }} - displayName: Source-Build Complete - pool: server - dependsOn: - - ${{ each platform in parameters.platforms }}: - - ${{ parameters.jobNamePrefix }}_${{ platform.name }} - - ${{ if eq(length(parameters.platforms), 0) }}: - - ${{ parameters.jobNamePrefix }}_${{ parameters.defaultManagedPlatform.name }} - -- ${{ each platform in parameters.platforms }}: - - template: /eng/common/templates/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ platform }} - -- ${{ if eq(length(parameters.platforms), 0) }}: - - template: /eng/common/templates/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ parameters.defaultManagedPlatform }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index b9ede10bf099ae..7fa105875592c8 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -1,24 +1,8 @@ variables: - - group: Publish-Build-Assets +- template: /eng/common/core-templates/post-build/common-variables.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: false - # Whether the build is internal or not - - name: IsInternalBuild - value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} - - # Default Maestro++ API Endpoint and API Version - - name: MaestroApiEndPoint - value: "https://maestro.dot.net" - - name: MaestroApiAccessToken - value: $(MaestroAccessToken) - - name: MaestroApiVersion - value: "2020-02-20" - - - name: SourceLinkCLIVersion - value: 3.0.0 - - name: SymbolToolVersion - value: 1.0.1 - - name: BinlogToolVersion - value: 1.0.11 - - - name: runCodesignValidationInjection - value: false + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index ee70e2b399c5a9..53ede714bdd207 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -1,282 +1,8 @@ -parameters: - # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. - # Publishing V1 is no longer supported - # Publishing V2 is no longer supported - # Publishing V3 is the default - - name: publishingInfraVersion - displayName: Which version of publishing should be used to promote the build definition? - type: number - default: 3 - values: - - 3 - - - name: BARBuildId - displayName: BAR Build Id - type: number - default: 0 - - - name: PromoteToChannelIds - displayName: Channel to promote BARBuildId to - type: string - default: '' - - - name: enableSourceLinkValidation - displayName: Enable SourceLink validation - type: boolean - default: false - - - name: enableSigningValidation - displayName: Enable signing validation - type: boolean - default: true - - - name: enableSymbolValidation - displayName: Enable symbol validation - type: boolean - default: false - - - name: enableNugetValidation - displayName: Enable NuGet validation - type: boolean - default: true - - - name: publishInstallersAndChecksums - displayName: Publish installers and checksums - type: boolean - default: true - - - name: SDLValidationParameters - type: object - default: - enable: false - publishGdn: false - continueOnError: false - params: '' - artifactNames: '' - downloadArtifacts: true - - # These parameters let the user customize the call to sdk-task.ps1 for publishing - # symbols & general artifacts as well as for signing validation - - name: symbolPublishingAdditionalParameters - displayName: Symbol publishing additional parameters - type: string - default: '' - - - name: artifactsPublishingAdditionalParameters - displayName: Artifact publishing additional parameters - type: string - default: '' - - - name: signingValidationAdditionalParameters - displayName: Signing validation additional parameters - type: string - default: '' - - # Which stages should finish execution before post-build stages start - - name: validateDependsOn - type: object - default: - - build - - - name: publishDependsOn - type: object - default: - - Validate - - # Optional: Call asset publishing rather than running in a separate stage - - name: publishAssetsImmediately - type: boolean - default: false - stages: -- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - - stage: Validate - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Validate Build Assets - variables: - - template: common-variables.yml - - template: /eng/common/templates/variables/pool-providers.yml - jobs: - - job: - displayName: NuGet Validation - condition: and(succeededOrFailed(), eq( ${{ parameters.enableNugetValidation }}, 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1 - arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ - -ToolDestinationPath $(Agent.BuildDirectory)/Extract/ - - - job: - displayName: Signing Validation - condition: and( eq( ${{ parameters.enableSigningValidation }}, 'true'), ne( variables['PostBuildSign'], 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - itemPattern: | - ** - !**/Microsoft.SourceBuild.Intermediate.*.nupkg - - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@1 - displayName: 'Authenticate to AzDO Feeds' - - # Signing validation will optionally work with the buildmanifest file which is downloaded from - # Azure DevOps above. - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task SigningValidation -restore -msbuildEngine vs - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' - /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' - ${{ parameters.signingValidationAdditionalParameters }} - - - template: ../steps/publish-logs.yml - parameters: - StageLabel: 'Validation' - JobLabel: 'Signing' - BinlogToolVersion: $(BinlogToolVersion) - - - job: - displayName: SourceLink Validation - condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: BlobArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1 - arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/ - -ExtractPath $(Agent.BuildDirectory)/Extract/ - -GHRepoName $(Build.Repository.Name) - -GHCommit $(Build.SourceVersion) - -SourcelinkCliVersion $(SourceLinkCLIVersion) - continueOnError: true - - - template: /eng/common/templates/job/execute-sdl.yml - parameters: - enable: ${{ parameters.SDLValidationParameters.enable }} - publishGuardianDirectoryToPipeline: ${{ parameters.SDLValidationParameters.publishGdn }} - additionalParameters: ${{ parameters.SDLValidationParameters.params }} - continueOnError: ${{ parameters.SDLValidationParameters.continueOnError }} - artifactNames: ${{ parameters.SDLValidationParameters.artifactNames }} - downloadArtifacts: ${{ parameters.SDLValidationParameters.downloadArtifacts }} - -- ${{ if ne(parameters.publishAssetsImmediately, 'true') }}: - - stage: publish_using_darc - ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - dependsOn: ${{ parameters.publishDependsOn }} - ${{ else }}: - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Publish using Darc - variables: - - template: common-variables.yml - - template: /eng/common/templates/variables/pool-providers.yml - jobs: - - job: - displayName: Publish Using Darc - timeoutInMinutes: 120 - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: NetCore1ESPool-Publishing-Internal - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: NuGetAuthenticate@1 +- template: /eng/common/core-templates/post-build/post-build.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: false - - task: PowerShell@2 - displayName: Publish Using Darc - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' - -MaestroToken '$(MaestroApiAccessToken)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/post-build/setup-maestro-vars.yml b/eng/common/templates/post-build/setup-maestro-vars.yml index 0c87f149a4ad77..a79fab5b441e84 100644 --- a/eng/common/templates/post-build/setup-maestro-vars.yml +++ b/eng/common/templates/post-build/setup-maestro-vars.yml @@ -1,70 +1,8 @@ -parameters: - BARBuildId: '' - PromoteToChannelIds: '' - steps: - - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Release Configs - inputs: - buildType: current - artifactName: ReleaseConfigs - checkDownloadedFiles: true - - - task: PowerShell@2 - name: setReleaseVars - displayName: Set Release Configs Vars - inputs: - targetType: inline - pwsh: true - script: | - try { - if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { - $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt - - $BarId = $Content | Select -Index 0 - $Channels = $Content | Select -Index 1 - $IsStableBuild = $Content | Select -Index 2 - - $AzureDevOpsProject = $Env:System_TeamProject - $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId - $AzureDevOpsBuildId = $Env:Build_BuildId - } - else { - $buildApiEndpoint = "${Env:MaestroApiEndPoint}/api/builds/${Env:BARBuildId}?api-version=${Env:MaestroApiVersion}" - - $apiHeaders = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' - $apiHeaders.Add('Accept', 'application/json') - $apiHeaders.Add('Authorization',"Bearer ${Env:MAESTRO_API_TOKEN}") - - $buildInfo = try { Invoke-WebRequest -Method Get -Uri $buildApiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } - - $BarId = $Env:BARBuildId - $Channels = $Env:PromoteToMaestroChannels -split "," - $Channels = $Channels -join "][" - $Channels = "[$Channels]" - - $IsStableBuild = $buildInfo.stable - $AzureDevOpsProject = $buildInfo.azureDevOpsProject - $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId - $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId - } - - Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" - Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" - Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" +- template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: false - Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" - Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" - Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" - } - catch { - Write-Host $_ - Write-Host $_.Exception - Write-Host $_.ScriptStackTrace - exit 1 - } - env: - MAESTRO_API_TOKEN: $(MaestroApiAccessToken) - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/steps/add-build-to-channel.yml b/eng/common/templates/steps/add-build-to-channel.yml index f67a210d62f3e5..42bbba161b9b6a 100644 --- a/eng/common/templates/steps/add-build-to-channel.yml +++ b/eng/common/templates/steps/add-build-to-channel.yml @@ -1,13 +1,7 @@ -parameters: - ChannelId: 0 - steps: -- task: PowerShell@2 - displayName: Add Build to Channel - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/add-build-to-channel.ps1 - arguments: -BuildId $(BARBuildId) - -ChannelId ${{ parameters.ChannelId }} - -MaestroApiAccessToken $(MaestroApiAccessToken) - -MaestroApiEndPoint $(MaestroApiEndPoint) - -MaestroApiVersion $(MaestroApiVersion) +- template: /eng/common/core-templates/steps/add-build-to-channel.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/build-reason.yml b/eng/common/templates/steps/build-reason.yml deleted file mode 100644 index eba58109b52c9d..00000000000000 --- a/eng/common/templates/steps/build-reason.yml +++ /dev/null @@ -1,12 +0,0 @@ -# build-reason.yml -# Description: runs steps if build.reason condition is valid. conditions is a string of valid build reasons -# to include steps (',' separated). -parameters: - conditions: '' - steps: [] - -steps: - - ${{ if and( not(startsWith(parameters.conditions, 'not')), contains(parameters.conditions, variables['build.reason'])) }}: - - ${{ parameters.steps }} - - ${{ if and( startsWith(parameters.conditions, 'not'), not(contains(parameters.conditions, variables['build.reason']))) }}: - - ${{ parameters.steps }} diff --git a/eng/common/templates/steps/component-governance.yml b/eng/common/templates/steps/component-governance.yml index 0ecec47b0c9177..c12a5f8d21d765 100644 --- a/eng/common/templates/steps/component-governance.yml +++ b/eng/common/templates/steps/component-governance.yml @@ -1,13 +1,7 @@ -parameters: - disableComponentGovernance: false - componentGovernanceIgnoreDirectories: '' - steps: -- ${{ if eq(parameters.disableComponentGovernance, 'true') }}: - - script: "echo ##vso[task.setvariable variable=skipComponentGovernanceDetection]true" - displayName: Set skipComponentGovernanceDetection variable -- ${{ if ne(parameters.disableComponentGovernance, 'true') }}: - - task: ComponentGovernanceComponentDetection@0 - continueOnError: true - inputs: - ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} \ No newline at end of file +- template: /eng/common/core-templates/steps/component-governance.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/execute-codeql.yml b/eng/common/templates/steps/execute-codeql.yml deleted file mode 100644 index 3930b1630214b3..00000000000000 --- a/eng/common/templates/steps/execute-codeql.yml +++ /dev/null @@ -1,32 +0,0 @@ -parameters: - # Language that should be analyzed. Defaults to csharp - language: csharp - # Build Commands - buildCommands: '' - overrideParameters: '' # Optional: to override values for parameters. - additionalParameters: '' # Optional: parameters that need user specific values eg: '-SourceToolsList @("abc","def") -ArtifactToolsList @("ghi","jkl")' - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - # Optional: if true, publish the '.gdn' folder as a pipeline artifact. This can help with in-depth - # diagnosis of problems with specific tool configurations. - publishGuardianDirectoryToPipeline: false - # The script to run to execute all SDL tools. Use this if you want to use a script to define SDL - # parameters rather than relying on YAML. It may be better to use a local script, because you can - # reproduce results locally without piecing together a command based on the YAML. - executeAllSdlToolsScript: 'eng/common/sdl/execute-all-sdl-tools.ps1' - # There is some sort of bug (has been reported) in Azure DevOps where if this parameter is named - # 'continueOnError', the parameter value is not correctly picked up. - # This can also be remedied by the caller (post-build.yml) if it does not use a nested parameter - # optional: determines whether to continue the build if the step errors; - sdlContinueOnError: false - -steps: -- template: /eng/common/templates/steps/execute-sdl.yml - parameters: - overrideGuardianVersion: ${{ parameters.overrideGuardianVersion }} - executeAllSdlToolsScript: ${{ parameters.executeAllSdlToolsScript }} - overrideParameters: ${{ parameters.overrideParameters }} - additionalParameters: '${{ parameters.additionalParameters }} - -CodeQLAdditionalRunConfigParams @("BuildCommands < ${{ parameters.buildCommands }}", "Language < ${{ parameters.language }}")' - publishGuardianDirectoryToPipeline: ${{ parameters.publishGuardianDirectoryToPipeline }} - sdlContinueOnError: ${{ parameters.sdlContinueOnError }} \ No newline at end of file diff --git a/eng/common/templates/steps/execute-sdl.yml b/eng/common/templates/steps/execute-sdl.yml deleted file mode 100644 index 07426fde05d824..00000000000000 --- a/eng/common/templates/steps/execute-sdl.yml +++ /dev/null @@ -1,88 +0,0 @@ -parameters: - overrideGuardianVersion: '' - executeAllSdlToolsScript: '' - overrideParameters: '' - additionalParameters: '' - publishGuardianDirectoryToPipeline: false - sdlContinueOnError: false - condition: '' - -steps: -- task: NuGetAuthenticate@1 - inputs: - nuGetServiceConnections: GuardianConnect - -- task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - -- ${{ if ne(parameters.overrideGuardianVersion, '') }}: - - pwsh: | - Set-Location -Path $(Build.SourcesDirectory)\eng\common\sdl - . .\sdl.ps1 - $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts -Version ${{ parameters.overrideGuardianVersion }} - Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" - displayName: Install Guardian (Overridden) - -- ${{ if eq(parameters.overrideGuardianVersion, '') }}: - - pwsh: | - Set-Location -Path $(Build.SourcesDirectory)\eng\common\sdl - . .\sdl.ps1 - $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts - Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" - displayName: Install Guardian - -- ${{ if ne(parameters.overrideParameters, '') }}: - - powershell: ${{ parameters.executeAllSdlToolsScript }} ${{ parameters.overrideParameters }} - displayName: Execute SDL (Overridden) - continueOnError: ${{ parameters.sdlContinueOnError }} - condition: ${{ parameters.condition }} - -- ${{ if eq(parameters.overrideParameters, '') }}: - - powershell: ${{ parameters.executeAllSdlToolsScript }} - -GuardianCliLocation $(GuardianCliLocation) - -NugetPackageDirectory $(Build.SourcesDirectory)\.packages - -AzureDevOpsAccessToken $(dn-bot-dotnet-build-rw-code-rw) - ${{ parameters.additionalParameters }} - displayName: Execute SDL - continueOnError: ${{ parameters.sdlContinueOnError }} - condition: ${{ parameters.condition }} - -- ${{ if ne(parameters.publishGuardianDirectoryToPipeline, 'false') }}: - # We want to publish the Guardian results and configuration for easy diagnosis. However, the - # '.gdn' dir is a mix of configuration, results, extracted dependencies, and Guardian default - # tooling files. Some of these files are large and aren't useful during an investigation, so - # exclude them by simply deleting them before publishing. (As of writing, there is no documented - # way to selectively exclude a dir from the pipeline artifact publish task.) - - task: DeleteFiles@1 - displayName: Delete Guardian dependencies to avoid uploading - inputs: - SourceFolder: $(Agent.BuildDirectory)/.gdn - Contents: | - c - i - condition: succeededOrFailed() - - - publish: $(Agent.BuildDirectory)/.gdn - artifact: GuardianConfiguration - displayName: Publish GuardianConfiguration - condition: succeededOrFailed() - - # Publish the SARIF files in a container named CodeAnalysisLogs to enable integration - # with the "SARIF SAST Scans Tab" Azure DevOps extension - - task: CopyFiles@2 - displayName: Copy SARIF files - inputs: - flattenFolders: true - sourceFolder: $(Agent.BuildDirectory)/.gdn/rc/ - contents: '**/*.sarif' - targetFolder: $(Build.SourcesDirectory)/CodeAnalysisLogs - condition: succeededOrFailed() - - # Use PublishBuildArtifacts because the SARIF extension only checks this case - # see microsoft/sarif-azuredevops-extension#4 - - task: PublishBuildArtifacts@1 - displayName: Publish SARIF files to CodeAnalysisLogs container - inputs: - pathToPublish: $(Build.SourcesDirectory)/CodeAnalysisLogs - artifactName: CodeAnalysisLogs - condition: succeededOrFailed() \ No newline at end of file diff --git a/eng/common/templates/steps/generate-sbom.yml b/eng/common/templates/steps/generate-sbom.yml index a06373f38fa5d5..26dc00a2e0f31e 100644 --- a/eng/common/templates/steps/generate-sbom.yml +++ b/eng/common/templates/steps/generate-sbom.yml @@ -1,48 +1,7 @@ -# BuildDropPath - The root folder of the drop directory for which the manifest file will be generated. -# PackageName - The name of the package this SBOM represents. -# PackageVersion - The version of the package this SBOM represents. -# ManifestDirPath - The path of the directory where the generated manifest files will be placed -# IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. - -parameters: - PackageVersion: 7.0.0 - BuildDropPath: '$(Build.SourcesDirectory)/artifacts' - PackageName: '.NET' - ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom - IgnoreDirectories: '' - sbomContinueOnError: true - steps: -- task: PowerShell@2 - displayName: Prep for SBOM generation in (Non-linux) - condition: or(eq(variables['Agent.Os'], 'Windows_NT'), eq(variables['Agent.Os'], 'Darwin')) - inputs: - filePath: ./eng/common/generate-sbom-prep.ps1 - arguments: ${{parameters.manifestDirPath}} - -# Chmodding is a workaround for https://github.com/dotnet/arcade/issues/8461 -- script: | - chmod +x ./eng/common/generate-sbom-prep.sh - ./eng/common/generate-sbom-prep.sh ${{parameters.manifestDirPath}} - displayName: Prep for SBOM generation in (Linux) - condition: eq(variables['Agent.Os'], 'Linux') - continueOnError: ${{ parameters.sbomContinueOnError }} - -- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 - displayName: 'Generate SBOM manifest' - continueOnError: ${{ parameters.sbomContinueOnError }} - inputs: - PackageName: ${{ parameters.packageName }} - BuildDropPath: ${{ parameters.buildDropPath }} - PackageVersion: ${{ parameters.packageVersion }} - ManifestDirPath: ${{ parameters.manifestDirPath }} - ${{ if ne(parameters.IgnoreDirectories, '') }}: - AdditionalComponentDetectorArgs: '--IgnoreDirectories ${{ parameters.IgnoreDirectories }}' - -- task: PublishPipelineArtifact@1 - displayName: Publish SBOM manifest - continueOnError: ${{parameters.sbomContinueOnError}} - inputs: - targetPath: '${{parameters.manifestDirPath}}' - artifactName: $(ARTIFACT_NAME) +- template: /eng/common/core-templates/steps/generate-sbom.yml + parameters: + is1ESPipeline: false + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/publish-build-artifacts.yml b/eng/common/templates/steps/publish-build-artifacts.yml new file mode 100644 index 00000000000000..6428a98dfef68e --- /dev/null +++ b/eng/common/templates/steps/publish-build-artifacts.yml @@ -0,0 +1,40 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false + +- name: displayName + type: string + default: 'Publish to Build Artifact' + +- name: condition + type: string + default: succeeded() + +- name: artifactName + type: string + +- name: pathToPublish + type: string + +- name: continueOnError + type: boolean + default: false + +- name: publishLocation + type: string + default: 'Container' + +steps: +- ${{ if eq(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates cannot be referenced from a 1ES managed template': error +- task: PublishBuildArtifacts@1 + displayName: ${{ parameters.displayName }} + condition: ${{ parameters.condition }} + ${{ if parameters.continueOnError }}: + continueOnError: ${{ parameters.continueOnError }} + inputs: + PublishLocation: ${{ parameters.publishLocation }} + PathtoPublish: ${{ parameters.pathToPublish }} + ${{ if parameters.artifactName }}: + ArtifactName: ${{ parameters.artifactName }} \ No newline at end of file diff --git a/eng/common/templates/steps/publish-logs.yml b/eng/common/templates/steps/publish-logs.yml index 80861297ddc074..4ea86bd8823555 100644 --- a/eng/common/templates/steps/publish-logs.yml +++ b/eng/common/templates/steps/publish-logs.yml @@ -1,49 +1,7 @@ -parameters: - StageLabel: '' - JobLabel: '' - CustomSensitiveDataList: '' - # A default - in case value from eng/common/templates/post-build/common-variables.yml is not passed - BinlogToolVersion: '1.0.11' - steps: -- task: Powershell@2 - displayName: Prepare Binlogs to Upload - inputs: - targetType: inline - script: | - New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - continueOnError: true - condition: always() - -- task: PowerShell@2 - displayName: Redact Logs - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/redact-logs.ps1 - # For now this needs to have explicit list of all sensitive data. Taken from eng/publishing/v3/publish.yml - # Sensitive data can as well be added to $(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' - # If the file exists - sensitive data for redaction will be sourced from it - # (single entry per line, lines starting with '# ' are considered comments and skipped) - arguments: -InputPath '$(Build.SourcesDirectory)/PostBuildLogs' - -BinlogToolVersion ${{parameters.BinlogToolVersion}} - -TokensFilePath '$(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' - '$(publishing-dnceng-devdiv-code-r-build-re)' - '$(MaestroAccessToken)' - '$(dn-bot-all-orgs-artifact-feeds-rw)' - '$(akams-client-id)' - '$(akams-client-secret)' - '$(microsoft-symbol-server-pat)' - '$(symweb-symbol-server-pat)' - '$(dn-bot-all-orgs-build-rw-code-rw)' - ${{parameters.CustomSensitiveDataList}} - continueOnError: true - condition: always() - -- task: PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/PostBuildLogs' - PublishLocation: Container - ArtifactName: PostBuildLogs - continueOnError: true - condition: always() +- template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/publish-pipeline-artifacts.yml b/eng/common/templates/steps/publish-pipeline-artifacts.yml new file mode 100644 index 00000000000000..88c56354128c06 --- /dev/null +++ b/eng/common/templates/steps/publish-pipeline-artifacts.yml @@ -0,0 +1,34 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false + +- name: args + type: object + default: {} + +steps: +- ${{ if eq(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates cannot be referenced from a 1ES managed template': error +- task: PublishPipelineArtifact@1 + displayName: ${{ coalesce(parameters.args.displayName, 'Publish to Build Artifact') }} + ${{ if parameters.args.condition }}: + condition: ${{ parameters.args.condition }} + ${{ else }}: + condition: succeeded() + ${{ if parameters.args.continueOnError }}: + continueOnError: ${{ parameters.args.continueOnError }} + inputs: + TargetPath: ${{ parameters.args.TargetPath }} + ${{ if parameters.args.ArtifactName }}: + ArtifactName: ${{ parameters.args.ArtifactName }} + ${{ if parameters.args.PublishLocation }}: + PublishLocation: ${{ parameters.args.PublishLocation }} + ${{ if parameters.args.FileSharePath }}: + FileSharePath: ${{ parameters.args.FileSharePath }} + ${{ if parameters.args.Parallel }}: + Parallel: ${{ parameters.args.Parallel }} + ${{ if parameters.args.ParallelCount }}: + ParallelCount: ${{ parameters.args.ParallelCount }} + ${{ if parameters.args.Properties }}: + Properties: ${{ properties.args.Properties }} \ No newline at end of file diff --git a/eng/common/templates/steps/retain-build.yml b/eng/common/templates/steps/retain-build.yml index 83d97a26a01ff9..8e841ace3d293f 100644 --- a/eng/common/templates/steps/retain-build.yml +++ b/eng/common/templates/steps/retain-build.yml @@ -1,28 +1,7 @@ -parameters: - # Optional azure devops PAT with build execute permissions for the build's organization, - # only needed if the build that should be retained ran on a different organization than - # the pipeline where this template is executing from - Token: '' - # Optional BuildId to retain, defaults to the current running build - BuildId: '' - # Azure devops Organization URI for the build in the https://dev.azure.com/ format. - # Defaults to the organization the current pipeline is running on - AzdoOrgUri: '$(System.CollectionUri)' - # Azure devops project for the build. Defaults to the project the current pipeline is running on - AzdoProject: '$(System.TeamProject)' - steps: - - task: powershell@2 - inputs: - targetType: 'filePath' - filePath: eng/common/retain-build.ps1 - pwsh: true - arguments: > - -AzdoOrgUri: ${{parameters.AzdoOrgUri}} - -AzdoProject ${{parameters.AzdoProject}} - -Token ${{coalesce(parameters.Token, '$env:SYSTEM_ACCESSTOKEN') }} - -BuildId ${{coalesce(parameters.BuildId, '$env:BUILD_ID')}} - displayName: Enable permanent build retention - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - BUILD_ID: $(Build.BuildId) \ No newline at end of file +- template: /eng/common/core-templates/steps/retain-build.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/run-on-unix.yml b/eng/common/templates/steps/run-on-unix.yml deleted file mode 100644 index e1733814f65dcc..00000000000000 --- a/eng/common/templates/steps/run-on-unix.yml +++ /dev/null @@ -1,7 +0,0 @@ -parameters: - agentOs: '' - steps: [] - -steps: -- ${{ if ne(parameters.agentOs, 'Windows_NT') }}: - - ${{ parameters.steps }} diff --git a/eng/common/templates/steps/run-on-windows.yml b/eng/common/templates/steps/run-on-windows.yml deleted file mode 100644 index 73e7e9c275a1f1..00000000000000 --- a/eng/common/templates/steps/run-on-windows.yml +++ /dev/null @@ -1,7 +0,0 @@ -parameters: - agentOs: '' - steps: [] - -steps: -- ${{ if eq(parameters.agentOs, 'Windows_NT') }}: - - ${{ parameters.steps }} diff --git a/eng/common/templates/steps/run-script-ifequalelse.yml b/eng/common/templates/steps/run-script-ifequalelse.yml deleted file mode 100644 index 3d1242f5587c82..00000000000000 --- a/eng/common/templates/steps/run-script-ifequalelse.yml +++ /dev/null @@ -1,33 +0,0 @@ -parameters: - # if parameter1 equals parameter 2, run 'ifScript' command, else run 'elsescript' command - parameter1: '' - parameter2: '' - ifScript: '' - elseScript: '' - - # name of script step - name: Script - - # display name of script step - displayName: If-Equal-Else Script - - # environment - env: {} - - # conditional expression for step execution - condition: '' - -steps: -- ${{ if and(ne(parameters.ifScript, ''), eq(parameters.parameter1, parameters.parameter2)) }}: - - script: ${{ parameters.ifScript }} - name: ${{ parameters.name }} - displayName: ${{ parameters.displayName }} - env: ${{ parameters.env }} - condition: ${{ parameters.condition }} - -- ${{ if and(ne(parameters.elseScript, ''), ne(parameters.parameter1, parameters.parameter2)) }}: - - script: ${{ parameters.elseScript }} - name: ${{ parameters.name }} - displayName: ${{ parameters.displayName }} - env: ${{ parameters.env }} - condition: ${{ parameters.condition }} \ No newline at end of file diff --git a/eng/common/templates/steps/send-to-helix.yml b/eng/common/templates/steps/send-to-helix.yml index 68fa739c4ab215..39f99fc2762d01 100644 --- a/eng/common/templates/steps/send-to-helix.yml +++ b/eng/common/templates/steps/send-to-helix.yml @@ -1,93 +1,7 @@ -# Please remember to update the documentation if you make changes to these parameters! -parameters: - HelixSource: 'pr/default' # required -- sources must start with pr/, official/, prodcon/, or agent/ - HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/' - HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number - HelixTargetQueues: '' # required -- semicolon-delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues - HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group - HelixProjectPath: 'eng/common/helixpublish.proj' # optional -- path to the project file to build relative to BUILD_SOURCESDIRECTORY - HelixProjectArguments: '' # optional -- arguments passed to the build command - HelixConfiguration: '' # optional -- additional property attached to a job - HelixPreCommands: '' # optional -- commands to run before Helix work item execution - HelixPostCommands: '' # optional -- commands to run after Helix work item execution - WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects - WorkItemCommand: '' # optional -- a command to execute on the payload; requires WorkItemDirectory; incompatible with XUnitProjects - WorkItemTimeout: '' # optional -- a timeout in TimeSpan.Parse-ready value (e.g. 00:02:00) for the work item command; requires WorkItemDirectory; incompatible with XUnitProjects - CorrelationPayloadDirectory: '' # optional -- a directory to zip up and send to Helix as a correlation payload - XUnitProjects: '' # optional -- semicolon-delimited list of XUnitProjects to parse and send to Helix; requires XUnitRuntimeTargetFramework, XUnitPublishTargetFramework, XUnitRunnerVersion, and IncludeDotNetCli=true - XUnitWorkItemTimeout: '' # optional -- the workitem timeout in seconds for all workitems created from the xUnit projects specified by XUnitProjects - XUnitPublishTargetFramework: '' # optional -- framework to use to publish your xUnit projects - XUnitRuntimeTargetFramework: '' # optional -- framework to use for the xUnit console runner - XUnitRunnerVersion: '' # optional -- version of the xUnit nuget package you wish to use on Helix; required for XUnitProjects - IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion - DotNetCliPackageType: '' # optional -- either 'sdk', 'runtime' or 'aspnetcore-runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." - IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set - HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting https://helix.int-dot.net ) - Creator: '' # optional -- if the build is external, use this to specify who is sending the job - DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO - condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() - continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false - steps: - - powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 $env:BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"' - displayName: ${{ parameters.DisplayNamePrefix }} (Windows) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog - displayName: ${{ parameters.DisplayNamePrefix }} (Unix) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} +- template: /eng/common/core-templates/steps/send-to-helix.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/source-build.yml b/eng/common/templates/steps/source-build.yml index 32738aa938013e..23c1d6f4e9f8d4 100644 --- a/eng/common/templates/steps/source-build.yml +++ b/eng/common/templates/steps/source-build.yml @@ -1,131 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. - - # This is a 'steps' template, and is intended for advanced scenarios where the existing build - # infra has a careful build methodology that must be followed. For example, a repo - # (dotnet/runtime) might choose to clone the GitHub repo only once and store it as a pipeline - # artifact for all subsequent jobs to use, to reduce dependence on a strong network connection to - # GitHub. Using this steps template leaves room for that infra to be included. - - # Defines the platform on which to run the steps. See 'eng/common/templates/job/source-build.yml' - # for details. The entire object is described in the 'job' template for simplicity, even though - # the usage of the properties on this object is split between the 'job' and 'steps' templates. - platform: {} - steps: -# Build. Keep it self-contained for simple reusability. (No source-build-specific job variables.) -- script: | - set -x - df -h - - # If building on the internal project, the artifact feeds variable may be available (usually only if needed) - # In that case, call the feed setup script to add internal feeds corresponding to public ones. - # In addition, add an msbuild argument to copy the WIP from the repo to the target build location. - # This is because SetupNuGetSources.sh will alter the current NuGet.config file, and we need to preserve those - # changes. - internalRestoreArgs= - if [ '$(dn-bot-dnceng-artifact-feeds-rw)' != '$''(dn-bot-dnceng-artifact-feeds-rw)' ]; then - # Temporarily work around https://github.com/dotnet/arcade/issues/7709 - chmod +x $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh - $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh $(Build.SourcesDirectory)/NuGet.config $(dn-bot-dnceng-artifact-feeds-rw) - internalRestoreArgs='/p:CopyWipIntoInnerSourceBuildRepo=true' - - # The 'Copy WIP' feature of source build uses git stash to apply changes from the original repo. - # This only works if there is a username/email configured, which won't be the case in most CI runs. - git config --get user.email - if [ $? -ne 0 ]; then - git config user.email dn-bot@microsoft.com - git config user.name dn-bot - fi - fi - - # If building on the internal project, the internal storage variable may be available (usually only if needed) - # In that case, add variables to allow the download of internal runtimes if the specified versions are not found - # in the default public locations. - internalRuntimeDownloadArgs= - if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then - internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://dotnetbuilds.blob.core.windows.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://dotnetbuilds.blob.core.windows.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' - fi - - buildConfig=Release - # Check if AzDO substitutes in a build config from a variable, and use it if so. - if [ '$(_BuildConfig)' != '$''(_BuildConfig)' ]; then - buildConfig='$(_BuildConfig)' - fi - - officialBuildArgs= - if [ '${{ and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}' = 'True' ]; then - officialBuildArgs='/p:DotNetPublishUsingPipelines=true /p:OfficialBuildId=$(BUILD.BUILDNUMBER)' - fi - - targetRidArgs= - if [ '${{ parameters.platform.targetRID }}' != '' ]; then - targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' - fi - - runtimeOsArgs= - if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then - runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' - fi - - baseOsArgs= - if [ '${{ parameters.platform.baseOS }}' != '' ]; then - baseOsArgs='/p:BaseOS=${{ parameters.platform.baseOS }}' - fi - - publishArgs= - if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then - publishArgs='--publish' - fi - - assetManifestFileName=SourceBuild_RidSpecific.xml - if [ '${{ parameters.platform.name }}' != '' ]; then - assetManifestFileName=SourceBuild_${{ parameters.platform.name }}.xml - fi - - ${{ coalesce(parameters.platform.buildScript, './build.sh') }} --ci \ - --configuration $buildConfig \ - --restore --build --pack $publishArgs -bl \ - $officialBuildArgs \ - $internalRuntimeDownloadArgs \ - $internalRestoreArgs \ - $targetRidArgs \ - $runtimeOsArgs \ - $baseOsArgs \ - /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ - /p:ArcadeBuildFromSource=true \ - /p:DotNetBuildSourceOnly=true \ - /p:DotNetBuildRepo=true \ - /p:AssetManifestFileName=$assetManifestFileName - displayName: Build - -# Upload build logs for diagnosis. -- task: CopyFiles@2 - displayName: Prepare BuildLogs staging directory - inputs: - SourceFolder: '$(Build.SourcesDirectory)' - Contents: | - **/*.log - **/*.binlog - artifacts/sb/prebuilt-report/** - TargetFolder: '$(Build.StagingDirectory)/BuildLogs' - CleanTargetFolder: true - continueOnError: true - condition: succeededOrFailed() - -- task: PublishPipelineArtifact@1 - displayName: Publish BuildLogs - inputs: - targetPath: '$(Build.StagingDirectory)/BuildLogs' - artifactName: BuildLogs_SourceBuild_${{ parameters.platform.name }}_Attempt$(System.JobAttempt) - continueOnError: true - condition: succeededOrFailed() +- template: /eng/common/core-templates/steps/source-build.yml + parameters: + is1ESPipeline: false -# Manually inject component detection so that we can ignore the source build upstream cache, which contains -# a nupkg cache of input packages (a local feed). -# This path must match the upstream cache path in property 'CurrentRepoSourceBuiltNupkgCacheDir' -# in src\Microsoft.DotNet.Arcade.Sdk\tools\SourceBuild\SourceBuildArcade.targets -- task: ComponentGovernanceComponentDetection@0 - displayName: Component Detection (Exclude upstream cache) - inputs: - ignoreDirectories: '$(Build.SourcesDirectory)/artifacts/sb/src/artifacts/obj/source-built-upstream-cache' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/telemetry-end.yml b/eng/common/templates/steps/telemetry-end.yml deleted file mode 100644 index fadc04ca1b9a3e..00000000000000 --- a/eng/common/templates/steps/telemetry-end.yml +++ /dev/null @@ -1,102 +0,0 @@ -parameters: - maxRetries: 5 - retryDelay: 10 # in seconds - -steps: -- bash: | - if [ "$AGENT_JOBSTATUS" = "Succeeded" ] || [ "$AGENT_JOBSTATUS" = "PartiallySucceeded" ]; then - errorCount=0 - else - errorCount=1 - fi - warningCount=0 - - curlStatus=1 - retryCount=0 - # retry loop to harden against spotty telemetry connections - # we don't retry successes and 4xx client errors - until [[ $curlStatus -eq 0 || ( $curlStatus -ge 400 && $curlStatus -le 499 ) || $retryCount -ge $MaxRetries ]] - do - if [ $retryCount -gt 0 ]; then - echo "Failed to send telemetry to Helix; waiting $RetryDelay seconds before retrying..." - sleep $RetryDelay - fi - - # create a temporary file for curl output - res=`mktemp` - - curlResult=` - curl --verbose --output $res --write-out "%{http_code}"\ - -H 'Content-Type: application/json' \ - -H "X-Helix-Job-Token: $Helix_JobToken" \ - -H 'Content-Length: 0' \ - -X POST -G "https://helix.dot.net/api/2018-03-14/telemetry/job/build/$Helix_WorkItemId/finish" \ - --data-urlencode "errorCount=$errorCount" \ - --data-urlencode "warningCount=$warningCount"` - curlStatus=$? - - if [ $curlStatus -eq 0 ]; then - if [ $curlResult -gt 299 ] || [ $curlResult -lt 200 ]; then - curlStatus=$curlResult - fi - fi - - let retryCount++ - done - - if [ $curlStatus -ne 0 ]; then - echo "Failed to Send Build Finish information after $retryCount retries" - vstsLogOutput="vso[task.logissue type=error;sourcepath=templates/steps/telemetry-end.yml;code=1;]Failed to Send Build Finish information: $curlStatus" - echo "##$vstsLogOutput" - exit 1 - fi - displayName: Send Unix Build End Telemetry - env: - # defined via VSTS variables in start-job.sh - Helix_JobToken: $(Helix_JobToken) - Helix_WorkItemId: $(Helix_WorkItemId) - MaxRetries: ${{ parameters.maxRetries }} - RetryDelay: ${{ parameters.retryDelay }} - condition: and(always(), ne(variables['Agent.Os'], 'Windows_NT')) -- powershell: | - if (($env:Agent_JobStatus -eq 'Succeeded') -or ($env:Agent_JobStatus -eq 'PartiallySucceeded')) { - $ErrorCount = 0 - } else { - $ErrorCount = 1 - } - $WarningCount = 0 - - # Basic retry loop to harden against server flakiness - $retryCount = 0 - while ($retryCount -lt $env:MaxRetries) { - try { - Invoke-RestMethod -Uri "https://helix.dot.net/api/2018-03-14/telemetry/job/build/$env:Helix_WorkItemId/finish?errorCount=$ErrorCount&warningCount=$WarningCount" -Method Post -ContentType "application/json" -Body "" ` - -Headers @{ 'X-Helix-Job-Token'=$env:Helix_JobToken } - break - } - catch { - $statusCode = $_.Exception.Response.StatusCode.value__ - if ($statusCode -ge 400 -and $statusCode -le 499) { - Write-Host "##vso[task.logissue]error Failed to send telemetry to Helix (status code $statusCode); not retrying (4xx client error)" - Write-Host "##vso[task.logissue]error ", $_.Exception.GetType().FullName, $_.Exception.Message - exit 1 - } - Write-Host "Failed to send telemetry to Helix (status code $statusCode); waiting $env:RetryDelay seconds before retrying..." - $retryCount++ - sleep $env:RetryDelay - continue - } - } - - if ($retryCount -ge $env:MaxRetries) { - Write-Host "##vso[task.logissue]error Failed to send telemetry to Helix after $retryCount retries." - exit 1 - } - displayName: Send Windows Build End Telemetry - env: - # defined via VSTS variables in start-job.ps1 - Helix_JobToken: $(Helix_JobToken) - Helix_WorkItemId: $(Helix_WorkItemId) - MaxRetries: ${{ parameters.maxRetries }} - RetryDelay: ${{ parameters.retryDelay }} - condition: and(always(),eq(variables['Agent.Os'], 'Windows_NT')) diff --git a/eng/common/templates/steps/telemetry-start.yml b/eng/common/templates/steps/telemetry-start.yml deleted file mode 100644 index 32c01ef0b553b4..00000000000000 --- a/eng/common/templates/steps/telemetry-start.yml +++ /dev/null @@ -1,241 +0,0 @@ -parameters: - helixSource: 'undefined_defaulted_in_telemetry.yml' - helixType: 'undefined_defaulted_in_telemetry.yml' - buildConfig: '' - runAsPublic: false - maxRetries: 5 - retryDelay: 10 # in seconds - -steps: -- ${{ if and(eq(parameters.runAsPublic, 'false'), not(eq(variables['System.TeamProject'], 'public'))) }}: - - task: AzureKeyVault@1 - inputs: - azureSubscription: 'HelixProd_KeyVault' - KeyVaultName: HelixProdKV - SecretsFilter: 'HelixApiAccessToken' - condition: always() -- bash: | - # create a temporary file - jobInfo=`mktemp` - - # write job info content to temporary file - cat > $jobInfo < Date: Sat, 27 Apr 2024 12:22:16 -0700 Subject: [PATCH 154/248] [WASM] Fix third parameter marshaling on callbacks (#101638) * Fix typo with get_signature_arg3_type incrorrecty arg2 instead of arg3 get_signature_arg3_type method is expected to read argument type by Arg3MarshalerType (=28) offset instead of Arg2MarshalerType (=24) * Add another callback tests to cover different parameter types --- .../InteropServices/JavaScript/JSImportTest.cs | 17 +++++++++++++++++ .../JavaScript/JavaScriptTestHelper.cs | 2 ++ .../JavaScript/JavaScriptTestHelper.mjs | 17 ++++++++++++++++- src/mono/browser/runtime/marshal.ts | 2 +- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportTest.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportTest.cs index b4c220519da097..632b27b105c945 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportTest.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportTest.cs @@ -1337,6 +1337,23 @@ public void JsImportCallback_ActionIntLong() Assert.Equal(43, calledB); } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWasmThreadingSupported))] + public void JsImportCallback_ActionIntLongDouble() + { + int calledA = -1; + long calledB = -1; + double calledC = -1; + JavaScriptTestHelper.back4_ActionIntLongDouble((a, b, c) => + { + calledA = a; + calledB = b; + calledC = c; + }, 42, 43, 44.5); + Assert.Equal(42, calledA); + Assert.Equal(43, calledB); + Assert.Equal(44.5, calledC); + } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWasmThreadingSupported))] public void JsImportCallback_ActionIntThrow() { diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs index b2127558a15206..c64be2635a56ec 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs @@ -493,6 +493,8 @@ public static async Task AwaitTaskOfObject([JSMarshalAs] internal static partial int back3_FunctionIntInt([JSMarshalAs>] Func? fun, [JSMarshalAs] int a); + [JSImport("back4", "JavaScriptTestHelper")] + internal static partial void back4_ActionIntLongDouble([JSMarshalAs>] Action? action, [JSMarshalAs] int a, [JSMarshalAs] long b, [JSMarshalAs] double c); [JSImport("invoke1", "JavaScriptTestHelper")] [return: JSMarshalAs>] diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs index e0cf11376d8d34..9d4851575bf34a 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs @@ -383,6 +383,21 @@ export function back3(arg1, arg2, arg3) { } } +export function back4(arg1, arg2, arg3, arg4) { + if (globalThis.gc) { + // console.log('globalThis.gc'); + globalThis.gc(); + } + try { + if (!(arg1 instanceof Function)) throw new Error('expecting Function!') + + return arg1(arg2, arg3, arg4); + } + catch (ex) { + throw ex; + } +} + export function backback(arg1, arg2, arg3) { if (globalThis.gc) { // console.log('globalThis.gc'); @@ -432,4 +447,4 @@ export async function setup() { export function delay(ms) { return new Promise(resolve => globalThis.setTimeout(resolve, ms)); -} \ No newline at end of file +} diff --git a/src/mono/browser/runtime/marshal.ts b/src/mono/browser/runtime/marshal.ts index e49387cc51eef9..b26a94926f88e7 100644 --- a/src/mono/browser/runtime/marshal.ts +++ b/src/mono/browser/runtime/marshal.ts @@ -143,7 +143,7 @@ export function get_signature_arg2_type (sig: JSMarshalerType): MarshalerType { export function get_signature_arg3_type (sig: JSMarshalerType): MarshalerType { mono_assert(sig, "Null sig"); - return getU8(sig + JSBindingTypeOffsets.Arg2MarshalerType); + return getU8(sig + JSBindingTypeOffsets.Arg3MarshalerType); } export function get_signature_argument_count (signature: JSFunctionSignature): number { From b8fe1d0ccb60926d6e7ef5d42e2398c178c9ee5c Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sat, 27 Apr 2024 15:04:08 -0700 Subject: [PATCH 155/248] Revert "Make mutable generic collection interfaces implement read-only collection interfaces (#95830)" (#101644) * Revert "Update ICollection usage to IReadOnlyCollection where applicable (#101469)" This reverts commit e92b7d0074adcdb026408bc862f11ac484edeba8. * Revert "Make mutable generic collection interfaces implement read-only collection interfaces (#95830)" This reverts commit a2bd5830ce09cd81d834afd5571bc6c9e5ad879b. * Update src/coreclr/System.Private.CoreLib/src/System/Array.CoreCLR.cs --- src/coreclr/vm/array.cpp | 19 +- .../System/Diagnostics/DiagnosticsHelper.cs | 8 - .../System/Collections/CollectionAsserts.cs | 152 --------------- .../Collections/ICollection.Generic.Tests.cs | 43 ++--- .../Collections/IDictionary.Generic.Tests.cs | 180 +++--------------- .../System/Collections/IList.Generic.Tests.cs | 75 ++++---- .../System/Collections/ISet.Generic.Tests.cs | 53 +++--- .../Frozen/FrozenSetInternalBase.cs | 12 -- .../Immutable/ImmutableExtensions.Minimal.cs | 2 - .../Collections/Generic/PriorityQueue.cs | 2 +- .../System/Collections/Generic/SortedSet.cs | 2 +- .../Generic/CollectionExtensionsTests.cs | 12 -- .../src/System/Dynamic/ExpandoObject.cs | 32 +--- .../src/System/Linq/ParallelEnumerable.cs | 4 +- .../System.Linq/src/System/Linq/AnyAll.cs | 2 +- .../src/System/Linq/AppendPrepend.SpeedOpt.cs | 4 +- .../System.Linq/src/System/Linq/Count.cs | 4 +- .../System/Linq/DefaultIfEmpty.SpeedOpt.cs | 2 +- .../System.Linq/src/System/Linq/ElementAt.cs | 4 +- .../System.Linq/src/System/Linq/First.cs | 2 +- .../System.Linq/src/System/Linq/Grouping.cs | 17 +- .../System.Linq/src/System/Linq/Last.cs | 4 +- .../System/Linq/OrderedEnumerable.SpeedOpt.cs | 2 +- .../src/System/Linq/Reverse.SpeedOpt.cs | 6 +- .../src/System/Linq/SequenceEqual.cs | 4 +- .../System.Linq/src/System/Linq/Single.cs | 2 +- .../ServiceNameCollection.cs | 2 +- .../Collections/Concurrent/ConcurrentQueue.cs | 2 +- .../System/Collections/Generic/Dictionary.cs | 2 +- .../src/System/Collections/Generic/HashSet.cs | 12 +- .../System/Collections/Generic/ICollection.cs | 6 +- .../System/Collections/Generic/IDictionary.cs | 22 +-- .../src/System/Collections/Generic/IList.cs | 6 +- .../src/System/Collections/Generic/ISet.cs | 35 +--- .../Xml/Xsl/Runtime/XmlQuerySequence.cs | 17 +- .../System.Runtime/ref/System.Runtime.cs | 49 ++--- .../src/System/Text/Json/Nodes/JsonObject.cs | 7 +- 37 files changed, 199 insertions(+), 610 deletions(-) diff --git a/src/coreclr/vm/array.cpp b/src/coreclr/vm/array.cpp index e1e2b31e4df647..ffb6e6def99ce0 100644 --- a/src/coreclr/vm/array.cpp +++ b/src/coreclr/vm/array.cpp @@ -1210,14 +1210,29 @@ MethodDesc* GetActualImplementationForArrayGenericIListOrIReadOnlyListMethod(Met } CONTRACTL_END + int slot = pItfcMeth->GetSlot(); + + // We need to pick the right starting method depending on the depth of the inheritance chain + static const BinderMethodID startingMethod[] = { + METHOD__SZARRAYHELPER__GETENUMERATOR, // First method of IEnumerable`1 + METHOD__SZARRAYHELPER__GET_COUNT, // First method of ICollection`1/IReadOnlyCollection`1 + METHOD__SZARRAYHELPER__GET_ITEM // First method of IList`1/IReadOnlyList`1 + }; + // Subtract one for the non-generic IEnumerable that the generic enumerable inherits from unsigned int inheritanceDepth = pItfcMeth->GetMethodTable()->GetNumInterfaces() - 1; + PREFIX_ASSUME(0 <= inheritanceDepth && inheritanceDepth < ARRAY_SIZE(startingMethod)); + + MethodDesc *pGenericImplementor = CoreLibBinder::GetMethod((BinderMethodID)(startingMethod[inheritanceDepth] + slot)); - MethodDesc *pGenericImplementor = MemberLoader::FindMethodByName(g_pSZArrayHelperClass, pItfcMeth->GetName()); + // The most common reason for this assert is that the order of the SZArrayHelper methods in + // corelib.h does not match the order they are implemented on the generic interfaces. + _ASSERTE(pGenericImplementor == MemberLoader::FindMethodByName(g_pSZArrayHelperClass, pItfcMeth->GetName())); // OPTIMIZATION: For any method other than GetEnumerator(), we can safely substitute // "Object" for reference-type theT's. This causes fewer methods to be instantiated. - if (inheritanceDepth != 0 && !theT.IsValueType()) + if (startingMethod[inheritanceDepth] != METHOD__SZARRAYHELPER__GETENUMERATOR && + !theT.IsValueType()) { theT = TypeHandle(g_pObjectClass); } diff --git a/src/libraries/Common/src/System/Diagnostics/DiagnosticsHelper.cs b/src/libraries/Common/src/System/Diagnostics/DiagnosticsHelper.cs index dcc9de3e4ad654..ce7f345b0ea9cd 100644 --- a/src/libraries/Common/src/System/Diagnostics/DiagnosticsHelper.cs +++ b/src/libraries/Common/src/System/Diagnostics/DiagnosticsHelper.cs @@ -35,22 +35,14 @@ internal static bool CompareTags(List>? sortedTags int size = count / (sizeof(ulong) * 8) + 1; BitMapper bitMapper = new BitMapper(size <= 100 ? stackalloc ulong[size] : new ulong[size]); -#if NET9_0_OR_GREATER // ICollection : IReadOnlyCollection on .NET 9+ - if (tags2 is IReadOnlyCollection> tagsCol) -#else if (tags2 is ICollection> tagsCol) -#endif { if (tagsCol.Count != count) { return false; } -#if NET9_0_OR_GREATER // IList : IReadOnlyList on .NET 9+ - if (tagsCol is IReadOnlyList> secondList) -#else if (tagsCol is IList> secondList) -#endif { for (int i = 0; i < count; i++) { diff --git a/src/libraries/Common/tests/System/Collections/CollectionAsserts.cs b/src/libraries/Common/tests/System/Collections/CollectionAsserts.cs index 1e76d40ebb411f..2de26be1737fdc 100644 --- a/src/libraries/Common/tests/System/Collections/CollectionAsserts.cs +++ b/src/libraries/Common/tests/System/Collections/CollectionAsserts.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; using System.Linq; using Xunit; @@ -10,151 +9,6 @@ namespace System.Collections.Tests { internal static class CollectionAsserts { - public static void HasCount(ICollection collection, int count) - { - Assert.Equal(count, collection.Count); -#if !NETFRAMEWORK - IReadOnlyCollection readOnlyCollection = collection; - Assert.Equal(count, readOnlyCollection.Count); -#endif - } - - public static void EqualAt(IList list, int index, T expected) - { - Assert.Equal(expected, list[index]); -#if !NETFRAMEWORK - IReadOnlyList readOnlyList = list; - Assert.Equal(expected, readOnlyList[index]); -#endif - } - - public static void NotEqualAt(IList list, int index, T expected) - { - Assert.NotEqual(expected, list[index]); -#if !NETFRAMEWORK - IReadOnlyList readOnlyList = list; - Assert.NotEqual(expected, readOnlyList[index]); -#endif - } - - public static void ThrowsElementAt(IList list, int index, Type exceptionType) - { - Assert.Throws(exceptionType, () => list[index]); -#if !NETFRAMEWORK - IReadOnlyList readOnlyList = list; - Assert.Throws(exceptionType, () => readOnlyList[index]); -#endif - } - - public static void ElementAtSucceeds(IList list, int index) - { - T result = list[index]; -#if !NETFRAMEWORK - IReadOnlyList readOnlyList = list; - Assert.Equal(result, readOnlyList[index]); -#endif - } - - public static void EqualAt(IDictionary dictionary, TKey key, TValue expected) - { - Assert.Equal(expected, dictionary[key]); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - Assert.Equal(expected, readOnlyDictionary[key]); -#endif - } - - public static void ContainsKey(IDictionary dictionary, TKey key, bool expected) - { - Assert.Equal(expected, dictionary.ContainsKey(key)); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - Assert.Equal(expected, readOnlyDictionary.ContainsKey(key)); -#endif - } - - public static void TryGetValue(IDictionary dictionary, TKey key, bool expected, TValue expectedValue = default) - { - Assert.Equal(expected, dictionary.TryGetValue(key, out TValue value)); - if (expected) - { - Assert.Equal(expectedValue, value); - } -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - Assert.Equal(expected, readOnlyDictionary.TryGetValue(key, out value)); - if (expected) - { - Assert.Equal(expectedValue, value); - } -#endif - } - - public static void Contains(ISet set, T expected) - { - Assert.True(set.Contains(expected)); -#if !NETFRAMEWORK - ICollection collection = set; - Assert.True(collection.Contains(expected)); - IReadOnlySet readOnlySet = set; - Assert.True(readOnlySet.Contains(expected)); -#endif - } - - public static void IsProperSubsetOf(ISet set, IEnumerable enumerable, bool expected) - { - Assert.Equal(expected, set.IsProperSubsetOf(enumerable)); -#if !NETFRAMEWORK - IReadOnlySet readOnlySet = set; - Assert.Equal(expected, readOnlySet.IsProperSubsetOf(enumerable)); -#endif - } - - public static void IsProperSupersetOf(ISet set, IEnumerable enumerable, bool expected) - { - Assert.Equal(expected, set.IsProperSupersetOf(enumerable)); -#if !NETFRAMEWORK - IReadOnlySet readOnlySet = set; - Assert.Equal(expected, readOnlySet.IsProperSupersetOf(enumerable)); -#endif - } - - public static void IsSubsetOf(ISet set, IEnumerable enumerable, bool expected) - { - Assert.Equal(expected, set.IsSubsetOf(enumerable)); -#if !NETFRAMEWORK - IReadOnlySet readOnlySet = set; - Assert.Equal(expected, readOnlySet.IsSubsetOf(enumerable)); -#endif - } - - public static void IsSupersetOf(ISet set, IEnumerable enumerable, bool expected) - { - Assert.Equal(expected, set.IsSupersetOf(enumerable)); -#if !NETFRAMEWORK - IReadOnlySet readOnlySet = set; - Assert.Equal(expected, readOnlySet.IsSupersetOf(enumerable)); -#endif - } - - public static void Overlaps(ISet set, IEnumerable enumerable, bool expected) - { - Assert.Equal(expected, set.Overlaps(enumerable)); -#if !NETFRAMEWORK - IReadOnlySet readOnlySet = set; - Assert.Equal(expected, readOnlySet.Overlaps(enumerable)); -#endif - } - - public static void SetEquals(ISet set, IEnumerable enumerable, bool expected) - { - Assert.Equal(expected, set.SetEquals(enumerable)); -#if !NETFRAMEWORK - IReadOnlySet readOnlySet = set; - Assert.Equal(expected, readOnlySet.SetEquals(enumerable)); -#endif - } - public static void Equal(ICollection expected, ICollection actual) { Assert.Equal(expected == null, actual == null); @@ -189,12 +43,6 @@ public static void Equal(ICollection expected, ICollection actual) return; } Assert.Equal(expected.Count, actual.Count); -#if !NETFRAMEWORK - IReadOnlyCollection readOnlyExpected = expected; - Assert.Equal(expected.Count, readOnlyExpected.Count); - IReadOnlyCollection readOnlyActual = actual; - Assert.Equal(actual.Count, readOnlyActual.Count); -#endif IEnumerator e = expected.GetEnumerator(); IEnumerator a = actual.GetEnumerator(); while (e.MoveNext()) diff --git a/src/libraries/Common/tests/System/Collections/ICollection.Generic.Tests.cs b/src/libraries/Common/tests/System/Collections/ICollection.Generic.Tests.cs index 8ae72dea074ab0..a94a9308b99ab4 100644 --- a/src/libraries/Common/tests/System/Collections/ICollection.Generic.Tests.cs +++ b/src/libraries/Common/tests/System/Collections/ICollection.Generic.Tests.cs @@ -130,7 +130,7 @@ public void ICollection_Generic_IsReadOnly_Validity(int count) public void ICollection_Generic_Count_Validity(int count) { ICollection collection = GenericICollectionFactory(count); - CollectionAsserts.HasCount(collection, count); + Assert.Equal(count, collection.Count); } #endregion @@ -145,7 +145,7 @@ public virtual void ICollection_Generic_Add_DefaultValue(int count) { ICollection collection = GenericICollectionFactory(count); collection.Add(default(T)); - CollectionAsserts.HasCount(collection, count + 1); + Assert.Equal(count + 1, collection.Count); } } @@ -161,7 +161,7 @@ public void ICollection_Generic_Add_InvalidValueToMiddleOfCollection(int count) collection.Add(invalidValue); for (int i = 0; i < count; i++) collection.Add(CreateT(i)); - CollectionAsserts.HasCount(collection, count * 2); + Assert.Equal(count * 2, collection.Count); }); } } @@ -178,7 +178,7 @@ public void ICollection_Generic_Add_InvalidValueToBeginningOfCollection(int coun collection.Add(invalidValue); for (int i = 0; i < count; i++) collection.Add(CreateT(i)); - CollectionAsserts.HasCount(collection, count); + Assert.Equal(count, collection.Count); }); } } @@ -192,9 +192,8 @@ public void ICollection_Generic_Add_InvalidValueToEndOfCollection(int count) Assert.All(InvalidValues, invalidValue => { ICollection collection = GenericICollectionFactory(count); - collection.Add(invalidValue); - CollectionAsserts.HasCount(collection, count); + Assert.Equal(count, collection.Count); }); } } @@ -209,7 +208,7 @@ public void ICollection_Generic_Add_DuplicateValue(int count) T duplicateValue = CreateT(700); collection.Add(duplicateValue); collection.Add(duplicateValue); - CollectionAsserts.HasCount(collection, count + 2); + Assert.Equal(count + 2, collection.Count); } } @@ -222,7 +221,7 @@ public void ICollection_Generic_Add_AfterCallingClear(int count) ICollection collection = GenericICollectionFactory(count); collection.Clear(); AddToCollection(collection, 5); - CollectionAsserts.HasCount(collection, 5); + Assert.Equal(5, collection.Count); } } @@ -262,7 +261,7 @@ public void ICollection_Generic_Add_AfterRemovingAllItems(int count) for (int i = 0; i < count; i++) collection.Remove(collection.ElementAt(0)); collection.Add(CreateT(254)); - CollectionAsserts.HasCount(collection, 1); + Assert.Equal(1, collection.Count); } } @@ -274,7 +273,7 @@ public void ICollection_Generic_Add_ToReadOnlyCollection(int count) { ICollection collection = GenericICollectionFactory(count); Assert.Throws(() => collection.Add(CreateT(0))); - CollectionAsserts.HasCount(collection, count); + Assert.Equal(count, collection.Count); } } @@ -307,12 +306,12 @@ public void ICollection_Generic_Clear(int count) if (IsReadOnly || AddRemoveClear_ThrowsNotSupported) { Assert.Throws(() => collection.Clear()); - CollectionAsserts.HasCount(collection, count); + Assert.Equal(count, collection.Count); } else { collection.Clear(); - CollectionAsserts.HasCount(collection, 0); + Assert.Equal(0, collection.Count); } } @@ -326,14 +325,14 @@ public void ICollection_Generic_Clear_Repeatedly(int count) Assert.Throws(() => collection.Clear()); Assert.Throws(() => collection.Clear()); Assert.Throws(() => collection.Clear()); - CollectionAsserts.HasCount(collection, count); + Assert.Equal(count, collection.Count); } else { collection.Clear(); collection.Clear(); collection.Clear(); - CollectionAsserts.HasCount(collection, 0); + Assert.Equal(0, collection.Count); } } @@ -435,7 +434,7 @@ public void ICollection_Generic_Contains_ValidValueThatExistsTwiceInTheCollectio T item = CreateT(12); collection.Add(item); collection.Add(item); - CollectionAsserts.HasCount(collection, count + 2); + Assert.Equal(count + 2, collection.Count); } } @@ -568,7 +567,7 @@ public void ICollection_Generic_Remove_DefaultValueNotContainedInCollection(int count--; } Assert.False(collection.Remove(value)); - CollectionAsserts.HasCount(collection, count); + Assert.Equal(count, collection.Count); } } @@ -584,7 +583,7 @@ public void ICollection_Generic_Remove_NonDefaultValueNotContainedInCollection(i while (collection.Contains(value) || Enumerable.Contains(InvalidValues, value)) value = CreateT(seed++); Assert.False(collection.Remove(value)); - CollectionAsserts.HasCount(collection, count); + Assert.Equal(count, collection.Count); } } @@ -603,7 +602,7 @@ public virtual void ICollection_Generic_Remove_DefaultValueContainedInCollection count++; } Assert.True(collection.Remove(value)); - CollectionAsserts.HasCount(collection, count - 1); + Assert.Equal(count - 1, collection.Count); } } @@ -622,7 +621,7 @@ public void ICollection_Generic_Remove_NonDefaultValueContainedInCollection(int count++; } Assert.True(collection.Remove(value)); - CollectionAsserts.HasCount(collection, count - 1); + Assert.Equal(count - 1, collection.Count); } } @@ -640,7 +639,7 @@ public void ICollection_Generic_Remove_ValueThatExistsTwiceInCollection(int coun count += 2; Assert.True(collection.Remove(value)); Assert.True(collection.Contains(value)); - CollectionAsserts.HasCount(collection, count - 1); + Assert.Equal(count - 1, collection.Count); } } @@ -655,7 +654,7 @@ public void ICollection_Generic_Remove_EveryValue(int count) { Assert.True(collection.Remove(value)); }); - CollectionAsserts.HasCount(collection, 0); + Assert.Empty(collection); } } @@ -668,7 +667,7 @@ public void ICollection_Generic_Remove_InvalidValue_ThrowsArgumentException(int { Assert.Throws(() => collection.Remove(value)); }); - CollectionAsserts.HasCount(collection, count); + Assert.Equal(count, collection.Count); } [Theory] diff --git a/src/libraries/Common/tests/System/Collections/IDictionary.Generic.Tests.cs b/src/libraries/Common/tests/System/Collections/IDictionary.Generic.Tests.cs index e6311ec89b4fc1..df92ab206f6686 100644 --- a/src/libraries/Common/tests/System/Collections/IDictionary.Generic.Tests.cs +++ b/src/libraries/Common/tests/System/Collections/IDictionary.Generic.Tests.cs @@ -266,16 +266,12 @@ public void IDictionary_Generic_ItemGet_DefaultKey(int count) if (!DefaultValueAllowed) { Assert.Throws(() => dictionary[default(TKey)]); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - Assert.Throws(() => readOnlyDictionary[default(TKey)]); -#endif } else { TValue value = CreateTValue(3452); dictionary[default(TKey)] = value; - CollectionAsserts.EqualAt(dictionary, default(TKey), value); + Assert.Equal(value, dictionary[default(TKey)]); } } } @@ -287,10 +283,6 @@ public void IDictionary_Generic_ItemGet_MissingNonDefaultKey_ThrowsKeyNotFoundEx IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = GetNewKey(dictionary); Assert.Throws(() => dictionary[missingKey]); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - Assert.Throws(() => readOnlyDictionary[missingKey]); -#endif } [Theory] @@ -304,10 +296,6 @@ public void IDictionary_Generic_ItemGet_MissingDefaultKey_ThrowsKeyNotFoundExcep while (dictionary.ContainsKey(missingKey)) dictionary.Remove(missingKey); Assert.Throws(() => dictionary[missingKey]); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - Assert.Throws(() => readOnlyDictionary[missingKey]); -#endif } } @@ -318,7 +306,7 @@ public void IDictionary_Generic_ItemGet_PresentKeyReturnsCorrectValue(int count) IDictionary dictionary = GenericIDictionaryFactory(count); foreach (KeyValuePair pair in dictionary) { - CollectionAsserts.EqualAt(dictionary, pair.Key, pair.Value); + Assert.Equal(pair.Value, dictionary[pair.Key]); } } @@ -341,7 +329,7 @@ public void IDictionary_Generic_ItemSet_DefaultKey(int count) { TValue value = CreateTValue(3452); dictionary[default(TKey)] = value; - CollectionAsserts.EqualAt(dictionary, default(TKey), value); + Assert.Equal(value, dictionary[default(TKey)]); } } } @@ -367,7 +355,7 @@ public void IDictionary_Generic_ItemSet_AddsNewValueWhenNotPresent(int count) IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = GetNewKey(dictionary); dictionary[missingKey] = CreateTValue(543); - CollectionAsserts.HasCount(dictionary, count + 1); + Assert.Equal(count + 1, dictionary.Count); } } @@ -382,8 +370,8 @@ public void IDictionary_Generic_ItemSet_ReplacesExistingValueWhenPresent(int cou dictionary.Add(existingKey, CreateTValue(5342)); TValue newValue = CreateTValue(1234); dictionary[existingKey] = newValue; - CollectionAsserts.HasCount(dictionary, count + 1); - CollectionAsserts.EqualAt(dictionary, existingKey, newValue); + Assert.Equal(count + 1, dictionary.Count); + Assert.Equal(newValue, dictionary[existingKey]); } } @@ -398,10 +386,6 @@ public void IDictionary_Generic_Keys_ContainsAllCorrectKeys(int count) IDictionary dictionary = GenericIDictionaryFactory(count); IEnumerable expected = dictionary.Select((pair) => pair.Key); Assert.True(expected.SequenceEqual(dictionary.Keys)); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - Assert.True(expected.SequenceEqual(readOnlyDictionary.Keys)); -#endif } [Theory] @@ -412,10 +396,6 @@ public void IDictionary_Generic_Keys_ModifyingTheDictionaryUpdatesTheCollection( { IDictionary dictionary = GenericIDictionaryFactory(count); ICollection keys = dictionary.Keys; -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - IEnumerable readOnlyKeys = readOnlyDictionary.Keys; -#endif int previousCount = keys.Count; if (count > 0) Assert.NotEmpty(keys); @@ -423,16 +403,10 @@ public void IDictionary_Generic_Keys_ModifyingTheDictionaryUpdatesTheCollection( if (IDictionary_Generic_Keys_Values_ModifyingTheDictionaryUpdatesTheCollection) { Assert.Empty(keys); -#if !NETFRAMEWORK - Assert.Empty(readOnlyKeys); -#endif } else { Assert.Equal(previousCount, keys.Count); -#if !NETFRAMEWORK - Assert.Equal(previousCount, readOnlyKeys.Count()); -#endif } } } @@ -446,20 +420,11 @@ public void IDictionary_Generic_Keys_Enumeration_ParentDictionaryModifiedInvalid IDictionary dictionary = GenericIDictionaryFactory(count); ICollection keys = dictionary.Keys; IEnumerator keysEnum = keys.GetEnumerator(); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - IEnumerable readOnlyKeys = readOnlyDictionary.Keys; - IEnumerator readOnlyKeysEnum = readOnlyKeys.GetEnumerator(); -#endif dictionary.Add(GetNewKey(dictionary), CreateTValue(3432)); if (count == 0 ? Enumerator_Empty_ModifiedDuringEnumeration_ThrowsInvalidOperationException : IDictionary_Generic_Keys_Values_Enumeration_ThrowsInvalidOperation_WhenParentModified) { Assert.Throws(() => keysEnum.MoveNext()); Assert.Throws(() => keysEnum.Reset()); -#if !NETFRAMEWORK - Assert.Throws(() => readOnlyKeysEnum.MoveNext()); - Assert.Throws(() => readOnlyKeysEnum.Reset()); -#endif } else { @@ -468,13 +433,6 @@ public void IDictionary_Generic_Keys_Enumeration_ParentDictionaryModifiedInvalid _ = keysEnum.Current; } keysEnum.Reset(); -#if !NETFRAMEWORK - if (readOnlyKeysEnum.MoveNext()) - { - _ = readOnlyKeysEnum.Current; - } - readOnlyKeysEnum.Reset(); -#endif } } } @@ -498,25 +456,10 @@ public void IDictionary_Generic_Keys_Enumeration_Reset(int count) IDictionary dictionary = GenericIDictionaryFactory(count); ICollection keys = dictionary.Keys; IEnumerator enumerator = keys.GetEnumerator(); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - IEnumerable readOnlyKeys = readOnlyDictionary.Keys; - IEnumerator readOnlyEnumerator = readOnlyKeys.GetEnumerator(); -#endif if (IDictionary_Generic_Keys_Values_Enumeration_ResetImplemented) - { enumerator.Reset(); -#if !NETFRAMEWORK - readOnlyEnumerator.Reset(); -#endif - } else - { Assert.Throws(() => enumerator.Reset()); -#if !NETFRAMEWORK - Assert.Throws(() => readOnlyEnumerator.Reset()); -#endif - } } #endregion @@ -530,10 +473,6 @@ public void IDictionary_Generic_Values_ContainsAllCorrectValues(int count) IDictionary dictionary = GenericIDictionaryFactory(count); IEnumerable expected = dictionary.Select((pair) => pair.Value); Assert.True(expected.SequenceEqual(dictionary.Values)); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - Assert.True(expected.SequenceEqual(readOnlyDictionary.Values)); -#endif } [Theory] @@ -552,10 +491,6 @@ public void IDictionary_Generic_Values_IncludeDuplicatesMultipleTimes(int count) dictionary.Add(missingKey, pair.Value); } Assert.Equal(count * 2, dictionary.Values.Count); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - Assert.Equal(count * 2, readOnlyDictionary.Values.Count()); -#endif } } @@ -565,18 +500,9 @@ public void IDictionary_Generic_Values_ModifyingTheDictionaryUpdatesTheCollectio { IDictionary dictionary = GenericIDictionaryFactory(count); ICollection values = dictionary.Values; -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - IEnumerable readOnlyValues = readOnlyDictionary.Values; -#endif int previousCount = values.Count; if (count > 0) - { Assert.NotEmpty(values); -#if !NETFRAMEWORK - Assert.NotEmpty(readOnlyValues); -#endif - } if (!IsReadOnly) { @@ -584,16 +510,10 @@ public void IDictionary_Generic_Values_ModifyingTheDictionaryUpdatesTheCollectio if (IDictionary_Generic_Keys_Values_ModifyingTheDictionaryUpdatesTheCollection) { Assert.Empty(values); -#if !NETFRAMEWORK - Assert.Empty(readOnlyValues); -#endif } else { Assert.Equal(previousCount, values.Count); -#if !NETFRAMEWORK - Assert.Equal(previousCount, readOnlyValues.Count()); -#endif } } } @@ -607,20 +527,11 @@ public void IDictionary_Generic_Values_Enumeration_ParentDictionaryModifiedInval IDictionary dictionary = GenericIDictionaryFactory(count); ICollection values = dictionary.Values; IEnumerator valuesEnum = values.GetEnumerator(); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - IEnumerable readOnlyValues = readOnlyDictionary.Values; - IEnumerator readOnlyValuesEnum = readOnlyValues.GetEnumerator(); -#endif dictionary.Add(GetNewKey(dictionary), CreateTValue(3432)); if (count == 0 ? Enumerator_Empty_ModifiedDuringEnumeration_ThrowsInvalidOperationException : IDictionary_Generic_Keys_Values_Enumeration_ThrowsInvalidOperation_WhenParentModified) { Assert.Throws(() => valuesEnum.MoveNext()); Assert.Throws(() => valuesEnum.Reset()); -#if !NETFRAMEWORK - Assert.Throws(() => readOnlyValuesEnum.MoveNext()); - Assert.Throws(() => readOnlyValuesEnum.Reset()); -#endif } else { @@ -629,13 +540,6 @@ public void IDictionary_Generic_Values_Enumeration_ParentDictionaryModifiedInval _ = valuesEnum.Current; } valuesEnum.Reset(); -#if !NETFRAMEWORK - if (readOnlyValuesEnum.MoveNext()) - { - _ = readOnlyValuesEnum.Current; - } - readOnlyValuesEnum.Reset(); -#endif } } } @@ -659,25 +563,10 @@ public void IDictionary_Generic_Values_Enumeration_Reset(int count) IDictionary dictionary = GenericIDictionaryFactory(count); ICollection values = dictionary.Values; IEnumerator enumerator = values.GetEnumerator(); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - IEnumerable readOnlyValues = readOnlyDictionary.Values; - IEnumerator readOnlyEnumerator = readOnlyValues.GetEnumerator(); -#endif if (IDictionary_Generic_Keys_Values_Enumeration_ResetImplemented) - { enumerator.Reset(); -#if !NETFRAMEWORK - readOnlyEnumerator.Reset(); -#endif - } else - { Assert.Throws(() => enumerator.Reset()); -#if !NETFRAMEWORK - Assert.Throws(() => readOnlyEnumerator.Reset()); -#endif - } } #endregion @@ -705,8 +594,8 @@ public void IDictionary_Generic_Add_DefaultKey_DefaultValue(int count) if (DefaultValueAllowed && !IsReadOnly) { dictionary.Add(missingKey, value); - CollectionAsserts.HasCount(dictionary, count + 1); - CollectionAsserts.EqualAt(dictionary, missingKey, value); + Assert.Equal(count + 1, dictionary.Count); + Assert.Equal(value, dictionary[missingKey]); } else if (!IsReadOnly) { @@ -724,8 +613,8 @@ public void IDictionary_Generic_Add_DefaultKey_NonDefaultValue(int count) if (DefaultValueAllowed && !IsReadOnly) { dictionary.Add(missingKey, value); - CollectionAsserts.HasCount(dictionary, count + 1); - CollectionAsserts.EqualAt(dictionary, missingKey, value); + Assert.Equal(count + 1, dictionary.Count); + Assert.Equal(value, dictionary[missingKey]); } else if (!IsReadOnly) { @@ -743,8 +632,8 @@ public void IDictionary_Generic_Add_NonDefaultKey_DefaultValue(int count) TKey missingKey = GetNewKey(dictionary); TValue value = default(TValue); dictionary.Add(missingKey, value); - CollectionAsserts.HasCount(dictionary, count + 1); - CollectionAsserts.EqualAt(dictionary, missingKey, value); + Assert.Equal(count + 1, dictionary.Count); + Assert.Equal(value, dictionary[missingKey]); } } @@ -758,8 +647,8 @@ public void IDictionary_Generic_Add_NonDefaultKey_NonDefaultValue(int count) TKey missingKey = GetNewKey(dictionary); TValue value = CreateTValue(1342); dictionary.Add(missingKey, value); - CollectionAsserts.HasCount(dictionary, count + 1); - CollectionAsserts.EqualAt(dictionary, missingKey, value); + Assert.Equal(count + 1, dictionary.Count); + Assert.Equal(value, dictionary[missingKey]); } } @@ -777,10 +666,6 @@ public void IDictionary_Generic_Add_DuplicateValue(int count) dictionary.Add(GetNewKey(dictionary), duplicate); dictionary.Add(GetNewKey(dictionary), duplicate); Assert.Equal(2, dictionary.Values.Count((value) => value.Equals(duplicate))); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - Assert.Equal(2, readOnlyDictionary.Values.Count((value) => value.Equals(duplicate))); -#endif } } @@ -807,7 +692,7 @@ public void IDictionary_Generic_Add_DistinctValuesWithHashCollisions(int count) if (dictionary != null) { AddToCollection(dictionary, count); - CollectionAsserts.HasCount(dictionary, count); + Assert.Equal(count, dictionary.Count); } } } @@ -824,7 +709,7 @@ public void IDictionary_Generic_ContainsKey_ValidKeyNotContainedInDictionary(int { IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = GetNewKey(dictionary); - CollectionAsserts.ContainsKey(dictionary, missingKey, false); + Assert.False(dictionary.ContainsKey(missingKey)); } } @@ -837,7 +722,7 @@ public void IDictionary_Generic_ContainsKey_ValidKeyContainedInDictionary(int co IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = GetNewKey(dictionary); dictionary.Add(missingKey, CreateTValue(34251)); - CollectionAsserts.ContainsKey(dictionary, missingKey, true); + Assert.True(dictionary.ContainsKey(missingKey)); } } @@ -854,17 +739,13 @@ public void IDictionary_Generic_ContainsKey_DefaultKeyNotContainedInDictionary(i TKey missingKey = default(TKey); while (dictionary.ContainsKey(missingKey)) dictionary.Remove(missingKey); - CollectionAsserts.ContainsKey(dictionary, missingKey, false); + Assert.False(dictionary.ContainsKey(missingKey)); } } else { // throws ArgumentNullException Assert.Throws(() => dictionary.ContainsKey(default(TKey))); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - Assert.Throws(() => readOnlyDictionary.ContainsKey(default(TKey))); -#endif } } @@ -878,7 +759,7 @@ public void IDictionary_Generic_ContainsKey_DefaultKeyContainedInDictionary(int TKey missingKey = default(TKey); if (!dictionary.ContainsKey(missingKey)) dictionary.Add(missingKey, CreateTValue(5341)); - CollectionAsserts.ContainsKey(dictionary, missingKey, true); + Assert.True(dictionary.ContainsKey(missingKey)); } } @@ -908,7 +789,7 @@ public void IDictionary_Generic_RemoveKey_EveryKey(int count) { Assert.True(dictionary.Remove(key)); }); - CollectionAsserts.HasCount(dictionary, 0); + Assert.Empty(dictionary); } } @@ -921,7 +802,7 @@ public void IDictionary_Generic_RemoveKey_ValidKeyNotContainedInDictionary(int c IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = GetNewKey(dictionary); Assert.False(dictionary.Remove(missingKey)); - CollectionAsserts.HasCount(dictionary, count); + Assert.Equal(count, dictionary.Count); } } @@ -935,7 +816,7 @@ public void IDictionary_Generic_RemoveKey_ValidKeyContainedInDictionary(int coun TKey missingKey = GetNewKey(dictionary); dictionary.Add(missingKey, CreateTValue(34251)); Assert.True(dictionary.Remove(missingKey)); - CollectionAsserts.HasCount(dictionary, count); + Assert.Equal(count, dictionary.Count); } } @@ -1028,7 +909,8 @@ public void IDictionary_Generic_TryGetValue_ValidKeyNotContainedInDictionary(int IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = GetNewKey(dictionary); TValue value = CreateTValue(5123); - CollectionAsserts.TryGetValue(dictionary, missingKey, false); + TValue outValue; + Assert.False(dictionary.TryGetValue(missingKey, out outValue)); } [Theory] @@ -1040,8 +922,10 @@ public void IDictionary_Generic_TryGetValue_ValidKeyContainedInDictionary(int co IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = GetNewKey(dictionary); TValue value = CreateTValue(5123); + TValue outValue; dictionary.TryAdd(missingKey, value); - CollectionAsserts.TryGetValue(dictionary, missingKey, true, value); + Assert.True(dictionary.TryGetValue(missingKey, out outValue)); + Assert.Equal(value, outValue); } } @@ -1058,16 +942,12 @@ public void IDictionary_Generic_TryGetValue_DefaultKeyNotContainedInDictionary(i TKey missingKey = default(TKey); while (dictionary.ContainsKey(missingKey)) dictionary.Remove(missingKey); - CollectionAsserts.TryGetValue(dictionary, missingKey, false); + Assert.False(dictionary.TryGetValue(missingKey, out outValue)); } } else { Assert.Throws(() => dictionary.TryGetValue(default(TKey), out outValue)); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - Assert.Throws(() => readOnlyDictionary.TryGetValue(default(TKey), out outValue)); -#endif } } @@ -1080,8 +960,10 @@ public void IDictionary_Generic_TryGetValue_DefaultKeyContainedInDictionary(int IDictionary dictionary = GenericIDictionaryFactory(count); TKey missingKey = default(TKey); TValue value = CreateTValue(5123); + TValue outValue; dictionary.TryAdd(missingKey, value); - CollectionAsserts.TryGetValue(dictionary, missingKey, true, value); + Assert.True(dictionary.TryGetValue(missingKey, out outValue)); + Assert.Equal(value, outValue); } } diff --git a/src/libraries/Common/tests/System/Collections/IList.Generic.Tests.cs b/src/libraries/Common/tests/System/Collections/IList.Generic.Tests.cs index 6d66f143f18d65..44f67e0ca24f83 100644 --- a/src/libraries/Common/tests/System/Collections/IList.Generic.Tests.cs +++ b/src/libraries/Common/tests/System/Collections/IList.Generic.Tests.cs @@ -103,8 +103,8 @@ protected override IEnumerable GetModifyEnumerables(ModifyOper public void IList_Generic_ItemGet_NegativeIndex_ThrowsException(int count) { IList list = GenericIListFactory(count); - CollectionAsserts.ThrowsElementAt(list, -1, IList_Generic_Item_InvalidIndex_ThrowType); - CollectionAsserts.ThrowsElementAt(list, int.MinValue, IList_Generic_Item_InvalidIndex_ThrowType); + Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[-1]); + Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[int.MinValue]); } [Theory] @@ -112,8 +112,8 @@ public void IList_Generic_ItemGet_NegativeIndex_ThrowsException(int count) public void IList_Generic_ItemGet_IndexGreaterThanListCount_ThrowsException(int count) { IList list = GenericIListFactory(count); - CollectionAsserts.ThrowsElementAt(list, count, IList_Generic_Item_InvalidIndex_ThrowType); - CollectionAsserts.ThrowsElementAt(list, count + 1, IList_Generic_Item_InvalidIndex_ThrowType); + Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[count]); + Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[count + 1]); } [Theory] @@ -121,7 +121,8 @@ public void IList_Generic_ItemGet_IndexGreaterThanListCount_ThrowsException(int public void IList_Generic_ItemGet_ValidGetWithinListBounds(int count) { IList list = GenericIListFactory(count); - Assert.All(Enumerable.Range(0, count), index => CollectionAsserts.ElementAtSucceeds(list, index)); + T result; + Assert.All(Enumerable.Range(0, count), index => result = list[index]); } #endregion @@ -138,7 +139,7 @@ public void IList_Generic_ItemSet_NegativeIndex_ThrowsException(int count) T validAdd = CreateT(0); Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[-1] = validAdd); Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[int.MinValue] = validAdd); - CollectionAsserts.HasCount(list, count); + Assert.Equal(count, list.Count); } } @@ -152,7 +153,7 @@ public void IList_Generic_ItemSet_IndexGreaterThanListCount_ThrowsException(int T validAdd = CreateT(0); Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[count] = validAdd); Assert.Throws(IList_Generic_Item_InvalidIndex_ThrowType, () => list[count + 1] = validAdd); - CollectionAsserts.HasCount(list, count); + Assert.Equal(count, list.Count); } } @@ -165,7 +166,7 @@ public void IList_Generic_ItemSet_OnReadOnlyList(int count) IList list = GenericIListFactory(count); T before = list[count / 2]; Assert.Throws(() => list[count / 2] = CreateT(321432)); - CollectionAsserts.EqualAt(list, count / 2, before); + Assert.Equal(before, list[count / 2]); } } @@ -178,7 +179,7 @@ public void IList_Generic_ItemSet_FirstItemToNonDefaultValue(int count) IList list = GenericIListFactory(count); T value = CreateT(123452); list[0] = value; - CollectionAsserts.EqualAt(list, 0, value); + Assert.Equal(value, list[0]); } } @@ -192,12 +193,12 @@ public void IList_Generic_ItemSet_FirstItemToDefaultValue(int count) if (DefaultValueAllowed) { list[0] = default(T); - CollectionAsserts.EqualAt(list, 0, default(T)); + Assert.Equal(default(T), list[0]); } else { Assert.Throws(() => list[0] = default(T)); - CollectionAsserts.NotEqualAt(list, 0, default(T)); + Assert.NotEqual(default(T), list[0]); } } } @@ -212,7 +213,7 @@ public void IList_Generic_ItemSet_LastItemToNonDefaultValue(int count) T value = CreateT(123452); int lastIndex = count > 0 ? count - 1 : 0; list[lastIndex] = value; - CollectionAsserts.EqualAt(list, lastIndex, value); + Assert.Equal(value, list[lastIndex]); } } @@ -227,12 +228,12 @@ public void IList_Generic_ItemSet_LastItemToDefaultValue(int count) if (DefaultValueAllowed) { list[lastIndex] = default(T); - CollectionAsserts.EqualAt(list, lastIndex, default(T)); + Assert.Equal(default(T), list[lastIndex]); } else { Assert.Throws(() => list[lastIndex] = default(T)); - CollectionAsserts.NotEqualAt(list, lastIndex, default(T)); + Assert.NotEqual(default(T), list[lastIndex]); } } } @@ -247,8 +248,8 @@ public void IList_Generic_ItemSet_DuplicateValues(int count) T value = CreateT(123452); list[0] = value; list[1] = value; - CollectionAsserts.EqualAt(list, 0, value); - CollectionAsserts.EqualAt(list, 1, value); + Assert.Equal(value, list[0]); + Assert.Equal(value, list[1]); } } @@ -395,7 +396,7 @@ public void IList_Generic_Insert_NegativeIndex_ThrowsArgumentOutOfRangeException T validAdd = CreateT(0); Assert.Throws(() => list.Insert(-1, validAdd)); Assert.Throws(() => list.Insert(int.MinValue, validAdd)); - CollectionAsserts.HasCount(list, count); + Assert.Equal(count, list.Count); } } @@ -408,8 +409,8 @@ public void IList_Generic_Insert_IndexGreaterThanListCount_Appends(int count) IList list = GenericIListFactory(count); T validAdd = CreateT(12350); list.Insert(count, validAdd); - CollectionAsserts.HasCount(list, count + 1); - CollectionAsserts.EqualAt(list, count, validAdd); + Assert.Equal(count + 1, list.Count); + Assert.Equal(validAdd, list[count]); } } @@ -421,7 +422,7 @@ public void IList_Generic_Insert_ToReadOnlyList(int count) { IList list = GenericIListFactory(count); Assert.Throws(() => list.Insert(count / 2, CreateT(321432))); - CollectionAsserts.HasCount(list, count); + Assert.Equal(count, list.Count); } } @@ -434,8 +435,8 @@ public void IList_Generic_Insert_FirstItemToNonDefaultValue(int count) IList list = GenericIListFactory(count); T value = CreateT(123452); list.Insert(0, value); - CollectionAsserts.EqualAt(list, 0, value); - CollectionAsserts.HasCount(list, count + 1); + Assert.Equal(value, list[0]); + Assert.Equal(count + 1, list.Count); } } @@ -448,8 +449,8 @@ public void IList_Generic_Insert_FirstItemToDefaultValue(int count) IList list = GenericIListFactory(count); T value = default(T); list.Insert(0, value); - CollectionAsserts.EqualAt(list, 0, value); - CollectionAsserts.HasCount(list, count + 1); + Assert.Equal(value, list[0]); + Assert.Equal(count + 1, list.Count); } } @@ -463,8 +464,8 @@ public void IList_Generic_Insert_LastItemToNonDefaultValue(int count) T value = CreateT(123452); int lastIndex = count > 0 ? count - 1 : 0; list.Insert(lastIndex, value); - CollectionAsserts.EqualAt(list, lastIndex, value); - CollectionAsserts.HasCount(list, count + 1); + Assert.Equal(value, list[lastIndex]); + Assert.Equal(count + 1, list.Count); } } @@ -478,8 +479,8 @@ public void IList_Generic_Insert_LastItemToDefaultValue(int count) T value = default(T); int lastIndex = count > 0 ? count - 1 : 0; list.Insert(lastIndex, value); - CollectionAsserts.EqualAt(list, lastIndex, value); - CollectionAsserts.HasCount(list, count + 1); + Assert.Equal(value, list[lastIndex]); + Assert.Equal(count + 1, list.Count); } } @@ -499,9 +500,9 @@ public void IList_Generic_Insert_DuplicateValues(int count) { list.Insert(0, value); list.Insert(1, value); - CollectionAsserts.EqualAt(list, 0, value); - CollectionAsserts.EqualAt(list, 1, value); - CollectionAsserts.HasCount(list, count + 2); + Assert.Equal(value, list[0]); + Assert.Equal(value, list[1]); + Assert.Equal(count + 2, list.Count); } } } @@ -534,7 +535,7 @@ public void IList_Generic_RemoveAt_NegativeIndex_ThrowsArgumentOutOfRangeExcepti T validAdd = CreateT(0); Assert.Throws(() => list.RemoveAt(-1)); Assert.Throws(() => list.RemoveAt(int.MinValue)); - CollectionAsserts.HasCount(list, count); + Assert.Equal(count, list.Count); } } @@ -548,7 +549,7 @@ public void IList_Generic_RemoveAt_IndexGreaterThanListCount_ThrowsArgumentOutOf T validAdd = CreateT(0); Assert.Throws(() => list.RemoveAt(count)); Assert.Throws(() => list.RemoveAt(count + 1)); - CollectionAsserts.HasCount(list, count); + Assert.Equal(count, list.Count); } } @@ -560,7 +561,7 @@ public void IList_Generic_RemoveAt_OnReadOnlyList(int count) { IList list = GenericIListFactory(count); Assert.Throws(() => list.RemoveAt(count / 2)); - CollectionAsserts.HasCount(list, count); + Assert.Equal(count, list.Count); } } @@ -571,11 +572,11 @@ public void IList_Generic_RemoveAt_AllValidIndices(int count) if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported) { IList list = GenericIListFactory(count); - CollectionAsserts.HasCount(list, count); + Assert.Equal(count, list.Count); Assert.All(Enumerable.Range(0, count).Reverse(), index => { list.RemoveAt(index); - CollectionAsserts.HasCount(list, index); + Assert.Equal(index, list.Count); }); } } @@ -590,7 +591,7 @@ public void IList_Generic_RemoveAt_ZeroMultipleTimes(int count) Assert.All(Enumerable.Range(0, count), index => { list.RemoveAt(0); - CollectionAsserts.HasCount(list, count - index - 1); + Assert.Equal(count - index - 1, list.Count); }); } } diff --git a/src/libraries/Common/tests/System/Collections/ISet.Generic.Tests.cs b/src/libraries/Common/tests/System/Collections/ISet.Generic.Tests.cs index 350faab6f44cb7..303001e8bd1443 100644 --- a/src/libraries/Common/tests/System/Collections/ISet.Generic.Tests.cs +++ b/src/libraries/Common/tests/System/Collections/ISet.Generic.Tests.cs @@ -84,8 +84,8 @@ public void ICollection_Generic_Add_ReturnValue(int count) Assert.True(set.Add(newValue)); if (!DuplicateValuesAllowed) Assert.False(set.Add(newValue)); - CollectionAsserts.HasCount(set, count + 1); - CollectionAsserts.Contains(set, newValue); + Assert.Equal(count + 1, set.Count); + Assert.True(set.Contains(newValue)); } } @@ -104,7 +104,7 @@ public void ICollection_Generic_Add_DuplicateValue_DoesNothing(int count) duplicateValue = CreateT(seed++); collection.Add(duplicateValue); collection.Add(duplicateValue); - CollectionAsserts.HasCount(collection, count + 1); + Assert.Equal(count + 1, collection.Count); } } } @@ -118,7 +118,7 @@ private void Validate_ExceptWith(ISet set, IEnumerable enumerable) if (set.Count == 0 || enumerable == set) { set.ExceptWith(enumerable); - CollectionAsserts.HasCount(set, 0); + Assert.Equal(0, set.Count); } else { @@ -126,7 +126,7 @@ private void Validate_ExceptWith(ISet set, IEnumerable enumerable) foreach (T element in enumerable) expected.Remove(element); set.ExceptWith(enumerable); - CollectionAsserts.HasCount(set, expected.Count); + Assert.Equal(expected.Count, set.Count); Assert.True(expected.SetEquals(set)); } } @@ -136,7 +136,7 @@ private void Validate_IntersectWith(ISet set, IEnumerable enumerable) if (set.Count == 0 || Enumerable.Count(enumerable) == 0) { set.IntersectWith(enumerable); - CollectionAsserts.HasCount(set, 0); + Assert.Equal(0, set.Count); } else if (set == enumerable) { @@ -152,7 +152,7 @@ private void Validate_IntersectWith(ISet set, IEnumerable enumerable) if (enumerable.Contains(value, comparer)) expected.Add(value); set.IntersectWith(enumerable); - CollectionAsserts.HasCount(set, expected.Count); + Assert.Equal(expected.Count, set.Count); Assert.True(expected.SetEquals(set)); } } @@ -178,7 +178,7 @@ private void Validate_IsProperSubsetOf(ISet set, IEnumerable enumerable) break; } } - CollectionAsserts.IsProperSubsetOf(set, enumerable, !setContainsValueNotInEnumerable && enumerableContainsValueNotInSet); + Assert.Equal(!setContainsValueNotInEnumerable && enumerableContainsValueNotInSet, set.IsProperSubsetOf(enumerable)); } private void Validate_IsProperSupersetOf(ISet set, IEnumerable enumerable) @@ -203,7 +203,7 @@ private void Validate_IsProperSupersetOf(ISet set, IEnumerable enumerable) } } isProperSuperset = isProperSuperset && setContainsElementsNotInEnumerable; - CollectionAsserts.IsProperSupersetOf(set, enumerable, isProperSuperset); + Assert.Equal(isProperSuperset, set.IsProperSupersetOf(enumerable)); } private void Validate_IsSubsetOf(ISet set, IEnumerable enumerable) @@ -212,10 +212,10 @@ private void Validate_IsSubsetOf(ISet set, IEnumerable enumerable) foreach (T value in set) if (!enumerable.Contains(value, comparer)) { - CollectionAsserts.IsSubsetOf(set, enumerable, false); + Assert.False(set.IsSubsetOf(enumerable)); return; } - CollectionAsserts.IsSubsetOf(set, enumerable, true); + Assert.True(set.IsSubsetOf(enumerable)); } private void Validate_IsSupersetOf(ISet set, IEnumerable enumerable) @@ -224,10 +224,10 @@ private void Validate_IsSupersetOf(ISet set, IEnumerable enumerable) foreach (T value in enumerable) if (!set.Contains(value, comparer)) { - CollectionAsserts.IsSupersetOf(set, enumerable, false); + Assert.False(set.IsSupersetOf(enumerable)); return; } - CollectionAsserts.IsSupersetOf(set, enumerable, true); + Assert.True(set.IsSupersetOf(enumerable)); } private void Validate_Overlaps(ISet set, IEnumerable enumerable) @@ -237,11 +237,11 @@ private void Validate_Overlaps(ISet set, IEnumerable enumerable) { if (set.Contains(value, comparer)) { - CollectionAsserts.Overlaps(set, enumerable, true); + Assert.True(set.Overlaps(enumerable)); return; } } - CollectionAsserts.Overlaps(set, enumerable, false); + Assert.False(set.Overlaps(enumerable)); } private void Validate_SetEquals(ISet set, IEnumerable enumerable) @@ -251,7 +251,7 @@ private void Validate_SetEquals(ISet set, IEnumerable enumerable) { if (!enumerable.Contains(value, comparer)) { - CollectionAsserts.SetEquals(set, enumerable, false); + Assert.False(set.SetEquals(enumerable)); return; } } @@ -259,11 +259,11 @@ private void Validate_SetEquals(ISet set, IEnumerable enumerable) { if (!set.Contains(value, comparer)) { - CollectionAsserts.SetEquals(set, enumerable, false); + Assert.False(set.SetEquals(enumerable)); return; } } - CollectionAsserts.SetEquals(set, enumerable, true); + Assert.True(set.SetEquals(enumerable)); } private void Validate_SymmetricExceptWith(ISet set, IEnumerable enumerable) @@ -277,7 +277,7 @@ private void Validate_SymmetricExceptWith(ISet set, IEnumerable enumerable if (!enumerable.Contains(element, comparer)) expected.Add(element); set.SymmetricExceptWith(enumerable); - CollectionAsserts.HasCount(set, expected.Count); + Assert.Equal(expected.Count, set.Count); Assert.True(expected.SetEquals(set)); } @@ -289,7 +289,7 @@ private void Validate_UnionWith(ISet set, IEnumerable enumerable) if (!set.Contains(element, comparer)) expected.Add(element); set.UnionWith(enumerable); - CollectionAsserts.HasCount(set, expected.Count); + Assert.Equal(expected.Count, set.Count); Assert.True(expected.SetEquals(set)); } @@ -308,15 +308,6 @@ public void ISet_Generic_NullEnumerableArgument(int count) Assert.Throws(() => set.IsSupersetOf(null)); Assert.Throws(() => set.Overlaps(null)); Assert.Throws(() => set.SetEquals(null)); -#if !NETFRAMEWORK - IReadOnlySet readOnlySet = set; - Assert.Throws(() => readOnlySet.IsProperSubsetOf(null)); - Assert.Throws(() => readOnlySet.IsProperSupersetOf(null)); - Assert.Throws(() => readOnlySet.IsSubsetOf(null)); - Assert.Throws(() => readOnlySet.IsSupersetOf(null)); - Assert.Throws(() => readOnlySet.Overlaps(null)); - Assert.Throws(() => readOnlySet.SetEquals(null)); -#endif if (!IsReadOnly) { Assert.Throws(() => set.ExceptWith(null)); @@ -511,7 +502,7 @@ public void ISet_Generic_Overlaps_Itself(int setLength) public void ISet_Generic_SetEquals_Itself(int setLength) { ISet set = GenericISetFactory(setLength); - CollectionAsserts.SetEquals(set, set, true); + Assert.True(set.SetEquals(set)); } [Theory] @@ -669,7 +660,7 @@ public void ISet_Generic_SymmetricExceptWith_AfterRemovingElements(EnumerableTyp if (!enumerable.Contains(element, comparer)) expected.Add(element); set.SymmetricExceptWith(enumerable); - CollectionAsserts.HasCount(set, expected.Count); + Assert.Equal(expected.Count, set.Count); Assert.True(expected.SetEquals(set)); } } diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenSetInternalBase.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenSetInternalBase.cs index 02e5e0cc07cb25..4afe1f7503e757 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenSetInternalBase.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenSetInternalBase.cs @@ -32,11 +32,7 @@ private protected override bool IsProperSubsetOfCore(IEnumerable other) { Debug.Assert(_thisSet.Count != 0, "EmptyFrozenSet should have been used."); -#if NET9_0_OR_GREATER // ICollection : IReadOnlyCollection on .NET 9+ - if (other is IReadOnlyCollection otherAsCollection) -#else if (other is ICollection otherAsCollection) -#endif { int otherCount = otherAsCollection.Count; @@ -63,11 +59,7 @@ private protected override bool IsProperSupersetOfCore(IEnumerable other) { Debug.Assert(_thisSet.Count != 0, "EmptyFrozenSet should have been used."); -#if NET9_0_OR_GREATER // ICollection : IReadOnlyCollection on .NET 9+ - if (other is IReadOnlyCollection otherAsCollection) -#else if (other is ICollection otherAsCollection) -#endif { int otherCount = otherAsCollection.Count; @@ -111,11 +103,7 @@ private protected override bool IsSupersetOfCore(IEnumerable other) Debug.Assert(_thisSet.Count != 0, "EmptyFrozenSet should have been used."); // Try to compute the answer based purely on counts. -#if NET9_0_OR_GREATER // ICollection : IReadOnlyCollection on .NET 9+ - if (other is IReadOnlyCollection otherAsCollection) -#else if (other is ICollection otherAsCollection) -#endif { int otherCount = otherAsCollection.Count; diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableExtensions.Minimal.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableExtensions.Minimal.cs index dc9c7d26898b7e..66b365bad872b7 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableExtensions.Minimal.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableExtensions.Minimal.cs @@ -38,13 +38,11 @@ internal static bool TryGetCount(this IEnumerable sequence, out int count) return true; } -#if !NET9_0_OR_GREATER // ICollection : IReadOnlyCollection on .NET 9+ if (sequence is ICollection collectionOfT) { count = collectionOfT.Count; return true; } -#endif if (sequence is IReadOnlyCollection readOnlyCollection) { diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs index 072e5ac34d605c..5047b764337389 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs @@ -462,7 +462,7 @@ public void EnqueueRange(IEnumerable elements, TPriority priority) ArgumentNullException.ThrowIfNull(elements); int count; - if (elements is IReadOnlyCollection collection && + if (elements is ICollection collection && (count = collection.Count) > _nodes.Length - _size) { Grow(checked(_size + count)); diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/SortedSet.cs b/src/libraries/System.Collections/src/System/Collections/Generic/SortedSet.cs index fd0beccb28a77d..2f7406d0d7bf4c 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/SortedSet.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/SortedSet.cs @@ -1323,7 +1323,7 @@ public bool Overlaps(IEnumerable other) if (Count == 0) return false; - if (other is IReadOnlyCollection c && c.Count == 0) + if (other is ICollection c && c.Count == 0) return false; SortedSet? asSorted = other as SortedSet; diff --git a/src/libraries/System.Collections/tests/Generic/CollectionExtensionsTests.cs b/src/libraries/System.Collections/tests/Generic/CollectionExtensionsTests.cs index 6a5b458232fc5c..213d9d6faca996 100644 --- a/src/libraries/System.Collections/tests/Generic/CollectionExtensionsTests.cs +++ b/src/libraries/System.Collections/tests/Generic/CollectionExtensionsTests.cs @@ -61,10 +61,6 @@ public void TryAdd_KeyDoesntExistInIDictionary_ReturnsTrue() IDictionary dictionary = new SortedDictionary(); Assert.True(dictionary.TryAdd("key", "value")); Assert.Equal("value", dictionary["key"]); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - Assert.Equal("value", readOnlyDictionary["key"]); -#endif } [Fact] @@ -73,10 +69,6 @@ public void TryAdd_KeyExistsInIDictionary_ReturnsFalse() IDictionary dictionary = new SortedDictionary() { ["key"] = "value" }; Assert.False(dictionary.TryAdd("key", "value2")); Assert.Equal("value", dictionary["key"]); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - Assert.Equal("value", readOnlyDictionary["key"]); -#endif } [Fact] @@ -104,10 +96,6 @@ public void Remove_KeyExistsInIDictionary_ReturnsTrue() Assert.True(dictionary.Remove("key", out var value)); Assert.Equal("value", value); Assert.Throws(() => dictionary["key"]); -#if !NETFRAMEWORK - IReadOnlyDictionary readOnlyDictionary = dictionary; - Assert.Throws(() => readOnlyDictionary["key"]); -#endif } [Fact] diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/ExpandoObject.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/ExpandoObject.cs index 906ee3fd84fc2f..288d01c185dbf5 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/ExpandoObject.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/ExpandoObject.cs @@ -17,7 +17,7 @@ namespace System.Dynamic /// /// Represents an object with members that can be dynamically added and removed at runtime. /// - public sealed class ExpandoObject : IDynamicMetaObjectProvider, IDictionary, IReadOnlyDictionary, INotifyPropertyChanged + public sealed class ExpandoObject : IDynamicMetaObjectProvider, IDictionary, INotifyPropertyChanged { private static readonly MethodInfo s_expandoTryGetValue = typeof(RuntimeOps).GetMethod(nameof(RuntimeOps.ExpandoTryGetValue))!; @@ -618,10 +618,6 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() ICollection IDictionary.Values => new ValueCollection(this); - IEnumerable IReadOnlyDictionary.Keys => new KeyCollection(this); - - IEnumerable IReadOnlyDictionary.Values => new ValueCollection(this); - object? IDictionary.this[string key] { get @@ -640,18 +636,6 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() } } - object? IReadOnlyDictionary.this[string key] - { - get - { - if (!TryGetValueForKey(key, out object? value)) - { - throw System.Linq.Expressions.Error.KeyDoesNotExistInExpando(key); - } - return value; - } - } - void IDictionary.Add(string key, object? value) { this.TryAddMember(key, value); @@ -666,15 +650,6 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() return index >= 0 && data[index] != Uninitialized; } - bool IReadOnlyDictionary.ContainsKey(string key) - { - ArgumentNullException.ThrowIfNull(key); - - ExpandoData data = _data; - int index = data.Class.GetValueIndexCaseSensitive(key); - return index >= 0 && data[index] != Uninitialized; - } - bool IDictionary.Remove(string key) { ArgumentNullException.ThrowIfNull(key); @@ -687,11 +662,6 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() return TryGetValueForKey(key, out value); } - bool IReadOnlyDictionary.TryGetValue(string key, out object? value) - { - return TryGetValueForKey(key, out value); - } - #endregion #region ICollection> Members diff --git a/src/libraries/System.Linq.Parallel/src/System/Linq/ParallelEnumerable.cs b/src/libraries/System.Linq.Parallel/src/System/Linq/ParallelEnumerable.cs index f0885d3d3e7d48..55ef371ea04226 100644 --- a/src/libraries/System.Linq.Parallel/src/System/Linq/ParallelEnumerable.cs +++ b/src/libraries/System.Linq.Parallel/src/System/Linq/ParallelEnumerable.cs @@ -1852,7 +1852,7 @@ public static int Count(this ParallelQuery source) // If the data source is a collection, we can just return the count right away. if (source is ParallelEnumerableWrapper sourceAsWrapper) { - if (sourceAsWrapper.WrappedEnumerable is IReadOnlyCollection sourceAsCollection) + if (sourceAsWrapper.WrappedEnumerable is ICollection sourceAsCollection) { return sourceAsCollection.Count; } @@ -1923,7 +1923,7 @@ public static long LongCount(this ParallelQuery source) // If the data source is a collection, we can just return the count right away. if (source is ParallelEnumerableWrapper sourceAsWrapper) { - if (sourceAsWrapper.WrappedEnumerable is IReadOnlyCollection sourceAsCollection) + if (sourceAsWrapper.WrappedEnumerable is ICollection sourceAsCollection) { return sourceAsCollection.Count; } diff --git a/src/libraries/System.Linq/src/System/Linq/AnyAll.cs b/src/libraries/System.Linq/src/System/Linq/AnyAll.cs index d6d6e4adccdeba..28a3783aa88297 100644 --- a/src/libraries/System.Linq/src/System/Linq/AnyAll.cs +++ b/src/libraries/System.Linq/src/System/Linq/AnyAll.cs @@ -15,7 +15,7 @@ public static bool Any(this IEnumerable source) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } - if (source is IReadOnlyCollection gc) + if (source is ICollection gc) { return gc.Count != 0; } diff --git a/src/libraries/System.Linq/src/System/Linq/AppendPrepend.SpeedOpt.cs b/src/libraries/System.Linq/src/System/Linq/AppendPrepend.SpeedOpt.cs index cd6fb6fa171ad7..01adb0af01e456 100644 --- a/src/libraries/System.Linq/src/System/Linq/AppendPrepend.SpeedOpt.cs +++ b/src/libraries/System.Linq/src/System/Linq/AppendPrepend.SpeedOpt.cs @@ -127,7 +127,7 @@ public override int GetCount(bool onlyIfCheap) return count == -1 ? -1 : count + 1; } - return !onlyIfCheap || _source is IReadOnlyCollection ? _source.Count() + 1 : -1; + return !onlyIfCheap || _source is ICollection ? _source.Count() + 1 : -1; } public override TSource? TryGetFirst(out bool found) @@ -276,7 +276,7 @@ public override int GetCount(bool onlyIfCheap) return count == -1 ? -1 : count + _appendCount + _prependCount; } - return !onlyIfCheap || _source is IReadOnlyCollection ? _source.Count() + _appendCount + _prependCount : -1; + return !onlyIfCheap || _source is ICollection ? _source.Count() + _appendCount + _prependCount : -1; } } } diff --git a/src/libraries/System.Linq/src/System/Linq/Count.cs b/src/libraries/System.Linq/src/System/Linq/Count.cs index 9b2511e0563c5a..6b8819f8c3cbcb 100644 --- a/src/libraries/System.Linq/src/System/Linq/Count.cs +++ b/src/libraries/System.Linq/src/System/Linq/Count.cs @@ -15,7 +15,7 @@ public static int Count(this IEnumerable source) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } - if (source is IReadOnlyCollection collectionoft) + if (source is ICollection collectionoft) { return collectionoft.Count; } @@ -101,7 +101,7 @@ public static bool TryGetNonEnumeratedCount(this IEnumerable s ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } - if (source is IReadOnlyCollection collectionoft) + if (source is ICollection collectionoft) { count = collectionoft.Count; return true; diff --git a/src/libraries/System.Linq/src/System/Linq/DefaultIfEmpty.SpeedOpt.cs b/src/libraries/System.Linq/src/System/Linq/DefaultIfEmpty.SpeedOpt.cs index 45f673f73486ae..c89d6797581e9b 100644 --- a/src/libraries/System.Linq/src/System/Linq/DefaultIfEmpty.SpeedOpt.cs +++ b/src/libraries/System.Linq/src/System/Linq/DefaultIfEmpty.SpeedOpt.cs @@ -30,7 +30,7 @@ public override List ToList() public override int GetCount(bool onlyIfCheap) { int count; - if (!onlyIfCheap || _source is IReadOnlyCollection || _source is ICollection) + if (!onlyIfCheap || _source is ICollection || _source is ICollection) { count = _source.Count(); } diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index 824a152a7764c2..97b87f9eba9999 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs @@ -16,7 +16,7 @@ public static TSource ElementAt(this IEnumerable source, int i ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } - if (source is IReadOnlyList list) + if (source is IList list) { return list[index]; } @@ -115,7 +115,7 @@ public static TSource ElementAt(this IEnumerable source, Index private static TSource? TryGetElementAt(this IEnumerable source, int index, out bool found) { - if (source is IReadOnlyList list) + if (source is IList list) { return (found = (uint)index < (uint)list.Count) ? list[index] : diff --git a/src/libraries/System.Linq/src/System/Linq/First.cs b/src/libraries/System.Linq/src/System/Linq/First.cs index 22532cdb18d13a..74ff81c2fec83b 100644 --- a/src/libraries/System.Linq/src/System/Linq/First.cs +++ b/src/libraries/System.Linq/src/System/Linq/First.cs @@ -78,7 +78,7 @@ public static TSource FirstOrDefault(this IEnumerable source, private static TSource? TryGetFirstNonIterator(IEnumerable source, out bool found) { - if (source is IReadOnlyList list) + if (source is IList list) { if (list.Count > 0) { diff --git a/src/libraries/System.Linq/src/System/Linq/Grouping.cs b/src/libraries/System.Linq/src/System/Linq/Grouping.cs index 47be36572acad0..6e19e4ab384e44 100644 --- a/src/libraries/System.Linq/src/System/Linq/Grouping.cs +++ b/src/libraries/System.Linq/src/System/Linq/Grouping.cs @@ -351,7 +351,7 @@ public interface IGrouping : IEnumerable [DebuggerDisplay("Key = {Key}")] [DebuggerTypeProxy(typeof(SystemLinq_GroupingDebugView<,>))] - internal sealed class Grouping : IGrouping, IList, IReadOnlyList + internal sealed class Grouping : IGrouping, IList { internal readonly TKey _key; internal readonly int _hashCode; @@ -398,8 +398,6 @@ public IEnumerator GetEnumerator() int ICollection.Count => _count; - int IReadOnlyCollection.Count => _count; - bool ICollection.IsReadOnly => true; void ICollection.Add(TElement item) => ThrowHelper.ThrowNotSupportedException(); @@ -433,18 +431,5 @@ TElement IList.this[int index] set => ThrowHelper.ThrowNotSupportedException(); } - - TElement IReadOnlyList.this[int index] - { - get - { - if ((uint)index >= (uint)_count) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - - return _elements[index]; - } - } } } diff --git a/src/libraries/System.Linq/src/System/Linq/Last.cs b/src/libraries/System.Linq/src/System/Linq/Last.cs index e17e409e25e3f7..007ee1659c3f5f 100644 --- a/src/libraries/System.Linq/src/System/Linq/Last.cs +++ b/src/libraries/System.Linq/src/System/Linq/Last.cs @@ -77,7 +77,7 @@ public static TSource LastOrDefault(this IEnumerable source, F private static TSource? TryGetLastNonIterator(IEnumerable source, out bool found) { - if (source is IReadOnlyList list) + if (source is IList list) { int count = list.Count; if (count > 0) @@ -126,7 +126,7 @@ public static TSource LastOrDefault(this IEnumerable source, F return ordered.TryGetLast(predicate, out found); } - if (source is IReadOnlyList list) + if (source is IList list) { for (int i = list.Count - 1; i >= 0; --i) { diff --git a/src/libraries/System.Linq/src/System/Linq/OrderedEnumerable.SpeedOpt.cs b/src/libraries/System.Linq/src/System/Linq/OrderedEnumerable.SpeedOpt.cs index ac9225303b426f..bf65a34b06efa7 100644 --- a/src/libraries/System.Linq/src/System/Linq/OrderedEnumerable.SpeedOpt.cs +++ b/src/libraries/System.Linq/src/System/Linq/OrderedEnumerable.SpeedOpt.cs @@ -58,7 +58,7 @@ public override int GetCount(bool onlyIfCheap) return iterator.GetCount(onlyIfCheap); } - return !onlyIfCheap || _source is IReadOnlyCollection || _source is ICollection ? _source.Count() : -1; + return !onlyIfCheap || _source is ICollection || _source is ICollection ? _source.Count() : -1; } internal TElement[] ToArray(int minIdx, int maxIdx) diff --git a/src/libraries/System.Linq/src/System/Linq/Reverse.SpeedOpt.cs b/src/libraries/System.Linq/src/System/Linq/Reverse.SpeedOpt.cs index 168ca818c96119..d1ec26de879afd 100644 --- a/src/libraries/System.Linq/src/System/Linq/Reverse.SpeedOpt.cs +++ b/src/libraries/System.Linq/src/System/Linq/Reverse.SpeedOpt.cs @@ -30,7 +30,7 @@ public override int GetCount(bool onlyIfCheap) => public override TSource? TryGetElementAt(int index, out bool found) { - if (_source is IReadOnlyList list) + if (_source is IList list) { int count = list.Count; if ((uint)index < (uint)count) @@ -59,7 +59,7 @@ public override int GetCount(bool onlyIfCheap) => { return iterator.TryGetLast(out found); } - else if (_source is IReadOnlyList list) + else if (_source is IList list) { int count = list.Count; if (count > 0) @@ -95,7 +95,7 @@ public override int GetCount(bool onlyIfCheap) => { return iterator.TryGetFirst(out found); } - else if (_source is IReadOnlyList list) + else if (_source is IList list) { if (list.Count > 0) { diff --git a/src/libraries/System.Linq/src/System/Linq/SequenceEqual.cs b/src/libraries/System.Linq/src/System/Linq/SequenceEqual.cs index 2568721f1ce169..16bf60e686145e 100644 --- a/src/libraries/System.Linq/src/System/Linq/SequenceEqual.cs +++ b/src/libraries/System.Linq/src/System/Linq/SequenceEqual.cs @@ -22,7 +22,7 @@ public static bool SequenceEqual(this IEnumerable first, IEnum ThrowHelper.ThrowArgumentNullException(ExceptionArgument.second); } - if (first is IReadOnlyCollection firstCol && second is IReadOnlyCollection secondCol) + if (first is ICollection firstCol && second is ICollection secondCol) { if (first.TryGetSpan(out ReadOnlySpan firstSpan) && second.TryGetSpan(out ReadOnlySpan secondSpan)) { @@ -34,7 +34,7 @@ public static bool SequenceEqual(this IEnumerable first, IEnum return false; } - if (firstCol is IReadOnlyList firstList && secondCol is IReadOnlyList secondList) + if (firstCol is IList firstList && secondCol is IList secondList) { comparer ??= EqualityComparer.Default; diff --git a/src/libraries/System.Linq/src/System/Linq/Single.cs b/src/libraries/System.Linq/src/System/Linq/Single.cs index 78e548e680669f..9c7328cc3ff16e 100644 --- a/src/libraries/System.Linq/src/System/Linq/Single.cs +++ b/src/libraries/System.Linq/src/System/Linq/Single.cs @@ -69,7 +69,7 @@ public static TSource SingleOrDefault(this IEnumerable source, ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } - if (source is IReadOnlyList list) + if (source is IList list) { switch (list.Count) { diff --git a/src/libraries/System.Net.Security/src/System/Security/Authentication/ExtendedProtection/ServiceNameCollection.cs b/src/libraries/System.Net.Security/src/System/Security/Authentication/ExtendedProtection/ServiceNameCollection.cs index 4abe58873916af..532f6e950d6b0d 100644 --- a/src/libraries/System.Net.Security/src/System/Security/Authentication/ExtendedProtection/ServiceNameCollection.cs +++ b/src/libraries/System.Net.Security/src/System/Security/Authentication/ExtendedProtection/ServiceNameCollection.cs @@ -147,7 +147,7 @@ private void AddIfNew(string serviceName) /// private static int GetCountOrOne(IEnumerable collection) { - IReadOnlyCollection? c = collection as IReadOnlyCollection; + ICollection? c = collection as ICollection; return c != null ? c.Count : 1; } 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 2eff1c59b12ec4..bfa9fcf65469ed 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 @@ -89,7 +89,7 @@ public ConcurrentQueue(IEnumerable collection) // case we round its length up to a power of 2, as all segments must // be a power of 2 in length. int length = InitialSegmentLength; - if (collection is IReadOnlyCollection c) + if (collection is ICollection c) { int count = c.Count; if (count > length) 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 f20e3c5cfee211..9b18d4a125ed21 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 @@ -98,7 +98,7 @@ public Dictionary(IDictionary dictionary, IEqualityComparer? public Dictionary(IEnumerable> collection) : this(collection, null) { } public Dictionary(IEnumerable> collection, IEqualityComparer? comparer) : - this((collection as IReadOnlyCollection>)?.Count ?? 0, comparer) + this((collection as ICollection>)?.Count ?? 0, comparer) { if (collection == null) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs index 6467164d6becbc..3b86548d20a7e4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs @@ -99,7 +99,7 @@ public HashSet(IEnumerable collection, IEqualityComparer? comparer) : this { // To avoid excess resizes, first set size based on collection's count. The collection may // contain duplicates, so call TrimExcess if resulting HashSet is larger than the threshold. - if (collection is IReadOnlyCollection coll) + if (collection is ICollection coll) { int count = coll.Count; if (count > 0) @@ -513,7 +513,7 @@ public void IntersectWith(IEnumerable other) } // If other is known to be empty, intersection is empty set; remove all elements, and we're done. - if (other is IReadOnlyCollection otherAsCollection) + if (other is ICollection otherAsCollection) { if (otherAsCollection.Count == 0) { @@ -652,7 +652,7 @@ public bool IsProperSubsetOf(IEnumerable other) return false; } - if (other is IReadOnlyCollection otherAsCollection) + if (other is ICollection otherAsCollection) { // No set is a proper subset of an empty set. if (otherAsCollection.Count == 0) @@ -701,7 +701,7 @@ public bool IsSupersetOf(IEnumerable other) } // Try to fall out early based on counts. - if (other is IReadOnlyCollection otherAsCollection) + if (other is ICollection otherAsCollection) { // If other is the empty set then this is a superset. if (otherAsCollection.Count == 0) @@ -745,7 +745,7 @@ public bool IsProperSupersetOf(IEnumerable other) return false; } - if (other is IReadOnlyCollection otherAsCollection) + if (other is ICollection otherAsCollection) { // If other is the empty set then this is a superset. if (otherAsCollection.Count == 0) @@ -838,7 +838,7 @@ public bool SetEquals(IEnumerable other) { // If this count is 0 but other contains at least one element, they can't be equal. if (Count == 0 && - other is IReadOnlyCollection otherAsCollection && + other is ICollection otherAsCollection && otherAsCollection.Count > 0) { return false; 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 24cf81efb2b440..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 @@ -9,9 +9,9 @@ namespace System.Collections.Generic { // Base interface for all collections, defining enumerators, size, and // synchronization methods. - public interface ICollection : IReadOnlyCollection + public interface ICollection : IEnumerable { - new int Count + int Count { #if MONO [DynamicDependency(nameof(Array.InternalArray__ICollection_get_Count), typeof(Array))] @@ -53,7 +53,5 @@ bool IsReadOnly [DynamicDependency(nameof(Array.InternalArray__ICollection_Remove) + "``1", typeof(Array))] #endif bool Remove(T item); - - int IReadOnlyCollection.Count => Count; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IDictionary.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IDictionary.cs index 7e3e30d8db0929..56a03106c205b6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IDictionary.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IDictionary.cs @@ -9,32 +9,32 @@ namespace System.Collections.Generic // Keys can be any non-null object. Values can be any object. // You can look up a value in an IDictionary via the default indexed // property, Items. - public interface IDictionary : ICollection>, IReadOnlyDictionary + public interface IDictionary : ICollection> { // Interfaces are not serializable // The Item property provides methods to read and edit entries // in the Dictionary. - new TValue this[TKey key] + TValue this[TKey key] { get; set; } // Returns a collections of the keys in this dictionary. - new ICollection Keys + ICollection Keys { get; } // Returns a collections of the values in this dictionary. - new ICollection Values + ICollection Values { get; } // Returns whether this dictionary contains a particular key. // - new bool ContainsKey(TKey key); + bool ContainsKey(TKey key); // Adds a key-value pair to the dictionary. // @@ -44,16 +44,6 @@ public interface IDictionary : ICollection.this[TKey key] => this[key]; - - IEnumerable IReadOnlyDictionary.Keys => Keys; - - IEnumerable IReadOnlyDictionary.Values => Values; - - bool IReadOnlyDictionary.ContainsKey(TKey key) => ContainsKey(key); - - bool IReadOnlyDictionary.TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) => TryGetValue(key, out value); + bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value); } } 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 ec8098c3ff7ea1..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 @@ -10,10 +10,10 @@ namespace System.Collections.Generic // An IList is an ordered collection of objects. The exact ordering // is up to the implementation of the list, ranging from a sorted // order to insertion order. - public interface IList : ICollection, IReadOnlyList + public interface IList : ICollection { // The Item property provides methods to read and edit entries in the List. - new T this[int index] + T this[int index] { #if MONO [DynamicDependency(nameof(Array.InternalArray__get_Item) + "``1", typeof(Array))] @@ -46,7 +46,5 @@ public interface IList : ICollection, IReadOnlyList [DynamicDependency(nameof(Array.InternalArray__RemoveAt), typeof(Array))] #endif void RemoveAt(int index); - - T IReadOnlyList.this[int index] => this[index]; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ISet.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ISet.cs index ce2e8e7c5f4ff1..cee05d198cda07 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ISet.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ISet.cs @@ -8,7 +8,7 @@ namespace System.Collections.Generic /// by some comparer. It also supports basic set operations such as Union, Intersection, /// Complement and Exclusive Complement. /// - public interface ISet : ICollection, IReadOnlySet + public interface ISet : ICollection { //Add ITEM to the set, return true if added, false if duplicate new bool Add(T item); @@ -26,42 +26,21 @@ public interface ISet : ICollection, IReadOnlySet void SymmetricExceptWith(IEnumerable other); //Check if this set is a subset of other - new bool IsSubsetOf(IEnumerable other); + bool IsSubsetOf(IEnumerable other); //Check if this set is a superset of other - new bool IsSupersetOf(IEnumerable other); + bool IsSupersetOf(IEnumerable other); //Check if this set is a subset of other, but not the same as it - new bool IsProperSupersetOf(IEnumerable other); + bool IsProperSupersetOf(IEnumerable other); //Check if this set is a superset of other, but not the same as it - new bool IsProperSubsetOf(IEnumerable other); + bool IsProperSubsetOf(IEnumerable other); //Check if this set has any elements in common with other - new bool Overlaps(IEnumerable other); + bool Overlaps(IEnumerable other); //Check if this set contains the same and only the same elements as other - new bool SetEquals(IEnumerable other); - - /// - /// Determines if the set contains a specific item - /// - /// The item to check if the set contains. - /// if found; otherwise . - new bool Contains(T item) => ((ICollection)this).Contains(item); - - bool IReadOnlySet.IsSubsetOf(IEnumerable other) => IsSubsetOf(other); - - bool IReadOnlySet.IsSupersetOf(IEnumerable other) => IsSupersetOf(other); - - bool IReadOnlySet.IsProperSupersetOf(IEnumerable other) => IsProperSupersetOf(other); - - bool IReadOnlySet.IsProperSubsetOf(IEnumerable other) => IsProperSubsetOf(other); - - bool IReadOnlySet.Overlaps(IEnumerable other) => Overlaps(other); - - bool IReadOnlySet.SetEquals(IEnumerable other) => SetEquals(other); - - bool IReadOnlySet.Contains(T value) => ((ICollection)this).Contains(value); + bool SetEquals(IEnumerable other); } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/XmlQuerySequence.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/XmlQuerySequence.cs index 23fc7a5c2e65a7..3c7e5b6ad25c32 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/XmlQuerySequence.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/XmlQuerySequence.cs @@ -19,7 +19,7 @@ namespace System.Xml.Xsl.Runtime /// A sequence of Xml values that dynamically expands and allows random access to items. /// [EditorBrowsable(EditorBrowsableState.Never)] - public class XmlQuerySequence : IList, IReadOnlyList, System.Collections.IList + public class XmlQuerySequence : IList, System.Collections.IList { public static readonly XmlQuerySequence Empty = new XmlQuerySequence(); @@ -489,7 +489,7 @@ public void AddClone(XPathItem item) /// A sequence of Xml nodes that dynamically expands and allows random access to items. /// [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class XmlQueryNodeSequence : XmlQuerySequence, IList, IReadOnlyList + public sealed class XmlQueryNodeSequence : XmlQuerySequence, IList { public static new readonly XmlQueryNodeSequence Empty = new XmlQueryNodeSequence(); @@ -731,19 +731,6 @@ XPathItem IList.this[int index] set { throw new NotSupportedException(); } } - /// - /// Return item at the specified index. - /// - XPathItem IReadOnlyList.this[int index] - { - get - { - ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(index, Count); - - return base[index]; - } - } - /// /// Returns the index of the specified value in the sequence. /// diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index c2f175247dc9b6..a3f2a4b07e2f48 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -7803,35 +7803,29 @@ public partial interface IAsyncEnumerator : System.IAsyncDisposable T Current { get; } System.Threading.Tasks.ValueTask MoveNextAsync(); } - public partial interface ICollection : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Collections.Generic.IReadOnlyCollection + public partial interface ICollection : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { - new int Count { get; } + int Count { get; } bool IsReadOnly { get; } void Add(T item); void Clear(); bool Contains(T item); void CopyTo(T[] array, int arrayIndex); bool Remove(T item); - int System.Collections.Generic.IReadOnlyCollection.Count => Count; } public partial interface IComparer { int Compare(T? x, T? y); } - public partial interface IDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable, System.Collections.Generic.IReadOnlyDictionary, System.Collections.Generic.IReadOnlyCollection> + public partial interface IDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { - new TValue this[TKey key] { get; set; } - new System.Collections.Generic.ICollection Keys { get; } - new System.Collections.Generic.ICollection Values { get; } + TValue this[TKey key] { get; set; } + System.Collections.Generic.ICollection Keys { get; } + System.Collections.Generic.ICollection Values { get; } void Add(TKey key, TValue value); - new bool ContainsKey(TKey key); + bool ContainsKey(TKey key); bool Remove(TKey key); - new bool TryGetValue(TKey key, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TValue value); - TValue System.Collections.Generic.IReadOnlyDictionary.this[TKey key] => this[key]; - System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Keys => Keys; - System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Values => Values; - bool System.Collections.Generic.IReadOnlyDictionary.ContainsKey(TKey key) => ContainsKey(key); - bool System.Collections.Generic.IReadOnlyDictionary.TryGetValue(TKey key, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TValue value) => TryGetValue(key, out value); + bool TryGetValue(TKey key, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TValue value); } public partial interface IEnumerable : System.Collections.IEnumerable { @@ -7846,13 +7840,12 @@ public partial interface IEqualityComparer bool Equals(T? x, T? y); int GetHashCode([System.Diagnostics.CodeAnalysis.DisallowNullAttribute] T obj); } - public partial interface IList : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.IReadOnlyCollection + public partial interface IList : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { - new T this[int index] { get; set; } + T this[int index] { get; set; } int IndexOf(T item); void Insert(int index, T item); void RemoveAt(int index); - T System.Collections.Generic.IReadOnlyList.this[int index] => this[index]; } public partial interface IReadOnlyCollection : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { @@ -7880,27 +7873,19 @@ public partial interface IReadOnlySet : System.Collections.Generic.IEnumerabl bool Overlaps(System.Collections.Generic.IEnumerable other); bool SetEquals(System.Collections.Generic.IEnumerable other); } - public partial interface ISet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Collections.Generic.IReadOnlySet, System.Collections.Generic.IReadOnlyCollection + public partial interface ISet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { new bool Add(T item); void ExceptWith(System.Collections.Generic.IEnumerable other); void IntersectWith(System.Collections.Generic.IEnumerable other); - new bool IsProperSubsetOf(System.Collections.Generic.IEnumerable other); - new bool IsProperSupersetOf(System.Collections.Generic.IEnumerable other); - new bool IsSubsetOf(System.Collections.Generic.IEnumerable other); - new bool IsSupersetOf(System.Collections.Generic.IEnumerable other); - new bool Overlaps(System.Collections.Generic.IEnumerable other); - new bool SetEquals(System.Collections.Generic.IEnumerable other); + bool IsProperSubsetOf(System.Collections.Generic.IEnumerable other); + bool IsProperSupersetOf(System.Collections.Generic.IEnumerable other); + bool IsSubsetOf(System.Collections.Generic.IEnumerable other); + bool IsSupersetOf(System.Collections.Generic.IEnumerable other); + bool Overlaps(System.Collections.Generic.IEnumerable other); + bool SetEquals(System.Collections.Generic.IEnumerable other); void SymmetricExceptWith(System.Collections.Generic.IEnumerable other); void UnionWith(System.Collections.Generic.IEnumerable other); - new bool Contains(T item) => ((ICollection)this).Contains(item); - bool System.Collections.Generic.IReadOnlySet.Contains(T item) => ((ICollection)this).Contains(item); - bool System.Collections.Generic.IReadOnlySet.IsProperSubsetOf(System.Collections.Generic.IEnumerable other) => IsProperSubsetOf(other); - bool System.Collections.Generic.IReadOnlySet.IsProperSupersetOf(System.Collections.Generic.IEnumerable other) => IsProperSupersetOf(other); - bool System.Collections.Generic.IReadOnlySet.IsSubsetOf(System.Collections.Generic.IEnumerable other) => IsSubsetOf(other); - bool System.Collections.Generic.IReadOnlySet.IsSupersetOf(System.Collections.Generic.IEnumerable other) => IsSupersetOf(other); - bool System.Collections.Generic.IReadOnlySet.Overlaps(System.Collections.Generic.IEnumerable other) => Overlaps(other); - bool System.Collections.Generic.IReadOnlySet.SetEquals(System.Collections.Generic.IEnumerable other) => SetEquals(other); } public partial class KeyNotFoundException : System.SystemException { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonObject.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonObject.cs index 021a4ac75b3c72..24f8653053af76 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonObject.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonObject.cs @@ -35,12 +35,7 @@ public JsonObject(IEnumerable> properties, JsonN { bool isCaseInsensitive = IsCaseInsensitive(options); - JsonPropertyDictionary dictionary = -#if NET9_0_OR_GREATER // ICollection : IReadOnlyCollection on .NET 9+ - properties is IReadOnlyCollection> propertiesCollection -#else - properties is ICollection> propertiesCollection -#endif + JsonPropertyDictionary dictionary = properties is ICollection> propertiesCollection ? new(isCaseInsensitive, propertiesCollection.Count) : new(isCaseInsensitive); From 6313ff8cee86c27aedade4d576f9e56c810cd345 Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Sun, 28 Apr 2024 07:54:10 -0700 Subject: [PATCH 156/248] Update build to `net9.0` images (#101630) * Update build to `net9.0` images * Update docs/workflow/building/coreclr/linux-instructions.md Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> * Revert x86 build change --------- Co-authored-by: Sven Boemer Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> --- .../building/coreclr/linux-instructions.md | 17 +++++++++-------- .../templates/pipeline-with-resources.yml | 10 +++++----- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/workflow/building/coreclr/linux-instructions.md b/docs/workflow/building/coreclr/linux-instructions.md index 8e7457ff521850..518208141e49f6 100644 --- a/docs/workflow/building/coreclr/linux-instructions.md +++ b/docs/workflow/building/coreclr/linux-instructions.md @@ -59,14 +59,15 @@ docker pull mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-ar All official builds are cross-builds with a rootfs for the target OS, and will use the clang version available on the container. | Host OS | Target OS | Target Arch | Image location | crossrootfs location | -| --------------------- | ------------ | --------------- | -------------------------------------------------------------------------------- | -------------------- | -| CBL-mariner 2.0 (x64) | Alpine 3.13 | x64 | `mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-amd64-alpine` | `/crossrootfs/x64` | -| CBL-mariner 2.0 (x64) | Ubuntu 16.04 | x64 | `mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-amd64` | `/crossrootfs/x64` | -| CBL-mariner 2.0 (x64) | Alpine | arm32 (armhf) | `mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-arm-alpine` | `/crossrootfs/arm` | -| CBL-mariner 2.0 (x64) | Ubuntu 16.04 | arm32 (armhf) | `mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-arm` | `/crossrootfs/arm` | -| CBL-mariner 2.0 (x64) | Alpine | arm64 (arm64v8) | `mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-arm64-alpine` | `/crossrootfs/arm64` | -| CBL-mariner 2.0 (x64) | Ubuntu 16.04 | arm64 (arm64v8) | `mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-arm64` | `/crossrootfs/arm64` | -| Ubuntu 18.04 (x64) | FreeBSD | x64 | `mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-cross-freebsd-12` | `/crossrootfs/x64` | +| --------------------- | ------------ | --------------- | -------------------------------------------------------------------------------------- | -------------------- | +| Azure Linux (x64) | Alpine 3.13 | x64 | `mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-amd64-alpine-net9.0` | `/crossrootfs/x64` | +| Azure Linux (x64) | Ubuntu 16.04 | x64 | `mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-amd64-net9.0` | `/crossrootfs/x64` | +| Azure Linux (x64) | Alpine | arm32 (armhf) | `mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-alpine-net9.0` | `/crossrootfs/arm` | +| Azure Linux (x64) | Ubuntu 16.04 | arm32 (armhf) | `mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0` | `/crossrootfs/arm` | +| Azure Linux (x64) | Alpine | arm64 (arm64v8) | `mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm64-alpine-net9.0` | `/crossrootfs/arm64` | +| Azure Linux (x64) | Ubuntu 16.04 | arm64 (arm64v8) | `mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm64-net9.0` | `/crossrootfs/arm64` | +| Azure Linux (x64) | Ubuntu 16.04 | x86 | `mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-x86-net8.0` | `/crossrootfs/x86` | +| CBL-mariner 2.0 (x64) | FreeBSD 13 | x64 | `mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-amd64-freebsd-13` | `/crossrootfs/x64` | These Docker images are built using the Dockerfiles maintained in the [dotnet-buildtools-prereqs-docker repo](https://github.com/dotnet/dotnet-buildtools-prereqs-docker). diff --git a/eng/pipelines/common/templates/pipeline-with-resources.yml b/eng/pipelines/common/templates/pipeline-with-resources.yml index 3c9fc538c4845b..aa7fc3acb1f06d 100644 --- a/eng/pipelines/common/templates/pipeline-with-resources.yml +++ b/eng/pipelines/common/templates/pipeline-with-resources.yml @@ -17,7 +17,7 @@ extends: containers: linux_arm: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net8.0 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0 env: ROOTFS_DIR: /crossrootfs/arm @@ -33,17 +33,17 @@ extends: ROOTFS_DIR: /crossrootfs/arm64 linux_musl_x64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-amd64-alpine-net8.0 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-amd64-alpine-net9.0 env: ROOTFS_DIR: /crossrootfs/x64 linux_musl_arm: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-alpine-net8.0 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-alpine-net9.0 env: ROOTFS_DIR: /crossrootfs/arm linux_musl_arm64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm64-alpine-net8.0 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm64-alpine-net9.0 env: ROOTFS_DIR: /crossrootfs/arm64 @@ -56,7 +56,7 @@ extends: image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-android-docker linux_x64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-amd64-net8.0 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-amd64-net9.0 env: ROOTFS_DIR: /crossrootfs/x64 From c3e5ce97a29317d3dab98d09c310daf11a2260c7 Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Sun, 28 Apr 2024 22:08:05 +0300 Subject: [PATCH 157/248] Fix x86 build with clang-18 (#101650) * Fix x86 build with clang-18 * Suppress Wsync-alignment * Update x86 pipeline to use clang-18 --- eng/pipelines/common/templates/pipeline-with-resources.yml | 2 +- src/coreclr/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/eng/pipelines/common/templates/pipeline-with-resources.yml b/eng/pipelines/common/templates/pipeline-with-resources.yml index aa7fc3acb1f06d..62f8434f8335c0 100644 --- a/eng/pipelines/common/templates/pipeline-with-resources.yml +++ b/eng/pipelines/common/templates/pipeline-with-resources.yml @@ -61,7 +61,7 @@ extends: ROOTFS_DIR: /crossrootfs/x64 linux_x86: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-x86-net8.0 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-x86-net9.0 env: ROOTFS_DIR: /crossrootfs/x86 diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt index aaf4005aa7394b..7ed0d509212cc4 100644 --- a/src/coreclr/CMakeLists.txt +++ b/src/coreclr/CMakeLists.txt @@ -206,6 +206,7 @@ if(CLR_CMAKE_HOST_UNIX) # warnings and errors to be suppressed. # Suppress these warnings here to avoid breaking the build. add_compile_options($<$:-Wno-null-arithmetic>) + add_compile_options($<$:-Wno-sync-alignment>) add_compile_options($<$:-Wno-conversion-null>) add_compile_options($<$:-Wno-pointer-arith>) From 95ed37a5dfaa75ca9ee8ec0b109a583e3ed753b1 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sun, 28 Apr 2024 21:02:54 -0700 Subject: [PATCH 158/248] [main] Update dependencies from dotnet/roslyn (#101330) * Update dependencies from https://github.com/dotnet/roslyn build 20240419.13 Microsoft.SourceBuild.Intermediate.roslyn , Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.CSharp , Microsoft.Net.Compilers.Toolset From Version 4.11.0-1.24219.1 -> To Version 4.11.0-1.24219.13 * Update dependencies from https://github.com/dotnet/roslyn build 20240420.2 Microsoft.SourceBuild.Intermediate.roslyn , Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.CSharp , Microsoft.Net.Compilers.Toolset From Version 4.11.0-1.24219.1 -> To Version 4.11.0-1.24220.2 * Update dependencies from https://github.com/dotnet/roslyn build 20240421.2 Microsoft.SourceBuild.Intermediate.roslyn , Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.CSharp , Microsoft.Net.Compilers.Toolset From Version 4.11.0-1.24219.1 -> To Version 4.11.0-1.24221.2 * Update dependencies from https://github.com/dotnet/roslyn build 20240423.2 Microsoft.SourceBuild.Intermediate.roslyn , Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.CSharp , Microsoft.Net.Compilers.Toolset From Version 4.11.0-1.24219.1 -> To Version 4.11.0-1.24223.2 * Update dependencies from https://github.com/dotnet/roslyn build 20240423.15 Microsoft.SourceBuild.Intermediate.roslyn , Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.CSharp , Microsoft.Net.Compilers.Toolset From Version 4.11.0-1.24219.1 -> To Version 4.11.0-1.24223.15 * Update dependencies from https://github.com/dotnet/roslyn build 20240424.9 Microsoft.SourceBuild.Intermediate.roslyn , Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.CSharp , Microsoft.Net.Compilers.Toolset From Version 4.11.0-1.24219.1 -> To Version 4.11.0-1.24224.9 * Update dependencies from https://github.com/dotnet/roslyn build 20240425.10 Microsoft.SourceBuild.Intermediate.roslyn , Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.CSharp , Microsoft.Net.Compilers.Toolset From Version 4.11.0-1.24219.1 -> To Version 4.11.0-1.24225.10 * Update dependencies from https://github.com/dotnet/roslyn build 20240426.4 Microsoft.SourceBuild.Intermediate.roslyn , Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.CSharp , Microsoft.Net.Compilers.Toolset From Version 4.11.0-1.24219.1 -> To Version 4.11.0-1.24226.4 * Update dependencies from https://github.com/dotnet/roslyn build 20240428.1 Microsoft.SourceBuild.Intermediate.roslyn , Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.CSharp , Microsoft.Net.Compilers.Toolset From Version 4.11.0-1.24219.1 -> To Version 4.11.0-1.24228.1 --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Larry Ewing --- eng/Version.Details.xml | 16 ++++++++-------- eng/Versions.props | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 9bcdac9884a810..029ab74db176f4 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -360,17 +360,17 @@ https://github.com/dotnet/runtime-assets 6e78861f1f307cd9f0e64a45b1d7884fa4470930 - + https://github.com/dotnet/roslyn - 3027ed4a9186a6924722a1597c8d31a59d411f7c + 7a96b1530744f6637ad6bb6bf5b8dfa33ea15b81 - + https://github.com/dotnet/roslyn - 3027ed4a9186a6924722a1597c8d31a59d411f7c + 7a96b1530744f6637ad6bb6bf5b8dfa33ea15b81 - + https://github.com/dotnet/roslyn - 3027ed4a9186a6924722a1597c8d31a59d411f7c + 7a96b1530744f6637ad6bb6bf5b8dfa33ea15b81 https://github.com/dotnet/roslyn-analyzers @@ -381,9 +381,9 @@ b07c100bfc66013a8444172d00cfa04c9ceb5a97 - + https://github.com/dotnet/roslyn - 3027ed4a9186a6924722a1597c8d31a59d411f7c + 7a96b1530744f6637ad6bb6bf5b8dfa33ea15b81 diff --git a/eng/Versions.props b/eng/Versions.props index 0ff857849146a1..25e794136a7ce1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -42,9 +42,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.11.0-1.24219.1 - 4.11.0-1.24219.1 - 4.11.0-1.24219.1 + 4.11.0-1.24228.1 + 4.11.0-1.24228.1 + 4.11.0-1.24228.1 diff --git a/eng/Versions.props b/eng/Versions.props index 25e794136a7ce1..223c05b2560787 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -34,8 +34,8 @@ - 3.11.0-beta1.24216.2 - 9.0.0-preview.24216.2 + 3.11.0-beta1.24225.1 + 9.0.0-preview.24225.1 - + https://github.com/dotnet/runtime - 56610095196ac12a397b1acd00835db4d86849b9 + b8fe1d0ccb60926d6e7ef5d42e2398c178c9ee5c - + https://github.com/dotnet/runtime - 56610095196ac12a397b1acd00835db4d86849b9 + b8fe1d0ccb60926d6e7ef5d42e2398c178c9ee5c - + https://github.com/dotnet/runtime - 56610095196ac12a397b1acd00835db4d86849b9 + b8fe1d0ccb60926d6e7ef5d42e2398c178c9ee5c - + https://github.com/dotnet/runtime - 56610095196ac12a397b1acd00835db4d86849b9 + b8fe1d0ccb60926d6e7ef5d42e2398c178c9ee5c https://github.com/dotnet/xharness diff --git a/eng/Versions.props b/eng/Versions.props index 223c05b2560787..168e86e4e81b2e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -104,10 +104,10 @@ 6.0.0-preview.1.102 - 9.0.0-preview.4.24219.3 + 9.0.0-preview.4.24227.6 6.0.0 - 9.0.0-preview.4.24219.3 + 9.0.0-preview.4.24227.6 6.0.0 1.1.1 @@ -119,19 +119,19 @@ 8.0.0 5.0.0 4.5.5 - 9.0.0-preview.4.24219.3 - 9.0.0-preview.4.24219.3 + 9.0.0-preview.4.24227.6 + 9.0.0-preview.4.24227.6 6.0.0 5.0.0 5.0.0 5.0.0 7.0.0 - 9.0.0-preview.4.24219.3 + 9.0.0-preview.4.24227.6 6.0.0 7.0.0 4.5.4 4.5.0 - 9.0.0-preview.4.24219.3 + 9.0.0-preview.4.24227.6 8.0.0 8.0.0 @@ -210,7 +210,7 @@ 0.11.4-alpha.24222.1 - 9.0.0-preview.4.24219.3 + 9.0.0-preview.4.24227.6 9.0.0-preview.5.24223.2 diff --git a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs index 72779375f4697a..33a86023ced277 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs @@ -29,6 +29,8 @@ namespace System.Reflection { internal partial struct TypeNameParser { + private static readonly TypeNameParseOptions s_typeNameParseOptions = new() { MaxNodes = int.MaxValue }; + private ModuleDesc _module; private bool _throwIfNotFound; private Func _canonResolver; @@ -36,7 +38,7 @@ internal partial struct TypeNameParser public static TypeDesc ResolveType(ModuleDesc module, string name, bool throwIfNotFound, Func canonResolver) { - if (!TypeName.TryParse(name.AsSpan(), out TypeName parsed)) + if (!TypeName.TryParse(name.AsSpan(), out TypeName parsed, s_typeNameParseOptions)) { ThrowHelper.ThrowTypeLoadException(name, module); } diff --git a/src/coreclr/tools/ILVerification/ILVerification.projitems b/src/coreclr/tools/ILVerification/ILVerification.projitems index 3b2c30ddef1f18..c0f3644b1ab343 100644 --- a/src/coreclr/tools/ILVerification/ILVerification.projitems +++ b/src/coreclr/tools/ILVerification/ILVerification.projitems @@ -66,30 +66,6 @@ Utilities\CustomAttributeTypeNameParser.cs - - Utilities\HexConverter.cs - - - Utilities\AssemblyNameFormatter.cs - - - Utilities\AssemblyNameParser.cs - - - Utilities\Metadata\AssemblyNameInfo.cs - - - Utilities\TypeName.cs - - - Utilities\TypeNameParserOptions.cs - - - Utilities\TypeNameParser.cs - - - Utilities\TypeNameParserHelpers.cs - System\Diagnostics\CodeAnalysis\UnconditionalSuppressMessageAttribute.cs diff --git a/src/coreclr/tools/ILVerify/ILVerify.csproj b/src/coreclr/tools/ILVerify/ILVerify.csproj index e1915c65d6f2dd..804f32ddc7bc38 100644 --- a/src/coreclr/tools/ILVerify/ILVerify.csproj +++ b/src/coreclr/tools/ILVerify/ILVerify.csproj @@ -17,6 +17,7 @@ + diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeNameParser.Dataflow.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeNameParser.Dataflow.cs index 5b0cfdb12b4445..278b6c4735afcc 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeNameParser.Dataflow.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeNameParser.Dataflow.cs @@ -9,6 +9,8 @@ namespace System.Reflection { internal partial struct TypeNameParser { + private static readonly TypeNameParseOptions s_typeNameParseOptions = new() { MaxNodes = int.MaxValue }; + private TypeSystemContext _context; private ModuleDesc _callingModule; private List _referencedModules; @@ -17,7 +19,7 @@ internal partial struct TypeNameParser public static TypeDesc ResolveType(string name, ModuleDesc callingModule, TypeSystemContext context, List referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary) { - if (!TypeName.TryParse(name, out TypeName parsed)) + if (!TypeName.TryParse(name, out TypeName parsed, s_typeNameParseOptions)) { typeWasNotFoundInAssemblyNorBaseLibrary = false; return null; diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem/ILCompiler.TypeSystem.csproj b/src/coreclr/tools/aot/ILCompiler.TypeSystem/ILCompiler.TypeSystem.csproj index 23afa3780b1abc..1a5db3b44445da 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem/ILCompiler.TypeSystem.csproj +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem/ILCompiler.TypeSystem.csproj @@ -198,39 +198,12 @@ Utilities\CustomAttributeTypeNameParser.cs - - Utilities\HexConverter.cs - - - Utilities\AssemblyNameFormatter.cs - - - Utilities\AssemblyNameParser.cs - - - Utilities\AssemblyNameInfo.cs - - - Utilities\TypeName.cs - - - Utilities\TypeNameParser.cs - - - Utilities\TypeNameParserHelpers.cs - - - Utilities\TypeNameParserOptions.cs - Utilities\CustomAttributeTypeNameParser.Helpers Utilities\ValueStringBuilder.cs - - Utilities\ValueStringBuilder.AppendSpanFormattable.cs - Utilities\GCPointerMap.Algorithm.cs @@ -741,6 +714,10 @@ + + + + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/libraries/Common/src/System/Reflection/Metadata/AssemblyNameInfo.cs b/src/libraries/Common/src/System/Reflection/Metadata/AssemblyNameInfo.cs index ee586e3b57a8c0..cb4de9467f660b 100644 --- a/src/libraries/Common/src/System/Reflection/Metadata/AssemblyNameInfo.cs +++ b/src/libraries/Common/src/System/Reflection/Metadata/AssemblyNameInfo.cs @@ -21,10 +21,10 @@ namespace System.Reflection.Metadata /// It's a more lightweight, immutable version of that does not pre-allocate instances. /// [DebuggerDisplay("{FullName}")] -#if SYSTEM_PRIVATE_CORELIB - internal -#else +#if SYSTEM_REFLECTION_METADATA public +#else + internal #endif sealed class AssemblyNameInfo { @@ -182,11 +182,7 @@ public AssemblyName ToAssemblyName() public static AssemblyNameInfo Parse(ReadOnlySpan assemblyName) => TryParse(assemblyName, out AssemblyNameInfo? result) ? result! -#if SYSTEM_REFLECTION_METADATA || SYSTEM_PRIVATE_CORELIB : throw new ArgumentException(SR.InvalidAssemblyName, nameof(assemblyName)); -#else // tools that reference this file as a link - : throw new ArgumentException("The given assembly name was invalid.", nameof(assemblyName)); -#endif /// /// Tries to parse a span of characters into an assembly name. diff --git a/src/libraries/Common/src/System/Reflection/Metadata/TypeName.cs b/src/libraries/Common/src/System/Reflection/Metadata/TypeName.cs index 2fac2f8ffd74db..1464f0248280b2 100644 --- a/src/libraries/Common/src/System/Reflection/Metadata/TypeName.cs +++ b/src/libraries/Common/src/System/Reflection/Metadata/TypeName.cs @@ -16,10 +16,10 @@ namespace System.Reflection.Metadata { [DebuggerDisplay("{AssemblyQualifiedName}")] -#if SYSTEM_PRIVATE_CORELIB - internal -#else +#if SYSTEM_REFLECTION_METADATA public +#else + internal #endif sealed class TypeName { diff --git a/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParser.cs b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParser.cs index 7c75f3ee844d6d..dcba442054a5d6 100644 --- a/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParser.cs +++ b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParser.cs @@ -17,7 +17,8 @@ namespace System.Reflection.Metadata [DebuggerDisplay("{_inputString}")] internal ref struct TypeNameParser { - private static readonly TypeNameParseOptions _defaults = new(); + private static readonly TypeNameParseOptions s_defaults = new(); + private readonly bool _throwOnError; private readonly TypeNameParseOptions _parseOptions; private ReadOnlySpan _inputString; @@ -26,7 +27,7 @@ private TypeNameParser(ReadOnlySpan name, bool throwOnError, TypeNameParse { _inputString = name; _throwOnError = throwOnError; - _parseOptions = options ?? _defaults; + _parseOptions = options ?? s_defaults; } internal static TypeName? Parse(ReadOnlySpan typeName, bool throwOnError, TypeNameParseOptions? options = default) @@ -50,7 +51,7 @@ private TypeNameParser(ReadOnlySpan name, bool throwOnError, TypeNameParse { if (throwOnError) { - if (recursiveDepth >= parser._parseOptions.MaxNodes) + if (parser._parseOptions.IsMaxDepthExceeded(recursiveDepth)) { ThrowInvalidOperation_MaxNodesExceeded(parser._parseOptions.MaxNodes); } @@ -249,7 +250,7 @@ private bool TryParseAssemblyName(ref AssemblyNameInfo? assemblyName) private bool TryDive(ref int depth) { - if (depth >= _parseOptions.MaxNodes) + if (_parseOptions.IsMaxDepthExceeded(depth)) { return false; } diff --git a/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserHelpers.cs b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserHelpers.cs index 3783f56c73d4b7..1cdc5e230ad96a 100644 --- a/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserHelpers.cs +++ b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserHelpers.cs @@ -331,53 +331,64 @@ internal static bool TryStripFirstCharAndTrailingSpaces(ref ReadOnlySpan s } [DoesNotReturn] - internal static void ThrowInvalidOperation_MaxNodesExceeded(int limit) => throw -#if SYSTEM_REFLECTION_METADATA - new InvalidOperationException(SR.Format(SR.InvalidOperation_MaxNodesExceeded, limit)); -#else // corelib and tools that reference this file as a link - new InvalidOperationException(); -#endif + internal static void ThrowArgumentException_InvalidTypeName(int errorIndex) + { + throw new ArgumentException(SR.Argument_InvalidTypeName, $"typeName@{errorIndex}"); + } [DoesNotReturn] - internal static void ThrowArgumentException_InvalidTypeName(int errorIndex) => throw -#if SYSTEM_PRIVATE_CORELIB - new ArgumentException(SR.Arg_ArgumentException, $"typeName@{errorIndex}"); -#elif SYSTEM_REFLECTION_METADATA - new ArgumentException(SR.Argument_InvalidTypeName, $"typeName@{errorIndex}"); -#else // tools that reference this file as a link - new ArgumentException(); + internal static void ThrowInvalidOperation_MaxNodesExceeded(int limit) + { +#if SYSTEM_REFLECTION_METADATA + throw new InvalidOperationException(SR.Format(SR.InvalidOperation_MaxNodesExceeded, limit)); +#else + Debug.Fail("Expected to be unreachable"); + throw new InvalidOperationException(); #endif + } [DoesNotReturn] - internal static void ThrowInvalidOperation_NotGenericType() => throw -#if SYSTEM_REFLECTION_METADATA || SYSTEM_PRIVATE_CORELIB - new InvalidOperationException(SR.InvalidOperation_NotGenericType); -#else // tools that reference this file as a link - new InvalidOperationException(); + internal static void ThrowInvalidOperation_NotGenericType() + { +#if SYSTEM_REFLECTION_METADATA + throw new InvalidOperationException(SR.InvalidOperation_NotGenericType); +#else + Debug.Fail("Expected to be unreachable"); + throw new InvalidOperationException(); #endif + } [DoesNotReturn] - internal static void ThrowInvalidOperation_NotNestedType() => throw + internal static void ThrowInvalidOperation_NotNestedType() + { #if SYSTEM_REFLECTION_METADATA - new InvalidOperationException(SR.InvalidOperation_NotNestedType); -#else // corelib and tools that reference this file as a link - new InvalidOperationException(); + throw new InvalidOperationException(SR.InvalidOperation_NotNestedType); +#else + Debug.Fail("Expected to be unreachable"); + throw new InvalidOperationException(); #endif + } [DoesNotReturn] - internal static void ThrowInvalidOperation_NoElement() => throw + internal static void ThrowInvalidOperation_NoElement() + { #if SYSTEM_REFLECTION_METADATA - new InvalidOperationException(SR.InvalidOperation_NoElement); -#else // corelib and tools that reference this file as a link - new InvalidOperationException(); + throw new InvalidOperationException(SR.InvalidOperation_NoElement); +#else + Debug.Fail("Expected to be unreachable"); + throw new InvalidOperationException(); #endif + } [DoesNotReturn] - internal static void ThrowInvalidOperation_HasToBeArrayClass() => throw -#if SYSTEM_REFLECTION_METADATA || SYSTEM_PRIVATE_CORELIB - new InvalidOperationException(SR.Argument_HasToBeArrayClass); -#else // tools that reference this file as a link - new InvalidOperationException(); + internal static void ThrowInvalidOperation_HasToBeArrayClass() + { +#if SYSTEM_REFLECTION_METADATA + throw new InvalidOperationException(SR.Argument_HasToBeArrayClass); +#else + Debug.Fail("Expected to be unreachable"); + throw new InvalidOperationException(); #endif + } } } diff --git a/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserOptions.cs b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserOptions.cs index 66350c9a44cac7..551876e73147c9 100644 --- a/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserOptions.cs +++ b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserOptions.cs @@ -3,19 +3,9 @@ namespace System.Reflection.Metadata { -#if SYSTEM_PRIVATE_CORELIB - internal -#else - public -#endif - sealed class TypeNameParseOptions + public sealed class TypeNameParseOptions { - private int _maxNodes = -#if SYSTEM_PRIVATE_CORELIB - int.MaxValue; // CoreLib has never introduced any limits -#else - 20; -#endif + private int _maxNodes = 20; /// /// Limits the maximum value of node count that parser can handle. @@ -37,5 +27,7 @@ public int MaxNodes _maxNodes = value; } } + + internal bool IsMaxDepthExceeded(int depth) => depth >= _maxNodes; } } diff --git a/src/libraries/Common/src/System/Reflection/TypeNameParser.Helpers.cs b/src/libraries/Common/src/System/Reflection/TypeNameParser.Helpers.cs index bcb2125d3f4ea3..84ef2137fb095b 100644 --- a/src/libraries/Common/src/System/Reflection/TypeNameParser.Helpers.cs +++ b/src/libraries/Common/src/System/Reflection/TypeNameParser.Helpers.cs @@ -8,6 +8,28 @@ #nullable enable +#if SYSTEM_PRIVATE_CORELIB +namespace System.Reflection.Metadata +{ + internal struct TypeNameParseOptions + { + public TypeNameParseOptions() { } +#pragma warning disable CA1822 // Mark members as static + // CoreLib does not enforce any limits + public bool IsMaxDepthExceeded(int _) => false; + public int MaxNodes + { + get + { + Debug.Fail("Expected to be unreachable"); + return 0; + } + } +#pragma warning restore CA1822 + } +} +#endif + namespace System.Reflection { internal partial struct TypeNameParser 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 fccffa63fa159e..f1b61a1ea67c4b 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 @@ -1424,6 +1424,9 @@ Common\System\LocalAppContextSwitches.Common.cs + + Common\System\HexConverter.cs + Common\System\HResults.cs @@ -1493,9 +1496,6 @@ Common\System\Reflection\Metadata\TypeNameParserHelpers.cs - - Common\System\Reflection\Metadata\TypeNameParserOptions.cs - Common\System\Runtime\Versioning\NonVersionableAttribute.cs @@ -1599,11 +1599,6 @@ - - - Common\System\HexConverter.cs - - Common\Interop\Windows\Advapi32\Interop.EncryptDecrypt.cs From f88ab88f4ce02569f84922cda802317e69682d8a Mon Sep 17 00:00:00 2001 From: Qiao Pengcheng Date: Mon, 29 Apr 2024 16:40:51 +0800 Subject: [PATCH 162/248] fixed the split error for LoongArch64. (#101656) * fixed the split error for LoongArch64. * amend code for CRs. * amend the splitting's judge independent of the `var->lvIsSplit` which will be delete in future. --- src/coreclr/jit/abi.cpp | 4 +++ src/coreclr/jit/codegencommon.cpp | 55 ++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/coreclr/jit/abi.cpp b/src/coreclr/jit/abi.cpp index 7a594f77f39121..7fa39d04644342 100644 --- a/src/coreclr/jit/abi.cpp +++ b/src/coreclr/jit/abi.cpp @@ -259,13 +259,17 @@ bool ABIPassingInformation::HasExactlyOneStackSegment() const bool ABIPassingInformation::IsSplitAcrossRegistersAndStack() const { if (NumSegments < 2) + { return false; + } bool isFirstInReg = Segments[0].IsPassedInRegister(); for (unsigned i = 1; i < NumSegments; i++) { if (isFirstInReg != Segments[i].IsPassedInRegister()) + { return true; + } } return false; } diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index c3608402d27ec2..301b10b1de0717 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -4119,7 +4119,7 @@ void CodeGen::genEnregisterOSRArgsAndLocals() } } -#if defined(SWIFT_SUPPORT) || defined(TARGET_RISCV64) +#if defined(SWIFT_SUPPORT) || defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) //----------------------------------------------------------------------------- // genHomeSwiftStructParameters: Move the incoming segment to the local stack frame. // @@ -4159,8 +4159,16 @@ void CodeGen::genHomeStackSegment(unsigned lclNum, } emitAttr size = emitTypeSize(loadType); - int loadOffset = - -(isFramePointerUsed() ? genCallerSPtoFPdelta() : genCallerSPtoInitialSPdelta()) + (int)seg.GetStackOffset(); + int loadOffset = (int)seg.GetStackOffset(); + if (isFramePointerUsed()) + { + loadOffset -= genCallerSPtoFPdelta(); + } + else + { + loadOffset -= genCallerSPtoInitialSPdelta(); + } + #ifdef TARGET_XARCH GetEmitter()->emitIns_R_AR(ins_Load(loadType), size, initReg, genFramePointerReg(), loadOffset); #else @@ -4171,7 +4179,7 @@ void CodeGen::genHomeStackSegment(unsigned lclNum, if (initRegStillZeroed) *initRegStillZeroed = false; } -#endif // defined(SWIFT_SUPPORT) || defined(TARGET_RISCV64) +#endif // defined(SWIFT_SUPPORT) || defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) #ifdef SWIFT_SUPPORT @@ -4248,32 +4256,41 @@ void CodeGen::genHomeSwiftStructParameters(bool handleStack) // void CodeGen::genHomeStackPartOfSplitParameter(regNumber initReg, bool* initRegStillZeroed) { -#ifdef TARGET_RISCV64 +#if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) unsigned lclNum = 0; for (; lclNum < compiler->info.compArgsCount; lclNum++) { LclVarDsc* var = compiler->lvaGetDesc(lclNum); - if (!var->lvIsSplit || !var->lvOnFrame) + if (!var->lvOnFrame || !varTypeIsStruct(var)) + { continue; + } - JITDUMP("Homing stack part of split parameter V%02u\n", lclNum); - - assert(varTypeIsStruct(var)); - assert(!compiler->lvaIsImplicitByRefLocal(lclNum)); const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(lclNum); - assert(abiInfo.NumSegments == 2); - assert(abiInfo.Segments[0].GetRegister() == REG_ARG_LAST); - const ABIPassingSegment& seg = abiInfo.Segments[1]; + if (abiInfo.IsSplitAcrossRegistersAndStack()) + { + assert(var->lvIsSplit); + JITDUMP("Homing stack part of split parameter V%02u\n", lclNum); - genHomeStackSegment(lclNum, seg, initReg, initRegStillZeroed); + assert(abiInfo.NumSegments == 2); + assert(abiInfo.Segments[0].GetRegister() == REG_ARG_LAST); + assert(abiInfo.Segments[1].GetStackOffset() == 0); + const ABIPassingSegment& seg = abiInfo.Segments[1]; - for (lclNum += 1; lclNum < compiler->info.compArgsCount; lclNum++) - { - assert(!compiler->lvaGetDesc(lclNum)->lvIsSplit); // There should be only one split parameter + genHomeStackSegment(lclNum, seg, initReg, initRegStillZeroed); + +#ifdef DEBUG + for (lclNum += 1; lclNum < compiler->info.compArgsCount; lclNum++) + { + const ABIPassingInformation& abiInfo2 = compiler->lvaGetParameterABIInfo(lclNum); + // There should be only one split parameter + assert(!abiInfo2.IsSplitAcrossRegistersAndStack()); + } +#endif + break; } - break; } -#endif +#endif // TARGET_RISCV64 || TARGET_LOONGARCH64 } /*----------------------------------------------------------------------------- From 9b4c5c6ad69dc6cc4fbbc584d63d4f836766efdc Mon Sep 17 00:00:00 2001 From: Eric StJohn Date: Mon, 29 Apr 2024 08:46:53 -0700 Subject: [PATCH 163/248] Prefer most derived member in Configuration Binder source generator (#101316) * Prefer most derived member in Configuration Binder source generator * Skip overridden properties in config source generator - include only definitions --- .../ConfigurationBindingGenerator.Parser.cs | 6 ++ .../ConfigurationBinderTests.TestClasses.cs | 59 ++++++++++++++++++ .../tests/Common/ConfigurationBinderTests.cs | 62 +++++++++++++++++++ 3 files changed, 127 insertions(+) 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 a569be384367eb..cb39cd788cfd7d 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs @@ -660,6 +660,12 @@ private ObjectSpec CreateObjectSpec(TypeParseInfo typeParseInfo) if (member is IPropertySymbol { IsIndexer: false, IsImplicitlyDeclared: false } property && !IsUnsupportedType(property.Type)) { string propertyName = property.Name; + + if (property.IsOverride || properties?.ContainsKey(propertyName) is true) + { + continue; + } + TypeRef propertyTypeRef = EnqueueTransitiveType(typeParseInfo, property.Type, DiagnosticDescriptors.PropertyNotSupported, propertyName); AttributeData? attributeData = property.GetAttributes().FirstOrDefault(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, _typeSymbols.ConfigurationKeyNameAttribute)); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.cs index 9aad9566463aff..02f3a74f317b1a 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 @@ -930,5 +930,64 @@ public class SimplePoco public string B { get; set; } } + public class BaseForHiddenMembers + { + public string A { get; set; } + public string B { get; set; } + public TestSettingsEnum E {get; set;} + + public virtual string C { get => CBase; set => CBase = value; } + + public string CBase; + + public virtual string D { get; } + + public virtual string F { get => FBase; set => FBase = value; } + public string FBase; + + + public virtual int X { get => XBase; set => XBase = value; } + public int XBase; + } + + public enum TestSettingsEnum2 + { + // Note - the reflection binder will try to bind to every member + Option1 = TestSettingsEnum.Option1, + Option2 = TestSettingsEnum.Option2, + } + + public class IntermediateDerivedClass : BaseForHiddenMembers + { + public new virtual string D { get => DBase; set => DBase = value; } + public string DBase; + + public override string F { get => "IF"; } + + } + + public class DerivedClassWithHiddenMembers : IntermediateDerivedClass + { + public new string A { get; } = "ADerived"; + public new int B { get; set; } + public new TestSettingsEnum2 E + { + get => (TestSettingsEnum2)base.E; + set => base.E = (TestSettingsEnum)value; + } + + // only override get + public override string C { get => "DC"; } + + // override new only get + public override string D { get => "DD"; } + + // two overrides of only get + public override string F { get => "DF"; } + + // override only set + public override int X { set => base.X = value + 1; } + } + } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs index 7b0a8ca7e7e385..95585b76239237 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs @@ -2471,5 +2471,67 @@ public MockConfigurationRoot(IList providers) : base(pro IConfigurationSection IConfiguration.GetSection(string key) => this[key] is null ? null : new ConfigurationSection(this, key); } + + [Fact] + public void CanBindToClassWithNewProperties() + { + /// the source generator will bind to the most derived property only. + /// the reflection binder will bind the same data to all properties (including hidden). + + var config = TestHelpers.GetConfigurationFromJsonString(""" + { + "A": "AVal", + "B": "5", + "C": "CVal", + "D": "DVal", + "E": "Option2", + "F": "FVal", + "X": "52" + } + """); + var obj = new DerivedClassWithHiddenMembers(); + + config.Bind(obj); + + BaseForHiddenMembers baseObj = obj; + IntermediateDerivedClass intermediateObj = obj; + + Assert.Equal("ADerived", obj.A); +#if BUILDING_SOURCE_GENERATOR_TESTS + // source generator will not set hidden property + Assert.Null(baseObj.A); +#else + // reflection binder will set hidden property + Assert.Equal("AVal", baseObj.A); +#endif + + Assert.Equal(5, obj.B); +#if BUILDING_SOURCE_GENERATOR_TESTS + // source generator will not set hidden property + Assert.Null(baseObj.B); +#else + // reflection binder will set hidden property + Assert.Equal("5", baseObj.B); +#endif + + Assert.Equal(TestSettingsEnum2.Option2, obj.E); + Assert.Equal(TestSettingsEnum.Option2, baseObj.E); + + Assert.Equal("DC", obj.C); + // The setter should still be called, even when only getter is overridden. + Assert.Equal("CVal", obj.CBase); + + // can hide a readonly property with r/w property + Assert.Null(baseObj.D); + Assert.Equal("DD", obj.D); + // The setter should still be called, even when only getter is overridden. + Assert.Equal("DVal", obj.DBase); + + Assert.Equal("DF", obj.F); + Assert.Equal("FVal", obj.FBase); + + Assert.Equal(53, obj.X); + Assert.Equal(53, obj.XBase); + } } } From 92ca5f3227ada3f1620cd9b0ea631491303e4148 Mon Sep 17 00:00:00 2001 From: Keith Dahlby Date: Mon, 29 Apr 2024 10:49:01 -0500 Subject: [PATCH 164/248] Annotate `config.GetValue()` with `[NotNullIfNotNull]` (#101336) * Annotate GetValue() with [NotNullIfNotNull] * Avoid duplicate NullableAttributes.cs * Annotate generated GetValue() with [NotNullIfNotNull] --- src/libraries/Directory.Build.targets | 1 + .../ConfigurationBindingGenerator.Emitter.cs | 2 ++ .../ConfigurationBindingGenerator.Parser.cs | 1 + .../gen/Emitter/ConfigurationBinder.cs | 10 ++++++++ .../gen/Parser/KnownTypeSymbols.cs | 4 +++ .../gen/Specs/SourceGenerationSpec.cs | 1 + ...crosoft.Extensions.Configuration.Binder.cs | 2 ++ .../src/ConfigurationBinder.cs | 2 ++ .../tests/Common/ConfigurationBinderTests.cs | 25 ++++++++++++++----- .../GetValue.generated.txt | 2 ++ .../GetValue_T_Key_DefaultValue.generated.txt | 1 + ...alue_TypeOf_Key_DefaultValue.generated.txt | 1 + ...ation.Binder.SourceGeneration.Tests.csproj | 3 +++ 13 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/libraries/Directory.Build.targets b/src/libraries/Directory.Build.targets index e3d599b2d8276a..5a3fff449e7bba 100644 --- a/src/libraries/Directory.Build.targets +++ b/src/libraries/Directory.Build.targets @@ -170,6 +170,7 @@ 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 d8c5a8925b46b2..1dceb31a0cc8aa 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs @@ -15,6 +15,7 @@ private sealed partial class Emitter private readonly TypeIndex _typeIndex; private readonly bool _emitEnumParseMethod; private readonly bool _emitGenericParseEnum; + private readonly bool _emitNotNullIfNotNull; private readonly bool _emitThrowIfNullMethod; private readonly SourceWriter _writer = new(); @@ -26,6 +27,7 @@ public Emitter(SourceGenerationSpec sourceGenSpec) _typeIndex = new TypeIndex(sourceGenSpec.ConfigTypes); _emitEnumParseMethod = sourceGenSpec.EmitEnumParseMethod; _emitGenericParseEnum = sourceGenSpec.EmitGenericParseEnum; + _emitNotNullIfNotNull = sourceGenSpec.EmitNotNullIfNotNull; _emitThrowIfNullMethod = sourceGenSpec.EmitThrowIfNullMethod; } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs index cb39cd788cfd7d..3d6e2b6503101a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs @@ -57,6 +57,7 @@ internal sealed partial class Parser(CompilationData compilationData) ConfigTypes = _createdTypeSpecs.Values.OrderBy(s => s.TypeRef.FullyQualifiedName).ToImmutableEquatableArray(), EmitEnumParseMethod = _emitEnumParseMethod, EmitGenericParseEnum = _emitGenericParseEnum, + EmitNotNullIfNotNull = _typeSymbols.NotNullIfNotNullAttribute is not null, EmitThrowIfNullMethod = IsThrowIfNullMethodToBeEmitted() }; } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/ConfigurationBinder.cs index c6f23779ec93d4..f49cabc8bfc0c5 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/ConfigurationBinder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/ConfigurationBinder.cs @@ -73,6 +73,7 @@ private void EmitGetValueMethods() if (ShouldEmitMethods(MethodsToGen.ConfigBinder_GetValue_T_key_defaultValue)) { EmitStartDefinition_Get_Or_GetValue_Overload(MethodsToGen.ConfigBinder_GetValue_T_key_defaultValue, documentation); + EmitNotNullIfNotNull(Identifier.defaultValue); _writer.WriteLine($"public static T? {Identifier.GetValue}(this {Identifier.IConfiguration} {Identifier.configuration}, string {Identifier.key}, T {Identifier.defaultValue}) => " + $"(T?)({expressionForGetValueCore}({Identifier.configuration}, typeof(T), {Identifier.key}) ?? {Identifier.defaultValue});"); } @@ -87,11 +88,20 @@ private void EmitGetValueMethods() if (ShouldEmitMethods(MethodsToGen.ConfigBinder_GetValue_TypeOf_key_defaultValue)) { EmitStartDefinition_Get_Or_GetValue_Overload(MethodsToGen.ConfigBinder_GetValue_TypeOf_key_defaultValue, documentation); + EmitNotNullIfNotNull(Identifier.defaultValue); _writer.WriteLine($"public static object? {Identifier.GetValue}(this {Identifier.IConfiguration} {Identifier.configuration}, Type {Identifier.type}, string {Identifier.key}, object? {Identifier.defaultValue}) => " + $"{expressionForGetValueCore}({Identifier.configuration}, {Identifier.type}, {Identifier.key}) ?? {Identifier.defaultValue};"); } } + private void EmitNotNullIfNotNull(string parameterName) + { + if (_emitNotNullIfNotNull) + { + _writer.WriteLine($"[return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof({parameterName}))]"); + } + } + private void EmitBindMethods_ConfigurationBinder() { if (!ShouldEmitMethods(MethodsToGen.ConfigBinder_Bind)) diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Parser/KnownTypeSymbols.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Parser/KnownTypeSymbols.cs index 89ff70db196b04..2f084ec7bdfce9 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Parser/KnownTypeSymbols.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Parser/KnownTypeSymbols.cs @@ -64,6 +64,7 @@ internal sealed class KnownTypeSymbols public INamedTypeSymbol? MemberInfo { get; } public INamedTypeSymbol? ParameterInfo { get; } public INamedTypeSymbol? Delegate { get; } + public INamedTypeSymbol? NotNullIfNotNullAttribute { get; } public KnownTypeSymbols(CSharpCompilation compilation) { @@ -132,6 +133,9 @@ public KnownTypeSymbols(CSharpCompilation compilation) IntPtr = Compilation.GetSpecialType(SpecialType.System_IntPtr); UIntPtr = Compilation.GetSpecialType(SpecialType.System_UIntPtr); Delegate = Compilation.GetSpecialType(SpecialType.System_Delegate); + + // Only generate nullable attributes if available + NotNullIfNotNullAttribute = compilation.GetBestTypeByMetadataName("System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute"); } } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/SourceGenerationSpec.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/SourceGenerationSpec.cs index c4fc5a6079ad99..e435ffa0cd0b23 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/SourceGenerationSpec.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/SourceGenerationSpec.cs @@ -12,6 +12,7 @@ public sealed record SourceGenerationSpec public required ImmutableEquatableArray ConfigTypes { get; init; } public required bool EmitEnumParseMethod { get; set; } public required bool EmitGenericParseEnum { get; set; } + public required bool EmitNotNullIfNotNull { get; set; } public required bool EmitThrowIfNullMethod { get; set; } } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.cs index 0f28d4f2fb9af8..c0ee592ed6b879 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.cs @@ -32,10 +32,12 @@ public static void Bind(this Microsoft.Extensions.Configuration.IConfiguration c [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] public static object? GetValue(this Microsoft.Extensions.Configuration.IConfiguration configuration, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, string key) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))] public static object? GetValue(this Microsoft.Extensions.Configuration.IConfiguration configuration, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, string key, object? defaultValue) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] public static T? GetValue<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] T>(this Microsoft.Extensions.Configuration.IConfiguration configuration, string key) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))] public static T? GetValue<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] T>(this Microsoft.Extensions.Configuration.IConfiguration configuration, string key, T defaultValue) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs index c6783555ca4757..658653c28c0fe1 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs @@ -167,6 +167,7 @@ public static void Bind(this IConfiguration configuration, object? instance, Act /// The default value to use if no value is found. /// The converted value. [RequiresUnreferencedCode(TrimmingWarningMessage)] + [return: NotNullIfNotNull(nameof(defaultValue))] public static T? GetValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(this IConfiguration configuration, string key, T defaultValue) { return (T?)GetValue(configuration, typeof(T), key, defaultValue); @@ -198,6 +199,7 @@ public static void Bind(this IConfiguration configuration, object? instance, Act /// The default value to use if no value is found. /// The converted value. [RequiresUnreferencedCode(TrimmingWarningMessage)] + [return: NotNullIfNotNull(nameof(defaultValue))] public static object? GetValue( this IConfiguration configuration, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] 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 95585b76239237..22691e75714263 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs @@ -326,11 +326,15 @@ public void CanBindToObjectProperty() [Fact] public void GetNullValue() { - var dic = new Dictionary + #nullable enable + #pragma warning disable IDE0004 // Cast is redundant + + var dic = new Dictionary { {"Integer", null}, {"Boolean", null}, {"Nested:Integer", null}, + {"String", null}, {"Object", null } }; var configurationBuilder = new ConfigurationBuilder(); @@ -341,13 +345,16 @@ public void GetNullValue() Assert.False(config.GetValue("Boolean")); Assert.Equal(0, config.GetValue("Integer")); Assert.Equal(0, config.GetValue("Nested:Integer")); + Assert.Null(config.GetValue("String")); Assert.Null(config.GetValue("Object")); // Generic overloads with default value. - Assert.True(config.GetValue("Boolean", true)); - Assert.Equal(1, config.GetValue("Integer", 1)); - Assert.Equal(1, config.GetValue("Nested:Integer", 1)); - Assert.Equal(new NestedConfig(""), config.GetValue("Object", new NestedConfig(""))); + Assert.True((bool)config.GetValue("Boolean", true)); + Assert.Equal(1, (int)config.GetValue("Integer", 1)); + Assert.Equal(1, (int)config.GetValue("Nested:Integer", 1)); + // [NotNullIfNotNull] avoids CS8600: Converting possible null value to non-nullable type. + Assert.Equal("s", (string)config.GetValue("String", "s")); + Assert.Equal(new NestedConfig(""), (NestedConfig)config.GetValue("Object", new NestedConfig(""))); // Type overloads. Assert.Null(config.GetValue(typeof(bool), "Boolean")); @@ -356,16 +363,22 @@ public void GetNullValue() Assert.Null(config.GetValue(typeof(ComplexOptions), "Object")); // Type overloads with default value. + // [NotNullIfNotNull] avoids CS8605: Unboxing a possibly null value. Assert.True((bool)config.GetValue(typeof(bool), "Boolean", true)); Assert.Equal(1, (int)config.GetValue(typeof(int), "Integer", 1)); Assert.Equal(1, (int)config.GetValue(typeof(int), "Nested:Integer", 1)); - Assert.Equal(new NestedConfig(""), config.GetValue("Object", new NestedConfig(""))); + // [NotNullIfNotNull] avoids CS8600: Converting possible null value to non-nullable type. + Assert.Equal("s", (string)config.GetValue(typeof(string), "String", "s")); + Assert.Equal(new NestedConfig(""), (NestedConfig)config.GetValue("Object", new NestedConfig(""))); // GetSection tests. Assert.False(config.GetSection("Boolean").Get()); Assert.Equal(0, config.GetSection("Integer").Get()); Assert.Equal(0, config.GetSection("Nested:Integer").Get()); Assert.Null(config.GetSection("Object").Get()); + + #pragma warning restore IDE0004 + #nullable restore } [Fact] diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue.generated.txt index 67df05b508e896..72edaaf8c6fba6 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue.generated.txt @@ -39,6 +39,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// Extracts the value with the specified key and converts it to the specified type. [InterceptsLocation(@"src-0.cs", 16, 24)] + [return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))] public static T? GetValue(this IConfiguration configuration, string key, T defaultValue) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? defaultValue); /// Extracts the value with the specified key and converts it to the specified type. @@ -47,6 +48,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// Extracts the value with the specified key and converts it to the specified type. [InterceptsLocation(@"src-0.cs", 17, 24)] + [return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))] public static object? GetValue(this IConfiguration configuration, Type type, string key, object? defaultValue) => BindingExtensions.GetValueCore(configuration, type, key) ?? defaultValue; #endregion IConfiguration extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt index b546b86ea1b9b6..c383398924de61 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt @@ -35,6 +35,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #region IConfiguration extensions. /// Extracts the value with the specified key and converts it to the specified type. [InterceptsLocation(@"src-0.cs", 12, 20)] + [return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))] public static T? GetValue(this IConfiguration configuration, string key, T defaultValue) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? defaultValue); #endregion IConfiguration extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt index 772160a53bdd55..8371cd0b05ca1f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt @@ -35,6 +35,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #region IConfiguration extensions. /// Extracts the value with the specified key and converts it to the specified type. [InterceptsLocation(@"src-0.cs", 11, 20)] + [return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))] public static object? GetValue(this IConfiguration configuration, Type type, string key, object? defaultValue) => BindingExtensions.GetValueCore(configuration, type, key) ?? defaultValue; #endregion IConfiguration extensions. 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 eccbe7d759b411..c19f91354cba5a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests.csproj @@ -8,6 +8,9 @@ $(NoWarn);SYSLIB1103,SYSLIB1104 $(InterceptorsPreviewNamespaces);Microsoft.Extensions.Configuration.Binder.SourceGeneration true + + + true From 62e7396d7db73609ed5a2baf65e38668b981aff4 Mon Sep 17 00:00:00 2001 From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com> Date: Mon, 29 Apr 2024 09:48:46 -0700 Subject: [PATCH 165/248] ILLink: give info message on duplicate members only when within a single descriptors file (#101574) In the trimmer we rely on the order of marking to determine if a descriptors file has a duplicate member. As we transition to the dependency analysis framework, the marking order changes, and this exposed scenarios where a descriptors file is found after some items have already been marked. This caused unnecessary IL2025 warnings (Duplicate preserve in descriptor file) to be reported. Instead of using the global marking state, we will keep a per-descriptor-file set of which members are preserved and only report duplicates within that set. --- .../linker/Linker.Steps/DescriptorMarker.cs | 27 +++++++++++++------ .../src/linker/Linker/MessageContainer.cs | 5 ++++ .../LinkXml/LinkXmlErrorCases.cs | 14 +++++++--- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/tools/illink/src/linker/Linker.Steps/DescriptorMarker.cs b/src/tools/illink/src/linker/Linker.Steps/DescriptorMarker.cs index a527ca2e0df60b..f07200ab47e4b8 100644 --- a/src/tools/illink/src/linker/Linker.Steps/DescriptorMarker.cs +++ b/src/tools/illink/src/linker/Linker.Steps/DescriptorMarker.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; @@ -23,14 +24,24 @@ public class DescriptorMarker : ProcessLinkerXmlBase static readonly string[] _accessorsAll = new string[] { "all" }; static readonly char[] _accessorsSep = new char[] { ';' }; + protected readonly HashSet _preservedMembers; + public DescriptorMarker (LinkContext context, Stream documentStream, string xmlDocumentLocation) : base (context, documentStream, xmlDocumentLocation) { + _preservedMembers = new (); } public DescriptorMarker (LinkContext context, Stream documentStream, EmbeddedResource resource, AssemblyDefinition resourceAssembly, string xmlDocumentLocation = "") : base (context, documentStream, resource, resourceAssembly, xmlDocumentLocation) { + _preservedMembers = new (); + } + + protected void LogDuplicatePreserve(string memberName, XPathNavigator duplicatePosition) + { + var origin = GetMessageOriginForPosition (duplicatePosition); + _context.LogMessage (MessageContainer.CreateInfoMessage (origin, $"Duplicate preserve of '{memberName}'")); } public void Mark () @@ -147,16 +158,16 @@ protected static TypePreserve GetTypePreserve (XPathNavigator nav) protected override void ProcessField (TypeDefinition type, FieldDefinition field, XPathNavigator nav) { - if (_context.Annotations.IsMarked (field)) - LogWarning (nav, DiagnosticId.XmlDuplicatePreserveMember, field.FullName); + if (!_preservedMembers.Add (field)) + LogDuplicatePreserve (field.FullName, nav); _context.Annotations.Mark (field, new DependencyInfo (DependencyKind.XmlDescriptor, _xmlDocumentLocation), GetMessageOriginForPosition (nav)); } protected override void ProcessMethod (TypeDefinition type, MethodDefinition method, XPathNavigator nav, object? customData) { - if (_context.Annotations.IsMarked (method)) - LogWarning (nav, DiagnosticId.XmlDuplicatePreserveMember, method.GetDisplayName ()); + if (!_preservedMembers.Add (method)) + LogDuplicatePreserve (method.GetDisplayName (), nav); _context.Annotations.MarkIndirectlyCalledMethod (method); _context.Annotations.SetAction (method, MethodAction.Parse); @@ -212,8 +223,8 @@ public static string GetMethodSignature (MethodDefinition meth, bool includeGene protected override void ProcessEvent (TypeDefinition type, EventDefinition @event, XPathNavigator nav, object? customData) { - if (_context.Annotations.IsMarked (@event)) - LogWarning (nav, DiagnosticId.XmlDuplicatePreserveMember, @event.FullName); + if (!_preservedMembers.Add (@event)) + LogDuplicatePreserve(@event.FullName, nav); ProcessMethod (type, @event.AddMethod, nav, customData); ProcessMethod (type, @event.RemoveMethod, nav, customData); @@ -224,8 +235,8 @@ protected override void ProcessProperty (TypeDefinition type, PropertyDefinition { string[] accessors = fromSignature ? GetAccessors (nav) : _accessorsAll; - if (_context.Annotations.IsMarked (property)) - LogWarning (nav, DiagnosticId.XmlDuplicatePreserveMember, property.FullName); + if (!_preservedMembers.Add (property)) + LogDuplicatePreserve(property.FullName, nav); if (Array.IndexOf (accessors, "all") >= 0) { ProcessMethodIfNotNull (type, property.GetMethod, nav, customData); diff --git a/src/tools/illink/src/linker/Linker/MessageContainer.cs b/src/tools/illink/src/linker/Linker/MessageContainer.cs index eb1fe94a53cfdf..0de844bd6e8002 100644 --- a/src/tools/illink/src/linker/Linker/MessageContainer.cs +++ b/src/tools/illink/src/linker/Linker/MessageContainer.cs @@ -253,6 +253,11 @@ public static MessageContainer CreateInfoMessage (string text) return new MessageContainer (MessageCategory.Info, text, null); } + internal static MessageContainer CreateInfoMessage (MessageOrigin origin, string text) + { + return new MessageContainer (MessageCategory.Info, text, null, "", origin); + } + /// /// Create a diagnostics message. /// diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkXml/LinkXmlErrorCases.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkXml/LinkXmlErrorCases.cs index 467831cbb69fcd..e9021db105d4e8 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkXml/LinkXmlErrorCases.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkXml/LinkXmlErrorCases.cs @@ -6,6 +6,7 @@ namespace Mono.Linker.Tests.Cases.LinkXml { [SetupLinkerDescriptorFile ("LinkXmlErrorCases.xml")] [SetupLinkerArgument ("--skip-unresolved", "true")] + [SetupLinkerArgument ("--verbose")] [ExpectedWarning ("IL2001", "TypeWithNoFields", FileName = "LinkXmlErrorCases.xml", SourceLine = 3, SourceColumn = 6)] [ExpectedWarning ("IL2002", "TypeWithNoMethods", FileName = "LinkXmlErrorCases.xml", SourceLine = 4, SourceColumn = 6)] @@ -17,10 +18,15 @@ namespace Mono.Linker.Tests.Cases.LinkXml [ExpectedWarning ("IL2017", "NonExistentProperty", "TypeWithNoProperties", FileName = "LinkXmlErrorCases.xml", SourceLine = 21, SourceColumn = 8)] [ExpectedWarning ("IL2018", "SetOnlyProperty", "TypeWithProperties", FileName = "LinkXmlErrorCases.xml", SourceLine = 25, SourceColumn = 8)] [ExpectedWarning ("IL2019", "GetOnlyProperty", "TypeWithProperties", FileName = "LinkXmlErrorCases.xml", SourceLine = 26, SourceColumn = 8)] - [ExpectedWarning ("IL2025", "Method", Tool.Trimmer, "", FileName = "LinkXmlErrorCases.xml", SourceLine = 39, SourceColumn = 8)] - [ExpectedWarning ("IL2025", "Event", Tool.Trimmer, "", FileName = "LinkXmlErrorCases.xml", SourceLine = 40, SourceColumn = 8)] - [ExpectedWarning ("IL2025", "Field", Tool.Trimmer, "", FileName = "LinkXmlErrorCases.xml", SourceLine = 41, SourceColumn = 8)] - [ExpectedWarning ("IL2025", "Property", Tool.Trimmer, "", FileName = "LinkXmlErrorCases.xml", SourceLine = 42, SourceColumn = 8)] + [LogContains ("Duplicate preserve of 'System.Int32 Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases/TypeWithEverything::Field'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases.TypeWithEverything.TypeWithEverything()'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases.TypeWithEverything.Method()'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'System.EventHandler Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases/TypeWithEverything::Event'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases.TypeWithEverything.Event.add'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases.TypeWithEverything.Event.remove'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'System.Int32 Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases/TypeWithEverything::Property()'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases.TypeWithEverything.Property.get'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases.TypeWithEverything.Property.set'", ProducedBy = Tool.Trimmer)] // NativeAOT doesn't support wildcard * and will skip usages of it, including if they would warn // https://github.com/dotnet/runtime/issues/80466 [ExpectedWarning ("IL2100", Tool.Trimmer, "", FileName = "LinkXmlErrorCases.xml", SourceLine = 50, SourceColumn = 4)] From 2d4dae9ce9e3a172fcc84e0e01a5756cb0b44bbc Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 12:07:44 -0500 Subject: [PATCH 166/248] [main] Update dependencies from dotnet/runtime, dotnet/sdk (#101682) * Update dependencies from https://github.com/dotnet/runtime build 20240429.1 Microsoft.DotNet.ILCompiler , Microsoft.NET.Sdk.IL , Microsoft.NETCore.App.Runtime.win-x64 , Microsoft.NETCore.ILAsm , runtime.native.System.IO.Ports , System.Reflection.Metadata , System.Reflection.MetadataLoadContext , System.Text.Json , Microsoft.SourceBuild.Intermediate.runtime.linux-x64 From Version 9.0.0-preview.4.24227.6 -> To Version 9.0.0-preview.4.24229.1 * Update dependencies from https://github.com/dotnet/sdk build 20240427.1 Microsoft.SourceBuild.Intermediate.sdk , Microsoft.DotNet.ApiCompat.Task From Version 9.0.100-preview.4.24221.4 -> To Version 9.0.100-preview.5.24227.1 --------- Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 16 +++++++-------- global.json | 2 +- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 7626973e31e9dc..021a0b220d86d3 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -282,43 +282,43 @@ https://github.com/dotnet/llvm-project 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/runtime - b8fe1d0ccb60926d6e7ef5d42e2398c178c9ee5c + 7745b5ec3db34cd358b26710c0ec32db8b0b23f7 - + https://github.com/dotnet/runtime - b8fe1d0ccb60926d6e7ef5d42e2398c178c9ee5c + 7745b5ec3db34cd358b26710c0ec32db8b0b23f7 - + https://github.com/dotnet/runtime - b8fe1d0ccb60926d6e7ef5d42e2398c178c9ee5c + 7745b5ec3db34cd358b26710c0ec32db8b0b23f7 - + https://github.com/dotnet/runtime - b8fe1d0ccb60926d6e7ef5d42e2398c178c9ee5c + 7745b5ec3db34cd358b26710c0ec32db8b0b23f7 - + https://github.com/dotnet/runtime - b8fe1d0ccb60926d6e7ef5d42e2398c178c9ee5c + 7745b5ec3db34cd358b26710c0ec32db8b0b23f7 - + https://github.com/dotnet/runtime - b8fe1d0ccb60926d6e7ef5d42e2398c178c9ee5c + 7745b5ec3db34cd358b26710c0ec32db8b0b23f7 - + https://github.com/dotnet/runtime - b8fe1d0ccb60926d6e7ef5d42e2398c178c9ee5c + 7745b5ec3db34cd358b26710c0ec32db8b0b23f7 - + https://github.com/dotnet/runtime - b8fe1d0ccb60926d6e7ef5d42e2398c178c9ee5c + 7745b5ec3db34cd358b26710c0ec32db8b0b23f7 - + https://github.com/dotnet/runtime - b8fe1d0ccb60926d6e7ef5d42e2398c178c9ee5c + 7745b5ec3db34cd358b26710c0ec32db8b0b23f7 https://github.com/dotnet/xharness @@ -386,14 +386,14 @@ 7a96b1530744f6637ad6bb6bf5b8dfa33ea15b81 - + https://github.com/dotnet/sdk - 1529907f03b73e097a6e4f33fd3c5aea2246f021 + 0f7644da23265f1be382b28ff56f5505b0329334 - + https://github.com/dotnet/sdk - 1529907f03b73e097a6e4f33fd3c5aea2246f021 + 0f7644da23265f1be382b28ff56f5505b0329334 diff --git a/eng/Versions.props b/eng/Versions.props index 168e86e4e81b2e..d9720d96516e56 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -81,7 +81,7 @@ 0.2.0 - 9.0.100-preview.4.24221.4 + 9.0.100-preview.5.24227.1 9.0.0-beta.24226.3 9.0.0-beta.24226.3 @@ -104,10 +104,10 @@ 6.0.0-preview.1.102 - 9.0.0-preview.4.24227.6 + 9.0.0-preview.4.24229.1 6.0.0 - 9.0.0-preview.4.24227.6 + 9.0.0-preview.4.24229.1 6.0.0 1.1.1 @@ -119,19 +119,19 @@ 8.0.0 5.0.0 4.5.5 - 9.0.0-preview.4.24227.6 - 9.0.0-preview.4.24227.6 + 9.0.0-preview.4.24229.1 + 9.0.0-preview.4.24229.1 6.0.0 5.0.0 5.0.0 5.0.0 7.0.0 - 9.0.0-preview.4.24227.6 + 9.0.0-preview.4.24229.1 6.0.0 7.0.0 4.5.4 4.5.0 - 9.0.0-preview.4.24227.6 + 9.0.0-preview.4.24229.1 8.0.0 8.0.0 @@ -210,7 +210,7 @@ 0.11.4-alpha.24222.1 - 9.0.0-preview.4.24227.6 + 9.0.0-preview.4.24229.1 9.0.0-preview.5.24223.2 diff --git a/global.json b/global.json index 2ea13b55221eef..8cafaf799ea2c5 100644 --- a/global.json +++ b/global.json @@ -13,6 +13,6 @@ "Microsoft.DotNet.SharedFramework.Sdk": "9.0.0-beta.24226.3", "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.Build.Traversal": "3.4.0", - "Microsoft.NET.Sdk.IL": "9.0.0-preview.4.24219.3" + "Microsoft.NET.Sdk.IL": "9.0.0-preview.4.24229.1" } } From 2f1c518d8bb905f2f4d71c72edc6115255a679a1 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 12:15:32 -0500 Subject: [PATCH 167/248] Update dependencies from https://github.com/dotnet/roslyn build 20240428.2 (#101679) Microsoft.SourceBuild.Intermediate.roslyn , Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.CSharp , Microsoft.Net.Compilers.Toolset From Version 4.11.0-1.24228.1 -> To Version 4.11.0-1.24228.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 16 ++++++++-------- eng/Versions.props | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 021a0b220d86d3..76279d16eb0303 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -360,17 +360,17 @@ https://github.com/dotnet/runtime-assets 6e78861f1f307cd9f0e64a45b1d7884fa4470930 - + https://github.com/dotnet/roslyn - 7a96b1530744f6637ad6bb6bf5b8dfa33ea15b81 + 75995e26b4c6f9a30ace7bcb65c0b4e42c0b397c - + https://github.com/dotnet/roslyn - 7a96b1530744f6637ad6bb6bf5b8dfa33ea15b81 + 75995e26b4c6f9a30ace7bcb65c0b4e42c0b397c - + https://github.com/dotnet/roslyn - 7a96b1530744f6637ad6bb6bf5b8dfa33ea15b81 + 75995e26b4c6f9a30ace7bcb65c0b4e42c0b397c https://github.com/dotnet/roslyn-analyzers @@ -381,9 +381,9 @@ 8dccccec1ce3bd2fb532ec77d7e092ab9d684db7 - + https://github.com/dotnet/roslyn - 7a96b1530744f6637ad6bb6bf5b8dfa33ea15b81 + 75995e26b4c6f9a30ace7bcb65c0b4e42c0b397c diff --git a/eng/Versions.props b/eng/Versions.props index d9720d96516e56..b7f74da3d8e4a2 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -42,9 +42,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.11.0-1.24228.1 - 4.11.0-1.24228.1 - 4.11.0-1.24228.1 + 4.11.0-1.24228.2 + 4.11.0-1.24228.2 + 4.11.0-1.24228.2 diff --git a/eng/Versions.props b/eng/Versions.props index b7f74da3d8e4a2..241d20a5801b05 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -153,12 +153,12 @@ 9.0.0-beta.24222.1 9.0.0-beta.24222.1 - 1.0.0-prerelease.24219.3 - 1.0.0-prerelease.24219.3 - 1.0.0-prerelease.24219.3 - 1.0.0-prerelease.24219.3 - 1.0.0-prerelease.24219.3 - 1.0.0-prerelease.24219.3 + 1.0.0-prerelease.24223.3 + 1.0.0-prerelease.24223.3 + 1.0.0-prerelease.24223.3 + 1.0.0-prerelease.24223.3 + 1.0.0-prerelease.24223.3 + 1.0.0-prerelease.24223.3 2.0.0 17.8.0-beta1.23475.2 From b88785f22d6a6d0618ebb63490b4a87e3b61c9f6 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Mon, 29 Apr 2024 13:43:21 -0400 Subject: [PATCH 169/248] Ignore line endings when comparing AsnXml generated content --- .../Security/Cryptography/Asn1/AsnXml.targets | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1/AsnXml.targets b/src/libraries/Common/src/System/Security/Cryptography/Asn1/AsnXml.targets index 940c73ca57237c..eb285cc2cfc279 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Asn1/AsnXml.targets +++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1/AsnXml.targets @@ -1,9 +1,6 @@ - <_AsnXmlDiffCmd>%24%28command -v diff%29 -q -a - <_AsnXmlDiffCmd Condition="$([MSBuild]::IsOsPlatform('windows')) == 'true'">$(SystemRoot)\System32\fc.exe /a - <_AsnXmlDiffCmd Condition="$([MSBuild]::IsOsPlatform('osx')) == 'true'">diff @@ -11,6 +8,27 @@ + + + + + + + + + + + + + + + - - - + + + - + From 73a428dd05b92ac727e5831340bb13e18afa39ba Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 29 Apr 2024 13:55:03 -0400 Subject: [PATCH 170/248] Fix handling of case-sensitive set loops in RegexPrefixAnalyzer.FindPrefixes (#101608) * Fix handling of case-sensitive set loops in RegexPrefixAnalyzer.FindPrefixes For an expression like `[Aa]{2}`, we were generating the strings "AA" and "aa" but not "Aa" or "aA". This code isn't exercised yet, as we're currently only using FindPrefixes for case-insensitive, but I'm trying to enable it for case-sensitive as well, and hit this. I'm not adding new tests here as plenty of existing tests catch it once it's enabled. * Also exit early as soon as we can detect too many possible prefixes --- .../RegularExpressions/RegexPrefixAnalyzer.cs | 43 +++++++++++++------ .../FunctionalTests/Regex.Match.Tests.cs | 11 ++--- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs index b46af7b1b9d066..556a187203f035 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs @@ -59,9 +59,11 @@ static bool FindPrefixesCore(RegexNode node, List results, bool i // If we're too deep to analyze further, we can't trust what we've already computed, so stop iterating. // Also bail if any of our results is already hitting the threshold, or if this node is RTL, which is // not worth the complexity of handling. + // Or if we've already discovered more than the allowed number of prefixes. if (!StackHelper.TryEnsureSufficientExecutionStack() || !results.TrueForAll(sb => sb.Length < MaxPrefixLength) || - (node.Options & RegexOptions.RightToLeft) != 0) + (node.Options & RegexOptions.RightToLeft) != 0 || + results.Count > MaxPrefixes) { return false; } @@ -162,23 +164,30 @@ static bool FindPrefixesCore(RegexNode node, List results, bool i int reps = node.Kind is RegexNodeKind.Set ? 1 : Math.Min(node.M, MaxPrefixLength); if (!ignoreCase) { - int existingCount = results.Count; - - // Duplicate all of the existing strings for all of the new suffixes, other than the first. - foreach (char suffix in setChars.Slice(1, charCount - 1)) + for (int rep = 0; rep < reps; rep++) { - for (int existing = 0; existing < existingCount; existing++) + int existingCount = results.Count; + if (existingCount * charCount > MaxPrefixes) { - StringBuilder newSb = new StringBuilder().Append(results[existing]); - newSb.Append(suffix, reps); - results.Add(newSb); + return false; } - } - // Then append the first suffix to all of the existing strings. - for (int existing = 0; existing < existingCount; existing++) - { - results[existing].Append(setChars[0], reps); + // Duplicate all of the existing strings for all of the new suffixes, other than the first. + foreach (char suffix in setChars.Slice(1, charCount - 1)) + { + for (int existing = 0; existing < existingCount; existing++) + { + StringBuilder newSb = new StringBuilder().Append(results[existing]); + newSb.Append(suffix); + results.Add(newSb); + } + } + + // Then append the first suffix to all of the existing strings. + for (int existing = 0; existing < existingCount; existing++) + { + results[existing].Append(setChars[0]); + } } } else @@ -248,6 +257,12 @@ static bool FindPrefixesCore(RegexNode node, List results, bool i { _ = FindPrefixesCore(node.Child(i), alternateBranchResults, ignoreCase); + // If we now have too many results, bail. + if ((allBranchResults?.Count ?? 0) + alternateBranchResults.Count > MaxPrefixes) + { + return false; + } + Debug.Assert(alternateBranchResults.Count > 0); foreach (StringBuilder sb in alternateBranchResults) { diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs index d58290174c222f..9d3679be60b938 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs @@ -1172,6 +1172,7 @@ public async Task Match_VaryingLengthStrings_Huge(RegexEngine engine) public static IEnumerable Match_DeepNesting_MemberData() { + foreach (RegexOptions options in new[] { RegexOptions.None, RegexOptions.IgnoreCase }) foreach (RegexEngine engine in RegexHelpers.AvailableEngines) { if (RegexHelpers.IsNonBacktracking(engine)) @@ -1180,15 +1181,15 @@ public static IEnumerable Match_DeepNesting_MemberData() continue; } - yield return new object[] { engine, 1 }; - yield return new object[] { engine, 10 }; - yield return new object[] { engine, 100 }; + yield return new object[] { engine, options, 1 }; + yield return new object[] { engine, options, 10 }; + yield return new object[] { engine, options, 100 }; } } [Theory] [MemberData(nameof(Match_DeepNesting_MemberData))] - public async Task Match_DeepNesting(RegexEngine engine, int count) + public async Task Match_DeepNesting(RegexEngine engine, RegexOptions options, int count) { const string Start = @"((?>abc|(?:def[ghi]", End = @")))"; const string Match = "defg"; @@ -1196,7 +1197,7 @@ public async Task Match_DeepNesting(RegexEngine engine, int count) string pattern = string.Concat(Enumerable.Repeat(Start, count)) + string.Concat(Enumerable.Repeat(End, count)); string input = string.Concat(Enumerable.Repeat(Match, count)); - Regex r = await RegexHelpers.GetRegexAsync(engine, pattern); + Regex r = await RegexHelpers.GetRegexAsync(engine, pattern, options); Match m = r.Match(input); Assert.True(m.Success); From 703105241219a31ba4c74d43d3c51559cdfdcdf1 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Mon, 29 Apr 2024 11:11:10 -0700 Subject: [PATCH 171/248] Arm64/Sve: Implement divide/multiply/subtract Math APIs (#101578) * Add Divide/Multiply/Subtract * Add hwintrinsic support for Divide,Multiply and Subtract * remove space * Add test cases * trim space * handle the scenario for 2 operands predicated-only instruction * Remove *DIVR and *SUBR from comments * fix jit format * fix merge conflict --- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 27 +- src/coreclr/jit/hwintrinsiclistarm64sve.h | 3 + .../Arm/Sve.PlatformNotSupported.cs | 293 ++++++++++++++++++ .../src/System/Runtime/Intrinsics/Arm/Sve.cs | 292 +++++++++++++++++ .../ref/System.Runtime.Intrinsics.cs | 23 +- .../GenerateHWIntrinsicTests_Arm.cs | 27 ++ 6 files changed, 660 insertions(+), 5 deletions(-) diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index c38afb87a83340..aadd8fcf28e000 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -511,11 +511,30 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) if (falseReg != embMaskOp1Reg) { - // None of targetReg, embMaskOp1Reg and falseReg are same. In such case, use the - // "unpredicated" version of the instruction and then use "sel" to select the active lanes. + // At the point, targetReg != embMaskOp1Reg != falseReg + if (HWIntrinsicInfo::IsOptionalEmbeddedMaskedOperation(intrinEmbMask.id)) + { + // If the embedded instruction supports optional mask operation, use the "unpredicated" + // version of the instruction, followed by "sel" to select the active lanes. + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, embMaskOp1Reg, + embMaskOp2Reg, opt, INS_SCALABLE_OPTS_UNPREDICATED); + } + else + { + // If the instruction just has "predicated" version, then move the "embMaskOp1Reg" + // into targetReg. Next, do the predicated operation on the targetReg and last, + // use "sel" to select the active lanes based on mask, and set inactive lanes + // to falseReg. + + assert(targetReg != embMaskOp2Reg); + assert(HWIntrinsicInfo::IsEmbeddedMaskedOperation(intrinEmbMask.id)); + + GetEmitter()->emitIns_R_R(INS_sve_movprfx, EA_SCALABLE, targetReg, embMaskOp1Reg); + + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, + opt); + } - GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, embMaskOp1Reg, embMaskOp2Reg, - opt, INS_SCALABLE_OPTS_UNPREDICATED); GetEmitter()->emitIns_R_R_R_R(INS_sve_sel, emitSize, targetReg, maskReg, targetReg, falseReg, opt, INS_SCALABLE_OPTS_UNPREDICATED); break; diff --git a/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/coreclr/jit/hwintrinsiclistarm64sve.h index ef9740e4556523..cbd5ea6eb4983e 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64sve.h +++ b/src/coreclr/jit/hwintrinsiclistarm64sve.h @@ -42,6 +42,7 @@ HARDWARE_INTRINSIC(Sve, CreateWhileLessThanOrEqualMask16Bit, HARDWARE_INTRINSIC(Sve, CreateWhileLessThanOrEqualMask32Bit, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_whilele, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ReturnsPerElementMask) HARDWARE_INTRINSIC(Sve, CreateWhileLessThanOrEqualMask64Bit, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_whilele, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ReturnsPerElementMask) HARDWARE_INTRINSIC(Sve, CreateWhileLessThanOrEqualMask8Bit, -1, 2, false, {INS_invalid, INS_sve_whilele, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, Divide, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sdiv, INS_sve_udiv, INS_sve_sdiv, INS_sve_udiv, INS_sve_fdiv, INS_sve_fdiv}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVector, -1, 2, true, {INS_sve_ld1b, INS_sve_ld1b, INS_sve_ld1h, INS_sve_ld1h, INS_sve_ld1w, INS_sve_ld1w, INS_sve_ld1d, INS_sve_ld1d, INS_sve_ld1w, INS_sve_ld1d}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToInt16, -1, 2, false, {INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) @@ -67,6 +68,8 @@ HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToUInt32, HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1h, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, Multiply, -1, 2, true, {INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_fmul, INS_sve_fmul}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sve, Subtract, -1, 2, true, {INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_fsub, INS_sve_fsub}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve, UnzipEven, -1, 2, true, {INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Sve, UnzipOdd, -1, 2, true, {INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs index 3b992e440ef6b5..84583b46874563 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs @@ -552,6 +552,32 @@ internal Arm64() { } public static unsafe Vector CreateWhileLessThanOrEqualMask8Bit(ulong left, ulong right) { throw new PlatformNotSupportedException(); } + /// Divide : Divide + + /// + /// svfloat32_t svdiv[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FDIV Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FDIV Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svdiv[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FDIV Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FDIV Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svdiv[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; FDIV Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Divide(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svdiv[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FDIV Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FDIV Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svdiv[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FDIV Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FDIV Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svdiv[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; FDIV Zresult.D, Pg/M, Zresult.D, Zop2.D + /// + public static unsafe Vector Divide(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// LoadVector : Unextended load /// @@ -840,6 +866,273 @@ internal Arm64() { } /// public static unsafe Vector LoadVectorUInt32ZeroExtendToUInt64(Vector mask, uint* address) { throw new PlatformNotSupportedException(); } + /// Multiply : Multiply + + /// + /// svint8_t svmul[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svint8_t svmul[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MUL Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svint8_t svmul[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// MOVPRFX Zresult.B, Pg/Z, Zop2.B; MUL Zresult.B, Pg/M, Zresult.B, Zop1.B + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svmul[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svint16_t svmul[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MUL Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svint16_t svmul[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// MOVPRFX Zresult.H, Pg/Z, Zop2.H; MUL Zresult.H, Pg/M, Zresult.H, Zop1.H + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svmul[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svint32_t svmul[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MUL Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svint32_t svmul[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// MOVPRFX Zresult.S, Pg/Z, Zop2.S; MUL Zresult.S, Pg/M, Zresult.S, Zop1.S + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svmul[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svint64_t svmul[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MUL Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svint64_t svmul[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// MOVPRFX Zresult.D, Pg/Z, Zop2.D; MUL Zresult.D, Pg/M, Zresult.D, Zop1.D + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint8_t svmul[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svuint8_t svmul[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MUL Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svuint8_t svmul[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// MOVPRFX Zresult.B, Pg/Z, Zop2.B; MUL Zresult.B, Pg/M, Zresult.B, Zop1.B + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svmul[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svuint16_t svmul[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MUL Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svuint16_t svmul[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// MOVPRFX Zresult.H, Pg/Z, Zop2.H; MUL Zresult.H, Pg/M, Zresult.H, Zop1.H + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svmul[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svuint32_t svmul[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MUL Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svuint32_t svmul[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// MOVPRFX Zresult.S, Pg/Z, Zop2.S; MUL Zresult.S, Pg/M, Zresult.S, Zop1.S + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svmul[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svuint64_t svmul[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MUL Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svuint64_t svmul[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// MOVPRFX Zresult.D, Pg/Z, Zop2.D; MUL Zresult.D, Pg/M, Zresult.D, Zop1.D + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svmul[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FMUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svmul[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMUL Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// FMUL Zresult.S, Zop1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FMUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svmul[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; FMUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// MOVPRFX Zresult.S, Pg/Z, Zop2.S; FMUL Zresult.S, Pg/M, Zresult.S, Zop1.S + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svmul[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FMUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svmul[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMUL Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// FMUL Zresult.D, Zop1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FMUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svmul[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; FMUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// MOVPRFX Zresult.D, Pg/Z, Zop2.D; FMUL Zresult.D, Pg/M, Zresult.D, Zop1.D + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// Subtract : Subtract + + /// + /// svint8_t svsub[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svint8_t svsub[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SUB Zresult.B, Zop1.B, Zop2.B + /// svint8_t svsub[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svsub[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svint16_t svsub[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SUB Zresult.H, Zop1.H, Zop2.H + /// svint16_t svsub[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svsub[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svint32_t svsub[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SUB Zresult.S, Zop1.S, Zop2.S + /// svint32_t svsub[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svsub[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svint64_t svsub[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SUB Zresult.D, Zop1.D, Zop2.D + /// svint64_t svsub[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint8_t svsub[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svuint8_t svsub[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SUB Zresult.B, Zop1.B, Zop2.B + /// svuint8_t svsub[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svsub[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svuint16_t svsub[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SUB Zresult.H, Zop1.H, Zop2.H + /// svuint16_t svsub[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svsub[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svuint32_t svsub[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SUB Zresult.S, Zop1.S, Zop2.S + /// svuint32_t svsub[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svsub[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svuint64_t svsub[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SUB Zresult.D, Zop1.D, Zop2.D + /// svuint64_t svsub[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svsub[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FSUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svsub[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FSUB Zresult.S, Zop1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FSUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svsub[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; FSUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svsub[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FSUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svsub[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FSUB Zresult.D, Zop1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FSUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svsub[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; FSUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// UnzipEven : Concatenate even elements from two inputs diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs index 0f4f57dad8e9bc..e823e36e4db2a9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs @@ -608,6 +608,32 @@ internal Arm64() { } public static unsafe Vector CreateWhileLessThanOrEqualMask8Bit(ulong left, ulong right) => CreateWhileLessThanOrEqualMask8Bit(left, right); + /// Divide : Divide + + /// + /// svfloat32_t svdiv[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FDIV Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FDIV Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svdiv[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FDIV Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FDIV Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svdiv[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; FDIV Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Divide(Vector left, Vector right) => Divide(left, right); + + /// + /// svfloat64_t svdiv[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FDIV Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FDIV Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svdiv[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FDIV Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FDIV Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svdiv[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; FDIV Zresult.D, Pg/M, Zresult.D, Zop2.D + /// + public static unsafe Vector Divide(Vector left, Vector right) => Divide(left, right); + /// LoadVector : Unextended load /// @@ -897,6 +923,272 @@ internal Arm64() { } public static unsafe Vector LoadVectorUInt32ZeroExtendToUInt64(Vector mask, uint* address) => LoadVectorUInt32ZeroExtendToUInt64(mask, address); + /// + /// svint8_t svmul[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svint8_t svmul[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MUL Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svint8_t svmul[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// MOVPRFX Zresult.B, Pg/Z, Zop2.B; MUL Zresult.B, Pg/M, Zresult.B, Zop1.B + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svint16_t svmul[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svint16_t svmul[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MUL Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svint16_t svmul[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// MOVPRFX Zresult.H, Pg/Z, Zop2.H; MUL Zresult.H, Pg/M, Zresult.H, Zop1.H + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svint32_t svmul[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svint32_t svmul[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MUL Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svint32_t svmul[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// MOVPRFX Zresult.S, Pg/Z, Zop2.S; MUL Zresult.S, Pg/M, Zresult.S, Zop1.S + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svint64_t svmul[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svint64_t svmul[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MUL Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svint64_t svmul[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// MOVPRFX Zresult.D, Pg/Z, Zop2.D; MUL Zresult.D, Pg/M, Zresult.D, Zop1.D + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svuint8_t svmul[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svuint8_t svmul[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MUL Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svuint8_t svmul[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// MOVPRFX Zresult.B, Pg/Z, Zop2.B; MUL Zresult.B, Pg/M, Zresult.B, Zop1.B + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svuint16_t svmul[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svuint16_t svmul[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MUL Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svuint16_t svmul[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// MOVPRFX Zresult.H, Pg/Z, Zop2.H; MUL Zresult.H, Pg/M, Zresult.H, Zop1.H + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svuint32_t svmul[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svuint32_t svmul[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MUL Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svuint32_t svmul[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// MOVPRFX Zresult.S, Pg/Z, Zop2.S; MUL Zresult.S, Pg/M, Zresult.S, Zop1.S + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svuint64_t svmul[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svuint64_t svmul[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MUL Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svuint64_t svmul[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// MOVPRFX Zresult.D, Pg/Z, Zop2.D; MUL Zresult.D, Pg/M, Zresult.D, Zop1.D + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svfloat32_t svmul[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FMUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svmul[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMUL Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// FMUL Zresult.S, Zop1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FMUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svmul[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; FMUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// MOVPRFX Zresult.S, Pg/Z, Zop2.S; FMUL Zresult.S, Pg/M, Zresult.S, Zop1.S + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svfloat64_t svmul[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FMUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svmul[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMUL Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// FMUL Zresult.D, Zop1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FMUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svmul[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; FMUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// MOVPRFX Zresult.D, Pg/Z, Zop2.D; FMUL Zresult.D, Pg/M, Zresult.D, Zop1.D + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// Subtract : Subtract + + /// + /// svint8_t svsub[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svint8_t svsub[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SUB Zresult.B, Zop1.B, Zop2.B + /// svint8_t svsub[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svint16_t svsub[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svint16_t svsub[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SUB Zresult.H, Zop1.H, Zop2.H + /// svint16_t svsub[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svint32_t svsub[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svint32_t svsub[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SUB Zresult.S, Zop1.S, Zop2.S + /// svint32_t svsub[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svint64_t svsub[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svint64_t svsub[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SUB Zresult.D, Zop1.D, Zop2.D + /// svint64_t svsub[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svuint8_t svsub[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svuint8_t svsub[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SUB Zresult.B, Zop1.B, Zop2.B + /// svuint8_t svsub[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svuint16_t svsub[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svuint16_t svsub[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SUB Zresult.H, Zop1.H, Zop2.H + /// svuint16_t svsub[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svuint32_t svsub[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svuint32_t svsub[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SUB Zresult.S, Zop1.S, Zop2.S + /// svuint32_t svsub[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svuint64_t svsub[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svuint64_t svsub[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SUB Zresult.D, Zop1.D, Zop2.D + /// svuint64_t svsub[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svfloat32_t svsub[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FSUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svsub[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FSUB Zresult.S, Zop1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FSUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svsub[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; FSUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svfloat64_t svsub[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FSUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svsub[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FSUB Zresult.D, Zop1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FSUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svsub[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; FSUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + /// UnzipEven : Concatenate even elements from two inputs /// diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 881100ff95976c..f67349e325b27e 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -4243,6 +4243,8 @@ internal Arm64() { } public static System.Numerics.Vector CreateWhileLessThanOrEqualMask8Bit(long left, long right) { throw null; } public static System.Numerics.Vector CreateWhileLessThanOrEqualMask8Bit(uint left, uint right) { throw null; } public static System.Numerics.Vector CreateWhileLessThanOrEqualMask8Bit(ulong left, ulong right) { throw null; } + public static System.Numerics.Vector Divide(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Divide(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, sbyte* address) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, short* address) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, int* address) { throw null; } @@ -4277,7 +4279,26 @@ internal Arm64() { } public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendToUInt64(System.Numerics.Vector mask, ushort* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendToInt64(System.Numerics.Vector mask, uint* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendToUInt64(System.Numerics.Vector mask, uint* address) { throw null; } - + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } diff --git a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs index db964d4793e1bb..9ef86027848352 100644 --- a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs +++ b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs @@ -2909,6 +2909,9 @@ ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Divide_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Divide", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Divide(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Divide(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Divide_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Divide", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Divide(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Divide(left[i], right[i])"}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), @@ -2993,6 +2996,29 @@ ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt32ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt32ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), @@ -3013,6 +3039,7 @@ ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), From 42f4c3096aa81da74aa27c63862611400639b8c4 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 29 Apr 2024 20:22:21 +0200 Subject: [PATCH 172/248] JIT: Move internal reserved registers to a side table (#101647) This gets rid of `GenTree::gtRsvdRegs` by moving internal registers to a side table. We generally use internal registers very rarely, so making the lookup more costly seems worth the trade off (especially to make it easier to expand `regMaskTP` to 16 bytes). There was one exception where we used internal registers a lot, which was `GT_CALL` for R2R codegen on arm64/arm32. For those nodes we always allocate an internal register to load the target into (the target is obtained by loading the R2R indirection cell that is passed in an argument register). For arm64 it was simple to avoid this internal register: we can simply use LR always, since that register is going to be overwritten by the call anyway. This results in -2% TP for crossgen2 arm64 just from avoiding building this extra interval. This is also the cause of the asm diffs. For arm32 the same strategy doesn't work as well because loading into LR is a 4 byte instruction while loading into other registers is a 2 byte instruction. So for arm32 we still use an internal register and take the small throughput hit. This change reduces JIT memory usage by ~1.5%. The throughput cost (when discounting some spurious inlining decision changes) seems to be around 0.1%. --- src/coreclr/jit/codegenarm.cpp | 24 ++--- src/coreclr/jit/codegenarm64.cpp | 45 ++++---- src/coreclr/jit/codegenarmarch.cpp | 82 ++++++++------- src/coreclr/jit/codegencommon.cpp | 107 ++++++++++++++++++++ src/coreclr/jit/codegeninterface.h | 22 +++- src/coreclr/jit/codegenlinear.cpp | 2 +- src/coreclr/jit/codegenloongarch64.cpp | 38 +++---- src/coreclr/jit/codegenriscv64.cpp | 76 +++++++------- src/coreclr/jit/codegenxarch.cpp | 66 ++++++------ src/coreclr/jit/emitarm.cpp | 18 ++-- src/coreclr/jit/emitarm64.cpp | 8 +- src/coreclr/jit/emitloongarch64.cpp | 6 +- src/coreclr/jit/emitriscv64.cpp | 14 +-- src/coreclr/jit/emitxarch.cpp | 2 +- src/coreclr/jit/gentree.cpp | 76 ++------------ src/coreclr/jit/gentree.h | 6 -- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 6 +- src/coreclr/jit/hwintrinsiccodegenxarch.cpp | 44 ++++---- src/coreclr/jit/jithashtable.h | 50 +++++++-- src/coreclr/jit/lsra.cpp | 4 +- src/coreclr/jit/lsraarmarch.cpp | 20 ++-- src/coreclr/jit/lsrabuild.cpp | 4 - src/coreclr/jit/simdcodegenxarch.cpp | 6 +- 23 files changed, 416 insertions(+), 310 deletions(-) diff --git a/src/coreclr/jit/codegenarm.cpp b/src/coreclr/jit/codegenarm.cpp index 2c010f116a2657..dea8b19fbee94f 100644 --- a/src/coreclr/jit/codegenarm.cpp +++ b/src/coreclr/jit/codegenarm.cpp @@ -280,7 +280,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre if (targetType == TYP_FLOAT) { // Get a temp integer register - regNumber tmpReg = tree->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(tree); float f = forceCastToFloat(constValue); instGen_Set_Reg_To_Imm(EA_4BYTE, tmpReg, *((int*)(&f))); @@ -293,8 +293,8 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre unsigned* cv = (unsigned*)&constValue; // Get two temp integer registers - regNumber tmpReg1 = tree->ExtractTempReg(); - regNumber tmpReg2 = tree->GetSingleTempReg(); + regNumber tmpReg1 = internalRegisters.Extract(tree); + regNumber tmpReg2 = internalRegisters.GetSingle(tree); instGen_Set_Reg_To_Imm(EA_4BYTE, tmpReg1, cv[0]); instGen_Set_Reg_To_Imm(EA_4BYTE, tmpReg2, cv[1]); @@ -431,9 +431,9 @@ void CodeGen::genLclHeap(GenTree* tree) } // Setup the regTmp, if there is one. - if (tree->AvailableTempRegCount() > 0) + if (internalRegisters.Count(tree) > 0) { - regTmp = tree->ExtractTempReg(); + regTmp = internalRegisters.Extract(tree); } // If we have an outgoing arg area then we must adjust the SP by popping off the @@ -833,7 +833,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) gcInfo.gcMarkRegPtrVal(REG_WRITE_BARRIER_DST_BYREF, dstAddr->TypeGet()); // Temp register used to perform the sequence of loads and stores. - regNumber tmpReg = cpObjNode->ExtractTempReg(); + regNumber tmpReg = internalRegisters.Extract(cpObjNode); assert(genIsValidIntReg(tmpReg)); if (cpObjNode->IsVolatile()) @@ -1026,18 +1026,18 @@ void CodeGen::genCodeForStoreLclFld(GenTreeLclFld* tree) { // Arm supports unaligned access only for integer types, // convert the storing floating data into 1 or 2 integer registers and write them as int. - regNumber addr = tree->ExtractTempReg(); + regNumber addr = internalRegisters.Extract(tree); emit->emitIns_R_S(INS_lea, EA_PTRSIZE, addr, varNum, offset); if (targetType == TYP_FLOAT) { - regNumber floatAsInt = tree->GetSingleTempReg(); + regNumber floatAsInt = internalRegisters.GetSingle(tree); emit->emitIns_Mov(INS_vmov_f2i, EA_4BYTE, floatAsInt, dataReg, /* canSkip */ false); emit->emitIns_R_R(INS_str, EA_4BYTE, floatAsInt, addr); } else { - regNumber halfdoubleAsInt1 = tree->ExtractTempReg(); - regNumber halfdoubleAsInt2 = tree->GetSingleTempReg(); + regNumber halfdoubleAsInt1 = internalRegisters.Extract(tree); + regNumber halfdoubleAsInt2 = internalRegisters.GetSingle(tree); emit->emitIns_R_R_R(INS_vmov_d2i, EA_8BYTE, halfdoubleAsInt1, halfdoubleAsInt2, dataReg); emit->emitIns_R_R_I(INS_str, EA_4BYTE, halfdoubleAsInt1, addr, 0); emit->emitIns_R_R_I(INS_str, EA_4BYTE, halfdoubleAsInt1, addr, 4); @@ -1209,7 +1209,7 @@ void CodeGen::genCkfinite(GenTree* treeNode) emitter* emit = GetEmitter(); var_types targetType = treeNode->TypeGet(); - regNumber intReg = treeNode->GetSingleTempReg(); + regNumber intReg = internalRegisters.GetSingle(treeNode); regNumber fpReg = genConsumeReg(treeNode->AsOp()->gtOp1); regNumber targetReg = treeNode->GetRegNum(); @@ -1592,7 +1592,7 @@ void CodeGen::genFloatToIntCast(GenTree* treeNode) genConsumeOperands(treeNode->AsOp()); - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); assert(insVcvt != INS_invalid); GetEmitter()->emitIns_R_R(insVcvt, dstSize, tmpReg, op1->GetRegNum()); diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index 8695545cc934a3..dc79220dcd0b87 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -2372,7 +2372,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre else { // Get a temp integer register to compute long address. - regNumber addrReg = tree->GetSingleTempReg(); + regNumber addrReg = internalRegisters.GetSingle(tree); // We must load the FP constant from the constant pool // Emit a data section constant for the float or double constant. @@ -2407,7 +2407,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre else { // Get a temp integer register to compute long address. - regNumber addrReg = tree->GetSingleTempReg(); + regNumber addrReg = internalRegisters.GetSingle(tree); simd8_t constValue; memcpy(&constValue, &vecCon->gtSimdVal, sizeof(simd8_t)); @@ -2431,7 +2431,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre else { // Get a temp integer register to compute long address. - regNumber addrReg = tree->GetSingleTempReg(); + regNumber addrReg = internalRegisters.GetSingle(tree); simd16_t constValue = {}; memcpy(&constValue, &vecCon->gtSimdVal, sizeof(simd12_t)); @@ -2455,7 +2455,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre else { // Get a temp integer register to compute long address. - regNumber addrReg = tree->GetSingleTempReg(); + regNumber addrReg = internalRegisters.GetSingle(tree); simd16_t constValue; memcpy(&constValue, &vecCon->gtSimdVal, sizeof(simd16_t)); @@ -3132,12 +3132,12 @@ void CodeGen::genLclHeap(GenTree* tree) // since we don't need any internal registers. if (compiler->info.compInitMem) { - assert(tree->AvailableTempRegCount() == 0); + assert(internalRegisters.Count(tree) == 0); regCnt = targetReg; } else { - regCnt = tree->ExtractTempReg(); + regCnt = internalRegisters.Extract(tree); inst_Mov(size->TypeGet(), regCnt, targetReg, /* canSkip */ true); } @@ -3254,12 +3254,12 @@ void CodeGen::genLclHeap(GenTree* tree) assert(regCnt == REG_NA); if (compiler->info.compInitMem) { - assert(tree->AvailableTempRegCount() == 0); + assert(internalRegisters.Count(tree) == 0); regCnt = targetReg; } else { - regCnt = tree->ExtractTempReg(); + regCnt = internalRegisters.Extract(tree); } instGen_Set_Reg_To_Imm(((unsigned int)amount == amount) ? EA_4BYTE : EA_8BYTE, regCnt, amount); } @@ -3323,7 +3323,7 @@ void CodeGen::genLclHeap(GenTree* tree) // // Setup the regTmp - regNumber regTmp = tree->GetSingleTempReg(); + regNumber regTmp = internalRegisters.GetSingle(tree); BasicBlock* loop = genCreateTempLabel(); BasicBlock* done = genCreateTempLabel(); @@ -3668,7 +3668,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) unsigned slots = layout->GetSlotCount(); // Temp register(s) used to perform the sequence of loads and stores. - regNumber tmpReg = cpObjNode->ExtractTempReg(RBM_ALLINT); + regNumber tmpReg = internalRegisters.Extract(cpObjNode, RBM_ALLINT); regNumber tmpReg2 = REG_NA; assert(genIsValidIntReg(tmpReg)); @@ -3677,7 +3677,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) if (slots > 1) { - tmpReg2 = cpObjNode->ExtractTempReg(RBM_ALLINT); + tmpReg2 = internalRegisters.Extract(cpObjNode, RBM_ALLINT); assert(tmpReg2 != tmpReg); assert(genIsValidIntReg(tmpReg2)); assert(tmpReg2 != REG_WRITE_BARRIER_DST_BYREF); @@ -3730,8 +3730,8 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) regNumber tmpSimdReg2 = REG_NA; if ((slots >= 4) && compiler->IsBaselineSimdIsaSupported()) { - tmpSimdReg1 = cpObjNode->ExtractTempReg(RBM_ALLFLOAT); - tmpSimdReg2 = cpObjNode->ExtractTempReg(RBM_ALLFLOAT); + tmpSimdReg1 = internalRegisters.Extract(cpObjNode, RBM_ALLFLOAT); + tmpSimdReg2 = internalRegisters.Extract(cpObjNode, RBM_ALLFLOAT); } unsigned i = 0; @@ -3810,7 +3810,7 @@ void CodeGen::genTableBasedSwitch(GenTree* treeNode) regNumber idxReg = treeNode->AsOp()->gtOp1->GetRegNum(); regNumber baseReg = treeNode->AsOp()->gtOp2->GetRegNum(); - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); // load the ip-relative offset (which is relative to start of fgFirstBB) GetEmitter()->emitIns_R_R_R(INS_ldr, EA_4BYTE, baseReg, baseReg, idxReg, INS_OPTS_LSL); @@ -3869,7 +3869,7 @@ void CodeGen::genLockedInstructions(GenTreeOp* treeNode) case GT_XAND: { // Grab a temp reg to perform `MVN` for dataReg first. - regNumber tempReg = treeNode->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(treeNode); GetEmitter()->emitIns_R_R(INS_mvn, dataSize, tempReg, dataReg); GetEmitter()->emitIns_R_R_R(INS_ldclral, dataSize, tempReg, (targetReg == REG_NA) ? REG_ZR : targetReg, addrReg); @@ -3902,9 +3902,10 @@ void CodeGen::genLockedInstructions(GenTreeOp* treeNode) // These are imported normally if Atomics aren't supported. assert(!treeNode->OperIs(GT_XORR, GT_XAND)); - regNumber exResultReg = treeNode->ExtractTempReg(RBM_ALLINT); - regNumber storeDataReg = (treeNode->OperGet() == GT_XCHG) ? dataReg : treeNode->ExtractTempReg(RBM_ALLINT); - regNumber loadReg = (targetReg != REG_NA) ? targetReg : storeDataReg; + regNumber exResultReg = internalRegisters.Extract(treeNode, RBM_ALLINT); + regNumber storeDataReg = + (treeNode->OperGet() == GT_XCHG) ? dataReg : internalRegisters.Extract(treeNode, RBM_ALLINT); + regNumber loadReg = (targetReg != REG_NA) ? targetReg : storeDataReg; // Check allocator assumptions // @@ -4055,7 +4056,7 @@ void CodeGen::genCodeForCmpXchg(GenTreeCmpXchg* treeNode) } else { - regNumber exResultReg = treeNode->ExtractTempReg(RBM_ALLINT); + regNumber exResultReg = internalRegisters.Extract(treeNode, RBM_ALLINT); // Check allocator assumptions // @@ -4600,7 +4601,7 @@ void CodeGen::genCkfinite(GenTree* treeNode) emitter* emit = GetEmitter(); // Extract exponent into a register. - regNumber intReg = treeNode->GetSingleTempReg(); + regNumber intReg = internalRegisters.GetSingle(treeNode); regNumber fpReg = genConsumeReg(op1); inst_Mov(targetType, intReg, fpReg, /* canSkip */ false, emitActualTypeSize(treeNode)); @@ -5351,7 +5352,7 @@ void CodeGen::genStoreIndTypeSimd12(GenTreeStoreInd* treeNode) regNumber dataReg = genConsumeReg(data); // Need an additional integer register to extract upper 4 bytes from data. - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); // 8-byte write GetEmitter()->emitIns_R_R(INS_str, EA_8BYTE, dataReg, addrReg); @@ -5386,7 +5387,7 @@ void CodeGen::genLoadIndTypeSimd12(GenTreeIndir* treeNode) regNumber addrReg = genConsumeReg(addr); // Need an additional int register to read upper 4 bytes, which is different from targetReg - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); // 8-byte read GetEmitter()->emitIns_R_R(INS_ldr, EA_8BYTE, tgtReg, addrReg); diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index d015332a76d8b7..90447292dbe837 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -910,9 +910,9 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) // in ARM64/ARM // Setup loReg (and hiReg) from the internal registers that we reserved in lower. // - regNumber loReg = treeNode->ExtractTempReg(); + regNumber loReg = internalRegisters.Extract(treeNode); #ifdef TARGET_ARM64 - regNumber hiReg = treeNode->GetSingleTempReg(); + regNumber hiReg = internalRegisters.GetSingle(treeNode); #endif // TARGET_ARM64 GenTreeLclVarCommon* srcLclNode = nullptr; @@ -1268,7 +1268,7 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) regNumber allocatedValueReg = REG_NA; if (treeNode->gtNumRegs == 1) { - allocatedValueReg = treeNode->ExtractTempReg(); + allocatedValueReg = internalRegisters.Extract(treeNode); } // Pick a register to store intermediate values in for the to-stack @@ -1640,19 +1640,19 @@ void CodeGen::genCodeForLclFld(GenTreeLclFld* tree) { // Arm supports unaligned access only for integer types, // load the floating data as 1 or 2 integer registers and convert them to float. - regNumber addr = tree->ExtractTempReg(); + regNumber addr = internalRegisters.Extract(tree); emit->emitIns_R_S(INS_lea, EA_PTRSIZE, addr, varNum, offs); if (targetType == TYP_FLOAT) { - regNumber floatAsInt = tree->GetSingleTempReg(); + regNumber floatAsInt = internalRegisters.GetSingle(tree); emit->emitIns_R_R(INS_ldr, EA_4BYTE, floatAsInt, addr); emit->emitIns_Mov(INS_vmov_i2f, EA_4BYTE, targetReg, floatAsInt, /* canSkip */ false); } else { - regNumber halfdoubleAsInt1 = tree->ExtractTempReg(); - regNumber halfdoubleAsInt2 = tree->GetSingleTempReg(); + regNumber halfdoubleAsInt1 = internalRegisters.Extract(tree); + regNumber halfdoubleAsInt2 = internalRegisters.GetSingle(tree); emit->emitIns_R_R_I(INS_ldr, EA_4BYTE, halfdoubleAsInt1, addr, 0); emit->emitIns_R_R_I(INS_ldr, EA_4BYTE, halfdoubleAsInt2, addr, 4); emit->emitIns_R_R_R(INS_vmov_i2d, EA_8BYTE, targetReg, halfdoubleAsInt1, halfdoubleAsInt2); @@ -1694,7 +1694,7 @@ void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) // The index is never contained, even if it is a constant. assert(index->isUsedFromReg()); - const regNumber tmpReg = node->ExtractTempReg(); + const regNumber tmpReg = internalRegisters.Extract(node); regNumber indexReg = index->GetRegNum(); @@ -1742,7 +1742,7 @@ void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) #ifdef TARGET_ARM64 if (!index->TypeIs(TYP_I_IMPL)) { - const regNumber tmpReg2 = node->ExtractTempReg(); + const regNumber tmpReg2 = internalRegisters.Extract(node); GetEmitter()->emitIns_Mov(INS_mov, EA_4BYTE, tmpReg2, indexReg, /* canSkip */ false); indexReg = tmpReg2; } @@ -2662,7 +2662,7 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) const int dstOffsetAdjustment = helper.GetDstOffset() - dstRegAddrAlignment; dstRegAddrAlignment = 0; - const regNumber tempReg = node->ExtractTempReg(RBM_ALLINT); + const regNumber tempReg = internalRegisters.Extract(node, RBM_ALLINT); genInstrWithConstant(INS_add, EA_PTRSIZE, tempReg, dstReg, dstOffsetAdjustment, tempReg); dstReg = tempReg; @@ -2684,7 +2684,7 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) if (shouldUse16ByteWideInstrs) { - const regNumber simdReg = node->GetSingleTempReg(RBM_ALLFLOAT); + const regNumber simdReg = internalRegisters.GetSingle(node, RBM_ALLFLOAT); const int initValue = (src->AsIntCon()->IconValue() & 0xFF); emit->emitIns_R_I(INS_movi, EA_16BYTE, simdReg, initValue, INS_OPTS_16B); @@ -2967,23 +2967,23 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) if ((srcOffsetAdjustment != 0) && (dstOffsetAdjustment != 0)) { - const regNumber tempReg1 = node->ExtractTempReg(RBM_ALLINT); + const regNumber tempReg1 = internalRegisters.Extract(node, RBM_ALLINT); genInstrWithConstant(INS_add, EA_PTRSIZE, tempReg1, srcReg, srcOffsetAdjustment, tempReg1); srcReg = tempReg1; - const regNumber tempReg2 = node->ExtractTempReg(RBM_ALLINT); + const regNumber tempReg2 = internalRegisters.Extract(node, RBM_ALLINT); genInstrWithConstant(INS_add, EA_PTRSIZE, tempReg2, dstReg, dstOffsetAdjustment, tempReg2); dstReg = tempReg2; } else if (srcOffsetAdjustment != 0) { - const regNumber tempReg = node->ExtractTempReg(RBM_ALLINT); + const regNumber tempReg = internalRegisters.Extract(node, RBM_ALLINT); genInstrWithConstant(INS_add, EA_PTRSIZE, tempReg, srcReg, srcOffsetAdjustment, tempReg); srcReg = tempReg; } else if (dstOffsetAdjustment != 0) { - const regNumber tempReg = node->ExtractTempReg(RBM_ALLINT); + const regNumber tempReg = internalRegisters.Extract(node, RBM_ALLINT); genInstrWithConstant(INS_add, EA_PTRSIZE, tempReg, dstReg, dstOffsetAdjustment, tempReg); dstReg = tempReg; } @@ -2991,16 +2991,16 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) regNumber intReg1 = REG_NA; regNumber intReg2 = REG_NA; - const unsigned intRegCount = node->AvailableTempRegCount(RBM_ALLINT); + const unsigned intRegCount = internalRegisters.Count(node, RBM_ALLINT); if (intRegCount >= 2) { - intReg1 = node->ExtractTempReg(RBM_ALLINT); - intReg2 = node->ExtractTempReg(RBM_ALLINT); + intReg1 = internalRegisters.Extract(node, RBM_ALLINT); + intReg2 = internalRegisters.Extract(node, RBM_ALLINT); } else if (intRegCount == 1) { - intReg1 = node->GetSingleTempReg(RBM_ALLINT); + intReg1 = internalRegisters.GetSingle(node, RBM_ALLINT); intReg2 = rsGetRsvdReg(); } else @@ -3010,8 +3010,8 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) if (shouldUse16ByteWideInstrs) { - const regNumber simdReg1 = node->ExtractTempReg(RBM_ALLFLOAT); - const regNumber simdReg2 = node->GetSingleTempReg(RBM_ALLFLOAT); + const regNumber simdReg1 = internalRegisters.Extract(node, RBM_ALLFLOAT); + const regNumber simdReg2 = internalRegisters.GetSingle(node, RBM_ALLFLOAT); helper.Unroll(FP_REGSIZE_BYTES, intReg1, simdReg1, simdReg2, srcReg, dstReg, GetEmitter()); } @@ -3022,7 +3022,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) #endif // TARGET_ARM64 #ifdef TARGET_ARM - const regNumber tempReg = node->ExtractTempReg(RBM_ALLINT); + const regNumber tempReg = internalRegisters.Extract(node, RBM_ALLINT); for (unsigned regSize = REGSIZE_BYTES; size > 0; size -= regSize, srcOffset += regSize, dstOffset += regSize) { @@ -3147,13 +3147,13 @@ void CodeGen::genCodeForMemmove(GenTreeBlk* tree) if (size >= simdSize) { // Number of SIMD regs needed to save the whole src to regs. - const unsigned numberOfSimdRegs = tree->AvailableTempRegCount(RBM_ALLFLOAT); + const unsigned numberOfSimdRegs = internalRegisters.Count(tree, RBM_ALLFLOAT); // Pop all temp regs to a local array, currently, this impl is limited with LSRA's MaxInternalCount regNumber tempRegs[LinearScan::MaxInternalCount] = {}; for (unsigned i = 0; i < numberOfSimdRegs; i++) { - tempRegs[i] = tree->ExtractTempReg(RBM_ALLFLOAT); + tempRegs[i] = internalRegisters.Extract(tree, RBM_ALLFLOAT); } auto emitSimdLoadStore = [&](bool load) { @@ -3190,15 +3190,15 @@ void CodeGen::genCodeForMemmove(GenTreeBlk* tree) const unsigned loadStoreSize = 1 << BitOperations::Log2(size); if (loadStoreSize == size) { - const regNumber tmpReg = tree->GetSingleTempReg(RBM_ALLINT); + const regNumber tmpReg = internalRegisters.GetSingle(tree, RBM_ALLINT); emitLoadStore(/* load */ true, loadStoreSize, tmpReg, 0); emitLoadStore(/* load */ false, loadStoreSize, tmpReg, 0); } else { - assert(tree->AvailableTempRegCount() == 2); - const regNumber tmpReg1 = tree->ExtractTempReg(RBM_ALLINT); - const regNumber tmpReg2 = tree->ExtractTempReg(RBM_ALLINT); + assert(internalRegisters.Count(tree) == 2); + const regNumber tmpReg1 = internalRegisters.Extract(tree, RBM_ALLINT); + const regNumber tmpReg2 = internalRegisters.Extract(tree, RBM_ALLINT); emitLoadStore(/* load */ true, loadStoreSize, tmpReg1, 0); emitLoadStore(/* load */ true, loadStoreSize, tmpReg2, size - loadStoreSize); emitLoadStore(/* load */ false, loadStoreSize, tmpReg1, 0); @@ -3258,7 +3258,7 @@ void CodeGen::genCodeForInitBlkLoop(GenTreeBlk* initBlkNode) // Extend liveness of dstReg in case if it gets killed by the store. gcInfo.gcMarkRegPtrVal(dstReg, dstNode->TypeGet()); - const regNumber offsetReg = initBlkNode->GetSingleTempReg(); + const regNumber offsetReg = internalRegisters.GetSingle(initBlkNode); instGen_Set_Reg_To_Imm(EA_PTRSIZE, offsetReg, size - TARGET_POINTER_SIZE); BasicBlock* loop = genCreateTempLabel(); @@ -3342,7 +3342,7 @@ void CodeGen::genCall(GenTreeCall* call) const regNumber regThis = genGetThisArgReg(call); #if defined(TARGET_ARM) - const regNumber tmpReg = call->ExtractTempReg(); + const regNumber tmpReg = internalRegisters.Extract(call); GetEmitter()->emitIns_R_R_I(INS_ldr, EA_4BYTE, tmpReg, regThis, 0); #elif defined(TARGET_ARM64) GetEmitter()->emitIns_R_R_I(INS_ldr, EA_4BYTE, REG_ZR, regThis, 0); @@ -3368,7 +3368,7 @@ void CodeGen::genCall(GenTreeCall* call) (call->IsVirtualStubRelativeIndir() && (call->gtEntryPoint.accessType == IAT_VALUE))); assert(call->gtControlExpr == nullptr); - regNumber tmpReg = call->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(call); // Register where we save call address in should not be overridden by epilog. assert((genRegMask(tmpReg) & (RBM_INT_CALLEE_TRASH & ~RBM_LR)) == genRegMask(tmpReg)); @@ -3376,7 +3376,7 @@ void CodeGen::genCall(GenTreeCall* call) call->IsVirtualStubRelativeIndir() ? compiler->virtualStubParamInfo->GetReg() : REG_R2R_INDIRECT_PARAM; GetEmitter()->emitIns_R_R(ins_Load(TYP_I_IMPL), emitActualTypeSize(TYP_I_IMPL), tmpReg, callAddrReg); // We will use this again when emitting the jump in genCallInstruction in the epilog - call->gtRsvdRegs |= genRegMask(tmpReg); + internalRegisters.Add(call, genRegMask(tmpReg)); } #endif @@ -3666,15 +3666,25 @@ void CodeGen::genCallInstruction(GenTreeCall* call) if (callThroughIndirReg != REG_NA) { assert(call->IsR2ROrVirtualStubRelativeIndir()); - regNumber targetAddrReg = call->GetSingleTempReg(); + regNumber targetAddrReg; // For fast tailcalls we have already loaded the call target when processing the call node. if (!call->IsFastTailCall()) { +#ifdef TARGET_ARM + // For arm32 we've allocated an internal register to load the target into. + // Loading into lr takes 4 bytes (instead of potentially 2 with another register). + targetAddrReg = internalRegisters.GetSingle(call); +#else + // For arm64 we just use lr and skip the internal register. + targetAddrReg = REG_LR; +#endif + GetEmitter()->emitIns_R_R(ins_Load(TYP_I_IMPL), emitActualTypeSize(TYP_I_IMPL), targetAddrReg, callThroughIndirReg); } else { + targetAddrReg = internalRegisters.GetSingle(call); // Register where we save call address in should not be overridden by epilog. assert((genRegMask(targetAddrReg) & (RBM_INT_CALLEE_TRASH & ~RBM_LR)) == genRegMask(targetAddrReg)); } @@ -3731,7 +3741,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) #ifdef TARGET_ARM if (!validImmForBL((ssize_t)addr)) { - regNumber tmpReg = call->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(call); instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, tmpReg, (ssize_t)addr); // clang-format off genEmitCall(emitter::EC_INDIR_R, @@ -4721,7 +4731,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) if (offset != 0) { - regNumber tmpReg = lea->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(lea); // When generating fully interruptible code we have to use the "large offset" sequence // when calculating a EA_BYREF as we can't report a byref that points outside of the object @@ -4803,7 +4813,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) else { // We require a tmpReg to hold the offset - regNumber tmpReg = lea->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(lea); // First load tmpReg with the large offset constant instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset); diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 301b10b1de0717..6ec296a1391bb5 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -62,10 +62,117 @@ CodeGenInterface* getCodeGenerator(Compiler* comp) return new (comp, CMK_Codegen) CodeGen(comp); } +NodeInternalRegisters::NodeInternalRegisters(Compiler* comp) + : m_table(comp->getAllocator(CMK_LSRA)) +{ +} + +//------------------------------------------------------------------------ +// Add: Add internal allocated registers for the specified node. +// +// Parameters: +// tree - IR node to add internal allocated registers to +// regs - Registers to add +// +void NodeInternalRegisters::Add(GenTree* tree, regMaskTP regs) +{ + assert(regs != RBM_NONE); + + regMaskTP* result = m_table.LookupPointerOrAdd(tree, RBM_NONE); + *result |= regs; +} + +//------------------------------------------------------------------------ +// Extract: Find the lowest number temporary register from the gtRsvdRegs set +// that is also in the optional given mask (typically, RBM_ALLINT or +// RBM_ALLFLOAT), and return it. Remove this register from the temporary +// register set, so it won't be returned again. +// +// Parameters: +// tree - IR node whose internal registers to extract +// mask - Mask of allowed registers that can be returned +// +// Returns: +// Register number. +// +regNumber NodeInternalRegisters::Extract(GenTree* tree, regMaskTP mask) +{ + regMaskTP* regs = m_table.LookupPointer(tree); + assert(regs != nullptr); + + regMaskTP availableSet = *regs & mask; + assert(availableSet != RBM_NONE); + + regNumber result = genFirstRegNumFromMask(availableSet); + *regs ^= genRegMask(result); + + return result; +} + +//------------------------------------------------------------------------ +// GetSingleTempReg: There is expected to be exactly one available temporary register +// in the given mask in the internal register set. Get that register. No future calls to get +// a temporary register are expected. Removes the register from the set, but only in +// DEBUG to avoid doing unnecessary work in non-DEBUG builds. +// +// Parameters: +// tree - IR node whose internal registers to extract +// mask - Mask of allowed registers that can be returned +// +// Returns: +// Register number. +// +regNumber NodeInternalRegisters::GetSingle(GenTree* tree, regMaskTP mask) +{ + regMaskTP* regs = m_table.LookupPointer(tree); + assert(regs != nullptr); + + regMaskTP availableSet = *regs & mask; + assert(genExactlyOneBit(availableSet)); + + regNumber result = genFirstRegNumFromMask(availableSet); + INDEBUG(*regs &= ~genRegMask(result)); + + return result; +} + +//------------------------------------------------------------------------ +// GetAll: Get all internal registers for the specified IR node. +// +// Parameters: +// tree - IR node whose internal registers to query +// +// Returns: +// Mask of registers. +// +regMaskTP NodeInternalRegisters::GetAll(GenTree* tree) +{ + regMaskTP regs; + return m_table.Lookup(tree, ®s) ? regs : RBM_NONE; +} + +//------------------------------------------------------------------------ +// Count: return the number of available temporary registers in the (optional) +// given set (typically, RBM_ALLINT or RBM_ALLFLOAT). +// +// Parameters: +// tree - IR node whose internal registers to query +// mask - Mask of registers to count +// +// Returns: +// Count of nodes +// +unsigned NodeInternalRegisters::Count(GenTree* tree, regMaskTP mask) +{ + regMaskTP regs; + return m_table.Lookup(tree, ®s) ? genCountBits(regs & mask) : 0; +} + // CodeGen constructor CodeGenInterface::CodeGenInterface(Compiler* theCompiler) : gcInfo(theCompiler) , regSet(theCompiler, gcInfo) + , internalRegisters(theCompiler) , compiler(theCompiler) , treeLifeUpdater(nullptr) { diff --git a/src/coreclr/jit/codegeninterface.h b/src/coreclr/jit/codegeninterface.h index ef87ccca858702..608c72c22d48d0 100644 --- a/src/coreclr/jit/codegeninterface.h +++ b/src/coreclr/jit/codegeninterface.h @@ -46,6 +46,21 @@ struct RegState CodeGenInterface* getCodeGenerator(Compiler* comp); +class NodeInternalRegisters +{ + typedef JitHashTable, regMaskTP> NodeInternalRegistersTable; + NodeInternalRegistersTable m_table; + +public: + NodeInternalRegisters(Compiler* comp); + + void Add(GenTree* tree, regMaskTP reg); + regNumber Extract(GenTree* tree, regMaskTP mask = static_cast(-1)); + regNumber GetSingle(GenTree* tree, regMaskTP mask = static_cast(-1)); + regMaskTP GetAll(GenTree* tree); + unsigned Count(GenTree* tree, regMaskTP mask = static_cast(-1)); +}; + class CodeGenInterface { friend class emitter; @@ -122,9 +137,10 @@ class CodeGenInterface GCInfo gcInfo; - RegSet regSet; - RegState intRegState; - RegState floatRegState; + RegSet regSet; + RegState intRegState; + RegState floatRegState; + NodeInternalRegisters internalRegisters; protected: Compiler* compiler; diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index d099fe192fc38a..786f40c2f4ca7d 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -1905,7 +1905,7 @@ void CodeGen::genSetBlockSize(GenTreeBlk* blkNode, regNumber sizeReg) { if (sizeReg != REG_NA) { - assert((blkNode->gtRsvdRegs & genRegMask(sizeReg)) != 0); + assert((internalRegisters.GetAll(blkNode) & genRegMask(sizeReg)) != 0); // This can go via helper which takes the size as a native uint. instGen_Set_Reg_To_Imm(EA_PTRSIZE, sizeReg, blkNode->Size()); } diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index 1bd29a432ce170..6fceb11807ed33 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -1513,7 +1513,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre else { // Get a temp integer register to compute long address. - // regNumber addrReg = tree->GetSingleTempReg(); + // regNumber addrReg = internalRegisters.GetSingle(tree); // We must load the FP constant from the constant pool // Emit a data section constant for the float or double constant. @@ -1962,12 +1962,12 @@ void CodeGen::genLclHeap(GenTree* tree) // since we don't need any internal registers. if (compiler->info.compInitMem) { - assert(tree->AvailableTempRegCount() == 0); + assert(internalRegisters.Count(tree) == 0); regCnt = targetReg; } else { - regCnt = tree->ExtractTempReg(); + regCnt = internalRegisters.Extract(tree); if (regCnt != targetReg) { emit->emitIns_R_R_I(INS_ori, easz, regCnt, targetReg, 0); @@ -2064,12 +2064,12 @@ void CodeGen::genLclHeap(GenTree* tree) assert(regCnt == REG_NA); if (compiler->info.compInitMem) { - assert(tree->AvailableTempRegCount() == 0); + assert(internalRegisters.Count(tree) == 0); regCnt = targetReg; } else { - regCnt = tree->ExtractTempReg(); + regCnt = internalRegisters.Extract(tree); } instGen_Set_Reg_To_Imm(((unsigned int)amount == amount) ? EA_4BYTE : EA_8BYTE, regCnt, amount); } @@ -2134,7 +2134,7 @@ void CodeGen::genLclHeap(GenTree* tree) // // Setup the regTmp - regNumber regTmp = tree->GetSingleTempReg(); + regNumber regTmp = internalRegisters.GetSingle(tree); assert(regCnt != REG_R21); emit->emitIns_R_R_R(INS_sltu, EA_PTRSIZE, REG_R21, REG_SPBASE, regCnt); @@ -2585,7 +2585,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) unsigned slots = layout->GetSlotCount(); // Temp register(s) used to perform the sequence of loads and stores. - regNumber tmpReg = cpObjNode->ExtractTempReg(); + regNumber tmpReg = internalRegisters.Extract(cpObjNode); regNumber tmpReg2 = REG_NA; assert(genIsValidIntReg(tmpReg)); @@ -2594,7 +2594,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) if (slots > 1) { - tmpReg2 = cpObjNode->GetSingleTempReg(); + tmpReg2 = internalRegisters.GetSingle(cpObjNode); assert(tmpReg2 != tmpReg); assert(genIsValidIntReg(tmpReg2)); assert(tmpReg2 != REG_WRITE_BARRIER_DST_BYREF); @@ -2729,7 +2729,7 @@ void CodeGen::genTableBasedSwitch(GenTree* treeNode) regNumber idxReg = treeNode->AsOp()->gtOp1->GetRegNum(); regNumber baseReg = treeNode->AsOp()->gtOp2->GetRegNum(); - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); // load the ip-relative offset (which is relative to start of fgFirstBB) GetEmitter()->emitIns_R_R_I(INS_slli_d, EA_8BYTE, REG_R21, idxReg, 2); @@ -3591,7 +3591,7 @@ void CodeGen::genCkfinite(GenTree* treeNode) emitAttr attr = emitActualTypeSize(treeNode); // Extract exponent into a register. - regNumber intReg = treeNode->GetSingleTempReg(); + regNumber intReg = internalRegisters.GetSingle(treeNode); regNumber fpReg = genConsumeReg(op1); emit->emitIns_R_R(attr == EA_8BYTE ? INS_movfr2gr_d : INS_movfr2gr_s, attr, intReg, fpReg); @@ -5101,7 +5101,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) // Setup loReg from the internal registers that we reserved in lower. // - regNumber loReg = treeNode->ExtractTempReg(); + regNumber loReg = internalRegisters.Extract(treeNode); regNumber addrReg = REG_NA; GenTreeLclVarCommon* varNode = nullptr; @@ -5382,7 +5382,7 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) assert(source->OperGet() == GT_BLK); assert(varTypeIsStruct(targetType)); - regNumber baseReg = treeNode->ExtractTempReg(); + regNumber baseReg = internalRegisters.Extract(treeNode); regNumber addrReg = REG_NA; GenTreeLclVarCommon* varNode = nullptr; @@ -6019,7 +6019,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode) assert(srcOffset < INT32_MAX - static_cast(size)); assert(dstOffset < INT32_MAX - static_cast(size)); - regNumber tempReg = cpBlkNode->ExtractTempReg(RBM_ALLINT); + regNumber tempReg = internalRegisters.Extract(cpBlkNode, RBM_ALLINT); if (size >= 2 * REGSIZE_BYTES) { @@ -6148,7 +6148,7 @@ void CodeGen::genCodeForInitBlkLoop(GenTreeBlk* initBlkNode) // Extend liveness of dstReg in case if it gets killed by the store. gcInfo.gcMarkRegPtrVal(dstReg, dstNode->TypeGet()); - const regNumber offsetReg = initBlkNode->GetSingleTempReg(); + const regNumber offsetReg = internalRegisters.GetSingle(initBlkNode); instGen_Set_Reg_To_Imm(EA_PTRSIZE, offsetReg, size - TARGET_POINTER_SIZE); // loop begin: @@ -6247,7 +6247,7 @@ void CodeGen::genCall(GenTreeCall* call) (call->IsVirtualStubRelativeIndir() && (call->gtEntryPoint.accessType == IAT_VALUE))); assert(call->gtControlExpr == nullptr); - regNumber tmpReg = call->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(call); // Register where we save call address in should not be overridden by epilog. assert((genRegMask(tmpReg) & (RBM_INT_CALLEE_TRASH & ~RBM_RA)) == genRegMask(tmpReg)); @@ -6255,7 +6255,7 @@ void CodeGen::genCall(GenTreeCall* call) call->IsVirtualStubRelativeIndir() ? compiler->virtualStubParamInfo->GetReg() : REG_R2R_INDIRECT_PARAM; GetEmitter()->emitIns_R_R_I(ins_Load(TYP_I_IMPL), emitActualTypeSize(TYP_I_IMPL), tmpReg, callAddrReg, 0); // We will use this again when emitting the jump in genCallInstruction in the epilog - call->gtRsvdRegs |= genRegMask(tmpReg); + internalRegisters.Add(call, genRegMask(tmpReg)); } #endif @@ -6473,7 +6473,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) if (callThroughIndirReg != REG_NA) { assert(call->IsR2ROrVirtualStubRelativeIndir()); - regNumber targetAddrReg = call->GetSingleTempReg(); + regNumber targetAddrReg = internalRegisters.GetSingle(call); // For fast tailcalls we have already loaded the call target when processing the call node. if (!call->IsFastTailCall()) { @@ -7131,7 +7131,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) } else { - regNumber tmpReg = lea->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(lea); noway_assert(tmpReg != index->GetRegNum()); noway_assert(tmpReg != memBase->GetRegNum()); @@ -7168,7 +7168,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) else { // We require a tmpReg to hold the offset - regNumber tmpReg = lea->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(lea); // First load tmpReg with the large offset constant emit->emitIns_I_la(EA_PTRSIZE, tmpReg, offset); diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index 0fa8bdb5874f40..84a2663dcbcce5 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -1536,7 +1536,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre else { // Get a temp integer register to compute long address. - // regNumber addrReg = tree->GetSingleTempReg(); + // regNumber addrReg = internalRegisters.GetSingle(tree); // We must load the FP constant from the constant pool // Emit a data section constant for the float or double constant. @@ -1616,7 +1616,7 @@ void CodeGen::genCodeForMulHi(GenTreeOp* treeNode) assert(EA_SIZE(attr) == EA_4BYTE); if (isUnsigned) { - regNumber tempReg = treeNode->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(treeNode); emit->emitIns_R_R_I(INS_slli, EA_8BYTE, tempReg, op1->GetRegNum(), 32); emit->emitIns_R_R_I(INS_slli, EA_8BYTE, targetReg, op2->GetRegNum(), 32); emit->emitIns_R_R_R(INS_mulhu, EA_8BYTE, targetReg, tempReg, targetReg); @@ -1982,7 +1982,7 @@ void CodeGen::genLclHeap(GenTree* tree) } else { - regCnt = tree->ExtractTempReg(); + regCnt = internalRegisters.Extract(tree); if (regCnt != targetReg) { emit->emitIns_R_R_I(INS_ori, easz, regCnt, targetReg, 0); @@ -2012,7 +2012,7 @@ void CodeGen::genLclHeap(GenTree* tree) unsigned outgoingArgSpaceAligned = roundUp(compiler->lvaOutgoingArgSpaceSize, STACK_ALIGN); // assert((compiler->lvaOutgoingArgSpaceSize % STACK_ALIGN) == 0); // This must be true for the stack to remain // // aligned - tempReg = tree->ExtractTempReg(); + tempReg = internalRegisters.Extract(tree); genInstrWithConstant(INS_addi, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, outgoingArgSpaceAligned, tempReg); stackAdjustment += outgoingArgSpaceAligned; } @@ -2067,7 +2067,7 @@ void CodeGen::genLclHeap(GenTree* tree) else { if (tempReg == REG_NA) - tempReg = tree->ExtractTempReg(); + tempReg = internalRegisters.Extract(tree); emit->emitLoadImmediate(EA_PTRSIZE, tempReg, amount); emit->emitIns_R_R_R(INS_sub, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, tempReg); } @@ -2085,7 +2085,7 @@ void CodeGen::genLclHeap(GenTree* tree) } else { - regCnt = tree->ExtractTempReg(); + regCnt = internalRegisters.Extract(tree); } instGen_Set_Reg_To_Imm(((unsigned int)amount == amount) ? EA_4BYTE : EA_8BYTE, regCnt, amount); } @@ -2152,9 +2152,9 @@ void CodeGen::genLclHeap(GenTree* tree) // if (tempReg == REG_NA) - tempReg = tree->ExtractTempReg(); + tempReg = internalRegisters.Extract(tree); - regNumber rPageSize = tree->GetSingleTempReg(); + regNumber rPageSize = internalRegisters.GetSingle(tree); assert(regCnt != tempReg); emit->emitIns_R_R_R(INS_sltu, EA_PTRSIZE, tempReg, REG_SPBASE, regCnt); @@ -2359,7 +2359,7 @@ void CodeGen::genCodeForDivMod(GenTreeOp* tree) ssize_t intConst = (int)(divisorOp->AsIntCon()->gtIconVal); if (!emitter::isGeneralRegister(divisorReg)) { - tempReg = tree->GetSingleTempReg(); + tempReg = internalRegisters.GetSingle(tree); divisorReg = tempReg; } emit->emitLoadImmediate(EA_PTRSIZE, divisorReg, intConst); @@ -2382,7 +2382,7 @@ void CodeGen::genCodeForDivMod(GenTreeOp* tree) if ((exceptions & ExceptionSetFlags::ArithmeticException) != ExceptionSetFlags::None) { if (tempReg == REG_NA) - tempReg = tree->GetSingleTempReg(); + tempReg = internalRegisters.GetSingle(tree); // Check if the divisor is not -1 branch to 'sdivLabel' emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, tempReg, REG_ZERO, -1); @@ -2608,7 +2608,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) unsigned slots = layout->GetSlotCount(); // Temp register(s) used to perform the sequence of loads and stores. - regNumber tmpReg = cpObjNode->ExtractTempReg(); + regNumber tmpReg = internalRegisters.Extract(cpObjNode); regNumber tmpReg2 = REG_NA; assert(genIsValidIntReg(tmpReg)); @@ -2617,7 +2617,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) if (slots > 1) { - tmpReg2 = cpObjNode->GetSingleTempReg(); + tmpReg2 = internalRegisters.GetSingle(cpObjNode); assert(tmpReg2 != tmpReg); assert(genIsValidIntReg(tmpReg2)); assert(tmpReg2 != REG_WRITE_BARRIER_DST_BYREF); @@ -2752,7 +2752,7 @@ void CodeGen::genTableBasedSwitch(GenTree* treeNode) regNumber idxReg = treeNode->AsOp()->gtOp1->GetRegNum(); regNumber baseReg = treeNode->AsOp()->gtOp2->GetRegNum(); - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); // load the ip-relative offset (which is relative to start of fgFirstBB) GetEmitter()->emitIns_R_R_I(INS_slli, EA_8BYTE, tmpReg, idxReg, 2); @@ -2852,7 +2852,7 @@ void CodeGen::genCodeForCmpXchg(GenTreeCmpXchg* treeNode) regNumber loc = locOp->GetRegNum(); regNumber val = valOp->GetRegNum(); regNumber comparand = comparandOp->GetRegNum(); - regNumber storeErr = treeNode->ExtractTempReg(RBM_ALLINT); + regNumber storeErr = internalRegisters.Extract(treeNode, RBM_ALLINT); // Register allocator should have extended the lifetimes of all input and internal registers // They should all be different @@ -3559,7 +3559,7 @@ void CodeGen::genFloatToIntCast(GenTree* treeNode) genConsumeOperands(treeNode->AsOp()); - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); assert(tmpReg != treeNode->GetRegNum()); assert(tmpReg != op1->GetRegNum()); @@ -3606,7 +3606,7 @@ void CodeGen::genCkfinite(GenTree* treeNode) emitAttr attr = emitActualTypeSize(treeNode); // Extract exponent into a register. - regNumber intReg = treeNode->GetSingleTempReg(); + regNumber intReg = internalRegisters.GetSingle(treeNode); regNumber fpReg = genConsumeReg(op1); emit->emitIns_R_R(attr == EA_4BYTE ? INS_fclass_s : INS_fclass_d, attr, intReg, fpReg); @@ -3671,7 +3671,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) } else if (tree->OperIs(GT_EQ)) { - regNumber tempReg = tree->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(tree); skipLabel = genCreateTempLabel(); emit->emitIns_R_R(cmpSize == EA_4BYTE ? INS_fclass_s : INS_fclass_d, cmpSize, targetReg, regOp1); emit->emitIns_R_R(cmpSize == EA_4BYTE ? INS_fclass_s : INS_fclass_d, cmpSize, tempReg, regOp2); @@ -3716,7 +3716,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) } else if (tree->OperIs(GT_NE)) { - regNumber tempReg = tree->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(tree); emit->emitIns_R_R(cmpSize == EA_4BYTE ? INS_fclass_s : INS_fclass_d, cmpSize, targetReg, regOp1); emit->emitIns_R_R(cmpSize == EA_4BYTE ? INS_fclass_s : INS_fclass_d, cmpSize, tempReg, regOp2); emit->emitIns_R_R_R(INS_or, EA_8BYTE, tempReg, targetReg, tempReg); @@ -3755,7 +3755,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) { imm = static_cast(imm); - regNumber tmpRegOp1 = tree->GetSingleTempReg(); + regNumber tmpRegOp1 = internalRegisters.GetSingle(tree); assert(regOp1 != tmpRegOp1); emit->emitIns_R_R_I(INS_slli, EA_8BYTE, tmpRegOp1, regOp1, 32); @@ -3884,7 +3884,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) if (cmpSize == EA_4BYTE) { regNumber tmpRegOp1 = REG_RA; - regNumber tmpRegOp2 = tree->GetSingleTempReg(); + regNumber tmpRegOp2 = internalRegisters.GetSingle(tree); assert(regOp1 != tmpRegOp2); assert(regOp2 != tmpRegOp2); @@ -5280,7 +5280,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) // Setup loReg from the internal registers that we reserved in lower. // - regNumber loReg = treeNode->ExtractTempReg(); + regNumber loReg = internalRegisters.Extract(treeNode); GenTreeLclVarCommon* srcLclNode = nullptr; regNumber addrReg = REG_NA; @@ -5523,7 +5523,7 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) regNumber allocatedValueReg = REG_NA; if (treeNode->gtNumRegs == 1) { - allocatedValueReg = treeNode->ExtractTempReg(); + allocatedValueReg = internalRegisters.Extract(treeNode); } // Pick a register to store intermediate values in for the to-stack @@ -5670,13 +5670,13 @@ void CodeGen::genRangeCheck(GenTree* oper) if (genActualType(length) == TYP_INT) { - regNumber tempReg = oper->ExtractTempReg(); + regNumber tempReg = internalRegisters.Extract(oper); GetEmitter()->emitIns_R_R_I(INS_addiw, EA_4BYTE, tempReg, lengthReg, 0); // sign-extend lengthReg = tempReg; } if (genActualType(index) == TYP_INT) { - regNumber tempReg = oper->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(oper); GetEmitter()->emitIns_R_R_I(INS_addiw, EA_4BYTE, tempReg, indexReg, 0); // sign-extend indexReg = tempReg; } @@ -5759,7 +5759,7 @@ void CodeGen::genCodeForShift(GenTree* tree) if (tree->OperIs(GT_ROR, GT_ROL)) { - regNumber tempReg = tree->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(tree); unsigned immWidth = emitter::getBitWidth(size); // For RISCV64, immWidth will be set to 32 or 64 if (!shiftBy->IsCnsIntOrI()) { @@ -5949,7 +5949,7 @@ void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) // The index is never contained, even if it is a constant. assert(index->isUsedFromReg()); - regNumber tempReg = node->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(node); // Generate the bounds check if necessary. if (node->IsBoundsChecked()) @@ -6156,7 +6156,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode) assert(srcOffset < INT32_MAX - static_cast(size)); assert(dstOffset < INT32_MAX - static_cast(size)); - regNumber tempReg = cpBlkNode->ExtractTempReg(RBM_ALLINT); + regNumber tempReg = internalRegisters.Extract(cpBlkNode, RBM_ALLINT); if (size >= 2 * REGSIZE_BYTES) { @@ -6285,7 +6285,7 @@ void CodeGen::genCodeForInitBlkLoop(GenTreeBlk* initBlkNode) // Extend liveness of dstReg in case if it gets killed by the store. gcInfo.gcMarkRegPtrVal(dstReg, dstNode->TypeGet()); - const regNumber tempReg = initBlkNode->GetSingleTempReg(); + const regNumber tempReg = internalRegisters.GetSingle(initBlkNode); instGen_Set_Reg_To_Imm(EA_PTRSIZE, tempReg, size - TARGET_POINTER_SIZE); // tempReg = dstReg + tempReg (a new interior pointer, but in a nongc region) @@ -6391,7 +6391,7 @@ void CodeGen::genCall(GenTreeCall* call) (call->IsVirtualStubRelativeIndir() && (call->gtEntryPoint.accessType == IAT_VALUE))); assert(call->gtControlExpr == nullptr); - regNumber tmpReg = call->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(call); // Register where we save call address in should not be overridden by epilog. assert((genRegMask(tmpReg) & (RBM_INT_CALLEE_TRASH & ~RBM_RA)) == genRegMask(tmpReg)); @@ -6399,7 +6399,7 @@ void CodeGen::genCall(GenTreeCall* call) call->IsVirtualStubRelativeIndir() ? compiler->virtualStubParamInfo->GetReg() : REG_R2R_INDIRECT_PARAM; GetEmitter()->emitIns_R_R_I(ins_Load(TYP_I_IMPL), emitActualTypeSize(TYP_I_IMPL), tmpReg, callAddrReg, 0); // We will use this again when emitting the jump in genCallInstruction in the epilog - call->gtRsvdRegs |= genRegMask(tmpReg); + internalRegisters.Add(call, genRegMask(tmpReg)); } #endif @@ -6617,7 +6617,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) if (callThroughIndirReg != REG_NA) { assert(call->IsR2ROrVirtualStubRelativeIndir()); - regNumber targetAddrReg = call->GetSingleTempReg(); + regNumber targetAddrReg = internalRegisters.GetSingle(call); // For fast tailcalls we have already loaded the call target when processing the call node. if (!call->IsFastTailCall()) { @@ -6885,7 +6885,7 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d case GenIntCastDesc::CHECK_UINT_RANGE: { - regNumber tempReg = cast->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(cast); // We need to check if the value is not greater than 0xFFFFFFFF // if the upper 32 bits are zero. ssize_t imm = -1; @@ -6899,7 +6899,7 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d case GenIntCastDesc::CHECK_POSITIVE_INT_RANGE: { - regNumber tempReg = cast->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(cast); // We need to check if the value is not greater than 0x7FFFFFFF // if the upper 33 bits are zero. // instGen_Set_Reg_To_Imm(EA_8BYTE, tempReg, 0xFFFFFFFF80000000LL); @@ -6915,7 +6915,7 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d case GenIntCastDesc::CHECK_INT_RANGE: { - const regNumber tempReg = cast->GetSingleTempReg(); + const regNumber tempReg = internalRegisters.GetSingle(cast); assert(tempReg != reg); GetEmitter()->emitLoadImmediate(EA_8BYTE, tempReg, INT32_MAX); genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_blt, tempReg, nullptr, reg); @@ -6930,7 +6930,7 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d assert(desc.CheckKind() == GenIntCastDesc::CHECK_SMALL_INT_RANGE); const int castMaxValue = desc.CheckSmallIntMax(); const int castMinValue = desc.CheckSmallIntMin(); - const regNumber tempReg = cast->GetSingleTempReg(); + const regNumber tempReg = internalRegisters.GetSingle(cast); instruction ins; if (castMaxValue > 2047) @@ -7229,7 +7229,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) assert(isPow2(lea->gtScale)); BitScanForward(&scale, lea->gtScale); assert(scale <= 4); - regNumber scaleTempReg = scale ? lea->ExtractTempReg() : REG_NA; + regNumber scaleTempReg = scale ? internalRegisters.Extract(lea) : REG_NA; if (offset == 0) { @@ -7250,7 +7250,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) } else { - regNumber tmpReg = lea->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(lea); noway_assert(tmpReg != index->GetRegNum()); noway_assert(tmpReg != memBase->GetRegNum()); @@ -7287,7 +7287,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) else { // We require a tmpReg to hold the offset - regNumber tmpReg = lea->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(lea); // First load tmpReg with the large offset constant emit->emitLoadImmediate(EA_PTRSIZE, tmpReg, offset); diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 4901ee9e3aa086..a2a17e735c9038 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -914,7 +914,7 @@ void CodeGen::genCodeForLongUMod(GenTreeOp* node) // xor edx, edx // div divisor->GetRegNum() // mov eax, temp - const regNumber tempReg = node->GetSingleTempReg(); + const regNumber tempReg = internalRegisters.GetSingle(node); inst_Mov(TYP_INT, tempReg, REG_EAX, /* canSkip */ false); inst_Mov(TYP_INT, REG_EAX, REG_EDX, /* canSkip */ false); instGen_Set_Reg_To_Zero(EA_PTRSIZE, REG_EDX); @@ -1761,7 +1761,7 @@ void CodeGen::genCodeForReturnTrap(GenTreeOp* tree) inst_JMP(EJ_je, skipLabel); // emit the call to the EE-helper that stops for GC (or other reasons) - regNumber tmpReg = tree->GetSingleTempReg(RBM_ALLINT); + regNumber tmpReg = internalRegisters.GetSingle(tree, RBM_ALLINT); assert(genIsValidIntReg(tmpReg)); genEmitHelperCall(CORINFO_HELP_STOP_FOR_GC, 0, EA_UNKNOWN, tmpReg); @@ -2334,7 +2334,7 @@ void CodeGen::genMultiRegStoreToSIMDLocal(GenTreeLclVar* lclNode) } else { - regNumber tempXmm = lclNode->GetSingleTempReg(); + regNumber tempXmm = internalRegisters.GetSingle(lclNode); assert(tempXmm != targetReg); inst_Mov(TYP_FLOAT, tempXmm, reg1, /* canSkip */ false); GetEmitter()->emitIns_SIMD_R_R_R(INS_punpckldq, size, targetReg, targetReg, tempXmm); @@ -2675,7 +2675,7 @@ void CodeGen::genCodeForMemmove(GenTreeBlk* tree) if ((size >= simdSize) && (simdSize > 0)) { // Number of SIMD regs needed to save the whole src to regs. - unsigned numberOfSimdRegs = tree->AvailableTempRegCount(RBM_ALLFLOAT); + unsigned numberOfSimdRegs = internalRegisters.Count(tree, RBM_ALLFLOAT); // Lowering takes care to only introduce this node such that we will always have enough // temporary SIMD registers to fully load the source and avoid any potential issues with overlap. @@ -2685,7 +2685,7 @@ void CodeGen::genCodeForMemmove(GenTreeBlk* tree) regNumber tempRegs[LinearScan::MaxInternalCount] = {}; for (unsigned i = 0; i < numberOfSimdRegs; i++) { - tempRegs[i] = tree->ExtractTempReg(RBM_ALLFLOAT); + tempRegs[i] = internalRegisters.Extract(tree, RBM_ALLFLOAT); } auto emitSimdLoadStore = [&](bool load) { @@ -2770,15 +2770,15 @@ void CodeGen::genCodeForMemmove(GenTreeBlk* tree) unsigned loadStoreSize = 1 << BitOperations::Log2(size); if (loadStoreSize == size) { - regNumber tmpReg = tree->GetSingleTempReg(RBM_ALLINT); + regNumber tmpReg = internalRegisters.GetSingle(tree, RBM_ALLINT); emitScalarLoadStore(/* load */ true, loadStoreSize, tmpReg, 0); emitScalarLoadStore(/* load */ false, loadStoreSize, tmpReg, 0); } else { - assert(tree->AvailableTempRegCount() == 2); - regNumber tmpReg1 = tree->ExtractTempReg(RBM_ALLINT); - regNumber tmpReg2 = tree->ExtractTempReg(RBM_ALLINT); + assert(internalRegisters.Count(tree) == 2); + regNumber tmpReg1 = internalRegisters.Extract(tree, RBM_ALLINT); + regNumber tmpReg2 = internalRegisters.Extract(tree, RBM_ALLINT); emitScalarLoadStore(/* load */ true, loadStoreSize, tmpReg1, 0); emitScalarLoadStore(/* load */ true, loadStoreSize, tmpReg2, size - loadStoreSize); emitScalarLoadStore(/* load */ false, loadStoreSize, tmpReg1, 0); @@ -2855,12 +2855,12 @@ void CodeGen::genLclHeap(GenTree* tree) // since we don't need any internal registers. if (compiler->info.compInitMem) { - assert(tree->AvailableTempRegCount() == 0); + assert(internalRegisters.Count(tree) == 0); regCnt = targetReg; } else { - regCnt = tree->GetSingleTempReg(); + regCnt = internalRegisters.GetSingle(tree); // Above, we put the size in targetReg. Now, copy it to our new temp register if necessary. inst_Mov(size->TypeGet(), regCnt, targetReg, /* canSkip */ true); @@ -2954,7 +2954,7 @@ void CodeGen::genLclHeap(GenTree* tree) // via BLK explicitly, so just bump the stack pointer. if ((amount >= compiler->eeGetPageSize()) || (TARGET_POINTER_SIZE == 4)) { - regCnt = tree->GetSingleTempReg(); + regCnt = internalRegisters.GetSingle(tree); instGen_Set_Reg_To_Imm(EA_PTRSIZE, regCnt, -(ssize_t)amount); genStackPointerDynamicAdjustmentWithProbe(regCnt); // lastTouchDelta is dynamic, and can be up to a page. So if we have outgoing arg space, @@ -2971,7 +2971,7 @@ void CodeGen::genLclHeap(GenTree* tree) } // We should not have any temp registers at this point. - assert(tree->AvailableTempRegCount() == 0); + assert(internalRegisters.Count(tree) == 0); if (compiler->info.compInitMem) { @@ -3234,7 +3234,7 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) #ifdef FEATURE_SIMD if (willUseSimdMov) { - regNumber srcXmmReg = node->GetSingleTempReg(RBM_ALLFLOAT); + regNumber srcXmmReg = internalRegisters.GetSingle(node, RBM_ALLFLOAT); unsigned regSize = compiler->roundDownSIMDSize(size); var_types loadType = compiler->getSIMDTypeForSize(regSize); simd_t vecCon; @@ -3392,7 +3392,7 @@ void CodeGen::genCodeForInitBlkLoop(GenTreeBlk* initBlkNode) // Extend liveness of dstReg in case if it gets killed by the store. gcInfo.gcMarkRegPtrVal(dstReg, dstNode->TypeGet()); - const regNumber offsetReg = initBlkNode->GetSingleTempReg(); + const regNumber offsetReg = internalRegisters.GetSingle(initBlkNode); instGen_Set_Reg_To_Imm(EA_PTRSIZE, offsetReg, size - TARGET_POINTER_SIZE); BasicBlock* loop = genCreateTempLabel(); @@ -3531,7 +3531,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) if ((size >= regSize) && (regSize > 0)) { - regNumber tempReg = node->GetSingleTempReg(RBM_ALLFLOAT); + regNumber tempReg = internalRegisters.GetSingle(node, RBM_ALLFLOAT); instruction simdMov = simdUnalignedMovIns(); @@ -3593,7 +3593,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) // Fill the remainder with normal loads/stores if (size > 0) { - regNumber tempReg = node->GetSingleTempReg(RBM_ALLINT); + regNumber tempReg = internalRegisters.GetSingle(node, RBM_ALLINT); #ifdef TARGET_AMD64 unsigned regSize = REGSIZE_BYTES; @@ -3878,11 +3878,11 @@ void CodeGen::genStructPutArgUnroll(GenTreePutArgStk* putArgNode) if (loadSize >= XMM_REGSIZE_BYTES) #endif { - xmmTmpReg = putArgNode->GetSingleTempReg(RBM_ALLFLOAT); + xmmTmpReg = internalRegisters.GetSingle(putArgNode, RBM_ALLFLOAT); } if ((loadSize % XMM_REGSIZE_BYTES) != 0) { - intTmpReg = putArgNode->GetSingleTempReg(RBM_ALLINT); + intTmpReg = internalRegisters.GetSingle(putArgNode, RBM_ALLINT); } #ifdef TARGET_X86 @@ -3934,7 +3934,7 @@ void CodeGen::genStructPutArgRepMovs(GenTreePutArgStk* putArgNode) // Make sure we got the arguments of the cpblk operation in the right registers, and that // 'src' is contained as expected. - assert(putArgNode->gtRsvdRegs == (RBM_RDI | RBM_RCX | RBM_RSI)); + assert(internalRegisters.GetAll(putArgNode) == (RBM_RDI | RBM_RCX | RBM_RSI)); assert(src->isContained()); genConsumePutStructArgStk(putArgNode, REG_RDI, REG_RSI, REG_RCX); @@ -4219,7 +4219,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) { // If the destination of the CpObj is on the stack, make sure we allocated // RCX to emit the movsp (alias for movsd or movsq for 32 and 64 bits respectively). - assert((cpObjNode->gtRsvdRegs & RBM_RCX) != 0); + assert((internalRegisters.GetAll(cpObjNode) & RBM_RCX) != 0); GetEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, slots); instGen(INS_r_movsp); @@ -4269,7 +4269,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) { // Otherwise, we can save code-size and improve CQ by emitting // rep movsp (alias for movsd/movsq for x86/x64) - assert((cpObjNode->gtRsvdRegs & RBM_RCX) != 0); + assert((internalRegisters.GetAll(cpObjNode) & RBM_RCX) != 0); GetEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, nonGcSlotCount); instGen(INS_r_movsp); @@ -4300,7 +4300,7 @@ void CodeGen::genTableBasedSwitch(GenTree* treeNode) regNumber idxReg = treeNode->AsOp()->gtOp1->GetRegNum(); regNumber baseReg = treeNode->AsOp()->gtOp2->GetRegNum(); - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); // load the ip-relative offset (which is relative to start of fgFirstBB) GetEmitter()->emitIns_R_ARX(INS_mov, EA_4BYTE, baseReg, baseReg, idxReg, 4, 0); @@ -4427,7 +4427,7 @@ void CodeGen::genLockedInstructions(GenTreeOp* node) // Extend liveness of addr gcInfo.gcMarkRegPtrVal(addr->GetRegNum(), addr->TypeGet()); - const regNumber tmpReg = node->GetSingleTempReg(); + const regNumber tmpReg = internalRegisters.GetSingle(node); GetEmitter()->emitIns_R_AR(INS_mov, size, REG_RAX, addr->GetRegNum(), 0); BasicBlock* loop = genCreateTempLabel(); genDefineTempLabel(loop); @@ -5306,7 +5306,7 @@ void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) regNumber tmpReg = REG_NA; #ifdef TARGET_64BIT - tmpReg = node->GetSingleTempReg(); + tmpReg = internalRegisters.GetSingle(node); #endif // Generate the bounds check if necessary. @@ -5356,7 +5356,7 @@ void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) // The VM doesn't allow such large array elements but let's be sure. noway_assert(scale <= INT32_MAX); #else // !TARGET_64BIT - tmpReg = node->GetSingleTempReg(); + tmpReg = internalRegisters.GetSingle(node); #endif // !TARGET_64BIT GetEmitter()->emitIns_R_I(emitter::inst3opImulForReg(tmpReg), EA_PTRSIZE, indexReg, @@ -7239,7 +7239,7 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d // We need to check if the value is not greater than 0xFFFFFFFF but this value // cannot be encoded in an immediate operand. Use a right shift to test if the // upper 32 bits are zero. This requires a temporary register. - const regNumber tempReg = cast->GetSingleTempReg(); + const regNumber tempReg = internalRegisters.GetSingle(cast); assert(tempReg != reg); GetEmitter()->emitIns_Mov(INS_mov, EA_8BYTE, tempReg, reg, /* canSkip */ false); GetEmitter()->emitIns_R_I(INS_shr_N, EA_8BYTE, tempReg, 32); @@ -7255,7 +7255,7 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d case GenIntCastDesc::CHECK_INT_RANGE: { // Emit "if ((long)(int)x != x) goto OVERFLOW" - const regNumber regTmp = cast->GetSingleTempReg(); + const regNumber regTmp = internalRegisters.GetSingle(cast); GetEmitter()->emitIns_Mov(INS_movsxd, EA_8BYTE, regTmp, reg, true); GetEmitter()->emitIns_R_R(INS_cmp, EA_8BYTE, reg, regTmp); genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW); @@ -7666,7 +7666,7 @@ void CodeGen::genCkfinite(GenTree* treeNode) regNumber targetReg = treeNode->GetRegNum(); // Extract exponent into a register. - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); genConsumeReg(op1); @@ -8357,17 +8357,17 @@ void CodeGen::genPutArgStkFieldList(GenTreePutArgStk* putArgStk) unsigned prevFieldOffset = currentOffset; regNumber intTmpReg = REG_NA; regNumber simdTmpReg = REG_NA; - if (putArgStk->AvailableTempRegCount() != 0) + if (internalRegisters.Count(putArgStk) != 0) { - regMaskTP rsvdRegs = putArgStk->gtRsvdRegs; + regMaskTP rsvdRegs = internalRegisters.GetAll(putArgStk); if ((rsvdRegs & RBM_ALLINT) != 0) { - intTmpReg = putArgStk->GetSingleTempReg(RBM_ALLINT); + intTmpReg = internalRegisters.GetSingle(putArgStk, RBM_ALLINT); assert(genIsValidIntReg(intTmpReg)); } if ((rsvdRegs & RBM_ALLFLOAT) != 0) { - simdTmpReg = putArgStk->GetSingleTempReg(RBM_ALLFLOAT); + simdTmpReg = internalRegisters.GetSingle(putArgStk, RBM_ALLFLOAT); assert(genIsValidFloatReg(simdTmpReg)); } assert(genCountBits(rsvdRegs) == (unsigned)((intTmpReg == REG_NA) ? 0 : 1) + ((simdTmpReg == REG_NA) ? 0 : 1)); diff --git a/src/coreclr/jit/emitarm.cpp b/src/coreclr/jit/emitarm.cpp index 81331547b4a924..65a6e098b2976a 100644 --- a/src/coreclr/jit/emitarm.cpp +++ b/src/coreclr/jit/emitarm.cpp @@ -7869,15 +7869,15 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR var_types type = indir->AsStoreInd()->Data()->TypeGet(); if (type == TYP_FLOAT) { - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); emitIns_Mov(INS_vmov_f2i, EA_4BYTE, tmpReg, dataReg, /* canSkip */ false); emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg, indir, 0); return; } else if (type == TYP_DOUBLE) { - regNumber tmpReg1 = indir->ExtractTempReg(); - regNumber tmpReg2 = indir->GetSingleTempReg(); + regNumber tmpReg1 = codeGen->internalRegisters.Extract(indir); + regNumber tmpReg2 = codeGen->internalRegisters.GetSingle(indir); emitIns_R_R_R(INS_vmov_d2i, EA_8BYTE, tmpReg1, tmpReg2, dataReg); emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg1, indir, 0); emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg2, indir, 4); @@ -7889,15 +7889,15 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR var_types type = indir->TypeGet(); if (type == TYP_FLOAT) { - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg, indir, 0); emitIns_Mov(INS_vmov_i2f, EA_4BYTE, dataReg, tmpReg, /* canSkip */ false); return; } else if (type == TYP_DOUBLE) { - regNumber tmpReg1 = indir->ExtractTempReg(); - regNumber tmpReg2 = indir->GetSingleTempReg(); + regNumber tmpReg1 = codeGen->internalRegisters.Extract(indir); + regNumber tmpReg2 = codeGen->internalRegisters.GetSingle(indir); emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg1, indir, 0); emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg2, indir, 4); emitIns_R_R_R(INS_vmov_i2d, EA_8BYTE, dataReg, tmpReg1, tmpReg2); @@ -7940,7 +7940,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR if (offset != 0) { - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); // If the LEA produces a GCREF or BYREF, we need to be careful to mark any temp register // computed with the base register as a BYREF. @@ -8023,7 +8023,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR else { // We require a tmpReg to hold the offset - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); // First load/store tmpReg with the large offset constant codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset); @@ -8175,7 +8175,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, { if (isMulOverflow) { - regNumber extraReg = dst->GetSingleTempReg(); + regNumber extraReg = codeGen->internalRegisters.GetSingle(dst); assert(extraReg != dst->GetRegNum()); if ((dst->gtFlags & GTF_UNSIGNED) != 0) diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index 181b9706e41611..3c988633e798b9 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -14243,7 +14243,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR if (offset != 0) { - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE; @@ -14350,7 +14350,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR else { // We require a tmpReg to hold the offset - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); // First load/store tmpReg with the large offset constant codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset); @@ -14490,7 +14490,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, { if (isMulOverflow) { - regNumber extraReg = dst->GetSingleTempReg(); + regNumber extraReg = codeGen->internalRegisters.GetSingle(dst); assert(extraReg != dst->GetRegNum()); if ((dst->gtFlags & GTF_UNSIGNED) != 0) @@ -16996,7 +16996,7 @@ void emitter::emitStoreSimd12ToLclOffset(unsigned varNum, unsigned offset, regNu emitIns_S_R(INS_str, EA_8BYTE, dataReg, varNum, offset); // Extract upper 4-bytes from data - regNumber tmpReg = tmpRegProvider->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(tmpRegProvider); emitIns_R_R_I(INS_mov, EA_4BYTE, tmpReg, dataReg, 2); // 4-byte write diff --git a/src/coreclr/jit/emitloongarch64.cpp b/src/coreclr/jit/emitloongarch64.cpp index 63d4e9a975b9b1..43281e536e8b31 100644 --- a/src/coreclr/jit/emitloongarch64.cpp +++ b/src/coreclr/jit/emitloongarch64.cpp @@ -4586,7 +4586,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR if (offset != 0) { - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); if (isValidSimm12(offset)) { @@ -4727,7 +4727,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR else { // We require a tmpReg to hold the offset - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); // First load/store tmpReg with the large offset constant emitIns_I_la(EA_PTRSIZE, tmpReg, offset); @@ -5058,7 +5058,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, if ((dst->gtFlags & GTF_UNSIGNED) == 0) { - saveOperReg2 = dst->GetSingleTempReg(); + saveOperReg2 = codeGen->internalRegisters.GetSingle(dst); assert((saveOperReg2 != REG_RA) && (saveOperReg2 != REG_R21)); assert(REG_RA != regOp1); assert(saveOperReg2 != regOp2); diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index d78fc0e9d5b29b..932c9a1125b016 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -4463,7 +4463,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR if (offset != 0) { - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); if (isValidSimm12(offset)) { @@ -4496,7 +4496,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg)); noway_assert(tmpReg != index->GetRegNum()); - regNumber scaleReg = indir->GetSingleTempReg(); + regNumber scaleReg = codeGen->internalRegisters.GetSingle(indir); // Then load/store dataReg from/to [tmpReg + index*scale] emitIns_R_R_I(INS_slli, addType, scaleReg, index->GetRegNum(), lsl); emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, scaleReg); @@ -4605,7 +4605,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR else { // We require a tmpReg to hold the offset - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); // First load/store tmpReg with the large offset constant emitLoadImmediate(EA_PTRSIZE, tmpReg, offset); @@ -4771,7 +4771,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, assert(ins == INS_addi || ins == INS_addiw || ins == INS_andi || ins == INS_ori || ins == INS_xori); - regNumber tempReg = needCheckOv ? dst->ExtractTempReg() : REG_NA; + regNumber tempReg = needCheckOv ? codeGen->internalRegisters.Extract(dst) : REG_NA; if (needCheckOv) { @@ -4823,7 +4823,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, } else { - regNumber tempReg = needCheckOv ? dst->ExtractTempReg() : REG_NA; + regNumber tempReg = needCheckOv ? codeGen->internalRegisters.Extract(dst) : REG_NA; switch (dst->OperGet()) { @@ -4897,7 +4897,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, } else { - regNumber tempReg2 = dst->ExtractTempReg(); + regNumber tempReg2 = codeGen->internalRegisters.Extract(dst); assert(tempReg2 != dstReg); assert(tempReg2 != src1Reg); assert(tempReg2 != src2Reg); @@ -5003,7 +5003,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, else { tempReg1 = REG_RA; - tempReg2 = dst->ExtractTempReg(); + tempReg2 = codeGen->internalRegisters.Extract(dst); assert(tempReg1 != tempReg2); assert(tempReg1 != saveOperReg1); assert(tempReg2 != saveOperReg2); diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 6bf148cf2d8883..35cb3a986ee580 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -5641,7 +5641,7 @@ void emitter::emitStoreSimd12ToLclOffset(unsigned varNum, unsigned offset, regNu } else { - regNumber tmpReg = tmpRegProvider->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(tmpRegProvider); assert(isFloatReg(tmpReg)); // Extract upper 4 bytes from data diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 8076662e183e44..d48fc45868ba22 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -9782,7 +9782,6 @@ GenTree* Compiler::gtCloneExpr(GenTree* tree) /* Make sure to copy back fields that may have been initialized */ copy->CopyRawCosts(tree); - copy->gtRsvdRegs = tree->gtRsvdRegs; copy->CopyReg(tree); return copy; } @@ -11644,7 +11643,7 @@ void Compiler::gtDispNode(GenTree* tree, IndentStack* indentStack, _In_ _In_opt_ if (verbose && 0) { printf(" RR="); - dspRegMask(tree->gtRsvdRegs); + dspRegMask(JitTls::GetCompiler()->codeGen->internalRegisters.GetAll(tree)); printf("\n"); } } @@ -27720,75 +27719,14 @@ regMaskTP ReturnTypeDesc::GetABIReturnRegs(CorInfoCallConvExtension callConv) co } //------------------------------------------------------------------------ -// The following functions manage the gtRsvdRegs set of temporary registers -// created by LSRA during code generation. - -//------------------------------------------------------------------------ -// AvailableTempRegCount: return the number of available temporary registers in the (optional) given set -// (typically, RBM_ALLINT or RBM_ALLFLOAT). -// -// Arguments: -// mask - (optional) Check for available temporary registers only in this set. -// -// Return Value: -// Count of available temporary registers in given set. -// -unsigned GenTree::AvailableTempRegCount(regMaskTP mask /* = (regMaskTP)-1 */) const -{ - return genCountBits(gtRsvdRegs & mask); -} - -//------------------------------------------------------------------------ -// GetSingleTempReg: There is expected to be exactly one available temporary register -// in the given mask in the gtRsvdRegs set. Get that register. No future calls to get -// a temporary register are expected. Removes the register from the set, but only in -// DEBUG to avoid doing unnecessary work in non-DEBUG builds. +// GetNum: Get the SSA number for a given field. // -// Arguments: -// mask - (optional) Get an available temporary register only in this set. -// -// Return Value: -// Available temporary register in given mask. -// -regNumber GenTree::GetSingleTempReg(regMaskTP mask /* = (regMaskTP)-1 */) -{ - regMaskTP availableSet = gtRsvdRegs & mask; - assert(genCountBits(availableSet) == 1); - regNumber tempReg = genRegNumFromMask(availableSet); - INDEBUG(gtRsvdRegs &= ~availableSet;) // Remove the register from the set, so it can't be used again. - return tempReg; -} - -//------------------------------------------------------------------------ -// ExtractTempReg: Find the lowest number temporary register from the gtRsvdRegs set -// that is also in the optional given mask (typically, RBM_ALLINT or RBM_ALLFLOAT), -// and return it. Remove this register from the temporary register set, so it won't -// be returned again. -// -// Arguments: -// mask - (optional) Extract an available temporary register only in this set. -// -// Return Value: -// Available temporary register in given mask. -// -regNumber GenTree::ExtractTempReg(regMaskTP mask /* = (regMaskTP)-1 */) -{ - regMaskTP availableSet = gtRsvdRegs & mask; - assert(genCountBits(availableSet) >= 1); - regNumber tempReg = genFirstRegNumFromMask(availableSet); - gtRsvdRegs ^= genRegMask(tempReg); - return tempReg; -} - -//------------------------------------------------------------------------ -// GetNum: Get the SSA number for a given field. -// -// Arguments: -// compiler - The Compiler instance -// index - The field index +// Arguments: +// compiler - The Compiler instance +// index - The field index // -// Return Value: -// The SSA number corresponding to the field at "index". +// Return Value: +// The SSA number corresponding to the field at "index". // unsigned SsaNumInfo::GetNum(Compiler* compiler, unsigned index) const { diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index 2f3a2a7b2f573b..7dbfef174994e6 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -956,12 +956,6 @@ struct GenTree ValueNumPair gtVNPair; - regMaskSmall gtRsvdRegs; // set of fixed trashed registers - - unsigned AvailableTempRegCount(regMaskTP mask = (regMaskTP)-1) const; - regNumber GetSingleTempReg(regMaskTP mask = (regMaskTP)-1); - regNumber ExtractTempReg(regMaskTP mask = (regMaskTP)-1); - void SetVNsFromNode(GenTree* tree) { gtVNPair = tree->gtVNPair; diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index aadd8fcf28e000..f58ca6c6e858d5 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -99,7 +99,7 @@ CodeGen::HWIntrinsicImmOpHelper::HWIntrinsicImmOpHelper(CodeGen* codeGen, GenTre // using the same approach as in hwintrinsicxarch.cpp - adding an additional indirection level in form of a // branch table. assert(!HWIntrinsicInfo::GeneratesMultipleIns(intrin->GetHWIntrinsicId())); - branchTargetReg = intrin->GetSingleTempReg(); + branchTargetReg = codeGen->internalRegisters.GetSingle(intrin); } endLabel = codeGen->genCreateTempLabel(); @@ -1206,7 +1206,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) if (intrin.op1->OperIsLocal()) { unsigned varNum = intrin.op1->AsLclVarCommon()->GetLclNum(); - baseReg = node->ExtractTempReg(); + baseReg = internalRegisters.Extract(node); // Load the address of varNum GetEmitter()->emitIns_R_S(INS_lea, EA_PTRSIZE, baseReg, varNum, 0); @@ -1226,7 +1226,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) unsigned simdInitTempVarNum = compiler->lvaSIMDInitTempVarNum; noway_assert(simdInitTempVarNum != BAD_VAR_NUM); - baseReg = node->ExtractTempReg(); + baseReg = internalRegisters.Extract(node); // Load the address of simdInitTempVarNum GetEmitter()->emitIns_R_S(INS_lea, EA_PTRSIZE, baseReg, simdInitTempVarNum, 0); diff --git a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp index 79e6b497c368a9..a4b6748f3db531 100644 --- a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp @@ -323,8 +323,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) insOpts newInstOptions = AddEmbRoundingMode(instOptions, i); genHWIntrinsic_R_RM(node, ins, simdSize, targetReg, rmOp, newInstOptions); }; - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; @@ -335,8 +335,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) insOpts newInstOptions = AddEmbRoundingMode(instOptions, i); genHWIntrinsic_R_R_RM(node, ins, simdSize, newInstOptions); }; - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; @@ -524,8 +524,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // Reflection. However, it // can also occur if the consumer calls it directly and just doesn't pass a // constant value. - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, op2Reg, baseReg, offsReg, emitSwCase); } } @@ -574,8 +574,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // We emit a fallback case for the scenario when the imm-op is not a constant. This should // normally happen when the intrinsic is called indirectly, such as via Reflection. However, it // can also occur if the consumer calls it directly and just doesn't pass a constant value. - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, op3Reg, baseReg, offsReg, emitSwCase); } } @@ -670,8 +670,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // We emit a fallback case for the scenario when the imm-op is not a constant. This should // normally happen when the intrinsic is called indirectly, such as via Reflection. However, it // can also occur if the consumer calls it directly and just doesn't pass a constant value. - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, op4Reg, baseReg, offsReg, emitSwCase); } } @@ -1373,8 +1373,8 @@ void CodeGen::genNonTableDrivenHWIntrinsicsJumpTableFallback(GenTreeHWIntrinsic* insOpts newInstOptions = AddEmbRoundingMode(instOptions, i); genHWIntrinsic_R_RM(node, ins, attr, targetReg, rmOp, newInstOptions); }; - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; } @@ -1394,8 +1394,8 @@ void CodeGen::genNonTableDrivenHWIntrinsicsJumpTableFallback(GenTreeHWIntrinsic* insOpts newInstOptions = AddEmbRoundingMode(instOptions, i); genHWIntrinsic_R_RM(node, ins, attr, targetReg, rmOp, newInstOptions); }; - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; } @@ -1408,8 +1408,8 @@ void CodeGen::genNonTableDrivenHWIntrinsicsJumpTableFallback(GenTreeHWIntrinsic* insOpts newInstOptions = AddEmbRoundingMode(instOptions, i); genHWIntrinsic_R_R_RM(node, ins, EA_8BYTE, newInstOptions); }; - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; } @@ -1440,8 +1440,8 @@ void CodeGen::genNonTableDrivenHWIntrinsicsJumpTableFallback(GenTreeHWIntrinsic* insOpts newInstOptions = AddEmbRoundingMode(instOptions, i); genHWIntrinsic_R_R_R_RM(ins, attr, targetReg, op1Reg, op2Reg, op3, newInstOptions); }; - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; } @@ -2074,8 +2074,8 @@ void CodeGen::genSSE41Intrinsic(GenTreeHWIntrinsic* node) // We emit a fallback case for the scenario when the imm-op is not a constant. This should // normally happen when the intrinsic is called indirectly, such as via Reflection. However, it // can also occur if the consumer calls it directly and just doesn't pass a constant value. - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, op2->GetRegNum(), baseReg, offsReg, emitSwCase); } break; @@ -2225,7 +2225,7 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption regNumber op2Reg = op2->GetRegNum(); regNumber addrBaseReg = REG_NA; regNumber addrIndexReg = REG_NA; - regNumber maskReg = node->ExtractTempReg(RBM_ALLFLOAT); + regNumber maskReg = internalRegisters.Extract(node, RBM_ALLFLOAT); if (numArgs == 5) { @@ -2902,7 +2902,7 @@ void CodeGen::genBMI1OrBMI2Intrinsic(GenTreeHWIntrinsic* node, insOpts instOptio assert(op3Reg != op1Reg); assert(op3Reg != targetReg); assert(op3Reg != REG_EDX); - lowReg = node->GetSingleTempReg(); + lowReg = internalRegisters.GetSingle(node); assert(op3Reg != lowReg); assert(lowReg != targetReg); } diff --git a/src/coreclr/jit/jithashtable.h b/src/coreclr/jit/jithashtable.h index f699c3eee19d24..7f9153b75864a7 100644 --- a/src/coreclr/jit/jithashtable.h +++ b/src/coreclr/jit/jithashtable.h @@ -233,7 +233,7 @@ class JitHashTable } //------------------------------------------------------------------------ - // Lookup: Get a pointer to the value associated to the specified key. + // LookupPointer: Get a pointer to the value associated to the specified key. // if any. // // Arguments: @@ -261,6 +261,48 @@ class JitHashTable } } + //------------------------------------------------------------------------ + // LookupPointerOrAdd: Get a pointer to the value associated to the specified key. + // If not present, add it with the specified default value and return a pointer to it. + // + // Arguments: + // k - the key + // defaultValue - Default value to add to the table if the key was not present + // + // Return Value: + // A pointer to the value associated with the specified key. + // + Value* LookupPointerOrAdd(Key k, Value defaultValue) + { + CheckGrowth(); + + assert(m_tableSizeInfo.prime != 0); + + unsigned index = GetIndexForKey(k); + + Node* n = m_table[index]; + while (n != nullptr) + { + if (KeyFuncs::Equals(k, n->m_key)) + { + return &n->m_val; + } + + n = n->m_next; + } + + n = new (m_alloc) Node(m_table[index], k, defaultValue); + m_table[index] = n; + m_tableCount++; + return &n->m_val; + } + + enum SetKind + { + None, + Overwrite + }; + //------------------------------------------------------------------------ // Set: Associate the specified value with the specified key. // @@ -279,12 +321,6 @@ class JitHashTable // If the key already exists and kind is Normal // this method will assert // - enum SetKind - { - None, - Overwrite - }; - bool Set(Key k, Value v, SetKind kind = None) { CheckGrowth(); diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index ebcb21fff18bc3..efd861348223dc 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -8106,7 +8106,7 @@ void LinearScan::resolveRegisters() assert(currentRefPosition->isIntervalRef()); if (currentRefPosition->getInterval()->isInternal) { - treeNode->gtRsvdRegs |= currentRefPosition->registerAssignment; + compiler->codeGen->internalRegisters.Add(treeNode, currentRefPosition->registerAssignment); } else { @@ -8918,7 +8918,7 @@ void LinearScan::handleOutgoingCriticalEdges(BasicBlock* block) GenTree* switchTable = LIR::AsRange(block).LastNode(); assert(switchTable != nullptr && switchTable->OperGet() == GT_SWITCH_TABLE); - consumedRegs = switchTable->gtRsvdRegs; + consumedRegs = compiler->codeGen->internalRegisters.GetAll(switchTable); GenTree* op1 = switchTable->gtGetOp1(); GenTree* op2 = switchTable->gtGetOp2(); noway_assert(op1 != nullptr && op2 != nullptr); diff --git a/src/coreclr/jit/lsraarmarch.cpp b/src/coreclr/jit/lsraarmarch.cpp index c2b8b74406584e..f88173e05e2092 100644 --- a/src/coreclr/jit/lsraarmarch.cpp +++ b/src/coreclr/jit/lsraarmarch.cpp @@ -181,16 +181,24 @@ int LinearScan::BuildCall(GenTreeCall* call) } else if (call->IsR2ROrVirtualStubRelativeIndir()) { - // For R2R and VSD we have stub address in REG_R2R_INDIRECT_PARAM - // and will load call address into the temp register from this register. - regMaskTP candidates = RBM_NONE; if (call->IsFastTailCall()) { - candidates = allRegs(TYP_INT) & RBM_INT_CALLEE_TRASH; + // For R2R and VSD we have stub address in REG_R2R_INDIRECT_PARAM + // and will load call address into the temp register from this register. + regMaskTP candidates = allRegs(TYP_INT) & RBM_INT_CALLEE_TRASH; assert(candidates != RBM_NONE); + buildInternalIntRegisterDefForNode(call, candidates); + } + else + { + // For arm64 we can use lr for non-tailcalls so we skip the + // internal register as a TP optimization. We could do the same for + // arm32, but loading into lr cannot be encoded in 2 bytes, so + // another register is usually better. +#ifdef TARGET_ARM + buildInternalIntRegisterDefForNode(call); +#endif } - - buildInternalIntRegisterDefForNode(call, candidates); } #ifdef TARGET_ARM else diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 37fa4320cc6918..22cba5900a7ddd 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -1730,10 +1730,6 @@ int LinearScan::ComputeAvailableSrcCount(GenTree* node) // void LinearScan::buildRefPositionsForNode(GenTree* tree, LsraLocation currentLoc) { - // The set of internal temporary registers used by this node are stored in the - // gtRsvdRegs register mask. Clear it out. - tree->gtRsvdRegs = RBM_NONE; - #ifdef DEBUG if (VERBOSE) { diff --git a/src/coreclr/jit/simdcodegenxarch.cpp b/src/coreclr/jit/simdcodegenxarch.cpp index d0fb1bf0aef4e8..aff087062f58fe 100644 --- a/src/coreclr/jit/simdcodegenxarch.cpp +++ b/src/coreclr/jit/simdcodegenxarch.cpp @@ -96,7 +96,7 @@ void CodeGen::genStoreIndTypeSimd12(GenTreeStoreInd* treeNode) } else { - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); // Extract upper 4 bytes from data emit->emitIns_R_R(INS_movhlps, EA_16BYTE, tmpReg, dataReg); @@ -295,7 +295,7 @@ void CodeGen::genEmitStoreLclTypeSimd12(GenTree* store, unsigned lclNum, unsigne } else { - regNumber tmpReg = store->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(store); // Extract upper 4 bytes from data emit->emitIns_R_R(INS_movhlps, EA_16BYTE, tmpReg, dataReg); @@ -391,7 +391,7 @@ void CodeGen::genPutArgStkSimd12(GenTreePutArgStk* treeNode) regNumber dataReg = genConsumeReg(data); // Need an additional Xmm register to extract upper 4 bytes from data. - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); genStoreSimd12ToStack(dataReg, tmpReg); } From 4170efe8fdc2dd06232b915076d1b77954632681 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 11:27:58 -0700 Subject: [PATCH 173/248] Bump actions/github-script from 6 to 7 (#101588) Bumps [actions/github-script](https://github.com/actions/github-script) from 6 to 7. - [Release notes](https://github.com/actions/github-script/releases) - [Commits](https://github.com/actions/github-script/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/github-script dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/bump-chrome-version.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/bump-chrome-version.yml b/.github/workflows/bump-chrome-version.yml index fc2f09cf3d01f7..e47563ca44a071 100644 --- a/.github/workflows/bump-chrome-version.yml +++ b/.github/workflows/bump-chrome-version.yml @@ -47,7 +47,7 @@ jobs: - name: Create PR if: steps.check_changes.outputs.has_changes == 'true' - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const { CHROME_LINUX_VER, CHROME_WIN_VER } = process.env; From 4ac82c948aa21554545362c86120a53ee9dff2fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 12:21:12 -0700 Subject: [PATCH 174/248] Bump actions/upload-artifact from 1 to 4 (#101587) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 1 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v1...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/aspnetcore-sync.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/aspnetcore-sync.yml b/.github/workflows/aspnetcore-sync.yml index 01aa3dfdabca60..12cc86c47b8983 100644 --- a/.github/workflows/aspnetcore-sync.yml +++ b/.github/workflows/aspnetcore-sync.yml @@ -42,7 +42,7 @@ jobs: mkdir ..\artifacts git status > ..\artifacts\status.txt git diff > ..\artifacts\diff.txt - - uses: actions/upload-artifact@v1 + - uses: actions/upload-artifact@v4 with: name: results path: artifacts From 261611930d6b436d7c4395450356b624d903d9bf Mon Sep 17 00:00:00 2001 From: Viktor Hofer Date: Mon, 29 Apr 2024 21:28:04 +0200 Subject: [PATCH 175/248] Replace usage of out-of-support TFM compiler directives (#101672) * Replace usage of out-of-support TFM compiler directives ... and directives for TFMs that we don't target anymore in main. Replaces the following directives with `NET` or `!NET`: - `#if NETCOREAPP2*` - `#if !NETCOREAPP2*` - `#if NETCOREAPP3*` - `#if !NETCOREAPP3*` - `#if NET5*` - `#if !NET5*` - `#if NET6*` - `#if !NET6*` - `#if NET7*` - `#if !NET7*` * Update EmitterTests.cs --- .../Utilities/LockFreeReaderHashtable.cs | 4 ++-- .../Common/src/Interop/Interop.Ldap.cs | 14 ++++++------ .../Common/src/Interop/Interop.Odbc.cs | 10 ++++----- .../CryptUI/Interop.CryptUIDlgCertificate.cs | 10 ++++----- .../Interop/Windows/Gdi32/Interop.AbortDoc.cs | 4 ++-- .../Gdi32/Interop.CreateCompatibleBitmap.cs | 4 ++-- .../Windows/Gdi32/Interop.CreateDIBSection.cs | 4 ++-- .../Interop/Windows/Gdi32/Interop.DEVMODE.cs | 2 +- .../Interop/Windows/Gdi32/Interop.EndDoc.cs | 4 ++-- .../Interop/Windows/Gdi32/Interop.EndPage.cs | 4 ++-- .../Windows/Gdi32/Interop.ExtEscape.cs | 6 ++--- .../Windows/Gdi32/Interop.GetDIBits.cs | 6 ++--- .../Windows/Gdi32/Interop.GetObject.cs | 8 +++---- .../Gdi32/Interop.GetPaletteEntries.cs | 4 ++-- .../Gdi32/Interop.IntersectClipRect.cs | 4 ++-- .../Interop/Windows/Gdi32/Interop.ResetDC.cs | 6 ++--- .../Interop/Windows/Gdi32/Interop.StartDoc.cs | 8 +++---- .../Windows/Gdi32/Interop.StartPage.cs | 4 ++-- .../Windows/Kernel32/Interop.SelectObject.cs | 6 ++--- .../Shell32/Interop.ExtractAssociatedIcon.cs | 4 ++-- .../Windows/User32/Interop.CopyImage.cs | 4 ++-- .../Interop.CreateIconFromResourceEx.cs | 2 +- .../Windows/User32/Interop.DestroyIcon.cs | 4 ++-- .../Windows/User32/Interop.DrawIconEx.cs | 8 +++---- .../Windows/User32/Interop.GetIconInfo.cs | 4 ++-- .../User32/Interop.GetSystemMetrics.cs | 2 +- .../Windows/User32/Interop.LoadIcon.cs | 4 ++-- .../Windows/WinHttp/Interop.winhttp.cs | 6 ++--- .../Windows/WinHttp/Interop.winhttp_types.cs | 6 ++--- .../WinMm/Interop.waveOutGetDevCaps.cs | 6 ++--- .../Winspool/Interop.DocumentProperties.cs | 12 +++++----- .../Windows/Winspool/Interop.EnumPrinters.cs | 2 +- .../src/System/CodeDom/CodeTypeReference.cs | 4 ++-- .../CodeDom/CodeTypeReferenceCollection.cs | 4 ++-- .../Data/Common/DbConnectionOptions.Common.cs | 4 ++-- .../src/System/IO/TempFileCollection.cs | 2 +- .../Common/src/System/IO/Win32Marshal.cs | 2 +- .../Cryptography/Asn1/AttributeAsn.manual.cs | 2 +- .../Asn1/X509ExtensionAsn.manual.cs | 2 +- .../Cryptography/CryptoThrowHelper.Windows.cs | 6 ++--- ...0108HmacCounterKdfImplementationManaged.cs | 3 --- .../Threading/Tasks/TaskToAsyncResult.cs | 6 ++--- .../Common/src/System/ThrowHelper.cs | 12 +++++----- .../TestUtilities/System/AssertExtensions.cs | 10 ++++----- .../System/WindowsIdentityFixture.cs | 6 ++--- .../tests/TestUtilities/TestEventListener.cs | 2 +- .../src/IMemoryCache.cs | 2 +- .../MemoryCacheGetCurrentStatisticsTests.cs | 2 +- .../src/PhysicalFilesWatcher.cs | 2 +- .../src/WindowsServiceHelpers.cs | 2 +- .../src/HostBuilder.cs | 5 ----- .../ref/Microsoft.Extensions.Http.cs | 6 ++--- .../DefaultSocketsHttpHandlerBuilder.cs | 2 +- .../HttpClientBuilderExtensions.cs | 2 +- .../ISocketsHttpHandlerBuilder.cs | 2 +- .../SocketsHttpHandlerBuilderExtensions.cs | 2 +- .../src/Logging/HttpClientLoggerHandler.cs | 2 +- .../src/Logging/LoggingHttpMessageHandler.cs | 4 ++-- .../Logging/LoggingScopeHttpMessageHandler.cs | 4 ++-- .../Logging/HttpClientLoggerTest.cs | 6 ++--- .../Logging/LoggingUriOutputTests.cs | 2 +- .../SocketsHttpHandlerConfigurationTest.cs | 2 +- .../TestMessageHandler.cs | 2 +- .../SourceGenerationTests/EmitterTests.cs | 6 ++--- .../Generated/OptionsValidationTests.cs | 2 +- .../SourceGenerationTests/Generated/Utils.cs | 4 ++-- .../TestClasses/Models.cs | 2 +- .../System/Collections/Frozen/Constants.cs | 8 +------ .../Collections/Frozen/FrozenHashTable.cs | 2 +- .../System/Collections/Frozen/FrozenSet.cs | 2 +- .../Collections/Frozen/String/KeyAnalyzer.cs | 2 +- .../Frozen/String/LengthBuckets.cs | 4 ++-- .../Immutable/ImmutableArray_1.Builder.cs | 6 ++--- .../src/System/Polyfills.cs | 8 +++---- .../tests/Frozen/FrozenSetTests.cs | 2 +- .../ImplicitMachineConfigHost.cs | 2 +- .../src/DbConnectionOptions.cs | 4 ++-- .../src/System/Diagnostics/Activity.cs | 4 ++-- .../Diagnostics/Metrics/CounterAggregator.cs | 2 +- .../Diagnostics/Reader/UnsafeNativeMethods.cs | 10 ++++----- .../System/Formats/Asn1/AsnDecoder.Integer.cs | 2 +- .../System/Formats/Asn1/AsnWriter.Integer.cs | 2 +- .../System/Formats/Asn1/SetOfValueComparer.cs | 2 +- .../src/System/IO/Hashing/Crc32.cs | 4 ++-- .../src/System/IO/Hashing/Crc64.cs | 2 +- .../src/System/IO/Hashing/XxHash128.cs | 8 +++---- .../src/System/IO/Hashing/XxHash3.cs | 4 ++-- .../src/System/IO/Hashing/XxHashShared.cs | 22 +++++++++---------- .../tests/NonCryptoHashTestDriver.cs | 2 +- .../System.IO.Hashing/tests/XxHash128Tests.cs | 6 ++--- .../InternalRelationshipCollection.cs | 2 +- .../Packaging/PackUriHelper.PackUriScheme.cs | 2 +- .../tests/PipeReaderCopyToAsyncTests.cs | 2 +- .../src/System/IO/Ports/SerialPort.cs | 2 +- .../Internal/Utilities/StreamExtensions.cs | 2 +- .../Reflection/TypeLoading/General/Helpers.cs | 2 +- .../Reflection/TypeLoading/Types/RoType.cs | 2 +- .../tests/src/Tests/Type/TypeTests.cs | 2 +- .../src/Internal/Cryptography/PkcsHelpers.cs | 2 +- .../System/Security/Cryptography/Xml/Utils.cs | 2 +- .../Cryptography/Xml/XmlResolverHelper.cs | 4 ++-- .../src/System/ServiceModel/XmlBuffer.cs | 2 +- .../src/Internal/Synthesis/AudioBase.cs | 2 +- .../src/Internal/Synthesis/EngineSite.cs | 2 +- .../System/Text/CodePagesEncodingProvider.cs | 2 +- .../System.Text.Json/Common/JsonHelpers.cs | 2 +- .../ref/System.Text.Json.netcoreapp.cs | 2 +- .../Json/Document/JsonDocument.MetadataDb.cs | 2 +- .../src/System/Text/Json/JsonConstants.cs | 2 +- .../Reader/Utf8JsonReader.MultiSegment.cs | 2 +- .../DefaultJsonTypeInfoResolver.Converters.cs | 2 +- .../JsonMetadataServices.Converters.cs | 2 +- .../Metadata/JsonPropertyInfo.cs | 2 +- ...CollectionTests.Dictionary.NonStringKey.cs | 2 +- .../tests/Common/TestClasses/TestClasses.cs | 2 +- .../Text/RegularExpressions/RegexCharClass.cs | 6 ++--- .../Text/RegularExpressions/RegexWriter.cs | 2 +- .../src/System/Threading/StackHelper.cs | 2 +- .../FunctionalTests/Regex.Match.Tests.cs | 14 ++++++------ .../FunctionalTests/Regex.Tests.Common.cs | 4 ++-- .../tests/FunctionalTests/RegexRunnerTests.cs | 2 +- .../src/Base/DataflowBlock.cs | 2 +- .../src/Internal/Common.cs | 2 +- .../src/System/Media/SoundPlayer.cs | 2 +- .../X509Certificates/X509Certificate2UI.cs | 4 ++-- .../WebcilConverter.cs | 4 ++-- .../WebcilWasmWrapper.cs | 8 +++---- .../DiagnosticsServerRouterFactory.cs | 2 +- 128 files changed, 253 insertions(+), 267 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/LockFreeReaderHashtable.cs b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/LockFreeReaderHashtable.cs index 613ec30fa01d2e..1b772684dc1c13 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/LockFreeReaderHashtable.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/LockFreeReaderHashtable.cs @@ -367,7 +367,7 @@ public TValue AddOrGetExisting(TValue value) private TValue AddOrGetExistingInner(TValue value, out bool addedValue) { -#if NET5_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(value); #else if (value == null) @@ -596,7 +596,7 @@ public bool Contains(TKey key) /// Value from the hashtable if found, otherwise null. public TValue GetValueIfExists(TValue value) { -#if NET5_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(value); #else if (value == null) diff --git a/src/libraries/Common/src/Interop/Interop.Ldap.cs b/src/libraries/Common/src/Interop/Interop.Ldap.cs index 7fb63a1d3c5e20..4020dd0fe89bbb 100644 --- a/src/libraries/Common/src/Interop/Interop.Ldap.cs +++ b/src/libraries/Common/src/Interop/Interop.Ldap.cs @@ -4,7 +4,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif using System.Security.Authentication; @@ -31,7 +31,7 @@ internal readonly struct Luid public int HighPart => _highPart; } -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #endif [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] @@ -49,7 +49,7 @@ internal struct SEC_WINNT_AUTH_IDENTITY_EX public string packageList; public int packageListLength; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(SEC_WINNT_AUTH_IDENTITY_EX), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] internal static class Marshaller { @@ -176,7 +176,7 @@ internal struct LDAP_TIMEVAL public int tv_usec; } -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(PinningMarshaller))] #endif [StructLayout(LayoutKind.Sequential)] @@ -185,7 +185,7 @@ internal sealed class BerVal public int bv_len; public IntPtr bv_val = IntPtr.Zero; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(BerVal), MarshalMode.ManagedToUnmanagedIn, typeof(PinningMarshaller))] internal static unsafe class PinningMarshaller { @@ -207,7 +207,7 @@ internal sealed class LdapControl public LdapControl() { } } -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #endif [StructLayout(LayoutKind.Sequential)] @@ -217,7 +217,7 @@ internal struct LdapReferralCallback public QUERYFORCONNECTIONInternal query; public NOTIFYOFNEWCONNECTIONInternal notify; public DEREFERENCECONNECTIONInternal dereference; -#if NET7_0_OR_GREATER +#if NET public static readonly unsafe int Size = sizeof(Marshaller.MarshalValue.Native); [CustomMarshaller(typeof(LdapReferralCallback), MarshalMode.ManagedToUnmanagedIn, typeof(MarshalValue))] diff --git a/src/libraries/Common/src/Interop/Interop.Odbc.cs b/src/libraries/Common/src/Interop/Interop.Odbc.cs index 250ef4371298b3..3e751856262025 100644 --- a/src/libraries/Common/src/Interop/Interop.Odbc.cs +++ b/src/libraries/Common/src/Interop/Interop.Odbc.cs @@ -5,7 +5,7 @@ using System.Data.Odbc; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif using System.Runtime.Versioning; @@ -38,7 +38,7 @@ internal static partial ODBC32.SQLRETURN SQLAllocHandle( /*SQLUSMALLINT*/ushort ColumnNumber, /*SQLSMALLINT*/ODBC32.SQL_C TargetType, /*SQLPOINTER*/ -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef TargetValue, @@ -64,13 +64,13 @@ internal static partial ODBC32.SQLRETURN SQLBindCol( /*SQLULEN*/IntPtr cbColDef, /*SQLSMALLINT*/IntPtr ibScale, /*SQLPOINTER*/ -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef rgbValue, /*SQLLEN*/IntPtr BufferLength, /*SQLLEN* */ -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef StrLen_or_Ind); @@ -326,7 +326,7 @@ internal static partial ODBC32.SQLRETURN SQLSetConnectAttrW( /*SQLSMALLINT*/short ColumnNumber, /*SQLSMALLINT*/ODBC32.SQL_DESC FieldIdentifier, /*SQLPOINTER*/ -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef CharacterAttribute, diff --git a/src/libraries/Common/src/Interop/Windows/CryptUI/Interop.CryptUIDlgCertificate.cs b/src/libraries/Common/src/Interop/Windows/CryptUI/Interop.CryptUIDlgCertificate.cs index e58a0b497dc412..97b5d4bba72617 100644 --- a/src/libraries/Common/src/Interop/Windows/CryptUI/Interop.CryptUIDlgCertificate.cs +++ b/src/libraries/Common/src/Interop/Windows/CryptUI/Interop.CryptUIDlgCertificate.cs @@ -4,7 +4,7 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif using Microsoft.Win32.SafeHandles; @@ -13,7 +13,7 @@ internal static partial class Interop { internal static partial class CryptUI { -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #else [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] @@ -39,7 +39,7 @@ internal struct CRYPTUI_VIEWCERTIFICATE_STRUCTW internal IntPtr rgPropSheetPages; internal uint nStartPage; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW), MarshalMode.Default, typeof(Marshaller))] public static class Marshaller { @@ -127,7 +127,7 @@ public CRYPTUI_VIEWCERTIFICATE_STRUCTW ToManaged() #endif } -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #else [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] @@ -151,7 +151,7 @@ internal struct CRYPTUI_SELECTCERTIFICATE_STRUCTW internal IntPtr rgPropSheetPages; internal IntPtr hSelectedCertStore; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(CRYPTUI_SELECTCERTIFICATE_STRUCTW), MarshalMode.Default, typeof(Marshaller))] public static class Marshaller { diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.AbortDoc.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.AbortDoc.cs index cca83bef74b6a4..0326ead026c334 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.AbortDoc.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.AbortDoc.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -12,7 +12,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial int AbortDoc( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateCompatibleBitmap.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateCompatibleBitmap.cs index e051d8f8d70055..fdfc84cddf583c 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateCompatibleBitmap.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateCompatibleBitmap.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,7 +13,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial IntPtr CreateCompatibleBitmap( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC, int width, int height); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateDIBSection.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateDIBSection.cs index ca024801b4287e..2654d0e653ad19 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateDIBSection.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateDIBSection.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,7 +13,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial IntPtr CreateDIBSection( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hdc, ref BITMAPINFO_FLAT bmi, int iUsage, ref IntPtr ppvBits, IntPtr hSection, int dwOffset); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.DEVMODE.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.DEVMODE.cs index aa26afa85665fb..bb0fa59f771279 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.DEVMODE.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.DEVMODE.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndDoc.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndDoc.cs index b65d8106b34392..2bd8ad72416341 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndDoc.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndDoc.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -12,7 +12,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial int EndDoc( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndPage.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndPage.cs index f09232b01fbacc..0349c5044ba194 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndPage.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndPage.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -12,7 +12,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial int EndPage( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ExtEscape.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ExtEscape.cs index 449ba1b934b333..6ade151f8b0660 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ExtEscape.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ExtEscape.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -16,14 +16,14 @@ internal static partial class Gdi32 [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial int ExtEscape( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC, int nEscape, int cbInput, ref int inData, int cbOutput, out int outData); [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial int ExtEscape( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC, int nEscape, int cbInput, byte[] inData, int cbOutput, out int outData); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetDIBits.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetDIBits.cs index 03cbc74a846d5f..11900ac16602ca 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetDIBits.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetDIBits.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,11 +13,11 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32)] internal static partial int GetDIBits( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hdc, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hbm, int arg1, int arg2, IntPtr arg3, ref BITMAPINFO_FLAT bmi, int arg5); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetObject.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetObject.cs index 83fcfa6f9d2359..afb88d5bd14a54 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetObject.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetObject.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,20 +13,20 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, EntryPoint = "GetObjectW", SetLastError = true)] internal static partial int GetObject( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hObject, int nSize, ref BITMAP bm); [LibraryImport(Libraries.Gdi32, EntryPoint = "GetObjectW", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)] internal static partial int GetObject( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hObject, int nSize, ref Interop.User32.LOGFONT lf); internal static unsafe int GetObject( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hObject, ref Interop.User32.LOGFONT lp) diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetPaletteEntries.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetPaletteEntries.cs index 4f2f2ed8035918..ab2ad0b6ea33bc 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetPaletteEntries.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetPaletteEntries.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -12,7 +12,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32)] internal static partial uint GetPaletteEntries( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hpal, int iStartIndex, int nEntries, byte[] lppe); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.IntersectClipRect.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.IntersectClipRect.cs index a82d6c5514ed2f..0084bcd6265270 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.IntersectClipRect.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.IntersectClipRect.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,7 +13,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial int IntersectClipRect( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC, int x1, int y1, int x2, int y2); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ResetDC.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ResetDC.cs index 3737f3f46699b1..e26750aa2895f9 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ResetDC.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ResetDC.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,11 +13,11 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, EntryPoint = "ResetDCW", SetLastError = true)] internal static partial IntPtr /*HDC*/ ResetDC( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef /*DEVMODE*/ lpDevMode); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartDoc.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartDoc.cs index c62da1844b8e6e..8199ff3f217ff3 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartDoc.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartDoc.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,12 +13,12 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, EntryPoint = "StartDocW", SetLastError = true)] internal static partial int StartDoc( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC, in DOCINFO lpDocInfo); -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #endif [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] @@ -32,7 +32,7 @@ internal struct DOCINFO public DOCINFO() { } -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(DOCINFO), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] public static class Marshaller { diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartPage.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartPage.cs index 00ecc844d7e8a3..549151d43337dd 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartPage.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartPage.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -12,7 +12,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial int StartPage( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC); diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SelectObject.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SelectObject.cs index efcc90a00fb256..da8fb34e900af0 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SelectObject.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SelectObject.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,11 +13,11 @@ internal static partial class Kernel32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial IntPtr SelectObject( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hdc, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef obj); diff --git a/src/libraries/Common/src/Interop/Windows/Shell32/Interop.ExtractAssociatedIcon.cs b/src/libraries/Common/src/Interop/Windows/Shell32/Interop.ExtractAssociatedIcon.cs index 6162795d061e19..d71fc5b7a0835a 100644 --- a/src/libraries/Common/src/Interop/Windows/Shell32/Interop.ExtractAssociatedIcon.cs +++ b/src/libraries/Common/src/Interop/Windows/Shell32/Interop.ExtractAssociatedIcon.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,7 +13,7 @@ internal static partial class Shell32 { [LibraryImport(Libraries.Shell32, EntryPoint = "ExtractAssociatedIconW")] internal static unsafe partial IntPtr ExtractAssociatedIcon( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hInst, char* iconPath, ref int index); diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.CopyImage.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.CopyImage.cs index 4211c156c36552..b971b37309311e 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.CopyImage.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.CopyImage.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,7 +13,7 @@ internal static partial class User32 { [LibraryImport(Libraries.User32, SetLastError = true)] internal static partial IntPtr CopyImage( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hImage, int uType, int cxDesired, int cyDesired, int fuFlags); diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.CreateIconFromResourceEx.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.CreateIconFromResourceEx.cs index a295619f2ac4a3..9c11ee7eba900b 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.CreateIconFromResourceEx.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.CreateIconFromResourceEx.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.DestroyIcon.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.DestroyIcon.cs index 1528c6ae181eb3..782dbcec0e7f4c 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.DestroyIcon.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.DestroyIcon.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -14,7 +14,7 @@ internal static partial class User32 [LibraryImport(Libraries.User32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static partial bool DestroyIcon( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hIcon); diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.DrawIconEx.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.DrawIconEx.cs index 6ac69016bde602..9c0a0bfee89ea3 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.DrawIconEx.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.DrawIconEx.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -14,15 +14,15 @@ internal static partial class User32 [LibraryImport(Libraries.User32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static partial bool DrawIconEx( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC, int x, int y, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hIcon, int width, int height, int iStepIfAniCursor, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hBrushFlickerFree, int diFlags); diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.GetIconInfo.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetIconInfo.cs index e97f54e2e8f6ee..faa505574e6b8c 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.GetIconInfo.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetIconInfo.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -14,7 +14,7 @@ internal static partial class User32 [LibraryImport(Libraries.User32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static partial bool GetIconInfo( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hIcon, ref ICONINFO info); diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.GetSystemMetrics.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetSystemMetrics.cs index 761e69a4a2c829..4232c4348719e9 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.GetSystemMetrics.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetSystemMetrics.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.LoadIcon.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.LoadIcon.cs index f391366d89b125..378129442bf185 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.LoadIcon.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.LoadIcon.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,7 +13,7 @@ internal static partial class User32 { [LibraryImport(Libraries.User32, EntryPoint = "LoadIconW", SetLastError = true)] internal static partial IntPtr LoadIcon( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hInst, IntPtr iconId); diff --git a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs index 7e1010013c35d5..69457b97300730 100644 --- a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs +++ b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif using System.Text; @@ -45,7 +45,7 @@ public static partial SafeWinHttpHandle WinHttpOpenRequest( [return: MarshalAs(UnmanagedType.Bool)] public static partial bool WinHttpAddRequestHeaders( SafeWinHttpHandle requestHandle, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(SimpleStringBufferMarshaller))] StringBuilder headers, #else #pragma warning disable CA1838 // Uses pooled StringBuilder @@ -55,7 +55,7 @@ public static partial bool WinHttpAddRequestHeaders( uint headersLength, uint modifiers); -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(StringBuilder), MarshalMode.ManagedToUnmanagedIn, typeof(SimpleStringBufferMarshaller))] private static unsafe class SimpleStringBufferMarshaller { diff --git a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs index 1cbdfa79d5962a..e76fa9b67e5bcb 100644 --- a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs +++ b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif using System.Text; @@ -247,7 +247,7 @@ public delegate void WINHTTP_STATUS_CALLBACK( IntPtr statusInformation, uint statusInformationLength); -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #endif [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] @@ -261,7 +261,7 @@ public struct WINHTTP_AUTOPROXY_OPTIONS public uint Reserved2; [MarshalAs(UnmanagedType.Bool)] public bool AutoLoginIfChallenged; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(WINHTTP_AUTOPROXY_OPTIONS), MarshalMode.Default, typeof(Marshaller))] public static class Marshaller { diff --git a/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs b/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs index a9ebcba2950c55..954101a9c3cbee 100644 --- a/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs +++ b/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -12,7 +12,7 @@ internal static partial class Interop internal static partial class WinMM { #pragma warning disable CA1823 // unused fields -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #endif internal struct WAVEOUTCAPS @@ -27,7 +27,7 @@ internal struct WAVEOUTCAPS private ushort wChannels; private ushort wReserved1; private ushort dwSupport; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(WAVEOUTCAPS), MarshalMode.Default, typeof(Marshaller))] public static class Marshaller { diff --git a/src/libraries/Common/src/Interop/Windows/Winspool/Interop.DocumentProperties.cs b/src/libraries/Common/src/Interop/Windows/Winspool/Interop.DocumentProperties.cs index bf54cfb1b5b90c..8e7b6ce0c9d763 100644 --- a/src/libraries/Common/src/Interop/Windows/Winspool/Interop.DocumentProperties.cs +++ b/src/libraries/Common/src/Interop/Windows/Winspool/Interop.DocumentProperties.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,26 +13,26 @@ internal static partial class Winspool { [LibraryImport(Libraries.Winspool, EntryPoint = "DocumentPropertiesW", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)] internal static partial int DocumentProperties( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hwnd, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hPrinter, string pDeviceName, IntPtr /*DEVMODE*/ pDevModeOutput, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef /*DEVMODE*/ pDevModeInput, int fMode); [LibraryImport(Libraries.Winspool, EntryPoint = "DocumentPropertiesW", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)] internal static partial int DocumentProperties( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hwnd, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hPrinter, string pDeviceName, IntPtr /*DEVMODE*/ pDevModeOutput, IntPtr /*DEVMODE*/ pDevModeInput, int fMode); diff --git a/src/libraries/Common/src/Interop/Windows/Winspool/Interop.EnumPrinters.cs b/src/libraries/Common/src/Interop/Windows/Winspool/Interop.EnumPrinters.cs index ca967e11d16d86..baeed522bb0c82 100644 --- a/src/libraries/Common/src/Interop/Windows/Winspool/Interop.EnumPrinters.cs +++ b/src/libraries/Common/src/Interop/Windows/Winspool/Interop.EnumPrinters.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif diff --git a/src/libraries/Common/src/System/CodeDom/CodeTypeReference.cs b/src/libraries/Common/src/System/CodeDom/CodeTypeReference.cs index 615d6017e37e37..cb75ff887f6871 100644 --- a/src/libraries/Common/src/System/CodeDom/CodeTypeReference.cs +++ b/src/libraries/Common/src/System/CodeDom/CodeTypeReference.cs @@ -42,7 +42,7 @@ public CodeTypeReference() public CodeTypeReference(Type type) { -#if NET5_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(type); #else if (type is null) @@ -271,7 +271,7 @@ private void Initialize(string? typeName, CodeTypeReferenceOptions options) } // Now see if we have some arity. baseType could be null if this is an array type. -#if NET5_0_OR_GREATER +#if NET if (_baseType != null && _baseType.Contains('`')) // string.Contains(char) is .NetCore2.1+ specific #else if (_baseType != null && _baseType.IndexOf('`') != -1) // string.Contains(char) is .NetCore2.1+ specific diff --git a/src/libraries/Common/src/System/CodeDom/CodeTypeReferenceCollection.cs b/src/libraries/Common/src/System/CodeDom/CodeTypeReferenceCollection.cs index 21b2ae857366ac..55119bc720664b 100644 --- a/src/libraries/Common/src/System/CodeDom/CodeTypeReferenceCollection.cs +++ b/src/libraries/Common/src/System/CodeDom/CodeTypeReferenceCollection.cs @@ -41,7 +41,7 @@ public CodeTypeReference this[int index] public void AddRange(CodeTypeReference[] value) { -#if NET5_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(value); #else if (value is null) @@ -58,7 +58,7 @@ public void AddRange(CodeTypeReference[] value) public void AddRange(CodeTypeReferenceCollection value) { -#if NET5_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(value); #else if (value is null) diff --git a/src/libraries/Common/src/System/Data/Common/DbConnectionOptions.Common.cs b/src/libraries/Common/src/System/Data/Common/DbConnectionOptions.Common.cs index 936c81c094e45d..da3b254f99eb25 100644 --- a/src/libraries/Common/src/System/Data/Common/DbConnectionOptions.Common.cs +++ b/src/libraries/Common/src/System/Data/Common/DbConnectionOptions.Common.cs @@ -50,7 +50,7 @@ internal partial class DbConnectionOptions private static readonly Regex s_connectionStringRegex = CreateConnectionStringRegex(); private static readonly Regex s_connectionStringRegexOdbc = CreateConnectionStringRegexOdbc(); -#if NET7_0_OR_GREATER +#if NET [GeneratedRegex(ConnectionStringPattern, RegexOptions.ExplicitCapture)] private static partial Regex CreateConnectionStringRegex(); @@ -67,7 +67,7 @@ internal partial class DbConnectionOptions private static readonly Regex s_connectionStringQuoteValueRegex = CreateConnectionStringQuoteValueRegex(); // generally do not quote the value if it matches the pattern private static readonly Regex s_connectionStringQuoteOdbcValueRegex = CreateConnectionStringQuoteOdbcValueRegex(); // do not quote odbc value if it matches this pattern -#if NET7_0_OR_GREATER +#if NET [GeneratedRegex("^(?![;\\s])[^\\p{Cc}]+(? public static IAsyncResult Begin(Task task, AsyncCallback? callback, object? state) { -#if NET6_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(task); #else if (task is null) @@ -68,7 +68,7 @@ public static TResult End(IAsyncResult asyncResult) => /// was not produced by a call to . public static Task Unwrap(IAsyncResult asyncResult) { -#if NET6_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(asyncResult); #else if (asyncResult is null) @@ -97,7 +97,7 @@ public static Task Unwrap(IAsyncResult asyncResult) /// public static Task Unwrap(IAsyncResult asyncResult) { -#if NET6_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(asyncResult); #else if (asyncResult is null) diff --git a/src/libraries/Common/src/System/ThrowHelper.cs b/src/libraries/Common/src/System/ThrowHelper.cs index 4257c05891e32c..098b8321492764 100644 --- a/src/libraries/Common/src/System/ThrowHelper.cs +++ b/src/libraries/Common/src/System/ThrowHelper.cs @@ -15,7 +15,7 @@ internal static partial class ThrowHelper /// The reference type argument to validate as non-null. /// The name of the parameter with which corresponds. internal static void ThrowIfNull( -#if NETCOREAPP3_0_OR_GREATER +#if NET [NotNull] #endif object? argument, @@ -27,7 +27,7 @@ internal static void ThrowIfNull( } } -#if NETCOREAPP3_0_OR_GREATER +#if NET [DoesNotReturn] #endif private static void Throw(string? paramName) => throw new ArgumentNullException(paramName); @@ -40,17 +40,17 @@ internal static void ThrowIfNull( /// The name of the parameter being checked. /// The original value of . [MethodImpl(MethodImplOptions.AggressiveInlining)] -#if NETCOREAPP3_0_OR_GREATER +#if NET [return: NotNull] #endif public static string IfNullOrWhitespace( -#if NETCOREAPP3_0_OR_GREATER +#if NET [NotNull] #endif string? argument, [CallerArgumentExpression(nameof(argument))] string paramName = "") { -#if !NETCOREAPP3_1_OR_GREATER +#if !NET if (argument == null) { throw new ArgumentNullException(paramName); @@ -74,7 +74,7 @@ public static string IfNullOrWhitespace( } } -#if !NETCOREAPP3_0_OR_GREATER +#if !NET namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] diff --git a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs index 232c05afb8d271..0d658dae016cc7 100644 --- a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs +++ b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs @@ -5,7 +5,7 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if NET6_0_OR_GREATER +#if NET using System.Runtime.Intrinsics; #endif using System.Threading; @@ -710,7 +710,7 @@ static unsafe bool IsPositiveZero(double value) return (*(ulong*)(&value)) == 0x0000000000000000; } -#if NET6_0_OR_GREATER +#if NET static unsafe bool IsNegativeZero(Half value) { return (*(ushort*)(&value)) == 0x8000; @@ -780,7 +780,7 @@ static string ToStringPadded(double value) } } -#if NET6_0_OR_GREATER +#if NET static string ToStringPadded(Half value) { if (Half.IsNaN(value)) @@ -1036,7 +1036,7 @@ public static void Equal(float expected, float actual, float variance) } } -#if NET6_0_OR_GREATER +#if NET /// Verifies that two values are equal, within the . /// The expected value /// The value to be compared against @@ -1196,7 +1196,7 @@ static unsafe int SingleToInt32Bits(float value) throw EqualException.ForMismatchedValues(ToStringPadded(expected), ToStringPadded(actual)); } -#if NET6_0_OR_GREATER +#if NET /// Verifies that two values's binary representations are identical. /// The expected value /// The value to be compared against diff --git a/src/libraries/Common/tests/TestUtilities/System/WindowsIdentityFixture.cs b/src/libraries/Common/tests/TestUtilities/System/WindowsIdentityFixture.cs index b4d9be2a52744d..2817d305e6d0a1 100644 --- a/src/libraries/Common/tests/TestUtilities/System/WindowsIdentityFixture.cs +++ b/src/libraries/Common/tests/TestUtilities/System/WindowsIdentityFixture.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Net; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif using System.Security.Cryptography; @@ -127,7 +127,7 @@ private void CreateUser() [LibraryImport("netapi32.dll")] internal static partial uint NetUserDel([MarshalAs(UnmanagedType.LPWStr)] string servername, [MarshalAs(UnmanagedType.LPWStr)] string username); -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(USER_INFO_1.Marshaller))] #endif [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] @@ -142,7 +142,7 @@ internal struct USER_INFO_1 public uint usri1_flags; public string usri1_script_path; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(USER_INFO_1), MarshalMode.Default, typeof(Marshaller))] public static class Marshaller { diff --git a/src/libraries/Common/tests/TestUtilities/TestEventListener.cs b/src/libraries/Common/tests/TestUtilities/TestEventListener.cs index 3c33bdb633e36b..8cb70ee3cbd8c9 100644 --- a/src/libraries/Common/tests/TestUtilities/TestEventListener.cs +++ b/src/libraries/Common/tests/TestUtilities/TestEventListener.cs @@ -99,7 +99,7 @@ protected override void OnEventSourceCreated(EventSource eventSource) protected override void OnEventWritten(EventWrittenEventArgs eventData) { StringBuilder sb = new StringBuilder(). -#if NETCOREAPP2_2_OR_GREATER || NETSTANDARD2_1_OR_GREATER +#if NET || NETSTANDARD2_1_OR_GREATER Append($"{eventData.TimeStamp:HH:mm:ss.fffffff}[{eventData.EventName}] "); #else Append($"[{eventData.EventName}] "); diff --git a/src/libraries/Microsoft.Extensions.Caching.Abstractions/src/IMemoryCache.cs b/src/libraries/Microsoft.Extensions.Caching.Abstractions/src/IMemoryCache.cs index ccce249b23d958..8388a9f0433eb1 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Abstractions/src/IMemoryCache.cs +++ b/src/libraries/Microsoft.Extensions.Caching.Abstractions/src/IMemoryCache.cs @@ -31,7 +31,7 @@ public interface IMemoryCache : IDisposable /// An object identifying the entry. void Remove(object key); -#if NET6_0_OR_GREATER +#if NET /// /// Gets a snapshot of the cache statistics if available. /// diff --git a/src/libraries/Microsoft.Extensions.Caching.Memory/tests/MemoryCacheGetCurrentStatisticsTests.cs b/src/libraries/Microsoft.Extensions.Caching.Memory/tests/MemoryCacheGetCurrentStatisticsTests.cs index cee6245f3e9c6b..576b7e103aebae 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Memory/tests/MemoryCacheGetCurrentStatisticsTests.cs +++ b/src/libraries/Microsoft.Extensions.Caching.Memory/tests/MemoryCacheGetCurrentStatisticsTests.cs @@ -106,7 +106,7 @@ public void GetCurrentStatistics_UpdateAfterExistingItemExpired_CurrentEstimated } } -#if NET6_0_OR_GREATER +#if NET [Fact] public void GetCurrentStatistics_DIMReturnsNull() { diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs index db0a767573a1e8..eaa53fec71ede1 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs @@ -160,7 +160,7 @@ private IChangeToken GetOrAddChangeToken(string pattern) } IChangeToken changeToken; -#if NET5_0_OR_GREATER +#if NET bool isWildCard = pattern.Contains('*'); #else bool isWildCard = pattern.IndexOf('*') != -1; diff --git a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceHelpers.cs b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceHelpers.cs index 9de601ddebe7d5..05eed40ff6df48 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceHelpers.cs +++ b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceHelpers.cs @@ -28,7 +28,7 @@ private static bool GetIsWindowsService() if ( #if NETFRAMEWORK Environment.OSVersion.Platform != PlatformID.Win32NT -#elif NET5_0_OR_GREATER +#elif NET !OperatingSystem.IsWindows() #else !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs b/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs index 7a965e0efc85f5..4a9806a2fcd787 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs @@ -190,11 +190,6 @@ internal static DiagnosticListener LogHostBuilding(HostApplicationBuilder hostAp return diagnosticListener; } -// Remove when https://github.com/dotnet/runtime/pull/78532 is merged and consumed by the used SDK. -#if NET7_0 - [UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", - Justification = "DiagnosticSource is used here to pass objects in-memory to code using HostFactoryResolver. This won't require creating new generic types.")] -#endif [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = "The values being passed into Write are being consumed by the application already.")] private static void Write<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>( diff --git a/src/libraries/Microsoft.Extensions.Http/ref/Microsoft.Extensions.Http.cs b/src/libraries/Microsoft.Extensions.Http/ref/Microsoft.Extensions.Http.cs index 51891e8ebcf754..8c791124208828 100644 --- a/src/libraries/Microsoft.Extensions.Http/ref/Microsoft.Extensions.Http.cs +++ b/src/libraries/Microsoft.Extensions.Http/ref/Microsoft.Extensions.Http.cs @@ -28,7 +28,7 @@ public static partial class HttpClientBuilderExtensions public static Microsoft.Extensions.DependencyInjection.IHttpClientBuilder RedactLoggedHeaders(this Microsoft.Extensions.DependencyInjection.IHttpClientBuilder builder, System.Func shouldRedactHeaderValue) { throw null; } public static Microsoft.Extensions.DependencyInjection.IHttpClientBuilder RemoveAllLoggers(this Microsoft.Extensions.DependencyInjection.IHttpClientBuilder builder) { throw null; } public static Microsoft.Extensions.DependencyInjection.IHttpClientBuilder SetHandlerLifetime(this Microsoft.Extensions.DependencyInjection.IHttpClientBuilder builder, System.TimeSpan handlerLifetime) { throw null; } -#if NET5_0_OR_GREATER +#if NET [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public static Microsoft.Extensions.DependencyInjection.IHttpClientBuilder UseSocketsHttpHandler(this Microsoft.Extensions.DependencyInjection.IHttpClientBuilder builder, System.Action? configureHandler = null) { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] @@ -64,14 +64,14 @@ public partial interface IHttpClientBuilder string Name { get; } Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get; } } -#if NET5_0_OR_GREATER +#if NET public partial interface ISocketsHttpHandlerBuilder { string Name { get; } Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get; } } #endif -#if NET5_0_OR_GREATER +#if NET public static partial class SocketsHttpHandlerBuilderExtensions { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] diff --git a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/DefaultSocketsHttpHandlerBuilder.cs b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/DefaultSocketsHttpHandlerBuilder.cs index 57b905c0f3e6e0..61986cedfbe1a3 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/DefaultSocketsHttpHandlerBuilder.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/DefaultSocketsHttpHandlerBuilder.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NET5_0_OR_GREATER +#if NET namespace Microsoft.Extensions.DependencyInjection { internal sealed class DefaultSocketsHttpHandlerBuilder : ISocketsHttpHandlerBuilder diff --git a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/HttpClientBuilderExtensions.cs b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/HttpClientBuilderExtensions.cs index a9adb32fc5d84c..758a989be3a8b2 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/HttpClientBuilderExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/HttpClientBuilderExtensions.cs @@ -265,7 +265,7 @@ public static IHttpClientBuilder ConfigureHttpMessageHandlerBuilder(this IHttpCl return builder; } -#if NET5_0_OR_GREATER +#if NET /// /// Adds or updates as a primary handler for a named . If provided, /// also adds a delegate that will be used to configure the primary . diff --git a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/ISocketsHttpHandlerBuilder.cs b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/ISocketsHttpHandlerBuilder.cs index d7509e009c9c47..75333f8d747c71 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/ISocketsHttpHandlerBuilder.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/ISocketsHttpHandlerBuilder.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NET5_0_OR_GREATER +#if NET namespace Microsoft.Extensions.DependencyInjection { /// diff --git a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/SocketsHttpHandlerBuilderExtensions.cs b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/SocketsHttpHandlerBuilderExtensions.cs index 0d56606b742bde..d3bb98c8a11620 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/SocketsHttpHandlerBuilderExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/SocketsHttpHandlerBuilderExtensions.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NET5_0_OR_GREATER +#if NET using System; using System.Net; using System.Net.Http; diff --git a/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpClientLoggerHandler.cs b/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpClientLoggerHandler.cs index 087ec81fbb6cd9..a7aeebe8578f3e 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpClientLoggerHandler.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpClientLoggerHandler.cs @@ -61,7 +61,7 @@ protected override async Task SendAsync(HttpRequestMessage } } -#if NET5_0_OR_GREATER +#if NET protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) { ThrowHelper.ThrowIfNull(request); diff --git a/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingHttpMessageHandler.cs b/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingHttpMessageHandler.cs index 5056474e9ead2f..e592e7d236fbb4 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingHttpMessageHandler.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingHttpMessageHandler.cs @@ -62,7 +62,7 @@ async Task Core(HttpRequestMessage request, bool useAsync, var stopwatch = ValueStopwatch.StartNew(); HttpResponseMessage response = useAsync ? await base.SendAsync(request, cancellationToken).ConfigureAwait(false) -#if NET5_0_OR_GREATER +#if NET : base.Send(request, cancellationToken); #else : throw new NotImplementedException("Unreachable code"); @@ -78,7 +78,7 @@ async Task Core(HttpRequestMessage request, bool useAsync, protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => SendCoreAsync(request, useAsync: true, cancellationToken); -#if NET5_0_OR_GREATER +#if NET /// /// Logs the request to and response from the sent . protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) diff --git a/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingScopeHttpMessageHandler.cs b/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingScopeHttpMessageHandler.cs index e170acbfe83c80..1894a005f84a68 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingScopeHttpMessageHandler.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingScopeHttpMessageHandler.cs @@ -63,7 +63,7 @@ async Task Core(HttpRequestMessage request, bool useAsync, Log.RequestPipelineStart(_logger, request, shouldRedactHeaderValue); HttpResponseMessage response = useAsync ? await base.SendAsync(request, cancellationToken).ConfigureAwait(false) -#if NET5_0_OR_GREATER +#if NET : base.Send(request, cancellationToken); #else : throw new NotImplementedException("Unreachable code"); @@ -80,7 +80,7 @@ async Task Core(HttpRequestMessage request, bool useAsync, protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => SendCoreAsync(request, useAsync: true, cancellationToken); -#if NET5_0_OR_GREATER +#if NET /// /// Logs the request to and response from the sent . protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) diff --git a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/HttpClientLoggerTest.cs b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/HttpClientLoggerTest.cs index 6fb8e2dd8f7a98..039ba46b186251 100644 --- a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/HttpClientLoggerTest.cs +++ b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/HttpClientLoggerTest.cs @@ -156,7 +156,7 @@ private void AssertCounters(TestCountingLogger testLogger, int requestCount, boo } } -#if NET5_0_OR_GREATER +#if NET [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNetCore))] [InlineData(false, false)] [InlineData(false, true)] @@ -588,7 +588,7 @@ private async Task SendAsyncCore(HttpRequestMessage request } else { -#if NET5_0_OR_GREATER +#if NET return base.Send(request, cancellationToken); #else throw new NotImplementedException("unreachable"); @@ -609,7 +609,7 @@ private async Task SendAsyncCore(HttpRequestMessage request protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => SendAsyncCore(request, async: true, cancellationToken); -#if NET5_0_OR_GREATER +#if NET protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) => SendAsyncCore(request, async: false, cancellationToken).GetAwaiter().GetResult(); #endif diff --git a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/LoggingUriOutputTests.cs b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/LoggingUriOutputTests.cs index 8f6ca7a8c4e285..bdd204f709df39 100644 --- a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/LoggingUriOutputTests.cs +++ b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/LoggingUriOutputTests.cs @@ -91,7 +91,7 @@ public async Task LoggingScopeHttpMessageHandler_LogsAbsoluteUri() Assert.Equal("HTTP GET http://api.example.com/search?term=Western%20Australia", message.Scope.ToString()); } -#if NET5_0_OR_GREATER +#if NET [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNetCore))] public void LoggingHttpMessageHandler_LogsAbsoluteUri_Sync() { diff --git a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/SocketsHttpHandlerConfigurationTest.cs b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/SocketsHttpHandlerConfigurationTest.cs index 4473917ff728f0..059557a0784a70 100644 --- a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/SocketsHttpHandlerConfigurationTest.cs +++ b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/SocketsHttpHandlerConfigurationTest.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NET5_0_OR_GREATER +#if NET using System; using System.Collections.Generic; using System.Net; diff --git a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/TestMessageHandler.cs b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/TestMessageHandler.cs index 5cbb8eb168f302..6bf2050cbd15c5 100644 --- a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/TestMessageHandler.cs +++ b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/TestMessageHandler.cs @@ -26,7 +26,7 @@ protected override Task SendAsync(HttpRequestMessage reques return Task.FromResult(response); } -#if NET5_0_OR_GREATER +#if NET protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) => _responseFactory(request); #endif } diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs index af91cab872c88f..1f54faf77d7fef 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs @@ -24,8 +24,8 @@ public async Task TestEmitter() #pragma warning disable RS1035 // To allow using the File IO APIs inside the analyzer test foreach (var file in Directory.GetFiles("TestClasses")) { -#if NETCOREAPP3_1_OR_GREATER - sources.Add("#define NETCOREAPP3_1_OR_GREATER\n" + File.ReadAllText(file)); +#if NET + sources.Add("#define NET\n" + File.ReadAllText(file)); #else sources.Add(File.ReadAllText(file)); #endif @@ -46,7 +46,7 @@ public async Task TestEmitter() Assert.Empty(d); _ = Assert.Single(r); -#if NETCOREAPP3_1_OR_GREATER +#if NET string baseline = File.ReadAllText(@"Baselines/NetCoreApp/Validators.g.cs"); #else string baseline = File.ReadAllText(@"Baselines/NetFX/Validators.g.cs"); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/OptionsValidationTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/OptionsValidationTests.cs index 4f9770ce7a17ca..01519b780eba1e 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/OptionsValidationTests.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/OptionsValidationTests.cs @@ -186,7 +186,7 @@ public void RangeAttributeModelDoubleInvalid() [Fact] public void RangeAttributeModelDateValid() { -#if NETCOREAPP3_1_OR_GREATER +#if NET // Setting non-invariant culture to check that // attribute's "ParseLimitsInInvariantCulture" property // was set up correctly in the validator: diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/Utils.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/Utils.cs index 7412374f18a56f..eb6bf661490995 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/Utils.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/Utils.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NETCOREAPP3_1_OR_GREATER +#if NET using System.Linq; #endif using Microsoft.Extensions.Options; @@ -15,7 +15,7 @@ public static void VerifyValidateOptionsResult(ValidateOptionsResult vr, int exp { Assert.NotNull(vr); -#if NETCOREAPP3_1_OR_GREATER +#if NET var failures = vr.Failures!.ToArray(); #else var failures = vr.FailureMessage!.Split(';'); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Models.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Models.cs index c245ebd783bdcf..bc76114ab62944 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Models.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Models.cs @@ -76,7 +76,7 @@ public class RangeAttributeModelDouble public class RangeAttributeModelDate { -#if NETCOREAPP3_1_OR_GREATER +#if NET [Range(typeof(DateTime), "1/2/2004", "3/4/2004", ParseLimitsInInvariantCulture = true)] #else [Range(typeof(DateTime), "1/2/2004", "3/4/2004")] diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Constants.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Constants.cs index 5371a0354aeac6..ed797f8fae7bba 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Constants.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Constants.cs @@ -61,19 +61,13 @@ public static bool IsKnownComparable() => typeof(T) == typeof(DateTime) || typeof(T) == typeof(DateTimeOffset) || typeof(T) == typeof(Guid) || -#if NETCOREAPP3_0_OR_GREATER +#if NET typeof(T) == typeof(Rune) || -#endif -#if NET5_0_OR_GREATER typeof(T) == typeof(Half) || typeof(T) == typeof(nint) || typeof(T) == typeof(nuint) || -#endif -#if NET6_0_OR_GREATER typeof(T) == typeof(DateOnly) || typeof(T) == typeof(TimeOnly) || -#endif -#if NET7_0_OR_GREATER typeof(T) == typeof(Int128) || typeof(T) == typeof(UInt128) || #endif diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs index afb4785147391f..2bda7b2c76e70a 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs @@ -159,7 +159,7 @@ private static int CalcNumBuckets(ReadOnlySpan hashCodes, bool hashCodesAre if (!hashCodesAreUnique) { codes = -#if NETCOREAPP2_0_OR_GREATER +#if NET new HashSet(hashCodes.Length); #else new HashSet(); diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenSet.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenSet.cs index 50bbdeb18aad64..79acea67bd100c 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenSet.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenSet.cs @@ -202,7 +202,7 @@ private static FrozenSet CreateFromSet(HashSet source) [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] [DebuggerDisplay("Count = {Count}")] public abstract class FrozenSet : ISet, -#if NET5_0_OR_GREATER +#if NET IReadOnlySet, #endif IReadOnlyCollection, ICollection diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs index 208cf88c6ea62d..0793b3d12f7315 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs @@ -64,7 +64,7 @@ private static bool TryUseSubstring(ReadOnlySpan uniqueStrings, bool all new JustifiedCaseInsensitiveSubstringComparer(); HashSet set = new HashSet( -#if NET6_0_OR_GREATER +#if NET uniqueStrings.Length, #endif comparer); diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/LengthBuckets.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/LengthBuckets.cs index 97659c5479365c..626b21a8bf1212 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/LengthBuckets.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/LengthBuckets.cs @@ -28,7 +28,7 @@ internal static class LengthBuckets } int arraySize = spread * MaxPerLength; -#if NET6_0_OR_GREATER +#if NET if (arraySize > Array.MaxLength) #else if (arraySize > 0X7FFFFFC7) @@ -87,7 +87,7 @@ internal static class LengthBuckets return null; } -#if NET6_0_OR_GREATER +#if NET // We don't need an array with every value initialized to zero if we are just about to overwrite every value anyway. int[] copy = GC.AllocateUninitializedArray(arraySize); Array.Copy(buckets, copy, arraySize); diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs index 060492a40bd06e..459a3889d30af8 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs @@ -589,7 +589,7 @@ public void RemoveRange(int index, int length) if (index + length < this._count) { -#if NET6_0_OR_GREATER +#if NET if (RuntimeHelpers.IsReferenceOrContainsReferences()) { Array.Clear(_elements, index, length); // Clear the elements so that the gc can reclaim the references. @@ -919,7 +919,7 @@ public int LastIndexOf(T item, int startIndex, int count, IEqualityComparer? /// public void Reverse() { -#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER +#if NET || NETSTANDARD2_1_OR_GREATER Array.Reverse(_elements, 0, _count); #else // The non-generic Array.Reverse is not used because it does not perform @@ -963,7 +963,7 @@ public void Sort(Comparison comparison) if (Count > 1) { -#if NET6_0_OR_GREATER +#if NET // MemoryExtensions.Sort is not available in .NET Framework / Standard 2.0. // But the overload with a Comparison argument doesn't allocate. _elements.AsSpan(0, _count).Sort(comparison); diff --git a/src/libraries/System.Collections.Immutable/src/System/Polyfills.cs b/src/libraries/System.Collections.Immutable/src/System/Polyfills.cs index 77f304f46fdcd8..eeb82f0960ccc4 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Polyfills.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Polyfills.cs @@ -6,7 +6,7 @@ namespace System.Collections.Generic { -#if !NETCOREAPP2_0_OR_GREATER +#if !NET internal static class KeyValuePairExtensions { [EditorBrowsable(EditorBrowsableState.Never)] @@ -18,7 +18,7 @@ public static void Deconstruct(this KeyValuePair sou } #endif -#if !NET5_0_OR_GREATER +#if !NET internal interface IReadOnlySet : IReadOnlyCollection { bool Contains(T item); @@ -34,7 +34,7 @@ internal interface IReadOnlySet : IReadOnlyCollection namespace System.Numerics { -#if !NETCOREAPP3_0_OR_GREATER +#if !NET internal static class BitOperations { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -45,7 +45,7 @@ internal static class BitOperations namespace System.Runtime.CompilerServices { -#if !NETCOREAPP3_0_OR_GREATER +#if !NET [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] internal sealed class CallerArgumentExpressionAttribute : Attribute { diff --git a/src/libraries/System.Collections.Immutable/tests/Frozen/FrozenSetTests.cs b/src/libraries/System.Collections.Immutable/tests/Frozen/FrozenSetTests.cs index 2558f9bedcd895..717efc31e45bb3 100644 --- a/src/libraries/System.Collections.Immutable/tests/Frozen/FrozenSetTests.cs +++ b/src/libraries/System.Collections.Immutable/tests/Frozen/FrozenSetTests.cs @@ -297,7 +297,7 @@ private sealed class InvertingComparer : IEqualityComparer private sealed class EmptySet : ISet -#if NET5_0_OR_GREATER +#if NET , IReadOnlySet #endif { diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ImplicitMachineConfigHost.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ImplicitMachineConfigHost.cs index 32403a8950c2c2..195b3ca5ff4a38 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ImplicitMachineConfigHost.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ImplicitMachineConfigHost.cs @@ -81,7 +81,7 @@ public override Stream OpenStreamForRead(string streamName)
" + -#if NET7_0_OR_GREATER +#if NET @"
" + #endif @"
diff --git a/src/libraries/System.Data.OleDb/src/DbConnectionOptions.cs b/src/libraries/System.Data.OleDb/src/DbConnectionOptions.cs index 0bb5bde47ea416..81b4ecdc5b7175 100644 --- a/src/libraries/System.Data.OleDb/src/DbConnectionOptions.cs +++ b/src/libraries/System.Data.OleDb/src/DbConnectionOptions.cs @@ -59,7 +59,7 @@ internal partial class DbConnectionOptions private static readonly Regex ConnectionStringRegex = CreateConnectionStringRegex(); private static readonly Regex ConnectionStringRegexOdbc = CreateConnectionStringRegexOdbc(); -#if NET7_0_OR_GREATER +#if NET [GeneratedRegex(ConnectionStringPattern, RegexOptions.ExplicitCapture)] private static partial Regex CreateConnectionStringRegex(); @@ -76,7 +76,7 @@ internal partial class DbConnectionOptions private static readonly Regex ConnectionStringQuoteValueRegex = CreateConnectionStringQuoteValueRegex(); // generally do not quote the value if it matches the pattern private static readonly Regex ConnectionStringQuoteOdbcValueRegex = CreateConnectionStringQuoteOdbcValueRegex(); // do not quote odbc value if it matches this pattern -#if NET7_0_OR_GREATER +#if NET [GeneratedRegex("^(?![;\\s])[^\\p{Cc}]+(? flagsChars = stackalloc char[2]; HexConverter.ToCharsBuffer((byte)((~ActivityTraceFlagsIsSet) & _w3CIdFlags), flagsChars, 0, HexConverter.Casing.Lower); string id = -#if NET6_0_OR_GREATER +#if NET string.Create(null, stackalloc char[128], $"00-{_traceId}-{_spanId}-{flagsChars}"); #else "00-" + _traceId + "-" + _spanId + "-" + flagsChars.ToString(); @@ -258,7 +258,7 @@ public string? ParentId Span flagsChars = stackalloc char[2]; HexConverter.ToCharsBuffer((byte)((~ActivityTraceFlagsIsSet) & _parentTraceFlags), flagsChars, 0, HexConverter.Casing.Lower); string parentId = -#if NET6_0_OR_GREATER +#if NET string.Create(null, stackalloc char[128], $"00-{_traceId}-{_parentSpanId}-{flagsChars}"); #else "00-" + _traceId + "-" + _parentSpanId + "-" + flagsChars.ToString(); diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/CounterAggregator.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/CounterAggregator.cs index b9e3c8d35bca70..4577c16b9b988e 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/CounterAggregator.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/CounterAggregator.cs @@ -33,7 +33,7 @@ public override void Update(double value) // Get the delta best associated with the current thread, preferring to use core ID rather than // thread ID to reduce contention. ref PaddedDouble delta = ref deltas[ -#if NETCOREAPP2_1_OR_GREATER +#if NET Thread.GetCurrentProcessorId() #else Environment.CurrentManagedThreadId diff --git a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs index e5cdb63f7ba76c..a8f8fd63369693 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs +++ b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs @@ -5,7 +5,7 @@ using System; using System.Diagnostics.Eventing.Reader; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif using System.Security; @@ -341,7 +341,7 @@ internal enum EvtLoginClass EvtRpcLogin = 1 } -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #endif [StructLayout(LayoutKind.Sequential)] @@ -355,7 +355,7 @@ internal struct EvtRpcLogin public string Domain; public CoTaskMemUnicodeSafeHandle Password; public int Flags; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(EvtRpcLogin), MarshalMode.ManagedToUnmanagedRef, typeof(ValueMarshaller))] public static class Marshaller { @@ -695,7 +695,7 @@ internal static partial bool EvtRender( out int buffUsed, out int propCount); -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #endif [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)] @@ -708,7 +708,7 @@ internal struct EvtStringVariant [FieldOffset(12)] public uint Type; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(EvtStringVariant), MarshalMode.Default, typeof(Marshaller))] public static class Marshaller { diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Integer.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Integer.cs index 102b05b82fb368..35372824d35e20 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Integer.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Integer.cs @@ -104,7 +104,7 @@ public static BigInteger ReadInteger( { ReadOnlySpan contents = ReadIntegerBytes(source, ruleSet, out int consumed, expectedTag); -#if NETCOREAPP2_1_OR_GREATER +#if NET BigInteger value = new BigInteger(contents, isBigEndian: true); #else byte[] tmp = CryptoPool.Rent(contents.Length); diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Integer.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Integer.cs index 389196c0acd261..b1720b5106b2cd 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Integer.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Integer.cs @@ -281,7 +281,7 @@ private void WriteIntegerCore(Asn1Tag tag, BigInteger value) Debug.Assert(!tag.IsConstructed); WriteTag(tag); -#if NETCOREAPP2_1_OR_GREATER +#if NET WriteLength(value.GetByteCount()); // WriteLength ensures the content-space value.TryWriteBytes(_buffer.AsSpan(_offset), out int bytesWritten, isBigEndian: true); diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/SetOfValueComparer.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/SetOfValueComparer.cs index 44b6c3030957e8..d766b5008c324c 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/SetOfValueComparer.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/SetOfValueComparer.cs @@ -17,7 +17,7 @@ internal static int Compare(ReadOnlySpan x, ReadOnlySpan y) int min = Math.Min(x.Length, y.Length); int diff; -#if NET7_0_OR_GREATER +#if NET int diffIndex = x.CommonPrefixLength(y); if (diffIndex != min) diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.cs index 3a844a60637b07..260bf0bdadb374 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.cs @@ -169,7 +169,7 @@ public static uint HashToUInt32(ReadOnlySpan source) => private static uint Update(uint crc, ReadOnlySpan source) { -#if NET7_0_OR_GREATER +#if NET if (CanBeVectorized(source)) { return UpdateVectorized(crc, source); @@ -181,7 +181,7 @@ private static uint Update(uint crc, ReadOnlySpan source) private static uint UpdateScalar(uint crc, ReadOnlySpan source) { -#if NET6_0_OR_GREATER +#if NET // Use ARM intrinsics for CRC if available. This is used for the trailing bytes on the vectorized path // and is the primary method if the vectorized path is unavailable. if (System.Runtime.Intrinsics.Arm.Crc32.Arm64.IsSupported) diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.cs index e9993a7503e787..89b81c657c518c 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.cs @@ -167,7 +167,7 @@ public static ulong HashToUInt64(ReadOnlySpan source) => private static ulong Update(ulong crc, ReadOnlySpan source) { -#if NET7_0_OR_GREATER +#if NET if (CanBeVectorized(source)) { return UpdateVectorized(crc, source); diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash128.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash128.cs index fdfd24a60ab1f4..e1181cb73f914d 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash128.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash128.cs @@ -17,7 +17,7 @@ namespace System.IO.Hashing /// For methods that persist the computed numerical hash value as bytes, /// the value is written in the Big Endian byte order. /// -#if NET5_0_OR_GREATER +#if NET [SkipLocalsInit] #endif public sealed unsafe class XxHash128 : NonCryptographicHashAlgorithm @@ -51,7 +51,7 @@ public XxHash128(long seed) : base(HashLengthInBytes) /// is null. public static byte[] Hash(byte[] source, long seed) { -#if NET6_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(source); #else if (source is null) @@ -110,7 +110,7 @@ public static bool TryHash(ReadOnlySpan source, Span destination, ou return false; } -#if NET7_0_OR_GREATER +#if NET /// Computes the XXH128 hash of the provided data. /// The data to hash. /// The seed value for this hash computation. The default is zero. @@ -197,7 +197,7 @@ private Hash128 GetCurrentHashAsHash128() return current; } -#if NET7_0_OR_GREATER +#if NET /// Gets the current computed hash value without modifying accumulated state. /// The hash value for the data already provided. [CLSCompliant(false)] diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash3.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash3.cs index 702409b949d451..affdfe78d6a850 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash3.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash3.cs @@ -16,7 +16,7 @@ namespace System.IO.Hashing /// For methods that persist the computed numerical hash value as bytes, /// the value is written in the Big Endian byte order. /// -#if NET5_0_OR_GREATER +#if NET [SkipLocalsInit] #endif public sealed unsafe class XxHash3 : NonCryptographicHashAlgorithm @@ -50,7 +50,7 @@ public XxHash3(long seed) : base(HashLengthInBytes) /// is null. public static byte[] Hash(byte[] source, long seed) { -#if NET6_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(source); #else if (source is null) diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHashShared.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHashShared.cs index bfdf1963ac3b02..cafa80dbbf112e 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHashShared.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHashShared.cs @@ -6,7 +6,7 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.X86; @@ -15,7 +15,7 @@ namespace System.IO.Hashing { /// Shared implementation of the XXH3 hash algorithm for 64-bit in and version. -#if NET5_0_OR_GREATER +#if NET [SkipLocalsInit] #endif internal static unsafe class XxHashShared @@ -333,7 +333,7 @@ public static void CopyAccumulators(ref State state, ulong* accumulators) { fixed (ulong* stateAccumulators = state.Accumulators) { -#if NET7_0_OR_GREATER +#if NET if (Vector256.IsHardwareAccelerated) { Vector256.Store(Vector256.Load(stateAccumulators), accumulators); @@ -390,7 +390,7 @@ public static void DigestLong(ref State state, ulong* accumulators, byte* secret [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void InitializeAccumulators(ulong* accumulators) { -#if NET7_0_OR_GREATER +#if NET if (Vector256.IsHardwareAccelerated) { Vector256.Store(Vector256.Create(Prime32_3, Prime64_1, Prime64_2, Prime64_3), accumulators); @@ -452,7 +452,7 @@ public static ulong Avalanche(ulong hash) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong Multiply64To128(ulong left, ulong right, out ulong lower) { -#if NET5_0_OR_GREATER +#if NET return Math.BigMul(left, right, out lower); #else ulong lowerLow = Multiply32To64((uint)left, (uint)right); @@ -479,7 +479,7 @@ public static void DeriveSecretFromSeed(byte* destinationSecret, ulong seed) { fixed (byte* defaultSecret = &MemoryMarshal.GetReference(DefaultSecret)) { -#if NET7_0_OR_GREATER +#if NET if (Vector256.IsHardwareAccelerated && BitConverter.IsLittleEndian) { Vector256 seedVec = Vector256.Create(seed, 0u - seed, seed, 0u - seed); @@ -515,7 +515,7 @@ private static void Accumulate(ulong* accumulators, byte* source, byte* secret, byte* secretForAccumulate = secret; byte* secretForScramble = secret + (SecretLengthBytes - StripeLengthBytes); -#if NET7_0_OR_GREATER +#if NET if (Vector256.IsHardwareAccelerated && BitConverter.IsLittleEndian) { Vector256 acc1 = Vector256.Load(accumulators); @@ -620,7 +620,7 @@ public static void Accumulate512(ulong* accumulators, byte* source, byte* secret [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void Accumulate512Inlined(ulong* accumulators, byte* source, byte* secret) { -#if NET7_0_OR_GREATER +#if NET if (Vector256.IsHardwareAccelerated && BitConverter.IsLittleEndian) { for (int i = 0; i < AccumulatorCount / Vector256.Count; i++) @@ -659,7 +659,7 @@ private static void Accumulate512Inlined(ulong* accumulators, byte* source, byte } } -#if NET7_0_OR_GREATER +#if NET [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector256 Accumulate256(Vector256 accVec, byte* source, Vector256 secret) { @@ -714,7 +714,7 @@ private static Vector128 MultiplyWideningLower(Vector128 source) private static void ScrambleAccumulators(ulong* accumulators, byte* secret) { -#if NET7_0_OR_GREATER +#if NET if (Vector256.IsHardwareAccelerated && BitConverter.IsLittleEndian) { for (int i = 0; i < AccumulatorCount / Vector256.Count; i++) @@ -752,7 +752,7 @@ private static void ScrambleAccumulators(ulong* accumulators, byte* secret) } } -#if NET7_0_OR_GREATER +#if NET [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector256 ScrambleAccumulator256(Vector256 accVec, Vector256 secret) { diff --git a/src/libraries/System.IO.Hashing/tests/NonCryptoHashTestDriver.cs b/src/libraries/System.IO.Hashing/tests/NonCryptoHashTestDriver.cs index f2d8e411533ec7..fe17c4c14eab87 100644 --- a/src/libraries/System.IO.Hashing/tests/NonCryptoHashTestDriver.cs +++ b/src/libraries/System.IO.Hashing/tests/NonCryptoHashTestDriver.cs @@ -420,7 +420,7 @@ public LargeTestCase(string name, byte data, long repeatCount, string outputHex) public IEnumerable> EnumerateDataChunks() { -#if NET5_0_OR_GREATER +#if NET byte[] chunk = GC.AllocateUninitializedArray(1024 * 1024); #else byte[] chunk = new byte[1024 * 1024]; diff --git a/src/libraries/System.IO.Hashing/tests/XxHash128Tests.cs b/src/libraries/System.IO.Hashing/tests/XxHash128Tests.cs index 8d32a6f06c1d2d..3ba2044d069505 100644 --- a/src/libraries/System.IO.Hashing/tests/XxHash128Tests.cs +++ b/src/libraries/System.IO.Hashing/tests/XxHash128Tests.cs @@ -41,7 +41,7 @@ public void Hash_OneShot_Expected() Assert.Equal(expectedHash128, ReadHashBigEndian(XxHash128.Hash(input, test.Seed))); Assert.Equal(expectedHash128, ReadHashBigEndian(XxHash128.Hash((ReadOnlySpan)input, test.Seed))); -#if NET7_0_OR_GREATER +#if NET // Validate `XxHash128.HashToUInt128` Assert.Equal(new UInt128(test.HashHigh, test.HashLow), XxHash128.HashToUInt128(input, test.Seed)); #endif @@ -110,7 +110,7 @@ public void Hash_Streaming_Expected() // Validate that the hash we get from doing a one-shot of all the data up to this point // matches the incremental hash for the data appended until now. -#if NET7_0_OR_GREATER +#if NET Assert.Equal(XxHash128.HashToUInt128(asciiBytes.AsSpan(0, processed), test.Seed), hash.GetCurrentHashAsUInt128()); #endif Assert.True(hash.TryGetCurrentHash(destination, out int bytesWritten)); @@ -120,7 +120,7 @@ public void Hash_Streaming_Expected() } // Validate the final hash code. -#if NET7_0_OR_GREATER +#if NET Assert.Equal(new UInt128(test.HashHigh, test.HashLow), hash.GetCurrentHashAsUInt128()); #endif Array.Clear(destination, 0, destination.Length); diff --git a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/InternalRelationshipCollection.cs b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/InternalRelationshipCollection.cs index b2ace96c807391..d76b0972d017ce 100644 --- a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/InternalRelationshipCollection.cs +++ b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/InternalRelationshipCollection.cs @@ -320,7 +320,7 @@ private void ProcessRelationshipAttributes(XmlCompatibilityReader reader) { try { -#if NET6_0_OR_GREATER +#if NET relationshipTargetMode = Enum.Parse(targetModeAttributeValue, ignoreCase: false); #else relationshipTargetMode = (TargetMode)(Enum.Parse(typeof(TargetMode), targetModeAttributeValue, ignoreCase: false)); diff --git a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.PackUriScheme.cs b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.PackUriScheme.cs index 2707afbf4b5391..8bf3d1e5a0e8b5 100644 --- a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.PackUriScheme.cs +++ b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.PackUriScheme.cs @@ -285,7 +285,7 @@ private static string EscapeSpecialCharacters(string path) // This is currently enforced by the order of characters in the s_specialCharacterChars array foreach (char c in s_specialCharacterChars) { -#if NET5_0_OR_GREATER +#if NET if (path.Contains(c)) #else if (path.IndexOf(c) != -1) diff --git a/src/libraries/System.IO.Pipelines/tests/PipeReaderCopyToAsyncTests.cs b/src/libraries/System.IO.Pipelines/tests/PipeReaderCopyToAsyncTests.cs index 21228b2a1bf726..3c524de5122365 100644 --- a/src/libraries/System.IO.Pipelines/tests/PipeReaderCopyToAsyncTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/PipeReaderCopyToAsyncTests.cs @@ -349,7 +349,7 @@ public override void Write(byte[] buffer, int offset, int count) Check(count); base.Write(buffer, offset, count); } -#if NETCOREAPP3_0_OR_GREATER +#if NET public override void Write(ReadOnlySpan buffer) { Check(buffer.Length); diff --git a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.cs b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.cs index 752163fd2bd379..426eb77d637d5b 100644 --- a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.cs +++ b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.cs @@ -963,7 +963,7 @@ public string ReadExisting() Buffer.BlockCopy(_inBuffer, _readPos, bytesReceived, 0, CachedBytesToRead); } -#if NET7_0_OR_GREATER +#if NET _internalSerialStream.ReadExactly(bytesReceived, CachedBytesToRead, bytesReceived.Length - CachedBytesToRead); // get everything #else int readCount = bytesReceived.Length - CachedBytesToRead; diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs index bb52925254c277..2bda7989a9bb9b 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs @@ -78,7 +78,7 @@ internal static int TryReadAll(this Stream stream, byte[] buffer, int offset, in #if NETCOREAPP internal static int TryReadAll(this Stream stream, Span buffer) -#if NET7_0_OR_GREATER +#if NET => stream.ReadAtLeast(buffer, buffer.Length, throwOnEndOfStream: false); #else { diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs index d172f20f1cb066..cc8e5f3ce1ad23 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs @@ -134,7 +134,7 @@ public static bool NeedsEscapingInTypeName(this char c) public static string UnescapeTypeNameIdentifier(this string identifier) { -#if NET5_0_OR_GREATER +#if NET if (identifier.Contains('\\')) #else if (identifier.IndexOf('\\') != -1) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.cs index 50ab6b7f307a08..1a5369f2f638d1 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.cs @@ -331,7 +331,7 @@ public sealed override Type MakeArrayType(int rank) private volatile RoType? _lazyUnderlyingEnumType; public sealed override Array GetEnumValues() => throw new InvalidOperationException(SR.Arg_InvalidOperation_Reflection); -#if NET7_0_OR_GREATER +#if NET [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2085:UnrecognizedReflectionPattern", Justification = "Enum Types are not trimmed.")] public override Array GetEnumValuesAsUnderlyingType() diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs index 03611db20825a4..c476213963544a 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs @@ -365,7 +365,7 @@ public static IEnumerable GetEnumUnderlyingTypeData } } -#if NET7_0_OR_GREATER +#if NET [Fact] public static void GetEnumValuesAsUnderlyingType() { diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/PkcsHelpers.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/PkcsHelpers.cs index 6351a376c0bc72..b26ff355f378e8 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 @@ -364,7 +364,7 @@ public static string ToSerialString(this byte[] serialBytes) return ToUpperHexString(serialBytes); } -#if NET5_0_OR_GREATER +#if NET private static string ToUpperHexString(ReadOnlySpan ba) { return Convert.ToHexString(ba); diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs index ffffeefa5bac37..de7bc2b9b77b7e 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs @@ -720,7 +720,7 @@ internal static X509Certificate2Collection BuildBagOfCerts(KeyInfoX509Data keyIn return collection; } -#if NET5_0_OR_GREATER +#if NET internal static string EncodeHexString(byte[] sArray) { return Convert.ToHexString(sArray); diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlResolverHelper.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlResolverHelper.cs index 3070ffa8e1d233..948f883b80a2eb 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlResolverHelper.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlResolverHelper.cs @@ -11,14 +11,14 @@ internal static class XmlResolverHelper { internal static XmlResolver GetThrowingResolver() { -#if NET7_0_OR_GREATER +#if NET return XmlResolver.ThrowingResolver; #else return XmlThrowingResolver.s_singleton; #endif } -#if !NET7_0_OR_GREATER +#if !NET // An XmlResolver that forbids all external entity resolution. // (Copied from XmlResolver.ThrowingResolver.cs.) private sealed class XmlThrowingResolver : XmlResolver diff --git a/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/XmlBuffer.cs b/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/XmlBuffer.cs index 17f3cfa2e1e7ad..4c31f32bf505a2 100644 --- a/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/XmlBuffer.cs +++ b/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/XmlBuffer.cs @@ -87,7 +87,7 @@ public void Close() _buffer = new byte[_stream.Length]; _stream.Position = 0; -#if NET7_0_OR_GREATER +#if NET _stream.ReadExactly(_buffer); #else int totalRead = 0; diff --git a/src/libraries/System.Speech/src/Internal/Synthesis/AudioBase.cs b/src/libraries/System.Speech/src/Internal/Synthesis/AudioBase.cs index 782cd59fb6c34c..c8ecfa78483570 100644 --- a/src/libraries/System.Speech/src/Internal/Synthesis/AudioBase.cs +++ b/src/libraries/System.Speech/src/Internal/Synthesis/AudioBase.cs @@ -122,7 +122,7 @@ internal void PlayWaveFile(AudioData audio) { byte[] data = new byte[(int)audio._stream.Length]; -#if NET7_0_OR_GREATER +#if NET audio._stream.ReadExactly(data); #else int totalRead = 0; diff --git a/src/libraries/System.Speech/src/Internal/Synthesis/EngineSite.cs b/src/libraries/System.Speech/src/Internal/Synthesis/EngineSite.cs index a658f37ca6180b..c6caca4d9c25bf 100644 --- a/src/libraries/System.Speech/src/Internal/Synthesis/EngineSite.cs +++ b/src/libraries/System.Speech/src/Internal/Synthesis/EngineSite.cs @@ -175,7 +175,7 @@ public Stream LoadResource(Uri uri, string mediaType) MemoryStream memStream = new(cLen); byte[] ab = new byte[cLen]; -#if NET7_0_OR_GREATER +#if NET stream.ReadExactly(ab); #else int totalRead = 0; diff --git a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/CodePagesEncodingProvider.cs b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/CodePagesEncodingProvider.cs index c984dbf460d8a4..58bb679c7712ae 100644 --- a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/CodePagesEncodingProvider.cs +++ b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/CodePagesEncodingProvider.cs @@ -197,7 +197,7 @@ public static EncodingProvider Instance internal static unsafe ref T GetNonNullPinnableReference(T[] array) where T : struct { return ref -#if NET5_0_OR_GREATER +#if NET MemoryMarshal.GetArrayDataReference(array); #else array.Length != 0 ? ref array[0] : ref Unsafe.AsRef((void*)1); diff --git a/src/libraries/System.Text.Json/Common/JsonHelpers.cs b/src/libraries/System.Text.Json/Common/JsonHelpers.cs index 5711afa8370689..afa3afb4dc2ce4 100644 --- a/src/libraries/System.Text.Json/Common/JsonHelpers.cs +++ b/src/libraries/System.Text.Json/Common/JsonHelpers.cs @@ -55,7 +55,7 @@ internal static bool RequiresSpecialNumberHandlingOnWrite(JsonNumberHandling? ha internal static void StableSortByKey(this List items, Func keySelector) where TKey : unmanaged, IComparable { -#if NET6_0_OR_GREATER +#if NET Span span = CollectionsMarshal.AsSpan(items); // Tuples implement lexical ordering OOTB which can be used to encode stable sorting diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.netcoreapp.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.netcoreapp.cs index 847da900ad35d8..bbf2e3846a6bcd 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.netcoreapp.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.netcoreapp.cs @@ -12,7 +12,7 @@ public static partial class JsonMetadataServices public static System.Text.Json.Serialization.JsonConverter HalfConverter { get { throw null; } } public static System.Text.Json.Serialization.JsonConverter TimeOnlyConverter { get { throw null; } } -#if NET7_0_OR_GREATER +#if NET public static System.Text.Json.Serialization.JsonConverter Int128Converter { get { throw null; } } [System.CLSCompliantAttribute(false)] public static System.Text.Json.Serialization.JsonConverter UInt128Converter { get { throw null; } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.MetadataDb.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.MetadataDb.cs index afdbf4bd0b9b26..a53df982c12eb4 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.MetadataDb.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.MetadataDb.cs @@ -240,7 +240,7 @@ private void Enlarge() // Note: Array.MaxLength exists only on .NET 6 or greater, // so for the other versions value is hardcoded const int MaxArrayLength = 0x7FFFFFC7; -#if NET6_0_OR_GREATER +#if NET Debug.Assert(MaxArrayLength == Array.MaxLength); #endif diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonConstants.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonConstants.cs index 7fe47499c1aa85..c2dbc58e131a0c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonConstants.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonConstants.cs @@ -65,7 +65,7 @@ internal static partial class JsonConstants // When transcoding from UTF8 -> UTF16, the byte count threshold where we rent from the array pool before performing a normal alloc. public const long ArrayPoolMaxSizeBeforeUsingNormalAlloc = -#if NET6_0_OR_GREATER +#if NET 1024 * 1024 * 1024; // ArrayPool limit increased in .NET 6 #else 1024 * 1024; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.MultiSegment.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.MultiSegment.cs index 8635031292e32c..22d3cc1c497d81 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.MultiSegment.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.MultiSegment.cs @@ -633,7 +633,7 @@ private static int FindMismatch(ReadOnlySpan span, ReadOnlySpan lite int indexOfFirstMismatch; -#if NET7_0_OR_GREATER +#if NET indexOfFirstMismatch = span.CommonPrefixLength(literal); #else int minLength = Math.Min(span.Length, literal.Length); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Converters.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Converters.cs index 117e3ba3d63a97..b5bb76c77b0652 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Converters.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Converters.cs @@ -74,7 +74,7 @@ private static Dictionary GetDefaultSimpleConverters() Add(JsonMetadataServices.UInt16Converter); Add(JsonMetadataServices.UInt32Converter); Add(JsonMetadataServices.UInt64Converter); -#if NET7_0_OR_GREATER +#if NET Add(JsonMetadataServices.Int128Converter); Add(JsonMetadataServices.UInt128Converter); #endif diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs index 83a24191b8fe25..1cf87d0c940e7a 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 @@ -108,7 +108,7 @@ public static partial class JsonMetadataServices public static JsonConverter Int64Converter => s_int64Converter ??= new Int64Converter(); private static JsonConverter? s_int64Converter; -#if NET7_0_OR_GREATER +#if NET /// /// Returns a instance that converts values. /// diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs index 959490b53f19fc..e70cd8848868af 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs @@ -626,7 +626,7 @@ private bool NumberHandingIsApplicable() #if NETCOREAPP potentialNumberType == typeof(Half) || #endif -#if NET7_0_OR_GREATER +#if NET potentialNumberType == typeof(Int128) || potentialNumberType == typeof(UInt128) || #endif diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs index dfaff9130fa78a..ce8ac3d254d3ac 100644 --- a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs +++ b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs @@ -46,7 +46,7 @@ public static IEnumerable GetTestDictionaries() yield return WrapArgs(DateTime.MaxValue, 1, expectedJson: $@"{{""{DateTime.MaxValue:O}"":1}}"); yield return WrapArgs(DateTimeOffset.MaxValue, 1, expectedJson: $@"{{""{DateTimeOffset.MaxValue:O}"":1}}"); yield return WrapArgs(TimeSpan.MaxValue, 1, expectedJson: $@"{{""{TimeSpan.MaxValue}"":1}}"); -#if NET6_0_OR_GREATER +#if NET yield return WrapArgs(DateOnly.MaxValue, 1, expectedJson: $@"{{""{DateOnly.MaxValue:O}"":1}}"); yield return WrapArgs(TimeOnly.MaxValue, 1, expectedJson: $@"{{""{TimeOnly.MaxValue:O}"":1}}"); #endif 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 9f8af715fdb8e4..92c12b1dfc44c9 100644 --- a/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.cs +++ b/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.cs @@ -1907,7 +1907,7 @@ public override void WriteAsPropertyName(Utf8JsonWriter writer, int value, JsonS public static class ReflectionExtensions { -#if NET6_0_OR_GREATER +#if NET [return: System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] public static Type WithConstructors( [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs index 5666498347e468..3c24bdc78ad06f 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs @@ -563,7 +563,7 @@ public static string ConvertOldStringsToClass(string set, string category) } return -#if NETCOREAPP2_1_OR_GREATER +#if NET string #else StringExtensions @@ -1304,7 +1304,7 @@ static bool InitializeValue(char ch, string set, ref uint[]? asciiLazyCache) } uint[]? cache = asciiLazyCache ?? Interlocked.CompareExchange(ref asciiLazyCache, new uint[CacheArrayLength], null) ?? asciiLazyCache; -#if NET5_0_OR_GREATER +#if NET Interlocked #else InterlockedExtensions @@ -1594,7 +1594,7 @@ internal static unsafe string CharsToStringClass(ReadOnlySpan chars) #pragma warning disable CS8500 // takes address of managed type ReadOnlySpan tmpChars = chars; // avoid address exposing the span and impacting the other code in the method that uses it return -#if NETCOREAPP2_1_OR_GREATER +#if NET string #else StringExtensions diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs index 5284c09339bd7b..4d779d4f48f127 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs @@ -177,7 +177,7 @@ private void Emit(RegexOpcode op, int opd1, int opd2) ///
private int StringCode(string str) { -#if NET6_0_OR_GREATER +#if NET ref int i = ref CollectionsMarshal.GetValueRefOrAddDefault(_stringTable, str, out bool exists); if (!exists) { diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Threading/StackHelper.cs b/src/libraries/System.Text.RegularExpressions/src/System/Threading/StackHelper.cs index c338c2bb73e95c..ded50c662ea4a4 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Threading/StackHelper.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Threading/StackHelper.cs @@ -12,7 +12,7 @@ internal static class StackHelper /// Tries to ensure there is sufficient stack to execute the average .NET function. public static bool TryEnsureSufficientExecutionStack() { -#if NETCOREAPP2_0_OR_GREATER +#if NET return RuntimeHelpers.TryEnsureSufficientExecutionStack(); #else try diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs index 9d3679be60b938..234b416a9b46de 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs @@ -1327,7 +1327,7 @@ public void Match_InstanceMethods_DefaultTimeout_Throws(RegexEngine engine) }, ((int)engine).ToString(CultureInfo.InvariantCulture)).Dispose(); } -#if NET7_0_OR_GREATER +#if NET [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] public void Match_InstanceMethods_DefaultTimeout_SourceGenerated_Throws() { @@ -1885,7 +1885,7 @@ public async Task Match_StartatDiffersFromBeginning(RegexEngine engine, string p Regex r = await RegexHelpers.GetRegexAsync(engine, pattern, options); Assert.Equal(expectedSuccessStartAt, r.IsMatch(input, startat)); -#if NET7_0_OR_GREATER +#if NET Assert.Equal(expectedSuccessStartAt, r.IsMatch(input.AsSpan(), startat)); #endif @@ -2069,7 +2069,7 @@ public async Task TestCharIsLowerCultureEdgeCasesAroundTurkishCharacters(RegexEn Regex r1 = await RegexHelpers.GetRegexAsync(engine, "[\u012F-\u0130]", RegexOptions.IgnoreCase); Regex r2 = await RegexHelpers.GetRegexAsync(engine, "[\u012F\u0130]", RegexOptions.IgnoreCase); Assert.Equal(r1.IsMatch("\u0130"), r2.IsMatch("\u0130")); -#if NET7_0_OR_GREATER +#if NET Assert.Equal(r1.IsMatch("\u0130".AsSpan()), r2.IsMatch("\u0130".AsSpan())); #endif @@ -2491,14 +2491,14 @@ private static void VerifyIsMatchThrows(Regex? r, string input, TimeSpan time if (r == null) { Assert.Throws(() => timeout == Regex.InfiniteMatchTimeout ? Regex.IsMatch(input, pattern, options) : Regex.IsMatch(input, pattern, options, timeout)); -#if NET7_0_OR_GREATER +#if NET Assert.Throws(() => timeout == Regex.InfiniteMatchTimeout ? Regex.IsMatch(input.AsSpan(), pattern, options) : Regex.IsMatch(input.AsSpan(), pattern, options, timeout)); #endif } else { Assert.Throws(() => r.IsMatch(input)); -#if NET7_0_OR_GREATER +#if NET Assert.Throws(() => r.IsMatch(input.AsSpan())); #endif } @@ -2513,7 +2513,7 @@ private static void VerifyIsMatch(Regex? r, string input, bool expected, TimeSpa { Assert.Equal(expected, Regex.IsMatch(input, pattern)); } -#if NET7_0_OR_GREATER +#if NET Assert.Equal(expected, timeout == Regex.InfiniteMatchTimeout ? Regex.IsMatch(input.AsSpan(), pattern, options) : Regex.IsMatch(input.AsSpan(), pattern, options, timeout)); if (options == RegexOptions.None) { @@ -2524,7 +2524,7 @@ private static void VerifyIsMatch(Regex? r, string input, bool expected, TimeSpa else { Assert.Equal(expected, r.IsMatch(input)); -#if NET7_0_OR_GREATER +#if NET Assert.Equal(expected, r.IsMatch(input.AsSpan())); #endif } diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Tests.Common.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Tests.Common.cs index 4d4f2252839ae5..b0a9b6549492bc 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Tests.Common.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Tests.Common.cs @@ -187,7 +187,7 @@ public static async Task GetRegexesAsync(RegexEngine engine, params (st /// Set the AppContext variable REGEX_NONBACKTRACKING_MAX_AUTOMATA_SIZE to the given max value. Only used with Nonbacktracking engine. public static void SetSafeSizeThreshold(int maxSize) { -#if NET7_0_OR_GREATER +#if NET AppContext.SetData("REGEX_NONBACKTRACKING_MAX_AUTOMATA_SIZE", maxSize); #endif } @@ -195,7 +195,7 @@ public static void SetSafeSizeThreshold(int maxSize) /// Remove the AppContext variable REGEX_NONBACKTRACKING_MAX_AUTOMATA_SIZE value. Only used with Nonbacktracking engine. public static void RestoreSafeSizeThresholdToDefault() { -#if NET7_0_OR_GREATER +#if NET AppContext.SetData("REGEX_NONBACKTRACKING_MAX_AUTOMATA_SIZE", null); #endif } diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexRunnerTests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexRunnerTests.cs index d4cd665e5b1af9..0f5799687011cd 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexRunnerTests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexRunnerTests.cs @@ -50,7 +50,7 @@ public async Task EnsureRunmatchValueIsNulledAfterIsMatch(RegexEngine engine) MethodInfo getTextMethod = typeof(Match).GetMethod("get_Text", BindingFlags.Instance | BindingFlags.NonPublic); Assert.Null(getTextMethod.Invoke(runmatch, [])); Assert.Equal(string.Empty, runmatch.Value); -#if NET7_0_OR_GREATER +#if NET Assert.True(runmatch.ValueSpan == ReadOnlySpan.Empty); #endif } diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs b/src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs index 63cdedf4b466a6..c91cff3b5423ab 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs @@ -1470,7 +1470,7 @@ public static Task OutputAvailableAsync( { // When cancellation is requested, unlink the target from the source and cancel the target. target._ctr = cancellationToken.Register( -#if NET6_0_OR_GREATER +#if NET OutputAvailableAsyncTarget.CancelAndUnlink, #else static state => OutputAvailableAsyncTarget.CancelAndUnlink(state, default), diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/Common.cs b/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/Common.cs index 7bfd3ecf35d952..c04ee9556003d4 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/Common.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/Common.cs @@ -190,7 +190,7 @@ internal static void WireCancellationToComplete( // data, and we also want to dispose of that registration when we complete so that we don't // leak into a long-living cancellation token. CancellationTokenRegistration reg = cancellationToken.Register( -#if NET6_0_OR_GREATER +#if NET completeAction, completeState #else state => diff --git a/src/libraries/System.Windows.Extensions/src/System/Media/SoundPlayer.cs b/src/libraries/System.Windows.Extensions/src/System/Media/SoundPlayer.cs index d77919070c24df..e57dff3e55ce2a 100644 --- a/src/libraries/System.Windows.Extensions/src/System/Media/SoundPlayer.cs +++ b/src/libraries/System.Windows.Extensions/src/System/Media/SoundPlayer.cs @@ -314,7 +314,7 @@ private void LoadStream(bool loadSync) int streamLen = (int)_stream.Length; _currentPos = 0; _streamData = new byte[streamLen]; -#if NET7_0_OR_GREATER +#if NET _stream.ReadExactly(_streamData); #else int totalRead = 0; diff --git a/src/libraries/System.Windows.Extensions/src/System/Security/Cryptography/X509Certificates/X509Certificate2UI.cs b/src/libraries/System.Windows.Extensions/src/System/Security/Cryptography/X509Certificates/X509Certificate2UI.cs index b19e217322f07e..dfdb4660ea4991 100644 --- a/src/libraries/System.Windows.Extensions/src/System/Security/Cryptography/X509Certificates/X509Certificate2UI.cs +++ b/src/libraries/System.Windows.Extensions/src/System/Security/Cryptography/X509Certificates/X509Certificate2UI.cs @@ -53,7 +53,7 @@ private static unsafe void DisplayX509Certificate(X509Certificate2 certificate, // Initialize view structure. Interop.CryptUI.CRYPTUI_VIEWCERTIFICATE_STRUCTW ViewInfo = default; -#if NET7_0_OR_GREATER +#if NET ViewInfo.dwSize = (uint)sizeof(Interop.CryptUI.CRYPTUI_VIEWCERTIFICATE_STRUCTW.Marshaller.Native); #else ViewInfo.dwSize = (uint)Marshal.SizeOf(); @@ -122,7 +122,7 @@ private static unsafe SafeCertStoreHandle SelectFromStore(SafeCertStoreHandle sa Interop.CryptUI.CRYPTUI_SELECTCERTIFICATE_STRUCTW csc = default; // Older versions of CRYPTUI do not check the size correctly, // so always force it to the oldest version of the structure. -#if NET7_0_OR_GREATER +#if NET // Declare a local for Native to enable us to get the managed byte offset // without having a null check cause a failure. Interop.CryptUI.CRYPTUI_SELECTCERTIFICATE_STRUCTW.Marshaller.Native native; diff --git a/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs b/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs index 13c34bde4b8ea1..0a0495f72fef4e 100644 --- a/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs +++ b/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs @@ -213,7 +213,7 @@ private static void WriteSectionHeader(Stream s, WebcilSectionHeader sectionHead WriteStructure(s, sectionHeader); } -#if NETCOREAPP2_1_OR_GREATER +#if NET private static void WriteStructure(Stream s, T structure) where T : unmanaged { @@ -256,7 +256,7 @@ private static void CopySections(Stream outStream, FileStream inputStream, Immut } } -#if NETCOREAPP2_1_OR_GREATER +#if NET private static void ReadExactly(FileStream s, Span buffer) { s.ReadExactly(buffer); diff --git a/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilWasmWrapper.cs b/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilWasmWrapper.cs index 3f8560446306fb..f47a1247474784 100644 --- a/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilWasmWrapper.cs +++ b/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilWasmWrapper.cs @@ -63,7 +63,7 @@ public void WriteWasmWrappedWebcil(Stream outputStream) // // extracted by wasm-reader -s wrapper.wasm private static -#if NET7_0_OR_GREATER +#if NET ReadOnlyMemory #else byte[] @@ -80,7 +80,7 @@ private static // // extracted by wasm-reader -s wrapper.wasm private static -#if NET7_0_OR_GREATER +#if NET ReadOnlyMemory #else byte[] @@ -91,7 +91,7 @@ private static private static void WriteWasmHeader(Stream outputStream) { -#if NET7_0_OR_GREATER +#if NET outputStream.Write(s_wasmWrapperPrefix.Span); #else outputStream.Write(s_wasmWrapperPrefix, 0, s_wasmWrapperPrefix.Length); @@ -100,7 +100,7 @@ private static void WriteWasmHeader(Stream outputStream) private static void WriteWasmSuffix(Stream outputStream) { -#if NET7_0_OR_GREATER +#if NET outputStream.Write(s_wasmWrapperSuffix.Span); #else outputStream.Write(s_wasmWrapperSuffix, 0, s_wasmWrapperSuffix.Length); diff --git a/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsServerRouter/DiagnosticsServerRouterFactory.cs b/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsServerRouter/DiagnosticsServerRouterFactory.cs index 30ccdc1a48f4be..41726e9286791b 100644 --- a/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsServerRouter/DiagnosticsServerRouterFactory.cs +++ b/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsServerRouter/DiagnosticsServerRouterFactory.cs @@ -136,7 +136,7 @@ protected async Task IsStreamConnectedAsync(Stream stream, CancellationToken tok protected bool IsCompletedSuccessfully(Task t) { -#if NETCOREAPP2_0_OR_GREATER +#if NET return t.IsCompletedSuccessfully; #else return t.IsCompleted && !t.IsCanceled && !t.IsFaulted; From 3f47add997451b6b0e5689008f1915653ed41002 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 12:30:30 -0700 Subject: [PATCH 176/248] Bump dotnet/actions-create-pull-request from 3 to 4 (#101586) Bumps [dotnet/actions-create-pull-request](https://github.com/dotnet/actions-create-pull-request) from 3 to 4. - [Commits](https://github.com/dotnet/actions-create-pull-request/compare/v3...v4) --- updated-dependencies: - dependency-name: dotnet/actions-create-pull-request dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/aspnetcore-sync.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/aspnetcore-sync.yml b/.github/workflows/aspnetcore-sync.yml index 12cc86c47b8983..e80fb301fa4cbe 100644 --- a/.github/workflows/aspnetcore-sync.yml +++ b/.github/workflows/aspnetcore-sync.yml @@ -57,7 +57,7 @@ jobs: - name: Send PR if: steps.check.outputs.changed == 'true' # https://github.com/marketplace/actions/create-pull-request - uses: dotnet/actions-create-pull-request@v3 + uses: dotnet/actions-create-pull-request@v4 with: token: ${{ secrets.GITHUB_TOKEN }} path: .\runtime From 6cd329b25315c5f21e86dac74f6cbe6d0deb6b0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 13:02:06 -0700 Subject: [PATCH 177/248] Bump actions/checkout v4 and set dependabot to only bump its major versions (#101585) * Bump actions/checkout from 2.0.0 to 4.1.4 Bumps [actions/checkout](https://github.com/actions/checkout) from 2.0.0 to 4.1.4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v4.1.4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Set dependabot to bump github-actions to major versions; use checkout v4 * Ignore patch and minor updates to actions/checkout --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jeff Handley --- .github/dependabot.yml | 3 +++ .github/workflows/aspnetcore-sync.yml | 4 ++-- .github/workflows/bump-chrome-version.yml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 9a538c12cfa42d..806f7fad67b045 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,3 +7,6 @@ updates: open-pull-requests-limit: 5 labels: - area-codeflow + ignore: + - dependency-name: "actions/checkout" + update-types: ["version-update:semver-patch","version-update:semver-minor"] diff --git a/.github/workflows/aspnetcore-sync.yml b/.github/workflows/aspnetcore-sync.yml index e80fb301fa4cbe..582f371cf9ab49 100644 --- a/.github/workflows/aspnetcore-sync.yml +++ b/.github/workflows/aspnetcore-sync.yml @@ -16,14 +16,14 @@ jobs: runs-on: windows-latest steps: - name: Checkout aspnetcore - uses: actions/checkout@v2.0.0 + uses: actions/checkout@v4 with: # Test this script using changes in a fork repository: 'dotnet/aspnetcore' path: aspnetcore ref: main - name: Checkout runtime - uses: actions/checkout@v2.0.0 + uses: actions/checkout@v4 with: # Test this script using changes in a fork repository: 'dotnet/runtime' diff --git a/.github/workflows/bump-chrome-version.yml b/.github/workflows/bump-chrome-version.yml index e47563ca44a071..e1d1e89658ca02 100644 --- a/.github/workflows/bump-chrome-version.yml +++ b/.github/workflows/bump-chrome-version.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Branch run: | git config user.name github-actions[bot] From 33a68d0cef067034df5cbac89415568e5fda63ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Tue, 30 Apr 2024 06:34:57 +0900 Subject: [PATCH 178/248] Reduce generic specialized code in console formatters (#101474) Move code that doesn't need to be generic to a non-generic method. Reduces the size of the Stage 2 goldilocks app by 1.4% since these methods are rather large (especially the `JsonConsoleFormatter` one) and we have many specializations. --- .../src/JsonConsoleFormatter.cs | 28 +++++++++++-------- .../src/SimpleConsoleFormatter.cs | 18 ++++++------ .../src/SystemdConsoleFormatter.cs | 13 ++++++--- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs index 122556bbbe460c..b3ff45e33d9ed1 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs @@ -32,10 +32,16 @@ public override void Write(in LogEntry logEntry, IExternalScopeP { return; } - LogLevel logLevel = logEntry.LogLevel; - string category = logEntry.Category; - int eventId = logEntry.EventId.Id; - Exception? exception = logEntry.Exception; + + // We extract most of the work into a non-generic method to save code size. If this was left in the generic + // method, we'd get generic specialization for all TState parameters, but that's unnecessary. + WriteInternal(scopeProvider, textWriter, message, logEntry.LogLevel, logEntry.Category, logEntry.EventId.Id, logEntry.Exception, + logEntry.State != null, logEntry.State?.ToString(), logEntry.State as IReadOnlyCollection>); + } + + private void WriteInternal(IExternalScopeProvider? scopeProvider, TextWriter textWriter, string message, LogLevel logLevel, + string category, int eventId, Exception? exception, bool hasState, string? stateMessage, IReadOnlyCollection>? stateProperties) + { const int DefaultBufferSize = 1024; using (var output = new PooledByteBufferWriter(DefaultBufferSize)) { @@ -48,9 +54,9 @@ public override void Write(in LogEntry logEntry, IExternalScopeP DateTimeOffset dateTimeOffset = FormatterOptions.UseUtcTimestamp ? DateTimeOffset.UtcNow : DateTimeOffset.Now; writer.WriteString("Timestamp", dateTimeOffset.ToString(timestampFormat)); } - writer.WriteNumber(nameof(logEntry.EventId), eventId); - writer.WriteString(nameof(logEntry.LogLevel), GetLogLevelString(logLevel)); - writer.WriteString(nameof(logEntry.Category), category); + writer.WriteNumber(nameof(LogEntry.EventId), eventId); + writer.WriteString(nameof(LogEntry.LogLevel), GetLogLevelString(logLevel)); + writer.WriteString(nameof(LogEntry.Category), category); writer.WriteString("Message", message); if (exception != null) @@ -58,11 +64,11 @@ public override void Write(in LogEntry logEntry, IExternalScopeP writer.WriteString(nameof(Exception), exception.ToString()); } - if (logEntry.State != null) + if (hasState) { - writer.WriteStartObject(nameof(logEntry.State)); - writer.WriteString("Message", logEntry.State.ToString()); - if (logEntry.State is IReadOnlyCollection> stateProperties) + writer.WriteStartObject(nameof(LogEntry.State)); + writer.WriteString("Message", stateMessage); + if (stateProperties != null) { foreach (KeyValuePair item in stateProperties) { diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/SimpleConsoleFormatter.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/SimpleConsoleFormatter.cs index 308c831dd2ea81..6aba8cb172ac8b 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/SimpleConsoleFormatter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/SimpleConsoleFormatter.cs @@ -51,7 +51,15 @@ public override void Write(in LogEntry logEntry, IExternalScopeP { return; } - LogLevel logLevel = logEntry.LogLevel; + + // We extract most of the work into a non-generic method to save code size. If this was left in the generic + // method, we'd get generic specialization for all TState parameters, but that's unnecessary. + WriteInternal(scopeProvider, textWriter, message, logEntry.LogLevel, logEntry.EventId.Id, logEntry.Exception, logEntry.Category); + } + + private void WriteInternal(IExternalScopeProvider? scopeProvider, TextWriter textWriter, string message, LogLevel logLevel, + int eventId, Exception? exception, string category) + { ConsoleColors logLevelColors = GetLogLevelConsoleColors(logLevel); string logLevelString = GetLogLevelString(logLevel); @@ -70,14 +78,8 @@ public override void Write(in LogEntry logEntry, IExternalScopeP { textWriter.WriteColoredMessage(logLevelString, logLevelColors.Background, logLevelColors.Foreground); } - CreateDefaultLogMessage(textWriter, logEntry, message, scopeProvider); - } - private void CreateDefaultLogMessage(TextWriter textWriter, in LogEntry logEntry, string message, IExternalScopeProvider? scopeProvider) - { bool singleLine = FormatterOptions.SingleLine; - int eventId = logEntry.EventId.Id; - Exception? exception = logEntry.Exception; // Example: // info: ConsoleApp.Program[10] @@ -85,7 +87,7 @@ private void CreateDefaultLogMessage(TextWriter textWriter, in LogEntry< // category and event id textWriter.Write(LoglevelPadding); - textWriter.Write(logEntry.Category); + textWriter.Write(category); textWriter.Write('['); #if NETCOREAPP diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/SystemdConsoleFormatter.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/SystemdConsoleFormatter.cs index 5c0626307db195..2d306fee1d0a4b 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/SystemdConsoleFormatter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/SystemdConsoleFormatter.cs @@ -41,10 +41,15 @@ public override void Write(in LogEntry logEntry, IExternalScopeP { return; } - LogLevel logLevel = logEntry.LogLevel; - string category = logEntry.Category; - int eventId = logEntry.EventId.Id; - Exception? exception = logEntry.Exception; + + // We extract most of the work into a non-generic method to save code size. If this was left in the generic + // method, we'd get generic specialization for all TState parameters, but that's unnecessary. + WriteInternal(scopeProvider, textWriter, message, logEntry.LogLevel, logEntry.Category, logEntry.EventId.Id, logEntry.Exception); + } + + private void WriteInternal(IExternalScopeProvider? scopeProvider, TextWriter textWriter, string message, LogLevel logLevel, string category, + int eventId, Exception? exception) + { // systemd reads messages from standard out line-by-line in a 'message' format. // newline characters are treated as message delimiters, so we must replace them. // Messages longer than the journal LineMax setting (default: 48KB) are cropped. From aab8803eac4111a711b6eb65242ee8a5b14fa411 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 29 Apr 2024 18:16:40 -0400 Subject: [PATCH 179/248] Disable TensorPrimitives vectorization of Log, Cbrt, Pow, and RootN (#101690) We had a test bug that was hiding cases where one of the expected / actual was NaN and the other wasn't. --- .../Numerics/Tensors/netcore/TensorPrimitives.Cbrt.cs | 2 +- .../Numerics/Tensors/netcore/TensorPrimitives.Log.cs | 2 +- .../Numerics/Tensors/netcore/TensorPrimitives.Pow.cs | 2 +- .../Numerics/Tensors/netcore/TensorPrimitives.RootN.cs | 2 +- src/libraries/System.Numerics.Tensors/tests/Helpers.cs | 10 ++++++++++ 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Cbrt.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Cbrt.cs index 1bc8b85696c121..3336411a098966 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Cbrt.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Cbrt.cs @@ -26,7 +26,7 @@ public static void Cbrt(ReadOnlySpan x, Span destination) private readonly struct CbrtOperator : IUnaryOperator where T : IRootFunctions { - public static bool Vectorizable => typeof(T) == typeof(float) || typeof(T) == typeof(double); + public static bool Vectorizable => false; // typeof(T) == typeof(float) || typeof(T) == typeof(double); // TODO: https://github.com/dotnet/runtime/issues/100535 public static T Invoke(T x) => T.Cbrt(x); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log.cs index 74d17f036d9404..d3d2f3e9a705d3 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log.cs @@ -161,7 +161,7 @@ public static Vector512 Invoke(Vector512 x) private readonly struct LogBaseOperator : IBinaryOperator where T : ILogarithmicFunctions { - public static bool Vectorizable => LogOperator.Vectorizable; + public static bool Vectorizable => false; //LogOperator.Vectorizable; // TODO: https://github.com/dotnet/runtime/issues/100535 public static T Invoke(T x, T y) => T.Log(x, y); public static Vector128 Invoke(Vector128 x, Vector128 y) => LogOperator.Invoke(x) / LogOperator.Invoke(y); public static Vector256 Invoke(Vector256 x, Vector256 y) => LogOperator.Invoke(x) / LogOperator.Invoke(y); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Pow.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Pow.cs index 72d35ed5be779f..263235e4a5c2e3 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Pow.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Pow.cs @@ -59,7 +59,7 @@ public static void Pow(T x, ReadOnlySpan y, Span destination) private readonly struct PowOperator : IBinaryOperator where T : IPowerFunctions { - public static bool Vectorizable => typeof(T) == typeof(float) || typeof(T) == typeof(double); + public static bool Vectorizable => false; // typeof(T) == typeof(float) || typeof(T) == typeof(double); // TODO: https://github.com/dotnet/runtime/issues/100535 public static T Invoke(T x, T y) => T.Pow(x, y); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.RootN.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.RootN.cs index e7c394892950a9..5a732f76936000 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.RootN.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.RootN.cs @@ -28,7 +28,7 @@ private readonly struct RootNOperator(int n) : IStatefulUnaryOperator wher { private readonly int _n = n; - public static bool Vectorizable => typeof(T) == typeof(float) || typeof(T) == typeof(double); + public static bool Vectorizable => false; // typeof(T) == typeof(float) || typeof(T) == typeof(double); // TODO: https://github.com/dotnet/runtime/issues/100535 public T Invoke(T x) => T.RootN(x, _n); diff --git a/src/libraries/System.Numerics.Tensors/tests/Helpers.cs b/src/libraries/System.Numerics.Tensors/tests/Helpers.cs index 729cacda351695..1cc399d0a5a52c 100644 --- a/src/libraries/System.Numerics.Tensors/tests/Helpers.cs +++ b/src/libraries/System.Numerics.Tensors/tests/Helpers.cs @@ -28,6 +28,11 @@ private static class DefaultTolerance where T : unmanaged, INumber public static bool IsEqualWithTolerance(T expected, T actual, T? tolerance = null) where T : unmanaged, INumber { + if (T.IsNaN(expected) != T.IsNaN(actual)) + { + return false; + } + tolerance = tolerance ?? DefaultTolerance.Value; T diff = T.Abs(expected - actual); return !(diff > tolerance && diff > T.Max(T.Abs(expected), T.Abs(actual)) * tolerance); @@ -35,6 +40,11 @@ public static bool IsEqualWithTolerance(T expected, T actual, T? tolerance = #else public static bool IsEqualWithTolerance(float expected, float actual, float? tolerance = null) { + if (float.IsNaN(expected) != float.IsNaN(actual)) + { + return false; + } + tolerance ??= DefaultFloatTolerance; float diff = MathF.Abs(expected - actual); return !(diff > tolerance && diff > MathF.Max(MathF.Abs(expected), MathF.Abs(actual)) * tolerance); From f9207e6c85bb6aebd9e7af7504fd3db28b32d058 Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Tue, 30 Apr 2024 04:02:07 +0300 Subject: [PATCH 180/248] Remove distros versions calculation (#100580) --- eng/common/native/init-distro-rid.sh | 18 +----------------- eng/pipelines/runtime.yml | 2 +- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/eng/common/native/init-distro-rid.sh b/eng/common/native/init-distro-rid.sh index 228be0b1598629..83ea7aab0e081c 100644 --- a/eng/common/native/init-distro-rid.sh +++ b/eng/common/native/init-distro-rid.sh @@ -20,10 +20,6 @@ getNonPortableDistroRid() # shellcheck disable=SC1091 if [ -e "${rootfsDir}/etc/os-release" ]; then . "${rootfsDir}/etc/os-release" - if [ "${ID}" = "rhel" ] || [ "${ID}" = "rocky" ] || [ "${ID}" = "alpine" ] || [ "${ID}" = "ol" ]; then - VERSION_ID="${VERSION_ID%.*}" # Remove the last version digit for these distros - fi - if echo "${VERSION_ID:-}" | grep -qE '^([[:digit:]]|\.)+$'; then nonPortableRid="${ID}.${VERSION_ID}-${targetArch}" else @@ -48,19 +44,7 @@ getNonPortableDistroRid() nonPortableRid="android.$__android_sdk_version-${targetArch}" elif [ "$targetOs" = "illumos" ]; then __uname_version=$(uname -v) - case "$__uname_version" in - omnios-*) - __omnios_major_version=$(echo "$__uname_version" | cut -c9-10) - nonPortableRid="omnios.$__omnios_major_version-${targetArch}" - ;; - joyent_*) - __smartos_major_version=$(echo "$__uname_version" | cut -c9-10) - nonPortableRid="smartos.$__smartos_major_version-${targetArch}" - ;; - *) - nonPortableRid="illumos-${targetArch}" - ;; - esac + nonPortableRid="illumos-${targetArch}" elif [ "$targetOs" = "solaris" ]; then __uname_version=$(uname -v) __solaris_major_version=$(echo "$__uname_version" | cut -d'.' -f1) diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 32f99429ffd692..dbf8e0a7fcc1e4 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -498,7 +498,7 @@ extends: jobParameters: testScope: innerloop nameSuffix: CoreCLR_NonPortable - buildArgs: -s clr.native+clr.tools+clr.corelib+clr.nativecorelib+clr.aot+clr.packages -c $(_BuildConfig) /p:PortableBuild=false + buildArgs: -s clr.native+clr.tools+clr.corelib+clr.nativecorelib+clr.aot+clr.packages --outputrid tizen.9.0.0-armel -c $(_BuildConfig) /p:PortableBuild=false timeoutInMinutes: 120 condition: >- or( From 55c904024601c133f8ad081bc704c3c1fc5c7c9b Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Mon, 29 Apr 2024 20:05:01 -0700 Subject: [PATCH 181/248] Arm64/Sve: Add SignExtend* and ZeroExtend* math APIs (#101702) * Add [Sign|Zero]Extend[8|16|32] APIs: * Add API to instruction mapping * eliminate extra movprfx for AllBitsSetMask * Add test cases --- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 3 +- src/coreclr/jit/hwintrinsiclistarm64sve.h | 7 +- .../Arm/Sve.PlatformNotSupported.cs | 158 +++++++++++++++++ .../src/System/Runtime/Intrinsics/Arm/Sve.cs | 160 ++++++++++++++++++ .../ref/System.Runtime.Intrinsics.cs | 17 ++ .../GenerateHWIntrinsicTests_Arm.cs | 28 ++- .../HardwareIntrinsics/Arm/Shared/Helpers.cs | 23 +++ 7 files changed, 386 insertions(+), 10 deletions(-) diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index f58ca6c6e858d5..1f7f2865631c10 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -448,14 +448,13 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) if (intrin.op3->isContained()) { assert(intrin.op3->IsVectorZero()); - if (intrin.op1->isContained()) + if (intrin.op1->isContained() || intrin.op1->IsMaskAllBitsSet()) { // We already skip importing ConditionalSelect if op1 == trueAll, however // if we still see it here, it is because we wrapped the predicated instruction // inside ConditionalSelect. // As such, no need to move the `falseReg` to `targetReg` // because the predicated instruction will eventually set it. - assert(intrin.op1->IsMaskAllBitsSet()); } else { diff --git a/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/coreclr/jit/hwintrinsiclistarm64sve.h index cbd5ea6eb4983e..b4d0c1319a2276 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64sve.h +++ b/src/coreclr/jit/hwintrinsiclistarm64sve.h @@ -69,10 +69,15 @@ HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToUInt64, HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, Multiply, -1, 2, true, {INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_fmul, INS_sve_fmul}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sve, SignExtend16, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sxth, INS_invalid, INS_sve_sxth, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, SignExtend32, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sxtw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, SignExtend8, -1, -1, false, {INS_invalid, INS_invalid, INS_sve_sxtb, INS_invalid, INS_sve_sxtb, INS_invalid, INS_sve_sxtb, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, Subtract, -1, 2, true, {INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_fsub, INS_sve_fsub}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) - HARDWARE_INTRINSIC(Sve, UnzipEven, -1, 2, true, {INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Sve, UnzipOdd, -1, 2, true, {INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, ZeroExtend16, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_uxth, INS_invalid, INS_sve_uxth, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, ZeroExtend32, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_uxtw, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, ZeroExtend8, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_uxtb, INS_invalid, INS_sve_uxtb, INS_invalid, INS_sve_uxtb, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, ZipHigh, -1, 2, true, {INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Sve, ZipLow, -1, 2, true, {INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs index 84583b46874563..afbaa6e8969c52 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs @@ -1010,6 +1010,86 @@ internal Arm64() { } /// public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// SignExtend16 : Sign-extend the low 16 bits + + /// + /// svint32_t svexth[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// SXTH Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; SXTH Zresult.S, Pg/M, Zop.S + /// svint32_t svexth[_s32]_x(svbool_t pg, svint32_t op) + /// SXTH Ztied.S, Pg/M, Ztied.S + /// MOVPRFX Zresult, Zop; SXTH Zresult.S, Pg/M, Zop.S + /// svint32_t svexth[_s32]_z(svbool_t pg, svint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; SXTH Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector SignExtend16(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svexth[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// SXTH Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; SXTH Zresult.D, Pg/M, Zop.D + /// svint64_t svexth[_s64]_x(svbool_t pg, svint64_t op) + /// SXTH Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; SXTH Zresult.D, Pg/M, Zop.D + /// svint64_t svexth[_s64]_z(svbool_t pg, svint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; SXTH Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector SignExtend16(Vector value) { throw new PlatformNotSupportedException(); } + + + /// SignExtend32 : Sign-extend the low 32 bits + + /// + /// svint64_t svextw[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// SXTW Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; SXTW Zresult.D, Pg/M, Zop.D + /// svint64_t svextw[_s64]_x(svbool_t pg, svint64_t op) + /// SXTW Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; SXTW Zresult.D, Pg/M, Zop.D + /// svint64_t svextw[_s64]_z(svbool_t pg, svint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; SXTW Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector SignExtend32(Vector value) { throw new PlatformNotSupportedException(); } + + + /// SignExtend8 : Sign-extend the low 8 bits + + /// + /// svint16_t svextb[_s16]_m(svint16_t inactive, svbool_t pg, svint16_t op) + /// SXTB Ztied.H, Pg/M, Zop.H + /// MOVPRFX Zresult, Zinactive; SXTB Zresult.H, Pg/M, Zop.H + /// svint16_t svextb[_s16]_x(svbool_t pg, svint16_t op) + /// SXTB Ztied.H, Pg/M, Ztied.H + /// MOVPRFX Zresult, Zop; SXTB Zresult.H, Pg/M, Zop.H + /// svint16_t svextb[_s16]_z(svbool_t pg, svint16_t op) + /// MOVPRFX Zresult.H, Pg/Z, Zop.H; SXTB Zresult.H, Pg/M, Zop.H + /// + public static unsafe Vector SignExtend8(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svextb[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// SXTB Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; SXTB Zresult.S, Pg/M, Zop.S + /// svint32_t svextb[_s32]_x(svbool_t pg, svint32_t op) + /// SXTB Ztied.S, Pg/M, Ztied.S + /// MOVPRFX Zresult, Zop; SXTB Zresult.S, Pg/M, Zop.S + /// svint32_t svextb[_s32]_z(svbool_t pg, svint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; SXTB Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector SignExtend8(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svextb[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// SXTB Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; SXTB Zresult.D, Pg/M, Zop.D + /// svint64_t svextb[_s64]_x(svbool_t pg, svint64_t op) + /// SXTB Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; SXTB Zresult.D, Pg/M, Zop.D + /// svint64_t svextb[_s64]_z(svbool_t pg, svint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; SXTB Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector SignExtend8(Vector value) { throw new PlatformNotSupportedException(); } + /// Subtract : Subtract /// @@ -1248,6 +1328,84 @@ internal Arm64() { } /// public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// ZeroExtend16 : Zero-extend the low 16 bits + + /// + /// svuint32_t svexth[_u32]_m(svuint32_t inactive, svbool_t pg, svuint32_t op) + /// UXTH Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; UXTH Zresult.S, Pg/M, Zop.S + /// svuint32_t svexth[_u32]_x(svbool_t pg, svuint32_t op) + /// UXTH Ztied.S, Pg/M, Ztied.S + /// AND Ztied.S, Ztied.S, #65535 + /// svuint32_t svexth[_u32]_z(svbool_t pg, svuint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; UXTH Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector ZeroExtend16(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svexth[_u64]_m(svuint64_t inactive, svbool_t pg, svuint64_t op) + /// UXTH Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; UXTH Zresult.D, Pg/M, Zop.D + /// svuint64_t svexth[_u64]_x(svbool_t pg, svuint64_t op) + /// UXTH Ztied.D, Pg/M, Ztied.D + /// AND Ztied.D, Ztied.D, #65535 + /// svuint64_t svexth[_u64]_z(svbool_t pg, svuint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; UXTH Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector ZeroExtend16(Vector value) { throw new PlatformNotSupportedException(); } + + + /// ZeroExtend32 : Zero-extend the low 32 bits + + /// + /// svuint64_t svextw[_u64]_m(svuint64_t inactive, svbool_t pg, svuint64_t op) + /// UXTW Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; UXTW Zresult.D, Pg/M, Zop.D + /// svuint64_t svextw[_u64]_x(svbool_t pg, svuint64_t op) + /// UXTW Ztied.D, Pg/M, Ztied.D + /// AND Ztied.D, Ztied.D, #4294967295 + /// svuint64_t svextw[_u64]_z(svbool_t pg, svuint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; UXTW Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector ZeroExtend32(Vector value) { throw new PlatformNotSupportedException(); } + + /// ZeroExtend8 : Zero-extend the low 8 bits + + /// + /// svuint16_t svextb[_u16]_m(svuint16_t inactive, svbool_t pg, svuint16_t op) + /// UXTB Ztied.H, Pg/M, Zop.H + /// MOVPRFX Zresult, Zinactive; UXTB Zresult.H, Pg/M, Zop.H + /// svuint16_t svextb[_u16]_x(svbool_t pg, svuint16_t op) + /// UXTB Ztied.H, Pg/M, Ztied.H + /// AND Ztied.H, Ztied.H, #255 + /// svuint16_t svextb[_u16]_z(svbool_t pg, svuint16_t op) + /// MOVPRFX Zresult.H, Pg/Z, Zop.H; UXTB Zresult.H, Pg/M, Zop.H + /// + public static unsafe Vector ZeroExtend8(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svextb[_u32]_m(svuint32_t inactive, svbool_t pg, svuint32_t op) + /// UXTB Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; UXTB Zresult.S, Pg/M, Zop.S + /// svuint32_t svextb[_u32]_x(svbool_t pg, svuint32_t op) + /// UXTB Ztied.S, Pg/M, Ztied.S + /// AND Ztied.S, Ztied.S, #255 + /// svuint32_t svextb[_u32]_z(svbool_t pg, svuint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; UXTB Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector ZeroExtend8(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svextb[_u64]_m(svuint64_t inactive, svbool_t pg, svuint64_t op) + /// UXTB Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; UXTB Zresult.D, Pg/M, Zop.D + /// svuint64_t svextb[_u64]_x(svbool_t pg, svuint64_t op) + /// UXTB Ztied.D, Pg/M, Ztied.D + /// AND Ztied.D, Ztied.D, #255 + /// svuint64_t svextb[_u64]_z(svbool_t pg, svuint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; UXTB Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector ZeroExtend8(Vector value) { throw new PlatformNotSupportedException(); } /// ZipHigh : Interleave elements from high halves of two inputs diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs index e823e36e4db2a9..7c2c8a0a4e78e6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs @@ -1065,6 +1065,85 @@ internal Arm64() { } /// public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + /// SignExtend16 : Sign-extend the low 16 bits + + /// + /// svint32_t svexth[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// SXTH Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; SXTH Zresult.S, Pg/M, Zop.S + /// svint32_t svexth[_s32]_x(svbool_t pg, svint32_t op) + /// SXTH Ztied.S, Pg/M, Ztied.S + /// MOVPRFX Zresult, Zop; SXTH Zresult.S, Pg/M, Zop.S + /// svint32_t svexth[_s32]_z(svbool_t pg, svint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; SXTH Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector SignExtend16(Vector value) => SignExtend16(value); + + /// + /// svint64_t svexth[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// SXTH Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; SXTH Zresult.D, Pg/M, Zop.D + /// svint64_t svexth[_s64]_x(svbool_t pg, svint64_t op) + /// SXTH Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; SXTH Zresult.D, Pg/M, Zop.D + /// svint64_t svexth[_s64]_z(svbool_t pg, svint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; SXTH Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector SignExtend16(Vector value) => SignExtend16(value); + + /// SignExtend32 : Sign-extend the low 32 bits + + /// + /// svint64_t svextw[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// SXTW Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; SXTW Zresult.D, Pg/M, Zop.D + /// svint64_t svextw[_s64]_x(svbool_t pg, svint64_t op) + /// SXTW Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; SXTW Zresult.D, Pg/M, Zop.D + /// svint64_t svextw[_s64]_z(svbool_t pg, svint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; SXTW Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector SignExtend32(Vector value) => SignExtend32(value); + + + /// SignExtend8 : Sign-extend the low 8 bits + + /// + /// svint16_t svextb[_s16]_m(svint16_t inactive, svbool_t pg, svint16_t op) + /// SXTB Ztied.H, Pg/M, Zop.H + /// MOVPRFX Zresult, Zinactive; SXTB Zresult.H, Pg/M, Zop.H + /// svint16_t svextb[_s16]_x(svbool_t pg, svint16_t op) + /// SXTB Ztied.H, Pg/M, Ztied.H + /// MOVPRFX Zresult, Zop; SXTB Zresult.H, Pg/M, Zop.H + /// svint16_t svextb[_s16]_z(svbool_t pg, svint16_t op) + /// MOVPRFX Zresult.H, Pg/Z, Zop.H; SXTB Zresult.H, Pg/M, Zop.H + /// + public static unsafe Vector SignExtend8(Vector value) => SignExtend8(value); + + /// + /// svint32_t svextb[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// SXTB Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; SXTB Zresult.S, Pg/M, Zop.S + /// svint32_t svextb[_s32]_x(svbool_t pg, svint32_t op) + /// SXTB Ztied.S, Pg/M, Ztied.S + /// MOVPRFX Zresult, Zop; SXTB Zresult.S, Pg/M, Zop.S + /// svint32_t svextb[_s32]_z(svbool_t pg, svint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; SXTB Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector SignExtend8(Vector value) => SignExtend8(value); + + /// + /// svint64_t svextb[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// SXTB Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; SXTB Zresult.D, Pg/M, Zop.D + /// svint64_t svextb[_s64]_x(svbool_t pg, svint64_t op) + /// SXTB Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; SXTB Zresult.D, Pg/M, Zop.D + /// svint64_t svextb[_s64]_z(svbool_t pg, svint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; SXTB Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector SignExtend8(Vector value) => SignExtend8(value); + /// Subtract : Subtract /// @@ -1329,6 +1408,87 @@ internal Arm64() { } /// UZP2 Presult.D, Pop1.D, Pop2.D /// public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + + /// ZeroExtend16 : Zero-extend the low 16 bits + + /// + /// svuint32_t svexth[_u32]_m(svuint32_t inactive, svbool_t pg, svuint32_t op) + /// UXTH Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; UXTH Zresult.S, Pg/M, Zop.S + /// svuint32_t svexth[_u32]_x(svbool_t pg, svuint32_t op) + /// UXTH Ztied.S, Pg/M, Ztied.S + /// AND Ztied.S, Ztied.S, #65535 + /// svuint32_t svexth[_u32]_z(svbool_t pg, svuint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; UXTH Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector ZeroExtend16(Vector value) => ZeroExtend16(value); + + /// + /// svuint64_t svexth[_u64]_m(svuint64_t inactive, svbool_t pg, svuint64_t op) + /// UXTH Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; UXTH Zresult.D, Pg/M, Zop.D + /// svuint64_t svexth[_u64]_x(svbool_t pg, svuint64_t op) + /// UXTH Ztied.D, Pg/M, Ztied.D + /// AND Ztied.D, Ztied.D, #65535 + /// svuint64_t svexth[_u64]_z(svbool_t pg, svuint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; UXTH Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector ZeroExtend16(Vector value) => ZeroExtend16(value); + + + /// ZeroExtend32 : Zero-extend the low 32 bits + + /// + /// svuint64_t svextw[_u64]_m(svuint64_t inactive, svbool_t pg, svuint64_t op) + /// UXTW Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; UXTW Zresult.D, Pg/M, Zop.D + /// svuint64_t svextw[_u64]_x(svbool_t pg, svuint64_t op) + /// UXTW Ztied.D, Pg/M, Ztied.D + /// AND Ztied.D, Ztied.D, #4294967295 + /// svuint64_t svextw[_u64]_z(svbool_t pg, svuint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; UXTW Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector ZeroExtend32(Vector value) => ZeroExtend32(value); + + + /// ZeroExtend8 : Zero-extend the low 8 bits + + /// + /// svuint16_t svextb[_u16]_m(svuint16_t inactive, svbool_t pg, svuint16_t op) + /// UXTB Ztied.H, Pg/M, Zop.H + /// MOVPRFX Zresult, Zinactive; UXTB Zresult.H, Pg/M, Zop.H + /// svuint16_t svextb[_u16]_x(svbool_t pg, svuint16_t op) + /// UXTB Ztied.H, Pg/M, Ztied.H + /// AND Ztied.H, Ztied.H, #255 + /// svuint16_t svextb[_u16]_z(svbool_t pg, svuint16_t op) + /// MOVPRFX Zresult.H, Pg/Z, Zop.H; UXTB Zresult.H, Pg/M, Zop.H + /// + public static unsafe Vector ZeroExtend8(Vector value) => ZeroExtend8(value); + + /// + /// svuint32_t svextb[_u32]_m(svuint32_t inactive, svbool_t pg, svuint32_t op) + /// UXTB Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; UXTB Zresult.S, Pg/M, Zop.S + /// svuint32_t svextb[_u32]_x(svbool_t pg, svuint32_t op) + /// UXTB Ztied.S, Pg/M, Ztied.S + /// AND Ztied.S, Ztied.S, #255 + /// svuint32_t svextb[_u32]_z(svbool_t pg, svuint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; UXTB Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector ZeroExtend8(Vector value) => ZeroExtend8(value); + + /// + /// svuint64_t svextb[_u64]_m(svuint64_t inactive, svbool_t pg, svuint64_t op) + /// UXTB Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; UXTB Zresult.D, Pg/M, Zop.D + /// svuint64_t svextb[_u64]_x(svbool_t pg, svuint64_t op) + /// UXTB Ztied.D, Pg/M, Ztied.D + /// AND Ztied.D, Ztied.D, #255 + /// svuint64_t svextb[_u64]_z(svbool_t pg, svuint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; UXTB Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector ZeroExtend8(Vector value) => ZeroExtend8(value); + /// ZipHigh : Interleave elements from high halves of two inputs /// diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index f67349e325b27e..88839fee87dcad 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -4279,6 +4279,14 @@ internal Arm64() { } public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendToUInt64(System.Numerics.Vector mask, ushort* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendToInt64(System.Numerics.Vector mask, uint* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendToUInt64(System.Numerics.Vector mask, uint* address) { throw null; } + + public static System.Numerics.Vector SignExtend16(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtend16(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtend32(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtend8(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtend8(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtend8(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -4289,6 +4297,7 @@ internal Arm64() { } public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -4299,6 +4308,7 @@ internal Arm64() { } public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -4321,6 +4331,13 @@ internal Arm64() { } public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZeroExtend16(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtend16(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtend32(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtend8(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtend8(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtend8(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } diff --git a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs index 9ef86027848352..589217ca968e4a 100644 --- a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs +++ b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs @@ -2972,12 +2972,6 @@ ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_uint", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_ulong", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), @@ -2990,6 +2984,12 @@ ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), @@ -3008,6 +3008,13 @@ ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend16_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend16_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend32_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 32, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 32, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend8_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend8_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend8_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, false)"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), @@ -3039,7 +3046,14 @@ ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), - + + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend16_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend16_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend32_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 32, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 32, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs index 4b44b29337573a..6e96c9fc080a5a 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs @@ -1701,6 +1701,29 @@ private static int HighNarrowing(long op1, bool round) public static long MultiplyWideningUpperAndSubtract(long[] op1, int[] op2, int[] op3, int i) => MultiplyWideningAndSubtract(op1[i], op2[i + op2.Length / 2], op3[i + op3.Length / 2]); + public static T SignExtend(T n, int numBits, bool zeroExtend) where T : struct, IComparable, IConvertible + { + // Get the underlying integer value + dynamic value = Convert.ChangeType(n, typeof(long)); + + // Mask to extract the lowest numBits + long mask = (1L << numBits) - 1; + long lowestBits = value & mask; + + // Sign extension for signed integers + long signBitMask = 1L << (numBits - 1); + if (!zeroExtend && ((lowestBits & signBitMask) != 0)) + { + // If sign bit is set, it's a negative number + return (T)Convert.ChangeType(-((~lowestBits & mask) + 1), typeof(T)); + } + else + { + // If sign bit is not set, it's a positive number + return (T)Convert.ChangeType(lowestBits, typeof(T)); + } + } + public static int SubtractHighNarrowing(long op1, long op2) => HighNarrowing((long)(op1 - op2), round: false); public static long SubtractHighNarrowingUpper(int[] op1, long[] op2, long[] op3, int i) => i < op1.Length ? op1[i] : SubtractHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); From 333fb71d54bd84256e740aa08f8b836d4cd71d98 Mon Sep 17 00:00:00 2001 From: AtariDreams Date: Tue, 30 Apr 2024 00:29:04 -0400 Subject: [PATCH 182/248] Optimize flips between 1 and 0 (#100491) We can solve this with a bit flip rather than + 1 mod 2. --- src/coreclr/jit/compiler.cpp | 2 +- src/coreclr/jit/emitxarch.cpp | 8 ++++---- src/coreclr/vm/gc_unwind_x86.inl | 5 +---- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 60f306307b90cd..f15820a7dc5746 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -2193,7 +2193,7 @@ const char* Compiler::compRegVarName(regNumber reg, bool displayVar, bool isFloa // consecutive calls before printing static int index = 0; // for circular index into the name array - index = (index + 1) % 2; // circular reuse of index + index ^= 1; // circular reuse of index sprintf_s(nameVarReg[index], NAME_VAR_REG_BUFFER_LEN, "%s'%s'", getRegName(reg), VarNameToStr(varName)); return nameVarReg[index]; diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 35cb3a986ee580..6fe7f00dddc359 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -10102,7 +10102,7 @@ const char* emitter::emitRegName(regNumber reg, emitAttr attr, bool varName) con suffix = 'd'; goto APPEND_SUFFIX; } - rbc = (rbc + 1) % 2; + rbc ^= 1; rb[rbc][0] = 'e'; rb[rbc][1] = rn[1]; rb[rbc][2] = rn[2]; @@ -10133,7 +10133,7 @@ const char* emitter::emitRegName(regNumber reg, emitAttr attr, bool varName) con { suffix = 'b'; APPEND_SUFFIX: - rbc = (rbc + 1) % 2; + rbc ^= 1; rb[rbc][0] = rn[0]; rb[rbc][1] = rn[1]; if (rn[2]) @@ -10151,7 +10151,7 @@ const char* emitter::emitRegName(regNumber reg, emitAttr attr, bool varName) con } else { - rbc = (rbc + 1) % 2; + rbc ^= 1; rb[rbc][0] = rn[1]; if (reg < 4) { @@ -10168,7 +10168,7 @@ const char* emitter::emitRegName(regNumber reg, emitAttr attr, bool varName) con #endif // TARGET_AMD64 #if defined(TARGET_X86) - rbc = (rbc + 1) % 2; + rbc ^= 1; rb[rbc][0] = rn[1]; rb[rbc][1] = 'l'; strcpy_s(&rb[rbc][2], sizeof(rb[0]) - 2, rn + 3); diff --git a/src/coreclr/vm/gc_unwind_x86.inl b/src/coreclr/vm/gc_unwind_x86.inl index 017f8f8f803a9e..33604336d28c52 100644 --- a/src/coreclr/vm/gc_unwind_x86.inl +++ b/src/coreclr/vm/gc_unwind_x86.inl @@ -1670,10 +1670,7 @@ unsigned scanArgRegTableI(PTR_CBYTE table, { thisPtrReg = REGI_NA; } - if (iptrRegs & regMask) - { - iptrRegs &= ~regMask; - } + iptrRegs &= ~regMask; } iptr = isThis = false; continue; From fcc2408188269837221ff73f169de161aa47acac Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Mon, 29 Apr 2024 22:18:15 -0700 Subject: [PATCH 183/248] Update build instructions table (#101706) --- docs/workflow/building/coreclr/linux-instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/workflow/building/coreclr/linux-instructions.md b/docs/workflow/building/coreclr/linux-instructions.md index 518208141e49f6..3acec5e95ad9a9 100644 --- a/docs/workflow/building/coreclr/linux-instructions.md +++ b/docs/workflow/building/coreclr/linux-instructions.md @@ -66,7 +66,7 @@ All official builds are cross-builds with a rootfs for the target OS, and will u | Azure Linux (x64) | Ubuntu 16.04 | arm32 (armhf) | `mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0` | `/crossrootfs/arm` | | Azure Linux (x64) | Alpine | arm64 (arm64v8) | `mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm64-alpine-net9.0` | `/crossrootfs/arm64` | | Azure Linux (x64) | Ubuntu 16.04 | arm64 (arm64v8) | `mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm64-net9.0` | `/crossrootfs/arm64` | -| Azure Linux (x64) | Ubuntu 16.04 | x86 | `mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-x86-net8.0` | `/crossrootfs/x86` | +| Azure Linux (x64) | Ubuntu 16.04 | x86 | `mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-x86-net9.0` | `/crossrootfs/x86` | | CBL-mariner 2.0 (x64) | FreeBSD 13 | x64 | `mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-amd64-freebsd-13` | `/crossrootfs/x64` | These Docker images are built using the Dockerfiles maintained in the [dotnet-buildtools-prereqs-docker repo](https://github.com/dotnet/dotnet-buildtools-prereqs-docker). From fc09b220e1c6f48ab755f9f259b8441c58c0880c Mon Sep 17 00:00:00 2001 From: Matous Kozak <55735845+matouskozak@users.noreply.github.com> Date: Tue, 30 Apr 2024 10:48:33 +0200 Subject: [PATCH 184/248] [mono] Force Mono to respect explicit struct size when LayoutKind.Sequential is used (#101529) * respect explicit size with sequential layout * test for sequential layout with explicit size --- src/mono/mono/metadata/class-init.c | 2 +- src/mono/mono/metadata/marshal.c | 7 +- .../MarshalUnalignedStructArray.cs | 75 +++++++++++++++++++ 3 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 src/tests/Interop/ArrayMarshalling/UnalignedStructArray/MarshalUnalignedStructArray.cs diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c index 13cf1fa612b359..8608dc30bfc63a 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -2331,7 +2331,7 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ instance_size = MAX (real_size, instance_size); - if (instance_size & (min_align - 1)) { + if (instance_size & (min_align - 1) && !explicit_size) { instance_size += min_align - 1; instance_size &= ~(min_align - 1); } diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 09fddd573c0fdb..aad740a31d90e5 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -5749,7 +5749,7 @@ MonoMarshalType * mono_marshal_load_type_info (MonoClass* klass) { int j, count = 0; - guint32 native_size = 0, min_align = 1, packing; + guint32 native_size = 0, min_align = 1, packing, explicit_size = 0; MonoMarshalType *info; MonoClassField* field; gpointer iter; @@ -5793,7 +5793,7 @@ mono_marshal_load_type_info (MonoClass* klass) info->num_fields = count; /* Try to find a size for this type in metadata */ - mono_metadata_packing_from_typedef (m_class_get_image (klass), m_class_get_type_token (klass), NULL, &native_size); + explicit_size = mono_metadata_packing_from_typedef (m_class_get_image (klass), m_class_get_type_token (klass), NULL, &native_size); if (m_class_get_parent (klass)) { int parent_size = mono_class_native_size (m_class_get_parent (klass), NULL); @@ -5879,6 +5879,9 @@ mono_marshal_load_type_info (MonoClass* klass) align_size = FALSE; else min_align = MIN (min_align, packing); + } else if (layout == TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT) { + if (explicit_size && native_size == info->native_size) + align_size = FALSE; } } diff --git a/src/tests/Interop/ArrayMarshalling/UnalignedStructArray/MarshalUnalignedStructArray.cs b/src/tests/Interop/ArrayMarshalling/UnalignedStructArray/MarshalUnalignedStructArray.cs new file mode 100644 index 00000000000000..266a5dbf28d83b --- /dev/null +++ b/src/tests/Interop/ArrayMarshalling/UnalignedStructArray/MarshalUnalignedStructArray.cs @@ -0,0 +1,75 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Runtime.InteropServices; +using TestLibrary; +using Xunit; + +public static unsafe class MarshalUnalignedStructArrayTest +{ + [Fact] + public static void TestEntryPoint() + { + /* + * This test validates that the size and offsets of InnerStruct and OuterStruct are as expected. + * It also demonstrates accessing unaligned data in an array. + */ + // Validate that both InnerStruct and OuterStruct have the correct size + Assert.Equal(12, sizeof(InnerStruct)); + Assert.Equal(24, sizeof(OuterStruct)); + + // Validate that the fields of InnerStruct are at the expected offsets + Assert.Equal(0, Marshal.OffsetOf("F0").ToInt32()); + Assert.Equal(8, Marshal.OffsetOf("F1").ToInt32()); + + // Validate that the fields of OuterStruct are at the expected offsets + Assert.Equal(0, Marshal.OffsetOf("F0").ToInt32()); + Assert.Equal(8, Marshal.OffsetOf("F1").ToInt32()); + Assert.Equal(20, Marshal.OffsetOf("F2").ToInt32()); + + // Validate that we are able to access unaligned in an array + InnerStruct[] arrStructs = new InnerStruct[] + { + new InnerStruct(1, 2), + new InnerStruct(3, 4), + new InnerStruct(5, 6), + }; + + fixed (InnerStruct* pStruct = &arrStructs[0]) + { + byte* ptr = (byte*)pStruct; + ptr += 12; + Assert.Equal(3, *(long*)ptr); + Assert.Equal(4, *(int*)(ptr + 8)); + } + + } +} + +[StructLayout(LayoutKind.Sequential, Size = 12)] +struct InnerStruct +{ + public long F0; + public uint F1; + + public InnerStruct(long f0, uint f1) + { + F0 = f0; + F1 = f1; + } +} + +[StructLayout(LayoutKind.Sequential, Size = 24)] +struct OuterStruct +{ + public sbyte F0; + public InnerStruct F1; + public uint F2; + + public OuterStruct(sbyte f0, InnerStruct f1, uint f2) + { + F0 = f0; + F1 = f1; + F2 = f2; + } +} From d7a6ffa857ee8bee4732604c0cb7e9008f0df90c Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Tue, 30 Apr 2024 10:48:47 +0200 Subject: [PATCH 185/248] SPMI: Replay recorded allocPgoInstrumentationBySchema HRESULT (#101696) Current SPMI collection has a recorded allocPgoInstrumentationBySchema call that failed (EE returned 0x80004001). SPMI fails to replay that correctly. Fix #101685 --- .../tools/superpmi/superpmi-shared/methodcontext.cpp | 9 ++++++--- .../tools/superpmi/superpmi-shared/methodcontext.h | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 4219aca7ca118b..25e3b1c7744150 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -5640,10 +5640,11 @@ HRESULT MethodContext::repAllocPgoInstrumentationBySchema( UINT32 countSchemaItems, BYTE** pInstrumentationData) { - if (repAllocPgoInstrumentationBySchemaRecorded(ftnHnd, pSchema, countSchemaItems, pInstrumentationData)) + HRESULT result; + if (repAllocPgoInstrumentationBySchemaRecorded(ftnHnd, pSchema, countSchemaItems, pInstrumentationData, &result)) { // Matching case: return same layout as recorded EE. - return S_OK; + return result; } // Do our own layout. @@ -5676,7 +5677,8 @@ bool MethodContext::repAllocPgoInstrumentationBySchemaRecorded( CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, UINT32 countSchemaItems, - BYTE** pInstrumentationData) + BYTE** pInstrumentationData, + HRESULT* result) { if (AllocPgoInstrumentationBySchema == nullptr) return false; @@ -5716,6 +5718,7 @@ bool MethodContext::repAllocPgoInstrumentationBySchemaRecorded( // We assume JIT does not write or read from this buffer, only generate // code that uses it. *pInstrumentationData = (BYTE*)value.instrumentationDataAddress; + *result = value.result; return true; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 2af344894e97d8..2c85988aa32e8e 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -709,7 +709,7 @@ class MethodContext void recAllocPgoInstrumentationBySchema(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, UINT32 countSchemaItems, BYTE** pInstrumentationData, HRESULT result); void dmpAllocPgoInstrumentationBySchema(DWORDLONG key, const Agnostic_AllocPgoInstrumentationBySchema& value); HRESULT repAllocPgoInstrumentationBySchema(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, UINT32 countSchemaItems, BYTE** pInstrumentationData); - bool repAllocPgoInstrumentationBySchemaRecorded(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, UINT32 countSchemaItems, BYTE** pInstrumentationData); + bool repAllocPgoInstrumentationBySchemaRecorded(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, UINT32 countSchemaItems, BYTE** pInstrumentationData, HRESULT* result); void recGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, UINT32* pCountSchemaItems, BYTE** pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource, bool* pDynamicPgo, HRESULT result); void dmpGetPgoInstrumentationResults(DWORDLONG key, const Agnostic_GetPgoInstrumentationResults& value); From 3fac575b7308febd8a1bbd34c2382eede1096b03 Mon Sep 17 00:00:00 2001 From: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Tue, 30 Apr 2024 12:14:05 +0200 Subject: [PATCH 186/248] Refresh cached credentials after PreAuthenticate fails (#101053) * Support refreshing credentials in pre-auth cache * Fix minor bug in CredentialCache * Add unit test * Fix tests * Fix tests attempt 2 * Merge two lock statements. * Fix build --- .../src/System/Net/CredentialCacheKey.cs | 133 ++++++++++++++++++ .../src/System.Net.Http.csproj | 3 + .../AuthenticationHelper.cs | 36 +++-- .../ConnectionPool/HttpConnectionPool.cs | 6 +- .../PreAuthCredentialCache.cs | 61 ++++++++ .../HttpClientHandlerTest.BasicAuth.cs | 114 +++++++++++++++ .../System.Net.Http.Functional.Tests.csproj | 1 + .../src/System.Net.Primitives.csproj | 2 + .../src/System/Net/CredentialCache.cs | 126 +---------------- .../FunctionalTests/CredentialCacheTest.cs | 11 ++ 10 files changed, 363 insertions(+), 130 deletions(-) create mode 100644 src/libraries/Common/src/System/Net/CredentialCacheKey.cs create mode 100644 src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/PreAuthCredentialCache.cs create mode 100644 src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.BasicAuth.cs diff --git a/src/libraries/Common/src/System/Net/CredentialCacheKey.cs b/src/libraries/Common/src/System/Net/CredentialCacheKey.cs new file mode 100644 index 00000000000000..0d59c101493157 --- /dev/null +++ b/src/libraries/Common/src/System/Net/CredentialCacheKey.cs @@ -0,0 +1,133 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; + +namespace System.Net +{ + internal sealed class CredentialCacheKey : IEquatable + { + public readonly Uri UriPrefix; + public readonly int UriPrefixLength = -1; + public readonly string AuthenticationType; + + internal CredentialCacheKey(Uri uriPrefix, string authenticationType) + { + Debug.Assert(uriPrefix != null); + Debug.Assert(authenticationType != null); + + UriPrefix = uriPrefix; + UriPrefixLength = UriPrefix.AbsolutePath.LastIndexOf('/'); + AuthenticationType = authenticationType; + } + + internal bool Match(Uri uri, string authenticationType) + { + if (uri == null || authenticationType == null) + { + return false; + } + + // If the protocols don't match, this credential is not applicable for the given Uri. + if (!string.Equals(authenticationType, AuthenticationType, StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Match({UriPrefix} & {uri})"); + + return IsPrefix(uri, UriPrefix); + } + + // IsPrefix (Uri) + // + // Determines whether is a prefix of this URI. A prefix + // match is defined as: + // + // scheme match + // + host match + // + port match, if any + // + path is a prefix of path, if any + // + // Returns: + // True if is a prefix of this URI + private static bool IsPrefix(Uri uri, Uri prefixUri) + { + Debug.Assert(uri != null); + Debug.Assert(prefixUri != null); + + if (prefixUri.Scheme != uri.Scheme || prefixUri.Host != uri.Host || prefixUri.Port != uri.Port) + { + return false; + } + + int prefixLen = prefixUri.AbsolutePath.LastIndexOf('/'); + if (prefixLen > uri.AbsolutePath.LastIndexOf('/')) + { + return false; + } + + return string.Compare(uri.AbsolutePath, 0, prefixUri.AbsolutePath, 0, prefixLen, StringComparison.OrdinalIgnoreCase) == 0; + } + + public override int GetHashCode() => + StringComparer.OrdinalIgnoreCase.GetHashCode(AuthenticationType) ^ + UriPrefix.GetHashCode(); + + public bool Equals([NotNullWhen(true)] CredentialCacheKey? other) + { + if (other == null) + { + return false; + } + + bool equals = + string.Equals(AuthenticationType, other.AuthenticationType, StringComparison.OrdinalIgnoreCase) && + UriPrefix.Equals(other.UriPrefix); + + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Equals({this},{other}) returns {equals}"); + + return equals; + } + + public override bool Equals([NotNullWhen(true)] object? obj) => Equals(obj as CredentialCacheKey); + + public override string ToString() => + string.Create(CultureInfo.InvariantCulture, $"[{UriPrefixLength}]:{UriPrefix}:{AuthenticationType}"); + } + + internal static class CredentialCacheHelper + { + public static bool TryGetCredential(Dictionary cache, Uri uriPrefix, string authType, [NotNullWhen(true)] out Uri? mostSpecificMatchUri, [NotNullWhen(true)] out NetworkCredential? mostSpecificMatch) + { + int longestMatchPrefix = -1; + mostSpecificMatch = null; + mostSpecificMatchUri = null; + + // Enumerate through every credential in the cache + foreach ((CredentialCacheKey key, NetworkCredential value) in cache) + { + // Determine if this credential is applicable to the current Uri/AuthType + if (key.Match(uriPrefix, authType)) + { + int prefixLen = key.UriPrefixLength; + + // Check if the match is better than the current-most-specific match + if (prefixLen > longestMatchPrefix) + { + // Yes: update the information about currently preferred match + longestMatchPrefix = prefixLen; + mostSpecificMatch = value; + mostSpecificMatchUri = key.UriPrefix; + } + } + } + + return mostSpecificMatch != null; + } + } +} diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj index 7db63948a28513..e4ffec94743f35 100644 --- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj +++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj @@ -164,6 +164,8 @@ Link="Common\System\Text\ValueStringBuilder.AppendSpanFormattable.cs" /> + @@ -216,6 +218,7 @@ + diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs index 639e0367ba5aa7..69f01907167c7e 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs @@ -215,11 +215,12 @@ private static async ValueTask SendWithAuthAsync(HttpReques // If preauth is enabled and this isn't proxy auth, try to get a basic credential from the // preauth credentials cache, and if successful, set an auth header for it onto the request. // Currently we only support preauth for Basic. - bool performedBasicPreauth = false; + NetworkCredential? preAuthCredential = null; + Uri? preAuthCredentialUri = null; if (preAuthenticate) { Debug.Assert(pool.PreAuthCredentials != null); - NetworkCredential? credential; + (Uri uriPrefix, NetworkCredential credential)? preAuthCredentialPair; lock (pool.PreAuthCredentials) { // Just look for basic credentials. If in the future we support preauth @@ -227,13 +228,13 @@ private static async ValueTask SendWithAuthAsync(HttpReques Debug.Assert(pool.PreAuthCredentials.GetCredential(authUri, NegotiateScheme) == null); Debug.Assert(pool.PreAuthCredentials.GetCredential(authUri, NtlmScheme) == null); Debug.Assert(pool.PreAuthCredentials.GetCredential(authUri, DigestScheme) == null); - credential = pool.PreAuthCredentials.GetCredential(authUri, BasicScheme); + preAuthCredentialPair = pool.PreAuthCredentials.GetCredential(authUri, BasicScheme); } - if (credential != null) + if (preAuthCredentialPair != null) { - SetBasicAuthToken(request, credential, isProxyAuth); - performedBasicPreauth = true; + (preAuthCredentialUri, preAuthCredential) = preAuthCredentialPair.Value; + SetBasicAuthToken(request, preAuthCredential, isProxyAuth); } } @@ -265,13 +266,21 @@ await TrySetDigestAuthToken(request, challenge.Credential, digestResponse, isPro break; case AuthenticationType.Basic: - if (performedBasicPreauth) + if (preAuthCredential != null) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.AuthenticationError(authUri, $"Pre-authentication with {(isProxyAuth ? "proxy" : "server")} failed."); } - break; + + if (challenge.Credential == preAuthCredential) + { + // Pre auth failed, and user supplied credentials are still same, we can stop there. + break; + } + + // Pre-auth credentials have changed, continue with the new ones. + // The old ones will be removed below. } response.Dispose(); @@ -293,6 +302,17 @@ await TrySetDigestAuthToken(request, challenge.Credential, digestResponse, isPro default: lock (pool.PreAuthCredentials!) { + // remove previously cached (failing) creds + if (preAuthCredentialUri != null) + { + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(pool.PreAuthCredentials, $"Removing Basic credential from cache, uri={preAuthCredentialUri}, username={preAuthCredential!.UserName}"); + } + + pool.PreAuthCredentials.Remove(preAuthCredentialUri, BasicScheme); + } + try { if (NetEventSource.Log.IsEnabled()) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.cs index 1cff8e9ad39516..0d9f3a2a1b9537 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.cs @@ -59,7 +59,7 @@ internal sealed partial class HttpConnectionPool : IDisposable private SslClientAuthenticationOptions? _sslOptionsHttp3; private readonly SslClientAuthenticationOptions? _sslOptionsProxy; - private readonly CredentialCache? _preAuthCredentials; + private readonly PreAuthCredentialCache? _preAuthCredentials; /// Whether the pool has been used since the last time a cleanup occurred. private bool _usedSinceLastCleanup = true; @@ -237,7 +237,7 @@ public HttpConnectionPool(HttpConnectionPoolManager poolManager, HttpConnectionK // Set up for PreAuthenticate. Access to this cache is guarded by a lock on the cache itself. if (_poolManager.Settings._preAuthenticate) { - _preAuthCredentials = new CredentialCache(); + _preAuthCredentials = new PreAuthCredentialCache(); } _http11RequestQueue = new RequestQueue(); @@ -296,7 +296,7 @@ private static SslClientAuthenticationOptions ConstructSslOptions(HttpConnection public bool IsSecure => _kind == HttpConnectionKind.Https || _kind == HttpConnectionKind.SslProxyTunnel || _kind == HttpConnectionKind.SslSocksTunnel; public Uri? ProxyUri => _proxyUri; public ICredentials? ProxyCredentials => _poolManager.ProxyCredentials; - public CredentialCache? PreAuthCredentials => _preAuthCredentials; + public PreAuthCredentialCache? PreAuthCredentials => _preAuthCredentials; public bool IsDefaultPort => OriginAuthority.Port == (IsSecure ? DefaultHttpsPort : DefaultHttpPort); private bool DoProxyAuth => (_kind == HttpConnectionKind.Proxy || _kind == HttpConnectionKind.ProxyConnect); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/PreAuthCredentialCache.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/PreAuthCredentialCache.cs new file mode 100644 index 00000000000000..1f4dcc54fb0c2c --- /dev/null +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/PreAuthCredentialCache.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; + +namespace System.Net.Http +{ + internal sealed class PreAuthCredentialCache + { + private Dictionary? _cache; + + public void Add(Uri uriPrefix, string authType, NetworkCredential cred) + { + Debug.Assert(uriPrefix != null); + Debug.Assert(authType != null); + + var key = new CredentialCacheKey(uriPrefix, authType); + + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Adding key:[{key}], cred:[{cred.Domain}],[{cred.UserName}]"); + + _cache ??= new Dictionary(); + _cache.Add(key, cred); + } + + public void Remove(Uri uriPrefix, string authType) + { + Debug.Assert(uriPrefix != null); + Debug.Assert(authType != null); + + if (_cache == null) + { + return; + } + + var key = new CredentialCacheKey(uriPrefix, authType); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Removing key:[{key}]"); + _cache.Remove(key); + } + + public (Uri uriPrefix, NetworkCredential credential)? GetCredential(Uri uriPrefix, string authType) + { + Debug.Assert(uriPrefix != null); + Debug.Assert(authType != null); + + if (_cache == null) + { + return null; + } + + CredentialCacheHelper.TryGetCredential(_cache, uriPrefix, authType, out Uri? mostSpecificMatchUri, out NetworkCredential? mostSpecificMatch); + + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Returning {(mostSpecificMatch == null ? "null" : "(" + mostSpecificMatch.UserName + ":" + mostSpecificMatch.Domain + ")")}"); + + return mostSpecificMatch == null ? null : (mostSpecificMatchUri!, mostSpecificMatch!); + } + } +} diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.BasicAuth.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.BasicAuth.cs new file mode 100644 index 00000000000000..a6ac590fb6adcf --- /dev/null +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.BasicAuth.cs @@ -0,0 +1,114 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Linq; +using System.Net.Test.Common; +using System.Text; +using System.Threading.Tasks; + +using Microsoft.DotNet.XUnitExtensions; +using Xunit; +using Xunit.Abstractions; + +namespace System.Net.Http.Functional.Tests +{ + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public class HttpClientHandlerTest_BasicAuth : HttpClientHandlerTestBase + { + public HttpClientHandlerTest_BasicAuth(ITestOutputHelper output) : base(output) + { + } + + protected override Version UseVersion => HttpVersion.Version20; + + [Fact] + public async Task RefreshesPreAuthCredentialsOnChange() + { + CredentialPlugin credentialPlugin = new CredentialPlugin(); + + using Http2LoopbackServer server = Http2LoopbackServer.CreateServer(); + server.AllowMultipleConnections = true; + + HttpClientHandler handler = CreateHttpClientHandler(); + handler.PreAuthenticate = true; + handler.Credentials = credentialPlugin; + using HttpClient client = CreateHttpClient(handler); + + Task sendTask = client.GetAsync(server.Address); + + async Task GetAuth(GenericLoopbackConnection connection) + { + HttpRequestData data = await connection.ReadRequestDataAsync(); + HttpHeaderData? header = data.Headers.FirstOrDefault(h => string.Equals(h.Name, "Authorization", StringComparison.OrdinalIgnoreCase)); + + if (header == null) + { + return ""; + } + + return Encoding.UTF8.GetString(Convert.FromBase64String(header.Value.Value.Replace("Basic", "", StringComparison.OrdinalIgnoreCase))); + } + + await server.HandleRequestAsync(HttpStatusCode.Unauthorized, headers: new[] { new HttpHeaderData("WWW-Authenticate", "Basic realm=\"test\"") }); + await server.AcceptConnectionAsync(async conn => + { + Assert.Equal("username:password", await GetAuth(conn)); + await conn.SendResponseAsync(HttpStatusCode.OK); + }).WaitAsync(TimeSpan.FromSeconds(30)); + + HttpResponseMessage response = await sendTask; + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + // change password and try again + credentialPlugin.ChangePassword(); + sendTask = client.GetAsync(server.Address); + + // first one reuses the cached credentials -> 401 + await server.AcceptConnectionAsync(async conn => + { + Assert.Equal("username:password", await GetAuth(conn)); + await conn.SendResponseAsync(HttpStatusCode.Unauthorized, headers: new[] { new HttpHeaderData("WWW-Authenticate", "Basic realm=\"test\"") }); + }).WaitAsync(TimeSpan.FromSeconds(30)); + + // client should try again with correct credentials + await server.AcceptConnectionAsync(async conn => + { + Assert.Equal("username:password1", await GetAuth(conn)); + await conn.SendResponseAsync(HttpStatusCode.OK); + }).WaitAsync(TimeSpan.FromSeconds(30)); + + response = await sendTask; + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + } + + internal class CredentialPlugin : ICredentials + { + public CredentialPlugin() + { + UserName = "username"; + counter = 0; + Password = "password"; + } + + private int counter; + public string UserName { get; private set; } + public string Password { get; private set; } + + public void ChangePassword() + { + counter++; + Password = "password" + counter; + } + + NetworkCredential? ICredentials.GetCredential(Uri uri, string authType) + { + if (authType == "Basic") + { + return new NetworkCredential(UserName, Password); + } + + return null; + } + } +} diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj index fd09f7db0b2282..0256d1d53a4517 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj @@ -245,6 +245,7 @@ + diff --git a/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj b/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj index a659207964a3e8..e71aaa8222e300 100644 --- a/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj +++ b/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj @@ -82,6 +82,8 @@ Link="Common\System\Text\StringBuilderCache.cs" /> + diff --git a/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs b/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs index 8cb88371227919..8e46d4ab6c529d 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs @@ -13,7 +13,7 @@ namespace System.Net // name-password pairs and associates these with host/realm. public class CredentialCache : ICredentials, ICredentialsByHost, IEnumerable { - private Dictionary? _cache; + private Dictionary? _cache; private Dictionary? _cacheForHosts; private int _version; @@ -37,11 +37,11 @@ public void Add(Uri uriPrefix, string authType, NetworkCredential cred) ++_version; - var key = new CredentialKey(uriPrefix, authType); + var key = new CredentialCacheKey(uriPrefix, authType); if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Adding key:[{key}], cred:[{cred.Domain}],[{cred.UserName}]"); - _cache ??= new Dictionary(); + _cache ??= new Dictionary(); _cache.Add(key, cred); } @@ -88,7 +88,7 @@ public void Remove(Uri? uriPrefix, string? authType) ++_version; - var key = new CredentialKey(uriPrefix, authType); + var key = new CredentialCacheKey(uriPrefix, authType); if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Removing key:[{key}]"); @@ -135,28 +135,7 @@ public void Remove(string? host, int port, string? authenticationType) return null; } - int longestMatchPrefix = -1; - NetworkCredential? mostSpecificMatch = null; - - // Enumerate through every credential in the cache - foreach (KeyValuePair pair in _cache) - { - CredentialKey key = pair.Key; - - // Determine if this credential is applicable to the current Uri/AuthType - if (key.Match(uriPrefix, authType)) - { - int prefixLen = key.UriPrefixLength; - - // Check if the match is better than the current-most-specific match - if (prefixLen > longestMatchPrefix) - { - // Yes: update the information about currently preferred match - longestMatchPrefix = prefixLen; - mostSpecificMatch = pair.Value; - } - } - } + CredentialCacheHelper.TryGetCredential(_cache, uriPrefix, authType, out _ /*uri*/, out NetworkCredential? mostSpecificMatch); if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Returning {(mostSpecificMatch == null ? "null" : "(" + mostSpecificMatch.UserName + ":" + mostSpecificMatch.Domain + ")")}"); @@ -201,7 +180,7 @@ internal static CredentialEnumerator Create(CredentialCache cache) { return cache._cacheForHosts != null ? new DoubleTableCredentialEnumerator(cache) : - new SingleTableCredentialEnumerator(cache, cache._cache); + new SingleTableCredentialEnumerator(cache, cache._cache); } else { @@ -286,7 +265,7 @@ public override void Reset() } } - private sealed class DoubleTableCredentialEnumerator : SingleTableCredentialEnumerator + private sealed class DoubleTableCredentialEnumerator : SingleTableCredentialEnumerator { private Dictionary.ValueCollection.Enumerator _enumerator; // mutable struct field deliberately not readonly. private bool _onThisEnumerator; @@ -406,95 +385,4 @@ public override bool Equals([NotNullWhen(true)] object? obj) => public override string ToString() => string.Create(CultureInfo.InvariantCulture, $"{Host}:{Port}:{AuthenticationType}"); } - - internal sealed class CredentialKey : IEquatable - { - public readonly Uri UriPrefix; - public readonly int UriPrefixLength = -1; - public readonly string AuthenticationType; - - internal CredentialKey(Uri uriPrefix, string authenticationType) - { - Debug.Assert(uriPrefix != null); - Debug.Assert(authenticationType != null); - - UriPrefix = uriPrefix; - UriPrefixLength = UriPrefix.ToString().Length; - AuthenticationType = authenticationType; - } - - internal bool Match(Uri uri, string authenticationType) - { - if (uri == null || authenticationType == null) - { - return false; - } - - // If the protocols don't match, this credential is not applicable for the given Uri. - if (!string.Equals(authenticationType, AuthenticationType, StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Match({UriPrefix} & {uri})"); - - return IsPrefix(uri, UriPrefix); - } - - // IsPrefix (Uri) - // - // Determines whether is a prefix of this URI. A prefix - // match is defined as: - // - // scheme match - // + host match - // + port match, if any - // + path is a prefix of path, if any - // - // Returns: - // True if is a prefix of this URI - private static bool IsPrefix(Uri uri, Uri prefixUri) - { - Debug.Assert(uri != null); - Debug.Assert(prefixUri != null); - - if (prefixUri.Scheme != uri.Scheme || prefixUri.Host != uri.Host || prefixUri.Port != uri.Port) - { - return false; - } - - int prefixLen = prefixUri.AbsolutePath.LastIndexOf('/'); - if (prefixLen > uri.AbsolutePath.LastIndexOf('/')) - { - return false; - } - - return string.Compare(uri.AbsolutePath, 0, prefixUri.AbsolutePath, 0, prefixLen, StringComparison.OrdinalIgnoreCase) == 0; - } - - public override int GetHashCode() => - StringComparer.OrdinalIgnoreCase.GetHashCode(AuthenticationType) ^ - UriPrefix.GetHashCode(); - - public bool Equals([NotNullWhen(true)] CredentialKey? other) - { - if (other == null) - { - return false; - } - - bool equals = - string.Equals(AuthenticationType, other.AuthenticationType, StringComparison.OrdinalIgnoreCase) && - UriPrefix.Equals(other.UriPrefix); - - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Equals({this},{other}) returns {equals}"); - - return equals; - } - - public override bool Equals([NotNullWhen(true)] object? obj) => Equals(obj as CredentialKey); - - public override string ToString() => - string.Create(CultureInfo.InvariantCulture, $"[{UriPrefixLength}]:{UriPrefix}:{AuthenticationType}"); - } } diff --git a/src/libraries/System.Net.Primitives/tests/FunctionalTests/CredentialCacheTest.cs b/src/libraries/System.Net.Primitives/tests/FunctionalTests/CredentialCacheTest.cs index a67967b36811c7..6895fabba4f1b9 100644 --- a/src/libraries/System.Net.Primitives/tests/FunctionalTests/CredentialCacheTest.cs +++ b/src/libraries/System.Net.Primitives/tests/FunctionalTests/CredentialCacheTest.cs @@ -272,6 +272,17 @@ public static void GetCredential_SimilarUriAuthenticationType_GetLongestUriPrefi Assert.Equal(nc, credential2); } + [Fact] + public static void GetCredential_LongerUriButShorterMatch() + { + CredentialCache cc = new CredentialCache(); + cc.Add(new Uri("http://microsoft:80/common/unique/something"), authenticationType1, credential2); + cc.Add(new Uri("http://microsoft:80/common/veryloooooongprefix"), authenticationType1, credential1); + + NetworkCredential nc = cc.GetCredential(new Uri("http://microsoft:80/common/unique/a"), authenticationType1); + Assert.Equal(nc, credential2); + } + [Fact] public static void GetCredential_UriAuthenticationType_Invalid() { From 2ad47cd52ebe57c1b4c2e28f95cc4eed6fcb354d Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com> Date: Tue, 30 Apr 2024 12:57:18 +0200 Subject: [PATCH 187/248] [wasm] Switch off `HybridGlobalization` lane on v8 on CI (#101671) * Stop testing on v8. * Try to block by scenario, * Limit scenarios. This reverts commit 38f64f7a8619b427f1b5c617db5dead7d8f194ee. --- .../extra-platforms/runtime-extra-platforms-wasm.yml | 2 -- ...ystem.Globalization.Calendars.Hybrid.WASM.Tests.csproj | 8 ++++++++ .../Hybrid/System.Globalization.Hybrid.WASM.Tests.csproj | 8 ++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml index d31cad685995d2..a5c6cb414227d8 100644 --- a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml +++ b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml @@ -197,7 +197,6 @@ jobs: isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }} alwaysRun: true scenarios: - - WasmTestOnV8 - WasmTestOnChrome - WasmTestOnFirefox - WasmTestOnNodeJS @@ -215,7 +214,6 @@ jobs: isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }} alwaysRun: true scenarios: - - WasmTestOnV8 - WasmTestOnChrome - WasmTestOnNodeJS diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Calendars.Tests/Hybrid/System.Globalization.Calendars.Hybrid.WASM.Tests.csproj b/src/libraries/System.Runtime/tests/System.Globalization.Calendars.Tests/Hybrid/System.Globalization.Calendars.Hybrid.WASM.Tests.csproj index 5b898363764087..7e10ef4ac1dd59 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Calendars.Tests/Hybrid/System.Globalization.Calendars.Hybrid.WASM.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Globalization.Calendars.Tests/Hybrid/System.Globalization.Calendars.Hybrid.WASM.Tests.csproj @@ -4,6 +4,14 @@ true true true + + + + WasmTestOnChrome + $(TestArchiveRoot)browserornodejs/ + $(TestArchiveTestsRoot)$(OSPlatformConfig)/ + $(DefineConstants);TARGET_BROWSER + true diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/Hybrid/System.Globalization.Hybrid.WASM.Tests.csproj b/src/libraries/System.Runtime/tests/System.Globalization.Tests/Hybrid/System.Globalization.Hybrid.WASM.Tests.csproj index a39604c1cfaccd..fdc037e655558d 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/Hybrid/System.Globalization.Hybrid.WASM.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/Hybrid/System.Globalization.Hybrid.WASM.Tests.csproj @@ -6,6 +6,14 @@ true true + + + WasmTestOnChrome + $(TestArchiveRoot)browserornodejs/ + $(TestArchiveTestsRoot)$(OSPlatformConfig)/ + $(DefineConstants);TARGET_BROWSER + true + From 80aa46441244c7a05f7b2bbbbb0d4812f76b488a Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 30 Apr 2024 06:26:56 -0700 Subject: [PATCH 188/248] Backport assorted changes from runtimelab (#101655) * Backport assorted changes from runtimelab - Official build template - FEATURE_HIJACK define - Misc other cleanup * Delete unused DATA_ALIGNMENT definition --- eng/native/configureplatform.cmake | 1 - eng/pipelines/common/xplat-setup.yml | 1 - eng/pipelines/runtimelab-official.yml | 78 +++++++++ eng/pipelines/runtimelab.yml | 149 ++++++------------ src/coreclr/nativeaot/Runtime/CMakeLists.txt | 14 +- src/coreclr/nativeaot/Runtime/CommonMacros.h | 27 ---- .../nativeaot/Runtime/GCMemoryHelpers.inl | 2 + src/coreclr/nativeaot/Runtime/PalRedhawk.h | 2 + src/coreclr/nativeaot/Runtime/portable.cpp | 22 --- src/coreclr/nativeaot/Runtime/thread.cpp | 30 ++-- src/coreclr/nativeaot/Runtime/thread.h | 20 ++- src/coreclr/nativeaot/Runtime/threadstore.cpp | 4 + .../nativeaot/Runtime/unix/PalRedhawkUnix.cpp | 7 +- 13 files changed, 178 insertions(+), 179 deletions(-) create mode 100644 eng/pipelines/runtimelab-official.yml diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake index c7c378ab0e41b3..20851f8617423d 100644 --- a/eng/native/configureplatform.cmake +++ b/eng/native/configureplatform.cmake @@ -429,7 +429,6 @@ endif(CLR_CMAKE_TARGET_OS STREQUAL haiku) if(CLR_CMAKE_TARGET_OS STREQUAL emscripten) set(CLR_CMAKE_TARGET_UNIX 1) - set(CLR_CMAKE_TARGET_LINUX 1) set(CLR_CMAKE_TARGET_BROWSER 1) endif(CLR_CMAKE_TARGET_OS STREQUAL emscripten) diff --git a/eng/pipelines/common/xplat-setup.yml b/eng/pipelines/common/xplat-setup.yml index 743f6a42531bcc..f50a2db9e81ec5 100644 --- a/eng/pipelines/common/xplat-setup.yml +++ b/eng/pipelines/common/xplat-setup.yml @@ -188,7 +188,6 @@ jobs: name: $(DncEngPublicBuildPool) demands: ImageOverride -equals windows.vs2022.amd64.open - ${{ if eq(parameters.helixQueuesTemplate, '') }}: # macOS hosted pool machines are slower so we need to give a greater timeout than the 60 mins default. ${{ if and(eq(parameters.jobParameters.timeoutInMinutes, ''), in(parameters.osGroup, 'osx', 'maccatalyst', 'ios', 'tvos')) }}: diff --git a/eng/pipelines/runtimelab-official.yml b/eng/pipelines/runtimelab-official.yml new file mode 100644 index 00000000000000..84a8bd69258d5c --- /dev/null +++ b/eng/pipelines/runtimelab-official.yml @@ -0,0 +1,78 @@ +trigger: + batch: true + branches: + include: + - feature/* + paths: + include: + - '*' + exclude: + - '**.md' + - eng/Version.Details.xml + - .devcontainer/* + - .github/* + - docs/* + - LICENSE.TXT + - PATENTS.TXT + - THIRD-PARTY-NOTICES.TXT + +variables: +- template: /eng/pipelines/common/variables.yml + parameters: + templatePath: 'templates-official' + +- ${{ if and(ne(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: + - name: TeamName + value: dotnet-core +extends: + template: /eng/pipelines/common/templates/pipeline-with-resources.yml@self + parameters: + isOfficialBuild: true + stages: + - stage: Build + jobs: + # + # Build the whole product with Release CoreCLR + # + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + buildConfig: release + platforms: + - linux_x64 + - windows_x64 + jobParameters: + templatePath: 'templates-official' + isOfficialBuild: true + timeoutInMinutes: 180 + buildArgs: -s clr+libs+hosts+packs -c $(_BuildConfig) + postBuildSteps: + # Upload the results. + - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml + parameters: + name: $(osGroup)$(osSubgroup)_$(archType) + + # + # Build libraries AllConfigurations for packages + # + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + buildConfig: Release + platforms: + - windows_x64 + jobParameters: + templatePath: 'templates-official' + buildArgs: -s tools+libs -allConfigurations -c $(_BuildConfig) /p:TestAssemblies=false /p:TestPackages=true + nameSuffix: Libraries_AllConfigurations + isOfficialBuild: true + postBuildSteps: + - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml + parameters: + name: Libraries_AllConfigurations + timeoutInMinutes: 95 + + - template: /eng/pipelines/official/stages/publish.yml + parameters: + isOfficialBuild: true diff --git a/eng/pipelines/runtimelab.yml b/eng/pipelines/runtimelab.yml index 0fe01fd2816f73..7e0aaeab207216 100644 --- a/eng/pipelines/runtimelab.yml +++ b/eng/pipelines/runtimelab.yml @@ -49,103 +49,56 @@ extends: stages: - stage: Build jobs: - - ${{ if ne(variables.isOfficialBuild, true) }}: - # - # Build the whole product with Checked CoreCLR and run runtime tests - # - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml - buildConfig: checked - platforms: - - linux_x64 - - windows_x64 - jobParameters: - timeoutInMinutes: 200 - buildArgs: -s clr+libs+hosts+packs -c debug -rc $(_BuildConfig) - postBuildSteps: - - template: /eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml - parameters: - creator: dotnet-bot - testRunNamePrefixSuffix: CoreCLR_$(_BuildConfig) + # + # Build the whole product with Checked CoreCLR and run runtime tests + # + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml + buildConfig: checked + platforms: + - linux_x64 + - windows_x64 + jobParameters: + timeoutInMinutes: 200 + buildArgs: -s clr+libs+hosts+packs -c debug -rc $(_BuildConfig) + postBuildSteps: + - template: /eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml + parameters: + creator: dotnet-bot + testRunNamePrefixSuffix: CoreCLR_$(_BuildConfig) - # - # Build the whole product with Release CoreCLR and run libraries tests - # - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml - buildConfig: release - platforms: - - linux_x64 - - windows_x64 - jobParameters: - timeoutInMinutes: 180 - buildArgs: -s clr+libs+libs.tests+hosts+packs -c $(_BuildConfig) /p:ArchiveTests=true - postBuildSteps: - - template: /eng/pipelines/libraries/helix.yml - parameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Libraries_$(_BuildConfig) + # + # Build the whole product with Release CoreCLR and run libraries tests + # + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + buildConfig: release + platforms: + - linux_x64 + - windows_x64 + jobParameters: + timeoutInMinutes: 180 + buildArgs: -s clr+libs+libs.tests+hosts+packs -c $(_BuildConfig) /p:ArchiveTests=true + postBuildSteps: + - template: /eng/pipelines/libraries/helix.yml + parameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Libraries_$(_BuildConfig) - # - # Build and test libraries AllConfigurations - # - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: ${{ variables.debugOnPrReleaseOnRolling }} - platforms: - - windows_x64 - jobParameters: - buildArgs: -test -s tools+libs+libs.tests -allConfigurations -c $(_BuildConfig) /p:TestAssemblies=false /p:TestPackages=true - nameSuffix: Libraries_AllConfigurations - timeoutInMinutes: 150 - - - ${{ else }}: - # - # Build the whole product with Release CoreCLR - # - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml - buildConfig: release - platforms: - - linux_x64 - - windows_x64 - jobParameters: - isOfficialBuild: true - timeoutInMinutes: 180 - buildArgs: -s clr+libs+hosts+packs -c $(_BuildConfig) - postBuildSteps: - # Upload the results. - - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml - parameters: - name: $(osGroup)$(osSubgroup)_$(archType) - - # - # Build libraries AllConfigurations for packages - # - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: Release - platforms: - - windows_x64 - jobParameters: - buildArgs: -s tools+libs -allConfigurations -c $(_BuildConfig) /p:TestAssemblies=false /p:TestPackages=true - nameSuffix: Libraries_AllConfigurations - isOfficialBuild: true - postBuildSteps: - - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml - parameters: - name: Libraries_AllConfigurations - timeoutInMinutes: 95 - - - ${{ if eq(variables.isOfficialBuild, true) }}: - - template: /eng/pipelines/official/stages/publish.yml - parameters: - isOfficialBuild: true \ No newline at end of file + # + # Build and test libraries AllConfigurations + # + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + buildConfig: ${{ variables.debugOnPrReleaseOnRolling }} + platforms: + - windows_x64 + jobParameters: + buildArgs: -test -s tools+libs+libs.tests -allConfigurations -c $(_BuildConfig) /p:TestAssemblies=false /p:TestPackages=true + nameSuffix: Libraries_AllConfigurations + timeoutInMinutes: 150 diff --git a/src/coreclr/nativeaot/Runtime/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/CMakeLists.txt index f070214054f7f9..4a10690b15af4f 100644 --- a/src/coreclr/nativeaot/Runtime/CMakeLists.txt +++ b/src/coreclr/nativeaot/Runtime/CMakeLists.txt @@ -231,15 +231,19 @@ if(FEATURE_EVENT_TRACE) add_definitions(-DFEATURE_EVENT_TRACE) endif() +if (NOT CLR_CMAKE_TARGET_ARCH_WASM) + add_definitions(-DFEATURE_HIJACK) +endif() + add_definitions(-DFEATURE_BASICFREEZE) add_definitions(-DFEATURE_CONSERVATIVE_GC) if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64) add_definitions(-DFEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP) add_definitions(-DFEATURE_MANUALLY_MANAGED_CARD_BUNDLES) -endif(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64) -if(CLR_CMAKE_TARGET_ARCH_ARM) +endif() +if(CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_WASM) add_definitions(-DFEATURE_64BIT_ALIGNMENT) -endif(CLR_CMAKE_TARGET_ARCH_ARM) +endif() add_definitions(-DFEATURE_CUSTOM_IMPORTS) add_definitions(-DFEATURE_DYNAMIC_CODE) @@ -250,7 +254,7 @@ add_definitions(-DNATIVEAOT) add_definitions(-DFEATURE_CACHED_INTERFACE_DISPATCH) if(CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM) add_definitions(-DINTERFACE_DISPATCH_CACHE_HAS_CELL_BACKPOINTER) -endif(CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM) +endif() add_definitions(-D_LIB) # there is a problem with undefined symbols when this is set @@ -267,7 +271,7 @@ if(CLR_CMAKE_TARGET_WIN32) add_compile_options($<$:/safeseh>) endif() else() - if(NOT CLR_CMAKE_TARGET_APPLE) + if(NOT CLR_CMAKE_TARGET_APPLE AND NOT CLR_CMAKE_TARGET_ARCH_WASM) add_definitions(-DFEATURE_READONLY_GS_COOKIE) endif() include(unix/configure.cmake) diff --git a/src/coreclr/nativeaot/Runtime/CommonMacros.h b/src/coreclr/nativeaot/Runtime/CommonMacros.h index a2b4183fb1ecd5..4b74de2360e616 100644 --- a/src/coreclr/nativeaot/Runtime/CommonMacros.h +++ b/src/coreclr/nativeaot/Runtime/CommonMacros.h @@ -125,35 +125,8 @@ inline bool IS_ALIGNED(T* val, uintptr_t alignment); #ifndef __GCENV_BASE_INCLUDED__ -#if defined(HOST_WASM) -#define OS_PAGE_SIZE 0x4 -#else #define OS_PAGE_SIZE PalOsPageSize() -#endif - -#if defined(HOST_AMD64) - -#define DATA_ALIGNMENT 8 - -#elif defined(HOST_X86) - -#define DATA_ALIGNMENT 4 - -#elif defined(HOST_ARM) -#define DATA_ALIGNMENT 4 - -#elif defined(HOST_ARM64) - -#define DATA_ALIGNMENT 8 - -#elif defined(HOST_WASM) - -#define DATA_ALIGNMENT 4 - -#else -#error Unsupported target architecture -#endif #endif // __GCENV_BASE_INCLUDED__ #if defined(TARGET_ARM) diff --git a/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.inl b/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.inl index bb4c64aed3cf48..cb4adbfc6a275f 100644 --- a/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.inl +++ b/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.inl @@ -172,6 +172,8 @@ static const uint32_t INVALIDGCVALUE = 0xcccccccd; FORCEINLINE void InlineWriteBarrier(void * dst, void * ref) { + ASSERT(((uint8_t*)dst >= g_lowest_address) && ((uint8_t*)dst < g_highest_address)) + if (((uint8_t*)ref >= g_ephemeral_low) && ((uint8_t*)ref < g_ephemeral_high)) { // volatile is used here to prevent fetch of g_card_table from being reordered diff --git a/src/coreclr/nativeaot/Runtime/PalRedhawk.h b/src/coreclr/nativeaot/Runtime/PalRedhawk.h index e44c87a6046e09..9257324bd1589b 100644 --- a/src/coreclr/nativeaot/Runtime/PalRedhawk.h +++ b/src/coreclr/nativeaot/Runtime/PalRedhawk.h @@ -688,9 +688,11 @@ REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalStartBackgroundGCThread(_In_ Background REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalStartFinalizerThread(_In_ BackgroundCallback callback, _In_opt_ void* pCallbackContext); REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalStartEventPipeHelperThread(_In_ BackgroundCallback callback, _In_opt_ void* pCallbackContext); +#ifdef FEATURE_HIJACK typedef void (*PalHijackCallback)(_In_ NATIVE_CONTEXT* pThreadContext, _In_opt_ void* pThreadToHijack); REDHAWK_PALIMPORT void REDHAWK_PALAPI PalHijack(HANDLE hThread, _In_opt_ void* pThreadToHijack); REDHAWK_PALIMPORT UInt32_BOOL REDHAWK_PALAPI PalRegisterHijackCallback(_In_ PalHijackCallback callback); +#endif 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, size_t templateSize); diff --git a/src/coreclr/nativeaot/Runtime/portable.cpp b/src/coreclr/nativeaot/Runtime/portable.cpp index bcd99d051198d8..318a10fd20a526 100644 --- a/src/coreclr/nativeaot/Runtime/portable.cpp +++ b/src/coreclr/nativeaot/Runtime/portable.cpp @@ -332,28 +332,6 @@ void * ReturnFromUniversalTransition; EXTERN_C void * ReturnFromUniversalTransition_DebugStepTailCall; void * ReturnFromUniversalTransition_DebugStepTailCall; -#endif // USE_PORTABLE_HELPERS - -#if defined(USE_PORTABLE_HELPERS) -// -// Return address hijacking -// -FCIMPL0(void, RhpGcStressHijack) -{ - ASSERT_UNCONDITIONALLY("NYI"); -} -FCIMPLEND - -FCIMPL0(void, RhpGcProbeHijack) -{ - ASSERT_UNCONDITIONALLY("NYI"); -} -FCIMPLEND - -#endif // defined(USE_PORTABLE_HELPERS) || defined(TARGET_UNIX) - -#if defined(USE_PORTABLE_HELPERS) - #if !defined (HOST_ARM64) FCIMPL2(void, RhpAssignRef, Object ** dst, Object * ref) { diff --git a/src/coreclr/nativeaot/Runtime/thread.cpp b/src/coreclr/nativeaot/Runtime/thread.cpp index 41fa9e53949459..1ae78d37d56fc4 100644 --- a/src/coreclr/nativeaot/Runtime/thread.cpp +++ b/src/coreclr/nativeaot/Runtime/thread.cpp @@ -578,7 +578,8 @@ void Thread::GcScanRootsWorker(ScanFunc * pfnEnumCallback, ScanContext * pvCallb #ifndef DACCESS_COMPILE -EXTERN_C void FASTCALL RhpSuspendRedirected(); +#ifdef FEATURE_HIJACK + EXTERN_C void FASTCALL RhpGcProbeHijack(); EXTERN_C void FASTCALL RhpGcStressHijack(); @@ -815,6 +816,7 @@ void Thread::HijackReturnAddressWorker(StackFrameIterator* frameIterator, Hijack GetPalThreadIdForLogging(), frameIterator->GetRegisterSet()->GetIP()); } } +#endif // FEATURE_HIJACK NATIVE_CONTEXT* Thread::GetInterruptedContext() { @@ -834,6 +836,16 @@ NATIVE_CONTEXT* Thread::EnsureRedirectionContext() return m_interruptedContext; } +EXTERN_C NOINLINE void FASTCALL RhpSuspendRedirected() +{ + Thread* pThread = ThreadStore::GetCurrentThread(); + pThread->WaitForGC(INTERRUPTED_THREAD_MARKER); + + // restore execution at interrupted location + PalRestoreContext(pThread->GetInterruptedContext()); + UNREACHABLE(); +} + bool Thread::Redirect() { ASSERT(!IsDoNotTriggerGcSet()); @@ -861,6 +873,7 @@ bool Thread::Redirect() } #endif //FEATURE_SUSPEND_REDIRECTION +#ifdef FEATURE_HIJACK bool Thread::InlineSuspend(NATIVE_CONTEXT* interruptedContext) { ASSERT(!IsDoNotTriggerGcSet()); @@ -948,6 +961,7 @@ void* Thread::GetHijackedReturnAddress() ASSERT(ThreadStore::GetCurrentThread() == this); return m_pvHijackedReturnAddress; } +#endif // FEATURE_HIJACK void Thread::SetState(ThreadStateFlags flags) { @@ -1021,20 +1035,6 @@ EXTERN_C NOINLINE void FASTCALL RhpGcPoll2(PInvokeTransitionFrame* pFrame) RhpWaitForGC2(pFrame); } -#ifdef FEATURE_SUSPEND_REDIRECTION - -EXTERN_C NOINLINE void FASTCALL RhpSuspendRedirected() -{ - Thread* pThread = ThreadStore::GetCurrentThread(); - pThread->WaitForGC(INTERRUPTED_THREAD_MARKER); - - // restore execution at interrupted location - PalRestoreContext(pThread->GetInterruptedContext()); - UNREACHABLE(); -} - -#endif //FEATURE_SUSPEND_REDIRECTION - void Thread::PushExInfo(ExInfo * pExInfo) { ValidateExInfoStack(); diff --git a/src/coreclr/nativeaot/Runtime/thread.h b/src/coreclr/nativeaot/Runtime/thread.h index 161fea12281688..3c8073faa2ac70 100644 --- a/src/coreclr/nativeaot/Runtime/thread.h +++ b/src/coreclr/nativeaot/Runtime/thread.h @@ -92,9 +92,11 @@ struct ThreadBuffer PInvokeTransitionFrame* m_pCachedTransitionFrame; PTR_Thread m_pNext; // used by ThreadStore's SList HANDLE m_hPalThread; // WARNING: this may legitimately be INVALID_HANDLE_VALUE +#ifdef FEATURE_HIJACK void ** m_ppvHijackedReturnAddressLocation; void * m_pvHijackedReturnAddress; uintptr_t m_uHijackedReturnValueFlags; +#endif // FEATURE_HIJACK PTR_ExInfo m_pExInfoStackHead; Object* m_threadAbortException; // ThreadAbortException instance -set only during thread abort #ifdef TARGET_X86 @@ -168,7 +170,7 @@ class Thread : private ThreadBuffer void ClearState(ThreadStateFlags flags); bool IsStateSet(ThreadStateFlags flags); - +#ifdef FEATURE_HIJACK static void HijackCallback(NATIVE_CONTEXT* pThreadContext, void* pThreadToHijack); // @@ -181,6 +183,11 @@ class Thread : private ThreadBuffer void HijackReturnAddress(NATIVE_CONTEXT* pSuspendCtx, HijackFunc* pfnHijackFunction); void HijackReturnAddressWorker(StackFrameIterator* frameIterator, HijackFunc* pfnHijackFunction); bool InlineSuspend(NATIVE_CONTEXT* interruptedContext); + void CrossThreadUnhijack(); + void UnhijackWorker(); +#else // FEATURE_HIJACK + void CrossThreadUnhijack() { } +#endif // FEATURE_HIJACK #ifdef FEATURE_SUSPEND_REDIRECTION bool Redirect(); @@ -188,8 +195,6 @@ class Thread : private ThreadBuffer bool CacheTransitionFrameForSuspend(); void ResetCachedTransitionFrame(); - void CrossThreadUnhijack(); - void UnhijackWorker(); void EnsureRuntimeInitialized(); // @@ -222,10 +227,17 @@ class Thread : private ThreadBuffer void GcScanRoots(ScanFunc* pfnEnumCallback, ScanContext * pvCallbackData); +#ifdef FEATURE_HIJACK void Hijack(); void Unhijack(); bool IsHijacked(); void* GetHijackedReturnAddress(); + static bool IsHijackTarget(void * address); +#else // FEATURE_HIJACK + void Unhijack() { } + bool IsHijacked() { return false; } + static bool IsHijackTarget(void * address) { return false; } +#endif // FEATURE_HIJACK #ifdef FEATURE_GC_STRESS static void HijackForGcStress(PAL_LIMITED_CONTEXT * pSuspendCtx); @@ -262,8 +274,6 @@ class Thread : private ThreadBuffer PInvokeTransitionFrame* GetTransitionFrameForStackTrace(); void * GetCurrentThreadPInvokeReturnAddress(); - static bool IsHijackTarget(void * address); - // // The set of operations used to support unmanaged code running in cooperative mode // diff --git a/src/coreclr/nativeaot/Runtime/threadstore.cpp b/src/coreclr/nativeaot/Runtime/threadstore.cpp index d94ef850a1c9bb..63bb947e2baa9b 100644 --- a/src/coreclr/nativeaot/Runtime/threadstore.cpp +++ b/src/coreclr/nativeaot/Runtime/threadstore.cpp @@ -85,8 +85,10 @@ ThreadStore * ThreadStore::Create(RuntimeInstance * pRuntimeInstance) if (NULL == pNewThreadStore) return NULL; +#ifdef FEATURE_HIJACK if (!PalRegisterHijackCallback(Thread::HijackCallback)) return NULL; +#endif pNewThreadStore->m_pRuntimeInstance = pRuntimeInstance; @@ -281,10 +283,12 @@ void ThreadStore::SuspendAllThreads(bool waitForGCEvent) if (!pTargetThread->CacheTransitionFrameForSuspend()) { remaining++; +#ifdef FEATURE_HIJACK if (!observeOnly) { pTargetThread->Hijack(); } +#endif // FEATURE_HIJACK } } END_FOREACH_THREAD diff --git a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp index 5cac500ca85a87..79a9476e3b7641 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp @@ -705,12 +705,7 @@ REDHAWK_PALEXPORT bool REDHAWK_PALAPI PalStartBackgroundGCThread(_In_ Background REDHAWK_PALEXPORT bool REDHAWK_PALAPI PalStartFinalizerThread(_In_ BackgroundCallback callback, _In_opt_ void* pCallbackContext) { -#ifdef HOST_WASM - // WASMTODO: No threads so we can't start the finalizer thread - return true; -#else // HOST_WASM return PalStartBackgroundWork(callback, pCallbackContext, UInt32_TRUE); -#endif // HOST_WASM } REDHAWK_PALEXPORT bool REDHAWK_PALAPI PalStartEventPipeHelperThread(_In_ BackgroundCallback callback, _In_opt_ void* pCallbackContext) @@ -989,6 +984,7 @@ extern "C" uint16_t RtlCaptureStackBackTrace(uint32_t arg1, uint32_t arg2, void* return 0; } +#ifdef FEATURE_HIJACK static PalHijackCallback g_pHijackCallback; static struct sigaction g_previousActivationHandler; @@ -1076,6 +1072,7 @@ REDHAWK_PALEXPORT void REDHAWK_PALAPI PalHijack(HANDLE hThread, _In_opt_ void* p abort(); } } +#endif // FEATURE_HIJACK extern "C" uint32_t WaitForSingleObjectEx(HANDLE handle, uint32_t milliseconds, UInt32_BOOL alertable) { From bb61fb53fe77c6871c3dd3660254d7f55a743ffe Mon Sep 17 00:00:00 2001 From: Omair Majid Date: Tue, 30 Apr 2024 09:36:05 -0400 Subject: [PATCH 189/248] With system brotli, do not use versioned symbols (#101576) The system version of libbrotli has symbols without the `V1.0` version. Support linking against that by removing the steps to use the versioned exports file. Without this fix, the build only works with bfd linker (I am not sure how). When lld is used, the build errors out: ld.lld : error : version script assignment of 'V1.0' to symbol 'BrotliDecoderCreateInstance' failed: symbol not defined [runtime/src/native/libs/build-native.proj] ld.lld : error : version script assignment of 'V1.0' to symbol 'BrotliDecoderDecompress' failed: symbol not defined [runtime/src/native/libs/build-native.proj] ld.lld : error : version script assignment of 'V1.0' to symbol 'BrotliDecoderDecompressStream' failed: symbol not defined [runtime/src/native/libs/build-native.proj] ld.lld : error : version script assignment of 'V1.0' to symbol 'BrotliDecoderDestroyInstance' failed: symbol not defined [runtime/src/native/libs/build-native.proj] ld.lld : error : version script assignment of 'V1.0' to symbol 'BrotliDecoderIsFinished' failed: symbol not defined [runtime/src/native/libs/build-native.proj] ld.lld : error : version script assignment of 'V1.0' to symbol 'BrotliEncoderCompress' failed: symbol not defined [runtime/src/native/libs/build-native.proj] ld.lld : error : version script assignment of 'V1.0' to symbol 'BrotliEncoderCompressStream' failed: symbol not defined [runtime/src/native/libs/build-native.proj] ld.lld : error : version script assignment of 'V1.0' to symbol 'BrotliEncoderCreateInstance' failed: symbol not defined [runtime/src/native/libs/build-native.proj] ld.lld : error : version script assignment of 'V1.0' to symbol 'BrotliEncoderDestroyInstance' failed: symbol not defined [runtime/src/native/libs/build-native.proj] ld.lld : error : version script assignment of 'V1.0' to symbol 'BrotliEncoderHasMoreOutput' failed: symbol not defined [runtime/src/native/libs/build-native.proj] ld.lld : error : version script assignment of 'V1.0' to symbol 'BrotliEncoderSetParameter' failed: symbol not defined [runtime/src/native/libs/build-native.proj] clang-18 : error : linker command failed with exit code 1 (use -v to see invocation) [runtime/src/native/libs/build-native.proj] --- .../CMakeLists.txt | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/native/libs/System.IO.Compression.Native/CMakeLists.txt b/src/native/libs/System.IO.Compression.Native/CMakeLists.txt index 0a05e96eb494ba..089363cf5554ec 100644 --- a/src/native/libs/System.IO.Compression.Native/CMakeLists.txt +++ b/src/native/libs/System.IO.Compression.Native/CMakeLists.txt @@ -66,7 +66,7 @@ if (CLR_CMAKE_TARGET_UNIX OR CLR_CMAKE_TARGET_BROWSER OR CLR_CMAKE_TARGET_WASI) ${NATIVE_LIBS_EXTRA} ) - if (NOT CLR_CMAKE_TARGET_MACCATALYST AND NOT CLR_CMAKE_TARGET_IOS AND NOT CLR_CMAKE_TARGET_TVOS AND NOT CLR_CMAKE_TARGET_ANDROID) + if (NOT CLR_CMAKE_TARGET_MACCATALYST AND NOT CLR_CMAKE_TARGET_IOS AND NOT CLR_CMAKE_TARGET_TVOS AND NOT CLR_CMAKE_TARGET_ANDROID AND NOT CLR_CMAKE_USE_SYSTEM_BROTLI) set(DEF_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/System.IO.Compression.Native_unixexports.src) set(EXPORTS_FILE ${CMAKE_CURRENT_BINARY_DIR}/System.IO.Compression.Native.exports) generate_exports_file(${DEF_SOURCES} ${EXPORTS_FILE}) @@ -78,16 +78,14 @@ if (CLR_CMAKE_TARGET_UNIX OR CLR_CMAKE_TARGET_BROWSER OR CLR_CMAKE_TARGET_WASI) set_property(TARGET System.IO.Compression.Native APPEND_STRING PROPERTY LINK_FLAGS ${EXPORTS_LINKER_OPTION}) set_property(TARGET System.IO.Compression.Native APPEND_STRING PROPERTY LINK_DEPENDS ${EXPORTS_FILE}) - if (NOT CLR_CMAKE_USE_SYSTEM_BROTLI) - add_custom_command(TARGET System.IO.Compression.Native POST_BUILD - COMMENT "Verifying System.IO.Compression.Native entry points against entrypoints.c " - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../verify-entrypoints.sh - $ - ${CMAKE_CURRENT_SOURCE_DIR}/entrypoints.c - ${CMAKE_NM} - VERBATIM - ) - endif () + add_custom_command(TARGET System.IO.Compression.Native POST_BUILD + COMMENT "Verifying System.IO.Compression.Native entry points against entrypoints.c " + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../verify-entrypoints.sh + $ + ${CMAKE_CURRENT_SOURCE_DIR}/entrypoints.c + ${CMAKE_NM} + VERBATIM + ) endif () install_with_stripped_symbols (System.IO.Compression.Native PROGRAMS .) From 82830499e172ff553be11f4e85386c6bf077a397 Mon Sep 17 00:00:00 2001 From: Sanjam Panda <36253777+saitama951@users.noreply.github.com> Date: Tue, 30 Apr 2024 19:20:24 +0530 Subject: [PATCH 190/248] fix stack local offset size for passing argument (#101103) --- src/mono/mono/mini/mini-s390x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/mono/mini/mini-s390x.c b/src/mono/mono/mini/mini-s390x.c index c87ec5573bc5e4..c084bdfb1be76e 100644 --- a/src/mono/mono/mini/mini-s390x.c +++ b/src/mono/mono/mini/mini-s390x.c @@ -1580,7 +1580,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) inst->inst_offset = offset + (8 - size); } } - offset += MAX(size, 8); + offset += 8; } curinst++; } From 9fa12355097e1ac17ac44445649a381323e9c35f Mon Sep 17 00:00:00 2001 From: Qiao Pengcheng Date: Tue, 30 Apr 2024 23:26:13 +0800 Subject: [PATCH 191/248] [LoongArch64] clear float type when passed by integer reg. (#101713) --- src/coreclr/jit/targetloongarch64.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/jit/targetloongarch64.cpp b/src/coreclr/jit/targetloongarch64.cpp index 6d63951c8ea205..9292f0e0e67a8f 100644 --- a/src/coreclr/jit/targetloongarch64.cpp +++ b/src/coreclr/jit/targetloongarch64.cpp @@ -161,6 +161,7 @@ ABIPassingInformation LoongArch64Classifier::Classify(Compiler* comp, canPassArgInRegisters = m_floatRegs.Count() > 0; if (!canPassArgInRegisters) { + type = TYP_I_IMPL; m_floatRegs.Clear(); canPassArgInRegisters = m_intRegs.Count() > 0; } From 017593d90781d797df8b2241f6d1f83c236c442b Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Tue, 30 Apr 2024 18:29:30 +0200 Subject: [PATCH 192/248] JIT: Avoid relying on bbNum to find lexical loop boundaries (#101714) Switch `FlowGraphNaturalLoop::GetLexicallyTopMostBlock` and `FlowGraphNaturalLoop::GetLexicallyBottomMostBlock` to more robust implementations that scan the basic block list forwards (and backwards) to find the boundary blocks. Fix #101695 --- src/coreclr/jit/flowgraph.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 8b73d10aa8dc1d..2a185d9e47b1d1 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -5555,7 +5555,7 @@ bool FlowGraphNaturalLoop::InitBlockEntersLoopOnTrue(BasicBlock* initBlock) // the loop. // // Returns: -// Block with highest bbNum. +// First block in block order contained in the loop. // // Remarks: // Mostly exists as a quirk while transitioning from the old loop @@ -5563,12 +5563,13 @@ bool FlowGraphNaturalLoop::InitBlockEntersLoopOnTrue(BasicBlock* initBlock) // BasicBlock* FlowGraphNaturalLoop::GetLexicallyTopMostBlock() { - BasicBlock* top = m_header; - VisitLoopBlocks([&top](BasicBlock* loopBlock) { - if (loopBlock->bbNum < top->bbNum) - top = loopBlock; - return BasicBlockVisit::Continue; - }); + BasicBlock* top = m_dfsTree->GetCompiler()->fgFirstBB; + + while (!ContainsBlock(top)) + { + top = top->Next(); + assert(top != nullptr); + } return top; } @@ -5578,7 +5579,7 @@ BasicBlock* FlowGraphNaturalLoop::GetLexicallyTopMostBlock() // within the loop. // // Returns: -// Block with highest bbNum. +// Last block in block order contained in the loop. // // Remarks: // Mostly exists as a quirk while transitioning from the old loop @@ -5586,12 +5587,13 @@ BasicBlock* FlowGraphNaturalLoop::GetLexicallyTopMostBlock() // BasicBlock* FlowGraphNaturalLoop::GetLexicallyBottomMostBlock() { - BasicBlock* bottom = m_header; - VisitLoopBlocks([&bottom](BasicBlock* loopBlock) { - if (loopBlock->bbNum > bottom->bbNum) - bottom = loopBlock; - return BasicBlockVisit::Continue; - }); + BasicBlock* bottom = m_dfsTree->GetCompiler()->fgLastBB; + + while (!ContainsBlock(bottom)) + { + bottom = bottom->Prev(); + assert(bottom != nullptr); + } return bottom; } From 30b3721b36ecaac4abb43c847940313d26f2edf7 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Tue, 30 Apr 2024 15:38:49 -0700 Subject: [PATCH 193/248] Preserve static type info for return value of ctor (#101212) Instead of tracking the return value as "TopValue" or "unknown", this models the constructor as returning a value with a static type when called with newobj, letting us undo the workaround from https://github.com/dotnet/runtime/pull/101031. --- .../Common/Compiler/Dataflow/MethodProxy.cs | 2 + .../Compiler/Dataflow/FlowAnnotations.cs | 8 ++-- .../Compiler/Dataflow/HandleCallAction.cs | 11 ++--- .../Compiler/Dataflow/MethodReturnValue.cs | 6 ++- .../Dataflow/ReflectionMethodBodyScanner.cs | 5 ++- .../TrimAnalysis/FlowAnnotations.cs | 8 ++-- .../TrimAnalysis/HandleCallAction.cs | 5 ++- .../TrimAnalysis/MethodProxy.cs | 2 + .../TrimAnalysis/MethodReturnValue.cs | 10 +++-- .../TrimAnalysis/TrimAnalysisVisitor.cs | 4 +- .../TrimAnalysis/FlowAnnotations.cs | 4 +- .../TrimAnalysis/HandleCallAction.cs | 24 +++++----- .../TypeSystemProxy/MethodProxy.cs | 1 + .../linker/Linker.Dataflow/FlowAnnotations.cs | 8 ++-- .../Linker.Dataflow/HandleCallAction.cs | 5 ++- .../src/linker/Linker.Dataflow/MethodProxy.cs | 2 + .../Linker.Dataflow/MethodReturnValue.cs | 11 ++++- .../ReflectionMethodBodyScanner.cs | 5 ++- .../DataFlowTests.cs | 6 +++ .../DataFlow/IReflectDataflow.cs | 3 ++ .../DataFlow/MethodReturnParameterDataFlow.cs | 8 ++-- .../DataFlow/MethodThisDataFlow.cs | 2 +- .../DataFlow/ObjectGetTypeDataflow.cs | 44 +++++++++++++++++++ 23 files changed, 129 insertions(+), 55 deletions(-) create mode 100644 src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ObjectGetTypeDataflow.cs diff --git a/src/coreclr/tools/Common/Compiler/Dataflow/MethodProxy.cs b/src/coreclr/tools/Common/Compiler/Dataflow/MethodProxy.cs index 3e282dfc76dcf9..cfb4bb12902958 100644 --- a/src/coreclr/tools/Common/Compiler/Dataflow/MethodProxy.cs +++ b/src/coreclr/tools/Common/Compiler/Dataflow/MethodProxy.cs @@ -66,6 +66,8 @@ internal partial ImmutableArray GetGenericParameters() return builder.ToImmutableArray(); } + internal partial bool IsConstructor() => Method.IsConstructor; + internal partial bool IsStatic() => Method.Signature.IsStatic; internal partial bool HasImplicitThis() => !Method.Signature.IsStatic; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs index 730330a31a9bc6..fd8094bc702831 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs @@ -951,12 +951,12 @@ internal partial bool MethodRequiresDataFlowAnalysis(MethodProxy method) => RequiresDataflowAnalysisDueToSignature(method.Method); #pragma warning disable CA1822 // Other partial implementations are not in the ilc project - internal partial MethodReturnValue GetMethodReturnValue(MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + internal partial MethodReturnValue GetMethodReturnValue(MethodProxy method, bool isNewObj, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) #pragma warning restore CA1822 // Mark members as static - => new MethodReturnValue(method.Method, dynamicallyAccessedMemberTypes); + => new MethodReturnValue(method.Method, isNewObj, dynamicallyAccessedMemberTypes); - internal partial MethodReturnValue GetMethodReturnValue(MethodProxy method) - => GetMethodReturnValue(method, GetReturnParameterAnnotation(method.Method)); + internal partial MethodReturnValue GetMethodReturnValue(MethodProxy method, bool isNewObj) + => GetMethodReturnValue(method, isNewObj, GetReturnParameterAnnotation(method.Method)); internal partial GenericParameterValue GetGenericParameterValue(GenericParameterProxy genericParameter) => new GenericParameterValue(genericParameter.GenericParameter, GetGenericParameterAnnotation(genericParameter.GenericParameter)); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs index c637185d15b539..7207efb6d03f59 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs @@ -39,6 +39,7 @@ public HandleCallAction( { _reflectionMarker = reflectionMarker; _operation = operation; + _isNewObj = operation == ILOpcode.newobj; _diagnosticContext = diagnosticContext; _callingMethod = callingMethod; _annotations = annotations; @@ -337,12 +338,6 @@ private partial bool TryHandleIntrinsic ( if (Intrinsics.GetIntrinsicIdForMethod(_callingMethod) == IntrinsicId.RuntimeReflectionExtensions_GetMethodInfo) break; - if (param.IsEmpty()) - { - // The static value is unknown and the below `foreach` won't execute - _reflectionMarker.Dependencies.Add(_reflectionMarker.Factory.ReflectedDelegate(null), "Delegate.Method access on unknown delegate type"); - } - foreach (var valueNode in param.AsEnumerable()) { TypeDesc? staticType = (valueNode as IValueWithStaticType)?.StaticType?.Type; @@ -390,7 +385,7 @@ private partial bool TryHandleIntrinsic ( if (staticType is null || (!staticType.IsDefType && !staticType.IsArray)) { // We don't know anything about the type GetType was called on. Track this as a usual "result of a method call without any annotations" - AddReturnValue(_reflectionMarker.Annotations.GetMethodReturnValue(calledMethod)); + AddReturnValue(_reflectionMarker.Annotations.GetMethodReturnValue(calledMethod, _isNewObj)); } else if (staticType.IsSealed() || staticType.IsTypeOf("System", "Delegate")) { @@ -425,7 +420,7 @@ private partial bool TryHandleIntrinsic ( // Return a value which is "unknown type" with annotation. For now we'll use the return value node // for the method, which means we're loosing the information about which staticType this // started with. For now we don't need it, but we can add it later on. - AddReturnValue(_reflectionMarker.Annotations.GetMethodReturnValue(calledMethod, annotation)); + AddReturnValue(_reflectionMarker.Annotations.GetMethodReturnValue(calledMethod, _isNewObj, annotation)); } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodReturnValue.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodReturnValue.cs index 7bb244d8d2bf07..7b90ffe6404599 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodReturnValue.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodReturnValue.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using ILCompiler.Dataflow; using ILLink.Shared.DataFlow; @@ -16,9 +17,10 @@ namespace ILLink.Shared.TrimAnalysis /// internal partial record MethodReturnValue { - public MethodReturnValue(MethodDesc method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + public MethodReturnValue(MethodDesc method, bool isNewObj, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) { - StaticType = method.Signature.ReturnType; + Debug.Assert(!isNewObj || method.IsConstructor, "isNewObj can only be true for constructors"); + StaticType = isNewObj ? method.OwningType : method.Signature.ReturnType; Method = method; DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs index 3d9cfd1daa7c81..6a00b2df965762 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs @@ -118,7 +118,7 @@ protected override void Scan(MethodIL methodBody, ref InterproceduralState inter if (!methodBody.OwningMethod.Signature.ReturnType.IsVoid) { var method = methodBody.OwningMethod; - var methodReturnValue = _annotations.GetMethodReturnValue(method); + var methodReturnValue = _annotations.GetMethodReturnValue(method, isNewObj: false); if (methodReturnValue.DynamicallyAccessedMemberTypes != 0) HandleAssignmentPattern(_origin, ReturnValue, methodReturnValue, method.GetDisplayName()); } @@ -315,7 +315,8 @@ public static MultiValue HandleCall( var callingMethodDefinition = callingMethodBody.OwningMethod; Debug.Assert(callingMethodDefinition == diagnosticContext.Origin.MemberDefinition); - var annotatedMethodReturnValue = reflectionMarker.Annotations.GetMethodReturnValue(calledMethod); + bool isNewObj = operation == ILOpcode.newobj; + var annotatedMethodReturnValue = reflectionMarker.Annotations.GetMethodReturnValue(calledMethod, isNewObj); Debug.Assert( RequiresReflectionMethodBodyScannerForCallSite(reflectionMarker.Annotations, calledMethod) || annotatedMethodReturnValue.DynamicallyAccessedMemberTypes == DynamicallyAccessedMemberTypes.None); diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/FlowAnnotations.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/FlowAnnotations.cs index db0eb0af579ede..2fa967fdc9405d 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/FlowAnnotations.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/FlowAnnotations.cs @@ -103,11 +103,11 @@ public static DynamicallyAccessedMemberTypes GetTypeAnnotation(ITypeSymbol type) internal partial bool MethodRequiresDataFlowAnalysis (MethodProxy method) => RequiresDataFlowAnalysis (method.Method); - internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) - => new MethodReturnValue (method.Method, dynamicallyAccessedMemberTypes); + internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, bool isNewObj, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + => new MethodReturnValue (method.Method, isNewObj, dynamicallyAccessedMemberTypes); - internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method) - => GetMethodReturnValue (method, GetMethodReturnValueAnnotation (method.Method)); + internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, bool isNewObj) + => GetMethodReturnValue (method, isNewObj, GetMethodReturnValueAnnotation (method.Method)); internal partial GenericParameterValue GetGenericParameterValue (GenericParameterProxy genericParameter) => new GenericParameterValue (genericParameter.TypeParameterSymbol); diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs index 9212cdc298fefb..d41ccee2388a58 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs @@ -33,6 +33,7 @@ public HandleCallAction ( { _owningSymbol = owningSymbol; _operation = operation; + _isNewObj = operation.Kind == OperationKind.ObjectCreation; _diagnosticContext = diagnosticContext; _annotations = FlowAnnotations.Instance; _reflectionAccessAnalyzer = default; @@ -86,7 +87,7 @@ private partial bool TryHandleIntrinsic ( if (staticType is null) { // We don't know anything about the type GetType was called on. Track this as a usual "result of a method call without any annotations" - AddReturnValue (FlowAnnotations.Instance.GetMethodReturnValue (calledMethod)); + AddReturnValue (FlowAnnotations.Instance.GetMethodReturnValue (calledMethod, _isNewObj)); } else if (staticType.IsSealed || staticType.IsTypeOf ("System", "Delegate") || staticType.TypeKind == TypeKind.Array) { // We can treat this one the same as if it was a typeof() expression @@ -106,7 +107,7 @@ private partial bool TryHandleIntrinsic ( AddReturnValue (new SystemTypeValue (new (staticType))); } else { var annotation = FlowAnnotations.GetTypeAnnotation (staticType); - AddReturnValue (FlowAnnotations.Instance.GetMethodReturnValue (calledMethod, annotation)); + AddReturnValue (FlowAnnotations.Instance.GetMethodReturnValue (calledMethod, _isNewObj, annotation)); } } break; diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodProxy.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodProxy.cs index 5001e5836eaccb..0b274879440f51 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodProxy.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodProxy.cs @@ -46,6 +46,8 @@ internal partial ImmutableArray GetGenericParameters () return builder.ToImmutableArray (); } + internal partial bool IsConstructor () => Method.IsConstructor (); + internal partial bool IsStatic () => Method.IsStatic; internal partial bool HasImplicitThis () => Method.HasImplicitThis (); diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodReturnValue.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodReturnValue.cs index 6a84896e577a86..d11181ad96d250 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodReturnValue.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodReturnValue.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using ILLink.RoslynAnalyzer; using ILLink.Shared.DataFlow; @@ -11,16 +12,17 @@ namespace ILLink.Shared.TrimAnalysis { internal partial record MethodReturnValue { - public MethodReturnValue (IMethodSymbol methodSymbol) - : this (methodSymbol, FlowAnnotations.GetMethodReturnValueAnnotation (methodSymbol)) + public MethodReturnValue (IMethodSymbol methodSymbol, bool isNewObj) + : this (methodSymbol, isNewObj, FlowAnnotations.GetMethodReturnValueAnnotation (methodSymbol)) { } - public MethodReturnValue (IMethodSymbol methodSymbol, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + public MethodReturnValue (IMethodSymbol methodSymbol, bool isNewObj, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) { + Debug.Assert (!isNewObj || methodSymbol.MethodKind == MethodKind.Constructor, "isNewObj can only be true for constructors"); MethodSymbol = methodSymbol; DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; - StaticType = new (methodSymbol.ReturnType); + StaticType = new (isNewObj ? methodSymbol.ContainingType : methodSymbol.ReturnType); } public readonly IMethodSymbol MethodSymbol; diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs index 4ff9333c55904b..c3aaa62d99ba97 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs @@ -116,7 +116,7 @@ public override MultiValue VisitConversion (IConversionOperation operation, Stat var value = base.VisitConversion (operation, state); if (operation.OperatorMethod != null) - return operation.OperatorMethod.ReturnType.IsTypeInterestingForDataflow () ? new MethodReturnValue (operation.OperatorMethod) : value; + return operation.OperatorMethod.ReturnType.IsTypeInterestingForDataflow () ? new MethodReturnValue (operation.OperatorMethod, isNewObj: false) : value; // TODO - is it possible to have annotation on the operator method parameters? // if so, will these be checked here? @@ -341,7 +341,7 @@ public override void HandleReturnValue (MultiValue returnValue, IOperation opera return; if (method.ReturnType.IsTypeInterestingForDataflow ()) { - var returnParameter = new MethodReturnValue (method); + var returnParameter = new MethodReturnValue (method, isNewObj: false); TrimAnalysisPatterns.Add ( new TrimAnalysisAssignmentPattern (returnValue, returnParameter, operation, OwningSymbol, featureContext), diff --git a/src/tools/illink/src/ILLink.Shared/TrimAnalysis/FlowAnnotations.cs b/src/tools/illink/src/ILLink.Shared/TrimAnalysis/FlowAnnotations.cs index 7ca5df5a6b8fe4..4ef9a9ce61a41f 100644 --- a/src/tools/illink/src/ILLink.Shared/TrimAnalysis/FlowAnnotations.cs +++ b/src/tools/illink/src/ILLink.Shared/TrimAnalysis/FlowAnnotations.cs @@ -19,9 +19,9 @@ partial class FlowAnnotations { internal partial bool MethodRequiresDataFlowAnalysis (MethodProxy method); - internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes); + internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, bool isNewObj, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes); - internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method); + internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, bool isNewObj); internal partial GenericParameterValue GetGenericParameterValue (GenericParameterProxy genericParameter); diff --git a/src/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs b/src/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs index 1ba45a7668bff0..ff2a393928deaf 100644 --- a/src/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs +++ b/src/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs @@ -26,6 +26,7 @@ internal partial struct HandleCallAction private readonly DiagnosticContext _diagnosticContext; private readonly FlowAnnotations _annotations; private readonly RequireDynamicallyAccessedMembersAction _requireDynamicallyAccessedMembersAction; + private readonly bool _isNewObj; public bool Invoke (MethodProxy calledMethod, MultiValue instanceValue, IReadOnlyList argumentValues, IntrinsicId intrinsicId, out MultiValue methodReturnValue) { @@ -37,11 +38,12 @@ public bool Invoke (MethodProxy calledMethod, MultiValue instanceValue, IReadOnl // As a convenience, if the code above didn't set the return value (and the method has a return value), // we will set it to be an unknown value with the return type of the method. - var annotatedMethodReturnValue = _annotations.GetMethodReturnValue (calledMethod); + var annotatedMethodReturnValue = _annotations.GetMethodReturnValue (calledMethod, _isNewObj); bool returnsVoid = calledMethod.ReturnsVoid (); - methodReturnValue = maybeMethodReturnValue ?? (returnsVoid ? - MultiValueLattice.Top : - annotatedMethodReturnValue); + methodReturnValue = maybeMethodReturnValue ?? + ((returnsVoid && !_isNewObj) + ? MultiValueLattice.Top + : annotatedMethodReturnValue); // Validate that the return value has the correct annotations as per the method return value annotations if (annotatedMethodReturnValue.DynamicallyAccessedMemberTypes != 0) { @@ -80,7 +82,7 @@ bool TryHandleSharedIntrinsic ( MultiValue? returnValue = methodReturnValue = null; bool requiresDataFlowAnalysis = _annotations.MethodRequiresDataFlowAnalysis (calledMethod); - var annotatedMethodReturnValue = _annotations.GetMethodReturnValue (calledMethod); + var annotatedMethodReturnValue = _annotations.GetMethodReturnValue (calledMethod, _isNewObj); Debug.Assert (requiresDataFlowAnalysis || annotatedMethodReturnValue.DynamicallyAccessedMemberTypes == DynamicallyAccessedMemberTypes.None); switch (intrinsicId) { @@ -237,7 +239,7 @@ GenericParameterValue genericParam && valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes == DynamicallyAccessedMemberTypes.All) returnMemberTypes = DynamicallyAccessedMemberTypes.All; - AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, returnMemberTypes)); + AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, _isNewObj, returnMemberTypes)); } } } @@ -544,7 +546,7 @@ GenericParameterValue genericParam // We only applied the annotation based on binding flags, so we will keep the necessary types // but we will not keep anything on them. So the return value has no known annotations on it - AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, DynamicallyAccessedMemberTypes.None)); + AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, _isNewObj, DynamicallyAccessedMemberTypes.None)); } } } else if (value is NullValue) { @@ -558,9 +560,9 @@ GenericParameterValue genericParam // since All applies recursively to all nested type (see MarkStep.MarkEntireType). // Otherwise we only mark the nested type itself, nothing on it, so the return value has no annotation on it. if (value is ValueWithDynamicallyAccessedMembers { DynamicallyAccessedMemberTypes: DynamicallyAccessedMemberTypes.All }) - AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, DynamicallyAccessedMemberTypes.All)); + AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, _isNewObj, DynamicallyAccessedMemberTypes.All)); else - AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, DynamicallyAccessedMemberTypes.None)); + AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, _isNewObj, DynamicallyAccessedMemberTypes.None)); } } } @@ -832,7 +834,7 @@ GenericParameterValue genericParam } else if (typeNameValue is ValueWithDynamicallyAccessedMembers valueWithDynamicallyAccessedMembers && valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes != 0) { // Propagate the annotation from the type name to the return value. Annotation on a string value will be fulfilled whenever a value is assigned to the string with annotation. // So while we don't know which type it is, we can guarantee that it will fulfill the annotation. - AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes)); + AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, _isNewObj, valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes)); } else { _diagnosticContext.AddDiagnostic (DiagnosticId.UnrecognizedTypeNameInTypeGetType, calledMethod.GetDisplayName ()); AddReturnValue (MultiValueLattice.Top); @@ -956,7 +958,7 @@ GenericParameterValue genericParam propagatedMemberTypes |= DynamicallyAccessedMemberTypes.Interfaces; } - AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, propagatedMemberTypes)); + AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, _isNewObj, propagatedMemberTypes)); } else if (value is SystemTypeValue systemTypeValue) { if (TryGetBaseType (systemTypeValue.RepresentedType, out var baseType)) AddReturnValue (new SystemTypeValue (baseType.Value)); diff --git a/src/tools/illink/src/ILLink.Shared/TypeSystemProxy/MethodProxy.cs b/src/tools/illink/src/ILLink.Shared/TypeSystemProxy/MethodProxy.cs index 92ba44e630babf..008d1c1536ef77 100644 --- a/src/tools/illink/src/ILLink.Shared/TypeSystemProxy/MethodProxy.cs +++ b/src/tools/illink/src/ILLink.Shared/TypeSystemProxy/MethodProxy.cs @@ -56,6 +56,7 @@ internal bool HasParameterOfType (ParameterIndex parameterIndex, string fullType internal partial bool HasGenericParameters (); internal partial bool HasGenericParametersCount (int genericParameterCount); internal partial ImmutableArray GetGenericParameters (); + internal partial bool IsConstructor (); internal partial bool IsStatic (); internal partial bool HasImplicitThis (); internal partial bool ReturnsVoid (); diff --git a/src/tools/illink/src/linker/Linker.Dataflow/FlowAnnotations.cs b/src/tools/illink/src/linker/Linker.Dataflow/FlowAnnotations.cs index 0c257fa068d898..3b148cf3a1ac59 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/FlowAnnotations.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/FlowAnnotations.cs @@ -682,11 +682,11 @@ public FieldAnnotation (FieldDefinition field, DynamicallyAccessedMemberTypes an internal partial bool MethodRequiresDataFlowAnalysis (MethodProxy method) => RequiresDataFlowAnalysis (method.Method); - internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) - => new MethodReturnValue (method.Method.ReturnType.ResolveToTypeDefinition (_context), method.Method, dynamicallyAccessedMemberTypes); + internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, bool isNewObj, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + => MethodReturnValue.Create (method.Method, isNewObj, dynamicallyAccessedMemberTypes, _context); - internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method) - => GetMethodReturnValue (method, GetReturnParameterAnnotation (method.Method)); + internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, bool isNewObj) + => GetMethodReturnValue (method, isNewObj, GetReturnParameterAnnotation (method.Method)); internal partial GenericParameterValue GetGenericParameterValue (GenericParameterProxy genericParameter) => new GenericParameterValue (genericParameter.GenericParameter, GetGenericParameterAnnotation (genericParameter.GenericParameter)); diff --git a/src/tools/illink/src/linker/Linker.Dataflow/HandleCallAction.cs b/src/tools/illink/src/linker/Linker.Dataflow/HandleCallAction.cs index 6721ec63478fac..998d9a06fdaeb6 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/HandleCallAction.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/HandleCallAction.cs @@ -37,6 +37,7 @@ public HandleCallAction ( { _context = context; _operation = operation; + _isNewObj = operation.OpCode == OpCodes.Newobj; _markStep = markStep; _reflectionMarker = reflectionMarker; _diagnosticContext = diagnosticContext; @@ -122,7 +123,7 @@ private partial bool TryHandleIntrinsic ( TypeDefinition? staticType = (valueNode as IValueWithStaticType)?.StaticType?.Type; if (staticType is null) { // We don't know anything about the type GetType was called on. Track this as a usual result of a method call without any annotations - AddReturnValue (_context.Annotations.FlowAnnotations.GetMethodReturnValue (calledMethod)); + AddReturnValue (_context.Annotations.FlowAnnotations.GetMethodReturnValue (calledMethod, _isNewObj)); } else if (staticType.IsSealed || staticType.IsTypeOf ("System", "Delegate") || staticType.IsTypeOf ("System", "Array")) { // We can treat this one the same as if it was a typeof() expression @@ -151,7 +152,7 @@ private partial bool TryHandleIntrinsic ( // Return a value which is "unknown type" with annotation. For now we'll use the return value node // for the method, which means we're loosing the information about which staticType this // started with. For now we don't need it, but we can add it later on. - AddReturnValue (_context.Annotations.FlowAnnotations.GetMethodReturnValue (calledMethod, annotation)); + AddReturnValue (_context.Annotations.FlowAnnotations.GetMethodReturnValue (calledMethod, _isNewObj, annotation)); } } } diff --git a/src/tools/illink/src/linker/Linker.Dataflow/MethodProxy.cs b/src/tools/illink/src/linker/Linker.Dataflow/MethodProxy.cs index a4ca0634a81f8d..6e6fd7a1bf2159 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/MethodProxy.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/MethodProxy.cs @@ -59,6 +59,8 @@ internal partial ImmutableArray GetGenericParameters () return builder.ToImmutableArray (); } + internal partial bool IsConstructor () => Method.IsConstructor; + internal partial bool IsStatic () => Method.IsStatic; internal partial bool HasImplicitThis () => Method.HasImplicitThis (); diff --git a/src/tools/illink/src/linker/Linker.Dataflow/MethodReturnValue.cs b/src/tools/illink/src/linker/Linker.Dataflow/MethodReturnValue.cs index 9197a7bda6be10..bec6951b17e4d7 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/MethodReturnValue.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/MethodReturnValue.cs @@ -2,9 +2,11 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using ILLink.Shared.DataFlow; using Mono.Cecil; +using Mono.Linker; using Mono.Linker.Dataflow; using TypeDefinition = Mono.Cecil.TypeDefinition; @@ -16,7 +18,14 @@ namespace ILLink.Shared.TrimAnalysis /// internal partial record MethodReturnValue { - public MethodReturnValue (TypeDefinition? staticType, MethodDefinition method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + public static MethodReturnValue Create (MethodDefinition method, bool isNewObj, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes, LinkContext context) + { + Debug.Assert (!isNewObj || method.IsConstructor, "isNewObj can only be true for constructors"); + var staticType = isNewObj ? method.DeclaringType : method.ReturnType.ResolveToTypeDefinition (context); + return new MethodReturnValue (staticType, method, dynamicallyAccessedMemberTypes); + } + + private MethodReturnValue (TypeDefinition? staticType, MethodDefinition method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) { StaticType = staticType == null ? null : new (staticType); Method = method; diff --git a/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs index c33649404f6b14..3f5109bfeff9bd 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs @@ -75,7 +75,7 @@ protected override void Scan (MethodIL methodIL, ref InterproceduralState interp if (!methodIL.Method.ReturnsVoid ()) { var method = methodIL.Method; - var methodReturnValue = _annotations.GetMethodReturnValue (method); + var methodReturnValue = _annotations.GetMethodReturnValue (method, isNewObj: false); if (methodReturnValue.DynamicallyAccessedMemberTypes != 0) HandleAssignmentPattern (_origin, ReturnValue, methodReturnValue); } @@ -179,7 +179,8 @@ public static MultiValue HandleCall ( Debug.Assert (callingMethodDefinition != null); bool requiresDataFlowAnalysis = context.Annotations.FlowAnnotations.RequiresDataFlowAnalysis (calledMethodDefinition); - var annotatedMethodReturnValue = context.Annotations.FlowAnnotations.GetMethodReturnValue (calledMethodDefinition); + bool isNewObj = operation.OpCode.Code == Code.Newobj; + var annotatedMethodReturnValue = context.Annotations.FlowAnnotations.GetMethodReturnValue (calledMethodDefinition, isNewObj); Debug.Assert (requiresDataFlowAnalysis || annotatedMethodReturnValue.DynamicallyAccessedMemberTypes == DynamicallyAccessedMemberTypes.None); var handleCallAction = new HandleCallAction (context, operation, markStep, reflectionMarker, diagnosticContext, callingMethodDefinition, calledMethod); diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs index c3ed28034906ad..3a95e6ea046cbd 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs @@ -313,6 +313,12 @@ public Task NullableAnnotations () return RunTest (); } + [Fact] + public Task ObjectGetTypeDataflow () + { + return RunTest (); + } + [Fact] public Task PropertyDataFlow () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/IReflectDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/IReflectDataflow.cs index ea14e8b4f2867f..db2bc09e13e59b 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/IReflectDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/IReflectDataflow.cs @@ -164,6 +164,9 @@ class TestType } [Kept] + // MyReflectOverType is not intrinsically understood by the analysis, so + // it doesn't satisfy the PublicFields | NonPublicFields requirement. + [ExpectedWarning ("IL2075")] public static void Test () { new MyReflectOverType (typeof (TestType)).GetFields (BindingFlags.Instance | BindingFlags.Public); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodReturnParameterDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodReturnParameterDataFlow.cs index 8f3adcbdaa0889..14c881bf2e4bdd 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodReturnParameterDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodReturnParameterDataFlow.cs @@ -190,7 +190,7 @@ class AnnotationOnUnsupportedReturnType { class UnsupportedType { - [UnexpectedWarning ("IL2082", Tool.Analyzer, "")] // https://github.com/dotnet/runtime/issues/101211 + [UnexpectedWarning ("IL2082", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/101211")] public UnsupportedType () { RequirePublicFields (this); } @@ -201,8 +201,7 @@ public UnsupportedType () { [ExpectedWarning ("IL2106")] // Linker and NativeAot should not produce IL2073 // They produce dataflow warnings despite the invalid annotations. - // https://github.com/dotnet/runtime/issues/101211 - [ExpectedWarning ("IL2073", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2073", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101211")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] static UnsupportedType GetWithPublicMethods () { return GetUnsupportedTypeInstance (); @@ -215,12 +214,13 @@ static void RequirePublicFields ( { } - [ExpectedWarning ("IL2072", Tool.Analyzer, "")] // https://github.com/dotnet/runtime/issues/101211 + [ExpectedWarning ("IL2072", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/101211")] static void TestMethodReturnValue () { var t = GetWithPublicMethods (); RequirePublicFields (t); } + [ExpectedWarning ("IL2072", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/101211")] static void TestCtorReturnValue () { var t = new UnsupportedType (); RequirePublicFields (t); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodThisDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodThisDataFlow.cs index 50ae6925bdb4ef..c57d784bce24db 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodThisDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodThisDataFlow.cs @@ -122,7 +122,7 @@ static void RequirePublicFields ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] UnsupportedType unsupportedTypeInstance) { } - [ExpectedWarning ("IL2075", nameof (UnsupportedType), nameof (UnsupportedType.GetMethod), Tool.Analyzer, "")] // BUG + [ExpectedWarning ("IL2075", nameof (UnsupportedType), nameof (UnsupportedType.GetMethod), Tool.Analyzer, "https://github.com/dotnet/runtime/issues/101211")] static void TestMethodThisParameter () { var t = GetUnsupportedTypeInstance (); t.GetMethod ("foo"); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ObjectGetTypeDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ObjectGetTypeDataflow.cs new file mode 100644 index 00000000000000..e089abd68955b3 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ObjectGetTypeDataflow.cs @@ -0,0 +1,44 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Helpers; + +namespace Mono.Linker.Tests.Cases.DataFlow +{ + [SkipKeptItemsValidation] + [ExpectedNoWarnings] + public class ObjectGetTypeDataflow + { + public static void Main () + { + SealedConstructorAsSource.Test (); + } + + class SealedConstructorAsSource + { + [KeptMember (".ctor()")] + public class Base + { + } + + [KeptMember (".ctor()")] + [KeptBaseType (typeof (Base))] + public sealed class Derived : Base + { + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode (nameof (Method))] + public void Method () { } + } + + [ExpectedWarning ("IL2026", nameof (Derived.Method))] + public static void Test () + { + new Derived ().GetType ().GetMethod ("Method"); + } + } + } +} From 7aefd27e8ab5011b082fca13717ef6e18050fe84 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Wed, 1 May 2024 00:47:49 +0200 Subject: [PATCH 194/248] Fix nonvolatile context restoration (#101709) * Fix nonvolatile context restoration There is a possibility of a race between the ClrRestoreNonVolatileContext and an async signal handling (like the one we use for runtime suspension). If the signal kicks in after we've loaded Rsp, but before we jumped to the target address, the context we are loading the registers from could get overwritten by the signal handler stack. So the ClrRestoreNonVolatileContext would end up jumping into a wrong target address. The fix is to load the target address into a register before loading the Rsp and then jumping using the register. * Fix arm and x86 --- src/coreclr/pal/src/arch/arm/context2.S | 21 ++++++++++++--------- src/coreclr/pal/src/arch/i386/context2.S | 17 ++++++++++++----- src/coreclr/vm/amd64/Context.S | 3 ++- src/coreclr/vm/amd64/Context.asm | 3 ++- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/coreclr/pal/src/arch/arm/context2.S b/src/coreclr/pal/src/arch/arm/context2.S index e292ca26fe2adc..bb41b0ff589b40 100644 --- a/src/coreclr/pal/src/arch/arm/context2.S +++ b/src/coreclr/pal/src/arch/arm/context2.S @@ -160,25 +160,28 @@ LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT): ldr R2, [r0, #(CONTEXT_Cpsr)] msr APSR, r2 - // Ideally, we would like to use `ldmia r0, {r0-r12, sp, lr, pc}` here, - // but clang 3.6 and later, as per ARM recommendation, disallows using - // Sp in the register list, and Pc and Lr simultaneously. - // So we are going to use the IPC register r12 to copy Sp, Lr and Pc - // which should be ok -- TODO: Is this really ok? + ldr r1, [r0, #(CONTEXT_Sp)] + ldr r2, [r0, #(CONTEXT_Pc)] + str r2, [r1, #-4] + ldr r2, [r0, #(CONTEXT_R12)] + str r2, [r1, #-8] add r12, r0, CONTEXT_R0 ldm r12, {r0-r11} - ldr sp, [r12, #(CONTEXT_Sp - (CONTEXT_R0))] ldr lr, [r12, #(CONTEXT_Lr - (CONTEXT_R0))] - ldr pc, [r12, #(CONTEXT_Pc - (CONTEXT_R0))] + ldr r12, [r12, #(CONTEXT_Sp - (CONTEXT_R0))] + sub r12, r12, #8 + mov sp, r12 + pop {r12, pc} LOCAL_LABEL(No_Restore_CONTEXT_INTEGER): ldr r2, [r0, #(CONTEXT_Cpsr)] msr APSR, r2 - ldr sp, [r0, #(CONTEXT_Sp)] ldr lr, [r0, #(CONTEXT_Lr)] - ldr pc, [r0, #(CONTEXT_Pc)] + ldr r2, [r0, #(CONTEXT_Pc)] + ldr sp, [r0, #(CONTEXT_Sp)] + bx r2 LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): ldr r2, [r0, #(CONTEXT_ContextFlags)] diff --git a/src/coreclr/pal/src/arch/i386/context2.S b/src/coreclr/pal/src/arch/i386/context2.S index cf5b464c27d0ce..35768ea6232af2 100644 --- a/src/coreclr/pal/src/arch/i386/context2.S +++ b/src/coreclr/pal/src/arch/i386/context2.S @@ -115,11 +115,12 @@ LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT): movdqu xmm7, [eax + CONTEXT_Xmm7] LOCAL_LABEL(Done_Restore_CONTEXT_EXTENDED_REGISTERS): - // Restore Stack - mov esp, [eax + CONTEXT_Esp] - // Create a minimal frame - push DWORD PTR [eax + CONTEXT_Eip] + mov ebx, [eax + CONTEXT_Esp] + mov ecx, [eax + CONTEXT_Eip] + mov edx, [eax + CONTEXT_Eax] + mov [ebx - 4], ecx + mov [ebx - 8], edx // Restore register(s) mov ebp, [eax + CONTEXT_Ebp] @@ -128,7 +129,13 @@ LOCAL_LABEL(Done_Restore_CONTEXT_EXTENDED_REGISTERS): mov edx, [eax + CONTEXT_Edx] mov ecx, [eax + CONTEXT_Ecx] mov ebx, [eax + CONTEXT_Ebx] - mov eax, [eax + CONTEXT_Eax] + + // Restore Stack + mov eax, [eax + CONTEXT_Esp] + sub eax, 8 + mov esp, eax + + pop eax // Resume ret diff --git a/src/coreclr/vm/amd64/Context.S b/src/coreclr/vm/amd64/Context.S index 0721c45f56727c..1eda47f0f9dc3f 100644 --- a/src/coreclr/vm/amd64/Context.S +++ b/src/coreclr/vm/amd64/Context.S @@ -51,8 +51,9 @@ NESTED_ENTRY ClrRestoreNonvolatileContextWorker, _TEXT, NoHandler // exception handling, iret and ret can't be used because their shadow stack enforcement would not allow that transition, // and using them would require writing to the shadow stack, which is not preferable. Instead, iret is partially // simulated. + mov rax, [r10 + OFFSETOF__CONTEXT__Rip] mov rsp, [r10 + OFFSETOF__CONTEXT__Rsp] - jmp qword ptr [r10 + OFFSETOF__CONTEXT__Rip] + jmp rax Done_Restore_CONTEXT_CONTROL: // The function was not asked to restore the control registers so we return back to the caller diff --git a/src/coreclr/vm/amd64/Context.asm b/src/coreclr/vm/amd64/Context.asm index a7165983cf4fa1..a2dbbda0b30991 100644 --- a/src/coreclr/vm/amd64/Context.asm +++ b/src/coreclr/vm/amd64/Context.asm @@ -63,8 +63,9 @@ NESTED_ENTRY ClrRestoreNonvolatileContextWorker, _TEXT mov eax, [r10 + OFFSETOF__CONTEXT__EFlags] push rax popfq + mov rax, [r10 + OFFSETOF__CONTEXT__Rip] mov rsp, [r10 + OFFSETOF__CONTEXT__Rsp] - jmp qword ptr [r10 + OFFSETOF__CONTEXT__Rip] + jmp rax Done_Restore_CONTEXT_CONTROL: ; The function was not asked to restore the control registers so we return back to the caller From b0c5a3dd5ca254c2cc3fdf3dc07502309c723045 Mon Sep 17 00:00:00 2001 From: Parker Bibus Date: Tue, 30 Apr 2024 16:53:09 -0700 Subject: [PATCH 195/248] Temporarily add specific dotnet-version as Windows runs are failing to setup with latest dotnet-install flow. (#101747) --- eng/pipelines/coreclr/templates/run-performance-job.yml | 2 +- eng/pipelines/coreclr/templates/run-scenarios-job.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/pipelines/coreclr/templates/run-performance-job.yml b/eng/pipelines/coreclr/templates/run-performance-job.yml index 2b61558e2fc97f..6b8fdc5f34ef25 100644 --- a/eng/pipelines/coreclr/templates/run-performance-job.yml +++ b/eng/pipelines/coreclr/templates/run-performance-job.yml @@ -179,7 +179,7 @@ jobs: displayName: Performance Setup (Unix) condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} - - script: $(Python) $(PerformanceDirectory)/scripts/ci_setup.py $(SetupArguments) ${{ parameters.additionalSetupParameters }} + - script: $(Python) $(PerformanceDirectory)/scripts/ci_setup.py $(SetupArguments) ${{ parameters.additionalSetupParameters }} --dotnet-versions 9.0.100-preview.5.24230.4 # Temporarily add a specific dotnet-version as Windows runs are currently failing to install the dotnet version displayName: Run ci setup script # Run perf testing in helix - template: /eng/pipelines/coreclr/templates/perf-send-to-helix.yml diff --git a/eng/pipelines/coreclr/templates/run-scenarios-job.yml b/eng/pipelines/coreclr/templates/run-scenarios-job.yml index 78db1ae8cbd091..13fdb47f15bc31 100644 --- a/eng/pipelines/coreclr/templates/run-scenarios-job.yml +++ b/eng/pipelines/coreclr/templates/run-scenarios-job.yml @@ -135,7 +135,7 @@ jobs: condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} # run ci-setup - - script: $(Python) $(PerformanceDirectory)\scripts\ci_setup.py $(SetupArguments) $(ExtraSetupArguments) --output-file $(WorkItemDirectory)\machine-setup.cmd + - script: $(Python) $(PerformanceDirectory)\scripts\ci_setup.py $(SetupArguments) $(ExtraSetupArguments) --dotnet-versions 9.0.100-preview.5.24230.4 --output-file $(WorkItemDirectory)\machine-setup.cmd # Temporarily add a specific dotnet-version as Windows runs are currently failing to install the dotnet version displayName: Run ci setup script (Windows) condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) - script: $(Python) $(PerformanceDirectory)/scripts/ci_setup.py $(SetupArguments) $(ExtraSetupArguments) --output-file $(WorkItemDirectory)/machine-setup.sh From a70000532fea5967633032f9c40896fa5b4e12f3 Mon Sep 17 00:00:00 2001 From: Alan Hayward Date: Wed, 1 May 2024 04:16:57 +0100 Subject: [PATCH 196/248] JIT ARM64-SVE: Add AddAcross (#101674) * JIT ARM64-SVE: Add AddAcross * Remove enum changes * Fix SVE tests max vector size to 512bit * fix zip test cases --------- Co-authored-by: Kunal Pathak --- src/coreclr/jit/codegenarm64test.cpp | 16 +- src/coreclr/jit/emitarm64sve.cpp | 29 +- src/coreclr/jit/hwintrinsiclistarm64sve.h | 1 + .../Arm/Sve.PlatformNotSupported.cs | 62 ++++ .../src/System/Runtime/Intrinsics/Arm/Sve.cs | 63 ++++ .../ref/System.Runtime.Intrinsics.cs | 10 + .../GenerateHWIntrinsicTests_Arm.cs | 274 ++++++++-------- .../HardwareIntrinsics/Arm/Shared/Helpers.cs | 153 +++++++++ .../Shared/_BinaryOp_SveTestTemplate.template | 2 +- .../_SveMinimalUnaryOpTestTemplate.template | 302 ++++++++++++++++++ .../Shared/_SveUnaryOpTestTemplate.template | 2 +- 11 files changed, 767 insertions(+), 147 deletions(-) create mode 100644 src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveMinimalUnaryOpTestTemplate.template diff --git a/src/coreclr/jit/codegenarm64test.cpp b/src/coreclr/jit/codegenarm64test.cpp index 52633ed6733e6a..2057a72323bf7b 100644 --- a/src/coreclr/jit/codegenarm64test.cpp +++ b/src/coreclr/jit/codegenarm64test.cpp @@ -5314,11 +5314,11 @@ void CodeGen::genArm64EmitterUnitTestsSve() #endif // ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED // IF_SVE_AI_3A - theEmitter->emitIns_R_R_R(INS_sve_saddv, EA_1BYTE, REG_V1, REG_P4, REG_V2, + theEmitter->emitIns_R_R_R(INS_sve_saddv, EA_SCALABLE, REG_V1, REG_P4, REG_V2, INS_OPTS_SCALABLE_B); // SADDV
, , . - theEmitter->emitIns_R_R_R(INS_sve_saddv, EA_2BYTE, REG_V2, REG_P5, REG_V3, + theEmitter->emitIns_R_R_R(INS_sve_saddv, EA_SCALABLE, REG_V2, REG_P5, REG_V3, INS_OPTS_SCALABLE_H); // SADDV
, , . - theEmitter->emitIns_R_R_R(INS_sve_uaddv, EA_4BYTE, REG_V3, REG_P6, REG_V4, + theEmitter->emitIns_R_R_R(INS_sve_uaddv, EA_SCALABLE, REG_V3, REG_P6, REG_V4, INS_OPTS_SCALABLE_S); // UADDV
, , . // IF_SVE_AJ_3A @@ -6768,15 +6768,15 @@ void CodeGen::genArm64EmitterUnitTestsSve() #endif // ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED // IF_SVE_HE_3A - theEmitter->emitIns_R_R_R(INS_sve_faddv, EA_2BYTE, REG_V21, REG_P7, REG_V7, + theEmitter->emitIns_R_R_R(INS_sve_faddv, EA_SCALABLE, REG_V21, REG_P7, REG_V7, INS_OPTS_SCALABLE_H); // FADDV , , . - theEmitter->emitIns_R_R_R(INS_sve_fmaxnmv, EA_2BYTE, REG_V22, REG_P6, REG_V6, + theEmitter->emitIns_R_R_R(INS_sve_fmaxnmv, EA_SCALABLE, REG_V22, REG_P6, REG_V6, INS_OPTS_SCALABLE_H); // FMAXNMV , , . - theEmitter->emitIns_R_R_R(INS_sve_fmaxv, EA_4BYTE, REG_V23, REG_P5, REG_V5, + theEmitter->emitIns_R_R_R(INS_sve_fmaxv, EA_SCALABLE, REG_V23, REG_P5, REG_V5, INS_OPTS_SCALABLE_S); // FMAXV , , . - theEmitter->emitIns_R_R_R(INS_sve_fminnmv, EA_8BYTE, REG_V24, REG_P4, REG_V4, + theEmitter->emitIns_R_R_R(INS_sve_fminnmv, EA_SCALABLE, REG_V24, REG_P4, REG_V4, INS_OPTS_SCALABLE_D); // FMINNMV , , . - theEmitter->emitIns_R_R_R(INS_sve_fminv, EA_4BYTE, REG_V25, REG_P3, REG_V3, + theEmitter->emitIns_R_R_R(INS_sve_fminv, EA_SCALABLE, REG_V25, REG_P3, REG_V3, INS_OPTS_SCALABLE_S); // FMINV , , . // IF_SVE_HQ_3A diff --git a/src/coreclr/jit/emitarm64sve.cpp b/src/coreclr/jit/emitarm64sve.cpp index 3eadf273290f85..19a1e89482a0e2 100644 --- a/src/coreclr/jit/emitarm64sve.cpp +++ b/src/coreclr/jit/emitarm64sve.cpp @@ -3060,7 +3060,6 @@ void emitter::emitInsSve_R_R_R(instruction ins, break; case INS_sve_saddv: - case INS_sve_uaddv: assert(isFloatReg(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); @@ -3069,6 +3068,15 @@ void emitter::emitInsSve_R_R_R(instruction ins, fmt = IF_SVE_AI_3A; break; + case INS_sve_uaddv: + assert(isFloatReg(reg1)); + assert(isLowPredicateRegister(reg2)); + assert(isVectorRegister(reg3)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); + fmt = IF_SVE_AI_3A; + break; + case INS_sve_addqv: unreached(); // TODO-SVE: Not yet supported. assert(isVectorRegister(reg1)); @@ -4059,7 +4067,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableFloat(opt)); - assert(isValidVectorElemsizeSveFloat(size)); + assert(isScalableVectorSize(size)); assert(insScalableOptsNone(sopt)); fmt = IF_SVE_HE_3A; break; @@ -4069,7 +4077,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableFloat(opt)); - assert(isValidVectorElemsizeSveFloat(size)); + assert(isScalableVectorSize(size)); assert(insScalableOptsNone(sopt)); fmt = IF_SVE_HJ_3A; break; @@ -12618,7 +12626,7 @@ void emitter::emitInsSveSanityCheck(instrDesc* id) assert(isVectorRegister(id->idReg1())); // ddddd assert(isLowPredicateRegister(id->idReg2())); // ggg assert(isVectorRegister(id->idReg3())); // mmmmm - assert(isValidVectorElemsizeSveFloat(id->idOpSize())); + assert(isScalableVectorSize(id->idOpSize())); break; // Scalable to general register. @@ -13211,11 +13219,20 @@ void emitter::emitInsSveSanityCheck(instrDesc* id) // Scalable, widening to scalar SIMD. case IF_SVE_AI_3A: // ........xx...... ...gggnnnnnddddd -- SVE integer add reduction (predicated) - assert(insOptsScalableWide(id->idInsOpt())); // xx + switch (id->idIns()) + { + case INS_sve_saddv: + assert(insOptsScalableWide(id->idInsOpt())); // xx + break; + + default: + assert(insOptsScalableStandard(id->idInsOpt())); // xx + break; + } assert(isVectorRegister(id->idReg1())); // ddddd assert(isLowPredicateRegister(id->idReg2())); // ggg assert(isVectorRegister(id->idReg3())); // mmmmm - assert(isValidVectorElemsizeWidening(id->idOpSize())); + assert(isScalableVectorSize(id->idOpSize())); break; // Scalable, possibly FP. diff --git a/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/coreclr/jit/hwintrinsiclistarm64sve.h index b4d0c1319a2276..1d023e47be9cc5 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64sve.h +++ b/src/coreclr/jit/hwintrinsiclistarm64sve.h @@ -19,6 +19,7 @@ // Sve HARDWARE_INTRINSIC(Sve, Abs, -1, -1, false, {INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_fabs, INS_sve_fabs}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation) HARDWARE_INTRINSIC(Sve, Add, -1, -1, false, {INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_fadd, INS_sve_fadd}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, AddAcross, -1, 1, true, {INS_sve_saddv, INS_sve_uaddv, INS_sve_saddv, INS_sve_uaddv, INS_sve_saddv, INS_sve_uaddv, INS_sve_uaddv, INS_sve_uaddv, INS_sve_faddv, INS_sve_faddv}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbeddedMaskedOperation) HARDWARE_INTRINSIC(Sve, ConditionalSelect, -1, 3, true, {INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(Sve, Count16BitElements, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_cnth, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_SpecialCodeGen|HW_Flag_NoFloatingPointUsed) HARDWARE_INTRINSIC(Sve, Count32BitElements, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_cntw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_SpecialCodeGen|HW_Flag_NoFloatingPointUsed) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs index afbaa6e8969c52..4715c3777543ad 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs @@ -148,6 +148,68 @@ internal Arm64() { } /// public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// AddAcross : Add reduction + + /// + /// float64_t svaddv[_f64](svbool_t pg, svfloat64_t op) + /// FADDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svaddv[_s16](svbool_t pg, svint16_t op) + /// SADDV Dresult, Pg, Zop.H + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svaddv[_s32](svbool_t pg, svint32_t op) + /// SADDV Dresult, Pg, Zop.S + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svaddv[_s8](svbool_t pg, svint8_t op) + /// SADDV Dresult, Pg, Zop.B + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svaddv[_s64](svbool_t pg, svint64_t op) + /// UADDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// float32_t svaddv[_f32](svbool_t pg, svfloat32_t op) + /// FADDV Sresult, Pg, Zop.S + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svaddv[_u8](svbool_t pg, svuint8_t op) + /// UADDV Dresult, Pg, Zop.B + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svaddv[_u16](svbool_t pg, svuint16_t op) + /// UADDV Dresult, Pg, Zop.H + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svaddv[_u32](svbool_t pg, svuint32_t op) + /// UADDV Dresult, Pg, Zop.S + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svaddv[_u64](svbool_t pg, svuint64_t op) + /// UADDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + /// ConditionalSelect : Conditionally select elements diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs index 7c2c8a0a4e78e6..3e88376b9614ad 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs @@ -177,6 +177,69 @@ internal Arm64() { } public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + /// AddAcross : Add reduction + + /// + /// float64_t svaddv[_f64](svbool_t pg, svfloat64_t op) + /// FADDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// int64_t svaddv[_s16](svbool_t pg, svint16_t op) + /// SADDV Dresult, Pg, Zop.H + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// int64_t svaddv[_s32](svbool_t pg, svint32_t op) + /// SADDV Dresult, Pg, Zop.S + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// int64_t svaddv[_s8](svbool_t pg, svint8_t op) + /// SADDV Dresult, Pg, Zop.B + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// int64_t svaddv[_s64](svbool_t pg, svint64_t op) + /// UADDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// float32_t svaddv[_f32](svbool_t pg, svfloat32_t op) + /// FADDV Sresult, Pg, Zop.S + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// uint64_t svaddv[_u8](svbool_t pg, svuint8_t op) + /// UADDV Dresult, Pg, Zop.B + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// uint64_t svaddv[_u16](svbool_t pg, svuint16_t op) + /// UADDV Dresult, Pg, Zop.H + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// uint64_t svaddv[_u32](svbool_t pg, svuint32_t op) + /// UADDV Dresult, Pg, Zop.S + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// uint64_t svaddv[_u64](svbool_t pg, svuint64_t op) + /// UADDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// ConditionalSelect : Conditionally select elements /// diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 88839fee87dcad..18365d784dfcee 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -4187,6 +4187,16 @@ internal Arm64() { } public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } public static ulong Count16BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } public static ulong Count32BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } public static ulong Count64BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } diff --git a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs index 589217ca968e4a..648a05ed3c0c51 100644 --- a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs +++ b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs @@ -98,29 +98,30 @@ (string templateFileName, string outputTemplateName, Dictionary templateData)[] Templates = new[] { - ("_UnaryOpScalarTestTemplate.template", "DuplicateTest.template", new Dictionary { ["TemplateName"] = "Duplicate", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_ImmUnaryOpTestTemplate.template", "ImmUnOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_ImmUnaryOpTestTemplate.template", "VecImmUnOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), - ("_ImmTernaryOpTestTemplate.template", "ImmTernOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), - ("_ImmOpTestTemplate.template", "ImmOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_ImmBinaryOpTestTemplate.template", "ImmBinOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_ImmBinaryOpTestTemplate.template", "VecImmBinOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), - ("_BinaryOpTestTemplate.template", "SimpleBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_TernaryOpTestTemplate.template", "VecTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), - ("_ImmTernaryOpTestTemplate.template", "VecImmTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), - ("_ImmTernaryOpTestTemplate.template", "SimpleImmTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_UnaryOpTestTemplate.template", "SimpleUnOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_UnaryOpTestTemplate.template", "SimpleVecOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), - ("_BinaryOpTestTemplate.template", "VecPairBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecPairBinOpTest_ValidationLogic }), - ("_BinaryOp_SveTestTemplate.template", "SveVecPairBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecPairBinOpTest_ValidationLogic }), - ("_UnaryOpTestTemplate.template", "VecReduceUnOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecReduceOpTest_ValidationLogic }), - ("_BinaryOpTestTemplate.template", "VecBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), - ("_TernaryOpTestTemplate.template", "SimpleTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_UnaryOpTestTemplate.template", "SecureHashUnOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), - ("_BinaryOpTestTemplate.template", "SecureHashBinOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), - ("_TernaryOpTestTemplate.template", "SecureHashTernOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), - ("_SveUnaryOpTestTemplate.template", "SveSimpleVecOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic, ["TemplateValidationLogicForCndSel"] = SimpleVecOpTest_ValidationLogicForCndSel }), - ("_SveBinaryOpTestTemplate.template", "SveVecBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic, ["TemplateValidationLogicForCndSel"] = SimpleVecOpTest_ValidationLogicForCndSel }), + ("_UnaryOpScalarTestTemplate.template", "DuplicateTest.template", new Dictionary { ["TemplateName"] = "Duplicate", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_ImmUnaryOpTestTemplate.template", "ImmUnOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_ImmUnaryOpTestTemplate.template", "VecImmUnOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_ImmTernaryOpTestTemplate.template", "ImmTernOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_ImmOpTestTemplate.template", "ImmOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_ImmBinaryOpTestTemplate.template", "ImmBinOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_ImmBinaryOpTestTemplate.template", "VecImmBinOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_BinaryOpTestTemplate.template", "SimpleBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_TernaryOpTestTemplate.template", "VecTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_ImmTernaryOpTestTemplate.template", "VecImmTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_ImmTernaryOpTestTemplate.template", "SimpleImmTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_UnaryOpTestTemplate.template", "SimpleUnOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_UnaryOpTestTemplate.template", "SimpleVecOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_BinaryOpTestTemplate.template", "VecPairBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecPairBinOpTest_ValidationLogic }), + ("_BinaryOp_SveTestTemplate.template", "SveVecPairBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecPairBinOpTest_ValidationLogic }), + ("_UnaryOpTestTemplate.template", "VecReduceUnOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecReduceOpTest_ValidationLogic }), + ("_BinaryOpTestTemplate.template", "VecBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_TernaryOpTestTemplate.template", "SimpleTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_UnaryOpTestTemplate.template", "SecureHashUnOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), + ("_BinaryOpTestTemplate.template", "SecureHashBinOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), + ("_TernaryOpTestTemplate.template", "SecureHashTernOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), + ("_SveUnaryOpTestTemplate.template", "SveSimpleVecOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic, ["TemplateValidationLogicForCndSel"] = SimpleVecOpTest_ValidationLogicForCndSel }), + ("_SveBinaryOpTestTemplate.template", "SveVecBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic, ["TemplateValidationLogicForCndSel"] = SimpleVecOpTest_ValidationLogicForCndSel }), + ("_SveMinimalUnaryOpTestTemplate.template", "SveVecReduceUnOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecReduceOpTest_ValidationLogic }), }; (string templateFileName, Dictionary templateData)[] AdvSimdInputs = new [] @@ -2909,8 +2910,16 @@ ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), - ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Divide_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Divide", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Divide(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Divide(left[i], right[i])"}), - ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Divide_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Divide", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Divide(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Divide(left[i], right[i])"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossRecursivePairwise(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0.0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossRecursivePairwise(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0.0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_long_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossWideningLong(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_long_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossWideningLong(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_long_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossWidening(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_ulong_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossWideningULong(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_ulong_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossWideningULong(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_ulong_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossWidening(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), @@ -2923,43 +2932,46 @@ ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), - ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count16BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count16BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Int16)));",}), - ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count32BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count32BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Int32)));",}), - ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count64BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count64BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Int64)));",}), - ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count8BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count8BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Byte)));",}), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count16BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count16BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Int16)));",}), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count32BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count32BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Int32)));",}), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count64BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count64BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Int64)));",}), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count8BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count8BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Byte)));",}), + + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask32Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask32Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask32Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask32Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask64Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask64Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask64Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask64Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask8Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask8Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask8Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask8Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask16Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask16Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask16Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask16Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask32Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask32Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask32Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask32Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask64Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask64Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask64Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask64Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask8Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask8Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask8Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask8Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt64)i, right) != (UInt64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int32)i, right) != (Int32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int64)i, right) != (Int64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt32)i, right) != (UInt32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt64)i, right) != (UInt64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask32Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int32)i, right) != (Int32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask32Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int64)i, right) != (Int64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask32Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt32)i, right) != (UInt32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask32Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt64)i, right) != (UInt64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask64Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int32)i, right) != (Int32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask64Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int64)i, right) != (Int64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask64Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt32)i, right) != (UInt32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask64Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt64)i, right) != (UInt64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask8Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int32)i, right) != (Int32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask8Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int64)i, right) != (Int64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask8Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt32)i, right) != (UInt32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask8Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt64)i, right) != (UInt64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask16Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int32)i, right) != (Int32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask16Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int64)i, right) != (Int64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask16Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt32)i, right) != (UInt32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask16Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt64)i, right) != (UInt64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask32Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int32)i, right) != (Int32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask32Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int64)i, right) != (Int64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask32Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt32)i, right) != (UInt32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask32Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt64)i, right) != (UInt64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask64Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int32)i, right) != (Int32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask64Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int64)i, right) != (Int64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask64Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt32)i, right) != (UInt32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask64Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt64)i, right) != (UInt64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask8Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int32)i, right) != (Int32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask8Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int64)i, right) != (Int64)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask8Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt32)i, right) != (UInt32)result[i]",}), - ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask8Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Divide_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Divide", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Divide(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Divide(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Divide_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Divide", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Divide(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Divide(left[i], right[i])"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_float", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_double", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), @@ -2972,30 +2984,30 @@ ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_uint", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_ulong", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt32SignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt32SignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt32SignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt32SignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt32ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt32ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt32SignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt32SignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt32SignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt32SignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt32ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt32ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), @@ -3026,54 +3038,54 @@ ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend16_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, true)"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend16_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, true)"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend32_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 32, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 32, true)"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend16_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend16_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend32_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 32, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 32, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), - ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), }; diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs index 6e96c9fc080a5a..f8c86732969119 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs @@ -1443,6 +1443,8 @@ public static float CompareTest(float left, float right) public static short AddAcrossWidening(sbyte[] op1) => Reduce(AddWidening, op1); + public static long AddAcrossWideningLong(sbyte[] op1) => Reduce(AddWidening, op1); + public static short AddPairwiseWidening(sbyte[] op1, int i) => AddWidening(op1[2 * i], op1[2 * i + 1]); public static short AddPairwiseWideningAndAdd(short[] op1, sbyte[] op2, int i) => (short)(op1[i] + AddWidening(op2[2 * i], op2[2 * i + 1])); @@ -1469,6 +1471,8 @@ private static sbyte HighNarrowing(short op1, bool round) public static short AddWidening(short op1, sbyte op2) => (short)(op1 + op2); + public static long AddWidening(long op1, sbyte op2) => (long)(op1 + (long)op2); + public static short AddWideningUpper(sbyte[] op1, sbyte[] op2, int i) => AddWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); public static short AddWideningUpper(short[] op1, sbyte[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); @@ -1533,6 +1537,18 @@ private static short Reduce(Func reduceOp, sbyte[] op1) return acc; } + private static long Reduce(Func reduceOp, sbyte[] op1) + { + long acc = op1[0]; + + for (int i = 1; i < op1.Length; i++) + { + acc = reduceOp(acc, op1[i]); + } + + return acc; + } + public static uint AbsoluteDifferenceWidening(short op1, short op2) => op1 < op2 ? (uint)(op2 - op1) : (uint)(op1 - op2); public static uint AbsoluteDifferenceWideningUpper(short[] op1, short[] op2, int i) => AbsoluteDifferenceWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); @@ -1543,6 +1559,8 @@ private static short Reduce(Func reduceOp, sbyte[] op1) public static int AddAcrossWidening(short[] op1) => Reduce(AddWidening, op1); + public static long AddAcrossWideningLong(short[] op1) => Reduce(AddWidening, op1); + public static int AddPairwiseWidening(short[] op1, int i) => AddWidening(op1[2 * i], op1[2 * i + 1]); public static int AddPairwiseWideningAndAdd(int[] op1, short[] op2, int i) => (int)(op1[i] + AddWidening(op2[2 * i], op2[2 * i + 1])); @@ -1569,6 +1587,8 @@ private static short HighNarrowing(int op1, bool round) public static int AddWidening(int op1, short op2) => (int)(op1 + op2); + public static long AddWidening(long op1, short op2) => (long)(op1 + (long)op2); + public static int AddWideningUpper(short[] op1, short[] op2, int i) => AddWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); public static int AddWideningUpper(int[] op1, short[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); @@ -1633,6 +1653,18 @@ private static int Reduce(Func reduceOp, short[] op1) return acc; } + private static long Reduce(Func reduceOp, short[] op1) + { + long acc = op1[0]; + + for (int i = 1; i < op1.Length; i++) + { + acc = reduceOp(acc, op1[i]); + } + + return acc; + } + public static ulong AbsoluteDifferenceWidening(int op1, int op2) => op1 < op2 ? (ulong)(op2 - op1) : (ulong)(op1 - op2); public static ulong AbsoluteDifferenceWideningUpper(int[] op1, int[] op2, int i) => AbsoluteDifferenceWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); @@ -1766,6 +1798,8 @@ private static long Reduce(Func reduceOp, int[] op1) public static ushort AddAcrossWidening(byte[] op1) => Reduce(AddWidening, op1); + public static ulong AddAcrossWideningULong(byte[] op1) => Reduce(AddWidening, op1); + public static ushort AddPairwiseWidening(byte[] op1, int i) => AddWidening(op1[2 * i], op1[2 * i + 1]); public static ushort AddPairwiseWideningAndAdd(ushort[] op1, byte[] op2, int i) => (ushort)(op1[i] + AddWidening(op2[2 * i], op2[2 * i + 1])); @@ -1792,6 +1826,8 @@ private static byte HighNarrowing(ushort op1, bool round) public static ushort AddWidening(ushort op1, byte op2) => (ushort)(op1 + op2); + public static ulong AddWidening(ulong op1, byte op2) => (ulong)(op1 + (ulong)op2); + public static ushort AddWideningUpper(byte[] op1, byte[] op2, int i) => AddWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); public static ushort AddWideningUpper(ushort[] op1, byte[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); @@ -1856,6 +1892,18 @@ private static ushort Reduce(Func reduceOp, byte[] op1) return acc; } + private static ulong Reduce(Func reduceOp, byte[] op1) + { + ulong acc = op1[0]; + + for (int i = 1; i < op1.Length; i++) + { + acc = reduceOp(acc, op1[i]); + } + + return acc; + } + public static uint AbsoluteDifferenceWidening(ushort op1, ushort op2) => op1 < op2 ? (uint)(op2 - op1) : (uint)(op1 - op2); public static uint AbsoluteDifferenceWideningUpper(ushort[] op1, ushort[] op2, int i) => AbsoluteDifferenceWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); @@ -1866,6 +1914,8 @@ private static ushort Reduce(Func reduceOp, byte[] op1) public static uint AddAcrossWidening(ushort[] op1) => Reduce(AddWidening, op1); + public static ulong AddAcrossWideningULong(ushort[] op1) => Reduce(AddWidening, op1); + public static uint AddPairwiseWidening(ushort[] op1, int i) => AddWidening(op1[2 * i], op1[2 * i + 1]); public static uint AddPairwiseWideningAndAdd(uint[] op1, ushort[] op2, int i) => (uint)(op1[i] + AddWidening(op2[2 * i], op2[2 * i + 1])); @@ -1892,6 +1942,8 @@ private static ushort HighNarrowing(uint op1, bool round) public static uint AddWidening(uint op1, ushort op2) => (uint)(op1 + op2); + public static ulong AddWidening(ulong op1, ushort op2) => (ulong)(op1 + (ulong)op2); + public static uint AddWideningUpper(ushort[] op1, ushort[] op2, int i) => AddWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); public static uint AddWideningUpper(uint[] op1, ushort[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); @@ -1956,6 +2008,18 @@ private static uint Reduce(Func reduceOp, ushort[] op1) return acc; } + private static ulong Reduce(Func reduceOp, ushort[] op1) + { + ulong acc = op1[0]; + + for (int i = 1; i < op1.Length; i++) + { + acc = reduceOp(acc, op1[i]); + } + + return acc; + } + public static ulong AbsoluteDifferenceWidening(uint op1, uint op2) => op1 < op2 ? (ulong)(op2 - op1) : (ulong)(op1 - op2); public static ulong AbsoluteDifferenceWideningUpper(uint[] op1, uint[] op2, int i) => AbsoluteDifferenceWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); @@ -2056,6 +2120,9 @@ private static ulong Reduce(Func reduceOp, uint[] op1) return acc; } + public static double AddWidening(double op1, float op2) => (double)(op1 + (double)op2); + + private static bool SignedSatQ(short val, out sbyte result) { bool saturated = false; @@ -5157,6 +5224,42 @@ private static uint Reduce(Func reduceOp, uint[] op1) return acc; } + public static long AddAcross(long[] op1) => Reduce(Add, op1); + + public static long MaxAcross(long[] op1) => Reduce(Max, op1); + + public static long MinAcross(long[] op1) => Reduce(Min, op1); + + private static long Reduce(Func reduceOp, long[] op1) + { + long acc = op1[0]; + + for (int i = 1; i < op1.Length; i++) + { + acc = reduceOp(acc, op1[i]); + } + + return acc; + } + + public static ulong AddAcross(ulong[] op1) => Reduce(Add, op1); + + public static ulong MaxAcross(ulong[] op1) => Reduce(Max, op1); + + public static ulong MinAcross(ulong[] op1) => Reduce(Min, op1); + + private static ulong Reduce(Func reduceOp, ulong[] op1) + { + ulong acc = op1[0]; + + for (int i = 1; i < op1.Length; i++) + { + acc = reduceOp(acc, op1[i]); + } + + return acc; + } + public static float AddAcross(float[] op1) => Reduce(Add, op1); public static float MaxAcross(float[] op1) => Reduce(Max, op1); @@ -5175,6 +5278,31 @@ private static float Reduce(Func reduceOp, float[] op1) return acc; } + public static float AddAcrossRecursivePairwise(float[] op1) => ReduceRecursivePairwise(Add, op1); + + private static float ReduceRecursivePairwise(Func reduceOp, float[] op1) + { + if (op1.Length == 2) + { + return reduceOp(op1[0], op1[1]); + } + + if (op1.Length % 2 != 0) + { + return float.NaN; + } + + float[] l = new float[op1.Length / 2]; + Array.Copy(op1, 0, l, 0, (op1.Length / 2)); + float l_reduced = ReduceRecursivePairwise(reduceOp, l); + + float[] r = new float[op1.Length / 2]; + Array.Copy(op1, (op1.Length / 2), r, 0, (op1.Length / 2)); + float r_reduced = ReduceRecursivePairwise(reduceOp, r); + + return reduceOp(l_reduced, r_reduced); + } + public static double AddAcross(double[] op1) => Reduce(Add, op1); public static double MaxAcross(double[] op1) => Reduce(Max, op1); @@ -5193,6 +5321,31 @@ private static double Reduce(Func reduceOp, double[] op1 return acc; } + public static double AddAcrossRecursivePairwise(double[] op1) => ReduceRecursivePairwise(Add, op1); + + private static double ReduceRecursivePairwise(Func reduceOp, double[] op1) + { + if (op1.Length == 2) + { + return reduceOp(op1[0], op1[1]); + } + + if (op1.Length % 2 != 0) + { + return double.NaN; + } + + double[] l = new double[op1.Length / 2]; + Array.Copy(op1, 0, l, 0, (op1.Length / 2)); + double l_reduced = ReduceRecursivePairwise(reduceOp, l); + + double[] r = new double[op1.Length / 2]; + Array.Copy(op1, (op1.Length / 2), r, 0, (op1.Length / 2)); + double r_reduced = ReduceRecursivePairwise(reduceOp, r); + + return reduceOp(l_reduced, r_reduced); + } + public static float MaxNumberAcross(float[] op1) => Reduce(MaxNumber, op1); public static float MinNumberAcross(float[] op1) => Reduce(MinNumber, op1); diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_BinaryOp_SveTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_BinaryOp_SveTestTemplate.template index 19923127555c1e..9e2c2c7516c293 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_BinaryOp_SveTestTemplate.template +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_BinaryOp_SveTestTemplate.template @@ -83,7 +83,7 @@ namespace JIT.HardwareIntrinsics.Arm int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op2BaseType}>(); int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); - if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) { throw new ArgumentException("Invalid value of alignment"); } diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveMinimalUnaryOpTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveMinimalUnaryOpTestTemplate.template new file mode 100644 index 00000000000000..782f77de3520ea --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveMinimalUnaryOpTestTemplate.template @@ -0,0 +1,302 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new {TemplateName}UnaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}UnaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException($"Invalid value of alignment: {alignment}, sizeOfinArray1: {sizeOfinArray1}, sizeOfoutArray: {sizeOfoutArray}"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}UnaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + + private DataTable _dataTable; + + public {TemplateName}UnaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + _dataTable = new DataTable(_data1, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{Op1BaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var result = {Isa}.{Method}(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveUnaryOpTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveUnaryOpTestTemplate.template index 557442de4cf0be..119cc5d88cb6fa 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveUnaryOpTestTemplate.template +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveUnaryOpTestTemplate.template @@ -191,7 +191,7 @@ namespace JIT.HardwareIntrinsics.Arm { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{RetBaseType}(SveMaskPattern.All); + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{Op1BaseType}(SveMaskPattern.All); var result = {Isa}.{Method}( {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray1Ptr)) From 5e2b55f660a81eaa85388123baaf7bebe1c0ad48 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 30 Apr 2024 20:50:04 -0700 Subject: [PATCH 197/248] Typos: ablity -> ability (#101755) * Fix typo in extractor.cpp ablity -> ability * More typos --------- Co-authored-by: Ikko Eltociear Ashimine --- src/coreclr/jit/optimizer.cpp | 2 +- .../Text/RegularExpressions/Symbolic/SymbolicRegexNode.cs | 2 +- src/native/corehost/bundle/extractor.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index 0de4cacc7bb0c5..7f2ef4bf95d6e6 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -5052,7 +5052,7 @@ void Compiler::optHoistCandidate(GenTree* tree, FlowGraphNaturalLoop* loop, LoopHoistContext* hoistCtxt) { - // It must pass the hoistable profitablity tests for this loop level + // It must pass the hoistable profitability tests for this loop level if (!optIsProfitableToHoistTree(tree, loop, hoistCtxt)) { JITDUMP(" ... not profitable to hoist\n"); diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexNode.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexNode.cs index b20564cee32a1c..a138c819be00fa 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexNode.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexNode.cs @@ -243,7 +243,7 @@ bool WithCache(uint context) Debug.Assert(context < CharKind.ContextLimit); - // If nullablity has been computed for the given context then return it + // If nullability has been computed for the given context then return it byte b = Volatile.Read(ref _nullabilityCache[context]); if (b != UndefinedByte) { diff --git a/src/native/corehost/bundle/extractor.cpp b/src/native/corehost/bundle/extractor.cpp index fc0659e82dc32d..ab2c53295055b9 100644 --- a/src/native/corehost/bundle/extractor.cpp +++ b/src/native/corehost/bundle/extractor.cpp @@ -219,7 +219,7 @@ void extractor_t::commit_dir() // Retry the move operation with some wait in between the attempts. This is to workaround for possible file locking // caused by AV software. Basically the extraction process above writes a bunch of executable files to disk // and some AV software may decide to scan them on write. If this happens the files will be locked which blocks - // our ablity to move them. + // our ability to move them. bool extracted_by_concurrent_process = false; bool extracted_by_current_process = From 6cb48206280ba5c48d117140532e4da1b4058849 Mon Sep 17 00:00:00 2001 From: Viktor Hofer Date: Wed, 1 May 2024 08:07:05 +0200 Subject: [PATCH 198/248] Replace NETCOREAPP compiler directive with NET (#101693) * Replace NETCOREAPP compiler directive with NET Consistently use the `NET` preprocessor directive instead of a mix of both `NETCOREAPP` and `NET`. * Remaining NETCOREAPP usages * Update TestCaseCompilationMetadataProvider.cs * Update TestCaseCompilationMetadataProvider.cs --- .../TestCasesRunner/ILInputCompiler.cs | 4 +- .../TestCaseCompilationMetadataProvider.cs | 2 +- .../TestCasesRunner/TestCaseCompiler.cs | 10 +- .../TrimmingArgumentBuilder.cs | 2 +- .../src/Extensions/ChangeCallbackRegistrar.cs | 2 +- .../Windows/NCrypt/Interop.Properties.cs | 2 +- .../src/System/HashCodeRandomization.cs | 2 +- .../Reflection/AssemblyNameFormatter.cs | 2 +- .../src/System/Resources/ResourceWriter.cs | 2 +- .../Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs | 2 +- .../Security/Cryptography/CryptoPool.cs | 2 +- .../System/Security/Cryptography/Helpers.cs | 8 +- .../Text/Json/PooledByteBufferWriter.cs | 4 +- .../src/System/Text/ValueStringBuilder.cs | 4 +- .../tests/SourceGenerators/RoslynTestUtils.cs | 2 +- .../System/Collections/TestBase.Generic.cs | 2 +- .../System/IO/Compression/ZipTestHelper.cs | 2 +- .../System/Net/Http/ByteAtATimeContent.cs | 2 +- .../HttpClientHandlerTest.Decompression.cs | 4 +- .../Net/Http/HttpClientHandlerTestBase.cs | 14 +- .../Http/HttpMessageHandlerLoopbackServer.cs | 2 +- .../System/Net/Http/ResponseStreamTest.cs | 2 +- .../tests/System/Net/Http/TestHelper.cs | 4 +- .../DSA/DSASignVerify.cs | 2 +- .../AlgorithmImplementations/EC/CurveDef.cs | 2 +- .../EC/EccTestBase.cs | 2 +- .../ECDiffieHellman/ECDiffieHellmanFactory.cs | 4 +- .../ECDiffieHellmanTests.Hash.cs | 2 +- .../ECDiffieHellmanTests.Hmac.cs | 2 +- .../ECDiffieHellmanTests.ImportExport.cs | 2 +- .../ECDiffieHellmanTests.NistValidation.cs | 2 +- .../ECDiffieHellmanTests.Tls.cs | 2 +- .../ECDiffieHellman/ECDiffieHellmanTests.cs | 2 +- .../ECDsa/ECDsaFactory.cs | 4 +- .../ECDsa/ECDsaImportExport.cs | 2 +- .../ECDsa/ECDsaStub.cs | 2 +- .../ECDsa/ECDsaTests.NistValidation.cs | 2 +- .../ECDsa/ECDsaTestsBase.cs | 2 +- .../Security/Cryptography/PlatformSupport.cs | 2 +- .../TestUtilities/System/AssertExtensions.cs | 2 +- .../TestUtilities/System/PlatformDetection.cs | 8 +- .../Runtime/InteropServices/SafeBufferUtil.cs | 2 +- .../src/ConfigurationBinder.cs | 2 +- .../ConfigurationBinderTests.Collections.cs | 4 +- .../ConfigurationBinderTests.Helpers.cs | 2 +- ...tionBinderTests.TestClasses.Collections.cs | 2 +- .../ConfigurationBinderTests.TestClasses.cs | 2 +- .../tests/Common/ConfigurationBinderTests.cs | 6 +- .../GeneratorTests.Helpers.cs | 4 +- .../src/ConfigurationKeyComparer.cs | 2 +- .../FunctionalTests/DisposableFileSystem.cs | 2 +- .../src/ActivatorUtilities.cs | 40 +-- .../tests/DI.Tests/ActivatorUtilitiesTests.cs | 24 +- .../src/DependencyContextPaths.cs | 2 +- .../tests/MockFileProvider.cs | 2 +- .../src/Internal/FileSystemInfoHelper.cs | 4 +- .../src/PhysicalFileProvider.cs | 2 +- .../src/PhysicalFilesWatcher.cs | 2 +- .../tests/TestUtility/DisposableFileSystem.cs | 2 +- .../src/SystemdHelpers.cs | 4 +- .../src/HostingHostBuilderExtensions.cs | 4 +- .../UnitTests/HostApplicationBuilderTests.cs | 6 +- .../tests/UnitTests/HostBuilderTests.cs | 4 +- .../OptionsBuilderExtensionsTests.cs | 2 +- .../src/Logging/HttpHeadersLogValue.cs | 2 +- .../src/AnsiParsingLogConsole.cs | 2 +- .../src/JsonConsoleFormatter.cs | 4 +- .../src/SimpleConsoleFormatter.cs | 4 +- .../tests/EventSourceLoggerTest.cs | 2 +- .../Common/TraceSourceLoggerProviderTest.cs | 2 +- .../tests/Common/TraceSourceScopeTest.cs | 2 +- .../tests/SourceGeneration.Unit.Tests/Main.cs | 18 +- .../src/StringSegment.cs | 2 +- .../src/StringSegmentComparer.cs | 2 +- .../src/StringValues.cs | 2 +- .../Microsoft/VisualBasic/VBCodeGenerator.cs | 6 +- .../System/CodeDom/TempFileCollectionTests.cs | 2 +- .../ref/System.Collections.Immutable.cs | 4 +- .../Immutable/AllocFreeConcurrentStack.cs | 10 +- .../Immutable/ImmutableExtensions.cs | 2 +- .../Immutable/ImmutableHashSet_1.cs | 2 +- .../Immutable/ImmutableSortedSet_1.cs | 2 +- .../tests/ImmutableListTest.cs | 2 +- .../Composition/Hosting/DirectoryCatalog.cs | 2 +- .../ConfigurationLockCollection.cs | 2 +- .../Configuration/ConfigurationProperty.cs | 2 +- .../ConfigurationSectionCollection.cs | 2 +- .../ConfigurationSectionGroupCollection.cs | 2 +- .../DiagnosticSourceEventSource.cs | 6 +- .../Diagnostics/Metrics/MetricsEventSource.cs | 2 +- .../Diagnostics/PerformanceCounterLib.cs | 4 +- .../tests/DirectoryServicesTestHelpers.cs | 2 +- .../Asn1/AsnCharacterStringEncodings.cs | 8 +- .../src/System/Formats/Asn1/AsnDecoder.Oid.cs | 2 +- .../src/System/Formats/Asn1/AsnWriter.Oid.cs | 2 +- .../src/System/Formats/Asn1/WellKnownOids.cs | 2 +- .../tests/Reader/ReadIA5String.cs | 2 +- .../Formats/Cbor/CborConformanceLevel.cs | 2 +- .../System/Formats/Cbor/Writer/CborWriter.cs | 2 +- .../Reader/CborReaderTests.TextString.cs | 8 +- .../Hashing/NonCryptographicHashAlgorithm.cs | 2 +- .../tests/NonCryptoHashTestDriver.cs | 4 +- .../System/IO/Packaging/ZipWrappingStream.cs | 2 +- .../System/IO/Pipelines/StreamPipeReader.cs | 4 +- .../System/IO/Pipelines/StreamPipeWriter.cs | 2 +- .../Infrastructure/CancelledReadsStream.cs | 2 +- .../Infrastructure/CancelledWritesStream.cs | 2 +- .../Infrastructure/ThrowAfterNWritesStream.cs | 2 +- .../tests/StreamPipeReaderTests.cs | 8 +- .../tests/StreamPipeWriterTests.cs | 2 +- .../src/System/IO/Ports/SerialPort.Unix.cs | 2 +- .../System/IO/Ports/SerialStream.Windows.cs | 2 +- .../Net/Http/Json/HttpClientJsonExtensions.cs | 2 +- .../src/System/Net/Http/Json/JsonContent.cs | 2 +- .../Net/Http/Json/LengthLimitReadStream.cs | 2 +- .../HttpClientJsonExtensionsTests.cs | 4 +- .../Net/Http/NoWriteNoSeekStreamContent.cs | 2 +- .../System/Net/Http/WinHttpResponseStream.cs | 2 +- .../System/Net/Http/WinHttpTrailersHelper.cs | 4 +- .../FunctionalTests/PlatformHandlerTest.cs | 4 +- .../HttpClientHandlerTest.RequestRetry.cs | 2 +- ...lientHandlerTestBase.SocketsHttpHandler.cs | 2 +- .../System.Numerics.Tensors/tests/Helpers.cs | 6 +- .../Context/Delegation/DelegatingAssembly.cs | 6 +- .../Context/Delegation/DelegatingModule.cs | 4 +- .../tests/DispatchProxyTests.cs | 2 +- .../Internal/Utilities/BitArithmetic.cs | 6 +- .../Internal/Utilities/BlobUtilities.cs | 6 +- .../Internal/Utilities/DecimalUtilities.cs | 4 +- .../Utilities/ImmutableMemoryStream.cs | 2 +- .../ReadOnlyUnmanagedMemoryStream.cs | 2 +- .../Internal/Utilities/StreamExtensions.cs | 2 +- .../PEReader.EmbeddedPortablePdb.cs | 2 +- .../Decoding/CustomAttributeDecoderTests.cs | 2 +- .../tests/Metadata/TypeNameTests.cs | 4 +- .../Assemblies/RoAssembly.Modules.cs | 4 +- .../TypeLoading/Assemblies/RoAssembly.cs | 6 +- .../Reflection/TypeLoading/General/Helpers.cs | 2 +- .../TypeLoading/Modules/RoModule.cs | 4 +- .../TypeLoading/Types/RoModifiedType.cs | 2 +- .../tests/src/TestUtils/NetStandardBridge.cs | 2 +- .../Configuration/CachingSectionGroup.cs | 2 +- .../Configuration/MemoryCacheElement.cs | 2 +- .../Configuration/MemoryCacheSection.cs | 2 +- .../MemoryCacheSettingsCollection.cs | 2 +- .../src/System/Runtime/Caching/Counters.cs | 4 +- .../Caching/FileChangeNotificationSystem.cs | 2 +- .../Runtime/Caching/HostFileChangeMonitor.cs | 2 +- .../src/System/Runtime/Caching/MemoryCache.cs | 2 +- .../Runtime/Caching/MemoryCacheStatistics.cs | 4 +- .../Runtime/Caching/MemoryCacheStore.cs | 2 +- .../Caching/PhysicalMemoryMonitor.Unix.cs | 2 +- .../System.Runtime.Caching/CountersTest.cs | 4 +- .../Marshal/StringMarshalingTests.cs | 2 +- .../tests/BinaryFormatterTestData.cs | 6 +- .../tests/EqualityExtensions.cs | 4 +- .../ResourceManagerTests.cs | 8 +- .../ValueTupleTests.cs | 22 +- .../Cryptography/Cose/CoseSignature.cs | 2 +- .../tests/CoseTestHelpers.cs | 2 +- .../ref/System.Security.Cryptography.Pkcs.cs | 4 +- .../Pal/AnyOS/ManagedPal.KeyTrans.cs | 2 +- .../Cryptography/Pal/AnyOS/ManagedPal.cs | 2 +- .../Pal/Windows/PkcsPalWindows.cs | 2 +- .../src/Internal/Cryptography/PkcsHelpers.cs | 6 +- .../Cryptography/Pkcs/CmsSignature.DSA.cs | 10 +- .../Cryptography/Pkcs/CmsSignature.ECDsa.cs | 12 +- .../Cryptography/Pkcs/CmsSignature.RSA.cs | 14 +- .../Cryptography/Pkcs/CmsSignature.cs | 8 +- .../Security/Cryptography/Pkcs/CmsSigner.cs | 2 +- .../Security/Cryptography/Pkcs/SignedCms.cs | 2 +- .../Security/Cryptography/Pkcs/SignerInfo.cs | 4 +- .../tests/CertLoader.cs | 4 +- .../tests/EnvelopedCms/DecryptTests.cs | 2 +- .../tests/EnvelopedCms/StateTests.cs | 8 +- .../tests/Pkcs12/CertBagTests.cs | 2 +- .../tests/Pkcs12/Pkcs12SafeBagTests.cs | 2 +- .../tests/SignedCms/CmsSignerTests.cs | 2 +- .../tests/SignedCms/SignedCmsTests.cs | 10 +- .../SignedCms/SignedCmsWholeDocumentTests.cs | 20 +- .../tests/SignedCms/SignerInfoTests.cs | 10 +- .../Cryptography/Xml/CryptoHelpers.cs | 4 +- .../Xml/DSASignatureDescription.cs | 4 +- .../Xml/RSAPKCS1SignatureDescription.cs | 6 +- .../System/Security/Cryptography/Xml/Utils.cs | 2 +- .../tests/ReferenceTest.cs | 4 +- .../tests/Samples/SigningVerifyingX509Cert.cs | 2 +- .../tests/SignedXmlTest.cs | 2 +- .../tests/TestHelpers.cs | 2 +- .../tests/AsymmetricAlgorithm/Trivial.cs | 2 +- .../tests/DefaultDSAProvider.cs | 2 +- .../tests/DefaultECDsaProvider.cs | 2 +- .../tests/DefaultRSAProvider.cs | 2 +- .../CertificateRequestUsageTests.cs | 2 +- .../tests/X509Certificates/X509StoreTests.cs | 2 +- .../System.Security.Permissions.Forwards.cs | 2 +- .../ref/System.Security.Permissions.cs | 270 +++++++++--------- .../System.Security.Permissions.netcoreapp.cs | 2 +- .../Configuration/ConfigurationPermission.cs | 2 +- .../ConfigurationPermissionAttribute.cs | 2 +- .../System/Data/Common/DBDataPermission.cs | 2 +- .../Data/Common/DBDataPermissionAttribute.cs | 2 +- .../src/System/Data/Odbc/OdbcPermission.cs | 2 +- .../Data/Odbc/OdbcPermissionAttribute.cs | 2 +- .../src/System/Data/OleDb/OleDbPermission.cs | 2 +- .../Data/OleDb/OleDbPermissionAttribute.cs | 2 +- .../Data/OracleClient/OraclePermission.cs | 2 +- .../OracleClient/OraclePermissionAttribute.cs | 2 +- .../Data/SqlClient/SqlClientPermission.cs | 2 +- .../SqlClient/SqlClientPermissionAttribute.cs | 2 +- .../System/Diagnostics/EventLogPermission.cs | 2 +- .../EventLogPermissionAttribute.cs | 2 +- .../PerformanceCounterPermission.cs | 2 +- .../PerformanceCounterPermissionAttribute.cs | 2 +- .../Drawing/Printing/PrintingPermission.cs | 2 +- .../Printing/PrintingPermissionAttribute.cs | 2 +- .../src/System/Net/DnsPermission.cs | 2 +- .../src/System/Net/DnsPermissionAttribute.cs | 2 +- .../src/System/Net/Mail/SmtpPermission.cs | 2 +- .../Net/Mail/SmtpPermissionAttribute.cs | 2 +- .../NetworkInformationPermission.cs | 2 +- .../NetworkInformationPermissionAttribute.cs | 2 +- .../PeerCollaborationPermission.cs | 2 +- .../PeerCollaborationPermissionAttribute.cs | 2 +- .../System/Net/PeerToPeer/PnrpPermission.cs | 2 +- .../Net/PeerToPeer/PnrpPermissionAttribute.cs | 2 +- .../src/System/Net/SocketPermission.cs | 2 +- .../System/Net/SocketPermissionAttribute.cs | 2 +- .../src/System/Net/WebPermission.cs | 2 +- .../src/System/Net/WebPermissionAttribute.cs | 2 +- .../System/Security/CodeAccessPermission.cs | 2 +- .../Security/HostProtectionException.cs | 2 +- .../src/System/Security/NamedPermissionSet.cs | 2 +- .../Permissions/DataProtectionPermission.cs | 2 +- .../DataProtectionPermissionAttribute.cs | 2 +- .../DataProtectionPermissionFlags.cs | 2 +- .../Permissions/EnvironmentPermission.cs | 2 +- .../EnvironmentPermissionAccess.cs | 2 +- .../EnvironmentPermissionAttribute.cs | 2 +- .../Permissions/FileDialogPermission.cs | 2 +- .../Permissions/FileDialogPermissionAccess.cs | 2 +- .../FileDialogPermissionAttribute.cs | 2 +- .../Security/Permissions/FileIOPermission.cs | 2 +- .../Permissions/FileIOPermissionAccess.cs | 2 +- .../Permissions/FileIOPermissionAttribute.cs | 2 +- .../Permissions/GacIdentityPermission.cs | 2 +- .../GacIdentityPermissionAttribute.cs | 2 +- .../Permissions/HostProtectionAttribute.cs | 2 +- .../Permissions/HostProtectionResource.cs | 2 +- .../Permissions/IUnrestrictedPermission.cs | 2 +- .../Permissions/IsolatedStorageContainment.cs | 2 +- .../IsolatedStorageFilePermission.cs | 2 +- .../IsolatedStorageFilePermissionAttribute.cs | 2 +- .../Permissions/IsolatedStoragePermission.cs | 2 +- .../IsolatedStoragePermissionAttribute.cs | 2 +- .../Permissions/KeyContainerPermission.cs | 2 +- .../KeyContainerPermissionAccessEntry.cs | 2 +- ...ontainerPermissionAccessEntryCollection.cs | 2 +- ...ontainerPermissionAccessEntryEnumerator.cs | 2 +- .../KeyContainerPermissionAttribute.cs | 2 +- .../KeyContainerPermissionFlags.cs | 2 +- .../Security/Permissions/MediaPermission.cs | 10 +- .../Permissions/PermissionSetAttribute.cs | 2 +- .../Permissions/PrincipalPermission.cs | 2 +- .../PrincipalPermissionAttribute.cs | 4 +- .../PublisherIdentityPermission.cs | 2 +- .../PublisherIdentityPermissionAttribute.cs | 2 +- .../Permissions/ReflectionPermission.cs | 2 +- .../ReflectionPermissionAttribute.cs | 2 +- .../Permissions/ReflectionPermissionFlag.cs | 2 +- .../Permissions/RegistryPermission.cs | 2 +- .../Permissions/RegistryPermissionAccess.cs | 2 +- .../RegistryPermissionAttribute.cs | 2 +- .../Permissions/ResourcePermissionBase.cs | 2 +- .../ResourcePermissionBaseEntry.cs | 2 +- .../Permissions/SecurityPermission.cs | 2 +- .../Permissions/SiteIdentityPermission.cs | 2 +- .../SiteIdentityPermissionAttribute.cs | 2 +- .../Security/Permissions/StorePermission.cs | 2 +- .../Permissions/StorePermissionAttribute.cs | 2 +- .../Permissions/StorePermissionFlags.cs | 2 +- .../StrongNameIdentityPermission.cs | 2 +- .../StrongNameIdentityPermissionAttribute.cs | 2 +- .../Permissions/StrongNamePublicKeyBlob.cs | 2 +- .../Permissions/TypeDescriptorPermission.cs | 2 +- .../TypeDescriptorPermissionAttribute.cs | 2 +- .../TypeDescriptorPermissionFlags.cs | 2 +- .../Security/Permissions/UIPermission.cs | 2 +- .../Permissions/UIPermissionAttribute.cs | 2 +- .../Permissions/UIPermissionClipboard.cs | 2 +- .../Permissions/UIPermissionWindow.cs | 2 +- .../Permissions/UrlIdentityPermission.cs | 2 +- .../UrlIdentityPermissionAttribute.cs | 2 +- .../Permissions/WebBrowserPermission.cs | 6 +- .../Permissions/ZoneIdentityPermission.cs | 2 +- .../ZoneIdentityPermissionAttribute.cs | 2 +- .../Security/Policy/ApplicationTrust.cs | 4 +- .../System/Security/Policy/FileCodeGroup.cs | 2 +- .../System/Security/Policy/GacInstalled.cs | 2 +- .../Policy/IIdentityPermissionFactory.cs | 2 +- .../src/System/Security/Policy/PolicyLevel.cs | 10 +- .../System/Security/Policy/PolicyStatement.cs | 6 +- .../src/System/Security/Policy/Publisher.cs | 2 +- .../src/System/Security/Policy/Site.cs | 2 +- .../src/System/Security/Policy/StrongName.cs | 2 +- .../Policy/StrongNameMembershipCondition.cs | 2 +- .../src/System/Security/Policy/Url.cs | 2 +- .../src/System/Security/Policy/Zone.cs | 2 +- .../src/System/Security/SecurityContext.cs | 2 +- .../src/System/Security/SecurityManager.cs | 2 +- .../ServiceControllerPermission.cs | 2 +- .../ServiceControllerPermissionAttribute.cs | 2 +- .../DistributedTransactionPermission.cs | 2 +- ...stributedTransactionPermissionAttribute.cs | 2 +- .../src/System/Web/AspNetHostingPermission.cs | 2 +- .../Web/AspNetHostingPermissionAttribute.cs | 2 +- .../Xaml/Permissions/XamlLoadPermission.cs | 2 +- .../Syndication/DateTimeHelper.cs | 2 +- .../src/System/ServiceProcess/ServiceBase.cs | 2 +- .../ServiceProcess/ServiceController.cs | 2 +- .../SessionChangeDescription.cs | 2 +- .../tests/ServiceBaseTests.cs | 2 +- .../src/System/IO/TextWriterExtensions.cs | 4 +- .../Web/AllowedBmpCodePointsBitmap.cs | 4 +- .../Web/OptimizedInboxTextEncoder.Ascii.cs | 4 +- .../Web/OptimizedInboxTextEncoder.cs | 8 +- .../System/Text/Encodings/Web/TextEncoder.cs | 4 +- .../Common/JsonCamelCaseNamingPolicy.cs | 2 +- .../System.Text.Json/Common/JsonHelpers.cs | 2 +- .../src/System/ReflectionExtensions.cs | 2 +- .../Text/Json/Document/JsonDocument.Parse.cs | 6 +- .../src/System/Text/Json/JsonHelpers.Date.cs | 2 +- .../src/System/Text/Json/JsonHelpers.cs | 12 +- .../src/System/Text/Json/Nodes/JsonArray.cs | 2 +- .../Reader/JsonReaderHelper.Unescaping.cs | 16 +- .../Text/Json/Reader/JsonReaderHelper.cs | 2 +- .../IEnumerableConverterFactoryHelpers.cs | 2 +- .../Converters/Value/CharConverter.cs | 4 +- .../Converters/Value/EnumConverter.cs | 20 +- .../Converters/Value/VersionConverter.cs | 8 +- .../Json/Serialization/JsonConverterOfT.cs | 4 +- .../JsonSerializerOptions.Caching.cs | 8 +- .../DefaultJsonTypeInfoResolver.Converters.cs | 2 +- .../DefaultJsonTypeInfoResolver.Helpers.cs | 2 +- .../JsonMetadataServices.Converters.cs | 4 +- .../Metadata/JsonPropertyInfo.cs | 2 +- .../Metadata/JsonPropertyInfoOfT.cs | 2 +- .../Serialization/Metadata/JsonTypeInfo.cs | 2 +- .../Metadata/JsonTypeInfoOfT.WriteHelpers.cs | 6 +- ...flectionEmitCachingMemberAccessor.Cache.cs | 4 +- .../ReflectionEmitCachingMemberAccessor.cs | 2 +- .../Metadata/ReflectionEmitMemberAccessor.cs | 2 +- .../Json/Serialization/ReadBufferState.cs | 4 +- .../Text/Json/ThrowHelper.Serialization.cs | 2 +- .../Json/Writer/JsonWriterHelper.Escaping.cs | 8 +- .../Text/Json/Writer/JsonWriterHelper.cs | 4 +- .../Utf8JsonWriter.WriteValues.Double.cs | 2 +- .../Utf8JsonWriter.WriteValues.Float.cs | 2 +- .../System/Text/Json/Writer/Utf8JsonWriter.cs | 6 +- ...CollectionTests.Dictionary.NonStringKey.cs | 4 +- .../tests/Common/JsonNumberTestData.cs | 8 +- .../tests/Common/JsonTestHelper.cs | 4 +- .../tests/Common/NumberHandlingTests.cs | 46 +-- .../tests/Common/Utf8MemoryStream.cs | 2 +- .../ContextClasses.cs | 2 +- .../MetadataAndSerializationContextTests.cs | 2 +- .../MetadataContextTests.cs | 4 +- .../MixedModeContextTests.cs | 2 +- .../RealWorldContextTests.cs | 2 +- .../Serialization/NumberHandlingTests.cs | 4 +- .../SerializationContextTests.cs | 8 +- .../CompilationHelper.cs | 8 +- .../JsonSourceGeneratorTests.cs | 4 +- .../System.Text.Json.Tests/JsonTestHelper.cs | 2 +- ...stomConverterTests.Dynamic.Sample.Tests.cs | 2 +- .../Serialization/Value.ReadTests.cs | 6 +- .../Serialization/Value.WriteTests.cs | 2 +- .../gen/RegexGenerator.Emitter.cs | 2 +- .../Regex.KnownPattern.Tests.cs | 2 +- .../RateLimiting/ConcurrencyLimiter.cs | 2 +- .../RateLimiting/FixedWindowRateLimiter.cs | 2 +- .../RateLimiting/SlidingWindowRateLimiter.cs | 2 +- .../RateLimiting/TokenBucketRateLimiter.cs | 2 +- src/tasks/Common/Utils.cs | 8 +- .../WebcilReader.cs | 2 +- .../Common/CoreCLRTestLibrary/Utilities.cs | 2 +- .../IpcUnixDomainSocketEndPoint.cs | 2 +- .../illink/external/Mono.Options/Options.cs | 2 +- .../NullableAttributes.cs | 4 +- .../Helpers/PlatformAssemblies.cs | 2 +- ...erDisplayAttributeOnAssemblyUsingTarget.cs | 2 +- ...semblyUsingTargetTypeNameInSameAssembly.cs | 2 +- ...getTypeNameOfGenericTypeInOtherAssembly.cs | 2 +- ...ggerDisplayAttributeOnTypeThatIsNotUsed.cs | 2 +- ...ypeWithCallToExtensionMethodOnFieldType.cs | 2 +- ...isplayOnTypeWithCallToMethodOnFieldType.cs | 2 +- .../CoreLibraryAssemblyAttributesAreKept.cs | 2 +- ...braryUnusedAssemblyAttributesAreRemoved.cs | 2 +- ...oreLibraryUsedAssemblyAttributesAreKept.cs | 2 +- ...ceCastableImplementationAttributeIsKept.cs | 6 +- .../DynamicDependencyFromAttributeXml.cs | 2 +- ...FromAttributeXmlOnNonReferencedAssembly.cs | 2 +- .../LinkAttributes/LinkerAttributeRemoval.cs | 2 +- .../ConstructorUsedViaReflection.cs | 4 +- .../Reflection/MethodUsedViaReflection.cs | 4 +- .../TypeForwarding/TypeForwardersRewrite.cs | 4 +- .../UnreachableBlock/ComplexConditions.cs | 4 +- .../UnreachableBlock/SizeOfInConditions.cs | 2 +- .../LinkedOtherIncludedLibrary.cs | 2 +- ...inkedOtherIncludedLibraryNoInstanceCtor.cs | 2 +- ...CanGenerateWarningSuppressionFileCSharp.cs | 2 +- .../CanGenerateWarningSuppressionFileXml.cs | 2 +- .../Warnings/Individual/WarningsAreSorted.cs | 2 +- .../SuppressWarningsInAssembly.cs | 2 +- .../SuppressWarningsInCopyAssembly.cs | 2 +- .../SuppressWarningsInMembersAndTypes.cs | 2 +- ...essWarningsInMembersAndTypesUsingTarget.cs | 2 +- .../SuppressWarningsInModule.cs | 2 +- .../Mono.Linker.Tests/TestCases/TestSuites.cs | 2 +- .../TestCasesRunner/ILCompiler.cs | 4 +- .../TestCaseCompilationMetadataProvider.cs | 2 +- .../TestCasesRunner/TestCaseCompiler.cs | 10 +- .../TrimmingArgumentBuilder.cs | 4 +- 423 files changed, 853 insertions(+), 853 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ILInputCompiler.cs b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ILInputCompiler.cs index e95197b669c94f..80a48c2da1695e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ILInputCompiler.cs +++ b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ILInputCompiler.cs @@ -45,7 +45,7 @@ protected virtual void SetupProcess (Process process, CompilerOptions options) private static string BuildArguments (CompilerOptions options) { var args = new StringBuilder (); -#if NETCOREAPP +#if NET args.Append (options.OutputPath.ExtensionWithDot == ".dll" ? "-dll" : "-exe"); args.Append ($" -out:{options.OutputPath.InQuotes ()}"); #else @@ -58,7 +58,7 @@ private static string BuildArguments (CompilerOptions options) protected virtual NPath LocateIlasm () { -#if NETCOREAPP +#if NET var extension = RuntimeInformation.IsOSPlatform (OSPlatform.Windows) ? ".exe" : ""; var toolsDir = (string) AppContext.GetData ("Mono.Linker.Tests.ILToolsDir")!; diff --git a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs index 4ff90c22300d4c..825663ac8bdae1 100644 --- a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs +++ b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs @@ -77,7 +77,7 @@ public virtual IEnumerable GetDefines () yield return "WIN32"; if (Characteristics.HasFlag (TestRunCharacteristics.TargetingNetCore)) - yield return "NETCOREAPP"; + yield return "NET"; if (Characteristics.HasFlag (TestRunCharacteristics.SupportsDefaultInterfaceMethods)) yield return "SUPPORTS_DEFAULT_INTERFACE_METHODS"; diff --git a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TestCaseCompiler.cs b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TestCaseCompiler.cs index d2b637de124e6f..b20c16631302c2 100644 --- a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TestCaseCompiler.cs +++ b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TestCaseCompiler.cs @@ -9,7 +9,7 @@ using System.Text; using Mono.Linker.Tests.Extensions; using Xunit; -#if NETCOREAPP +#if NET using System.Runtime.InteropServices; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Emit; @@ -190,7 +190,7 @@ protected static NPath MakeSupportingAssemblyReferencePathAbsolute (NPath output if (Path.IsPathRooted (referenceFileName)) return referenceFileName.ToNPath (); -#if NETCOREAPP +#if NET if (referenceFileName.StartsWith ("System.", StringComparison.Ordinal) || referenceFileName.StartsWith ("Mono.", StringComparison.Ordinal) || referenceFileName.StartsWith ("Microsoft.", StringComparison.Ordinal) || @@ -224,14 +224,14 @@ protected NPath CompileAssembly (CompilerOptions options) protected virtual NPath CompileCSharpAssemblyWithDefaultCompiler (CompilerOptions options) { -#if NETCOREAPP +#if NET return CompileCSharpAssemblyWithRoslyn (options); #else return CompileCSharpAssemblyWithCsc (options); #endif } -#if NETCOREAPP +#if NET protected virtual NPath CompileCSharpAssemblyWithRoslyn (CompilerOptions options) { var languageVersion = LanguageVersion.Default; @@ -331,7 +331,7 @@ protected virtual NPath CompileCSharpAssemblyWithRoslyn (CompilerOptions options protected virtual NPath CompileCSharpAssemblyWithCsc (CompilerOptions options) { -#if NETCOREAPP +#if NET return CompileCSharpAssemblyWithRoslyn (options); #else return CompileCSharpAssemblyWithExternalCompiler (LocateCscExecutable (), options, "/shared "); diff --git a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs index 1d075aeffeb354..ebcad66b5e0c48 100644 --- a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs @@ -217,7 +217,7 @@ public virtual void ProcessOptions (TestCaseLinkerOptions options) IgnoreLinkAttributes (options.IgnoreLinkAttributes); -#if !NETCOREAPP +#if !NET if (!string.IsNullOrEmpty (options.Il8n)) AddIl8n (options.Il8n); #endif diff --git a/src/libraries/Common/src/Extensions/ChangeCallbackRegistrar.cs b/src/libraries/Common/src/Extensions/ChangeCallbackRegistrar.cs index eecd1fa8c1e515..aa7899a64136e3 100644 --- a/src/libraries/Common/src/Extensions/ChangeCallbackRegistrar.cs +++ b/src/libraries/Common/src/Extensions/ChangeCallbackRegistrar.cs @@ -21,7 +21,7 @@ internal static class ChangeCallbackRegistrar /// The registration. internal static IDisposable UnsafeRegisterChangeCallback(Action callback, object? state, CancellationToken token, Action onFailure, T onFailureState) { -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 try { return token.UnsafeRegister(callback, state); diff --git a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Properties.cs b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Properties.cs index 41c079d5ad144e..ec001c0b55a93d 100644 --- a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Properties.cs +++ b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Properties.cs @@ -56,7 +56,7 @@ internal static unsafe ErrorCode NCryptGetIntProperty(SafeNCryptHandle hObject, { fixed (int* pResult = &result) { -#if NETSTANDARD || NETCOREAPP +#if NETSTANDARD || NET Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); #endif diff --git a/src/libraries/Common/src/System/HashCodeRandomization.cs b/src/libraries/Common/src/System/HashCodeRandomization.cs index 16cd6cb577c052..8a7273e51eaeb1 100644 --- a/src/libraries/Common/src/System/HashCodeRandomization.cs +++ b/src/libraries/Common/src/System/HashCodeRandomization.cs @@ -16,7 +16,7 @@ internal static class HashCodeRandomization { public static int GetRandomizedOrdinalHashCode(this string value) { -#if NETCOREAPP +#if NET // In .NET Core, string hash codes are already randomized. return value.GetHashCode(); diff --git a/src/libraries/Common/src/System/Reflection/AssemblyNameFormatter.cs b/src/libraries/Common/src/System/Reflection/AssemblyNameFormatter.cs index 9d5eeebc85a6d0..b4fbdca1e9091e 100644 --- a/src/libraries/Common/src/System/Reflection/AssemblyNameFormatter.cs +++ b/src/libraries/Common/src/System/Reflection/AssemblyNameFormatter.cs @@ -129,7 +129,7 @@ private static void AppendQuoted(this ref ValueStringBuilder vsb, string s) vsb.Append(quoteChar); } -#if !NETCOREAPP +#if !NET private static void AppendSpanFormattable(this ref ValueStringBuilder vsb, ushort value) { vsb.Append(value.ToString()); diff --git a/src/libraries/Common/src/System/Resources/ResourceWriter.cs b/src/libraries/Common/src/System/Resources/ResourceWriter.cs index 1f93de2776395b..81a70e7ae2f521 100644 --- a/src/libraries/Common/src/System/Resources/ResourceWriter.cs +++ b/src/libraries/Common/src/System/Resources/ResourceWriter.cs @@ -488,7 +488,7 @@ private static ResourceTypeCode FindTypeCode(object? value, List types) if (typeName.StartsWith("ResourceTypeCode.", StringComparison.Ordinal)) { typeName = typeName.Substring(17); // Remove through '.' -#if NETCOREAPP +#if NET ResourceTypeCode typeCode = Enum.Parse(typeName); #else ResourceTypeCode typeCode = (ResourceTypeCode)Enum.Parse(typeof(ResourceTypeCode), typeName); diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs b/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs index f299c936232547..38e60abcebc640 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs @@ -63,7 +63,7 @@ internal bool VerifyMac( throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } -#if NETCOREAPP +#if NET Debug.Assert(expectedOutputSize <= 64); // SHA512 is the largest digest size we know about Span derived = stackalloc byte[expectedOutputSize]; #else diff --git a/src/libraries/Common/src/System/Security/Cryptography/CryptoPool.cs b/src/libraries/Common/src/System/Security/Cryptography/CryptoPool.cs index dd3a37c32237bf..e4b71ded239f2d 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/CryptoPool.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/CryptoPool.cs @@ -27,7 +27,7 @@ internal static void Return(byte[] array, int clearSize = ClearAll) if (!clearWholeArray && clearSize != 0) { -#if (NETCOREAPP || NETSTANDARD2_1) && !CP_NO_ZEROMEMORY +#if (NET || NETSTANDARD2_1) && !CP_NO_ZEROMEMORY CryptographicOperations.ZeroMemory(array.AsSpan(0, clearSize)); #else Array.Clear(array, 0, clearSize); diff --git a/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs b/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs index 0071c345d1d20a..462e4d26a8f64d 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs @@ -12,13 +12,13 @@ internal static partial class Helpers { [UnsupportedOSPlatformGuard("browser")] internal static bool HasSymmetricEncryption { get; } = -#if NETCOREAPP +#if NET !OperatingSystem.IsBrowser(); #else true; #endif -#if NETCOREAPP +#if NET [UnsupportedOSPlatformGuard("ios")] [UnsupportedOSPlatformGuard("tvos")] public static bool IsDSASupported => !OperatingSystem.IsIOS() && !OperatingSystem.IsTvOS(); @@ -26,7 +26,7 @@ internal static partial class Helpers public static bool IsDSASupported => true; #endif -#if NETCOREAPP +#if NET [UnsupportedOSPlatformGuard("android")] [UnsupportedOSPlatformGuard("browser")] public static bool IsRC2Supported => !OperatingSystem.IsAndroid() && !OperatingSystem.IsBrowser(); @@ -36,7 +36,7 @@ internal static partial class Helpers [UnsupportedOSPlatformGuard("browser")] internal static bool HasMD5 { get; } = -#if NETCOREAPP +#if NET !OperatingSystem.IsBrowser(); #else true; diff --git a/src/libraries/Common/src/System/Text/Json/PooledByteBufferWriter.cs b/src/libraries/Common/src/System/Text/Json/PooledByteBufferWriter.cs index 75424aed0d3cc3..51e1cccb43e305 100644 --- a/src/libraries/Common/src/System/Text/Json/PooledByteBufferWriter.cs +++ b/src/libraries/Common/src/System/Text/Json/PooledByteBufferWriter.cs @@ -27,7 +27,7 @@ internal sealed class PooledByteBufferWriter : IBufferWriter, IDisposable private PooledByteBufferWriter() { -#if NETCOREAPP +#if NET // Ensure we are in sync with the Array.MaxLength implementation. Debug.Assert(MaximumBufferSize == Array.MaxLength); #endif @@ -147,7 +147,7 @@ public Span GetSpan(int sizeHint = MinimumBufferSize) return _rentedBuffer.AsSpan(_index); } -#if NETCOREAPP +#if NET internal ValueTask WriteToStreamAsync(Stream destination, CancellationToken cancellationToken) { return destination.WriteAsync(WrittenMemory, cancellationToken); diff --git a/src/libraries/Common/src/System/Text/ValueStringBuilder.cs b/src/libraries/Common/src/System/Text/ValueStringBuilder.cs index a0844b04664248..14aa77db3e57b0 100644 --- a/src/libraries/Common/src/System/Text/ValueStringBuilder.cs +++ b/src/libraries/Common/src/System/Text/ValueStringBuilder.cs @@ -161,7 +161,7 @@ public void Insert(int index, string? s) int remaining = _pos - index; _chars.Slice(index, remaining).CopyTo(_chars.Slice(index + count)); s -#if !NETCOREAPP +#if !NET .AsSpan() #endif .CopyTo(_chars.Slice(index)); @@ -213,7 +213,7 @@ private void AppendSlow(string s) } s -#if !NETCOREAPP +#if !NET .AsSpan() #endif .CopyTo(_chars.Slice(pos)); diff --git a/src/libraries/Common/tests/SourceGenerators/RoslynTestUtils.cs b/src/libraries/Common/tests/SourceGenerators/RoslynTestUtils.cs index e67289721d8af9..e1c53d3b8aa16e 100644 --- a/src/libraries/Common/tests/SourceGenerators/RoslynTestUtils.cs +++ b/src/libraries/Common/tests/SourceGenerators/RoslynTestUtils.cs @@ -349,7 +349,7 @@ private static async Task RecreateDocumentAsync(Document document) } private static string ReplaceLineEndings(string text) => -#if NETCOREAPP +#if NET text.ReplaceLineEndings("\n"); #else text.Replace("\r\n", "\n"); diff --git a/src/libraries/Common/tests/System/Collections/TestBase.Generic.cs b/src/libraries/Common/tests/System/Collections/TestBase.Generic.cs index 73d382893d2898..0a22540b6588b9 100644 --- a/src/libraries/Common/tests/System/Collections/TestBase.Generic.cs +++ b/src/libraries/Common/tests/System/Collections/TestBase.Generic.cs @@ -255,7 +255,7 @@ protected IEnumerable CreateHashSet(IEnumerable enumerableToMatchTo, int c return set; } -#if NETCOREAPP +#if NET /// /// Create a HashSet with a specific initial capacity and fill it with a specific number of elements. /// diff --git a/src/libraries/Common/tests/System/IO/Compression/ZipTestHelper.cs b/src/libraries/Common/tests/System/IO/Compression/ZipTestHelper.cs index 6d194788762fa4..9666a16e2fb3ce 100644 --- a/src/libraries/Common/tests/System/IO/Compression/ZipTestHelper.cs +++ b/src/libraries/Common/tests/System/IO/Compression/ZipTestHelper.cs @@ -233,7 +233,7 @@ public static void IsZipSameAsDir(Stream archiveFile, string directory, ZipArchi using (Stream entrystream = entry.Open()) { ReadAllBytes(entrystream, buffer, 0, buffer.Length); -#if NETCOREAPP +#if NET uint zipcrc = entry.Crc32; Assert.Equal(CRC.CalculateCRC(buffer), zipcrc); #endif diff --git a/src/libraries/Common/tests/System/Net/Http/ByteAtATimeContent.cs b/src/libraries/Common/tests/System/Net/Http/ByteAtATimeContent.cs index d1b54ece613db1..e0407d918acc4d 100644 --- a/src/libraries/Common/tests/System/Net/Http/ByteAtATimeContent.cs +++ b/src/libraries/Common/tests/System/Net/Http/ByteAtATimeContent.cs @@ -24,7 +24,7 @@ public ByteAtATimeContent(int length, Task waitToSend, TaskCompletionSource SerializeToStreamAsync(stream, context).GetAwaiter().GetResult(); #endif diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs index 4da9edc2ca2147..f45206e9941dfe 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs @@ -200,7 +200,7 @@ await server.AcceptConnectionAsync(async connection => } [Theory] -#if NETCOREAPP +#if NET [InlineData(DecompressionMethods.Brotli, "br", "")] [InlineData(DecompressionMethods.Brotli, "br", "br")] [InlineData(DecompressionMethods.Brotli, "br", "gzip")] @@ -264,7 +264,7 @@ await LoopbackServer.CreateServerAsync(async (server, url) => } [Theory] -#if NETCOREAPP +#if NET [InlineData(DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.Brotli, "gzip; q=1.0, deflate; q=1.0, br; q=1.0", "")] #endif [InlineData(DecompressionMethods.GZip | DecompressionMethods.Deflate, "gzip; q=1.0, deflate; q=1.0", "")] diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTestBase.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTestBase.cs index fdf301a809b863..689a6d6821eb62 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTestBase.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTestBase.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; -#if !NETCOREAPP +#if !NET using System.Diagnostics; #endif using System.IO; @@ -90,7 +90,7 @@ public VersionCheckerHttpHandler(HttpMessageHandler innerHandler, Version expect _expectedVersion = expectedVersion; } -#if NETCOREAPP +#if NET protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) { if (request.Version != _expectedVersion) @@ -138,7 +138,7 @@ public static Task SendAsync(this HttpClient client, bool a } else { -#if NETCOREAPP +#if NET // Note that the sync call must be done on a different thread because it blocks until the server replies. // However, the server-side of the request handling is in many cases invoked after the client, thus deadlocking the test. return Task.Run(() => client.Send(request, completionOption, cancellationToken)); @@ -159,7 +159,7 @@ public static Task SendAsync(this HttpMessageInvoker invoke } else { -#if NETCOREAPP +#if NET // Note that the sync call must be done on a different thread because it blocks until the server replies. // However, the server-side of the request handling is in many cases invoked after the client, thus deadlocking the test. return Task.Run(() => invoker.Send(request, cancellationToken)); @@ -176,7 +176,7 @@ public static Task ReadAsStreamAsync(this HttpContent content, bool asyn { if (async) { -#if NETCOREAPP +#if NET // No CancellationToken accepting overload on NETFX. return content.ReadAsStreamAsync(cancellationToken); #else @@ -186,7 +186,7 @@ public static Task ReadAsStreamAsync(this HttpContent content, bool asyn } else { -#if NETCOREAPP +#if NET return Task.FromResult(content.ReadAsStream(cancellationToken)); #else // Framework won't ever have the sync API. @@ -199,7 +199,7 @@ public static Task ReadAsStreamAsync(this HttpContent content, bool asyn public static Task GetByteArrayAsync(this HttpClient client, bool async, bool useCopyTo, Uri uri) { -#if NETCOREAPP +#if NET return Task.Run(async () => { var m = new HttpRequestMessage(HttpMethod.Get, uri); diff --git a/src/libraries/Common/tests/System/Net/Http/HttpMessageHandlerLoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/HttpMessageHandlerLoopbackServer.cs index 9d9d412511ac6e..4b6a326cf6f585 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpMessageHandlerLoopbackServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpMessageHandlerLoopbackServer.cs @@ -60,7 +60,7 @@ public LoopbackServerHttpMessageHandler(Func AllowAllCertificates = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; #else public static Func AllowAllCertificates = (_, __, ___, ____) => true; @@ -149,7 +149,7 @@ public static X509Certificate2 CreateServerSelfSignedCertificate(string name = " } } -#if NETCOREAPP +#if NET public static SocketsHttpHandler CreateSocketsHttpHandler(bool allowAllCertificates = false) { var handler = new SocketsHttpHandler(); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs index cd8bf922227cd6..6ad596a040c4b3 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs @@ -75,7 +75,7 @@ public void InvalidArrayArguments_Throws() } } -#if NETCOREAPP +#if NET [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst, "Not supported on Browser/iOS/tvOS/MacCatalyst")] public sealed class DSASignVerify_Span : DSASignVerify { diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/CurveDef.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/CurveDef.cs index a49b2c3329b725..b0c5823145a87b 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/CurveDef.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/CurveDef.cs @@ -5,7 +5,7 @@ namespace System.Security.Cryptography.Tests { public class CurveDef { -#if NETCOREAPP +#if NET public CurveDef() { } public ECCurve Curve; public ECCurve.ECCurveType CurveType; diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/EccTestBase.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/EccTestBase.cs index 5f9dae4c8fcefb..8cc2391ba8dce8 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/EccTestBase.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/EccTestBase.cs @@ -15,7 +15,7 @@ namespace System.Security.Cryptography.Tests /// public abstract class EccTestBase { -#if NETCOREAPP +#if NET internal const string ECDSA_P224_OID_VALUE = "1.3.132.0.33"; // Also called nistP224 or secP224r1 internal const string ECDSA_P256_OID_VALUE = "1.2.840.10045.3.1.7"; // Also called nistP256, secP256r1 or prime256v1(OpenSsl) internal const string ECDSA_P384_OID_VALUE = "1.3.132.0.34"; // Also called nistP384 or secP384r1 diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanFactory.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanFactory.cs index 84bbea4587eef4..9a2de091ab3b42 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanFactory.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanFactory.cs @@ -7,7 +7,7 @@ public interface IECDiffieHellmanProvider { ECDiffieHellman Create(); ECDiffieHellman Create(int keySize); -#if NETCOREAPP +#if NET ECDiffieHellman Create(ECCurve curve); #endif bool IsCurveValid(Oid oid); @@ -29,7 +29,7 @@ public static ECDiffieHellman Create(int keySize) return s_provider.Create(keySize); } -#if NETCOREAPP +#if NET public static ECDiffieHellman Create(ECCurve curve) { return s_provider.Create(curve); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hash.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hash.cs index 0065092e52aad1..ae8d32b02cc665 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hash.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hash.cs @@ -290,7 +290,7 @@ public static IEnumerable HashDerivationTestCases() } } -#if NETCOREAPP +#if NET [Theory] [MemberData(nameof(HashDerivationTestCases))] public static void HashDerivation_KnownResults( diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hmac.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hmac.cs index f95fb64aafd3a4..575a9d853fe266 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hmac.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hmac.cs @@ -349,7 +349,7 @@ public static IEnumerable HmacDerivationTestCases() } } -#if NETCOREAPP +#if NET [Theory] [MemberData(nameof(HmacDerivationTestCases))] public static void HmacDerivation_KnownResults( diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs index 82f78094bb1000..1c507beee0d8d7 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs @@ -8,7 +8,7 @@ namespace System.Security.Cryptography.EcDiffieHellman.Tests { -#if NETCOREAPP +#if NET public partial class ECDiffieHellmanTests { // On CentOS, secp224r1 (also called nistP224) appears to be disabled. To prevent test failures on that platform, diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.NistValidation.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.NistValidation.cs index d79d8de3edba17..ce07c475bec5fd 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.NistValidation.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.NistValidation.cs @@ -8,7 +8,7 @@ namespace System.Security.Cryptography.EcDiffieHellman.Tests { -#if NETCOREAPP +#if NET // These test cases are from http://csrc.nist.gov/groups/STM/cavp/component-testing.html#test-vectors // SP 800-56A ECCCDH Primitive test vectors // ecccdhtestvectors.zip diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Tls.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Tls.cs index 4bffb87b2dd1da..d8c6e8f0ff0641 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Tls.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Tls.cs @@ -189,7 +189,7 @@ public static IEnumerable TlsDerivationTestCases() }; } -#if NETCOREAPP +#if NET [Theory] [MemberData(nameof(TlsDerivationTestCases))] public static void TlsDerivation_KnownResults(string labelText, string answerHex) diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.cs index 0b41aa08ea28c7..dc7a757d6e5373 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.cs @@ -172,7 +172,7 @@ public static void UseAfterDispose(bool importKey) pubKey.Dispose(); } -#if NETCOREAPP +#if NET private static ECDiffieHellman OpenKnownKey() { ECParameters ecParams = new ECParameters diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaFactory.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaFactory.cs index 59d45d3de99c7e..01e5dfe6701f48 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaFactory.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaFactory.cs @@ -7,7 +7,7 @@ public interface IECDsaProvider { ECDsa Create(); ECDsa Create(int keySize); -#if NETCOREAPP +#if NET ECDsa Create(ECCurve curve); #endif bool IsCurveValid(Oid oid); @@ -26,7 +26,7 @@ public static ECDsa Create(int keySize) return s_provider.Create(keySize); } -#if NETCOREAPP +#if NET public static ECDsa Create(ECCurve curve) { return s_provider.Create(curve); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs index 1925320e66ab5a..058b626c62c89a 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs @@ -15,7 +15,7 @@ public class ECDsaImportExportTests : ECDsaTestsBase internal static bool CanDeriveNewPublicKey { get; } = EcDiffieHellman.Tests.ECDiffieHellmanFactory.CanDeriveNewPublicKey; -#if NETCOREAPP +#if NET [Fact] public static void DiminishedCoordsRoundtrip() { diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaStub.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaStub.cs index b40f4e721a497d..43c44b71a2a288 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaStub.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaStub.cs @@ -30,7 +30,7 @@ protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) throw new NotImplementedException(); } -#if NETCOREAPP +#if NET public override void ImportParameters(ECParameters parameters) { throw new NotImplementedException(); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.NistValidation.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.NistValidation.cs index d0c596935ef092..e0da3f3e75a811 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.NistValidation.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.NistValidation.cs @@ -13,7 +13,7 @@ public abstract partial class ECDsaTests : ECDsaTestsBase // FIPS 186-4 ECDSA test vectors // 186-3ecdsatestvectors.zip // SigGen.txt -#if NETCOREAPP +#if NET [Fact] public void ValidateNistP256Sha256() { diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs index 9da985adfd21fb..9c2e3fc0b44abd 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs @@ -15,7 +15,7 @@ namespace System.Security.Cryptography.EcDsa.Tests [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] public abstract class ECDsaTestsBase : EccTestBase { -#if NETCOREAPP +#if NET internal static void Verify256(ECDsa e, bool expected) { byte[] sig = ("998791331eb2e1f4259297f5d9cb82fa20dec98e1cb0900e6b8f014a406c3d02cbdbf5238bde471c3155fc25565524301429" diff --git a/src/libraries/Common/tests/System/Security/Cryptography/PlatformSupport.cs b/src/libraries/Common/tests/System/Security/Cryptography/PlatformSupport.cs index ae9f09caf23a5d..7be1321023e2bf 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/PlatformSupport.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/PlatformSupport.cs @@ -74,7 +74,7 @@ static bool DetermineAlgorithmFunctional(CngAlgorithm algorithm) // Whether or not the current platform supports RC2 internal static readonly bool IsRC2Supported = !PlatformDetection.IsAndroid; -#if NETCOREAPP +#if NET internal static readonly bool IsAndroidVersionAtLeast31 = OperatingSystem.IsAndroidVersionAtLeast(31); #else internal static readonly bool IsAndroidVersionAtLeast31 = false; diff --git a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs index 0d658dae016cc7..cdab35da2b134b 100644 --- a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs +++ b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs @@ -27,7 +27,7 @@ public static class AssertExtensions public static void ThrowsOnAot(Action action) where T : Exception { -#if NETCOREAPP // Dynamic code is always supported on .NET Framework +#if NET // Dynamic code is always supported on .NET Framework if (!RuntimeFeature.IsDynamicCodeSupported) { Assert.Throws(action); diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index ec6645cec0c319..8aac8589611098 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -125,7 +125,7 @@ public static int SlowRuntimeTimeoutModifier public static bool IsCaseInsensitiveOS => IsWindows || IsOSX || IsMacCatalyst; public static bool IsCaseSensitiveOS => !IsCaseInsensitiveOS; -#if NETCOREAPP +#if NET public static bool FileCreateCaseSensitive => IsCaseSensitiveOS && !RuntimeInformation.RuntimeIdentifier.StartsWith("iossimulator") && !RuntimeInformation.RuntimeIdentifier.StartsWith("tvossimulator"); #else @@ -181,7 +181,7 @@ private static bool GetLinqExpressionsBuiltWithIsInterpretingOnly() public static bool IsNotInContainer => !IsInContainer; public static bool SupportsComInterop => IsWindows && IsNotMonoRuntime && !IsNativeAot; // matches definitions in clr.featuredefines.props -#if NETCOREAPP +#if NET public static bool IsBuiltInComEnabled => SupportsComInterop && (AppContext.TryGetSwitch("System.Runtime.InteropServices.BuiltInComInterop.IsSupported", out bool isEnabled) ? isEnabled @@ -198,7 +198,7 @@ private static bool GetLinqExpressionsBuiltWithIsInterpretingOnly() public static bool SupportsSsl3 => GetSsl3Support(); public static bool SupportsSsl2 => IsWindows && !PlatformDetection.IsWindows10Version1607OrGreater; -#if NETCOREAPP +#if NET public static bool IsReflectionEmitSupported => RuntimeFeature.IsDynamicCodeSupported; public static bool IsNotReflectionEmitSupported => !IsReflectionEmitSupported; #else @@ -668,7 +668,7 @@ private static bool GetSendsCAListByDefault() private static bool GetIsRunningOnMonoInterpreter() { -#if NETCOREAPP +#if NET return IsMonoRuntime && RuntimeFeature.IsDynamicCodeSupported && !RuntimeFeature.IsDynamicCodeCompiled; #else return false; diff --git a/src/libraries/Common/tests/TestUtilities/System/Runtime/InteropServices/SafeBufferUtil.cs b/src/libraries/Common/tests/TestUtilities/System/Runtime/InteropServices/SafeBufferUtil.cs index f667b1e26cec55..d3ff55aa515635 100644 --- a/src/libraries/Common/tests/TestUtilities/System/Runtime/InteropServices/SafeBufferUtil.cs +++ b/src/libraries/Common/tests/TestUtilities/System/Runtime/InteropServices/SafeBufferUtil.cs @@ -19,7 +19,7 @@ private sealed class AllocHGlobalSafeHandle : SafeBuffer { public AllocHGlobalSafeHandle(nuint cb) : base(ownsHandle: true) { -#if !NETCOREAPP +#if !NET RuntimeHelpers.PrepareConstrainedRegions(); #endif try diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs index 658653c28c0fe1..060d1f55d72a05 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs @@ -952,7 +952,7 @@ private static bool TypeIsASetInterface(Type type) Type genericTypeDefinition = type.GetGenericTypeDefinition(); return genericTypeDefinition == typeof(ISet<>) -#if NETCOREAPP +#if NET || genericTypeDefinition == typeof(IReadOnlySet<>) #endif ; diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Collections.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Collections.cs index 73afe160f28f2c..06b44553ab9fd5 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Collections.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Collections.cs @@ -1532,7 +1532,7 @@ public void CanBindISetNoSetter() Assert.Equal("Yo2", options.ISetNoSetter.ElementAt(1)); } -#if NETCOREAPP +#if NET [Fact] public void CanBindInstantiatedIReadOnlySet() { @@ -2291,7 +2291,7 @@ public void TestOptionsWithDifferentCollectionInterfaces() Assert.True(3 == options.UnInstantiatedISet.Count(), $"UnInstantiatedISet count is {options.UnInstantiatedISet.Count()} .. {options.UnInstantiatedISet.ElementAt(options.UnInstantiatedISet.Count() - 1)}"); Assert.Equal(new string[] { "a", "A", "B" }, options.UnInstantiatedISet); -#if NETCOREAPP +#if NET Assert.True(3 == options.InstantiatedIReadOnlySet.Count(), $"InstantiatedIReadOnlySet count is {options.InstantiatedIReadOnlySet.Count()} .. {options.InstantiatedIReadOnlySet.ElementAt(options.InstantiatedIReadOnlySet.Count() - 1)}"); Assert.Equal(new string[] { "a", "b", "Z" }, options.InstantiatedIReadOnlySet); Assert.False(options.IsSameInstantiatedIReadOnlySet()); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Helpers.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Helpers.cs index d6521ed86dfdec..488e9b81c99d1f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Helpers.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Helpers.cs @@ -109,7 +109,7 @@ public string ReadOnly public ISet UninstantiatedHashSetWithUnsupportedKey { get; set; } -#if NETCOREAPP +#if NET public IReadOnlySet InstantiatedIReadOnlySet { get; set; } = new HashSet(); public IReadOnlySet InstantiatedIReadOnlySetWithSomeValues { get; set; } = new HashSet(new[] { "existing1", "existing2" }); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.Collections.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.Collections.cs index c8f672eb7fdb75..30d1fc8dc5b8c0 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.Collections.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.Collections.cs @@ -354,7 +354,7 @@ public class OptionsWithDifferentCollectionInterfaces public ISet InstantiatedISet { get; set; } = s_instantiatedISet; public bool IsSameInstantiatedISet() => object.ReferenceEquals(s_instantiatedISet, InstantiatedISet); -#if NETCOREAPP +#if NET private static IReadOnlySet s_instantiatedIReadOnlySet = new HashSet(StringComparer.OrdinalIgnoreCase) { "a", "A", "b" }; public IReadOnlySet InstantiatedIReadOnlySet { get; set; } = s_instantiatedIReadOnlySet; public bool IsSameInstantiatedIReadOnlySet() => object.ReferenceEquals(s_instantiatedIReadOnlySet, InstantiatedIReadOnlySet); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.cs index 02f3a74f317b1a..b7ef3cba018edb 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.cs @@ -743,7 +743,7 @@ public record RecordWithPrimitives public Uri Prop25 { get; set; } public Version Prop26 { get; set; } public DayOfWeek Prop27 { get; set; } -#if NETCOREAPP +#if NET public Int128 Prop7 { get; set; } public Half Prop11 { get; set; } public UInt128 Prop12 { get; set; } 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 22691e75714263..4986778a87ceeb 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs @@ -1971,7 +1971,7 @@ public void TypeWithPrimitives_Pass() #endif Assert.Equal(CultureInfo.GetCultureInfo("yo-NG"), obj.Prop17); -#if NETCOREAPP +#if NET data = @"{ ""Prop7"": 9, ""Prop11"": 65500, @@ -2146,10 +2146,10 @@ public void TraceSwitchTest() TraceSwitch ts = new(displayName: "TraceSwitch", description: "This switch is set via config."); ConfigurationBinder.Bind(config, "TraceSwitch", ts); Assert.Equal(TraceLevel.Info, ts.Level); -#if NETCOREAPP +#if NET // Value property is not publicly exposed in .NET Framework. Assert.Equal("Info", ts.Value); -#endif // NETCOREAPP +#endif // NET } #endif diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/GeneratorTests.Helpers.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/GeneratorTests.Helpers.cs index 24285047fff900..e9dcad70de4f9d 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/GeneratorTests.Helpers.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/GeneratorTests.Helpers.cs @@ -106,7 +106,7 @@ private static async Task VerifyAgainstBaselineUsingF ExpectedDiagnostics expectedDiags = ExpectedDiagnostics.None) { string environmentSubFolder = -#if NETCOREAPP +#if NET "netcoreapp" #else "net462" @@ -138,7 +138,7 @@ private static async Task VerifyAgainstBaselineUsingF string source = string.Join(Environment.NewLine, lines).TrimEnd(Environment.NewLine.ToCharArray()) + Environment.NewLine; path = Path.Combine($"{repoRootDir}\\src\\libraries\\Microsoft.Extensions.Configuration.Binder\\tests\\SourceGenerationTests\\", path); -#if NETCOREAPP +#if NET await File.WriteAllTextAsync(path, source); #else File.WriteAllText(path, source); diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs index f00a9ab49f041d..274f4696dd94af 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs @@ -69,7 +69,7 @@ static ReadOnlySpan SkipAheadOnDelimiter(ReadOnlySpan a) static int Compare(ReadOnlySpan a, ReadOnlySpan b) { -#if NETCOREAPP +#if NET bool aIsInt = int.TryParse(a, out int value1); bool bIsInt = int.TryParse(b, out int value2); #else diff --git a/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/DisposableFileSystem.cs b/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/DisposableFileSystem.cs index fffca558b0c74d..0c16295d5be547 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/DisposableFileSystem.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/DisposableFileSystem.cs @@ -14,7 +14,7 @@ public class DisposableFileSystem : IDisposable public DisposableFileSystem() { -#if NETCOREAPP +#if NET DirectoryInfo = Directory.CreateTempSubdirectory(); #else DirectoryInfo = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ActivatorUtilities.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ActivatorUtilities.cs index 0b8a0bacae59e6..6d8a30b6dd5d4e 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ActivatorUtilities.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ActivatorUtilities.cs @@ -12,7 +12,7 @@ using System.Runtime.InteropServices; using Microsoft.Extensions.Internal; -#if NETCOREAPP +#if NET [assembly: System.Reflection.Metadata.MetadataUpdateHandler(typeof(Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ActivatorUtilitiesUpdateHandler))] #endif @@ -23,7 +23,7 @@ namespace Microsoft.Extensions.DependencyInjection /// public static class ActivatorUtilities { -#if NETCOREAPP +#if NET // Support caching of constructor metadata for the common case of types in non-collectible assemblies. private static readonly ConcurrentDictionary s_constructorInfos = new(); @@ -60,7 +60,7 @@ public static object CreateInstance( } ConstructorInfoEx[]? constructors; -#if NETCOREAPP +#if NET if (!s_constructorInfos.TryGetValue(instanceType, out constructors)) { constructors = GetOrAddConstructors(instanceType); @@ -135,7 +135,7 @@ public static object CreateInstance( if (bestLength < length) { bestLength = length; -#if NETCOREAPP +#if NET ctorArgs.CopyTo(bestCtorArgs); #else if (i == constructors.Length - 1) @@ -191,7 +191,7 @@ public static object CreateInstance( matcher.MapParameters(parameterMap, parameters); return matcher.CreateInstance(provider); -#if NETCOREAPP +#if NET int GetMaxArgCount() { int max = 0; @@ -222,7 +222,7 @@ static void InitializeCtorArgValues(ref object[] ctorArgs, int length) #endif } -#if NETCOREAPP +#if NET private static ConstructorInfoEx[] GetOrAddConstructors( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) { @@ -246,7 +246,7 @@ private static ConstructorInfoEx[] GetOrAddConstructors( s_collectibleConstructorInfos.Value.AddOrUpdate(type, value); return value; } -#endif // NETCOREAPP +#endif // NET private static ConstructorInfoEx[] CreateConstructorInfoExs( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) @@ -277,7 +277,7 @@ public static ObjectFactory CreateFactory( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type instanceType, Type[] argumentTypes) { -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP +#if NETSTANDARD2_1_OR_GREATER || NET if (!RuntimeFeature.IsDynamicCodeCompiled) { // Create a reflection-based factory when dynamic code is not compiled\jitted as would be the case with @@ -314,7 +314,7 @@ public static ObjectFactory CreateFactory<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>( Type[] argumentTypes) { -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP +#if NETSTANDARD2_1_OR_GREATER || NET if (!RuntimeFeature.IsDynamicCodeCompiled) { // See the comment above in the non-generic CreateFactory() for why we use 'IsDynamicCodeCompiled' here. @@ -437,7 +437,7 @@ private static BlockExpression BuildFactoryExpression( Expression.New(constructor, constructorArguments)); } -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP +#if NETSTANDARD2_1_OR_GREATER || NET [DoesNotReturn] private static void ThrowHelperArgumentNullExceptionServiceProvider() { @@ -451,7 +451,7 @@ private static ObjectFactory CreateFactoryReflection( FindApplicableConstructor(instanceType, argumentTypes, constructors: null, out ConstructorInfo constructor, out int?[] parameterMap); Type declaringType = constructor.DeclaringType!; -#if NETCOREAPP +#if NET ConstructorInvoker invoker = ConstructorInvoker.Create(constructor); ParameterInfo[] constructorParameters = constructor.GetParameters(); @@ -520,7 +520,7 @@ ObjectFactory InvokeCanonical() FactoryParameterContext[] parameters = GetFactoryParameterContext(); return (serviceProvider, arguments) => ReflectionFactoryCanonical(constructor, parameters, declaringType, serviceProvider, arguments); -#endif // NETCOREAPP +#endif // NET FactoryParameterContext[] GetFactoryParameterContext() { @@ -542,7 +542,7 @@ FactoryParameterContext[] GetFactoryParameterContext() return parameters; } } -#endif // NETSTANDARD2_1_OR_GREATER || NETCOREAPP +#endif // NETSTANDARD2_1_OR_GREATER || NET private readonly struct FactoryParameterContext { @@ -644,7 +644,7 @@ private static bool TryFindPreferredConstructor( if (constructors is null) { -#if NETCOREAPP +#if NET if (!s_constructorInfos.TryGetValue(instanceType, out constructors)) { constructors = GetOrAddConstructors(instanceType); @@ -725,7 +725,7 @@ private sealed class ConstructorInfoEx public readonly ParameterInfo[] Parameters; public readonly bool IsPreferred; private readonly object?[]? _parameterKeys; -#if NETCOREAPP +#if NET public ConstructorInvoker? _invoker; public ConstructorInvoker Invoker { @@ -801,7 +801,7 @@ private readonly ref struct ConstructorMatcher { private readonly ConstructorInfoEx _constructor; -#if NETCOREAPP +#if NET private readonly Span _parameterValues; public ConstructorMatcher(ConstructorInfoEx constructor, Span parameterValues) #else @@ -884,7 +884,7 @@ public object CreateInstance(IServiceProvider provider) } } -#if NETCOREAPP +#if NET return _constructor.Invoker.Invoke(_parameterValues.Slice(0, _constructor.Parameters.Length)); #else try @@ -922,7 +922,7 @@ private static void ThrowMarkedCtorDoesNotTakeAllProvidedArguments() throw new InvalidOperationException(SR.Format(SR.MarkedCtorMissingArgumentTypes, nameof(ActivatorUtilitiesConstructorAttribute))); } -#if NETCOREAPP // Use the faster ConstructorInvoker which also has alloc-free APIs when <= 4 parameters. +#if NET // Use the faster ConstructorInvoker which also has alloc-free APIs when <= 4 parameters. private static object ReflectionFactoryServiceOnlyFixed( ConstructorInvoker invoker, FactoryParameterContext[] parameters, @@ -1167,7 +1167,7 @@ private static void ThrowHelperNullReferenceException() { throw new NullReferenceException(); } -#elif NETSTANDARD2_1_OR_GREATER || NETCOREAPP +#elif NETSTANDARD2_1_OR_GREATER || NET private static object ReflectionFactoryCanonical( ConstructorInfo constructor, FactoryParameterContext[] parameters, @@ -1197,7 +1197,7 @@ private static object ReflectionFactoryCanonical( } #endif -#if NETCOREAPP +#if NET internal static class ActivatorUtilitiesUpdateHandler { public static void ClearCache(Type[]? _) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ActivatorUtilitiesTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ActivatorUtilitiesTests.cs index 1144ff33a1c7b6..8e0d07c0b0acd4 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ActivatorUtilitiesTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ActivatorUtilitiesTests.cs @@ -8,7 +8,7 @@ using Xunit; using System.Runtime.CompilerServices; -#if NETCOREAPP +#if NET using System.Runtime.Loader; #endif @@ -332,7 +332,7 @@ public void CreateFactory_CreatesFactoryMethod_5Types_5Injected() [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_CreatesFactoryMethod_KeyedParams(bool useDynamicCode) @@ -363,7 +363,7 @@ public void CreateFactory_CreatesFactoryMethod_KeyedParams(bool useDynamicCode) [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_CreatesFactoryMethod_KeyedParams_5Types(bool useDynamicCode) @@ -396,7 +396,7 @@ public void CreateFactory_CreatesFactoryMethod_KeyedParams_5Types(bool useDynami [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_CreatesFactoryMethod_KeyedParams_1Injected(bool useDynamicCode) @@ -426,7 +426,7 @@ public void CreateFactory_CreatesFactoryMethod_KeyedParams_1Injected(bool useDyn [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_RemoteExecutor_CreatesFactoryMethod(bool useDynamicCode) @@ -460,7 +460,7 @@ public void CreateFactory_RemoteExecutor_CreatesFactoryMethod(bool useDynamicCod [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_RemoteExecutor_NullArguments_Throws(bool useDynamicCode) @@ -483,7 +483,7 @@ public void CreateFactory_RemoteExecutor_NullArguments_Throws(bool useDynamicCod [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_RemoteExecutor_NoArguments_UseNullDefaultValue(bool useDynamicCode) @@ -507,7 +507,7 @@ public void CreateFactory_RemoteExecutor_NoArguments_UseNullDefaultValue(bool us [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_RemoteExecutor_NoArguments_ThrowRequiredValue(bool useDynamicCode) @@ -531,7 +531,7 @@ public void CreateFactory_RemoteExecutor_NoArguments_ThrowRequiredValue(bool use [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_RemoteExecutor_NullArgument_UseDefaultValue(bool useDynamicCode) @@ -555,7 +555,7 @@ public void CreateFactory_RemoteExecutor_NullArgument_UseDefaultValue(bool useDy [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_RemoteExecutor_NoParameters_Success(bool useDynamicCode) @@ -577,7 +577,7 @@ public void CreateFactory_RemoteExecutor_NoParameters_Success(bool useDynamicCod }, options); } -#if NETCOREAPP +#if NET [ActiveIssue("https://github.com/dotnet/runtime/issues/34072", TestRuntimes.Mono)] [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] @@ -1008,7 +1008,7 @@ public ClassWithStringDefaultValue(string text = "DEFAULT") } } -#if NETCOREAPP +#if NET internal class MyLoadContext : AssemblyLoadContext { private MyLoadContext() : base(isCollectible: true) diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextPaths.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextPaths.cs index b5c6730eef3eec..298b704ac1c288 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextPaths.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextPaths.cs @@ -40,7 +40,7 @@ private static DependencyContextPaths GetCurrent() internal static DependencyContextPaths Create(string? depsFiles, string? sharedRuntime) { -#if NETCOREAPP +#if NET const char separator = ';'; #else // This method is only executed once at startup. No need to cache the char[]. diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Composite/tests/MockFileProvider.cs b/src/libraries/Microsoft.Extensions.FileProviders.Composite/tests/MockFileProvider.cs index c9ce31d6e276d5..eed6a5044e6aca 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Composite/tests/MockFileProvider.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Composite/tests/MockFileProvider.cs @@ -11,7 +11,7 @@ namespace Microsoft.Extensions.FileProviders.Composite { public class MockFileProvider : IFileProvider { -#if NETCOREAPP +#if NET static MockFileProvider() { // Castle DynamicProxy hasn't been updated to ignore .net5 infrastructure attributes diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/FileSystemInfoHelper.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/FileSystemInfoHelper.cs index 6559d5d46c9fc1..4796d4a8b0a390 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/FileSystemInfoHelper.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/FileSystemInfoHelper.cs @@ -31,7 +31,7 @@ public static bool IsExcluded(FileSystemInfo fileSystemInfo, ExclusionFilters fi public static DateTime? GetFileLinkTargetLastWriteTimeUtc(string filePath) { -#if NETCOREAPP +#if NET var fileInfo = new FileInfo(filePath); if (fileInfo.Exists) { @@ -47,7 +47,7 @@ public static bool IsExcluded(FileSystemInfo fileSystemInfo, ExclusionFilters fi // If file is not a link, return null to inform the caller that file is not a link. public static DateTime? GetFileLinkTargetLastWriteTimeUtc(FileInfo fileInfo) { -#if NETCOREAPP +#if NET Debug.Assert(fileInfo.Exists); if (fileInfo.LinkTarget != null) { diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFileProvider.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFileProvider.cs index fb2306d56e9f9d..925df9892752b6 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFileProvider.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFileProvider.cs @@ -162,7 +162,7 @@ internal PhysicalFilesWatcher CreateFileWatcher() string root = PathUtils.EnsureTrailingSlash(Path.GetFullPath(Root)); FileSystemWatcher? watcher; -#if NETCOREAPP +#if NET // For browser/iOS/tvOS we will proactively fallback to polling since FileSystemWatcher is not supported. if (OperatingSystem.IsBrowser() || (OperatingSystem.IsIOS() && !OperatingSystem.IsMacCatalyst()) || OperatingSystem.IsTvOS()) { diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs index eaa53fec71ede1..712a83a3ef2c6e 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs @@ -88,7 +88,7 @@ public PhysicalFilesWatcher( if (fileSystemWatcher != null) { -#if NETCOREAPP +#if NET if (OperatingSystem.IsBrowser() || (OperatingSystem.IsIOS() && !OperatingSystem.IsMacCatalyst()) || OperatingSystem.IsTvOS()) { throw new PlatformNotSupportedException(SR.Format(SR.FileSystemWatcher_PlatformNotSupported, typeof(FileSystemWatcher))); diff --git a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/TestUtility/DisposableFileSystem.cs b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/TestUtility/DisposableFileSystem.cs index 50abfa57af42e3..1571b88402ec0b 100644 --- a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/TestUtility/DisposableFileSystem.cs +++ b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/TestUtility/DisposableFileSystem.cs @@ -10,7 +10,7 @@ public class DisposableFileSystem : IDisposable { public DisposableFileSystem() { -#if NETCOREAPP +#if NET DirectoryInfo = Directory.CreateTempSubdirectory(); #else DirectoryInfo = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())); diff --git a/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdHelpers.cs b/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdHelpers.cs index c7887bc29b2302..53d382c5e7c913 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdHelpers.cs +++ b/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdHelpers.cs @@ -5,7 +5,7 @@ using System.Globalization; using System.IO; using System.Text; -#if !NETCOREAPP +#if !NET using System.Diagnostics; #endif @@ -37,7 +37,7 @@ private static bool GetIsSystemdService() // To support containerized systemd services, check if we're the main process (PID 1) // and if there are systemd environment variables defined for notifying the service // manager, or passing listen handles. -#if NETCOREAPP +#if NET int processId = Environment.ProcessId; #else int processId = Process.GetCurrentProcess().Id; diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs b/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs index a0407b8c2ec7be..09274bad3a3cbb 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs @@ -275,7 +275,7 @@ internal static void AddDefaultServices(HostBuilderContext hostingContext, IServ services.AddLogging(logging => { bool isWindows = -#if NETCOREAPP +#if NET OperatingSystem.IsWindows(); #elif NETFRAMEWORK Environment.OSVersion.Platform == PlatformID.Win32NT; @@ -292,7 +292,7 @@ internal static void AddDefaultServices(HostBuilderContext hostingContext, IServ } logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); -#if NETCOREAPP +#if NET if (!OperatingSystem.IsBrowser()) #endif { diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs index d2167ae3697f82..f923221fdb7b6e 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs @@ -255,7 +255,7 @@ public void DisableDefaultIHostEnvironmentValues(CreateBuilderFunc createBuilder HostApplicationBuilder builder = createBuilder(); Assert.Equal(Environments.Production, builder.Environment.EnvironmentName); -#if NETCOREAPP +#if NET Assert.NotNull(builder.Environment.ApplicationName); #elif NETFRAMEWORK // Note GetEntryAssembly returns null for the net4x console test runner. @@ -270,7 +270,7 @@ public void DisableDefaultIHostEnvironmentValues(CreateBuilderFunc createBuilder var env = host.Services.GetRequiredService(); Assert.Equal(Environments.Production, env.EnvironmentName); -#if NETCOREAPP +#if NET Assert.NotNull(env.ApplicationName); #elif NETFRAMEWORK // Note GetEntryAssembly returns null for the net4x console test runner. @@ -382,7 +382,7 @@ public void DirectSettingsOverrideConfigurationSetting(CreateBuilderSettingsFunc private static string CreateTempSubdirectory() { -#if NETCOREAPP +#if NET DirectoryInfo directoryInfo = Directory.CreateTempSubdirectory(); #else DirectoryInfo directoryInfo = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())); diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostBuilderTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostBuilderTests.cs index 5d37dbd15ec333..da863fec653535 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostBuilderTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostBuilderTests.cs @@ -174,7 +174,7 @@ public void DefaultIHostEnvironmentValues() { var env = hostContext.HostingEnvironment; Assert.Equal(Environments.Production, env.EnvironmentName); -#if NETCOREAPP +#if NET Assert.NotNull(env.ApplicationName); #elif NETFRAMEWORK // Note GetEntryAssembly returns null for the net4x console test runner. @@ -190,7 +190,7 @@ public void DefaultIHostEnvironmentValues() { var env = host.Services.GetRequiredService(); Assert.Equal(Environments.Production, env.EnvironmentName); -#if NETCOREAPP +#if NET Assert.NotNull(env.ApplicationName); #elif NETFRAMEWORK // Note GetEntryAssembly returns null for the net4x console test runner. diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/OptionsBuilderExtensionsTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/OptionsBuilderExtensionsTests.cs index 74c2a1c0bfe92c..6a67cbcaa9508e 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/OptionsBuilderExtensionsTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/OptionsBuilderExtensionsTests.cs @@ -413,7 +413,7 @@ private static void ValidateFailure(Type type, OptionsValidationException e, int // Check for the error in any of the failures foreach (var error in errorsToMatch) { -#if NETCOREAPP +#if NET Assert.True(e.Failures.FirstOrDefault(predicate: f => f.Contains(error, StringComparison.CurrentCulture)) != null, "Did not find: " + error + " " + e.Failures.First()); #else Assert.True(e.Failures.FirstOrDefault(predicate: f => f.IndexOf(error, StringComparison.CurrentCulture) >= 0) != null, "Did not find: " + error + " " + e.Failures.First()); diff --git a/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpHeadersLogValue.cs b/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpHeadersLogValue.cs index 802192c4a905c9..23b07adf7f503d 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpHeadersLogValue.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpHeadersLogValue.cs @@ -103,7 +103,7 @@ public override string ToString() } else { -#if NETCOREAPP +#if NET builder.AppendJoin(", ", (IEnumerable)kvp.Value); builder.AppendLine(); #else diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/AnsiParsingLogConsole.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/AnsiParsingLogConsole.cs index 8cab45f3ffc06b..563fcacac6dadf 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/AnsiParsingLogConsole.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/AnsiParsingLogConsole.cs @@ -62,7 +62,7 @@ private void WriteToConsole(string message, int startIndex, int length, ConsoleC { ReadOnlySpan span = message.AsSpan(startIndex, length); var colorChanged = SetColor(background, foreground); -#if NETCOREAPP +#if NET _textWriter.Write(span); #else _textWriter.Write(span.ToString()); diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs index b3ff45e33d9ed1..3b613ac50e206a 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs @@ -81,7 +81,7 @@ private void WriteInternal(IExternalScopeProvider? scopeProvider, TextWriter tex writer.WriteEndObject(); writer.Flush(); } -#if NETCOREAPP +#if NET textWriter.Write(Encoding.UTF8.GetString(output.WrittenMemory.Span)); #else textWriter.Write(Encoding.UTF8.GetString(output.WrittenMemory.Span.ToArray())); @@ -145,7 +145,7 @@ private static void WriteItem(Utf8JsonWriter writer, KeyValuePair OperatingSystem.IsAndroid() || OperatingSystem.IsTvOS() || OperatingSystem.IsIOS(); // returns true on MacCatalyst @@ -90,7 +90,7 @@ private void WriteInternal(IExternalScopeProvider? scopeProvider, TextWriter tex textWriter.Write(category); textWriter.Write('['); -#if NETCOREAPP +#if NET Span span = stackalloc char[10]; if (eventId.TryFormat(span, out int charsWritten)) textWriter.Write(span.Slice(0, charsWritten)); diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/EventSourceLoggerTest.cs b/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/EventSourceLoggerTest.cs index 343036cca5b5ce..eb4f25eb34fc5d 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/EventSourceLoggerTest.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/EventSourceLoggerTest.cs @@ -904,7 +904,7 @@ private static class EventTypes @"""FormattedMessage"":""Logger2 Event5 Critical bar 23 45") }, // Starting in netcoreapp3.0 Exception.ToString() puts a newline before inner exceptions -#if NETCOREAPP +#if NET { "E5JS", (e) => VerifySingleEvent(e, "Logger2", EventTypes.MessageJson, 5, null, LogLevel.Critical, @"""ArgumentsJson"":{""stringParam"":""bar"",""int1Param"":""23"",""int2Param"":""45""", @$"""ExceptionJson"":{{""TypeName"":""System.Exception"",""Message"":""oops"",""HResult"":""-2146233088"",""VerboseMessage"":""System.Exception: oops{EscapedNewline()} ---\u003E System.Exception: inner oops") }, diff --git a/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceLoggerProviderTest.cs b/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceLoggerProviderTest.cs index 80d9e7ab1909a0..83dd9e8b619bff 100644 --- a/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceLoggerProviderTest.cs +++ b/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceLoggerProviderTest.cs @@ -66,7 +66,7 @@ public override void WriteLine(string message) } } } -#elif NETCOREAPP +#elif NET #else #error Target framework needs to be updated #endif diff --git a/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceScopeTest.cs b/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceScopeTest.cs index 25bd315a8679b0..42c16ecd30bba7 100644 --- a/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceScopeTest.cs +++ b/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceScopeTest.cs @@ -33,7 +33,7 @@ public static void DiagnosticsScope_PushesAndPops_LogicalOperationStack() Assert.Same(a, c); Assert.Same(state, b); } -#elif NETCOREAPP +#elif NET #else #error Target framework needs to be updated #endif diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Main.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Main.cs index 618c751d281059..5a3479b42c3568 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Main.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Main.cs @@ -56,11 +56,11 @@ public partial struct MyOptionsValidator : IValidateOptions Assert.Empty(diagnostics); _ = Assert.Single(generatedSources); -#if NETCOREAPP +#if NET string generatedSource = File.ReadAllText(@"Baselines/EmitterWithCustomValidator.netcore.g.cs"); #else string generatedSource = File.ReadAllText(@"Baselines/EmitterWithCustomValidator.netfx.g.cs"); -#endif // NETCOREAPP +#endif // NET Assert.Equal(generatedSource.Replace("\r\n", "\n"), generatedSources[0].SourceText.ToString().Replace("\r\n", "\n")); } @@ -1715,7 +1715,7 @@ private static CSharpCompilation CreateCompilationForOptionsSource(string assemb public async Task GeneratedAttributesTest(LanguageVersion languageVersion) { -#if NETCOREAPP +#if NET string lengthAttribute = $$""" [LengthAttribute(1, 3)] public string? P0 { get; set; } @@ -1728,7 +1728,7 @@ public async Task GeneratedAttributesTest(LanguageVersion languageVersion) """; #else string lengthAttribute = ""; -#endif //NETCOREAPP +#endif //NET string source = $$""" using System; @@ -1807,7 +1807,7 @@ public sealed partial class OptionsUsingGeneratedAttributesValidator : IValidate var diags = syntaxTree.GetDiagnostics().ToArray(); Assert.Empty(diags); -#if NETCOREAPP +#if NET string generatedSource = File.ReadAllText(languageVersion == LanguageVersion.CSharp10 ? @"Baselines/GeneratedAttributesTest.netcore.lang10.g.cs" : @"Baselines/GeneratedAttributesTest.netcore.lang11.g.cs"); #else string generatedSource = File.ReadAllText(languageVersion == LanguageVersion.CSharp10 ? @"Baselines/GeneratedAttributesTest.netfx.lang10.g.cs" : @"Baselines/GeneratedAttributesTest.netfx.lang11.g.cs"); @@ -1857,11 +1857,11 @@ public partial class MyOptionsValidator : IValidateOptions Assert.Empty(diagnostics); Assert.Single(generatedSources); -#if NETCOREAPP +#if NET string generatedSource = File.ReadAllText(@"Baselines/UsingInterfaceAsPropertyTypeForLengthAttributesTests.netcore.g.cs"); #else string generatedSource = File.ReadAllText(@"Baselines/UsingInterfaceAsPropertyTypeForLengthAttributesTests.netfx.g.cs"); -#endif // NETCOREAPP +#endif // NET Assert.Equal(generatedSource.Replace("\r\n", "\n"), generatedSources[0].SourceText.ToString().Replace("\r\n", "\n")); } @@ -1907,11 +1907,11 @@ public sealed class EndPointsOptions var (diagnostics, src) = await RunGenerator(source); Assert.Empty(diagnostics); Assert.Single(src); -#if NETCOREAPP +#if NET string generatedSource = File.ReadAllText(@"Baselines/OptionsExtendingSystemClassTest.netcore.g.cs"); #else string generatedSource = File.ReadAllText(@"Baselines/OptionsExtendingSystemClassTest.netfx.g.cs"); -#endif // NETCOREAPP +#endif // NET Assert.Equal(generatedSource.Replace("\r\n", "\n"), src[0].SourceText.ToString().Replace("\r\n", "\n")); } } diff --git a/src/libraries/Microsoft.Extensions.Primitives/src/StringSegment.cs b/src/libraries/Microsoft.Extensions.Primitives/src/StringSegment.cs index c78527db921b5d..f91f2314439cae 100644 --- a/src/libraries/Microsoft.Extensions.Primitives/src/StringSegment.cs +++ b/src/libraries/Microsoft.Extensions.Primitives/src/StringSegment.cs @@ -271,7 +271,7 @@ public bool Equals(string? text, StringComparison comparisonType) [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int GetHashCode() { -#if NETCOREAPP +#if NET return string.GetHashCode(AsSpan()); #elif (NETSTANDARD2_0 || NETFRAMEWORK) // This GetHashCode is expensive since it allocates on every call. diff --git a/src/libraries/Microsoft.Extensions.Primitives/src/StringSegmentComparer.cs b/src/libraries/Microsoft.Extensions.Primitives/src/StringSegmentComparer.cs index 9942f7959f5bdf..f1c645483da8f4 100644 --- a/src/libraries/Microsoft.Extensions.Primitives/src/StringSegmentComparer.cs +++ b/src/libraries/Microsoft.Extensions.Primitives/src/StringSegmentComparer.cs @@ -61,7 +61,7 @@ public bool Equals(StringSegment x, StringSegment y) /// A hash code for a , suitable for use in hashing algorithms and data structures like a hash table. public int GetHashCode(StringSegment obj) { -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 return string.GetHashCode(obj.AsSpan(), Comparison); #else if (!obj.HasValue) diff --git a/src/libraries/Microsoft.Extensions.Primitives/src/StringValues.cs b/src/libraries/Microsoft.Extensions.Primitives/src/StringValues.cs index 45cfea152227dc..591830f3bec384 100644 --- a/src/libraries/Microsoft.Extensions.Primitives/src/StringValues.cs +++ b/src/libraries/Microsoft.Extensions.Primitives/src/StringValues.cs @@ -219,7 +219,7 @@ static string GetJoinedStringValueFromArray(string?[] values) length += value.Length; } } -#if NETCOREAPP +#if NET // Create the new string return string.Create(length, values, (span, strings) => { int offset = 0; diff --git a/src/libraries/System.CodeDom/src/Microsoft/VisualBasic/VBCodeGenerator.cs b/src/libraries/System.CodeDom/src/Microsoft/VisualBasic/VBCodeGenerator.cs index e83798d5d6e2c2..58f468d7c8fa97 100644 --- a/src/libraries/System.CodeDom/src/Microsoft/VisualBasic/VBCodeGenerator.cs +++ b/src/libraries/System.CodeDom/src/Microsoft/VisualBasic/VBCodeGenerator.cs @@ -865,7 +865,7 @@ protected override void GenerateArrayCreateExpression(CodeArrayCreateExpression string typeName = GetTypeOutput(e.CreateType); Output.Write(typeName); -#if NETCOREAPP +#if NET if (!typeName.Contains('(')) #else if (typeName.IndexOf('(') == -1) @@ -892,7 +892,7 @@ protected override void GenerateArrayCreateExpression(CodeArrayCreateExpression } else { -#if NETCOREAPP +#if NET Output.Write(typeName.AsSpan(0, index + 1)); #else Output.Write(typeName.Substring(0, index + 1)); @@ -917,7 +917,7 @@ protected override void GenerateArrayCreateExpression(CodeArrayCreateExpression } else { -#if NETCOREAPP +#if NET Output.Write(typeName.AsSpan(index + 1)); #else Output.Write(typeName.Substring(index + 1)); diff --git a/src/libraries/System.CodeDom/tests/System/CodeDom/TempFileCollectionTests.cs b/src/libraries/System.CodeDom/tests/System/CodeDom/TempFileCollectionTests.cs index 7162c9358fdd3c..0fce53d4f8772d 100644 --- a/src/libraries/System.CodeDom/tests/System/CodeDom/TempFileCollectionTests.cs +++ b/src/libraries/System.CodeDom/tests/System/CodeDom/TempFileCollectionTests.cs @@ -277,7 +277,7 @@ private static string TempDirectory() { if (s_tempDirectory == null) { -#if NETCOREAPP +#if NET string tempDirectory = Directory.CreateTempSubdirectory().FullName; #else string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); diff --git a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs index 3c2f745f3c0c3c..8a6933a4039bf8 100644 --- a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs +++ b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs @@ -572,7 +572,7 @@ public static partial class ImmutableHashSet } [System.Runtime.CompilerServices.CollectionBuilderAttribute(typeof(System.Collections.Immutable.ImmutableHashSet), "Create")] -#if NETCOREAPP +#if NET public sealed partial class ImmutableHashSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.ISet, System.Collections.Generic.IReadOnlySet, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.Immutable.IImmutableSet #else public sealed partial class ImmutableHashSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.ISet, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.Immutable.IImmutableSet @@ -1073,7 +1073,7 @@ public static partial class ImmutableSortedSet } [System.Runtime.CompilerServices.CollectionBuilderAttribute(typeof(System.Collections.Immutable.ImmutableSortedSet), "Create")] -#if NETCOREAPP +#if NET public sealed partial class ImmutableSortedSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.ISet, System.Collections.Generic.IReadOnlySet, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Collections.Immutable.IImmutableSet #else public sealed partial class ImmutableSortedSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.ISet, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Collections.Immutable.IImmutableSet diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/AllocFreeConcurrentStack.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/AllocFreeConcurrentStack.cs index ad22b0bbab6952..1f1b1be4c5bf37 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/AllocFreeConcurrentStack.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/AllocFreeConcurrentStack.cs @@ -10,7 +10,7 @@ internal static class AllocFreeConcurrentStack { private const int MaxSize = 35; -#if NETCOREAPP +#if NET [ThreadStatic] private static Stack>? t_stack; #else @@ -20,7 +20,7 @@ internal static class AllocFreeConcurrentStack public static void TryAdd(T item) { Stack> localStack = -#if NETCOREAPP +#if NET t_stack ??= new Stack>(MaxSize); #else ThreadLocalStack; @@ -36,7 +36,7 @@ public static void TryAdd(T item) public static bool TryTake([MaybeNullWhen(false)] out T item) { -#if NETCOREAPP +#if NET Stack>? localStack = t_stack; // cache in a local to avoid unnecessary TLS hits on repeated accesses #else Stack> localStack = ThreadLocalStack; @@ -51,7 +51,7 @@ public static bool TryTake([MaybeNullWhen(false)] out T item) return false; } -#if !NETCOREAPP +#if !NET private static Stack> ThreadLocalStack { get @@ -73,7 +73,7 @@ private static Stack> ThreadLocalStack #endif } -#if !NETCOREAPP +#if !NET internal static class AllocFreeConcurrentStack { // Workaround for https://github.com/dotnet/runtime/issues/4731. diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableExtensions.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableExtensions.cs index 823c5e04cd279d..8d941eb0bcec12 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableExtensions.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableExtensions.cs @@ -16,7 +16,7 @@ internal static partial class ImmutableExtensions { internal static bool IsValueType() { -#if NETCOREAPP +#if NET return typeof(T).IsValueType; #else if (default(T) != null) diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs index b2e073484bb4ad..2ff4b68d19af36 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs @@ -15,7 +15,7 @@ namespace System.Collections.Immutable [CollectionBuilder(typeof(ImmutableHashSet), nameof(ImmutableHashSet.Create))] [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] -#if NETCOREAPP +#if NET public sealed partial class ImmutableHashSet : IImmutableSet, IHashKeyCollection, IReadOnlyCollection, ICollection, ISet, IReadOnlySet, ICollection, IStrongEnumerable.Enumerator> #else public sealed partial class ImmutableHashSet : IImmutableSet, IHashKeyCollection, IReadOnlyCollection, ICollection, ISet, ICollection, IStrongEnumerable.Enumerator> diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet_1.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet_1.cs index 2befd4a7c1307d..ee1d369c6ea144 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet_1.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet_1.cs @@ -20,7 +20,7 @@ namespace System.Collections.Immutable [CollectionBuilder(typeof(ImmutableSortedSet), nameof(ImmutableSortedSet.Create))] [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] -#if NETCOREAPP +#if NET public sealed partial class ImmutableSortedSet : IImmutableSet, ISortKeyCollection, IReadOnlySet, IReadOnlyList, IList, ISet, IList, IStrongEnumerable.Enumerator> #else public sealed partial class ImmutableSortedSet : IImmutableSet, ISortKeyCollection, IReadOnlyList, IList, ISet, IList, IStrongEnumerable.Enumerator> diff --git a/src/libraries/System.Collections.Immutable/tests/ImmutableListTest.cs b/src/libraries/System.Collections.Immutable/tests/ImmutableListTest.cs index 7223c1305e9c62..e522f4cff834ea 100644 --- a/src/libraries/System.Collections.Immutable/tests/ImmutableListTest.cs +++ b/src/libraries/System.Collections.Immutable/tests/ImmutableListTest.cs @@ -793,7 +793,7 @@ public static void TestDebuggerAttributes_Null() Assert.IsType(tie.InnerException); } -#if NETCOREAPP +#if NET [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] public void UsableWithCollectibleAssemblies() { diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/DirectoryCatalog.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/DirectoryCatalog.cs index 95ea38065458f1..75744ec2c1d30c 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/DirectoryCatalog.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/DirectoryCatalog.cs @@ -22,7 +22,7 @@ namespace System.ComponentModel.Composition.Hosting public partial class DirectoryCatalog : ComposablePartCatalog, INotifyComposablePartCatalogChanged, ICompositionElement { private static bool IsWindows => -#if NETCOREAPP_5_0_OR_GREATER +#if NET OperatingSystem.IsWindows(); #else RuntimeInformation.IsOSPlatform(OSPlatform.Windows); diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationLockCollection.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationLockCollection.cs index de0d3af555f8d9..8f5c8c9f37c3c4 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationLockCollection.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationLockCollection.cs @@ -220,7 +220,7 @@ internal bool DefinedInParent(string name) string parentListEnclosed = "," + _seedList + ","; if (name.Equals(_ignoreName) || -#if NETCOREAPP +#if NET parentListEnclosed.Contains("," + name + ",", StringComparison.Ordinal)) #else parentListEnclosed.IndexOf("," + name + ",", StringComparison.Ordinal) >= 0) diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationProperty.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationProperty.cs index f401066ddd8d20..959ba9bd9ed54e 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationProperty.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationProperty.cs @@ -133,7 +133,7 @@ internal ConfigurationProperty(PropertyInfo info) if (collectionAttribute != null) { -#if NETCOREAPP +#if NET if (!collectionAttribute.AddItemName.Contains(',')) #else if (collectionAttribute.AddItemName.IndexOf(',') == -1) diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionCollection.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionCollection.cs index b103a4a35a26c8..ef54b46ac03182 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionCollection.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionCollection.cs @@ -88,7 +88,7 @@ public ConfigurationSection Get(string name) throw ExceptionUtil.ParameterNullOrEmpty(nameof(name)); // prevent GetConfig from returning config not in this collection -#if NETCOREAPP +#if NET if (name.Contains('/')) #else if (name.IndexOf('/') >= 0) diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionGroupCollection.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionGroupCollection.cs index 68157107c77a7e..81210e851119e6 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionGroupCollection.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionGroupCollection.cs @@ -92,7 +92,7 @@ public ConfigurationSectionGroup Get(string name) throw ExceptionUtil.ParameterNullOrEmpty(nameof(name)); // prevent GetConfig from returning config not in this collection -#if NETCOREAPP +#if NET if (name.Contains('/')) #else if (name.IndexOf('/') >= 0) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs index e1678dc3dda86a..4d4edfbf7b798f 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -1362,7 +1362,7 @@ public static PropertyFetch FetcherForProperty(Type? type, string propertyName) private static PropertyFetch CreateEnumeratePropertyFetch(Type type, TypeInfo enumerableOfTType) { Type elemType = enumerableOfTType.GetGenericArguments()[0]; -#if NETCOREAPP +#if NET if (!RuntimeFeature.IsDynamicCodeSupported && elemType.IsValueType) { return new EnumeratePropertyFetch(type); @@ -1377,7 +1377,7 @@ private static PropertyFetch CreateEnumeratePropertyFetch(Type type, TypeInfo en Justification = "MakeGenericType is only called when IsDynamicCodeSupported is true or only with ref types.")] private static PropertyFetch CreatePropertyFetch(Type type, PropertyInfo propertyInfo) { -#if NETCOREAPP +#if NET if (!RuntimeFeature.IsDynamicCodeSupported && (propertyInfo.DeclaringType!.IsValueType || propertyInfo.PropertyType.IsValueType)) { return new ReflectionPropertyFetch(type, propertyInfo); @@ -1434,7 +1434,7 @@ public ValueTypedFetchProperty(Type type, PropertyInfo property) : base(type) private readonly StructFunc _propertyFetch; } -#if NETCOREAPP +#if NET /// /// A fetcher that can be used when MakeGenericType isn't available. /// diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs index a3c443b0a38f11..ba789aa98b15bf 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs @@ -737,7 +737,7 @@ private static string FormatQuantiles(QuantileValue[] quantiles) StringBuilder sb = new StringBuilder(); for (int i = 0; i < quantiles.Length; i++) { -#if NETCOREAPP +#if NET sb.Append(CultureInfo.InvariantCulture, $"{quantiles[i].Quantile}={quantiles[i].Value}"); #else sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}", quantiles[i].Quantile, quantiles[i].Value); diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs index f6b7737ef81ab2..2f7e0847782aca 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs @@ -13,7 +13,7 @@ using Microsoft.Win32; using static Interop.Advapi32; -#if !NETCOREAPP +#if !NET using MemoryMarshal = System.Diagnostics.PerformanceCounterLib; #endif @@ -120,7 +120,7 @@ internal static string ComputerName } } -#if !NETCOREAPP +#if !NET internal static T Read(ReadOnlySpan span) where T : struct => System.Runtime.InteropServices.MemoryMarshal.Read(span); diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs index fb663740108b08..422c37e70dbb30 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs @@ -22,7 +22,7 @@ public static bool IsLibLdapInstalled { get { -#if NETCOREAPP +#if NET if (!_isLibLdapInstalled.HasValue) { if (PlatformDetection.IsApplePlatform) diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnCharacterStringEncodings.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnCharacterStringEncodings.cs index 48ae19cce80c90..e13d5ddfd6f7b0 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnCharacterStringEncodings.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnCharacterStringEncodings.cs @@ -100,7 +100,7 @@ public override int GetByteCount(string s) } public -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 override #endif int GetByteCount(ReadOnlySpan chars) @@ -135,7 +135,7 @@ public override unsafe int GetCharCount(byte* bytes, int count) } public -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 override #endif int GetCharCount(ReadOnlySpan bytes) @@ -435,7 +435,7 @@ public override int GetByteCount(string s) return s_utf8Encoding.GetByteCount(s); } -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 public override int GetByteCount(ReadOnlySpan chars) { return s_utf8Encoding.GetByteCount(chars); @@ -476,7 +476,7 @@ public override unsafe int GetCharCount(byte* bytes, int count) } } -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 public override int GetCharCount(ReadOnlySpan bytes) { try diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Oid.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Oid.cs index fac90e12aec1c2..33e5a0adb1c986 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Oid.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Oid.cs @@ -61,7 +61,7 @@ public static string ReadObjectIdentifier( UniversalTagNumber.ObjectIdentifier, out int consumed); -#if NETCOREAPP +#if NET string? wellKnown = WellKnownOids.GetValue(contents); if (wellKnown is not null) diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Oid.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Oid.cs index 7c046016c531b2..04a063a11fdc31 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Oid.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Oid.cs @@ -59,7 +59,7 @@ public void WriteObjectIdentifier(ReadOnlySpan oidValue, Asn1Tag? tag = nu { CheckUniversalTag(tag, UniversalTagNumber.ObjectIdentifier); -#if NETCOREAPP +#if NET ReadOnlySpan wellKnownContents = WellKnownOids.GetContents(oidValue); if (!wellKnownContents.IsEmpty) diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/WellKnownOids.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/WellKnownOids.cs index c308c5af7fd5db..215dbe5eb846f1 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/WellKnownOids.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/WellKnownOids.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NETCOREAPP +#if NET namespace System.Formats.Asn1 { internal static class WellKnownOids diff --git a/src/libraries/System.Formats.Asn1/tests/Reader/ReadIA5String.cs b/src/libraries/System.Formats.Asn1/tests/Reader/ReadIA5String.cs index b7a74a95c3ff60..b11db277363c88 100644 --- a/src/libraries/System.Formats.Asn1/tests/Reader/ReadIA5String.cs +++ b/src/libraries/System.Formats.Asn1/tests/Reader/ReadIA5String.cs @@ -678,7 +678,7 @@ public static void ExpectedTag_IgnoresConstructed( Assert.Equal(val1.ByteArrayToHex(), val2.ByteArrayToHex()); -#if NETCOREAPP +#if NET string expected = Encoding.ASCII.GetString(val1.Span); #else string expected = Encoding.ASCII.GetString(val1.ToArray()); diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborConformanceLevel.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborConformanceLevel.cs index b31bbbcd62a2a3..b46066f061a5bc 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborConformanceLevel.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborConformanceLevel.cs @@ -207,7 +207,7 @@ public static bool RequireCanonicalSimpleValueEncodings(CborConformanceMode conf public static int GetKeyEncodingHashCode(ReadOnlySpan encoding) { HashCode hash = default; -#if NETCOREAPP +#if NET hash.AddBytes(encoding); #else while (encoding.Length >= sizeof(int)) diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.cs index 988b79dae85f47..9354a772f64fde 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.cs @@ -241,7 +241,7 @@ private void EnsureWriteCapacity(int pendingCount) { int newCapacity = currentCapacity == 0 ? 1024 : currentCapacity * 2; const uint MaxArrayLength = 0x7FFFFFC7; // Array.MaxLength -#if NETCOREAPP +#if NET Debug.Assert(MaxArrayLength == Array.MaxLength); #endif if ((uint)newCapacity > MaxArrayLength || newCapacity < requiredCapacity) diff --git a/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.TextString.cs b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.TextString.cs index 4f6acad8e5287c..314592bb6f0099 100644 --- a/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.TextString.cs +++ b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.TextString.cs @@ -106,7 +106,7 @@ public static void TryReadTextString_IndefiniteLengthConcatenated_SingleValue__H Assert.True(result); Assert.Equal(expectedValue.Length, charsWritten); Assert.Equal(expectedValue, new string(buffer.Slice(0, charsWritten) -#if !NETCOREAPP +#if !NET .ToArray() #endif )); @@ -136,7 +136,7 @@ public static void TryReadTextString_BufferTooSmall_ShouldReturnFalse(string act Assert.True(result); Assert.Equal(actualValue.Length, charsWritten); Assert.Equal(actualValue, new string(buffer.AsSpan(0, charsWritten) -#if !NETCOREAPP +#if !NET .ToArray() #endif )); @@ -162,7 +162,7 @@ public static void TryReadTextString_IndefiniteLengthConcatenated_BufferTooSmall Assert.True(result); Assert.Equal(expectedValue.Length, charsWritten); Assert.Equal(expectedValue, new string(buffer.AsSpan(0, charsWritten) -#if !NETCOREAPP +#if !NET .ToArray() #endif )); @@ -184,7 +184,7 @@ public static void ReadDefiniteLengthTextStringBytes_SingleValue_HappyPath(strin ReadOnlyMemory resultBytes = reader.ReadDefiniteLengthTextStringBytes(); string result = Encoding.UTF8.GetString(resultBytes.Span -#if !NETCOREAPP +#if !NET .ToArray() #endif ); diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/NonCryptographicHashAlgorithm.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/NonCryptographicHashAlgorithm.cs index c11622efbbd2f1..9b18216370a11f 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/NonCryptographicHashAlgorithm.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/NonCryptographicHashAlgorithm.cs @@ -156,7 +156,7 @@ private async Task AppendAsyncCore(Stream stream, CancellationToken cancellation while (true) { -#if NETCOREAPP +#if NET int read = await stream.ReadAsync(buffer.AsMemory(), cancellationToken).ConfigureAwait(false); #else int read = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); diff --git a/src/libraries/System.IO.Hashing/tests/NonCryptoHashTestDriver.cs b/src/libraries/System.IO.Hashing/tests/NonCryptoHashTestDriver.cs index fe17c4c14eab87..3204d93d4fb577 100644 --- a/src/libraries/System.IO.Hashing/tests/NonCryptoHashTestDriver.cs +++ b/src/libraries/System.IO.Hashing/tests/NonCryptoHashTestDriver.cs @@ -334,7 +334,7 @@ protected TestCaseBase(string name, byte[] output) internal static string ToHexString(ReadOnlySpan input) { -#if NETCOREAPP +#if NET return Convert.ToHexString(input); #else var builder = new global::System.Text.StringBuilder(input.Length * 2); @@ -350,7 +350,7 @@ internal static string ToHexString(ReadOnlySpan input) internal static byte[] FromHexString(string hexString) { -#if NETCOREAPP +#if NET return Convert.FromHexString(hexString); #else byte[] bytes = new byte[hexString.Length / 2]; diff --git a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipWrappingStream.cs b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipWrappingStream.cs index e3f3b42e775310..2a50857af0e3f2 100644 --- a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipWrappingStream.cs +++ b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipWrappingStream.cs @@ -67,7 +67,7 @@ int count return _baseStream.Read(buffer, offset, count); } -#if NETCOREAPP +#if NET public override void Write( ReadOnlySpan buffer ) diff --git a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeReader.cs b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeReader.cs index 747d23e778f87a..0b4d13593a03f6 100644 --- a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeReader.cs +++ b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeReader.cs @@ -171,7 +171,7 @@ public override void Complete(Exception? exception = null) } } -#if NETCOREAPP +#if NET public override ValueTask CompleteAsync(Exception? exception = null) => CompleteAndGetNeedsDispose() ? InnerStream.DisposeAsync() : default; #endif @@ -239,7 +239,7 @@ private ValueTask ReadInternalAsync(int? minimumSize, CancellationTo return Core(this, minimumSize, tokenSource, cancellationToken); -#if NETCOREAPP +#if NET [AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))] #endif static async ValueTask Core(StreamPipeReader reader, int? minimumSize, CancellationTokenSource tokenSource, CancellationToken cancellationToken) diff --git a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeWriter.cs b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeWriter.cs index c065df5cd1a10b..6f5731a9fbb07f 100644 --- a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeWriter.cs +++ b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeWriter.cs @@ -286,7 +286,7 @@ private void Cancel() InternalTokenSource.Cancel(); } -#if NETCOREAPP +#if NET [AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))] #endif private async ValueTask FlushAsyncInternal(bool writeToStream, ReadOnlyMemory data, CancellationToken cancellationToken = default) diff --git a/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledReadsStream.cs b/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledReadsStream.cs index 0b925b337a7482..dc6c6474f1fcd4 100644 --- a/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledReadsStream.cs +++ b/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledReadsStream.cs @@ -24,7 +24,7 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, return 0; } -#if NETCOREAPP +#if NET public override async ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) { await WaitForReadTask.Task; diff --git a/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledWritesStream.cs b/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledWritesStream.cs index a0e15629cee1d6..a3bde09cad0a27 100644 --- a/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledWritesStream.cs +++ b/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledWritesStream.cs @@ -23,7 +23,7 @@ public override async Task WriteAsync(byte[] buffer, int offset, int count, Canc cancellationToken.ThrowIfCancellationRequested(); } -#if NETCOREAPP +#if NET public override async ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) { await WaitForWriteTask.Task; diff --git a/src/libraries/System.IO.Pipelines/tests/Infrastructure/ThrowAfterNWritesStream.cs b/src/libraries/System.IO.Pipelines/tests/Infrastructure/ThrowAfterNWritesStream.cs index b46d0c233ea37a..72640a70e4f730 100644 --- a/src/libraries/System.IO.Pipelines/tests/Infrastructure/ThrowAfterNWritesStream.cs +++ b/src/libraries/System.IO.Pipelines/tests/Infrastructure/ThrowAfterNWritesStream.cs @@ -32,7 +32,7 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati return Task.CompletedTask; } -#if NETCOREAPP +#if NET public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) { if (_writes >= _maxWrites) diff --git a/src/libraries/System.IO.Pipelines/tests/StreamPipeReaderTests.cs b/src/libraries/System.IO.Pipelines/tests/StreamPipeReaderTests.cs index f70373c58fefd3..f9fb1f87dbafba 100644 --- a/src/libraries/System.IO.Pipelines/tests/StreamPipeReaderTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/StreamPipeReaderTests.cs @@ -614,7 +614,7 @@ public async Task CompleteCallsAppropriateDisposeMethodOnUnderlyingStream() stream = new(); reader = PipeReader.Create(stream); await reader.CompleteAsync(); -#if NETCOREAPP +#if NET Assert.False(stream.DisposeCalled); Assert.True(stream.DisposeAsyncCalled); #else @@ -661,7 +661,7 @@ public override Task ReadAsync(byte[] buffer, int offset, int count, Cancel { throw new OperationCanceledException(); } -#if NETCOREAPP +#if NET public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) { throw new OperationCanceledException(); @@ -696,7 +696,7 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, return bytes; } -#if NETCOREAPP +#if NET public override async ValueTask ReadAsync(Memory destination, CancellationToken cancellationToken = default) { if (_throwOnNextCallToRead) @@ -723,7 +723,7 @@ protected override void Dispose(bool disposing) DisposeCalled = true; } -#if NETCOREAPP +#if NET public override ValueTask DisposeAsync() { DisposeAsyncCalled = true; diff --git a/src/libraries/System.IO.Pipelines/tests/StreamPipeWriterTests.cs b/src/libraries/System.IO.Pipelines/tests/StreamPipeWriterTests.cs index 6b158f8fdb2256..3a812857822df6 100644 --- a/src/libraries/System.IO.Pipelines/tests/StreamPipeWriterTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/StreamPipeWriterTests.cs @@ -661,7 +661,7 @@ public override Task FlushAsync(CancellationToken cancellationToken) throw new OperationCanceledException(); } -#if NETCOREAPP +#if NET public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) { throw new OperationCanceledException(); diff --git a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.Unix.cs b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.Unix.cs index edcf919c2ea684..65bbba57685a21 100644 --- a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.Unix.cs +++ b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.Unix.cs @@ -13,7 +13,7 @@ public partial class SerialPort : Component { public static string[] GetPortNames() { -#if NETCOREAPP +#if NET return OperatingSystem.IsLinux() ? GetPortNames_Linux() : OperatingSystem.IsAndroid() ? GetPortNames_Linux() : OperatingSystem.IsMacOS() ? GetPortNames_OSX() diff --git a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialStream.Windows.cs b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialStream.Windows.cs index 398eb2817a1d91..fa79f2a9c1e0ea 100644 --- a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialStream.Windows.cs +++ b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialStream.Windows.cs @@ -562,7 +562,7 @@ internal SerialStream(string portName, int baudRate, Parity parity, int dataBits if (!portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase) || !uint.TryParse( -#if NETCOREAPP +#if NET portName.AsSpan(3), #else portName.Substring(3), diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.cs index 2d033b206872e6..4223cf3e064109 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.cs @@ -95,7 +95,7 @@ public static partial class HttpClientJsonExtensions { // Matches how HttpClient throws a timeout exception. string message = SR.Format(SR.net_http_request_timedout, client.Timeout.TotalSeconds); -#if NETCOREAPP +#if NET throw new TaskCanceledException(message, new TimeoutException(oce.Message, oce), oce.CancellationToken); #else throw new TaskCanceledException(message, new TimeoutException(oce.Message, oce)); diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs index 539df6d3d43f22..179cb829ef52df 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs @@ -114,7 +114,7 @@ private Task SerializeToStreamAsyncCore(Stream targetStream, CancellationToken c private async Task SerializeToStreamAsyncTranscoding(Stream targetStream, bool async, Encoding targetEncoding, CancellationToken cancellationToken) { // Wrap provided stream into a transcoding stream that buffers the data transcoded from utf-8 to the targetEncoding. -#if NETCOREAPP +#if NET Stream transcodingStream = Encoding.CreateTranscodingStream(targetStream, targetEncoding, Encoding.UTF8, leaveOpen: true); try { diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/LengthLimitReadStream.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/LengthLimitReadStream.cs index 9837587958a927..b40d400f89fb56 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/LengthLimitReadStream.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/LengthLimitReadStream.cs @@ -37,7 +37,7 @@ internal static void ThrowExceededBufferLimit(int limit) public override bool CanSeek => _innerStream.CanSeek; public override bool CanWrite => false; -#if NETCOREAPP +#if NET public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => ReadAsync(new Memory(buffer, offset, count), cancellationToken).AsTask(); diff --git a/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpClientJsonExtensionsTests.cs b/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpClientJsonExtensionsTests.cs index fee02cc8822950..a57b1cf24f5162 100644 --- a/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpClientJsonExtensionsTests.cs +++ b/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpClientJsonExtensionsTests.cs @@ -478,7 +478,7 @@ await LoopbackServer.CreateClientAndServerAsync(async uri => Exception ex = await Assert.ThrowsAsync(() => useDeleteAsync ? client.DeleteFromJsonAsync(uri) : client.GetFromJsonAsync(uri)); -#if NETCOREAPP +#if NET Assert.Contains("HttpClient.Timeout", ex.Message); Assert.IsType(ex.InnerException); #endif @@ -526,7 +526,7 @@ await LoopbackServer.CreateClientAndServerAsync(async uri => } }); -#if NETCOREAPP +#if NET Assert.Contains("HttpClient.Timeout", ex.Message); Assert.IsType(ex.InnerException); #endif diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/NoWriteNoSeekStreamContent.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/NoWriteNoSeekStreamContent.cs index 047ef52edbb562..67992f6b25c4b2 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/NoWriteNoSeekStreamContent.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/NoWriteNoSeekStreamContent.cs @@ -29,7 +29,7 @@ protected override Task SerializeToStreamAsync(Stream stream, TransportContext? SerializeToStreamAsync(stream, context, CancellationToken.None); #pragma warning disable IDE0060 -#if NETCOREAPP +#if NET protected override #else internal diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseStream.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseStream.cs index dccbaea01da0b5..5482588aa2f5e6 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseStream.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseStream.cs @@ -154,7 +154,7 @@ private async Task CopyToAsyncCore(Stream destination, byte[] buffer, Cancellati Debug.Assert(bytesRead > 0); // Write that data out to the output stream -#if NETSTANDARD2_1 || NETCOREAPP +#if NETSTANDARD2_1 || NET await destination.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false); #else await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false); diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpTrailersHelper.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpTrailersHelper.cs index 2bf4de4e34eb37..e4f4257a366feb 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpTrailersHelper.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpTrailersHelper.cs @@ -11,7 +11,7 @@ namespace System.Net.Http internal static class WinHttpTrailersHelper { // UNITTEST is true when building against WinHttpHandler.Unit.Tests, which includes the source file. -#if !NETSTANDARD2_1 && !NETCOREAPP && !UNITTEST +#if !NETSTANDARD2_1 && !NET && !UNITTEST // Trailer property name was chosen to be descriptive and be unlikely to collide with a user set property. // Apps and libraries will use this key so it shouldn't change. private const string RequestMessagePropertyName = "__ResponseTrailers"; @@ -24,7 +24,7 @@ private sealed class HttpResponseTrailers : HttpHeaders public static HttpHeaders GetResponseTrailers(HttpResponseMessage response) { -#if NETSTANDARD2_1 || NETCOREAPP || UNITTEST +#if NETSTANDARD2_1 || NET || UNITTEST return response.TrailingHeaders; #else HttpResponseTrailers responseTrailers = new HttpResponseTrailers(); diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs index b75571770fa9ec..0d2165eda36e91 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs @@ -82,7 +82,7 @@ public sealed class PlatformHandler_HttpClientEKUTest : HttpClientEKUTest public PlatformHandler_HttpClientEKUTest(ITestOutputHelper output) : base(output) { } } -#if NETCOREAPP +#if NET public sealed class PlatformHandler_HttpClientHandler_Decompression_Tests : HttpClientHandler_Decompression_Test { public PlatformHandler_HttpClientHandler_Decompression_Tests(ITestOutputHelper output) : base(output) { } @@ -182,7 +182,7 @@ public sealed class PlatformHandler_HttpClientHandler_Authentication_Test : Http public PlatformHandler_HttpClientHandler_Authentication_Test(ITestOutputHelper output) : base(output) { } } -#if NETCOREAPP +#if NET #if !WINHTTPHANDLER_TEST // [ActiveIssue("https://github.com/dotnet/runtime/issues/33930")] [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsWindows10Version1607OrGreater))] public sealed class PlatformHandlerTest_Cookies_Http2 : HttpClientHandlerTest_Cookies diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.RequestRetry.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.RequestRetry.cs index 4e2426b958e658..8198fb8818a08e 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.RequestRetry.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.RequestRetry.cs @@ -170,7 +170,7 @@ public SynchronizedSendContent(TaskCompletionSource sendingContent, Task c _sendingContent = sendingContent; } -#if NETCOREAPP +#if NET protected override void SerializeToStream(Stream stream, TransportContext context, CancellationToken cancellationToken) => SerializeToStreamAsync(stream, context).GetAwaiter().GetResult(); #endif diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs index 888b38b813127e..088e57294d54b2 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs @@ -96,7 +96,7 @@ protected static LoopbackServerFactory GetFactoryForVersion(Version useVersion) { return useVersion.Major switch { -#if NETCOREAPP +#if NET #if HTTP3 3 => Http3LoopbackServerFactory.Singleton, #endif diff --git a/src/libraries/System.Numerics.Tensors/tests/Helpers.cs b/src/libraries/System.Numerics.Tensors/tests/Helpers.cs index 1cc399d0a5a52c..a43f770bd16bd4 100644 --- a/src/libraries/System.Numerics.Tensors/tests/Helpers.cs +++ b/src/libraries/System.Numerics.Tensors/tests/Helpers.cs @@ -20,7 +20,7 @@ internal static class Helpers public const float DefaultHalfTolerance = 3.90625e-03f; public const double DefaultToleranceForEstimates = 1.171875e-02; -#if NETCOREAPP +#if NET private static class DefaultTolerance where T : unmanaged, INumber { public static readonly T Value = DetermineTolerance(DefaultDoubleTolerance, DefaultFloatTolerance, Half.CreateTruncating(DefaultHalfTolerance)) ?? T.CreateTruncating(0); @@ -54,7 +54,7 @@ public static bool IsEqualWithTolerance(float expected, float actual, float? tol public static T? DetermineTolerance( double? doubleTolerance = null, float? floatTolerance = null -#if NETCOREAPP +#if NET , Half? halfTolerance = null #endif ) where T : struct @@ -67,7 +67,7 @@ public static bool IsEqualWithTolerance(float expected, float actual, float? tol { return (T?)(object)floatTolerance; } -#if NETCOREAPP +#if NET else if (typeof(T) == typeof(Half) && halfTolerance != null) { return (T?)(object)halfTolerance; diff --git a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs index dd48ebd0d9e00f..c2588f7fde3314 100644 --- a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs +++ b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs @@ -72,7 +72,7 @@ public override SecurityRuleSet SecurityRuleSet get { return UnderlyingAssembly.SecurityRuleSet; } } -#if NETCOREAPP +#if NET [Obsolete] [RequiresAssemblyFiles] #endif @@ -91,7 +91,7 @@ public override MethodInfo? EntryPoint get { return UnderlyingAssembly.EntryPoint; } } -#if NETCOREAPP +#if NET [Obsolete] [RequiresAssemblyFiles] #endif @@ -200,7 +200,7 @@ public override Type[] GetTypes() return UnderlyingAssembly.GetTypes(); } -#if NETCOREAPP +#if NET [Obsolete] #endif public override bool GlobalAssemblyCache diff --git a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs index d69e26494a779c..21e19635db409f 100644 --- a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs +++ b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs @@ -25,7 +25,7 @@ public override Assembly Assembly internal const string UnknownStringMessageInRAF = "Returns for modules with no file path"; -#if NETCOREAPP +#if NET [RequiresAssemblyFiles(UnknownStringMessageInRAF)] #endif public override string FullyQualifiedName @@ -48,7 +48,7 @@ public override Guid ModuleVersionId get { return UnderlyingModule.ModuleVersionId; } } -#if NETCOREAPP +#if NET [RequiresAssemblyFiles(UnknownStringMessageInRAF)] #endif public override string Name diff --git a/src/libraries/System.Reflection.DispatchProxy/tests/DispatchProxyTests.cs b/src/libraries/System.Reflection.DispatchProxy/tests/DispatchProxyTests.cs index 96091763187549..df16833b724e29 100644 --- a/src/libraries/System.Reflection.DispatchProxy/tests/DispatchProxyTests.cs +++ b/src/libraries/System.Reflection.DispatchProxy/tests/DispatchProxyTests.cs @@ -557,7 +557,7 @@ public static void Proxy_Declares_Interface_Properties(bool useGenericCreate) Assert.NotNull(propertyInfo); } -#if NETCOREAPP +#if NET [Fact] public static void Invoke_Event_Add_And_Remove_And_Raise_Invokes_Correct_Methods_Generic_And_Non_Generic_Tests() { diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BitArithmetic.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BitArithmetic.cs index 7ad3c4aba6e618..43e7f2aad0f6e5 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BitArithmetic.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BitArithmetic.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -#if NETCOREAPP +#if NET using System.Numerics; #endif @@ -17,7 +17,7 @@ internal static int CountBits(int v) internal static int CountBits(uint v) { -#if NETCOREAPP +#if NET return BitOperations.PopCount(v); #else unchecked @@ -31,7 +31,7 @@ internal static int CountBits(uint v) internal static int CountBits(ulong v) { -#if NETCOREAPP +#if NET return BitOperations.PopCount(v); #else const ulong Mask01010101 = 0x5555555555555555UL; diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs index 843e95e616d34b..462d2408b1d3e1 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs @@ -20,7 +20,7 @@ public static void WriteBytes(this byte[] buffer, int start, byte value, int byt public static void WriteDouble(this byte[] buffer, int start, double value) { -#if NETCOREAPP +#if NET WriteUInt64(buffer, start, BitConverter.DoubleToUInt64Bits(value)); #else WriteUInt64(buffer, start, *(ulong*)&value); @@ -29,7 +29,7 @@ public static void WriteDouble(this byte[] buffer, int start, double value) public static void WriteSingle(this byte[] buffer, int start, float value) { -#if NETCOREAPP +#if NET WriteUInt32(buffer, start, BitConverter.SingleToUInt32Bits(value)); #else WriteUInt32(buffer, start, *(uint*)&value); @@ -76,7 +76,7 @@ public static void WriteDecimal(this byte[] buffer, int start, decimal value) public static void WriteGuid(this byte[] buffer, int start, Guid value) { -#if NETCOREAPP +#if NET bool written = value.TryWriteBytes(buffer.AsSpan(start)); // This function is not public, callers have to ensure that enough space is available. Debug.Assert(written); diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/DecimalUtilities.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/DecimalUtilities.cs index 3733a4b45a5a0e..be69480203e924 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/DecimalUtilities.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/DecimalUtilities.cs @@ -7,7 +7,7 @@ internal static class DecimalUtilities { public static int GetScale(this decimal value) { -#if NETCOREAPP +#if NET Span bits = stackalloc int[4]; decimal.GetBits(value, bits); return unchecked((byte)(bits[3] >> 16)); @@ -18,7 +18,7 @@ public static int GetScale(this decimal value) public static void GetBits(this decimal value, out bool isNegative, out byte scale, out uint low, out uint mid, out uint high) { -#if NETCOREAPP +#if NET Span bits = stackalloc int[4]; decimal.GetBits(value, bits); #else diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableMemoryStream.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableMemoryStream.cs index 26dc9290ab4e6f..fe94886ac859d9 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableMemoryStream.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableMemoryStream.cs @@ -72,7 +72,7 @@ public override int Read(byte[] buffer, int offset, int count) return result; } -#if NETCOREAPP +#if NET // Duplicate the Read(byte[]) logic here instead of refactoring both to use Spans // so we don't affect perf on .NET Framework. public override int Read(Span buffer) diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ReadOnlyUnmanagedMemoryStream.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ReadOnlyUnmanagedMemoryStream.cs index 2a31a96a154058..b3fe0044c43c92 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ReadOnlyUnmanagedMemoryStream.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ReadOnlyUnmanagedMemoryStream.cs @@ -36,7 +36,7 @@ public override int Read(byte[] buffer, int offset, int count) return bytesRead; } -#if NETCOREAPP +#if NET // Duplicate the Read(byte[]) logic here instead of refactoring both to use Spans // so we don't affect perf on .NET Framework. public override int Read(Span buffer) diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs index 2bda7989a9bb9b..484f138762fe41 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs @@ -76,7 +76,7 @@ internal static int TryReadAll(this Stream stream, byte[] buffer, int offset, in return totalBytesRead; } -#if NETCOREAPP +#if NET internal static int TryReadAll(this Stream stream, Span buffer) #if NET => stream.ReadAtLeast(buffer, buffer.Length, throwOnEndOfStream: false); diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEReader.EmbeddedPortablePdb.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEReader.EmbeddedPortablePdb.cs index 51eff57e43c03f..e9d3b25e95af50 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEReader.EmbeddedPortablePdb.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEReader.EmbeddedPortablePdb.cs @@ -99,7 +99,7 @@ internal static unsafe NativeHeapMemoryBlock DecodeEmbeddedPortablePdbDebugDirec try { -#if NETCOREAPP +#if NET actualLength = deflate.TryReadAll(new Span(decompressed.Pointer, decompressed.Size)); #else using var decompressedStream = new UnmanagedMemoryStream(decompressed.Pointer, decompressed.Size, decompressed.Size, FileAccess.Write); diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/Decoding/CustomAttributeDecoderTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/Decoding/CustomAttributeDecoderTests.cs index 62944bef46d208..b697f7fadab38d 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/Decoding/CustomAttributeDecoderTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/Decoding/CustomAttributeDecoderTests.cs @@ -197,7 +197,7 @@ public void TestCustomAttributeDecoderUsingReflection() } } -#if NETCOREAPP && !TARGET_BROWSER // Generic attribute is not supported on .NET Framework. +#if NET && !TARGET_BROWSER // Generic attribute is not supported on .NET Framework. [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.HasAssemblyFiles))] [ActiveIssue("https://github.com/dotnet/runtime/issues/60579", TestPlatforms.iOS | TestPlatforms.tvOS)] public void TestCustomAttributeDecoderGenericUsingReflection() diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameTests.cs index 53f8e43821bc61..a5e22b5d6c503b 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameTests.cs @@ -81,7 +81,7 @@ public void ParserIsNotEnforcingRuntimeSpecificRules(string input) if (PlatformDetection.IsNotMonoRuntime) // https://github.com/dotnet/runtime/issues/45033 { -#if NETCOREAPP +#if NET Assert.Throws(() => Type.GetType(input)); #endif } @@ -631,7 +631,7 @@ static void Test(Type type) Assert.Equal(type.AssemblyQualifiedName, parsed.AssemblyQualifiedName); // now load load the type from name Verify(type, parsed, ignoreCase: false); -#if NETCOREAPP // something weird is going on here +#if NET // something weird is going on here // load using lowercase name Verify(type, TypeName.Parse(type.AssemblyQualifiedName.ToLower().AsSpan()), ignoreCase: true); // load using uppercase name diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs index b6ad1c372e0f78..e5caf0e3a79f89 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs @@ -17,7 +17,7 @@ internal abstract partial class RoAssembly public sealed override Module? GetModule(string name) => GetRoModule(name); public sealed override Module[] GetModules(bool getResourceModules) => ComputeRoModules(getResourceModules).CloneArray(); -#if NETCOREAPP +#if NET [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif public sealed override FileStream? GetFile(string name) @@ -28,7 +28,7 @@ internal abstract partial class RoAssembly return new FileStream(m.FullyQualifiedName, FileMode.Open, FileAccess.Read, FileShare.Read); } -#if NETCOREAPP +#if NET [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif public sealed override FileStream[] GetFiles(bool getResourceModules) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs index 9e0e4320a021c9..8ba5c16560087e 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs @@ -45,12 +45,12 @@ protected RoAssembly(MetadataLoadContext loader, int assemblyFileCount) // Location and codebase public abstract override string Location { get; } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeBaseMessage, DiagnosticId = Obsoletions.CodeBaseDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif public sealed override string CodeBase => throw new NotSupportedException(SR.NotSupported_AssemblyCodeBase); -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeBaseMessage, DiagnosticId = Obsoletions.CodeBaseDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif @@ -159,7 +159,7 @@ public sealed override AssemblyName[] GetReferencedAssemblies() // Miscellaneous properties public sealed override bool ReflectionOnly => true; -#if NETCOREAPP +#if NET [Obsolete("The Global Assembly Cache is not supported.", DiagnosticId = "SYSLIB0005", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed override bool GlobalAssemblyCache => false; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs index cc8e5f3ce1ad23..c303886f9e7063 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs @@ -367,7 +367,7 @@ public static RoAssemblyName ToRoAssemblyName(this AssemblyName assemblyName) public static byte[] ToUtf8(this string s) => Encoding.UTF8.GetBytes(s); -#if NETCOREAPP +#if NET public static string ToUtf16(this ReadOnlySpan utf8) => Encoding.UTF8.GetString(utf8); #else public static unsafe string ToUtf16(this ReadOnlySpan utf8) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs index bd19faaac6256d..f236b209b3d25f 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs @@ -34,7 +34,7 @@ internal RoModule(string fullyQualifiedName) internal const string UnknownStringMessageInRAF = "Returns for modules with no file path"; -#if NETCOREAPP +#if NET [RequiresAssemblyFiles(UnknownStringMessageInRAF)] #endif public sealed override string FullyQualifiedName => _fullyQualifiedName; @@ -42,7 +42,7 @@ internal RoModule(string fullyQualifiedName) public abstract override int MetadataToken { get; } public abstract override Guid ModuleVersionId { get; } -#if NETCOREAPP +#if NET [RequiresAssemblyFiles(UnknownStringMessageInRAF)] #endif public sealed override string Name diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoModifiedType.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoModifiedType.cs index afb9c79952ccfe..0e5928d26bbc6c 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoModifiedType.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoModifiedType.cs @@ -152,7 +152,7 @@ public override Type[] GetOptionalCustomModifiers() public override IEnumerable DeclaredNestedTypes { -#if NETCOREAPP +#if NET [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicNestedTypes | DynamicallyAccessedMemberTypes.PublicNestedTypes)] #endif get { throw new NotSupportedException(SR.NotSupported_ModifiedType); } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/TestUtils/NetStandardBridge.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/TestUtils/NetStandardBridge.cs index 95ae7cea3e3e1c..e4fb5fbc1f5ac8 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/TestUtils/NetStandardBridge.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/TestUtils/NetStandardBridge.cs @@ -8,7 +8,7 @@ namespace System.Reflection.Tests { internal static class NetCoreApiEmulators { -#if NETCOREAPP +#if NET public static bool IsSZArray(this Type t) => t.IsSZArray; public static bool IsVariableBoundArray(this Type t) => t.IsVariableBoundArray; public static bool IsTypeDefinition(this Type t) => t.IsTypeDefinition; diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/CachingSectionGroup.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/CachingSectionGroup.cs index 327dd53ba40735..2a72776e992089 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/CachingSectionGroup.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/CachingSectionGroup.cs @@ -7,7 +7,7 @@ namespace System.Runtime.Caching.Configuration { -#if NETCOREAPP +#if NET [UnsupportedOSPlatform("browser")] #endif internal sealed class CachingSectionGroup : ConfigurationSectionGroup diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/MemoryCacheElement.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/MemoryCacheElement.cs index 9fcfd59126aa40..a72fc237c5f055 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/MemoryCacheElement.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/MemoryCacheElement.cs @@ -8,7 +8,7 @@ namespace System.Runtime.Caching.Configuration { -#if NETCOREAPP +#if NET [UnsupportedOSPlatform("browser")] #endif internal sealed class MemoryCacheElement : ConfigurationElement diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/MemoryCacheSection.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/MemoryCacheSection.cs index 05e0387374ec8d..cd15eaa788b61e 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/MemoryCacheSection.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/MemoryCacheSection.cs @@ -21,7 +21,7 @@ namespace System.Runtime.Caching.Configuration */ -#if NETCOREAPP +#if NET [UnsupportedOSPlatform("browser")] #endif internal sealed class MemoryCacheSection : ConfigurationSection diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/MemoryCacheSettingsCollection.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/MemoryCacheSettingsCollection.cs index e3c1a5bd3eb1da..8088d208640d34 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/MemoryCacheSettingsCollection.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Configuration/MemoryCacheSettingsCollection.cs @@ -7,7 +7,7 @@ namespace System.Runtime.Caching.Configuration { -#if NETCOREAPP +#if NET [UnsupportedOSPlatform("browser")] #endif [ConfigurationCollection(typeof(MemoryCacheElement), diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Counters.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Counters.cs index bd5e9d11eea649..8e8d65117bf950 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Counters.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/Counters.cs @@ -9,12 +9,12 @@ namespace System.Runtime.Caching { -#if NETCOREAPP +#if NET [UnsupportedOSPlatform("browser")] #endif internal sealed class Counters : EventSource { -#if NETCOREAPP +#if NET private const string EVENT_SOURCE_NAME_ROOT = "System.Runtime.Caching."; private const int NUM_COUNTERS = 7; diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/FileChangeNotificationSystem.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/FileChangeNotificationSystem.cs index 76a6eabd0088a2..ee23f09a97e150 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/FileChangeNotificationSystem.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/FileChangeNotificationSystem.cs @@ -11,7 +11,7 @@ namespace System.Runtime.Caching { -#if NETCOREAPP +#if NET [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/HostFileChangeMonitor.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/HostFileChangeMonitor.cs index fa5afafe378738..374ff288ea0bbe 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/HostFileChangeMonitor.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/HostFileChangeMonitor.cs @@ -98,7 +98,7 @@ private static void InitFCN() #pragma warning disable IDE0074 // Use compound assignment if (fcn == null) { -#if NETCOREAPP +#if NET if (OperatingSystem.IsBrowser() || (OperatingSystem.IsIOS() && !OperatingSystem.IsMacCatalyst()) || OperatingSystem.IsTvOS()) { throw new PlatformNotSupportedException(); diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCache.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCache.cs index 18a0cad6bce880..75053fdbbe52df 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCache.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCache.cs @@ -40,7 +40,7 @@ public class MemoryCache : ObjectCache, IEnumerable, IDisposable private bool _throwOnDisposed; private EventHandler _onAppDomainUnload; private UnhandledExceptionEventHandler _onUnhandledException; -#if NETCOREAPP +#if NET [UnsupportedOSPlatformGuard("browser")] private static bool _countersSupported => !OperatingSystem.IsBrowser(); #else diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCacheStatistics.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCacheStatistics.cs index 96cfc3bda655bd..dba747c4acdfe5 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCacheStatistics.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCacheStatistics.cs @@ -37,7 +37,7 @@ internal sealed class MemoryCacheStatistics : IDisposable private CacheMemoryMonitor _cacheMemoryMonitor; private readonly MemoryCache _memoryCache; private readonly PhysicalMemoryMonitor _physicalMemoryMonitor; -#if NETCOREAPP +#if NET [UnsupportedOSPlatformGuard("browser")] private static bool _configSupported => !OperatingSystem.IsBrowser(); #else @@ -153,7 +153,7 @@ private void InitializeConfiguration(NameValueCollection config) _configCacheMemoryLimitMegabytes = ConfigUtil.GetIntValue(config, ConfigUtil.CacheMemoryLimitMegabytes, _configCacheMemoryLimitMegabytes, true, int.MaxValue); _configPhysicalMemoryLimitPercentage = ConfigUtil.GetIntValue(config, ConfigUtil.PhysicalMemoryLimitPercentage, _configPhysicalMemoryLimitPercentage, true, 100); } -#if !NETCOREAPP +#if !NET if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && _configPhysicalMemoryLimitPercentage > 0) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_PhysicalMemoryLimitPercentage); diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCacheStore.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCacheStore.cs index 1381b7043dd844..146935b54bafa0 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCacheStore.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCacheStore.cs @@ -26,7 +26,7 @@ internal sealed class MemoryCacheStore : IDisposable private volatile bool _useInsertBlock; private readonly MemoryCache _cache; private readonly Counters _perfCounters; -#if NETCOREAPP +#if NET [UnsupportedOSPlatformGuard("browser")] private static bool _countersSupported => !OperatingSystem.IsBrowser(); #else diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/PhysicalMemoryMonitor.Unix.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/PhysicalMemoryMonitor.Unix.cs index 9629e440067137..5390e89ee5ad21 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/PhysicalMemoryMonitor.Unix.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/PhysicalMemoryMonitor.Unix.cs @@ -22,7 +22,7 @@ internal sealed partial class PhysicalMemoryMonitor : MemoryMonitor * highlights how our behavior might be slightly different from windows in these * cases since this was a monitor that cared about actual physical memory. */ -#if NETCOREAPP +#if NET private int lastGCCount; protected override int GetCurrentPressure() diff --git a/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching/CountersTest.cs b/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching/CountersTest.cs index 3fea8fb0cf28f9..9fa077c5be3809 100644 --- a/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching/CountersTest.cs +++ b/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching/CountersTest.cs @@ -73,7 +73,7 @@ private async Task PollCounters(string cacheName) { MemoryCacheCounterValues counters = new MemoryCacheCounterValues(); -#if NETCOREAPP +#if NET var events = new ConcurrentQueue(); using (var listener = new TestEventListener("System.Runtime.Caching." + cacheName, EventLevel.Verbose, eventCounterInterval: 0.1d)) { @@ -134,7 +134,7 @@ private async Task PollCounters(string cacheName) return counters; } -#if NETCOREAPP +#if NET private static async Task WaitForEventCountersAsync(ConcurrentQueue events) { DateTime startTime = DateTime.UtcNow; diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringMarshalingTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringMarshalingTests.cs index 413809f30f6007..6181069f6bf48d 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringMarshalingTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringMarshalingTests.cs @@ -147,7 +147,7 @@ public void StringToHGlobalUniToString() } -#if NETCOREAPP +#if NET [Fact] public void TestUTF8String() { diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTestData.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTestData.cs index f599a02df8df0f..d3e06e69b43926 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTestData.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTestData.cs @@ -60,7 +60,7 @@ using System.Diagnostics.Eventing.Reader; // System.Text.Json is a .NET Core 3.0 specific library -#if NETCOREAPP +#if NET using System.Text.Json; #endif @@ -494,7 +494,7 @@ public static IEnumerable SerializableObjects() yield return new object[] { PopulateException(isolatedStorageException), new TypeSerializableValue[] { new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAEAQAAADJTeXN0ZW0uSU8uSXNvbGF0ZWRTdG9yYWdlLklzb2xhdGVkU3RvcmFnZUV4Y2VwdGlvbgwAAAAJQ2xhc3NOYW1lB01lc3NhZ2UERGF0YQ5Jbm5lckV4Y2VwdGlvbgdIZWxwVVJMEFN0YWNrVHJhY2VTdHJpbmcWUmVtb3RlU3RhY2tUcmFjZVN0cmluZxBSZW1vdGVTdGFja0luZGV4D0V4Y2VwdGlvbk1ldGhvZAdIUmVzdWx0BlNvdXJjZQ1XYXRzb25CdWNrZXRzAQEDAwEBAQABAAEHKVN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsEFN5c3RlbS5FeGNlcHRpb24ICAIGAgAAADJTeXN0ZW0uSU8uSXNvbGF0ZWRTdG9yYWdlLklzb2xhdGVkU3RvcmFnZUV4Y2VwdGlvbgYDAAAAB21lc3NhZ2UJBAAAAAkFAAAABgYAAAAZaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbQYHAAAAFFN0YWNrVHJhY2Ugc3RyaW5nLi4uBggAAAAbUmVtb3RlIFN0YWNrVHJhY2Ugc3RyaW5nLi4uAAAAAAroAwAABgkAAAAXRXhjZXB0aW9uX0NsYXNzX1NhbXBsZXMKBAQAAAApU3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwDAAAABGhlYWQHdmVyc2lvbgVjb3VudAMAADhTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbCtEaWN0aW9uYXJ5Tm9kZQgICQoAAAACAAAAAgAAAAQFAAAAEFN5c3RlbS5FeGNlcHRpb24MAAAACUNsYXNzTmFtZQdNZXNzYWdlBERhdGEOSW5uZXJFeGNlcHRpb24HSGVscFVSTBBTdGFja1RyYWNlU3RyaW5nFlJlbW90ZVN0YWNrVHJhY2VTdHJpbmcQUmVtb3RlU3RhY2tJbmRleA9FeGNlcHRpb25NZXRob2QHSFJlc3VsdAZTb3VyY2UNV2F0c29uQnVja2V0cwEBAwMBAQEAAQABBylTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbBBTeXN0ZW0uRXhjZXB0aW9uCAgCBgsAAAAQU3lzdGVtLkV4Y2VwdGlvbgkDAAAACQ0AAAAJDgAAAAkGAAAACQcAAAAJCAAAAAAAAAAK6AMAAAkJAAAACgQKAAAAOFN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsK0RpY3Rpb25hcnlOb2RlAwAAAANrZXkFdmFsdWUEbmV4dAICAzhTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbCtEaWN0aW9uYXJ5Tm9kZQYTAAAABnNlY3JldAgBAQkUAAAAAQ0AAAAEAAAACRUAAAACAAAAAgAAAAEOAAAABQAAAAkLAAAABhcAAAAXSW5uZXIgZXhjZXB0aW9uIG1lc3NhZ2UKCgoKCgAAAAAKABUTgAoKARQAAAAKAAAACAgBAAAABhgAAAADb25lCgEVAAAACgAAAAkTAAAACAEBCRoAAAABGgAAAAoAAAAICAEAAAAJGAAAAAoL", TargetFrameworkMoniker.netcoreapp20), new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAEAQAAADJTeXN0ZW0uSU8uSXNvbGF0ZWRTdG9yYWdlLklzb2xhdGVkU3RvcmFnZUV4Y2VwdGlvbgwAAAAJQ2xhc3NOYW1lB01lc3NhZ2UERGF0YQ5Jbm5lckV4Y2VwdGlvbgdIZWxwVVJMEFN0YWNrVHJhY2VTdHJpbmcWUmVtb3RlU3RhY2tUcmFjZVN0cmluZxBSZW1vdGVTdGFja0luZGV4D0V4Y2VwdGlvbk1ldGhvZAdIUmVzdWx0BlNvdXJjZQ1XYXRzb25CdWNrZXRzAQEDAwEBAQABAAEHKVN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsEFN5c3RlbS5FeGNlcHRpb24ICAIGAgAAADJTeXN0ZW0uSU8uSXNvbGF0ZWRTdG9yYWdlLklzb2xhdGVkU3RvcmFnZUV4Y2VwdGlvbgYDAAAAB21lc3NhZ2UJBAAAAAkFAAAABgYAAAAZaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbQYHAAAAFFN0YWNrVHJhY2Ugc3RyaW5nLi4uBggAAAAbUmVtb3RlIFN0YWNrVHJhY2Ugc3RyaW5nLi4uAAAAAAroAwAABgkAAAAXRXhjZXB0aW9uX0NsYXNzX1NhbXBsZXMKBAQAAAApU3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwDAAAABGhlYWQHdmVyc2lvbgVjb3VudAMAADhTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbCtEaWN0aW9uYXJ5Tm9kZQgICQoAAAACAAAAAgAAAAQFAAAAEFN5c3RlbS5FeGNlcHRpb24MAAAACUNsYXNzTmFtZQdNZXNzYWdlBERhdGEOSW5uZXJFeGNlcHRpb24HSGVscFVSTBBTdGFja1RyYWNlU3RyaW5nFlJlbW90ZVN0YWNrVHJhY2VTdHJpbmcQUmVtb3RlU3RhY2tJbmRleA9FeGNlcHRpb25NZXRob2QHSFJlc3VsdAZTb3VyY2UNV2F0c29uQnVja2V0cwEBAwMBAQEAAQABBylTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbBBTeXN0ZW0uRXhjZXB0aW9uCAgCBgsAAAAQU3lzdGVtLkV4Y2VwdGlvbgkDAAAACQ0AAAAJDgAAAAkGAAAACQcAAAAJCAAAAAAAAAAK6AMAAAkJAAAACgQKAAAAOFN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsK0RpY3Rpb25hcnlOb2RlAwAAAANrZXkFdmFsdWUEbmV4dAICAzhTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbCtEaWN0aW9uYXJ5Tm9kZQYTAAAABnNlY3JldAgBAQkUAAAAAQ0AAAAEAAAACRUAAAACAAAAAgAAAAEOAAAABQAAAAkLAAAABhcAAAAXSW5uZXIgZXhjZXB0aW9uIG1lc3NhZ2UKCgoKCgAAAAAKABUTgAoKARQAAAAKAAAACAgBAAAABhgAAAADb25lCgEVAAAACgAAAAkTAAAACAEBCRoAAAABGgAAAAoAAAAICAEAAAAJGAAAAAoL", TargetFrameworkMoniker.netfx461) } }; } -#if NETCOREAPP +#if NET var jsonException = new JsonException("message", path: "path", lineNumber: 1, bytePositionInLine: 2, innerException: exception); yield return new object[] { PopulateException(jsonException), new TypeSerializableValue[] { new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAFNTeXN0ZW0uVGV4dC5Kc29uLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Y2M3YjEzZmZjZDJkZGQ1MQUBAAAAHlN5c3RlbS5UZXh0Lkpzb24uSnNvbkV4Y2VwdGlvbhAAAAAJQ2xhc3NOYW1lB01lc3NhZ2UERGF0YQ5Jbm5lckV4Y2VwdGlvbgdIZWxwVVJMEFN0YWNrVHJhY2VTdHJpbmcWUmVtb3RlU3RhY2tUcmFjZVN0cmluZxBSZW1vdGVTdGFja0luZGV4D0V4Y2VwdGlvbk1ldGhvZAdIUmVzdWx0BlNvdXJjZQ1XYXRzb25CdWNrZXRzCkxpbmVOdW1iZXISQnl0ZVBvc2l0aW9uSW5MaW5lBFBhdGgNQWN0dWFsTWVzc2FnZQEBAwMBAQEAAQABBwMDAQEpU3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwQU3lzdGVtLkV4Y2VwdGlvbggIAgxTeXN0ZW0uSW50NjQMU3lzdGVtLkludDY0AgAAAAYDAAAAHlN5c3RlbS5UZXh0Lkpzb24uSnNvbkV4Y2VwdGlvbgYEAAAAB21lc3NhZ2UJBQAAAAkGAAAABgcAAAAZaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbQYIAAAAFFN0YWNrVHJhY2Ugc3RyaW5nLi4uBgkAAAAbUmVtb3RlIFN0YWNrVHJhY2Ugc3RyaW5nLi4uAAAAAAroAwAABgoAAAAXRXhjZXB0aW9uX0NsYXNzX1NhbXBsZXMKCAkBAAAAAAAAAAgJAgAAAAAAAAAGCwAAAARwYXRoCQQAAAAEBQAAAClTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbAMAAAAEaGVhZAd2ZXJzaW9uBWNvdW50AwAAOFN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsK0RpY3Rpb25hcnlOb2RlCAgJDQAAAAIAAAACAAAABAYAAAAQU3lzdGVtLkV4Y2VwdGlvbgwAAAAJQ2xhc3NOYW1lB01lc3NhZ2UERGF0YQ5Jbm5lckV4Y2VwdGlvbgdIZWxwVVJMEFN0YWNrVHJhY2VTdHJpbmcWUmVtb3RlU3RhY2tUcmFjZVN0cmluZxBSZW1vdGVTdGFja0luZGV4D0V4Y2VwdGlvbk1ldGhvZAdIUmVzdWx0BlNvdXJjZQ1XYXRzb25CdWNrZXRzAQEDAwEBAQABAAEHKVN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsEFN5c3RlbS5FeGNlcHRpb24ICAIGDgAAABBTeXN0ZW0uRXhjZXB0aW9uCQQAAAAJEAAAAAkRAAAACQcAAAAJCAAAAAkJAAAAAAAAAAroAwAACQoAAAAKBA0AAAA4U3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwrRGljdGlvbmFyeU5vZGUDAAAAA2tleQV2YWx1ZQRuZXh0AgIDOFN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsK0RpY3Rpb25hcnlOb2RlBhYAAAAGc2VjcmV0CAEBCRcAAAABEAAAAAUAAAAJGAAAAAIAAAACAAAAAREAAAAGAAAACQ4AAAAGGgAAABdJbm5lciBleGNlcHRpb24gbWVzc2FnZQoKCgoKAAAAAAoAFROACgoBFwAAAA0AAAAICAEAAAAGGwAAAANvbmUKARgAAAANAAAACRYAAAAIAQEJHQAAAAEdAAAADQAAAAgIAQAAAAkbAAAACgs=", TargetFrameworkMoniker.netcoreapp30) } }; @@ -677,7 +677,7 @@ public static IEnumerable SerializableObjects() yield return new object[] { PopulateException(smtpFailedRecipientsException), new TypeSerializableValue[] { new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAElTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAtU3lzdGVtLk5ldC5NYWlsLlNtdHBGYWlsZWRSZWNpcGllbnRzRXhjZXB0aW9uDwAAAAlDbGFzc05hbWUHTWVzc2FnZQREYXRhDklubmVyRXhjZXB0aW9uB0hlbHBVUkwQU3RhY2tUcmFjZVN0cmluZxZSZW1vdGVTdGFja1RyYWNlU3RyaW5nEFJlbW90ZVN0YWNrSW5kZXgPRXhjZXB0aW9uTWV0aG9kB0hSZXN1bHQGU291cmNlDVdhdHNvbkJ1Y2tldHMGU3RhdHVzD2ZhaWxlZFJlY2lwaWVudA9pbm5lckV4Y2VwdGlvbnMBAQMEAQEBAAEAAQcAAQQpU3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwsU3lzdGVtLk5ldC5NYWlsLlNtdHBGYWlsZWRSZWNpcGllbnRFeGNlcHRpb24CAAAACAgCCC5TeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudEV4Y2VwdGlvbltdAgAAAAIAAAAGAwAAAC1TeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudHNFeGNlcHRpb24GBAAAAAdtZXNzYWdlCQUAAAAJBgAAAAYHAAAAGWh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20GCAAAABRTdGFja1RyYWNlIHN0cmluZy4uLgYJAAAAG1JlbW90ZSBTdGFja1RyYWNlIHN0cmluZy4uLgAAAAAK6AMAAAYKAAAAF0V4Y2VwdGlvbl9DbGFzc19TYW1wbGVzCv////8GCwAAAA9mYWlsZWRSZWNpcGllbnQJDAAAAAQFAAAAKVN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsAwAAAARoZWFkB3ZlcnNpb24FY291bnQDAAA4U3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwrRGljdGlvbmFyeU5vZGUICAkNAAAAAgAAAAIAAAAFBgAAACxTeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudEV4Y2VwdGlvbg4AAAAJQ2xhc3NOYW1lB01lc3NhZ2UERGF0YQ5Jbm5lckV4Y2VwdGlvbgdIZWxwVVJMEFN0YWNrVHJhY2VTdHJpbmcWUmVtb3RlU3RhY2tUcmFjZVN0cmluZxBSZW1vdGVTdGFja0luZGV4D0V4Y2VwdGlvbk1ldGhvZAdIUmVzdWx0BlNvdXJjZQ1XYXRzb25CdWNrZXRzBlN0YXR1cw9mYWlsZWRSZWNpcGllbnQBAQMDAQEBAAEAAQcAASlTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbBBTeXN0ZW0uRXhjZXB0aW9uCAgCCAIAAAAGDgAAACxTeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudEV4Y2VwdGlvbgYPAAAAMkNvbXBsZXRlZC4gVGhlIHNlcnZlciByZXNwb25zZSB3YXM6IHNlcnZlclJlc3BvbnNlCRAAAAAKCQcAAAAJCAAAAAkJAAAAAAAAAAroAwAACQoAAAAK+gAAAAkLAAAABwwAAAAAAQAAAAEAAAAELFN5c3RlbS5OZXQuTWFpbC5TbXRwRmFpbGVkUmVjaXBpZW50RXhjZXB0aW9uAgAAAAkGAAAABA0AAAA4U3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwrRGljdGlvbmFyeU5vZGUDAAAAA2tleQV2YWx1ZQRuZXh0AgIDOFN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsK0RpY3Rpb25hcnlOb2RlBhcAAAAGc2VjcmV0CAEBCRgAAAABEAAAAAUAAAAJGQAAAAIAAAACAAAAARgAAAANAAAACAgBAAAABhoAAAADb25lCgEZAAAADQAAAAkXAAAACAEBCRwAAAABHAAAAA0AAAAICAEAAAAJGgAAAAoL", TargetFrameworkMoniker.netcoreapp20), new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAElTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAtU3lzdGVtLk5ldC5NYWlsLlNtdHBGYWlsZWRSZWNpcGllbnRzRXhjZXB0aW9uDwAAAAlDbGFzc05hbWUHTWVzc2FnZQREYXRhDklubmVyRXhjZXB0aW9uB0hlbHBVUkwQU3RhY2tUcmFjZVN0cmluZxZSZW1vdGVTdGFja1RyYWNlU3RyaW5nEFJlbW90ZVN0YWNrSW5kZXgPRXhjZXB0aW9uTWV0aG9kB0hSZXN1bHQGU291cmNlDVdhdHNvbkJ1Y2tldHMGU3RhdHVzD2ZhaWxlZFJlY2lwaWVudA9pbm5lckV4Y2VwdGlvbnMBAQMEAQEBAAEAAQcAAQQpU3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwsU3lzdGVtLk5ldC5NYWlsLlNtdHBGYWlsZWRSZWNpcGllbnRFeGNlcHRpb24CAAAACAgCCC5TeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudEV4Y2VwdGlvbltdAgAAAAIAAAAGAwAAAC1TeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudHNFeGNlcHRpb24GBAAAAAdtZXNzYWdlCQUAAAAJBgAAAAYHAAAAGWh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20GCAAAABRTdGFja1RyYWNlIHN0cmluZy4uLgYJAAAAG1JlbW90ZSBTdGFja1RyYWNlIHN0cmluZy4uLgAAAAAK6AMAAAYKAAAAF0V4Y2VwdGlvbl9DbGFzc19TYW1wbGVzCv////8GCwAAAA9mYWlsZWRSZWNpcGllbnQJDAAAAAQFAAAAKVN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsAwAAAARoZWFkB3ZlcnNpb24FY291bnQDAAA4U3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwrRGljdGlvbmFyeU5vZGUICAkNAAAAAgAAAAIAAAAFBgAAACxTeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudEV4Y2VwdGlvbg4AAAAJQ2xhc3NOYW1lB01lc3NhZ2UERGF0YQ5Jbm5lckV4Y2VwdGlvbgdIZWxwVVJMEFN0YWNrVHJhY2VTdHJpbmcWUmVtb3RlU3RhY2tUcmFjZVN0cmluZxBSZW1vdGVTdGFja0luZGV4D0V4Y2VwdGlvbk1ldGhvZAdIUmVzdWx0BlNvdXJjZQ1XYXRzb25CdWNrZXRzBlN0YXR1cw9mYWlsZWRSZWNpcGllbnQBAQMDAQEBAAEAAQcAASlTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbBBTeXN0ZW0uRXhjZXB0aW9uCAgCCAIAAAAGDgAAACxTeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudEV4Y2VwdGlvbgYPAAAAMkNvbXBsZXRlZC4gVGhlIHNlcnZlciByZXNwb25zZSB3YXM6IHNlcnZlclJlc3BvbnNlCRAAAAAKCQcAAAAJCAAAAAkJAAAAAAAAAAroAwAACQoAAAAK+gAAAAkLAAAABwwAAAAAAQAAAAEAAAAELFN5c3RlbS5OZXQuTWFpbC5TbXRwRmFpbGVkUmVjaXBpZW50RXhjZXB0aW9uAgAAAAkGAAAABA0AAAA4U3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwrRGljdGlvbmFyeU5vZGUDAAAAA2tleQV2YWx1ZQRuZXh0AgIDOFN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsK0RpY3Rpb25hcnlOb2RlBhcAAAAGc2VjcmV0CAEBCRgAAAABEAAAAAUAAAAJGQAAAAIAAAACAAAAARgAAAANAAAACAgBAAAABhoAAAADb25lCgEZAAAADQAAAAkXAAAACAEBCRwAAAABHAAAAA0AAAAICAEAAAAJGgAAAAoL", TargetFrameworkMoniker.netfx461) } }; } -#if NETCOREAPP +#if NET var ambiguousImplementationException = new AmbiguousImplementationException(); yield return new object[] { PopulateException(ambiguousImplementationException, false), new TypeSerializableValue[] { new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uUnVudGltZSwgVmVyc2lvbj00LjIuMS4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAAC9TeXN0ZW0uUnVudGltZS5BbWJpZ3VvdXNJbXBsZW1lbnRhdGlvbkV4Y2VwdGlvbgwAAAAJQ2xhc3NOYW1lB01lc3NhZ2UERGF0YQ5Jbm5lckV4Y2VwdGlvbgdIZWxwVVJMEFN0YWNrVHJhY2VTdHJpbmcWUmVtb3RlU3RhY2tUcmFjZVN0cmluZxBSZW1vdGVTdGFja0luZGV4D0V4Y2VwdGlvbk1ldGhvZAdIUmVzdWx0BlNvdXJjZQ1XYXRzb25CdWNrZXRzAQEDAwEBAQABAAEHKVN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsEFN5c3RlbS5FeGNlcHRpb24ICAICAAAABgMAAAAvU3lzdGVtLlJ1bnRpbWUuQW1iaWd1b3VzSW1wbGVtZW50YXRpb25FeGNlcHRpb24GBAAAAB9BbWJpZ3VvdXMgaW1wbGVtZW50YXRpb24gZm91bmQuCQUAAAAKBgYAAAAZaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbQYHAAAAFFN0YWNrVHJhY2Ugc3RyaW5nLi4uBggAAAAbUmVtb3RlIFN0YWNrVHJhY2Ugc3RyaW5nLi4uAAAAAApqEBOABgkAAAAXRXhjZXB0aW9uX0NsYXNzX1NhbXBsZXMKBAUAAAApU3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwDAAAABGhlYWQHdmVyc2lvbgVjb3VudAMAADhTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbCtEaWN0aW9uYXJ5Tm9kZQgICQoAAAACAAAAAgAAAAQKAAAAOFN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsK0RpY3Rpb25hcnlOb2RlAwAAAANrZXkFdmFsdWUEbmV4dAICAzhTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbCtEaWN0aW9uYXJ5Tm9kZQYLAAAABnNlY3JldAgBAQkMAAAAAQwAAAAKAAAACAgBAAAABg0AAAADb25lCgs=", TargetFrameworkMoniker.netcoreapp30) } }; var switchExpressionException = new SwitchExpressionException(34); diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/EqualityExtensions.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/EqualityExtensions.cs index e6d9652007e396..cbb1b2bba6b2ad 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/EqualityExtensions.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/EqualityExtensions.cs @@ -23,7 +23,7 @@ using Xunit; // System.Text.Json is a .NET Core 3.0 specific library -#if NETCOREAPP +#if NET using System.Text.Json; #endif @@ -1195,7 +1195,7 @@ public static void IsEqual(this AggregateException @this, AggregateException oth @this.InnerExceptions.CheckSequenceEquals(other.InnerExceptions, isSamePlatform); } -#if NETCOREAPP +#if NET public static void IsEqual(this JsonException @this, JsonException other, bool isSamePlatform) { if (@this == null && other == null) diff --git a/src/libraries/System.Runtime/tests/System.Resources.ResourceManager.Tests/ResourceManagerTests.cs b/src/libraries/System.Runtime/tests/System.Resources.ResourceManager.Tests/ResourceManagerTests.cs index 6bb68cb65b1455..b80b709fd171fe 100644 --- a/src/libraries/System.Runtime/tests/System.Resources.ResourceManager.Tests/ResourceManagerTests.cs +++ b/src/libraries/System.Runtime/tests/System.Resources.ResourceManager.Tests/ResourceManagerTests.cs @@ -112,7 +112,7 @@ public static void GetString_FromTestClassWithoutNeutralResources() static int ResourcesAfAZEvents = 0; -#if NETCOREAPP +#if NET static System.Reflection.Assembly AssemblyResolvingEventHandler(System.Runtime.Loader.AssemblyLoadContext alc, System.Reflection.AssemblyName name) { if (name.FullName.StartsWith("System.Resources.ResourceManager.Tests.resources")) @@ -138,7 +138,7 @@ static System.Reflection.Assembly AssemblyResolveEventHandler(object sender, Res { if (name.Contains("Culture=af-ZA")) { -#if NETCOREAPP +#if NET Assert.Equal(1, ResourcesAfAZEvents); #else Assert.Equal(0, ResourcesAfAZEvents); @@ -162,7 +162,7 @@ public static void GetString_ExpectEvents() private static void Remote_ExpectEvents() { -#if NETCOREAPP +#if NET System.Runtime.Loader.AssemblyLoadContext.Default.Resolving += AssemblyResolvingEventHandler; #endif AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(AssemblyResolveEventHandler); @@ -176,7 +176,7 @@ private static void Remote_ExpectEvents() string actual = resourceManager.GetString("One", culture); Assert.Equal("Value-One", actual); -#if NETCOREAPP +#if NET Assert.Equal(2, ResourcesAfAZEvents); #else Assert.Equal(1, ResourcesAfAZEvents); diff --git a/src/libraries/System.Runtime/tests/System.ValueTuple.Tests/ValueTupleTests.cs b/src/libraries/System.Runtime/tests/System.ValueTuple.Tests/ValueTupleTests.cs index 147b4ea9647cbf..0e85e1565149db 100644 --- a/src/libraries/System.Runtime/tests/System.ValueTuple.Tests/ValueTupleTests.cs +++ b/src/libraries/System.Runtime/tests/System.ValueTuple.Tests/ValueTupleTests.cs @@ -3,7 +3,7 @@ using System.Collections; using Xunit; -#if NETCOREAPP +#if NET using System.Runtime.CompilerServices; #endif @@ -775,7 +775,7 @@ public static void ZeroTuples() AssertExtensions.Throws("other", () => ((IStructuralComparable)a).CompareTo("string", DummyTestComparer.Instance)); Assert.Equal("(1, 2, 3, 4, 5, 6, 7, )", CreateLong(1, 2, 3, 4, 5, 6, 7, new ValueTuple()).ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(); Assert.Throws(() => it[-1].ToString()); Assert.Throws(() => it[0].ToString()); @@ -812,7 +812,7 @@ public static void OneTuples() Assert.Equal("()", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(1); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -852,7 +852,7 @@ public static void TwoTuples() Assert.Equal("(, )", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(1, 2); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -897,7 +897,7 @@ public static void ThreeTuples() Assert.Equal("(, , )", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(1, 2, 3); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -948,7 +948,7 @@ public static void FourTuples() Assert.Equal("(, , , )", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(1, 2, 3, 4); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -1004,7 +1004,7 @@ public static void FiveTuples() Assert.Equal("(, , , , )", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(1, 2, 3, 4, 5); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -1065,7 +1065,7 @@ public static void SixTuples() Assert.Equal("(, , , , , )", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(1, 2, 3, 4, 5, 6); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -1131,7 +1131,7 @@ public static void SevenTuples() Assert.Equal("(, , , , , , )", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(1, 2, 3, 4, 5, 6, 7); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -1223,7 +1223,7 @@ public static void EightTuples() Assert.Equal("(, , , , , , , )", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8)); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -1312,7 +1312,7 @@ public static void EightTuplesWithBadRest() Assert.Equal("(1, 2, 3, 4, 5, 6, 7, 1, 0, 0, 0, 0, 0, 0, 42)", CreateLong(1, 2, 3, 4, 5, 6, 7, d).ToString()); -#if NETCOREAPP +#if NET ITuple it = d; Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); diff --git a/src/libraries/System.Security.Cryptography.Cose/src/System/Security/Cryptography/Cose/CoseSignature.cs b/src/libraries/System.Security.Cryptography.Cose/src/System/Security/Cryptography/Cose/CoseSignature.cs index 831c5c8f676bd2..da0962a48b3bdf 100644 --- a/src/libraries/System.Security.Cryptography.Cose/src/System/Security/Cryptography/Cose/CoseSignature.cs +++ b/src/libraries/System.Security.Cryptography.Cose/src/System/Security/Cryptography/Cose/CoseSignature.cs @@ -450,7 +450,7 @@ private bool VerifyCore(AsymmetricAlgorithm key, ReadOnlySpan contentBytes private bool VerifyHash(AsymmetricAlgorithm key, IncrementalHash hasher, HashAlgorithmName hashAlgorithm, KeyType keyType, RSASignaturePadding? padding) { -#if NETCOREAPP +#if NET Debug.Assert(hasher.HashLengthInBytes <= 512 / 8); // largest hash we can get (SHA512). Span hash = stackalloc byte[hasher.HashLengthInBytes]; hasher.GetHashAndReset(hash); diff --git a/src/libraries/System.Security.Cryptography.Cose/tests/CoseTestHelpers.cs b/src/libraries/System.Security.Cryptography.Cose/tests/CoseTestHelpers.cs index 4eb5d7dba72dd5..2e73ce54ffefbd 100644 --- a/src/libraries/System.Security.Cryptography.Cose/tests/CoseTestHelpers.cs +++ b/src/libraries/System.Security.Cryptography.Cose/tests/CoseTestHelpers.cs @@ -588,7 +588,7 @@ public static IEnumerable AllCborTypes() w.WriteDouble(default); yield return ReturnDataAndReset(w); -#if NETCOREAPP +#if NET w.WriteHalf(default); yield return ReturnDataAndReset(w); #endif diff --git a/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.cs b/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.cs index 6c17e4ac084049..f687149f802229 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.cs @@ -83,7 +83,7 @@ public void Reset() { } public sealed partial class CmsSigner { public CmsSigner() { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("CmsSigner(CspParameters) is obsolete and is not supported. Use an alternative constructor instead.", DiagnosticId = "SYSLIB0034", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] @@ -270,7 +270,7 @@ internal SignerInfo() { } public void CheckHash() { } public void CheckSignature(bool verifySignatureOnly) { } public void CheckSignature(System.Security.Cryptography.X509Certificates.X509Certificate2Collection extraStore, bool verifySignatureOnly) { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("ComputeCounterSignature without specifying a CmsSigner is obsolete and is not supported. Use the overload that accepts a CmsSigner.", DiagnosticId = "SYSLIB0035", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.KeyTrans.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.KeyTrans.cs index e95be29e999099..fd9cc62ac0ec22 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.KeyTrans.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.KeyTrans.cs @@ -189,7 +189,7 @@ private KeyTransRecipientInfoAsn MakeKtri( return null; } -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 byte[]? cek = null; int cekLength = 0; diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.cs index c0831046595a23..69525a16b001e9 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.cs @@ -80,7 +80,7 @@ public override byte[] GetSubjectKeyIdentifier(X509Certificate2 certificate) return (T?)(object?)certificate.GetRSAPrivateKey(); if (typeof(T) == typeof(ECDsa)) return (T?)(object?)certificate.GetECDsaPrivateKey(); -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 if (typeof(T) == typeof(DSA) && Internal.Cryptography.Helpers.IsDSASupported) return (T?)(object?)certificate.GetDSAPrivateKey(); #endif diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/PkcsPalWindows.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/PkcsPalWindows.cs index ab05ccc6f9f6ef..db93dff50c67ec 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/PkcsPalWindows.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/PkcsPalWindows.cs @@ -127,7 +127,7 @@ public sealed override byte[] GetSubjectKeyIdentifier(X509Certificate2 certifica if (keySpec == CryptKeySpec.CERT_NCRYPT_KEY_SPEC) { -#if NETSTANDARD || NETCOREAPP +#if NETSTANDARD || NET Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); #endif diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/PkcsHelpers.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/PkcsHelpers.cs index b26ff355f378e8..1cf3bc1f4a5a20 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/PkcsHelpers.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/PkcsHelpers.cs @@ -36,7 +36,7 @@ private static bool DetectInitOnlyOid() } } -#if !NETCOREAPP && !NETSTANDARD2_1 +#if !NET && !NETSTANDARD2_1 // Compatibility API. internal static void AppendData(this IncrementalHash hasher, ReadOnlySpan data) { @@ -369,7 +369,7 @@ private static string ToUpperHexString(ReadOnlySpan ba) { return Convert.ToHexString(ba); } -#elif NETCOREAPP || NETSTANDARD2_1 +#elif NETSTANDARD2_1 private static string ToUpperHexString(ReadOnlySpan ba) { return HexConverter.ToString(ba, HexConverter.Casing.Upper); @@ -433,7 +433,7 @@ public static Pkcs9AttributeObject CreateBestPkcs9AttributeObjectAvailable(Oid o Oids.SigningTime => new Pkcs9SigningTime(encodedAttribute), Oids.ContentType => new Pkcs9ContentType(encodedAttribute), Oids.MessageDigest => new Pkcs9MessageDigest(encodedAttribute), -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 Oids.LocalKeyId => new Pkcs9LocalKeyId() { RawData = encodedAttribute.ToArray() }, #endif _ => new Pkcs9AttributeObject(oid, encodedAttribute), diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs index 97192c83b91652..183520aa9c3f0a 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs @@ -43,7 +43,7 @@ protected override bool VerifyKeyType(AsymmetricAlgorithm key) } internal override bool VerifySignature( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan valueHash, ReadOnlyMemory signature, #else @@ -76,7 +76,7 @@ internal override bool VerifySignature( DSAParameters dsaParameters = dsa.ExportParameters(false); int bufSize = 2 * dsaParameters.Q!.Length; -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 byte[] rented = CryptoPool.Rent(bufSize); Span ieee = new Span(rented, 0, bufSize); @@ -91,7 +91,7 @@ internal override bool VerifySignature( } return dsa.VerifySignature(valueHash, ieee); -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 } finally { @@ -101,7 +101,7 @@ internal override bool VerifySignature( } protected override bool Sign( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan dataHash, #else byte[] dataHash, @@ -145,7 +145,7 @@ protected override bool Sign( signatureAlgorithm = oidValue; -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 // The Q size cannot be bigger than the KeySize. byte[] rented = CryptoPool.Rent(dsa.KeySize / 8); int bytesWritten = 0; diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs index dd098e46362ea6..e89e6e5232d514 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs @@ -44,7 +44,7 @@ protected override bool VerifyKeyType(AsymmetricAlgorithm key) } internal override bool VerifySignature( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan valueHash, ReadOnlyMemory signature, #else @@ -80,7 +80,7 @@ internal override bool VerifySignature( bufSize = 2 * fieldSize; } -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 byte[] rented = CryptoPool.Rent(bufSize); Span ieee = new Span(rented, 0, bufSize); @@ -95,7 +95,7 @@ internal override bool VerifySignature( } return key.VerifyHash(valueHash, ieee); -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 } finally { @@ -105,7 +105,7 @@ internal override bool VerifySignature( } protected override bool Sign( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan dataHash, #else byte[] dataHash, @@ -152,7 +152,7 @@ protected override bool Sign( signatureAlgorithm = oidValue; -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 int bufSize; checked { @@ -188,7 +188,7 @@ protected override bool Sign( #endif signatureValue = DsaIeeeToDer(key.SignHash( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 dataHash.ToArray() #else dataHash diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs index 51677662dd5219..80aa6abb9085a3 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs @@ -45,7 +45,7 @@ protected override bool VerifyKeyType(AsymmetricAlgorithm key) } internal override bool VerifySignature( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan valueHash, ReadOnlyMemory signature, #else @@ -81,7 +81,7 @@ internal override bool VerifySignature( return publicKey.VerifyHash( valueHash, -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 signature.Span, #else signature, @@ -97,7 +97,7 @@ protected abstract RSASignaturePadding GetSignaturePadding( int digestValueLength); private protected static bool SignCore( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan dataHash, #else byte[] dataHash, @@ -122,7 +122,7 @@ private protected static bool SignCore( return false; } -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 byte[] signature = new byte[privateKey.KeySize / 8]; bool signed = privateKey.TrySignHash( @@ -147,7 +147,7 @@ private protected static bool SignCore( } #endif signatureValue = privateKey.SignHash( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 dataHash.ToArray(), #else dataHash, @@ -199,7 +199,7 @@ protected override RSASignaturePadding GetSignaturePadding( } protected override bool Sign( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan dataHash, #else byte[] dataHash, @@ -319,7 +319,7 @@ protected override RSASignaturePadding GetSignaturePadding( } protected override bool Sign( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan dataHash, #else byte[] dataHash, diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs index 7cf3436b54aa63..a0595c61dc3c00 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs @@ -30,7 +30,7 @@ static CmsSignature() protected abstract bool VerifyKeyType(AsymmetricAlgorithm key); internal abstract bool VerifySignature( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan valueHash, ReadOnlyMemory signature, #else @@ -43,7 +43,7 @@ internal abstract bool VerifySignature( X509Certificate2 certificate); protected abstract bool Sign( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan dataHash, #else byte[] dataHash, @@ -112,7 +112,7 @@ protected abstract bool Sign( } internal static bool Sign( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan dataHash, #else byte[] dataHash, @@ -224,7 +224,7 @@ private static byte[] DsaIeeeToDer(ReadOnlySpan ieeeSignature) { writer.PushSequence(); -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 // r BigInteger val = new BigInteger( ieeeSignature.Slice(0, fieldSize), diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs index d9d592c7d578ec..04c2fd59e78aa7 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 @@ -73,7 +73,7 @@ public CmsSigner(X509Certificate2? certificate) { } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CmsSignerCspParamsCtorMessage, DiagnosticId = Obsoletions.CmsSignerCspParamsCtorDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [EditorBrowsable(EditorBrowsableState.Never)] diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs index 0b0700d2658410..51dccc6458d6d2 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs @@ -96,7 +96,7 @@ public X509Certificate2Collection Certificates if (choice.Certificate.HasValue) { coll.Add(new X509Certificate2(choice.Certificate.Value -#if NETCOREAPP +#if NET .Span #else .ToArray() diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs index 021e1f8e9be2d4..46b6fc056e4c1b 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs @@ -262,7 +262,7 @@ private SignerInfoCollection GetCounterSigners(AttributeAsn[] unsignedAttrs) return new SignerInfoCollection(signerInfos.ToArray()); } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.SignerInfoCounterSigMessage, DiagnosticId = Obsoletions.SignerInfoCounterSigDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [EditorBrowsable(EditorBrowsableState.Never)] @@ -746,7 +746,7 @@ private bool VerifySignature( return false; } -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 // SHA-2-512 is the biggest digest type we know about. Span digestValue = stackalloc byte[512 / 8]; ReadOnlySpan digest = digestValue; diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/CertLoader.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/CertLoader.cs index be71f91529a105..e310abc86cd463 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/CertLoader.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/CertLoader.cs @@ -14,7 +14,7 @@ internal abstract partial class CertLoader // Prefer ephemeral when available private static X509KeyStorageFlags GetBestKeyStorageFlags() { -#if NETCOREAPP +#if NET if (OperatingSystem.IsWindows()) { // On Windows 7 ephemeral keys with a key usage embedded in the PFX @@ -176,7 +176,7 @@ public CertLoaderFromRawData(byte[] cerData, byte[] pfxData = null, string passw internal override CertLoader CloneAsEphemeralLoader() { -#if NETCOREAPP +#if NET return new CertLoaderFromRawData(CerData, PfxData, Password) { KeyStorageFlags = X509KeyStorageFlags.EphemeralKeySet, diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/DecryptTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/DecryptTests.cs index bca63841dfde72..58ff32fd632859 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/DecryptTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/DecryptTests.cs @@ -835,7 +835,7 @@ internal void VerifySimpleDecrypt(byte[] encodedMessage, CertLoader certLoader, if (cert == null) return; // Sorry - CertLoader is not configured to load certs with private keys - we've tested as much as we can. -#if NETCOREAPP // API not present on netfx +#if NET // API not present on netfx if (_useExplicitPrivateKey) { using (X509Certificate2 pubCert = certLoader.GetCertificate()) diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/StateTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/StateTests.cs index 02b83db21688f0..288aa11e4ad94f 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/StateTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/StateTests.cs @@ -274,7 +274,7 @@ public static void PostDecode_ContentInfo_netcore() [Theory] [OuterLoop(/* Leaks key on disk if interrupted */)] [InlineData(false)] -#if NETCOREAPP // API not supported on netfx +#if NET // API not supported on netfx [InlineData(true)] #endif public static void PostDecrypt_Encode(bool useExplicitPrivateKey) @@ -300,7 +300,7 @@ public static void PostDecrypt_Encode(bool useExplicitPrivateKey) if (useExplicitPrivateKey) { -#if NETCOREAPP +#if NET ecms.Decrypt(r[0], cer.GetRSAPrivateKey()); #else Assert.Fail("Should not run on this platform"); @@ -362,7 +362,7 @@ public static void PostDecrypt_RecipientInfos() [Theory] [OuterLoop(/* Leaks key on disk if interrupted */)] [InlineData(false)] -#if NETCOREAPP // API not supported on netfx +#if NET // API not supported on netfx [InlineData(true)] #endif public static void PostDecrypt_Decrypt(bool useExplicitPrivateKey) @@ -404,7 +404,7 @@ public static void PostDecrypt_Decrypt(bool useExplicitPrivateKey) { if (useExplicitPrivateKey) { -#if NETCOREAPP +#if NET ecms.Decrypt(r[0], cert1.GetRSAPrivateKey()); #else Assert.Fail("Should not run on this platform"); diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/CertBagTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/CertBagTests.cs index 68f364b9d858ab..45ffae839acdac 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/CertBagTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/CertBagTests.cs @@ -47,7 +47,7 @@ public static void OidCtorPreservesFriendlyName() Oid firstCall = certBag.GetCertificateType(); Oid secondCall = certBag.GetCertificateType(); -#if !NETCOREAPP +#if !NET Assert.NotSame(oid, firstCall); Assert.NotSame(oid, secondCall); Assert.NotSame(firstCall, secondCall); diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/Pkcs12SafeBagTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/Pkcs12SafeBagTests.cs index d5ace8984490ac..9c7f5e360df666 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/Pkcs12SafeBagTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/Pkcs12SafeBagTests.cs @@ -66,7 +66,7 @@ public static void GetBagIdIsFactory() Assert.Equal(Oids.Aes192, firstCall.Value); Assert.Equal(firstCall.Value, secondCall.Value); -#if !NETCOREAPP +#if !NET Assert.NotSame(firstCall, secondCall); #endif } diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/CmsSignerTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/CmsSignerTests.cs index a99d2f8d4dde94..27be5cf21152f1 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/CmsSignerTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/CmsSignerTests.cs @@ -21,7 +21,7 @@ public static void SignerIdentifierType_InvalidValues(SubjectIdentifierType inva () => signer.SignerIdentifierType = invalidType); } -#if NETCOREAPP +#if NET [Fact] public static void SignaturePadding_InvalidValue() { diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs index 7eee42aa5db719..c0c1421daac423 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs @@ -562,7 +562,7 @@ public static void AddFirstSigner_DSA(SubjectIdentifierType identifierType, bool Assert.NotSame(cms.Certificates[0], firstSigner.Certificate); Assert.Equal(cms.Certificates[0], firstSigner.Certificate); -#if NETCOREAPP +#if NET byte[] signature = firstSigner.GetSignature(); Assert.NotEmpty(signature); // DSA PKIX signature format is a DER SEQUENCE. @@ -581,7 +581,7 @@ public static void AddFirstSigner_DSA(SubjectIdentifierType identifierType, bool Assert.Equal(identifierType, cms.SignerInfos[0].SignerIdentifier.Type); Assert.Equal(firstSigner.Certificate, cms.SignerInfos[0].Certificate); -#if NETCOREAPP +#if NET byte[] sig2 = cms.SignerInfos[0].GetSignature(); Assert.Equal(signature, sig2); #endif @@ -633,7 +633,7 @@ public static void AddFirstSigner_ECDSA(SubjectIdentifierType identifierType, bo Assert.NotSame(cms.Certificates[0], firstSigner.Certificate); Assert.Equal(cms.Certificates[0], firstSigner.Certificate); -#if NETCOREAPP +#if NET byte[] signature = firstSigner.GetSignature(); Assert.NotEmpty(signature); // ECDSA PKIX signature format is a DER SEQUENCE. @@ -655,7 +655,7 @@ public static void AddFirstSigner_ECDSA(SubjectIdentifierType identifierType, bo Assert.Equal(identifierType, cms.SignerInfos[0].SignerIdentifier.Type); Assert.Equal(firstSigner.Certificate, cms.SignerInfos[0].Certificate); -#if NETCOREAPP +#if NET byte[] sig2 = cms.SignerInfos[0].GetSignature(); Assert.Equal(signature, sig2); #endif @@ -1165,7 +1165,7 @@ public static void EnsureDataIsolation_NewDocument(bool detached) // CheckSignature doesn't read the public mutable data contentInfo.Content[0] ^= 0xFF; -#if !NETCOREAPP +#if !NET contentInfo.ContentType.Value = Oids.Pkcs7Hashed; #endif cms.CheckSignature(true); diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsWholeDocumentTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsWholeDocumentTests.cs index 8918d7adbb66c6..c5b7c000e2b733 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsWholeDocumentTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsWholeDocumentTests.cs @@ -60,7 +60,7 @@ public static void ReadRsaPssDocument(bool fromSpan) Assert.Equal(SubjectIdentifierType.SubjectKeyIdentifier, signer.SignerIdentifier.Type); Assert.Equal("1063CAB14FB14C47DC211C0E0285F3EE5946BF2D", signer.SignerIdentifier.Value); Assert.Equal("2.16.840.1.101.3.4.2.1", signer.DigestAlgorithm.Value); -#if NETCOREAPP +#if NET Assert.Equal("1.2.840.113549.1.1.10", signer.SignatureAlgorithm.Value); #endif @@ -91,7 +91,7 @@ public static void ReadRsaPssDocument(bool fromSpan) messageDigestAttr.MessageDigest.ByteArrayToHex()); Assert.IsType(signedAttrs[3].Values[0]); -#if !NETCOREAPP +#if !NET Assert.NotSame(signedAttrs[3].Oid, signedAttrs[3].Values[0].Oid); #endif Assert.Equal( @@ -101,7 +101,7 @@ public static void ReadRsaPssDocument(bool fromSpan) "082A864886F70D0302020128", signedAttrs[3].Values[0].RawData.ByteArrayToHex()); -#if NETCOREAPP +#if NET Assert.Equal( "B93E81D141B3C9F159AB0021910635DC72E8E860BE43C28E5D53243D6DC247B7" + "D4F18C20195E80DEDCC75B29C43CE5047AD775B65BFC93589BD748B950C68BAD" + @@ -170,7 +170,7 @@ public static void ReadRsaPkcs1SimpleDocument() Assert.Equal(SubjectIdentifierType.IssuerAndSerialNumber, signer.SignerIdentifier.Type); Assert.Equal(Oids.Sha1, signer.DigestAlgorithm.Value); -#if NETCOREAPP +#if NET Assert.Equal(Oids.Rsa, signer.SignatureAlgorithm.Value); Assert.Equal( @@ -237,7 +237,7 @@ public static void ReadRsaPkcs1CounterSigned() Assert.Equal(SubjectIdentifierType.IssuerAndSerialNumber, signer.SignerIdentifier.Type); Assert.Equal(Oids.Sha1, signer.DigestAlgorithm.Value); -#if NETCOREAPP +#if NET Assert.Equal(Oids.Rsa, signer.SignatureAlgorithm.Value); Assert.Equal( @@ -311,7 +311,7 @@ public static void CheckNoSignatureDocument() Assert.Null(signer.Certificate); Assert.Equal(Oids.Sha1, signer.DigestAlgorithm.Value); -#if NETCOREAPP +#if NET Assert.Equal("1.3.6.1.5.5.7.6.2", signer.SignatureAlgorithm.Value); Assert.Equal( @@ -370,7 +370,7 @@ public static void CheckNoSignatureDocument() "833378066BDCCBA7047EF6919843D181A57D6479", csMessageDigest.MessageDigest.ByteArrayToHex()); -#if NETCOREAPP +#if NET Assert.Equal(Oids.Rsa, counterSigner.SignatureAlgorithm.Value); Assert.Equal( @@ -447,7 +447,7 @@ public static void NonEmbeddedCertificate() Assert.Empty(signer.CounterSignerInfos); Assert.Null(signer.Certificate); -#if NETCOREAPP +#if NET Assert.Equal(Oids.Rsa, signer.SignatureAlgorithm.Value); Assert.Equal( @@ -551,7 +551,7 @@ public static void ReadRsaPkcs1DoubleCounterSigned() Assert.Equal(SubjectIdentifierType.IssuerAndSerialNumber, signer.SignerIdentifier.Type); Assert.Equal(Oids.Sha1, signer.DigestAlgorithm.Value); -#if NETCOREAPP +#if NET Assert.Equal(Oids.Rsa, signer.SignatureAlgorithm.Value); Assert.Equal( @@ -597,7 +597,7 @@ public static void ReadRsaPkcs1DoubleCounterSigned() // Assert.NotThrows cms.CheckSignature(true); -#if NETCOREAPP +#if NET Assert.Equal( "1AA282DBED4D862D7CEA30F803E790BDB0C97EE852778CEEDDCD94BB9304A155" + "2E60A8D36052AC8C2D28755F3B2F473824100AB3A6ABD4C15ABD77E0FFE13D0D" + diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs index 10a51fc819545a..37d8b29ddc5d11 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs @@ -100,7 +100,7 @@ public static void SignerInfo_CounterSignerInfos_UniquePerCall_WhenNonEmpty() Assert.NotSame(counterSigner.Certificate, counterSigner2.Certificate); Assert.Equal(counterSigner.Certificate, counterSigner2.Certificate); -#if NETCOREAPP +#if NET byte[] signature = counterSigner.GetSignature(); byte[] signature2 = counterSigner2.GetSignature(); @@ -110,7 +110,7 @@ public static void SignerInfo_CounterSignerInfos_UniquePerCall_WhenNonEmpty() } } -#if NETCOREAPP +#if NET [Fact] public static void SignerInfo_GetSignature_UniquePerCall() { @@ -139,7 +139,7 @@ public static void SignerInfo_DigestAlgorithm_NotSame() Assert.NotSame(oid, oid2); } -#if NETCOREAPP +#if NET [Fact] public static void SignerInfo_SignatureAlgorithm_NotSame() { @@ -745,7 +745,7 @@ public static void AddCounterSigner_DSA() Assert.NotEqual(firstSigner2.Certificate, counterSigner.Certificate); Assert.Equal(2, cms.Certificates.Count); -#if NETCOREAPP +#if NET byte[] signature = counterSigner.GetSignature(); Assert.NotEmpty(signature); // DSA PKIX signature format is a DER SEQUENCE. @@ -813,7 +813,7 @@ public static void AddCounterSigner_ECDSA(SubjectIdentifierType identifierType, Assert.NotEqual(firstSigner2.Certificate, counterSigner.Certificate); Assert.Equal(2, cms.Certificates.Count); -#if NETCOREAPP +#if NET byte[] signature = counterSigner.GetSignature(); Assert.NotEmpty(signature); // DSA PKIX signature format is a DER SEQUENCE. diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoHelpers.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoHelpers.cs index 17fedbe3daa9a0..5a6ece8b2d6c9b 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoHelpers.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoHelpers.cs @@ -50,7 +50,7 @@ internal static class CryptoHelpers [RequiresDynamicCode(XsltRequiresDynamicCodeMessage)] private static XmlDsigXsltTransform CreateXmlDsigXsltTransform() { -#if NETCOREAPP +#if NET if (!RuntimeFeature.IsDynamicCodeSupported) { // XSLTs are only supported when dynamic code is supported. See https://github.com/dotnet/runtime/issues/84389 @@ -73,7 +73,7 @@ private static XmlDsigXsltTransform CreateXmlDsigXsltTransform() { return (CryptoConfig.CreateFromName(name) ?? CreateFromKnownName(name)) as T; } -#if NETCOREAPP +#if NET catch (NotSupportedException) { if (name == "http://www.w3.org/TR/1999/REC-xslt-19991116") diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSASignatureDescription.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSASignatureDescription.cs index 22b1c4c355a79b..46e214ab54fa56 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSASignatureDescription.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSASignatureDescription.cs @@ -17,7 +17,7 @@ public DSASignatureDescription() DigestAlgorithm = "SHA1"; } -#if NETCOREAPP +#if NET [RequiresUnreferencedCode("CreateDeformatter is not trim compatible because the algorithm implementation referenced by DeformatterAlgorithm might be removed.")] #endif public sealed override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key) @@ -28,7 +28,7 @@ public sealed override AsymmetricSignatureDeformatter CreateDeformatter(Asymmetr return item; } -#if NETCOREAPP +#if NET [RequiresUnreferencedCode("CreateFormatter is not trim compatible because the algorithm implementation referenced by FormatterAlgorithm might be removed.")] #endif public sealed override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key) diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAPKCS1SignatureDescription.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAPKCS1SignatureDescription.cs index 6d5a8fd733e03a..28e0850891d8a1 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAPKCS1SignatureDescription.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAPKCS1SignatureDescription.cs @@ -15,7 +15,7 @@ public RSAPKCS1SignatureDescription(string hashAlgorithmName) DigestAlgorithm = hashAlgorithmName; } -#if NETCOREAPP +#if NET [RequiresUnreferencedCode("CreateDeformatter is not trim compatible because the algorithm implementation referenced by DeformatterAlgorithm might be removed.")] #endif public sealed override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key) @@ -26,7 +26,7 @@ public sealed override AsymmetricSignatureDeformatter CreateDeformatter(Asymmetr return item; } -#if NETCOREAPP +#if NET [RequiresUnreferencedCode("CreateFormatter is not trim compatible because the algorithm implementation referenced by FormatterAlgorithm might be removed.")] #endif public sealed override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key) @@ -37,7 +37,7 @@ public sealed override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAl return item; } -#if NETCOREAPP +#if NET [RequiresUnreferencedCode("CreateDigest is not trim compatible because the algorithm implementation referenced by DigestAlgorithm might be removed.")] #endif public abstract override HashAlgorithm CreateDigest(); diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs index de7bc2b9b77b7e..5505994fd82933 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs @@ -761,7 +761,7 @@ internal static bool IsSelfSigned(X509Chain chain) { AsymmetricAlgorithm? algorithm = (AsymmetricAlgorithm?)certificate.GetRSAPublicKey() ?? certificate.GetECDsaPublicKey(); -#if NETCOREAPP +#if NET if (algorithm is null && !OperatingSystem.IsTvOS() && !OperatingSystem.IsIOS()) { algorithm = certificate.GetDSAPublicKey(); diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/ReferenceTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/ReferenceTest.cs index a28065dac5a310..db65e8de538167 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/ReferenceTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/ReferenceTest.cs @@ -131,7 +131,7 @@ public void LoadXPathTransforms() [ConditionalFact] public void LoadXsltTransforms() { -#if NETCOREAPP +#if NET if (!RuntimeFeature.IsDynamicCodeSupported) { throw new SkipTestException("XSLTs are only supported when dynamic code is supported. See https://github.com/dotnet/runtime/issues/84389"); @@ -167,7 +167,7 @@ public void LoadAllTransforms() xsltTransform += ""; xsltTransform += ""; int expectedTransformsCount = 6; -#if NETCOREAPP +#if NET if (!RuntimeFeature.IsDynamicCodeSupported) { // XSLTs are only supported when dynamic code is supported. See https://github.com/dotnet/runtime/issues/84389 diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/Samples/SigningVerifyingX509Cert.cs b/src/libraries/System.Security.Cryptography.Xml/tests/Samples/SigningVerifyingX509Cert.cs index 37431c1e53c124..69af96accd8db0 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/Samples/SigningVerifyingX509Cert.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/Samples/SigningVerifyingX509Cert.cs @@ -87,7 +87,7 @@ public void SignedXmlHasDSACertificateVerifiableSignature() xmlDoc.PreserveWhitespace = true; xmlDoc.LoadXml(ExampleXml); -#if NETCOREAPP +#if NET using (DSA key = x509cert.GetDSAPrivateKey()) { SignXml(xmlDoc, key); diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs index bd22c5b835eed8..54c153694f7bf7 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs @@ -1673,7 +1673,7 @@ static byte[] GetResponse() => try { -#if NETCOREAPP +#if NET socket = await listener.AcceptSocketAsync(cancellationToken); #else socket = await listener.AcceptSocketAsync(); diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/TestHelpers.cs b/src/libraries/System.Security.Cryptography.Xml/tests/TestHelpers.cs index 16364a4315c354..17e498325abb27 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/TestHelpers.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/TestHelpers.cs @@ -229,7 +229,7 @@ internal static DSA GetWorkingDSA() { DSA dsa = DSA.Create(); -#if NETCOREAPP +#if NET if (OperatingSystem.IsMacOS()) { // macOS cannot generate DSA keys, so for this platform we will use a fixed key. diff --git a/src/libraries/System.Security.Cryptography/tests/AsymmetricAlgorithm/Trivial.cs b/src/libraries/System.Security.Cryptography/tests/AsymmetricAlgorithm/Trivial.cs index 1fb2f0306aa8ef..97a6ba6d3548ae 100644 --- a/src/libraries/System.Security.Cryptography/tests/AsymmetricAlgorithm/Trivial.cs +++ b/src/libraries/System.Security.Cryptography/tests/AsymmetricAlgorithm/Trivial.cs @@ -51,7 +51,7 @@ public static void ValidKeySizeUsesProperty() } } -#if NETCOREAPP +#if NET [Fact] public static void ClearCallsDispose() { diff --git a/src/libraries/System.Security.Cryptography/tests/DefaultDSAProvider.cs b/src/libraries/System.Security.Cryptography/tests/DefaultDSAProvider.cs index e04a1ce81f2602..03c3bf5d02a349 100644 --- a/src/libraries/System.Security.Cryptography/tests/DefaultDSAProvider.cs +++ b/src/libraries/System.Security.Cryptography/tests/DefaultDSAProvider.cs @@ -12,7 +12,7 @@ public DSA Create() public DSA Create(int keySize) { -#if NETCOREAPP +#if NET return DSA.Create(keySize); #else DSA dsa = Create(); diff --git a/src/libraries/System.Security.Cryptography/tests/DefaultECDsaProvider.cs b/src/libraries/System.Security.Cryptography/tests/DefaultECDsaProvider.cs index 001869125e0ca5..91015c49a39f4e 100644 --- a/src/libraries/System.Security.Cryptography/tests/DefaultECDsaProvider.cs +++ b/src/libraries/System.Security.Cryptography/tests/DefaultECDsaProvider.cs @@ -19,7 +19,7 @@ public ECDsa Create(int keySize) return ec; } -#if NETCOREAPP +#if NET public ECDsa Create(ECCurve curve) { return ECDsa.Create(curve); diff --git a/src/libraries/System.Security.Cryptography/tests/DefaultRSAProvider.cs b/src/libraries/System.Security.Cryptography/tests/DefaultRSAProvider.cs index c65b78ace1288e..ab19c2aa03344a 100644 --- a/src/libraries/System.Security.Cryptography/tests/DefaultRSAProvider.cs +++ b/src/libraries/System.Security.Cryptography/tests/DefaultRSAProvider.cs @@ -15,7 +15,7 @@ public class DefaultRSAProvider : IRSAProvider public RSA Create(int keySize) { -#if NETCOREAPP +#if NET return RSA.Create(keySize); #else RSA rsa = Create(); diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs index e65a0445b09b28..8c434619d72eb0 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs @@ -551,7 +551,7 @@ public static void InvalidSignatureAlgorithmEncoding(string caseName, string sig Exception exception = Assert.Throws( () => request.Create(request.SubjectName, generator, now, now.AddDays(1), new byte[1])); -#if NETCOREAPP +#if NET if (CultureInfo.CurrentCulture.Name == "en-US") { Assert.Contains("ASN1", exception.Message, StringComparison.OrdinalIgnoreCase); diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.cs index 0c8e374018564d..fb286e393c98d6 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NETCOREAPP +#if NET #define HAVE_STORE_ISOPEN #endif diff --git a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.Forwards.cs b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.Forwards.cs index 4d9a824761f533..c4f0228c054129 100644 --- a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.Forwards.cs +++ b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.Forwards.cs @@ -15,7 +15,7 @@ [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Permissions.SecurityPermissionFlag))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Policy.Evidence))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Policy.EvidenceBase))] -#if NETCOREAPP +#if NET [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.IStackWalk))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.PermissionSet))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Permissions.PermissionState))] diff --git a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.cs b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.cs index 512d130416ea6a..5d2fc5fabc8b31 100644 --- a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.cs +++ b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.cs @@ -17,7 +17,7 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser } namespace System.Configuration { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class ConfigurationPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -31,7 +31,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.All, AllowMultiple=true, Inherited=false)] @@ -43,7 +43,7 @@ public ConfigurationPermissionAttribute(System.Security.Permissions.SecurityActi } namespace System.Data.Common { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public abstract partial class DBDataPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -65,7 +65,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -84,7 +84,7 @@ protected DBDataPermissionAttribute(System.Security.Permissions.SecurityAction a } namespace System.Data.Odbc { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class OdbcPermission : System.Data.Common.DBDataPermission @@ -95,7 +95,7 @@ public OdbcPermission(System.Security.Permissions.PermissionState state, bool al public override void Add(string connectionString, string restrictions, System.Data.KeyRestrictionBehavior behavior) { } public override System.Security.IPermission Copy() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -107,7 +107,7 @@ public OdbcPermissionAttribute(System.Security.Permissions.SecurityAction action } namespace System.Data.OleDb { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class OleDbPermission : System.Data.Common.DBDataPermission @@ -120,7 +120,7 @@ public OleDbPermission(System.Security.Permissions.PermissionState state, bool a public string Provider { get { throw null; } set { } } public override System.Security.IPermission Copy() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -135,7 +135,7 @@ public OleDbPermissionAttribute(System.Security.Permissions.SecurityAction actio } namespace System.Data.OracleClient { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class OraclePermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -151,7 +151,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -171,7 +171,7 @@ public OraclePermissionAttribute(System.Security.Permissions.SecurityAction acti } namespace System.Data.SqlClient { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class SqlClientPermission : System.Data.Common.DBDataPermission @@ -182,7 +182,7 @@ public SqlClientPermission(System.Security.Permissions.PermissionState state, bo public override void Add(string connectionString, string restrictions, System.Data.KeyRestrictionBehavior behavior) { } public override System.Security.IPermission Copy() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -194,7 +194,7 @@ public SqlClientPermissionAttribute(System.Security.Permissions.SecurityAction a } namespace System.Diagnostics { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class EventLogPermission : System.Security.Permissions.ResourcePermissionBase @@ -215,7 +215,7 @@ public enum EventLogPermissionAccess Write = 16, Administer = 48, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Event | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -249,7 +249,7 @@ protected override void OnRemove(int index, object value) { } protected override void OnSet(int index, object oldValue, object newValue) { } public void Remove(System.Diagnostics.EventLogPermissionEntry value) { } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class PerformanceCounterPermission : System.Security.Permissions.ResourcePermissionBase @@ -270,7 +270,7 @@ public enum PerformanceCounterPermissionAccess Instrument = 3, Administer = 7, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Event | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -360,7 +360,7 @@ public void Remove(System.DirectoryServices.DirectoryServicesPermissionEntry val } namespace System.Drawing.Printing { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class PrintingPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -376,7 +376,7 @@ public override void FromXml(System.Security.SecurityElement element) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.All, AllowMultiple=true)] @@ -396,7 +396,7 @@ public enum PrintingPermissionLevel } namespace System.Net { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class DnsPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -410,7 +410,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -434,7 +434,7 @@ public enum NetworkAccess Connect = 64, Accept = 128, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class SocketPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -453,7 +453,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -474,7 +474,7 @@ public enum TransportType Tcp = 2, All = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class WebPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -495,7 +495,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -517,7 +517,7 @@ public enum SmtpAccess Connect = 1, ConnectToUnrestrictedPort = 2, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class SmtpPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -535,7 +535,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -555,7 +555,7 @@ public enum NetworkInformationAccess Read = 1, Ping = 4, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class NetworkInformationPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -572,7 +572,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -585,7 +585,7 @@ public NetworkInformationPermissionAttribute(System.Security.Permissions.Securit } namespace System.Net.PeerToPeer { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class PnrpPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -599,7 +599,7 @@ public override void FromXml(System.Security.SecurityElement e) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -618,7 +618,7 @@ public enum PnrpScope } namespace System.Net.PeerToPeer.Collaboration { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class PeerCollaborationPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -632,7 +632,7 @@ public override void FromXml(System.Security.SecurityElement e) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -644,7 +644,7 @@ public PeerCollaborationPermissionAttribute(System.Security.Permissions.Security } namespace System.Security { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public abstract partial class CodeAccessPermission : System.Security.IPermission, System.Security.ISecurityEncodable, System.Security.IStackWalk @@ -670,7 +670,7 @@ public static void RevertPermitOnly() { } public abstract System.Security.SecurityElement ToXml(); public virtual System.Security.IPermission Union(System.Security.IPermission other) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public partial class HostProtectionException : System.SystemException @@ -723,7 +723,7 @@ public partial interface ISecurityPolicyEncodable void FromXml(System.Security.SecurityElement e, System.Security.Policy.PolicyLevel level); System.Security.SecurityElement ToXml(System.Security.Policy.PolicyLevel level); } -#if !NETCOREAPP +#if !NET public partial interface IStackWalk { void Assert(); @@ -732,7 +732,7 @@ public partial interface IStackWalk void PermitOnly(); } #endif -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class NamedPermissionSet : System.Security.PermissionSet @@ -750,7 +750,7 @@ public override void FromXml(System.Security.SecurityElement et) { } public override int GetHashCode() { throw null; } public override System.Security.SecurityElement ToXml() { throw null; } } -#if !NETCOREAPP +#if !NET public partial class PermissionSet : System.Collections.ICollection, System.Collections.IEnumerable, System.Runtime.Serialization.IDeserializationCallback, System.Security.ISecurityEncodable, System.Security.IStackWalk { public PermissionSet(System.Security.Permissions.PermissionState state) { } @@ -800,7 +800,7 @@ public enum PolicyLevelType Enterprise = 2, AppDomain = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class SecurityContext : System.IDisposable @@ -821,7 +821,7 @@ public enum SecurityContextSource CurrentAppDomain = 0, CurrentAssembly = 1, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public static partial class SecurityManager @@ -882,7 +882,7 @@ public XmlSyntaxException(string message, System.Exception inner) { } } namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class DataProtectionPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -898,7 +898,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -912,7 +912,7 @@ public DataProtectionPermissionAttribute(System.Security.Permissions.SecurityAct public bool UnprotectMemory { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -925,7 +925,7 @@ public enum DataProtectionPermissionFlags UnprotectMemory = 8, AllFlags = 15, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class EnvironmentPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -943,7 +943,7 @@ public void SetPathList(System.Security.Permissions.EnvironmentPermissionAccess public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission other) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -954,7 +954,7 @@ public enum EnvironmentPermissionAccess Write = 2, AllAccess = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -966,7 +966,7 @@ public EnvironmentPermissionAttribute(System.Security.Permissions.SecurityAction public string Write { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class FileDialogPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -982,7 +982,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -993,7 +993,7 @@ public enum FileDialogPermissionAccess Save = 2, OpenSave = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1004,7 +1004,7 @@ public FileDialogPermissionAttribute(System.Security.Permissions.SecurityAction public bool Save { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class FileIOPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1031,7 +1031,7 @@ public void SetPathList(System.Security.Permissions.FileIOPermissionAccess acces public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission other) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -1044,7 +1044,7 @@ public enum FileIOPermissionAccess PathDiscovery = 8, AllAccess = 15, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1064,7 +1064,7 @@ public FileIOPermissionAttribute(System.Security.Permissions.SecurityAction acti public string Write { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class GacIdentityPermission : System.Security.CodeAccessPermission @@ -1078,7 +1078,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1087,7 +1087,7 @@ public sealed partial class GacIdentityPermissionAttribute : System.Security.Per public GacIdentityPermissionAttribute(System.Security.Permissions.SecurityAction action) : base (default(System.Security.Permissions.SecurityAction)) { } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Delegate | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1107,7 +1107,7 @@ public HostProtectionAttribute(System.Security.Permissions.SecurityAction action public bool UI { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -1125,7 +1125,7 @@ public enum HostProtectionResource MayLeakOnAbort = 256, All = 511, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum IsolatedStorageContainment @@ -1143,7 +1143,7 @@ public enum IsolatedStorageContainment AdministerIsolatedStorageByUser = 112, UnrestrictedIsolatedStorage = 240, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class IsolatedStorageFilePermission : System.Security.Permissions.IsolatedStoragePermission @@ -1155,7 +1155,7 @@ public IsolatedStorageFilePermission(System.Security.Permissions.PermissionState public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1164,7 +1164,7 @@ public sealed partial class IsolatedStorageFilePermissionAttribute : System.Secu public IsolatedStorageFilePermissionAttribute(System.Security.Permissions.SecurityAction action) : base (default(System.Security.Permissions.SecurityAction)) { } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public abstract partial class IsolatedStoragePermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1176,7 +1176,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public bool IsUnrestricted() { throw null; } public override System.Security.SecurityElement ToXml() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public abstract partial class IsolatedStoragePermissionAttribute : System.Security.Permissions.CodeAccessSecurityAttribute @@ -1185,14 +1185,14 @@ protected IsolatedStoragePermissionAttribute(System.Security.Permissions.Securit public System.Security.Permissions.IsolatedStorageContainment UsageAllowed { get { throw null; } set { } } public long UserQuota { get { throw null; } set { } } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public partial interface IUnrestrictedPermission { bool IsUnrestricted(); } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class KeyContainerPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1210,7 +1210,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class KeyContainerPermissionAccessEntry @@ -1227,7 +1227,7 @@ public KeyContainerPermissionAccessEntry(string keyStore, string providerName, i public override bool Equals(object o) { throw null; } public override int GetHashCode() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class KeyContainerPermissionAccessEntryCollection : System.Collections.ICollection, System.Collections.IEnumerable @@ -1246,7 +1246,7 @@ public void CopyTo(System.Security.Permissions.KeyContainerPermissionAccessEntry public void Remove(System.Security.Permissions.KeyContainerPermissionAccessEntry accessEntry) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class KeyContainerPermissionAccessEntryEnumerator : System.Collections.IEnumerator @@ -1257,7 +1257,7 @@ public KeyContainerPermissionAccessEntryEnumerator() { } public bool MoveNext() { throw null; } public void Reset() { } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1272,7 +1272,7 @@ public KeyContainerPermissionAttribute(System.Security.Permissions.SecurityActio public int ProviderType { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum KeyContainerPermissionFlags @@ -1289,7 +1289,7 @@ public enum KeyContainerPermissionFlags ChangeAcl = 8192, AllFlags = 13111, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class MediaPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1311,7 +1311,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1323,7 +1323,7 @@ public MediaPermissionAttribute(System.Security.Permissions.SecurityAction actio public System.Security.Permissions.MediaPermissionVideo Video { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum MediaPermissionAudio @@ -1333,7 +1333,7 @@ public enum MediaPermissionAudio SafeAudio = 2, AllAudio = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum MediaPermissionImage @@ -1343,7 +1343,7 @@ public enum MediaPermissionImage SafeImage = 2, AllImage = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum MediaPermissionVideo @@ -1353,7 +1353,7 @@ public enum MediaPermissionVideo SafeVideo = 2, AllVideo = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1368,14 +1368,14 @@ public PermissionSetAttribute(System.Security.Permissions.SecurityAction action) public override System.Security.IPermission CreatePermission() { throw null; } public System.Security.PermissionSet CreatePermissionSet() { throw null; } } -#if !NETCOREAPP +#if !NET public enum PermissionState { None = 0, Unrestricted = 1, } #endif -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class PrincipalPermission : System.Security.IPermission, System.Security.ISecurityEncodable, System.Security.Permissions.IUnrestrictedPermission @@ -1395,13 +1395,13 @@ public void FromXml(System.Security.SecurityElement elem) { } public System.Security.SecurityElement ToXml() { throw null; } public System.Security.IPermission Union(System.Security.IPermission other) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Method, AllowMultiple=true, Inherited=false)] public sealed partial class PrincipalPermissionAttribute : System.Security.Permissions.CodeAccessSecurityAttribute { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("PrincipalPermissionAttribute is not honored by the runtime and must not be used.", true, DiagnosticId = "SYSLIB0002", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public PrincipalPermissionAttribute(System.Security.Permissions.SecurityAction action) : base (default(System.Security.Permissions.SecurityAction)) { } @@ -1410,7 +1410,7 @@ public PrincipalPermissionAttribute(System.Security.Permissions.SecurityAction a public string Role { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class PublisherIdentityPermission : System.Security.CodeAccessPermission @@ -1425,7 +1425,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1437,7 +1437,7 @@ public PublisherIdentityPermissionAttribute(System.Security.Permissions.Security public string X509Certificate { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class ReflectionPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1453,7 +1453,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission other) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1469,7 +1469,7 @@ public ReflectionPermissionAttribute(System.Security.Permissions.SecurityAction public bool TypeInformation { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -1485,7 +1485,7 @@ public enum ReflectionPermissionFlag AllFlags = 7, RestrictedMemberAccess = 8, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class RegistryPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1505,7 +1505,7 @@ public void SetPathList(System.Security.Permissions.RegistryPermissionAccess acc public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission other) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -1517,7 +1517,7 @@ public enum RegistryPermissionAccess Create = 4, AllAccess = 7, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1534,7 +1534,7 @@ public RegistryPermissionAttribute(System.Security.Permissions.SecurityAction ac public string Write { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public abstract partial class ResourcePermissionBase : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1557,7 +1557,7 @@ protected void RemovePermissionAccess(System.Security.Permissions.ResourcePermis public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public partial class ResourcePermissionBaseEntry @@ -1567,7 +1567,7 @@ public ResourcePermissionBaseEntry(int permissionAccess, string[] permissionAcce public int PermissionAccess { get { throw null; } } public string[] PermissionAccessPath { get { throw null; } } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class SecurityPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1583,7 +1583,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class SiteIdentityPermission : System.Security.CodeAccessPermission @@ -1598,7 +1598,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1608,7 +1608,7 @@ public SiteIdentityPermissionAttribute(System.Security.Permissions.SecurityActio public string Site { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class StorePermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1624,7 +1624,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1641,7 +1641,7 @@ public StorePermissionAttribute(System.Security.Permissions.SecurityAction actio public bool RemoveFromStore { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -1657,7 +1657,7 @@ public enum StorePermissionFlags EnumerateCertificates = 128, AllFlags = 247, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class StrongNameIdentityPermission : System.Security.CodeAccessPermission @@ -1674,7 +1674,7 @@ public override void FromXml(System.Security.SecurityElement e) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1686,7 +1686,7 @@ public StrongNameIdentityPermissionAttribute(System.Security.Permissions.Securit public string Version { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class StrongNamePublicKeyBlob @@ -1696,7 +1696,7 @@ public StrongNamePublicKeyBlob(byte[] publicKey) { } public override int GetHashCode() { throw null; } public override string ToString() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class TypeDescriptorPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1712,7 +1712,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1723,7 +1723,7 @@ public TypeDescriptorPermissionAttribute(System.Security.Permissions.SecurityAct public bool RestrictedRegistrationAccess { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -1732,7 +1732,7 @@ public enum TypeDescriptorPermissionFlags NoFlags = 0, RestrictedRegistrationAccess = 1, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class UIPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1751,7 +1751,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1762,7 +1762,7 @@ public UIPermissionAttribute(System.Security.Permissions.SecurityAction action) public System.Security.Permissions.UIPermissionWindow Window { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum UIPermissionClipboard @@ -1771,7 +1771,7 @@ public enum UIPermissionClipboard OwnClipboard = 1, AllClipboard = 2, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum UIPermissionWindow @@ -1781,7 +1781,7 @@ public enum UIPermissionWindow SafeTopLevelWindows = 2, AllWindows = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class UrlIdentityPermission : System.Security.CodeAccessPermission @@ -1796,7 +1796,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1806,7 +1806,7 @@ public UrlIdentityPermissionAttribute(System.Security.Permissions.SecurityAction public string Url { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class WebBrowserPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1823,7 +1823,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1833,7 +1833,7 @@ public WebBrowserPermissionAttribute(System.Security.Permissions.SecurityAction public System.Security.Permissions.WebBrowserPermissionLevel Level { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum WebBrowserPermissionLevel @@ -1842,7 +1842,7 @@ public enum WebBrowserPermissionLevel Safe = 1, Unrestricted = 2, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class ZoneIdentityPermission : System.Security.CodeAccessPermission @@ -1857,7 +1857,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1909,14 +1909,14 @@ public sealed partial class ApplicationTrust : System.Security.Policy.EvidenceBa { public ApplicationTrust() { } public ApplicationTrust(System.ApplicationIdentity identity) { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public ApplicationTrust(System.Security.PermissionSet defaultGrantSet, System.Collections.Generic.IEnumerable fullTrustAssemblies) { } public System.ApplicationIdentity ApplicationIdentity { get { throw null; } set { } } public System.Security.Policy.PolicyStatement DefaultGrantSet { get { throw null; } set { } } public object ExtraInfo { get { throw null; } set { } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public System.Collections.Generic.IList FullTrustAssemblies { get { throw null; } } @@ -2000,7 +2000,7 @@ public void RemoveChild(System.Security.Policy.CodeGroup group) { } public System.Security.SecurityElement ToXml() { throw null; } public System.Security.SecurityElement ToXml(System.Security.Policy.PolicyLevel level) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class FileCodeGroup : System.Security.Policy.CodeGroup @@ -2026,7 +2026,7 @@ public sealed partial class FirstMatchCodeGroup : System.Security.Policy.CodeGro public override System.Security.Policy.PolicyStatement Resolve(System.Security.Policy.Evidence evidence) { throw null; } public override System.Security.Policy.CodeGroup ResolveMatchingCodeGroups(System.Security.Policy.Evidence evidence) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class GacInstalled : System.Security.Policy.EvidenceBase, System.Security.Policy.IIdentityPermissionFactory @@ -2085,7 +2085,7 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser public System.Security.SecurityElement ToXml() { throw null; } public System.Security.SecurityElement ToXml(System.Security.Policy.PolicyLevel level) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public partial interface IIdentityPermissionFactory @@ -2153,18 +2153,18 @@ internal PolicyLevel() { } public void AddFullTrustAssembly(System.Security.Policy.StrongName sn) { } [Obsolete("Because all GAC assemblies always get full trust, the full trust list is no longer meaningful. You should install any assemblies that are used in security policy in the GAC to ensure they are trusted.")] public void AddFullTrustAssembly(System.Security.Policy.StrongNameMembershipCondition snMC) { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public void AddNamedPermissionSet(System.Security.NamedPermissionSet permSet) { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public System.Security.NamedPermissionSet ChangeNamedPermissionSet(string name, System.Security.PermissionSet pSet) { throw null; } [System.ObsoleteAttribute("AppDomain policy levels are obsolete. See https://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public static System.Security.Policy.PolicyLevel CreateAppDomainLevel() { throw null; } public void FromXml(System.Security.SecurityElement e) { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public System.Security.NamedPermissionSet GetNamedPermissionSet(string name) { throw null; } @@ -2173,11 +2173,11 @@ public void Recover() { } public void RemoveFullTrustAssembly(System.Security.Policy.StrongName sn) { } [Obsolete("Because all GAC assemblies always get full trust, the full trust list is no longer meaningful. You should install any assemblies that are used in security policy in the GAC to ensure they are trusted.")] public void RemoveFullTrustAssembly(System.Security.Policy.StrongNameMembershipCondition snMC) { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public System.Security.NamedPermissionSet RemoveNamedPermissionSet(System.Security.NamedPermissionSet permSet) { throw null; } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public System.Security.NamedPermissionSet RemoveNamedPermissionSet(string name) { throw null; } @@ -2188,17 +2188,17 @@ public void Reset() { } } public sealed partial class PolicyStatement : System.Security.ISecurityEncodable, System.Security.ISecurityPolicyEncodable { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public PolicyStatement(System.Security.PermissionSet permSet) { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public PolicyStatement(System.Security.PermissionSet permSet, System.Security.Policy.PolicyStatementAttribute attributes) { } public System.Security.Policy.PolicyStatementAttribute Attributes { get { throw null; } set { } } public string AttributeString { get { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public System.Security.PermissionSet PermissionSet { get { throw null; } set { } } @@ -2218,7 +2218,7 @@ public enum PolicyStatementAttribute LevelFinal = 2, All = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class Publisher : System.Security.Policy.EvidenceBase, System.Security.Policy.IIdentityPermissionFactory @@ -2245,7 +2245,7 @@ public void FromXml(System.Security.SecurityElement e, System.Security.Policy.Po public System.Security.SecurityElement ToXml() { throw null; } public System.Security.SecurityElement ToXml(System.Security.Policy.PolicyLevel level) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class Site : System.Security.Policy.EvidenceBase, System.Security.Policy.IIdentityPermissionFactory @@ -2273,7 +2273,7 @@ public void FromXml(System.Security.SecurityElement e, System.Security.Policy.Po public System.Security.SecurityElement ToXml() { throw null; } public System.Security.SecurityElement ToXml(System.Security.Policy.PolicyLevel level) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class StrongName : System.Security.Policy.EvidenceBase, System.Security.Policy.IIdentityPermissionFactory @@ -2288,7 +2288,7 @@ public StrongName(System.Security.Permissions.StrongNamePublicKeyBlob blob, stri public override int GetHashCode() { throw null; } public override string ToString() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class StrongNameMembershipCondition : System.Security.ISecurityEncodable, System.Security.ISecurityPolicyEncodable, System.Security.Policy.IMembershipCondition @@ -2333,7 +2333,7 @@ public sealed partial class UnionCodeGroup : System.Security.Policy.CodeGroup public override System.Security.Policy.PolicyStatement Resolve(System.Security.Policy.Evidence evidence) { throw null; } public override System.Security.Policy.CodeGroup ResolveMatchingCodeGroups(System.Security.Policy.Evidence evidence) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class Url : System.Security.Policy.EvidenceBase, System.Security.Policy.IIdentityPermissionFactory @@ -2360,7 +2360,7 @@ public void FromXml(System.Security.SecurityElement e, System.Security.Policy.Po public System.Security.SecurityElement ToXml() { throw null; } public System.Security.SecurityElement ToXml(System.Security.Policy.PolicyLevel level) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class Zone : System.Security.Policy.EvidenceBase, System.Security.Policy.IIdentityPermissionFactory @@ -2391,7 +2391,7 @@ public void FromXml(System.Security.SecurityElement e, System.Security.Policy.Po } namespace System.ServiceProcess { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class ServiceControllerPermission : System.Security.Permissions.ResourcePermissionBase @@ -2409,7 +2409,7 @@ public enum ServiceControllerPermissionAccess Browse = 2, Control = 6, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Event | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple = true, Inherited = false)] @@ -2449,7 +2449,7 @@ public void Remove(System.ServiceProcess.ServiceControllerPermissionEntry value) } namespace System.Transactions { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class DistributedTransactionPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -2463,7 +2463,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.All, AllowMultiple=true)] @@ -2476,7 +2476,7 @@ public DistributedTransactionPermissionAttribute(System.Security.Permissions.Sec } namespace System.Web { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class AspNetHostingPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -2492,7 +2492,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.All, AllowMultiple=true, Inherited=false)] diff --git a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.netcoreapp.cs b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.netcoreapp.cs index bd7e4dd59a6c7b..f3e0de569038cb 100644 --- a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.netcoreapp.cs +++ b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.netcoreapp.cs @@ -6,7 +6,7 @@ namespace System.Xaml.Permissions { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class XamlLoadPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermission.cs b/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermission.cs index 3adc471ddc8949..47967148e4b60c 100644 --- a/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermission.cs @@ -6,7 +6,7 @@ namespace System.Configuration { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class ConfigurationPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermissionAttribute.cs index 8366e422d9172f..43a98812096e14 100644 --- a/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Configuration { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermission.cs b/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermission.cs index 93b727f99073f2..3982f48df334ff 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermission.cs @@ -6,7 +6,7 @@ namespace System.Data.Common { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public abstract class DBDataPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermissionAttribute.cs index 9968cb6d565abb..ac1e409a951df6 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermissionAttribute.cs @@ -5,7 +5,7 @@ namespace System.Data.Common { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method, diff --git a/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermission.cs b/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermission.cs index 6504d49d88814b..2dca7ee412de82 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermission.cs @@ -7,7 +7,7 @@ namespace System.Data.Odbc { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class OdbcPermission : DBDataPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermissionAttribute.cs index c6286aa49ba751..e0bd5ec1abf82d 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermissionAttribute.cs @@ -7,7 +7,7 @@ namespace System.Data.Odbc { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | diff --git a/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermission.cs b/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermission.cs index d71f863adcf374..7b162ca30c2696 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermission.cs @@ -7,7 +7,7 @@ namespace System.Data.OleDb { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class OleDbPermission : DBDataPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermissionAttribute.cs index c4e0aca2d7a287..c5e90d99441762 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermissionAttribute.cs @@ -7,7 +7,7 @@ namespace System.Data.OleDb { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | diff --git a/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermission.cs b/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermission.cs index a0389c9a0be15f..3517fd1cb4ee9d 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermission.cs @@ -6,7 +6,7 @@ namespace System.Data.OracleClient { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class OraclePermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermissionAttribute.cs index 639d38aa48e91e..bc7175def787ec 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermissionAttribute.cs @@ -5,7 +5,7 @@ namespace System.Data.OracleClient { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | diff --git a/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermission.cs b/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermission.cs index e3cc4ced62e7a2..1cd20d3ead17b6 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermission.cs @@ -6,7 +6,7 @@ namespace System.Data.SqlClient { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class SqlClientPermission : DBDataPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermissionAttribute.cs index 0979d37e899ff9..fffc013004f700 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermissionAttribute.cs @@ -7,7 +7,7 @@ namespace System.Data.SqlClient { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method, diff --git a/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermission.cs b/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermission.cs index e1e64c3c12be69..206e729cbb09c8 100644 --- a/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermission.cs @@ -5,7 +5,7 @@ namespace System.Diagnostics { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class EventLogPermission : ResourcePermissionBase diff --git a/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermissionAttribute.cs index e296e032d6ba79..a0406ccde6a240 100644 --- a/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Diagnostics { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct diff --git a/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermission.cs b/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermission.cs index 49cee1607c3381..d3b0c2b6e15593 100644 --- a/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermission.cs @@ -5,7 +5,7 @@ namespace System.Diagnostics { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class PerformanceCounterPermission : ResourcePermissionBase diff --git a/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermissionAttribute.cs index 804e21d7d809b2..0f7322763e104b 100644 --- a/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermissionAttribute.cs @@ -5,7 +5,7 @@ using System.Security.Permissions; namespace System.Diagnostics { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Event, diff --git a/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermission.cs b/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermission.cs index e429ac0b32599a..9981ec0a12d57d 100644 --- a/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermission.cs @@ -6,7 +6,7 @@ namespace System.Drawing.Printing { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class PrintingPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermissionAttribute.cs index 654f04f6ede1f0..71c3d6e46d6581 100644 --- a/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermissionAttribute.cs @@ -5,7 +5,7 @@ namespace System.Drawing.Printing { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] diff --git a/src/libraries/System.Security.Permissions/src/System/Net/DnsPermission.cs b/src/libraries/System.Security.Permissions/src/System/Net/DnsPermission.cs index 86817bf064ea29..4bc042aa3c42aa 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/DnsPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/DnsPermission.cs @@ -6,7 +6,7 @@ namespace System.Net { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class DnsPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Net/DnsPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Net/DnsPermissionAttribute.cs index ab40a425fcaa8e..61f45a9f646d81 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/DnsPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/DnsPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Net { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | diff --git a/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermission.cs b/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermission.cs index d9c5c6edba6a74..4284d30ea6b87d 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermission.cs @@ -6,7 +6,7 @@ namespace System.Net.Mail { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class SmtpPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermissionAttribute.cs index 8d8a3379277e46..3a91cbdffafb5d 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Net.Mail { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | diff --git a/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermission.cs b/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermission.cs index 40a7e39426acbe..1acf38c0fd91ab 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermission.cs @@ -6,7 +6,7 @@ namespace System.Net.NetworkInformation { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class NetworkInformationPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermissionAttribute.cs index d25b0cf35e4e84..befe4af33830df 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Net.NetworkInformation { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermission.cs b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermission.cs index 25627f89a6bd05..c09cceea2a47a3 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermission.cs @@ -6,7 +6,7 @@ namespace System.Net.PeerToPeer.Collaboration { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class PeerCollaborationPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermissionAttribute.cs index 8e171c3cd5c7f8..5fb68c79dcf682 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Net.PeerToPeer.Collaboration { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | diff --git a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermission.cs b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermission.cs index c7b3ccbdf7789a..bac836ed20b7a9 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermission.cs @@ -6,7 +6,7 @@ namespace System.Net.PeerToPeer { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class PnrpPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermissionAttribute.cs index b9df6e845e49ed..88b06a69b287f7 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Net.PeerToPeer { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | diff --git a/src/libraries/System.Security.Permissions/src/System/Net/SocketPermission.cs b/src/libraries/System.Security.Permissions/src/System/Net/SocketPermission.cs index 88e835058e7872..1e51df16e9606b 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/SocketPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/SocketPermission.cs @@ -6,7 +6,7 @@ namespace System.Net { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class SocketPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Net/SocketPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Net/SocketPermissionAttribute.cs index 88147043b9218a..cf4611a39e6e66 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/SocketPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/SocketPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Net { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | diff --git a/src/libraries/System.Security.Permissions/src/System/Net/WebPermission.cs b/src/libraries/System.Security.Permissions/src/System/Net/WebPermission.cs index e61b27b590f2d8..e7fe49c24dd72c 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/WebPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/WebPermission.cs @@ -8,7 +8,7 @@ namespace System.Net { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class WebPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Net/WebPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Net/WebPermissionAttribute.cs index 7113110a896b36..82f30ea9df7222 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/WebPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/WebPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Net { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | diff --git a/src/libraries/System.Security.Permissions/src/System/Security/CodeAccessPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/CodeAccessPermission.cs index 4ecc14aca2bff1..9ca3f51ce606bf 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/CodeAccessPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/CodeAccessPermission.cs @@ -3,7 +3,7 @@ namespace System.Security { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public abstract partial class CodeAccessPermission : IPermission, ISecurityEncodable, IStackWalk diff --git a/src/libraries/System.Security.Permissions/src/System/Security/HostProtectionException.cs b/src/libraries/System.Security.Permissions/src/System/Security/HostProtectionException.cs index b93a00a2a8e59b..455e045198c419 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/HostProtectionException.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/HostProtectionException.cs @@ -8,7 +8,7 @@ namespace System.Security { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Serializable] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/NamedPermissionSet.cs b/src/libraries/System.Security.Permissions/src/System/Security/NamedPermissionSet.cs index 26bfa5dae85d9b..b437033366e084 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/NamedPermissionSet.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/NamedPermissionSet.cs @@ -5,7 +5,7 @@ namespace System.Security { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class NamedPermissionSet : PermissionSet diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermission.cs index 2af3cafe200eb0..f7c18edfea5e03 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class DataProtectionPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionAttribute.cs index 5c6d99af3565a7..b3cf765ca13e34 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionFlags.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionFlags.cs index 44a442408e8f8a..80c1dd19d18012 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionFlags.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionFlags.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermission.cs index 5c26c149475416..76f0c82c8029c4 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class EnvironmentPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAccess.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAccess.cs index b5dee502e691a8..0a7f56c80ffff0 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAccess.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAccess.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAttribute.cs index d68a1e4842fbb4..b69d26db2be97b 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermission.cs index 6774ece3a08074..952148edcb99c4 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class FileDialogPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAccess.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAccess.cs index 80dfc8f43e1606..8d2eb8a87bd02c 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAccess.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAccess.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAttribute.cs index a6dc55eb78b656..9f4c8b6fc8ebaa 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermission.cs index 7df64c4145df16..99e507ecd7c579 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class FileIOPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAccess.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAccess.cs index e3fb61c97b2391..029e63b1a0938d 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAccess.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAccess.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAttribute.cs index 1780e55dde857c..702cc1fae17931 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermission.cs index a0d0abc573fdb9..39604e13f555e1 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class GacIdentityPermission : CodeAccessPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermissionAttribute.cs index bdeee8607fd10d..928f72a5b51fa4 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionAttribute.cs index 56f6d8a24bbe1c..ecf10307271e5b 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(4205), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionResource.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionResource.cs index d1db88246d0037..81e284a6564778 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionResource.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionResource.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IUnrestrictedPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IUnrestrictedPermission.cs index a4c95a4a13fd23..04e5fa166a59a1 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IUnrestrictedPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IUnrestrictedPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public partial interface IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageContainment.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageContainment.cs index 1563eba6e790ff..4292c351f4f575 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageContainment.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageContainment.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum IsolatedStorageContainment diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermission.cs index fafbdca772d713..4e3535109fbc12 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class IsolatedStorageFilePermission : IsolatedStoragePermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermissionAttribute.cs index e7d95b86409154..8789e27a496d04 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermission.cs index d0d08571e6a8e5..c33e6fcae17746 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public abstract class IsolatedStoragePermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermissionAttribute.cs index 30189ad078167e..77bdd246411bb5 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public abstract class IsolatedStoragePermissionAttribute : CodeAccessSecurityAttribute diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermission.cs index 0f6a490160057f..5567368fc678a7 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class KeyContainerPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntry.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntry.cs index 771c23abb4db7c..038ab40f6d9361 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntry.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntry.cs @@ -5,7 +5,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class KeyContainerPermissionAccessEntry diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryCollection.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryCollection.cs index 4dd5f15a0d0995..f4312632fb71dc 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryCollection.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryCollection.cs @@ -5,7 +5,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class KeyContainerPermissionAccessEntryCollection : ICollection diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryEnumerator.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryEnumerator.cs index 86ed27dd250cab..e8af76d424051e 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryEnumerator.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryEnumerator.cs @@ -5,7 +5,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class KeyContainerPermissionAccessEntryEnumerator : IEnumerator diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAttribute.cs index 7211ff86ccbaf0..239772f6912b0a 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionFlags.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionFlags.cs index 50004c265344b5..0a4ece5eb35d52 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionFlags.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionFlags.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum KeyContainerPermissionFlags diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/MediaPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/MediaPermission.cs index 26d3b914f868ec..543f37aa11671d 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/MediaPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/MediaPermission.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum MediaPermissionAudio @@ -13,7 +13,7 @@ public enum MediaPermissionAudio AllAudio } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum MediaPermissionVideo @@ -24,7 +24,7 @@ public enum MediaPermissionVideo AllVideo, } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum MediaPermissionImage @@ -35,7 +35,7 @@ public enum MediaPermissionImage AllImage, } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class MediaPermission : CodeAccessPermission, IUnrestrictedPermission @@ -61,7 +61,7 @@ public override void FromXml(SecurityElement securityElement) { } public MediaPermissionImage Image { get { return MediaPermissionImage.AllImage; } } } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PermissionSetAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PermissionSetAttribute.cs index c36c4cbc73bd98..6bfe07a081b8e2 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PermissionSetAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PermissionSetAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermission.cs index 060fd7b4f06794..aebdfcfbe66185 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermission.cs @@ -8,7 +8,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class PrincipalPermission : IPermission, ISecurityEncodable, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermissionAttribute.cs index b8a3ff91e7b4e3..14a620670ec878 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermissionAttribute.cs @@ -3,13 +3,13 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(68), AllowMultiple = true, Inherited = false)] public sealed partial class PrincipalPermissionAttribute : CodeAccessSecurityAttribute { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.PrincipalPermissionAttributeMessage, error: true, DiagnosticId = Obsoletions.PrincipalPermissionAttributeDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public PrincipalPermissionAttribute(SecurityAction action) : base(default(SecurityAction)) { } diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermission.cs index b0faace69f7ecd..1c326f70458146 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermission.cs @@ -5,7 +5,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class PublisherIdentityPermission : CodeAccessPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermissionAttribute.cs index d8ce7f50636b88..567d880bfdc8cb 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermission.cs index d6577df8242439..153550aa2a74be 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class ReflectionPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionAttribute.cs index aeec90580dccd7..f6762fe4944bbc 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionFlag.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionFlag.cs index 1c9e39eb6b3d7f..14d809eee162e2 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionFlag.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionFlag.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermission.cs index 04fa83df808422..03cefc8f6ae055 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermission.cs @@ -5,7 +5,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class RegistryPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAccess.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAccess.cs index b2f0384acdc1d3..2f50d5d5fecd65 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAccess.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAccess.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAttribute.cs index da29af354dc307..9c4495a8ea3b18 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBase.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBase.cs index 597647caf26d87..4297b80a495567 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBase.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBase.cs @@ -5,7 +5,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public abstract class ResourcePermissionBase : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBaseEntry.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBaseEntry.cs index 77c012439029b6..ade10e2674c7a3 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBaseEntry.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBaseEntry.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public class ResourcePermissionBaseEntry diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SecurityPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SecurityPermission.cs index a1aa39a9764f73..5df48d3d440f9e 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SecurityPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SecurityPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class SecurityPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermission.cs index 160a9301aed394..d1296b7bd7e4b5 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class SiteIdentityPermission : CodeAccessPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermissionAttribute.cs index 9110f6b74f7402..da1eacf54f7688 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermission.cs index 691439b51dd580..07a2ea11dbe4a6 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class StorePermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionAttribute.cs index c3c50ebf60afe5..8614491c3d21d2 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionFlags.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionFlags.cs index 283e66a697f7c5..13b271e49dc847 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionFlags.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionFlags.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermission.cs index 1d66fa2f7e48ac..2fd19c8447fd3d 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class StrongNameIdentityPermission : CodeAccessPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermissionAttribute.cs index 07b3014ec9a7fb..7863adc97853a8 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs index 44b39f9c8ad986..513e5e04b21cb2 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class StrongNamePublicKeyBlob diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermission.cs index d1e18e0a81069e..8ba9f50cdb8aa9 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class TypeDescriptorPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionAttribute.cs index 767a40af5103d2..708244fba8b5ce 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionFlags.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionFlags.cs index b8c76becc953b8..ad40546c57cefc 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionFlags.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionFlags.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermission.cs index a325753b611342..95e3fadeea8b4b 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class UIPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionAttribute.cs index f5569f8af056c0..8de20804274028 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionClipboard.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionClipboard.cs index cbe563a8ecffb8..7739ac11bd19e6 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionClipboard.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionClipboard.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum UIPermissionClipboard diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionWindow.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionWindow.cs index c87c0b8dfdf661..766027238938e0 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionWindow.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionWindow.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum UIPermissionWindow diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermission.cs index 1ddc1172e27372..7a74ef52fcd150 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class UrlIdentityPermission : CodeAccessPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermissionAttribute.cs index 49ce74de84e48d..cda8134abe7f60 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/WebBrowserPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/WebBrowserPermission.cs index 3f0670d9fa276a..c4ac4a3fb126f3 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/WebBrowserPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/WebBrowserPermission.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum WebBrowserPermissionLevel @@ -12,7 +12,7 @@ public enum WebBrowserPermissionLevel Unrestricted } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class WebBrowserPermission : CodeAccessPermission, IUnrestrictedPermission @@ -30,7 +30,7 @@ public override void FromXml(SecurityElement securityElement) { } public WebBrowserPermissionLevel Level { get { return WebBrowserPermissionLevel.Unrestricted; } set { } } } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermission.cs index 61e1945c22ef96..0caf076e6e585e 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class ZoneIdentityPermission : CodeAccessPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermissionAttribute.cs index 0f66c4bd431761..2833529125c59a 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/ApplicationTrust.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/ApplicationTrust.cs index b17afed7b99df7..6646fe2979389f 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/ApplicationTrust.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/ApplicationTrust.cs @@ -9,14 +9,14 @@ public sealed partial class ApplicationTrust : EvidenceBase, ISecurityEncodable { public ApplicationTrust() { } public ApplicationTrust(ApplicationIdentity identity) { } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public ApplicationTrust(PermissionSet defaultGrantSet, IEnumerable fullTrustAssemblies) { } public ApplicationIdentity ApplicationIdentity { get; set; } public PolicyStatement DefaultGrantSet { get; set; } public object ExtraInfo { get; set; } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public IList FullTrustAssemblies { get { return default(IList); } } diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/FileCodeGroup.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/FileCodeGroup.cs index 599d70f03c4317..4e73e5d26f9b86 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/FileCodeGroup.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/FileCodeGroup.cs @@ -3,7 +3,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class FileCodeGroup : CodeGroup diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/GacInstalled.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/GacInstalled.cs index f6565fbf791617..ddee079fb88dbc 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/GacInstalled.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/GacInstalled.cs @@ -3,7 +3,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class GacInstalled : EvidenceBase, IIdentityPermissionFactory diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/IIdentityPermissionFactory.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/IIdentityPermissionFactory.cs index f519bf2c06c2da..b310bdb61d5a59 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/IIdentityPermissionFactory.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/IIdentityPermissionFactory.cs @@ -3,7 +3,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public partial interface IIdentityPermissionFactory diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyLevel.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyLevel.cs index 74afa9599191c4..06c65039eee7ac 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyLevel.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyLevel.cs @@ -18,18 +18,18 @@ internal PolicyLevel() { } public void AddFullTrustAssembly(StrongName sn) { } [Obsolete("Because all GAC assemblies always get full trust, the full trust list is no longer meaningful. You should install any assemblies that are used in security policy in the GAC to ensure they are trusted.")] public void AddFullTrustAssembly(StrongNameMembershipCondition snMC) { } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public void AddNamedPermissionSet(NamedPermissionSet permSet) { } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public NamedPermissionSet ChangeNamedPermissionSet(string name, PermissionSet pSet) { return default(NamedPermissionSet); } [Obsolete("AppDomain policy levels are obsolete. See https://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public static PolicyLevel CreateAppDomainLevel() { return default(PolicyLevel); } public void FromXml(SecurityElement e) { } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public NamedPermissionSet GetNamedPermissionSet(string name) { return default(NamedPermissionSet); } @@ -38,11 +38,11 @@ public void Recover() { } public void RemoveFullTrustAssembly(StrongName sn) { } [Obsolete("Because all GAC assemblies always get full trust, the full trust list is no longer meaningful. You should install any assemblies that are used in security policy in the GAC to ensure they are trusted.")] public void RemoveFullTrustAssembly(StrongNameMembershipCondition snMC) { } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public NamedPermissionSet RemoveNamedPermissionSet(NamedPermissionSet permSet) { return default(NamedPermissionSet); } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public NamedPermissionSet RemoveNamedPermissionSet(string name) { return default(NamedPermissionSet); } diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyStatement.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyStatement.cs index d94b4ebaec305d..7ded9666afeb99 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyStatement.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyStatement.cs @@ -5,17 +5,17 @@ namespace System.Security.Policy { public sealed partial class PolicyStatement : ISecurityEncodable, ISecurityPolicyEncodable { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public PolicyStatement(PermissionSet permSet) { } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public PolicyStatement(PermissionSet permSet, PolicyStatementAttribute attributes) { } public PolicyStatementAttribute Attributes { get; set; } public string AttributeString { get { return null; } } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public PermissionSet PermissionSet { get; set; } diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Publisher.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Publisher.cs index 82d4a4c014ac61..ada8aecc2c1448 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Publisher.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Publisher.cs @@ -5,7 +5,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class Publisher : EvidenceBase, IIdentityPermissionFactory diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Site.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Site.cs index e257cb4d44f126..885d0cdf5a37ca 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Site.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Site.cs @@ -3,7 +3,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class Site : EvidenceBase, IIdentityPermissionFactory diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongName.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongName.cs index 7f9521026ed3fc..6ef2b7de49a826 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongName.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongName.cs @@ -5,7 +5,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class StrongName : EvidenceBase, IIdentityPermissionFactory diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongNameMembershipCondition.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongNameMembershipCondition.cs index e7fa159370023c..a4fcaaa3ac2a72 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongNameMembershipCondition.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongNameMembershipCondition.cs @@ -5,7 +5,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class StrongNameMembershipCondition : ISecurityEncodable, ISecurityPolicyEncodable, IMembershipCondition diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Url.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Url.cs index a108d3691fb56b..c83c904c5056c2 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Url.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Url.cs @@ -3,7 +3,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class Url : EvidenceBase, IIdentityPermissionFactory diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Zone.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Zone.cs index 2e08fd3e3a0f01..e494f429238cb8 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Zone.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Zone.cs @@ -3,7 +3,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class Zone : EvidenceBase, IIdentityPermissionFactory diff --git a/src/libraries/System.Security.Permissions/src/System/Security/SecurityContext.cs b/src/libraries/System.Security.Permissions/src/System/Security/SecurityContext.cs index 1ee1b1d5e60a92..8d8756a54fb145 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/SecurityContext.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/SecurityContext.cs @@ -5,7 +5,7 @@ namespace System.Security { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class SecurityContext : System.IDisposable diff --git a/src/libraries/System.Security.Permissions/src/System/Security/SecurityManager.cs b/src/libraries/System.Security.Permissions/src/System/Security/SecurityManager.cs index 0ff033c383beb9..9f02c6f3951431 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/SecurityManager.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/SecurityManager.cs @@ -6,7 +6,7 @@ namespace System.Security { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public static partial class SecurityManager diff --git a/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermission.cs b/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermission.cs index c049d1e6704697..af27008cee09a3 100644 --- a/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermission.cs @@ -5,7 +5,7 @@ namespace System.ServiceProcess { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class ServiceControllerPermission : ResourcePermissionBase diff --git a/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermissionAttribute.cs index bf7d8cbd98da3d..fea924e61bd5ce 100644 --- a/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.ServiceProcess { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly | AttributeTargets.Event, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermission.cs b/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermission.cs index 0905e0f5b7bd23..7107e3fd7a23f4 100644 --- a/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermission.cs @@ -6,7 +6,7 @@ namespace System.Transactions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class DistributedTransactionPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermissionAttribute.cs index cf17caabf319bf..4c794df14bee42 100644 --- a/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Transactions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] diff --git a/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermission.cs b/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermission.cs index 74b2a712674cb5..9735b517fe4f90 100644 --- a/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermission.cs @@ -6,7 +6,7 @@ namespace System.Web { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class AspNetHostingPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermissionAttribute.cs index d5c8631f21623a..9b91e5a31dc784 100644 --- a/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Web { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Xaml/Permissions/XamlLoadPermission.cs b/src/libraries/System.Security.Permissions/src/System/Xaml/Permissions/XamlLoadPermission.cs index e5b1f021d1c734..5ce3a929edeb7e 100644 --- a/src/libraries/System.Security.Permissions/src/System/Xaml/Permissions/XamlLoadPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Xaml/Permissions/XamlLoadPermission.cs @@ -10,7 +10,7 @@ namespace System.Xaml.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class XamlLoadPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/Syndication/DateTimeHelper.cs b/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/Syndication/DateTimeHelper.cs index ee0bb46bdfb161..b9b6cada89d568 100644 --- a/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/Syndication/DateTimeHelper.cs +++ b/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/Syndication/DateTimeHelper.cs @@ -58,7 +58,7 @@ private static bool Rfc3339DateTimeParser(string dateTimeString, out DateTimeOff ++i; } -#if NETCOREAPP +#if NET dateTimeString = string.Concat(dateTimeString.AsSpan(0, 19), dateTimeString.AsSpan(i)); #else dateTimeString = dateTimeString.Substring(0, 19) + dateTimeString.Substring(i); diff --git a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs index dc3a9d931f13e3..fa6be7f42e7403 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs @@ -73,7 +73,7 @@ public unsafe void RequestAdditionalTime(int milliseconds) } } -#if NETCOREAPP +#if NET /// /// When this method is called from OnStart, OnStop, OnPause or OnContinue, /// the specified wait hint is passed to the diff --git a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceController.cs b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceController.cs index 2892e1abebe46f..3041721ecaa6a0 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceController.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceController.cs @@ -934,7 +934,7 @@ public void Stop() /// /// true to stop all running dependent services together with the service; false to stop only the service. /// -#if NETCOREAPP +#if NET public #else private diff --git a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/SessionChangeDescription.cs b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/SessionChangeDescription.cs index e4924e93c414e5..0503b80316e893 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/SessionChangeDescription.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/SessionChangeDescription.cs @@ -6,7 +6,7 @@ namespace System.ServiceProcess { public readonly struct SessionChangeDescription -#if NETCOREAPP +#if NET : IEquatable #endif { diff --git a/src/libraries/System.ServiceProcess.ServiceController/tests/ServiceBaseTests.cs b/src/libraries/System.ServiceProcess.ServiceController/tests/ServiceBaseTests.cs index 2d097c766c3322..f0b49f902fa838 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/tests/ServiceBaseTests.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/tests/ServiceBaseTests.cs @@ -70,7 +70,7 @@ private void Cleanup() } } -#if NETCOREAPP +#if NET [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsPrivilegedProcess))] [InlineData(-2)] [InlineData((long)int.MaxValue + 1)] diff --git a/src/libraries/System.Text.Encodings.Web/src/System/IO/TextWriterExtensions.cs b/src/libraries/System.Text.Encodings.Web/src/System/IO/TextWriterExtensions.cs index bcb3cb0bd77830..11bff860545bd3 100644 --- a/src/libraries/System.Text.Encodings.Web/src/System/IO/TextWriterExtensions.cs +++ b/src/libraries/System.Text.Encodings.Web/src/System/IO/TextWriterExtensions.cs @@ -3,7 +3,7 @@ using System.Diagnostics; -#if !NETCOREAPP +#if !NET using System.Buffers; #endif @@ -29,7 +29,7 @@ public static void WritePartialString(this TextWriter writer, string value, int // if slicing is required, call TextWriter.Write(ROS) if available; // otherwise rent an array and implement the Write routine ourselves ReadOnlySpan sliced = value.AsSpan(offset, count); -#if NETCOREAPP +#if NET writer.Write(sliced); #else char[] rented = ArrayPool.Shared.Rent(sliced.Length); diff --git a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/AllowedBmpCodePointsBitmap.cs b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/AllowedBmpCodePointsBitmap.cs index 377d1d0c071d45..d989b7c267e78d 100644 --- a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/AllowedBmpCodePointsBitmap.cs +++ b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/AllowedBmpCodePointsBitmap.cs @@ -6,7 +6,7 @@ using System.Runtime.CompilerServices; using System.Text.Unicode; -#if NETCOREAPP +#if NET using System.Numerics; #endif @@ -69,7 +69,7 @@ public void ForbidUndefinedCharacters() Span thisAllowedCharactersBitmap = new Span(pBitmap, BitmapLengthInDWords); Debug.Assert(definedCharsBitmapAsLittleEndian.Length == thisAllowedCharactersBitmap.Length * sizeof(uint)); -#if NETCOREAPP +#if NET if (Vector.IsHardwareAccelerated && BitConverter.IsLittleEndian) { while (!definedCharsBitmapAsLittleEndian.IsEmpty) diff --git a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.Ascii.cs b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.Ascii.cs index 03c0e7fc324bfd..d2aac7f94f4cfb 100644 --- a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.Ascii.cs +++ b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.Ascii.cs @@ -5,7 +5,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if NETCOREAPP +#if NET using System.Runtime.Intrinsics; #endif @@ -22,7 +22,7 @@ private unsafe partial struct AllowedAsciiCodePoints [FieldOffset(0)] // ensure same offset with AsVector field private fixed byte AsBytes[16]; -#if NETCOREAPP +#if NET #if !TARGET_BROWSER [FieldOffset(0)] // ensure same offset with AsBytes field internal Vector128 AsVector; diff --git a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.cs b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.cs index 56fc2b77a93872..e3f12a3b2a84de 100644 --- a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.cs +++ b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.cs @@ -5,11 +5,11 @@ using System.Diagnostics; using System.Runtime.CompilerServices; -#if NETCOREAPP +#if NET using System.Runtime.Intrinsics.X86; #endif -#if NETCOREAPP +#if NET using System.Runtime.Intrinsics.Arm; #endif @@ -347,7 +347,7 @@ public int GetIndexOfFirstByteToEncode(ReadOnlySpan data) int dataOriginalLength = data.Length; -#if NETCOREAPP +#if NET if (Ssse3.IsSupported || (AdvSimd.Arm64.IsSupported && BitConverter.IsLittleEndian)) { int asciiBytesSkipped; @@ -416,7 +416,7 @@ public unsafe int GetIndexOfFirstCharToEncode(ReadOnlySpan data) // The SIMD-enabled version handles only ASCII characters. nuint idx = 0; -#if NETCOREAPP +#if NET if (Ssse3.IsSupported) { idx = GetIndexOfFirstCharToEncodeSsse3(pData, lengthInChars); diff --git a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/TextEncoder.cs b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/TextEncoder.cs index 41b620e1beec02..4c9aee5292948a 100644 --- a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/TextEncoder.cs +++ b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/TextEncoder.cs @@ -150,7 +150,7 @@ private string EncodeToNewString(ReadOnlySpan value, int indexOfFirstCharT ReadOnlySpan remainingInput = value.Slice(indexOfFirstCharToEncode); ValueStringBuilder stringBuilder = new ValueStringBuilder(stackalloc char[EncodeStartingOutputBufferSize]); -#if !NETCOREAPP +#if !NET // Can't call string.Concat later in the method, so memcpy now. stringBuilder.Append(value.Slice(0, indexOfFirstCharToEncode)); #endif @@ -175,7 +175,7 @@ private string EncodeToNewString(ReadOnlySpan value, int indexOfFirstCharT stringBuilder.Length -= destBuffer.Length - charsWrittenJustNow; } while (!remainingInput.IsEmpty); -#if NETCOREAPP +#if NET string retVal = string.Concat(value.Slice(0, indexOfFirstCharToEncode), stringBuilder.AsSpan()); stringBuilder.Dispose(); return retVal; diff --git a/src/libraries/System.Text.Json/Common/JsonCamelCaseNamingPolicy.cs b/src/libraries/System.Text.Json/Common/JsonCamelCaseNamingPolicy.cs index 436489906a6250..43fa642a3c6d2d 100644 --- a/src/libraries/System.Text.Json/Common/JsonCamelCaseNamingPolicy.cs +++ b/src/libraries/System.Text.Json/Common/JsonCamelCaseNamingPolicy.cs @@ -12,7 +12,7 @@ public override string ConvertName(string name) return name; } -#if NETCOREAPP +#if NET return string.Create(name.Length, name, (chars, name) => { name.CopyTo(chars); diff --git a/src/libraries/System.Text.Json/Common/JsonHelpers.cs b/src/libraries/System.Text.Json/Common/JsonHelpers.cs index afa3afb4dc2ce4..ad718eba4a41fe 100644 --- a/src/libraries/System.Text.Json/Common/JsonHelpers.cs +++ b/src/libraries/System.Text.Json/Common/JsonHelpers.cs @@ -11,7 +11,7 @@ namespace System.Text.Json { internal static partial class JsonHelpers { -#if !NETCOREAPP +#if !NET /// /// netstandard/netfx polyfill for Dictionary.TryAdd /// diff --git a/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs b/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs index 9dab389dd045a0..ec6b46db24e877 100644 --- a/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs +++ b/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs @@ -97,7 +97,7 @@ private static bool HasCustomAttributeWithName(this MemberInfo memberInfo, strin object?[] parameters) { ConstructorInfo ctorInfo = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, parameterTypes, null)!; -#if NETCOREAPP +#if NET return ctorInfo.Invoke(BindingFlags.DoNotWrapExceptions, null, parameters, null); #else object? result = null; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs index f9b1fffd4243b2..6bd5a2814b6460 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs @@ -833,7 +833,7 @@ private static ArraySegment ReadToEnd(Stream stream) } private static async -#if NETCOREAPP +#if NET ValueTask> #else Task> @@ -871,7 +871,7 @@ private static async Debug.Assert(rented.Length >= JsonConstants.Utf8Bom.Length); lastRead = await stream.ReadAsync( -#if NETCOREAPP +#if NET rented.AsMemory(written, utf8BomLength - written), #else rented, @@ -902,7 +902,7 @@ private static async } lastRead = await stream.ReadAsync( -#if NETCOREAPP +#if NET rented.AsMemory(written), #else rented, diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs index f6c6e9255d9c31..751f262acf3a34 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs @@ -95,7 +95,7 @@ public static bool TryParseAsISO(ReadOnlySpan source, out DateTimeOffset v return TryCreateDateTimeOffsetInterpretingDataAsLocalTime(parseData, out value); } -#if NETCOREAPP +#if NET public static bool TryParseAsIso(ReadOnlySpan source, out DateOnly value) { if (TryParseDateTimeOffset(source, out DateTimeParseData parseData) && diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs index 322b1d315c091e..63e2e177f49eb3 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs @@ -76,7 +76,7 @@ static bool TryAdvanceWithReadAhead(scoped ref Utf8JsonReader reader) } } -#if !NETCOREAPP +#if !NET /// /// Returns if is a valid Unicode scalar /// value, i.e., is in [ U+0000..U+D7FF ], inclusive; or [ U+E000..U+10FFFF ], inclusive. @@ -165,7 +165,7 @@ public static bool TrySkipPartial(this ref Utf8JsonReader reader) /// public static string Utf8GetString(ReadOnlySpan bytes) { -#if NETCOREAPP +#if NET return Encoding.UTF8.GetString(bytes); #else if (bytes.Length == 0) @@ -191,7 +191,7 @@ public static Dictionary CreateDictionaryFromCollection comparer) where TKey : notnull { -#if !NETCOREAPP +#if !NET var dictionary = new Dictionary(comparer); foreach (KeyValuePair item in collection) @@ -207,7 +207,7 @@ public static Dictionary CreateDictionaryFromCollection= 0); path.Append('['); -#if NETCOREAPP +#if NET Span chars = stackalloc char[JsonConstants.MaximumFormatUInt32Length]; bool formatted = ((uint)index).TryFormat(chars, out int charsWritten); Debug.Assert(formatted); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs index 7408aaecc53ce0..298a59a6471739 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs @@ -210,7 +210,7 @@ public static string TranscodeHelper(ReadOnlySpan utf8Unescaped) { try { -#if NETCOREAPP +#if NET return s_utf8Encoding.GetString(utf8Unescaped); #else if (utf8Unescaped.IsEmpty) @@ -241,7 +241,7 @@ public static int TranscodeHelper(ReadOnlySpan utf8Unescaped, Span d { try { -#if NETCOREAPP +#if NET return s_utf8Encoding.GetChars(utf8Unescaped, destination); #else if (utf8Unescaped.IsEmpty) @@ -285,7 +285,7 @@ public static void ValidateUtf8(ReadOnlySpan utf8Buffer) #else try { -#if NETCOREAPP +#if NET s_utf8Encoding.GetCharCount(utf8Buffer); #else if (utf8Buffer.IsEmpty) @@ -317,7 +317,7 @@ internal static int GetUtf8ByteCount(ReadOnlySpan text) { try { -#if NETCOREAPP +#if NET return s_utf8Encoding.GetByteCount(text); #else if (text.IsEmpty) @@ -348,7 +348,7 @@ internal static int GetUtf8FromText(ReadOnlySpan text, Span dest) { try { -#if NETCOREAPP +#if NET return s_utf8Encoding.GetBytes(text, dest); #else if (text.IsEmpty) @@ -379,7 +379,7 @@ internal static int GetUtf8FromText(ReadOnlySpan text, Span dest) internal static string GetTextFromUtf8(ReadOnlySpan utf8Text) { -#if NETCOREAPP +#if NET return s_utf8Encoding.GetString(utf8Text); #else if (utf8Text.IsEmpty) @@ -528,7 +528,7 @@ private static bool TryUnescape(ReadOnlySpan source, Span destinatio + JsonConstants.UnicodePlane01StartValue; } -#if NETCOREAPP +#if NET var rune = new Rune(scalar); bool success = rune.TryEncodeToUtf8(destination.Slice(written), out int bytesWritten); #else @@ -601,7 +601,7 @@ private static bool TryUnescape(ReadOnlySpan source, Span destinatio return false; } -#if !NETCOREAPP +#if !NET /// /// Copies the UTF-8 code unit representation of this scalar to an output buffer. /// The buffer must be large enough to hold the required number of s. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs index 9cdcc0ddfad74f..b426f61cbb31dd 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs @@ -145,7 +145,7 @@ public static bool TryGetEscapedGuid(ReadOnlySpan source, out Guid value) return false; } -#if NETCOREAPP +#if NET public static bool TryGetFloatingPointConstant(ReadOnlySpan span, out Half value) { if (span.Length == 3) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactoryHelpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactoryHelpers.cs index 622ba2cf21d19e..3d1c4ce8fce545 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactoryHelpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactoryHelpers.cs @@ -93,7 +93,7 @@ public static MethodInfo GetImmutableDictionaryCreateRangeMethod(this Type type, public static bool IsNonGenericStackOrQueue(this Type type) { -#if NETCOREAPP +#if NET // Optimize for linking scenarios where mscorlib is trimmed out. const string stackTypeName = "System.Collections.Stack, System.Collections.NonGeneric"; const string queueTypeName = "System.Collections.Queue, System.Collections.NonGeneric"; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/CharConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/CharConverter.cs index 82e7e2699a956e..c102a0879e1ac6 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/CharConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/CharConverter.cs @@ -36,7 +36,7 @@ public override char Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSer public override void Write(Utf8JsonWriter writer, char value, JsonSerializerOptions options) { writer.WriteStringValue( -#if NETCOREAPP +#if NET new ReadOnlySpan(in value) #else value.ToString() @@ -53,7 +53,7 @@ internal override char ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type ty internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, char value, JsonSerializerOptions options, bool isWritingExtensionDataProperty) { writer.WritePropertyName( -#if NETCOREAPP +#if NET new ReadOnlySpan(in value) #else value.ToString() diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs index 99b576030243eb..5f9ddf1eee1b62 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs @@ -61,7 +61,7 @@ public EnumConverter(EnumConverterOptions converterOptions, JsonNamingPolicy? na _nameCacheForReading = new ConcurrentDictionary(); } -#if NETCOREAPP +#if NET string[] names = Enum.GetNames(); T[] values = Enum.GetValues(); #else @@ -74,7 +74,7 @@ public EnumConverter(EnumConverterOptions converterOptions, JsonNamingPolicy? na for (int i = 0; i < names.Length; i++) { -#if NETCOREAPP +#if NET T value = values[i]; #else T value = (T)values.GetValue(i)!; @@ -106,7 +106,7 @@ public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerial return default; } -#if NETCOREAPP +#if NET if (TryParseEnumCore(ref reader, out T value)) #else string? enumString = reader.GetString(); @@ -116,7 +116,7 @@ public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerial return value; } -#if NETCOREAPP +#if NET return ReadEnumUsingNamingPolicy(reader.GetString()); #else return ReadEnumUsingNamingPolicy(enumString); @@ -270,7 +270,7 @@ public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions internal override T ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { -#if NETCOREAPP +#if NET if (TryParseEnumCore(ref reader, out T value)) #else string? enumString = reader.GetString(); @@ -280,7 +280,7 @@ internal override T ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeT return value; } -#if NETCOREAPP +#if NET return ReadEnumUsingNamingPolicy(reader.GetString()); #else return ReadEnumUsingNamingPolicy(enumString); @@ -362,14 +362,14 @@ internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, T value, J } private bool TryParseEnumCore( -#if NETCOREAPP +#if NET ref Utf8JsonReader reader, #else string? source, #endif out T value) { -#if NETCOREAPP +#if NET char[]? rentedBuffer = null; int bufferLength = reader.ValueLength; @@ -393,7 +393,7 @@ private bool TryParseEnumCore( value = default; } -#if NETCOREAPP +#if NET if (rentedBuffer != null) { charBuffer.Slice(0, charsWritten).Clear(); @@ -525,7 +525,7 @@ private static string[] SplitFlagsEnum(string value) { // todo: optimize implementation here by leveraging https://github.com/dotnet/runtime/issues/934. return value.Split( -#if NETCOREAPP +#if NET ValueSeparator #else new string[] { ValueSeparator }, StringSplitOptions.None diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/VersionConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/VersionConverter.cs index c3e60ab0448d34..85e0d8f67398a4 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/VersionConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/VersionConverter.cs @@ -7,7 +7,7 @@ namespace System.Text.Json.Serialization.Converters { internal sealed class VersionConverter : JsonPrimitiveConverter { -#if NETCOREAPP +#if NET private const int MinimumVersionLength = 3; // 0.0 private const int MaximumVersionLength = 43; // 2147483647.2147483647.2147483647.2147483647 @@ -34,7 +34,7 @@ private static Version ReadCore(ref Utf8JsonReader reader) { Debug.Assert(reader.TokenType is JsonTokenType.PropertyName or JsonTokenType.String); -#if NETCOREAPP +#if NET if (!JsonHelpers.IsInRangeInclusive(reader.ValueLength, MinimumVersionLength, MaximumEscapedVersionLength)) { ThrowHelper.ThrowFormatException(DataType.Version); @@ -84,7 +84,7 @@ public override void Write(Utf8JsonWriter writer, Version? value, JsonSerializer return; } -#if NETCOREAPP +#if NET #if NET8_0_OR_GREATER Span span = stackalloc byte[MaximumVersionLength]; #else @@ -110,7 +110,7 @@ internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, Version va ThrowHelper.ThrowArgumentNullException(nameof(value)); } -#if NETCOREAPP +#if NET #if NET8_0_OR_GREATER Span span = stackalloc byte[MaximumVersionLength]; #else diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs index 469abaae498d25..cf8b87696ea713 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs @@ -214,7 +214,7 @@ internal bool TryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSeriali bool success; if ( -#if NETCOREAPP +#if NET !typeof(T).IsValueType && #endif CanBePolymorphic) @@ -367,7 +367,7 @@ internal bool TryWrite(Utf8JsonWriter writer, in T? value, JsonSerializerOptions bool success; if ( -#if NETCOREAPP +#if NET // Short-circuit the check against "is not null"; treated as a constant by recent versions of the JIT. !typeof(T).IsValueType && #else diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs index c8fd040736dbb9..e171d8cdebe490 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs @@ -213,7 +213,7 @@ internal void ClearCaches() internal sealed class CachingContext { private readonly ConcurrentDictionary _cache = new(); -#if !NETCOREAPP +#if !NET private readonly Func _cacheEntryFactory; #endif @@ -221,7 +221,7 @@ public CachingContext(JsonSerializerOptions options, int hashCode) { Options = options; HashCode = hashCode; -#if !NETCOREAPP +#if !NET _cacheEntryFactory = type => CreateCacheEntry(type, this); #endif } @@ -254,7 +254,7 @@ public void Clear() private CacheEntry GetOrAddCacheEntry(Type type) { -#if NETCOREAPP +#if NET return _cache.GetOrAdd(type, CreateCacheEntry, this); #else return _cache.GetOrAdd(type, _cacheEntryFactory); @@ -605,7 +605,7 @@ static void AddHashCode(ref HashCode hc, TValue? value) } } -#if !NETCOREAPP +#if !NET /// /// Polyfill for System.HashCode. /// diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Converters.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Converters.cs index b5bb76c77b0652..c96e2a1c8f5da5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Converters.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Converters.cs @@ -51,7 +51,7 @@ private static Dictionary GetDefaultSimpleConverters() Add(JsonMetadataServices.CharConverter); Add(JsonMetadataServices.DateTimeConverter); Add(JsonMetadataServices.DateTimeOffsetConverter); -#if NETCOREAPP +#if NET Add(JsonMetadataServices.DateOnlyConverter); Add(JsonMetadataServices.TimeOnlyConverter); Add(JsonMetadataServices.HalfConverter); 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 3a39315eba51c0..3ce9c15709819a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Helpers.cs @@ -23,7 +23,7 @@ internal static MemberAccessor MemberAccessor static MemberAccessor Initialize() { MemberAccessor value = -#if NETCOREAPP +#if NET // if dynamic code isn't supported, fallback to reflection RuntimeFeature.IsDynamicCodeSupported ? new ReflectionEmitCachingMemberAccessor() : diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs index 1cf87d0c940e7a..9c6cb4b9e3ce3d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs @@ -50,7 +50,7 @@ public static partial class JsonMetadataServices public static JsonConverter DateTimeOffsetConverter => s_dateTimeOffsetConverter ??= new DateTimeOffsetConverter(); private static JsonConverter? s_dateTimeOffsetConverter; -#if NETCOREAPP +#if NET /// /// Returns a instance that converts values. /// @@ -188,7 +188,7 @@ public static partial class JsonMetadataServices public static JsonConverter ObjectConverter => s_objectConverter ??= new DefaultObjectConverter(); private static JsonConverter? s_objectConverter; -#if NETCOREAPP +#if NET /// /// Returns a instance that converts values. /// diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs index e70cd8848868af..4a6f10aa440630 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs @@ -623,7 +623,7 @@ private bool NumberHandingIsApplicable() potentialNumberType == typeof(ushort) || potentialNumberType == typeof(uint) || potentialNumberType == typeof(ulong) || -#if NETCOREAPP +#if NET potentialNumberType == typeof(Half) || #endif #if NET diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs index 379a3754cf574f..01369330feb68f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs @@ -160,7 +160,7 @@ internal override bool GetMemberAndWriteJson(object obj, ref WriteStack state, U T value = Get!(obj); if ( -#if NETCOREAPP +#if NET !typeof(T).IsValueType && // treated as a constant by recent versions of the JIT. #else !EffectiveConverter.IsValueType && diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs index e915c5bf4879ea..f8d5bffedc51dc 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs @@ -1249,7 +1249,7 @@ internal void SetCreateObjectIfCompatible(Delegate? createObject) private static bool IsByRefLike(Type type) { -#if NETCOREAPP +#if NET return type.IsByRefLike; #else if (!type.IsValueType) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.WriteHelpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.WriteHelpers.cs index d916334c1925a3..08bec6e288981b 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 @@ -36,7 +36,7 @@ internal void Serialize( writer.Flush(); } else if ( -#if NETCOREAPP +#if NET !typeof(T).IsValueType && #endif Converter.CanBePolymorphic && @@ -96,7 +96,7 @@ internal async Task SerializeAsync( await bufferWriter.WriteToStreamAsync(utf8Json, cancellationToken).ConfigureAwait(false); } else if ( -#if NETCOREAPP +#if NET !typeof(T).IsValueType && #endif Converter.CanBePolymorphic && @@ -222,7 +222,7 @@ internal void Serialize( } } else if ( -#if NETCOREAPP +#if NET !typeof(T).IsValueType && #endif Converter.CanBePolymorphic && diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.Cache.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.Cache.cs index 8e966a122a4ffe..dc203854c3d858 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.Cache.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.Cache.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NETFRAMEWORK || NETCOREAPP +#if NETFRAMEWORK || NET using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; @@ -30,7 +30,7 @@ public TValue GetOrAdd(TKey key, Func valueFactory) where { CacheEntry entry = _cache.GetOrAdd( key, -#if NETCOREAPP +#if NET static (TKey key, Func valueFactory) => new(valueFactory(key)), valueFactory); #else diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.cs index 4efe2a3af47f12..dc18286f7e1270 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NETFRAMEWORK || NETCOREAPP +#if NETFRAMEWORK || NET using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Reflection; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitMemberAccessor.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitMemberAccessor.cs index 5e6f6986539e10..7bda4bda73f5eb 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitMemberAccessor.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitMemberAccessor.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NETFRAMEWORK || NETCOREAPP +#if NETFRAMEWORK || NET using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs index 593bb6a20dffa0..dc624235377a3f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs @@ -49,7 +49,7 @@ public readonly async ValueTask ReadFromStreamAsync( do { int bytesRead = await utf8Json.ReadAsync( -#if NETCOREAPP +#if NET bufferState._buffer.AsMemory(bufferState._count), #else bufferState._buffer, bufferState._count, bufferState._buffer.Length - bufferState._count, @@ -80,7 +80,7 @@ public void ReadFromStream(Stream utf8Json) do { int bytesRead = utf8Json.Read( -#if NETCOREAPP +#if NET _buffer.AsSpan(_count)); #else _buffer, _count, _buffer.Length - _count); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs index d183423c132325..5647005377e3f0 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs @@ -412,7 +412,7 @@ public static void ReThrowWithPath(scoped ref ReadStack state, JsonReaderExcepti string message = ex.Message; // Insert the "Path" portion before "LineNumber" and "BytePositionInLine". -#if NETCOREAPP +#if NET int iPos = message.AsSpan().LastIndexOf(" LineNumber: "); #else int iPos = message.LastIndexOf(" LineNumber: ", StringComparison.Ordinal); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.Escaping.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.Escaping.cs index 62705446f8f5d1..140ecfb9112314 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.Escaping.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.Escaping.cs @@ -6,7 +6,7 @@ using System.Diagnostics; using System.Text.Encodings.Web; -#if !NETCOREAPP +#if !NET using System.Runtime.CompilerServices; #endif @@ -42,7 +42,7 @@ internal static partial class JsonWriterHelper 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // U+00F0..U+00FF ]; -#if NETCOREAPP +#if NET private const string HexFormatString = "X4"; #endif @@ -290,7 +290,7 @@ private static void EscapeNextChars(char value, Span destination, ref int break; default: destination[written++] = 'u'; -#if NETCOREAPP +#if NET int intChar = value; intChar.TryFormat(destination.Slice(written), out int charsWritten, HexFormatString); Debug.Assert(charsWritten == 4); @@ -302,7 +302,7 @@ private static void EscapeNextChars(char value, Span destination, ref int } } -#if !NETCOREAPP +#if !NET private static int WriteHex(int value, Span destination, int written) { destination[written++] = HexConverter.ToCharUpper(value >> 12); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs index b5dccf9423be6d..b2e05f589fc10c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs @@ -264,7 +264,7 @@ public static unsafe bool IsValidUtf8String(ReadOnlySpan bytes) #else try { -#if NETCOREAPP +#if NET s_utf8Encoding.GetCharCount(bytes); #else if (!bytes.IsEmpty) @@ -286,7 +286,7 @@ public static unsafe bool IsValidUtf8String(ReadOnlySpan bytes) internal static unsafe OperationStatus ToUtf8(ReadOnlySpan source, Span destination, out int written) { -#if NETCOREAPP +#if NET OperationStatus status = Utf8.FromUtf16(source, destination, out int charsRead, out written, replaceInvalidSequences: false, isFinalBlock: true); Debug.Assert(status is OperationStatus.Done or OperationStatus.DestinationTooSmall or OperationStatus.InvalidData); Debug.Assert(charsRead == source.Length || status is not OperationStatus.Done); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Double.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Double.cs index 03fab27688d0dc..abaa20358cf6a7 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Double.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Double.cs @@ -106,7 +106,7 @@ private static bool TryFormatDouble(double value, Span destination, out in // the .NET Core 3.0 logic of forwarding to the UTF16 formatter and transcoding it back to UTF8, // with some additional changes to remove dependencies on Span APIs which don't exist downlevel. -#if NETCOREAPP +#if NET return Utf8Formatter.TryFormat(value, destination, out bytesWritten); #else string utf16Text = value.ToString(JsonConstants.DoubleFormatString, CultureInfo.InvariantCulture); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Float.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Float.cs index 7342704d3479ae..c65c92a89c0357 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Float.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Float.cs @@ -106,7 +106,7 @@ private static bool TryFormatSingle(float value, Span destination, out int // the .NET Core 3.0 logic of forwarding to the UTF16 formatter and transcoding it back to UTF8, // with some additional changes to remove dependencies on Span APIs which don't exist downlevel. -#if NETCOREAPP +#if NET return Utf8Formatter.TryFormat(value, destination, out bytesWritten); #else string utf16Text = value.ToString(JsonConstants.SingleFormatString, CultureInfo.InvariantCulture); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs index fcf3ab2d4c2547..f357a89d5d2d04 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs @@ -8,7 +8,7 @@ using System.Threading; using System.Threading.Tasks; -#if !NETCOREAPP +#if !NET using System.Runtime.InteropServices; #endif @@ -309,7 +309,7 @@ public void Flush() _arrayBufferWriter.Advance(BytesPending); BytesPending = 0; -#if NETCOREAPP +#if NET _stream.Write(_arrayBufferWriter.WrittenSpan); #else Debug.Assert(_arrayBufferWriter.WrittenMemory.Length == _arrayBufferWriter.WrittenCount); @@ -423,7 +423,7 @@ public async Task FlushAsync(CancellationToken cancellationToken = default) _arrayBufferWriter.Advance(BytesPending); BytesPending = 0; -#if NETCOREAPP +#if NET await _stream.WriteAsync(_arrayBufferWriter.WrittenMemory, cancellationToken).ConfigureAwait(false); #else Debug.Assert(_arrayBufferWriter.WrittenMemory.Length == _arrayBufferWriter.WrittenCount); diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs index ce8ac3d254d3ac..4d61a6f8b3091d 100644 --- a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs +++ b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs @@ -66,7 +66,7 @@ public static IEnumerable GetTestDictionaries() yield return WrapArgs(ushort.MaxValue, 1); yield return WrapArgs(uint.MaxValue, 1); yield return WrapArgs(ulong.MaxValue, 1); -#if NETCOREAPP +#if NET yield return WrapArgs(Half.MinValue, 1); yield return WrapArgs(Int128.MinValue, 1); yield return WrapArgs(UInt128.MaxValue, 1); @@ -340,7 +340,7 @@ public async Task TestEscapedValuesOnDeserialize(string escapedPropertyName, obj new object[] { @"\u0042\u0061\u0072\u002c\u0042\u0061\u007a", MyEnumFlags.Bar | MyEnumFlags.Baz, typeof(Dictionary) }, new object[] { @"\u002b", '+', typeof(Dictionary) }, -#if NETCOREAPP +#if NET new object[] { @"\u0033\u002e\u0031\u0032\u0035\u0065\u0034", (Half)3.125e4, typeof(Dictionary) }, new object[] { @"\u002D\u0031\u0037\u0030\u0031\u0034\u0031\u0031\u0038\u0033\u0034\u0036\u0030\u0034\u0036\u0039\u0032\u0033\u0031\u0037\u0033\u0031\u0036\u0038\u0037\u0033\u0030\u0033\u0037\u0031\u0035\u0038\u0038\u0034\u0031\u0030\u0035\u0037\u0032\u0038", diff --git a/src/libraries/System.Text.Json/tests/Common/JsonNumberTestData.cs b/src/libraries/System.Text.Json/tests/Common/JsonNumberTestData.cs index d2d2591ade5ffb..83cf29458dd063 100644 --- a/src/libraries/System.Text.Json/tests/Common/JsonNumberTestData.cs +++ b/src/libraries/System.Text.Json/tests/Common/JsonNumberTestData.cs @@ -20,7 +20,7 @@ internal class JsonNumberTestData public static List Floats { get; set; } public static List Doubles { get; set; } public static List Decimals { get; set; } -#if NETCOREAPP +#if NET public static List Int128s { get; set; } public static List UInt128s { get; set; } public static List Halfs { get; set; } @@ -37,7 +37,7 @@ internal class JsonNumberTestData public static List NullableFloats { get; set; } public static List NullableDoubles { get; set; } public static List NullableDecimals { get; set; } -#if NETCOREAPP +#if NET public static List NullableInt128s { get; set; } public static List NullableUInt128s { get; set; } public static List NullableHalfs { get; set; } @@ -247,7 +247,7 @@ static JsonNumberTestData() } #endregion -#if NETCOREAPP +#if NET #region generate Int128s Int128s = new List { @@ -381,7 +381,7 @@ static JsonNumberTestData() NullableFloats = new List(Floats.Select(num => (float?)num)); NullableDoubles = new List(Doubles.Select(num => (double?)num)); NullableDecimals = new List(Decimals.Select(num => (decimal?)num)); -#if NETCOREAPP +#if NET NullableInt128s = new List(Int128s.Select(num => (Int128?)num)); NullableUInt128s = new List(UInt128s.Select(num => (UInt128?)num)); NullableHalfs = new List(Halfs.Select(num => (Half?)num)); diff --git a/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs b/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs index f641a4a31290c0..8d96c4e79c432b 100644 --- a/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs +++ b/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs @@ -15,7 +15,7 @@ namespace System.Text.Json { internal static partial class JsonTestHelper { -#if NETCOREAPP +#if NET public const string DoubleFormatString = null; public const string SingleFormatString = null; #else @@ -23,7 +23,7 @@ internal static partial class JsonTestHelper public const string SingleFormatString = "G9"; #endif -#if NETCOREAPP +#if NET public static Half NextHalf(Random random) { double mantissa = (random.NextDouble() * 2.0) - 1.0; diff --git a/src/libraries/System.Text.Json/tests/Common/NumberHandlingTests.cs b/src/libraries/System.Text.Json/tests/Common/NumberHandlingTests.cs index 6b16a631576fa2..833b01114dc682 100644 --- a/src/libraries/System.Text.Json/tests/Common/NumberHandlingTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/NumberHandlingTests.cs @@ -63,7 +63,7 @@ public async Task Number_AsRootType_RoundTrip() await RunAsRootTypeTest(JsonNumberTestData.Floats); await RunAsRootTypeTest(JsonNumberTestData.Doubles); await RunAsRootTypeTest(JsonNumberTestData.Decimals); -#if NETCOREAPP +#if NET await RunAsRootTypeTest(JsonNumberTestData.Int128s); await RunAsRootTypeTest(JsonNumberTestData.UInt128s); await RunAsRootTypeTest(JsonNumberTestData.Halfs); @@ -79,7 +79,7 @@ public async Task Number_AsRootType_RoundTrip() await RunAsRootTypeTest(JsonNumberTestData.NullableFloats); await RunAsRootTypeTest(JsonNumberTestData.NullableDoubles); await RunAsRootTypeTest(JsonNumberTestData.NullableDecimals); -#if NETCOREAPP +#if NET await RunAsRootTypeTest(JsonNumberTestData.NullableInt128s); await RunAsRootTypeTest(JsonNumberTestData.NullableUInt128s); await RunAsRootTypeTest(JsonNumberTestData.NullableHalfs); @@ -383,7 +383,7 @@ public async Task Number_AsCollectionElement_RoundTrip() await RunAsCollectionElementTest(JsonNumberTestData.Floats); await RunAsCollectionElementTest(JsonNumberTestData.Doubles); await RunAsCollectionElementTest(JsonNumberTestData.Decimals); -#if NETCOREAPP +#if NET await RunAsCollectionElementTest(JsonNumberTestData.Int128s); await RunAsCollectionElementTest(JsonNumberTestData.UInt128s); await RunAsCollectionElementTest(JsonNumberTestData.Halfs); @@ -403,7 +403,7 @@ public async Task Number_AsCollectionElement_RoundTrip() await RunAsCollectionElementTest(JsonNumberTestData.NullableFloats); await RunAsCollectionElementTest(JsonNumberTestData.NullableDoubles); await RunAsCollectionElementTest(JsonNumberTestData.NullableDecimals); -#if NETCOREAPP +#if NET await RunAsCollectionElementTest(JsonNumberTestData.NullableInt128s); await RunAsCollectionElementTest(JsonNumberTestData.NullableUInt128s); await RunAsCollectionElementTest(JsonNumberTestData.NullableHalfs); @@ -781,7 +781,7 @@ public async Task FloatingPointConstants_Pass() async Task PerformFloatingPointSerialization(string testString) { string testStringAsJson = $@"""{testString}"""; -#if NETCOREAPP +#if NET string testJson = @$"{{""HalfNumber"":{testStringAsJson},""FloatNumber"":{testStringAsJson},""DoubleNumber"":{testStringAsJson}}}"; #else string testJson = @$"{{""FloatNumber"":{testStringAsJson},""DoubleNumber"":{testStringAsJson}}}"; @@ -792,14 +792,14 @@ async Task PerformFloatingPointSerialization(string testString) { case "NaN": obj = await Serializer.DeserializeWrapper(testJson, s_optionsAllowFloatConstants); -#if NETCOREAPP +#if NET Assert.Equal(Half.NaN, obj.HalfNumber); #endif Assert.Equal(float.NaN, obj.FloatNumber); Assert.Equal(double.NaN, obj.DoubleNumber); obj = await Serializer.DeserializeWrapper(testJson, s_optionReadFromStr); -#if NETCOREAPP +#if NET Assert.Equal(Half.NaN, obj.HalfNumber); #endif Assert.Equal(float.NaN, obj.FloatNumber); @@ -807,14 +807,14 @@ async Task PerformFloatingPointSerialization(string testString) break; case "Infinity": obj = await Serializer.DeserializeWrapper(testJson, s_optionsAllowFloatConstants); -#if NETCOREAPP +#if NET Assert.Equal(Half.PositiveInfinity, obj.HalfNumber); #endif Assert.Equal(float.PositiveInfinity, obj.FloatNumber); Assert.Equal(double.PositiveInfinity, obj.DoubleNumber); obj = await Serializer.DeserializeWrapper(testJson, s_optionReadFromStr); -#if NETCOREAPP +#if NET Assert.Equal(Half.PositiveInfinity, obj.HalfNumber); #endif Assert.Equal(float.PositiveInfinity, obj.FloatNumber); @@ -822,14 +822,14 @@ async Task PerformFloatingPointSerialization(string testString) break; case "-Infinity": obj = await Serializer.DeserializeWrapper(testJson, s_optionsAllowFloatConstants); -#if NETCOREAPP +#if NET Assert.Equal(Half.NegativeInfinity, obj.HalfNumber); #endif Assert.Equal(float.NegativeInfinity, obj.FloatNumber); Assert.Equal(double.NegativeInfinity, obj.DoubleNumber); obj = await Serializer.DeserializeWrapper(testJson, s_optionReadFromStr); -#if NETCOREAPP +#if NET Assert.Equal(Half.NegativeInfinity, obj.HalfNumber); #endif Assert.Equal(float.NegativeInfinity, obj.FloatNumber); @@ -877,7 +877,7 @@ public async Task FloatingPointConstants_Fail(string testString) { string testStringAsJson = $@"""{testString}"""; string testJson; -#if NETCOREAPP +#if NET testJson = @$"{{""HalfNumber"":{testStringAsJson}}}"; await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(testJson, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(testJson, s_optionReadFromStr)); @@ -894,7 +894,7 @@ public async Task FloatingPointConstants_Fail(string testString) [Fact] public async Task AllowFloatingPointConstants_WriteAsNumber_IfNotConstant() { -#if NETCOREAPP +#if NET Half half = (Half)1; // Not written as "1" Assert.Equal("1", await Serializer.SerializeWrapper(half, s_optionsAllowFloatConstants)); @@ -914,7 +914,7 @@ public async Task AllowFloatingPointConstants_WriteAsNumber_IfNotConstant() [InlineData("-Infinity")] public async Task Unquoted_FloatingPointConstants_Read_Fail(string testString) { -#if NETCOREAPP +#if NET await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(testString, s_optionsAllowFloatConstants)); #endif await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(testString, s_optionsAllowFloatConstants)); @@ -924,7 +924,7 @@ public async Task Unquoted_FloatingPointConstants_Read_Fail(string testString) public struct StructWithNumbers { -#if NETCOREAPP +#if NET public Half HalfNumber { get; set; } #endif public float FloatNumber { get; set; } @@ -985,7 +985,7 @@ public async Task FloatingPointConstants_IncompatibleNumber() await AssertFloatingPointIncompatible_Fails(); await AssertFloatingPointIncompatible_Fails(); await AssertFloatingPointIncompatible_Fails(); -#if NETCOREAPP +#if NET await AssertFloatingPointIncompatible_Fails(); await AssertFloatingPointIncompatible_Fails(); await AssertFloatingPointIncompatible_Fails(); @@ -1031,7 +1031,7 @@ public async Task UnsupportedFormats() await AssertUnsupportedFormatThrows(); await AssertUnsupportedFormatThrows(); await AssertUnsupportedFormatThrows(); -#if NETCOREAPP +#if NET await AssertUnsupportedFormatThrows(); await AssertUnsupportedFormatThrows(); await AssertUnsupportedFormatThrows(); @@ -1058,7 +1058,7 @@ private async Task AssertUnsupportedFormatThrows() } } -#if NETCOREAPP +#if NET [Fact] public async Task InvalidNumberFormatThrows() { @@ -1103,7 +1103,7 @@ public async Task EscapingTest() await PerformEscapingTest(JsonNumberTestData.Floats, options); await PerformEscapingTest(JsonNumberTestData.Doubles, options); await PerformEscapingTest(JsonNumberTestData.Decimals, options); -#if NETCOREAPP +#if NET await PerformEscapingTest(JsonNumberTestData.Int128s, options); await PerformEscapingTest(JsonNumberTestData.UInt128s, options); await PerformEscapingTest(JsonNumberTestData.Halfs, options); @@ -1180,7 +1180,7 @@ public async Task Number_RoundtripNull() await Perform_Number_RoundTripNull_Test(); await Perform_Number_RoundTripNull_Test(); await Perform_Number_RoundTripNull_Test(); -#if NETCOREAPP +#if NET await Perform_Number_RoundTripNull_Test(); await Perform_Number_RoundTripNull_Test(); await Perform_Number_RoundTripNull_Test(); @@ -1210,7 +1210,7 @@ public async Task NullableNumber_RoundtripNull() await Perform_NullableNumber_RoundTripNull_Test(); await Perform_NullableNumber_RoundTripNull_Test(); await Perform_NullableNumber_RoundTripNull_Test(); -#if NETCOREAPP +#if NET await Perform_NullableNumber_RoundTripNull_Test(); await Perform_NullableNumber_RoundTripNull_Test(); await Perform_NullableNumber_RoundTripNull_Test(); @@ -1243,7 +1243,7 @@ public async Task Disallow_ArbritaryStrings_On_AllowFloatingPointConstants() await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); -#if NETCOREAPP +#if NET await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); @@ -1259,7 +1259,7 @@ public async Task Disallow_ArbritaryStrings_On_AllowFloatingPointConstants() await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); -#if NETCOREAPP +#if NET await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); diff --git a/src/libraries/System.Text.Json/tests/Common/Utf8MemoryStream.cs b/src/libraries/System.Text.Json/tests/Common/Utf8MemoryStream.cs index 2904d744aa949a..c28b5bb6c1127b 100644 --- a/src/libraries/System.Text.Json/tests/Common/Utf8MemoryStream.cs +++ b/src/libraries/System.Text.Json/tests/Common/Utf8MemoryStream.cs @@ -20,7 +20,7 @@ public Utf8MemoryStream(string text) : base(Encoding.UTF8.GetBytes(text)) { } -#if NETCOREAPP +#if NET public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) => base.WriteAsync(buffer, _ignoreCancellationTokenOnWriteAsync ? default : cancellationToken); #endif diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs index 182981002b742b..a26c22e1dde2c6 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs @@ -38,7 +38,7 @@ public interface ITestContext public JsonTypeInfo JsonElement { get; } public JsonTypeInfo ClassWithEnumAndNullable { get; } public JsonTypeInfo ClassWithNullableProperties { get; } -#if NETCOREAPP +#if NET public JsonTypeInfo ClassWithDateOnlyAndTimeOnlyValues { get; } #endif public JsonTypeInfo ClassWithCustomConverter { get; } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs index 308a6b8a104600..2db01d53c6eba9 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs @@ -34,7 +34,7 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(JsonElement))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties))] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(RealWorldContextTests.ClassWithDateOnlyAndTimeOnlyValues))] #endif [JsonSerializable(typeof(ClassWithCustomConverter))] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs index 10e394518cdf5e..7c99a9f7ec4bbb 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs @@ -33,7 +33,7 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(JsonElement), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties), GenerationMode = JsonSourceGenerationMode.Metadata)] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(RealWorldContextTests.ClassWithDateOnlyAndTimeOnlyValues), GenerationMode = JsonSourceGenerationMode.Metadata)] #endif [JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata)] @@ -137,7 +137,7 @@ public override void EnsureFastPathGeneratedAsExpected() [JsonSerializable(typeof(JsonElement))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties))] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(RealWorldContextTests.ClassWithDateOnlyAndTimeOnlyValues))] #endif [JsonSerializable(typeof(ClassWithCustomConverter))] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs index 529bd598b6ea25..d2ef2350092be6 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs @@ -34,7 +34,7 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(JsonElement), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(RealWorldContextTests.ClassWithDateOnlyAndTimeOnlyValues), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] #endif [JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs index 00ce5d49d45131..152b716d2aaf16 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs @@ -893,7 +893,7 @@ void RunTest(ClassWithNullableProperties expected) } } -#if NETCOREAPP +#if NET [Fact] public virtual void ClassWithDateOnlyAndTimeOnlyValues_Roundtrip() { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NumberHandlingTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NumberHandlingTests.cs index 0fdcf44a0e88ee..9b5ae831bc43aa 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NumberHandlingTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NumberHandlingTests.cs @@ -244,7 +244,7 @@ public NumberHandlingTests_Metadata() [JsonSerializable(typeof(List))] [JsonSerializable(typeof(Queue))] [JsonSerializable(typeof(ImmutableList))] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(Int128))] [JsonSerializable(typeof(Int128[]))] [JsonSerializable(typeof(ConcurrentQueue))] @@ -694,7 +694,7 @@ public NumberHandlingTests_Default() [JsonSerializable(typeof(List))] [JsonSerializable(typeof(List))] [JsonSerializable(typeof(List))] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(Int128))] [JsonSerializable(typeof(Int128[]))] [JsonSerializable(typeof(ConcurrentQueue))] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs index 162a8b12bd7e74..937117a84b7d1c 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs @@ -35,7 +35,7 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(JsonElement))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties))] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(RealWorldContextTests.ClassWithDateOnlyAndTimeOnlyValues))] #endif [JsonSerializable(typeof(ClassWithCustomConverter))] @@ -88,7 +88,7 @@ internal partial class SerializationContext : JsonSerializerContext, ITestContex [JsonSerializable(typeof(JsonElement), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties), GenerationMode = JsonSourceGenerationMode.Serialization)] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(RealWorldContextTests.ClassWithDateOnlyAndTimeOnlyValues), GenerationMode = JsonSourceGenerationMode.Serialization)] #endif [JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] @@ -144,7 +144,7 @@ internal partial class SerializationWithPerTypeAttributeContext : JsonSerializer [JsonSerializable(typeof(JsonElement), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties), GenerationMode = JsonSourceGenerationMode.Serialization)] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(RealWorldContextTests.ClassWithDateOnlyAndTimeOnlyValues), GenerationMode = JsonSourceGenerationMode.Serialization)] #endif [JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] @@ -482,7 +482,7 @@ void RunTest(ClassWithNullableProperties expected) } } -#if NETCOREAPP +#if NET [Fact] public override void ClassWithDateOnlyAndTimeOnlyValues_Roundtrip() { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/CompilationHelper.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/CompilationHelper.cs index 09daf5795dab24..7f56065297f171 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/CompilationHelper.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/CompilationHelper.cs @@ -46,7 +46,7 @@ public static CSharpParseOptions CreateParseOptions( documentationMode: documentationMode ?? DocumentationMode.Parse); } -#if NETCOREAPP +#if NET private static readonly Assembly systemRuntimeAssembly = Assembly.Load(new AssemblyName("System.Runtime")); #endif @@ -68,7 +68,7 @@ public static Compilation CreateCompilation( MetadataReference.CreateFromFile(typeof(GeneratedCodeAttribute).Assembly.Location), MetadataReference.CreateFromFile(typeof(ReadOnlySpan<>).Assembly.Location), MetadataReference.CreateFromFile(typeof(Console).Assembly.Location), -#if NETCOREAPP +#if NET MetadataReference.CreateFromFile(typeof(LinkedList<>).Assembly.Location), MetadataReference.CreateFromFile(systemRuntimeAssembly.Location), #else @@ -94,7 +94,7 @@ public static Compilation CreateCompilation( SyntaxTree[] syntaxTrees = new[] { CSharpSyntaxTree.ParseText(source, parseOptions), -#if !NETCOREAPP +#if !NET CSharpSyntaxTree.ParseText(NetfxPolyfillAttributes, parseOptions), #endif }; @@ -169,7 +169,7 @@ public static byte[] CreateAssemblyImage(Compilation compilation) return ms.ToArray(); } -#if !NETCOREAPP +#if !NET private const string NetfxPolyfillAttributes = """ namespace System.Runtime.CompilerServices { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorTests.cs index e2f08b988441c0..0143e7dd1c4154 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorTests.cs @@ -711,7 +711,7 @@ public class NestedGenericClass [InlineData("public ref partial struct MyGenericRefStruct")] [InlineData("public readonly partial struct MyReadOnlyStruct")] [InlineData("public readonly ref partial struct MyReadOnlyRefStruct")] -#if ROSLYN4_0_OR_GREATER && NETCOREAPP +#if ROSLYN4_0_OR_GREATER && NET [InlineData("public partial record MyRecord(int x)", LanguageVersion.CSharp10)] [InlineData("public partial record struct MyRecordStruct(int x)", LanguageVersion.CSharp10)] #endif @@ -771,7 +771,7 @@ internal partial class JsonContext : JsonSerializerContext CompilationHelper.RunJsonSourceGenerator(compilation); } -#if ROSLYN4_4_OR_GREATER && NETCOREAPP +#if ROSLYN4_4_OR_GREATER && NET [Fact] public void ShadowedMemberInitializers() { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonTestHelper.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonTestHelper.cs index 3083d0bed99a02..adaff17da693c2 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonTestHelper.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonTestHelper.cs @@ -754,7 +754,7 @@ public static TException AssertThrows(ref Utf8JsonReader json, Asser throw ex is null ? ThrowsException.ForNoException(typeof(TException)) : ThrowsException.ForIncorrectExceptionType(typeof(TException), ex); } -#if NETCOREAPP +#if NET // This is needed due to the fact that git might normalize line endings when checking-out files public static string NormalizeLineEndings(this string value) => value.ReplaceLineEndings(); #else diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.Tests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.Tests.cs index 69c53e91e37d37..3eef5a856aee20 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.Tests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.Tests.cs @@ -59,7 +59,7 @@ public static void VerifyPrimitives() Assert.IsType(obj); double dbl = (double)obj; -#if !NETCOREAPP +#if !NET string temp = dbl.ToString(System.Globalization.CultureInfo.InvariantCulture); // The reader uses "G17" format which causes temp to be 4.2000000000000002 in this case. dbl = double.Parse(temp, System.Globalization.CultureInfo.InvariantCulture); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.ReadTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.ReadTests.cs index 437acca92b09b2..b080c282911e22 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.ReadTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.ReadTests.cs @@ -391,7 +391,7 @@ public static void ReadPrimitiveUri() private static int SingleToInt32Bits(float value) { -#if NETCOREAPP +#if NET return BitConverter.SingleToInt32Bits(value); #else return Unsafe.As(ref value); @@ -470,7 +470,7 @@ private static void DeserializeLongJsonString(int stringLength) string json; char fillChar = 'x'; -#if NETCOREAPP +#if NET json = string.Create(stringLength, fillChar, (chars, fillChar) => { chars.Fill(fillChar); @@ -566,7 +566,7 @@ public static void TimeSpan_Read_Failure(string json, bool addQuotes = true) Assert.Throws(() => JsonSerializer.Deserialize(json)); } -#if NETCOREAPP +#if NET [Theory] [InlineData("1970-01-01")] [InlineData("2002-02-13")] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.WriteTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.WriteTests.cs index af83df3f9696d6..a59e7dc9170334 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.WriteTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.WriteTests.cs @@ -148,7 +148,7 @@ public static void TimeSpan_Write_Success(string value, string? expectedValue = Assert.Equal(json, JsonConvert.SerializeObject(ts)); } -#if NETCOREAPP +#if NET [Theory] [InlineData("1970-01-01")] [InlineData("2002-02-13")] diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs index 0a6cb3212cb2fa..486371fd3e0b76 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs @@ -5602,7 +5602,7 @@ private static string DescribeLoop(RegexNode node, RegexMethod rm) } private static string ToHexStringNoDashes(byte[] bytes) => -#if NETCOREAPP +#if NET Convert.ToHexString(bytes); #else BitConverter.ToString(bytes).Replace("-", ""); diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.KnownPattern.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.KnownPattern.Tests.cs index 5748fd8df3c2e5..e7fe42f1cb1658 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.KnownPattern.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.KnownPattern.Tests.cs @@ -1526,7 +1526,7 @@ other is not null && (Options & ~RegexOptions.Compiled) == (other.Options & ~RegexOptions.Compiled); // Compiled doesn't affect semantics, so remove it from equality for our purposes } -#if NETCOREAPP +#if NET [OuterLoop("Takes many seconds")] [Fact] public async Task PatternsDataSet_ConstructRegexForAll_NonBacktracking() diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs index 7131b4fe1d7999..bab7263c2b1c76 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs @@ -434,7 +434,7 @@ public RequestRegistration(int permitCount, ConcurrencyLimiter limiter, Cancella // is going to invoke the callback synchronously, but this does not create // a deadlock because lock are reentrant if (cancellationToken.CanBeCanceled) -#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER +#if NET || NETSTANDARD2_1_OR_GREATER _cancellationTokenRegistration = cancellationToken.UnsafeRegister(Cancel, this); #else _cancellationTokenRegistration = cancellationToken.Register(Cancel, this); diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs index daaed9cf5ce422..7ed567f174a5f1 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs @@ -471,7 +471,7 @@ public RequestRegistration(int permitCount, FixedWindowRateLimiter limiter, Canc // is going to invoke the callback synchronously, but this does not create // a deadlock because lock are reentrant if (cancellationToken.CanBeCanceled) -#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER +#if NET || NETSTANDARD2_1_OR_GREATER _cancellationTokenRegistration = cancellationToken.UnsafeRegister(Cancel, this); #else _cancellationTokenRegistration = cancellationToken.Register(Cancel, this); diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs index 23dbf98e0fcdea..16398459a4d8a8 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs @@ -484,7 +484,7 @@ public RequestRegistration(int permitCount, SlidingWindowRateLimiter limiter, Ca // is going to invoke the callback synchronously, but this does not create // a deadlock because lock are reentrant if (cancellationToken.CanBeCanceled) -#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER +#if NET || NETSTANDARD2_1_OR_GREATER _cancellationTokenRegistration = cancellationToken.UnsafeRegister(Cancel, this); #else _cancellationTokenRegistration = cancellationToken.Register(Cancel, this); diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs index 67a3a55a29ad03..73d78efdc680de 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs @@ -485,7 +485,7 @@ public RequestRegistration(int permitCount, TokenBucketRateLimiter limiter, Canc // is going to invoke the callback synchronously, but this does not create // a deadlock because lock are reentrant if (cancellationToken.CanBeCanceled) -#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER +#if NET || NETSTANDARD2_1_OR_GREATER _cancellationTokenRegistration = cancellationToken.UnsafeRegister(Cancel, this); #else _cancellationTokenRegistration = cancellationToken.Register(Cancel, this); diff --git a/src/tasks/Common/Utils.cs b/src/tasks/Common/Utils.cs index 2f2e8b2ce02d1a..1e724bf3ce2d8d 100644 --- a/src/tasks/Common/Utils.cs +++ b/src/tasks/Common/Utils.cs @@ -326,7 +326,7 @@ public static string ComputeTextIntegrity(string str) return "sha256-" + Convert.ToBase64String(hash); } -#if NETCOREAPP +#if NET public static void DirectoryCopy(string sourceDir, string destDir, Func? predicate=null) { if (!Directory.Exists(destDir)) @@ -350,7 +350,7 @@ public static void DirectoryCopy(string sourceDir, string destDir, Func(decompressedSize); #else decompressedBuffer = new byte[decompressedSize]; diff --git a/src/tests/Common/CoreCLRTestLibrary/Utilities.cs b/src/tests/Common/CoreCLRTestLibrary/Utilities.cs index d48a3e6bd6e79d..a3d6df5a623482 100644 --- a/src/tests/Common/CoreCLRTestLibrary/Utilities.cs +++ b/src/tests/Common/CoreCLRTestLibrary/Utilities.cs @@ -101,7 +101,7 @@ public static bool IsWindowsIoTCore public static bool HasAssemblyFiles => !string.IsNullOrEmpty(typeof(Utilities).Assembly.Location); public static bool IsSingleFile => !HasAssemblyFiles; -#if NETCOREAPP +#if NET public static bool IsReflectionEmitSupported => RuntimeFeature.IsDynamicCodeSupported; public static bool IsNotReflectionEmitSupported => !IsReflectionEmitSupported; #else diff --git a/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcUnixDomainSocketEndPoint.cs b/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcUnixDomainSocketEndPoint.cs index f9413852a510f2..b939b4b22d15af 100644 --- a/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcUnixDomainSocketEndPoint.cs +++ b/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcUnixDomainSocketEndPoint.cs @@ -23,7 +23,7 @@ public IpcUnixDomainSocketEndPoint(string endPoint) private static EndPoint CreateEndPoint(string endPoint) { -#if NETCOREAPP +#if NET return new UnixDomainSocketEndPoint(endPoint); #elif NETSTANDARD2_0 // UnixDomainSocketEndPoint is not part of .NET Standard 2.0 diff --git a/src/tools/illink/external/Mono.Options/Options.cs b/src/tools/illink/external/Mono.Options/Options.cs index 07176081d7b3fc..d8b3d78a455096 100644 --- a/src/tools/illink/external/Mono.Options/Options.cs +++ b/src/tools/illink/external/Mono.Options/Options.cs @@ -749,7 +749,7 @@ public string OptionName { get {return this.option;} } -#if !PCL && !NETCOREAPP +#if !PCL && !NET #pragma warning disable 618 // SecurityPermissionAttribute is obsolete [SecurityPermission (SecurityAction.LinkDemand, SerializationFormatter = true)] #pragma warning restore 618 diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/NullableAttributes.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/NullableAttributes.cs index 7ab77287ed5f31..7cf10912ea38b2 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/NullableAttributes.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/NullableAttributes.cs @@ -5,7 +5,7 @@ // and updated to have the scope of the attributes be internal. namespace System.Diagnostics.CodeAnalysis { -#if !NETCOREAPP +#if !NET /// Specifies that null is allowed as an input even if the corresponding type disallows it. [AttributeUsage (AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] @@ -86,7 +86,7 @@ internal sealed class DoesNotReturnIfAttribute : Attribute #endif -#if !NETCOREAPP || NETCOREAPP3_1 +#if !NET /// Specifies that the method or property will ensure that the listed field and property members have not-null values. [AttributeUsage (AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Helpers/PlatformAssemblies.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Helpers/PlatformAssemblies.cs index c2e77e98f8d445..8638267f26acc3 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Helpers/PlatformAssemblies.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Helpers/PlatformAssemblies.cs @@ -5,7 +5,7 @@ namespace Mono.Linker.Tests.Cases.Expectations.Helpers { public static class PlatformAssemblies { -#if NETCOREAPP +#if NET public const string CoreLib = "System.Private.CoreLib.dll"; #else public const string CoreLib = "mscorlib.dll"; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs index ff3d0937d56137..f0c6c8cd4deefd 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs @@ -10,7 +10,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers { [SetupLinkerTrimMode ("link")] -#if !NETCOREAPP +#if !NET [SetupLinkerKeepDebugMembers ("true")] #endif diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs index 31a098588c05bf..e6da349605d78b 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs @@ -9,7 +9,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers { [SetupLinkerTrimMode ("link")] -#if !NETCOREAPP +#if !NET [SetupLinkerKeepDebugMembers ("true")] #endif diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs index db44758dbb2acf..0f88184ecf3a70 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs @@ -10,7 +10,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers { [SetupLinkerTrimMode ("link")] -#if !NETCOREAPP +#if !NET [SetupLinkerKeepDebugMembers ("true")] #endif [SetupCompileBefore ("library.dll", new[] { "../Dependencies/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.cs" })] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs index af5922ed8fe707..8e65562af475ce 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers { -#if !NETCOREAPP +#if !NET [SetupLinkerKeepDebugMembers ("true")] #endif diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToExtensionMethodOnFieldType.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToExtensionMethodOnFieldType.cs index 71ed65a23c0eb2..6e13271e867904 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToExtensionMethodOnFieldType.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToExtensionMethodOnFieldType.cs @@ -7,7 +7,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers { -#if !NETCOREAPP +#if !NET [SetupLinkerKeepDebugMembers ("true")] #endif public class DebuggerDisplayOnTypeWithCallToExtensionMethodOnFieldType diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToMethodOnFieldType.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToMethodOnFieldType.cs index 156bdb28e78c0f..e2fe84975f7c57 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToMethodOnFieldType.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToMethodOnFieldType.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers { -#if !NETCOREAPP +#if !NET [SetupLinkerKeepDebugMembers ("true")] #endif public class DebuggerDisplayOnTypeWithCallToMethodOnFieldType diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs index e4d0bf419cc3d0..d86d4bf3fbd65a 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs @@ -13,7 +13,7 @@ namespace Mono.Linker.Tests.Cases.Attributes [SetupLinkerArgument ("--skip-unresolved", "true")] [KeptAttributeInAssembly (PlatformAssemblies.CoreLib, typeof (AssemblyDescriptionAttribute))] [KeptAttributeInAssembly (PlatformAssemblies.CoreLib, typeof (AssemblyCompanyAttribute))] -#if !NETCOREAPP +#if !NET [KeptAttributeInAssembly ("System.dll", typeof (AssemblyDescriptionAttribute))] [KeptAttributeInAssembly ("System.dll", typeof (AssemblyCompanyAttribute))] #endif diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs index 64e046ec77106d..44ab4218270abb 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs @@ -10,7 +10,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed [SetupLinkerTrimMode ("link")] [SetupLinkerArgument ("--used-attrs-only", "true")] [RemovedAttributeInAssembly (PlatformAssemblies.CoreLib, typeof (AssemblyDescriptionAttribute))] -#if !NETCOREAPP +#if !NET [RemovedAttributeInAssembly ("System.dll", typeof (AssemblyDescriptionAttribute))] #endif public class CoreLibraryUnusedAssemblyAttributesAreRemoved diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs index bbbbe72db926d2..f3c70ec1a38dcf 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs @@ -10,7 +10,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed [SetupLinkerTrimMode ("link")] [SetupLinkerArgument ("--used-attrs-only", "true")] [KeptAttributeInAssembly (PlatformAssemblies.CoreLib, typeof (AssemblyDescriptionAttribute))] -#if !NETCOREAPP +#if !NET [KeptAttributeInAssembly ("System.dll", typeof (AssemblyDescriptionAttribute))] #endif public class CoreLibraryUsedAssemblyAttributesAreKept diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/TypeWithDynamicInterfaceCastableImplementationAttributeIsKept.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/TypeWithDynamicInterfaceCastableImplementationAttributeIsKept.cs index c6dd27cb57553a..51be76c9f7fab1 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/TypeWithDynamicInterfaceCastableImplementationAttributeIsKept.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/TypeWithDynamicInterfaceCastableImplementationAttributeIsKept.cs @@ -22,7 +22,7 @@ public class TypeWithDynamicInterfaceCastableImplementationAttributeIsKept { public static void Main () { -#if NETCOREAPP +#if NET Foo foo = new Foo (); GetBar (foo).Bar (); IReferenced baz = GetBaz (foo); @@ -32,7 +32,7 @@ public static void Main () #endif } -#if NETCOREAPP +#if NET [Kept] private static IReferencedAndCalled GetBar (object obj) { @@ -53,7 +53,7 @@ static IReferencedAssembly GetReferencedInterface (object obj) #endif } -#if NETCOREAPP +#if NET [Kept] [KeptMember (".ctor()")] [KeptInterface (typeof (IDynamicInterfaceCastable))] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXml.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXml.cs index e80a60f55ec2de..7c9acc549bdf53 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXml.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXml.cs @@ -7,7 +7,7 @@ namespace Mono.Linker.Tests.Cases.DynamicDependencies // and will be found always. // For mono though, we have to specify the assembly (Mono.Linker.Tests.Cases.Expectations) because at the time of processing // that assembly is not yet loaded into the closure in ILLink, so it won't find the attribute type. -#if NETCOREAPP +#if NET [SetupLinkAttributesFile ("DynamicDependencyFromAttributeXml.netcore.Attributes.xml")] #else [SetupLinkAttributesFile ("DynamicDependencyFromAttributeXml.mono.Attributes.xml")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXmlOnNonReferencedAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXmlOnNonReferencedAssembly.cs index f3daf2eeaf03f7..6660e84b1ec175 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXmlOnNonReferencedAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXmlOnNonReferencedAssembly.cs @@ -12,7 +12,7 @@ namespace Mono.Linker.Tests.Cases.DynamicDependencies [KeptAssembly ("field_library.dll")] [KeptMemberInAssembly ("method_library.dll", "Mono.Linker.Tests.Cases.DynamicDependencies.Dependencies.DynamicDependencyFromAttributeXmlOnNonReferencedAssemblyLibrary_Method", "Method()")] [KeptMemberInAssembly ("field_library.dll", "Mono.Linker.Tests.Cases.DynamicDependencies.Dependencies.DynamicDependencyFromAttributeXmlOnNonReferencedAssemblyLibrary_Field", "Method()")] -#if NETCOREAPP +#if NET [SetupLinkAttributesFile ("DynamicDependencyFromAttributeXmlOnNonReferencedAssembly.netcore.Attributes.xml")] #else [SetupLinkAttributesFile ("DynamicDependencyFromAttributeXmlOnNonReferencedAssembly.mono.Attributes.xml")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemoval.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemoval.cs index 9a8e4c4cb28cd8..3a7317444127b4 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemoval.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemoval.cs @@ -17,7 +17,7 @@ namespace Mono.Linker.Tests.Cases.LinkAttributes [SetupCompileBefore ("attribute.dll", new[] { "Dependencies/LinkerAttributeRemovalAttributeToRemove.cs" })] [SetupCompileBefore ("copyattribute.dll", new[] { "Dependencies/LinkerAttributeRemovalAttributeFromCopyAssembly.cs" })] [SetupLinkerAction ("copy", "copyattribute")] -#if !NETCOREAPP +#if !NET [Reference ("System.dll")] [SetupCompileBefore ("copyassembly.dll", new[] { "Dependencies/LinkerAttributeRemovalCopyAssembly.cs" }, references: new[] { "System.dll", "attribute.dll" })] #else diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs index 7ca59831a01a47..dae1731331bb13 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs @@ -16,7 +16,7 @@ public static void Main () GetConstructor_BindingAttr_Binder_Types_Modifiers.TestWithBindingFlags (); GetConstructor_BindingAttr_Binder_Types_Modifiers.TestWithUnknownBindingFlags (BindingFlags.Public); GetConstructor_BindingAttr_Binder_CallConvention_Types_Modifiers.TestWithCallingConvention (); -#if NETCOREAPP +#if NET GetConstructor_BindingAttr_Types.Test (); #endif TestNullType (); @@ -217,7 +217,7 @@ public static void TestWithCallingConvention () } } -#if NETCOREAPP +#if NET [Kept] class GetConstructor_BindingAttr_Types { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs index baf8860765d2dd..55e6c440fbc159 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs @@ -26,7 +26,7 @@ public static void Main () GetMethod_Name_BindingAttr.TestUnknownNameAndWrongBindingFlags ("Unknown"); GetMethod_Name_BindingAttr_Binder_Types_Modifiers.TestNameBindingFlagsAndParameterModifier (); GetMethod_Name_BindingAttr_Binder_CallConvention_Types_Modifiers.TestNameBindingFlagsCallingConventionParameterModifier (); -#if NETCOREAPP +#if NET GetMethod_Name_BindingAttr_Types.TestNameBindingFlagsAndTypes (); GetMethod_Name_GenericParameterCount_Types.TestNameWithIntAndType (); GetMethod_Name_GenericParameterCount_Types_Modifiers.TestNameWithIntAndTypeAndModifiers (); @@ -391,7 +391,7 @@ public static void TestNameBindingFlagsCallingConventionParameterModifier () } } -#if NETCOREAPP +#if NET // GetMethod(string name, BindingFlags bindingAttr, Type[] types) [Kept] class GetMethod_Name_BindingAttr_Types diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwardersRewrite.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwardersRewrite.cs index 240f365439954a..4ed5061aa4988e 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwardersRewrite.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwardersRewrite.cs @@ -21,7 +21,7 @@ unsafe class TypeForwardersRewrite { static void Main () { -#if NETCOREAPP +#if NET Test (null); #endif Test2 (null); @@ -56,7 +56,7 @@ static void Main () [KeptMember ("Invoke()")] delegate C D (); -#if NETCOREAPP +#if NET [Kept] static void Test (delegate* arg) { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs index ea7d62c5fb7daf..68714608fcca98 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs @@ -17,7 +17,7 @@ public static void Main () } [Kept] -#if !NETCOREAPP +#if !NET [ExpectBodyModified] #else [ExpectedInstructionSequence (new[] { @@ -50,7 +50,7 @@ static void Test_1 (object type) } [Kept] -#if !NETCOREAPP +#if !NET [ExpectBodyModified] #else [ExpectedInstructionSequence (new[] { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.cs index 0e0c1ef2a33556..230b7e4e9ba02b 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.UnreachableBlock { -#if NETCOREAPP +#if NET [SetupLinkerSubstitutionFile ("SizeOfInConditions.netcore.xml")] #else [SetupLinkerSubstitutionFile ("SizeOfInConditions.net_4_x.xml")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibrary.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibrary.cs index 9c9ae70e6dc1b2..0da48a31799df5 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibrary.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibrary.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.UnreachableBody { -#if NETCOREAPP +#if NET [SetupLinkerArgument ("-a", "other2.dll")] #else [SetupLinkerArgument ("-r", "other2")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibraryNoInstanceCtor.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibraryNoInstanceCtor.cs index 852c9351af12bc..9cdfe5cb72f1d3 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibraryNoInstanceCtor.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibraryNoInstanceCtor.cs @@ -5,7 +5,7 @@ namespace Mono.Linker.Tests.Cases.UnreachableBody { [SetupLinkerArgument ("--skip-unresolved", "true")] [Define ("OTHER_INCLUDED")] -#if NETCOREAPP +#if NET [SetupLinkerArgument ("-a", "other.dll", "visible")] #else [SetupLinkerArgument ("-r", "other")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileCSharp.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileCSharp.cs index 4bb2c22213bffe..afe1832a0013db 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileCSharp.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileCSharp.cs @@ -8,7 +8,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.Individual { [SetupLinkerTrimMode ("skip")] -#if !NETCOREAPP +#if !NET [Reference ("System.Core.dll")] [SetupCompileBefore ("library.dll", new[] { typeof (TriggerWarnings_Lib) }, new[] { "System.Core.dll" })] #else diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileXml.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileXml.cs index 47d1c929435de7..e11f941e23f888 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileXml.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileXml.cs @@ -5,7 +5,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.Individual { [SetupLinkerTrimMode ("skip")] -#if !NETCOREAPP +#if !NET [SetupCompileBefore ("library.dll", new[] { typeof (TriggerWarnings_Lib) }, new[] { "System.Core.dll" })] #else [SetupCompileBefore ("library.dll", new[] { typeof (TriggerWarnings_Lib) })] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/WarningsAreSorted.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/WarningsAreSorted.cs index c39f6a9028ce53..10cd9d58982d77 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/WarningsAreSorted.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/WarningsAreSorted.cs @@ -12,7 +12,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.Individual { [SkipRemainingErrorsValidation] [SetupLinkerTrimMode ("skip")] -#if !NETCOREAPP +#if !NET [SetupCompileBefore ("library.dll", new[] { typeof (TriggerWarnings_Lib) }, new[] { "System.Core.dll" })] #else [SetupCompileBefore ("library.dll", new[] { typeof (TriggerWarnings_Lib) })] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInAssembly.cs index c9e88bdf6a729c..63b0c109c17987 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInAssembly.cs @@ -7,7 +7,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression { -#if !NETCOREAPP +#if !NET [Mono.Linker.Tests.Cases.Expectations.Metadata.Reference ("System.Core.dll")] #endif [SkipKeptItemsValidation] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCopyAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCopyAssembly.cs index a4e0082b3b5ef6..8985bc61897541 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCopyAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCopyAssembly.cs @@ -7,7 +7,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression { -#if !NETCOREAPP +#if !NET [Reference ("System.Core.dll")] #endif [SetupLinkerAction ("copy", "test")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypes.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypes.cs index 596b7d2cf62f9d..8287c0caddb7ee 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypes.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypes.cs @@ -6,7 +6,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression { -#if !NETCOREAPP +#if !NET [Mono.Linker.Tests.Cases.Expectations.Metadata.Reference ("System.Core.dll")] #endif [SkipKeptItemsValidation] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypesUsingTarget.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypesUsingTarget.cs index a0121281c2494f..d00ac7d68fb484 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypesUsingTarget.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypesUsingTarget.cs @@ -12,7 +12,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression { -#if !NETCOREAPP +#if !NET [Mono.Linker.Tests.Cases.Expectations.Metadata.Reference ("System.Core.dll")] #endif [SkipKeptItemsValidation] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInModule.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInModule.cs index 8273e453bc8f1b..9906cecac482cb 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInModule.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInModule.cs @@ -9,7 +9,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression { -#if !NETCOREAPP +#if !NET [Mono.Linker.Tests.Cases.Expectations.Metadata.Reference ("System.Core.dll")] #endif [SkipKeptItemsValidation] diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCases/TestSuites.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCases/TestSuites.cs index fd25f5cc8cef97..a05e68b17bd468 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCases/TestSuites.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCases/TestSuites.cs @@ -52,7 +52,7 @@ public void CodegenAnnotationTests (TestCase testCase) if (Environment.OSVersion.Platform == PlatformID.Win32NT) Assert.Ignore ("These tests are not valid when trimming .NET Framework"); -#if NETCOREAPP +#if NET Assert.Ignore ("These tests are not valid when trimming .NET Core"); #endif Run (testCase); diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs index 7b5835d2b0fc4f..bff5b87a995088 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs @@ -49,7 +49,7 @@ protected virtual void SetupProcess (Process process, CompilerOptions options) private static string BuildArguments (CompilerOptions options) { var args = new StringBuilder (); -#if NETCOREAPP +#if NET args.Append (options.OutputPath.ExtensionWithDot == ".dll" ? "-dll" : "-exe"); args.Append ($" -out:{options.OutputPath.InQuotes ()}"); #else @@ -62,7 +62,7 @@ private static string BuildArguments (CompilerOptions options) protected virtual NPath LocateIlasm () { -#if NETCOREAPP +#if NET var extension = RuntimeInformation.IsOSPlatform (OSPlatform.Windows) ? ".exe" : ""; var toolsDir = (string)AppContext.GetData("Mono.Linker.Tests.ILToolsDir")!; diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs index c26e833d9e9f3a..fe25e06dd2c7a1 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs @@ -76,7 +76,7 @@ public virtual IEnumerable GetDefines () yield return "WIN32"; if (Characteristics.HasFlag (TestRunCharacteristics.TargetingNetCore)) - yield return "NETCOREAPP"; + yield return "NET"; if (Characteristics.HasFlag (TestRunCharacteristics.SupportsDefaultInterfaceMethods)) yield return "SUPPORTS_DEFAULT_INTERFACE_METHODS"; diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs index ec427ebdbc4858..89c202e472c05a 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs @@ -9,7 +9,7 @@ using System.Text; using Mono.Linker.Tests.Extensions; using NUnit.Framework; -#if NETCOREAPP +#if NET using System.Runtime.InteropServices; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Emit; @@ -190,7 +190,7 @@ protected static NPath MakeSupportingAssemblyReferencePathAbsolute (NPath output if (Path.IsPathRooted (referenceFileName)) return referenceFileName.ToNPath (); -#if NETCOREAPP +#if NET if (referenceFileName.StartsWith ("System.", StringComparison.Ordinal) || referenceFileName.StartsWith ("Mono.", StringComparison.Ordinal) || referenceFileName.StartsWith ("Microsoft.", StringComparison.Ordinal) || @@ -224,14 +224,14 @@ protected NPath CompileAssembly (CompilerOptions options) protected virtual NPath CompileCSharpAssemblyWithDefaultCompiler (CompilerOptions options) { -#if NETCOREAPP +#if NET return CompileCSharpAssemblyWithRoslyn (options); #else return CompileCSharpAssemblyWithCsc (options); #endif } -#if NETCOREAPP +#if NET protected virtual NPath CompileCSharpAssemblyWithRoslyn (CompilerOptions options) { var languageVersion = LanguageVersion.Preview; @@ -328,7 +328,7 @@ protected virtual NPath CompileCSharpAssemblyWithRoslyn (CompilerOptions options protected virtual NPath CompileCSharpAssemblyWithCsc (CompilerOptions options) { -#if NETCOREAPP +#if NET return CompileCSharpAssemblyWithRoslyn (options); #else return CompileCSharpAssemblyWithExternalCompiler (LocateCscExecutable (), options, "/shared "); diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs index cdb59e6571130d..8789c404839b48 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs @@ -66,7 +66,7 @@ public virtual void RootAssemblyEntryPoint (string fileName) public virtual void RootAssemblyVisible (string fileName) { -#if NETCOREAPP +#if NET Append ("-a"); Append (fileName); Append ("visible"); @@ -213,7 +213,7 @@ public virtual void ProcessOptions (TestCaseLinkerOptions options) IgnoreLinkAttributes (options.IgnoreLinkAttributes); -#if !NETCOREAPP +#if !NET if (!string.IsNullOrEmpty (options.Il8n)) AddIl8n (options.Il8n); #endif From d77b37ba4f02bc19217ea438f72c9799a51eaaed Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Tue, 30 Apr 2024 23:35:16 -0700 Subject: [PATCH 199/248] Arm64/Sve: Add SignExtendWidening* and ZeroExtendWidening* math APIs (#101743) * Add SignExtendWidening* and ZeroExtendWidening* APIs * Map API to instruction * Add missing SignExtendWidening* APIs * Add test cases * fix bugs * Forgot to push the template * jit format * Fix the LargeVectorSize --- src/coreclr/jit/emitarm64sve.cpp | 16 ++-- src/coreclr/jit/hwintrinsiclistarm64sve.h | 4 + .../Arm/Sve.PlatformNotSupported.cs | 85 +++++++++++++++++- .../src/System/Runtime/Intrinsics/Arm/Sve.cs | 89 ++++++++++++++++++- .../ref/System.Runtime.Intrinsics.cs | 14 +++ .../GenerateHWIntrinsicTests_Arm.cs | 50 +++++++---- 6 files changed, 229 insertions(+), 29 deletions(-) diff --git a/src/coreclr/jit/emitarm64sve.cpp b/src/coreclr/jit/emitarm64sve.cpp index 19a1e89482a0e2..f7aa628e3f835f 100644 --- a/src/coreclr/jit/emitarm64sve.cpp +++ b/src/coreclr/jit/emitarm64sve.cpp @@ -2185,7 +2185,7 @@ void emitter::emitInsSve_R_R(instruction ins, case INS_sve_uunpkhi: case INS_sve_uunpklo: assert(insScalableOptsNone(sopt)); - assert(insOptsScalableAtLeastHalf(opt)); + assert(insOptsScalableWide(opt)); assert(isVectorRegister(reg1)); assert(isVectorRegister(reg2)); assert(isScalableVectorSize(size)); @@ -11805,7 +11805,6 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id) case IF_SVE_BJ_2A: // ........xx...... ......nnnnnddddd -- SVE floating-point exponential accelerator case IF_SVE_CG_2A: // ........xx...... ......nnnnnddddd -- SVE reverse vector elements - case IF_SVE_CH_2A: // ........xx...... ......nnnnnddddd -- SVE unpack vector elements case IF_SVE_HF_2A: // ........xx...... ......nnnnnddddd -- SVE floating-point reciprocal estimate (unpredicated) code = emitInsCodeSve(ins, fmt); code |= insEncodeReg_V<4, 0>(id->idReg1()); // ddddd @@ -11814,6 +11813,13 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id) dst += emitOutput_Instr(dst, code); break; + case IF_SVE_CH_2A: // ........xx...... ......nnnnnddddd -- SVE unpack vector elements + code = emitInsCodeSve(ins, fmt); + code |= insEncodeReg_V<4, 0>(id->idReg1()); // ddddd + code |= insEncodeReg_V<9, 5>(id->idReg2()); // nnnnn + code |= insEncodeSveElemsize(optGetSveElemsize((insOpts)(id->idInsOpt() + 1))); // xx + dst += emitOutput_Instr(dst, code); + break; case IF_SVE_BF_2A: // ........xx.xxiii ......nnnnnddddd -- SVE bitwise shift by immediate (unpredicated) case IF_SVE_FT_2A: // ........xx.xxiii ......nnnnnddddd -- SVE2 bitwise shift and insert case IF_SVE_FU_2A: // ........xx.xxiii ......nnnnnddddd -- SVE2 bitwise shift right and accumulate @@ -14389,7 +14395,7 @@ void emitter::emitInsSveSanityCheck(instrDesc* id) case IF_SVE_BJ_2A: // ........xx...... ......nnnnnddddd -- SVE floating-point exponential accelerator case IF_SVE_CH_2A: // ........xx...... ......nnnnnddddd -- SVE unpack vector elements case IF_SVE_HF_2A: // ........xx...... ......nnnnnddddd -- SVE floating-point reciprocal estimate (unpredicated) - assert(insOptsScalableAtLeastHalf(id->idInsOpt())); + assert(insOptsScalableWide(id->idInsOpt())); assert(isVectorRegister(id->idReg1())); assert(isVectorRegister(id->idReg2())); break; @@ -16231,8 +16237,8 @@ void emitter::emitDispInsSveHelp(instrDesc* id) case IF_SVE_HH_2A: // ................ ......nnnnnddddd -- SVE2 FP8 upconverts // ., . case IF_SVE_CH_2A: // ........xx...... ......nnnnnddddd -- SVE unpack vector elements - emitDispSveReg(id->idReg1(), id->idInsOpt(), true); - emitDispSveReg(id->idReg2(), (insOpts)((unsigned)id->idInsOpt() - 1), false); + emitDispSveReg(id->idReg1(), (insOpts)(id->idInsOpt() + 1), true); + emitDispSveReg(id->idReg2(), id->idInsOpt(), false); break; // ., . diff --git a/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/coreclr/jit/hwintrinsiclistarm64sve.h index 1d023e47be9cc5..6a8346c216282c 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64sve.h +++ b/src/coreclr/jit/hwintrinsiclistarm64sve.h @@ -73,12 +73,16 @@ HARDWARE_INTRINSIC(Sve, Multiply, HARDWARE_INTRINSIC(Sve, SignExtend16, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sxth, INS_invalid, INS_sve_sxth, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, SignExtend32, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sxtw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, SignExtend8, -1, -1, false, {INS_invalid, INS_invalid, INS_sve_sxtb, INS_invalid, INS_sve_sxtb, INS_invalid, INS_sve_sxtb, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, SignExtendWideningLower, -1, 1, true, {INS_sve_sunpklo, INS_invalid, INS_sve_sunpklo, INS_invalid, INS_sve_sunpklo, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Sve, SignExtendWideningUpper, -1, 1, true, {INS_sve_sunpkhi, INS_invalid, INS_sve_sunpkhi, INS_invalid, INS_sve_sunpkhi, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Sve, Subtract, -1, 2, true, {INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_fsub, INS_sve_fsub}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve, UnzipEven, -1, 2, true, {INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Sve, UnzipOdd, -1, 2, true, {INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Sve, ZeroExtend16, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_uxth, INS_invalid, INS_sve_uxth, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, ZeroExtend32, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_uxtw, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, ZeroExtend8, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_uxtb, INS_invalid, INS_sve_uxtb, INS_invalid, INS_sve_uxtb, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, ZeroExtendWideningLower, -1, 1, true, {INS_invalid, INS_sve_uunpklo, INS_invalid, INS_sve_uunpklo, INS_invalid, INS_sve_uunpklo, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Sve, ZeroExtendWideningUpper, -1, 1, true, {INS_invalid, INS_sve_uunpkhi, INS_invalid, INS_sve_uunpkhi, INS_invalid, INS_sve_uunpkhi, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Sve, ZipHigh, -1, 2, true, {INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Sve, ZipLow, -1, 2, true, {INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs index 4715c3777543ad..5cc1d3df2f7cb7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs @@ -1276,6 +1276,48 @@ internal Arm64() { } /// public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// SignExtendWideningLower : Unpack and extend low half + + /// + /// svint16_t svunpklo[_s16](svint8_t op) + /// SUNPKLO Zresult.H, Zop.B + /// + public static unsafe Vector SignExtendWideningLower(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svunpklo[_s32](svint16_t op) + /// SUNPKLO Zresult.S, Zop.H + /// + public static unsafe Vector SignExtendWideningLower(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svunpklo[_s64](svint32_t op) + /// SUNPKLO Zresult.D, Zop.S + /// + public static unsafe Vector SignExtendWideningLower(Vector value) { throw new PlatformNotSupportedException(); } + + + /// SignExtendWideningUpper : Unpack and extend high half + + /// + /// svint16_t svunpkhi[_s16](svint8_t op) + /// SUNPKHI Zresult.H, Zop.B + /// + public static unsafe Vector SignExtendWideningUpper(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svunpkhi[_s32](svint16_t op) + /// SUNPKHI Zresult.S, Zop.H + /// + public static unsafe Vector SignExtendWideningUpper(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svunpkhi[_s64](svint32_t op) + /// SUNPKHI Zresult.D, Zop.S + /// + public static unsafe Vector SignExtendWideningUpper(Vector value) { throw new PlatformNotSupportedException(); } + + /// UnzipEven : Concatenate even elements from two inputs /// @@ -1469,13 +1511,52 @@ internal Arm64() { } /// public static unsafe Vector ZeroExtend8(Vector value) { throw new PlatformNotSupportedException(); } + /// ZeroExtendWideningLower : Unpack and extend low half + + /// + /// svuint16_t svunpklo[_u16](svuint8_t op) + /// UUNPKLO Zresult.H, Zop.B + /// + public static unsafe Vector ZeroExtendWideningLower(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svunpklo[_u32](svuint16_t op) + /// UUNPKLO Zresult.S, Zop.H + /// + public static unsafe Vector ZeroExtendWideningLower(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svunpklo[_u64](svuint32_t op) + /// UUNPKLO Zresult.D, Zop.S + /// + public static unsafe Vector ZeroExtendWideningLower(Vector value) { throw new PlatformNotSupportedException(); } + + + /// ZeroExtendWideningUpper : Unpack and extend high half + + /// + /// svuint16_t svunpkhi[_u16](svuint8_t op) + /// UUNPKHI Zresult.H, Zop.B + /// + public static unsafe Vector ZeroExtendWideningUpper(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svunpkhi[_u32](svuint16_t op) + /// UUNPKHI Zresult.S, Zop.H + /// + public static unsafe Vector ZeroExtendWideningUpper(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svunpkhi[_u64](svuint32_t op) + /// UUNPKHI Zresult.D, Zop.S + /// + public static unsafe Vector ZeroExtendWideningUpper(Vector value) { throw new PlatformNotSupportedException(); } + /// ZipHigh : Interleave elements from high halves of two inputs /// /// svuint8_t svzip2[_u8](svuint8_t op1, svuint8_t op2) /// ZIP2 Zresult.B, Zop1.B, Zop2.B - /// svbool_t svzip2_b8(svbool_t op1, svbool_t op2) - /// ZIP2 Presult.B, Pop1.B, Pop2.B /// public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs index 3e88376b9614ad..d195dd03dfb484 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs @@ -1207,6 +1207,48 @@ internal Arm64() { } /// public static unsafe Vector SignExtend8(Vector value) => SignExtend8(value); + + /// SignExtendWideningLower : Unpack and extend low half + + /// + /// svint16_t svunpklo[_s16](svint8_t op) + /// SUNPKLO Zresult.H, Zop.B + /// + public static unsafe Vector SignExtendWideningLower(Vector value) => SignExtendWideningLower(value); + + /// + /// svint32_t svunpklo[_s32](svint16_t op) + /// SUNPKLO Zresult.S, Zop.H + /// + public static unsafe Vector SignExtendWideningLower(Vector value) => SignExtendWideningLower(value); + + /// + /// svint64_t svunpklo[_s64](svint32_t op) + /// SUNPKLO Zresult.D, Zop.S + /// + public static unsafe Vector SignExtendWideningLower(Vector value) => SignExtendWideningLower(value); + + + /// SignExtendWideningUpper : Unpack and extend high half + + /// + /// svint16_t svunpkhi[_s16](svint8_t op) + /// SUNPKHI Zresult.H, Zop.B + /// + public static unsafe Vector SignExtendWideningUpper(Vector value) => SignExtendWideningUpper(value); + + /// + /// svint32_t svunpkhi[_s32](svint16_t op) + /// SUNPKHI Zresult.S, Zop.H + /// + public static unsafe Vector SignExtendWideningUpper(Vector value) => SignExtendWideningUpper(value); + + /// + /// svint64_t svunpkhi[_s64](svint32_t op) + /// SUNPKHI Zresult.D, Zop.S + /// + public static unsafe Vector SignExtendWideningUpper(Vector value) => SignExtendWideningUpper(value); + /// Subtract : Subtract /// @@ -1552,16 +1594,55 @@ internal Arm64() { } /// public static unsafe Vector ZeroExtend8(Vector value) => ZeroExtend8(value); + /// ZeroExtendWideningLower : Unpack and extend low half + + /// + /// svuint16_t svunpklo[_u16](svuint8_t op) + /// UUNPKLO Zresult.H, Zop.B + /// + public static unsafe Vector ZeroExtendWideningLower(Vector value) => ZeroExtendWideningLower(value); + + /// + /// svuint32_t svunpklo[_u32](svuint16_t op) + /// UUNPKLO Zresult.S, Zop.H + /// + public static unsafe Vector ZeroExtendWideningLower(Vector value) => ZeroExtendWideningLower(value); + + /// + /// svuint64_t svunpklo[_u64](svuint32_t op) + /// UUNPKLO Zresult.D, Zop.S + /// + public static unsafe Vector ZeroExtendWideningLower(Vector value) => ZeroExtendWideningLower(value); + + + /// ZeroExtendWideningUpper : Unpack and extend high half + + /// + /// svuint16_t svunpkhi[_u16](svuint8_t op) + /// UUNPKHI Zresult.H, Zop.B + /// + public static unsafe Vector ZeroExtendWideningUpper(Vector value) => ZeroExtendWideningUpper(value); + + /// + /// svuint32_t svunpkhi[_u32](svuint16_t op) + /// UUNPKHI Zresult.S, Zop.H + /// svbool_t svunpkhi[_b](svbool_t op) + /// PUNPKHI Presult.H, Pop.B + /// + public static unsafe Vector ZeroExtendWideningUpper(Vector value) => ZeroExtendWideningUpper(value); + + /// + /// svuint64_t svunpkhi[_u64](svuint32_t op) + /// UUNPKHI Zresult.D, Zop.S + /// + public static unsafe Vector ZeroExtendWideningUpper(Vector value) => ZeroExtendWideningUpper(value); + /// ZipHigh : Interleave elements from high halves of two inputs /// /// svuint8_t svzip2[_u8](svuint8_t op1, svuint8_t op2) /// ZIP2 Zresult.B, Zop1.B, Zop2.B - /// svbool_t svzip2_b8(svbool_t op1, svbool_t op2) - /// ZIP2 Presult.B, Pop1.B, Pop2.B /// - - public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); /// diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 18365d784dfcee..1262604f92895b 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -4297,6 +4297,13 @@ internal Arm64() { } public static System.Numerics.Vector SignExtend8(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector SignExtend8(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtendWideningLower(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtendWideningLower(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtendWideningLower(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtendWideningUpper(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtendWideningUpper(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtendWideningUpper(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -4348,6 +4355,13 @@ internal Arm64() { } public static System.Numerics.Vector ZeroExtend8(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector ZeroExtend8(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtendWideningLower(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtendWideningLower(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtendWideningLower(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtendWideningUpper(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtendWideningUpper(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtendWideningUpper(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } diff --git a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs index 648a05ed3c0c51..9b769782295623 100644 --- a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs +++ b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs @@ -2892,12 +2892,12 @@ (string templateFileName, Dictionary templateData)[] SveInputs = new [] { - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.Abs(leftOp[i])"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.Abs(leftOp[i])"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)-TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "(sbyte)Helpers.Abs(leftOp[i])"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)-TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "(short)Helpers.Abs(leftOp[i])"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "(int)Helpers.Abs(leftOp[i])"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "(long)Helpers.Abs(firstOp[i]) != (long)result[i]", ["GetIterResult"] = "(long)Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)-TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "(sbyte)Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)-TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "(short)Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "(int)Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "(long)Helpers.Abs(firstOp[i]) != (long)result[i]", ["GetIterResult"] = "(long)Helpers.Abs(leftOp[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), @@ -3020,12 +3020,19 @@ ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend16_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, false)"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend16_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, false)"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend32_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 32, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 32, false)"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend8_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, false)"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend8_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, false)"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend8_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend16_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend16_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend32_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 32, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 32, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend8_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend8_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend8_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, false)"}), + + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_SignExtendWideningLower_short_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtendWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.SignExtendWidening(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "Helpers.SignExtendWidening(firstOp[i]) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_SignExtendWideningLower_int_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtendWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.SignExtendWidening(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "Helpers.SignExtendWidening(firstOp[i]) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_SignExtendWideningLower_long_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtendWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.SignExtendWidening(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "Helpers.SignExtendWidening(firstOp[i]) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_SignExtendWideningUpper_short_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtendWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.SignExtendWideningUpper(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "Helpers.SignExtendWideningUpper(firstOp, i) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_SignExtendWideningUpper_int_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtendWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.SignExtendWideningUpper(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "Helpers.SignExtendWideningUpper(firstOp, i) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_SignExtendWideningUpper_long_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtendWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.SignExtendWideningUpper(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "Helpers.SignExtendWideningUpper(firstOp, i) != result[i]"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), @@ -3059,12 +3066,19 @@ ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend16_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, true)"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend16_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, true)"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend32_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 32, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 32, true)"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), - ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend16_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend16_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend32_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 32, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 32, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), + + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_ZeroExtendWideningLower_ushort_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtendWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.ZeroExtendWidening(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "Helpers.ZeroExtendWidening(firstOp[i]) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_ZeroExtendWideningLower_uint_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtendWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.ZeroExtendWidening(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "Helpers.ZeroExtendWidening(firstOp[i]) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_ZeroExtendWideningLower_ulong_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtendWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.ZeroExtendWidening(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "Helpers.ZeroExtendWidening(firstOp[i]) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_ZeroExtendWideningUpper_ushort_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtendWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.ZeroExtendWideningUpper(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_ZeroExtendWideningUpper_uint_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtendWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.ZeroExtendWideningUpper(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_ZeroExtendWideningUpper_ulong_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtendWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.ZeroExtendWideningUpper(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), From 64917a932cfb40f02da3192b7d5e9f0117935346 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Wed, 1 May 2024 10:59:47 +0200 Subject: [PATCH 200/248] [wasm] Update patch after template change (#101712) --- src/mono/sample/wasm/browser-frame/browser-frame.diff | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mono/sample/wasm/browser-frame/browser-frame.diff b/src/mono/sample/wasm/browser-frame/browser-frame.diff index 72795bed439422..a709abb5d609e2 100644 --- a/src/mono/sample/wasm/browser-frame/browser-frame.diff +++ b/src/mono/sample/wasm/browser-frame/browser-frame.diff @@ -1,15 +1,15 @@ diff -ru browser-frame/Program.cs browser-frame/Program.cs --- a/browser-frame/Program.cs 2024-03-07 09:00:37 +++ b/browser-frame/Program.cs 2024-03-05 15:38:42 -@@ -1,6 +1,8 @@ - using System; +@@ -3,6 +3,8 @@ using System.Runtime.InteropServices.JavaScript; + using System.Threading.Tasks; +BrowserBench.FrameApp.ReachedManaged(); + Console.WriteLine("Hello, Browser!"); - public partial class MyClass + if (args.Length == 1 && args[0] == "start") diff -ru browser-frame/wwwroot/index.html browser-frame/wwwroot/index.html --- a/browser-frame/wwwroot/index.html 2024-03-07 09:00:37 +++ b/browser-frame/wwwroot/index.html 2024-03-05 15:38:42 From 350aa16807c6d346059657287e01b14474f10d74 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 11:00:08 +0200 Subject: [PATCH 201/248] [main] Update dependencies from dotnet/arcade (#101715) * Update dependencies from https://github.com/dotnet/arcade build 20240429.1 Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XliffTasks , Microsoft.DotNet.XUnitAssert , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 9.0.0-beta.24226.3 -> To Version 9.0.0-beta.24229.1 * Update dependencies from https://github.com/dotnet/arcade build 20240429.1 Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XliffTasks , Microsoft.DotNet.XUnitAssert , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 9.0.0-beta.24226.3 -> To Version 9.0.0-beta.24229.1 --------- Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 84 +++++++++---------- eng/Versions.props | 32 +++---- eng/common/native/init-distro-rid.sh | 18 +++- .../steps/publish-pipeline-artifacts.yml | 24 +++--- global.json | 6 +- 5 files changed, 90 insertions(+), 74 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 4afd8464469d7d..9aaf65a3ca51a8 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -92,87 +92,87 @@ - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 https://github.com/dotnet/runtime-assets @@ -332,9 +332,9 @@ https://github.com/dotnet/xharness ec633d9ddbdb86dd3d772989889690821f790484 - + https://github.com/dotnet/arcade - 97e2f41e909dcabb1103fe98ba4540a246662187 + be933308b9024d798a9a22c0b8f3c8e3616ffbd8 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index 241d20a5801b05..854ddc25ee07e2 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -83,22 +83,22 @@ 9.0.100-preview.5.24227.1 - 9.0.0-beta.24226.3 - 9.0.0-beta.24226.3 - 9.0.0-beta.24226.3 - 9.0.0-beta.24226.3 - 2.6.7-beta.24226.3 - 9.0.0-beta.24226.3 - 2.6.7-beta.24226.3 - 9.0.0-beta.24226.3 - 9.0.0-beta.24226.3 - 9.0.0-beta.24226.3 - 9.0.0-beta.24226.3 - 9.0.0-beta.24226.3 - 9.0.0-beta.24226.3 - 9.0.0-beta.24226.3 - 9.0.0-beta.24226.3 - 9.0.0-beta.24226.3 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 2.6.7-beta.24229.1 + 9.0.0-beta.24229.1 + 2.6.7-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 1.4.0 diff --git a/eng/common/native/init-distro-rid.sh b/eng/common/native/init-distro-rid.sh index 83ea7aab0e081c..228be0b1598629 100644 --- a/eng/common/native/init-distro-rid.sh +++ b/eng/common/native/init-distro-rid.sh @@ -20,6 +20,10 @@ getNonPortableDistroRid() # shellcheck disable=SC1091 if [ -e "${rootfsDir}/etc/os-release" ]; then . "${rootfsDir}/etc/os-release" + if [ "${ID}" = "rhel" ] || [ "${ID}" = "rocky" ] || [ "${ID}" = "alpine" ] || [ "${ID}" = "ol" ]; then + VERSION_ID="${VERSION_ID%.*}" # Remove the last version digit for these distros + fi + if echo "${VERSION_ID:-}" | grep -qE '^([[:digit:]]|\.)+$'; then nonPortableRid="${ID}.${VERSION_ID}-${targetArch}" else @@ -44,7 +48,19 @@ getNonPortableDistroRid() nonPortableRid="android.$__android_sdk_version-${targetArch}" elif [ "$targetOs" = "illumos" ]; then __uname_version=$(uname -v) - nonPortableRid="illumos-${targetArch}" + case "$__uname_version" in + omnios-*) + __omnios_major_version=$(echo "$__uname_version" | cut -c9-10) + nonPortableRid="omnios.$__omnios_major_version-${targetArch}" + ;; + joyent_*) + __smartos_major_version=$(echo "$__uname_version" | cut -c9-10) + nonPortableRid="smartos.$__smartos_major_version-${targetArch}" + ;; + *) + nonPortableRid="illumos-${targetArch}" + ;; + esac elif [ "$targetOs" = "solaris" ]; then __uname_version=$(uname -v) __solaris_major_version=$(echo "$__uname_version" | cut -d'.' -f1) diff --git a/eng/common/templates/steps/publish-pipeline-artifacts.yml b/eng/common/templates/steps/publish-pipeline-artifacts.yml index 88c56354128c06..815c86038e3ab3 100644 --- a/eng/common/templates/steps/publish-pipeline-artifacts.yml +++ b/eng/common/templates/steps/publish-pipeline-artifacts.yml @@ -19,16 +19,16 @@ steps: ${{ if parameters.args.continueOnError }}: continueOnError: ${{ parameters.args.continueOnError }} inputs: - TargetPath: ${{ parameters.args.TargetPath }} - ${{ if parameters.args.ArtifactName }}: - ArtifactName: ${{ parameters.args.ArtifactName }} - ${{ if parameters.args.PublishLocation }}: - PublishLocation: ${{ parameters.args.PublishLocation }} - ${{ if parameters.args.FileSharePath }}: - FileSharePath: ${{ parameters.args.FileSharePath }} + targetPath: ${{ parameters.args.targetPath }} + ${{ if parameters.args.artifactName }}: + artifactName: ${{ parameters.args.artifactName }} + ${{ if parameters.args.publishLocation }}: + publishLocation: ${{ parameters.args.publishLocation }} + ${{ if parameters.args.fileSharePath }}: + fileSharePath: ${{ parameters.args.fileSharePath }} ${{ if parameters.args.Parallel }}: - Parallel: ${{ parameters.args.Parallel }} - ${{ if parameters.args.ParallelCount }}: - ParallelCount: ${{ parameters.args.ParallelCount }} - ${{ if parameters.args.Properties }}: - Properties: ${{ properties.args.Properties }} \ No newline at end of file + parallel: ${{ parameters.args.Parallel }} + ${{ if parameters.args.parallelCount }}: + parallelCount: ${{ parameters.args.parallelCount }} + ${{ if parameters.args.properties }}: + properties: ${{ properties.args.properties }} \ No newline at end of file diff --git a/global.json b/global.json index 8cafaf799ea2c5..55e7657f79c437 100644 --- a/global.json +++ b/global.json @@ -8,9 +8,9 @@ "dotnet": "9.0.100-preview.3.24204.13" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24226.3", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.24226.3", - "Microsoft.DotNet.SharedFramework.Sdk": "9.0.0-beta.24226.3", + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24229.1", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.24229.1", + "Microsoft.DotNet.SharedFramework.Sdk": "9.0.0-beta.24229.1", "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.Build.Traversal": "3.4.0", "Microsoft.NET.Sdk.IL": "9.0.0-preview.4.24229.1" From a177fbd500f85fa779319800e7f41408257522c3 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Wed, 1 May 2024 14:49:45 +0200 Subject: [PATCH 202/248] Clean up in LowerStoreIndirCoalescing (#101665) --- src/coreclr/jit/lower.cpp | 143 ++++++++++++++++++++------------------ src/coreclr/jit/lower.h | 31 ++++++++- 2 files changed, 106 insertions(+), 68 deletions(-) diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index cb8eb5d6a97a0d..a3f1ca141af0dc 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -8347,54 +8347,57 @@ void Lowering::LowerBlockStoreAsHelperCall(GenTreeBlk* blkNode) #endif } -struct StoreCoalescingData -{ - var_types targetType; - GenTree* baseAddr; - GenTree* index; - GenTree* value; - uint32_t scale; - int offset; -}; - //------------------------------------------------------------------------ -// GetStoreCoalescingData: given a STOREIND node, get the data needed to perform -// store coalescing including pointer to the previous node. +// GetLoadStoreCoalescingData: given a STOREIND/IND node, get the data needed to perform +// store/load coalescing including pointer to the previous node. // // Arguments: // comp - the compiler instance -// ind - the STOREIND node -// data - [OUT] the data needed for store coalescing +// ind - the STOREIND/IND node +// data - [OUT] the data needed for store/load coalescing // // Return Value: // true if the data was successfully retrieved, false otherwise. -// Basically, false means that we definitely can't do store coalescing. // -static bool GetStoreCoalescingData(Compiler* comp, GenTreeStoreInd* ind, StoreCoalescingData* data) +bool Lowering::GetLoadStoreCoalescingData(GenTreeIndir* ind, LoadStoreCoalescingData* data) const { - // Don't merge volatile stores. + // Don't merge volatile load/stores. if (ind->IsVolatile()) { return false; } - // Data has to be INT_CNS, can be also VEC_CNS in future. - if (!ind->Data()->IsCnsIntOrI() && !ind->Data()->IsVectorConst()) - { - return false; - } + const bool isStore = ind->OperIs(GT_STOREIND, GT_STORE_BLK); + const bool isLoad = ind->OperIs(GT_IND); auto isNodeInvariant = [](Compiler* comp, GenTree* node, bool allowNull) { if (node == nullptr) { return allowNull; } + if (node->OperIsConst()) + { + return true; + } // We can allow bigger trees here, but it's not clear if it's worth it. return node->OperIs(GT_LCL_VAR) && !comp->lvaVarAddrExposed(node->AsLclVar()->GetLclNum()); }; + if (isStore) + { + // For stores, Data() is expected to be an invariant node + if (!isNodeInvariant(comp, ind->Data(), false)) + { + return false; + } + } + else if (!isLoad) + { + return false; + } + data->targetType = ind->TypeGet(); - data->value = ind->Data(); + data->value = isStore ? ind->Data() : nullptr; if (ind->Addr()->OperIs(GT_LEA)) { GenTree* base = ind->Addr()->AsAddrMode()->Base(); @@ -8430,12 +8433,24 @@ static bool GetStoreCoalescingData(Compiler* comp, GenTreeStoreInd* ind, StoreCo // Address is not LEA or local. return false; } + + bool isClosedRange = false; + // Make sure there are no other unexpected nodes in-between. + LIR::ReadOnlyRange range = BlockRange().GetTreeRange(ind, &isClosedRange); + if (!isClosedRange) + { + return false; + } + + data->rangeStart = range.FirstNode(); + data->rangeEnd = range.LastNode(); + return true; } //------------------------------------------------------------------------ -// LowerStoreIndirCoalescing: If the given STOREIND node is followed by a similar -// STOREIND node, try to merge them into a single store of a twice wider type. Example: +// LowerStoreIndirCoalescing: If the given IND/STOREIND node is followed by a similar +// IND/STOREIND node, try to merge them into a single store of a twice wider type. Example: // // * STOREIND int // +--* LCL_VAR byref V00 @@ -8459,7 +8474,7 @@ static bool GetStoreCoalescingData(Compiler* comp, GenTreeStoreInd* ind, StoreCo // Arguments: // ind - the current STOREIND node // -void Lowering::LowerStoreIndirCoalescing(GenTreeStoreInd* ind) +void Lowering::LowerStoreIndirCoalescing(GenTreeIndir* ind) { // LA, RISC-V and ARM32 more likely to recieve a terrible performance hit from // unaligned accesses making this optimization questionable. @@ -8469,12 +8484,9 @@ void Lowering::LowerStoreIndirCoalescing(GenTreeStoreInd* ind) return; } - // TODO-ARM64-CQ: enable TYP_REF if we find a case where it's beneficial. - // The algorithm does support TYP_REF (with null value), but it seems to be not worth - // it on ARM64 where it's pretty efficient to do "stp xzr, xzr, [addr]" to clear two - // items at once. Although, it may be profitable to do "stp q0, q0, [addr]". - if (!varTypeIsIntegral(ind) && !varTypeIsSIMD(ind)) + if (!ind->OperIs(GT_STOREIND, GT_STORE_BLK)) { + // Load coalescing is not yet supported return; } @@ -8492,24 +8504,16 @@ void Lowering::LowerStoreIndirCoalescing(GenTreeStoreInd* ind) // to get a single store of 8 bytes. do { - StoreCoalescingData currData; - StoreCoalescingData prevData; + LoadStoreCoalescingData currData; + LoadStoreCoalescingData prevData; // Get coalescing data for the current STOREIND - if (!GetStoreCoalescingData(comp, ind, &currData)) + if (!GetLoadStoreCoalescingData(ind, &currData)) { return; } - bool isClosedRange = false; - // Now we need to find the very first LIR node representing the current STOREIND - // and make sure that there are no other unexpected nodes in-between. - LIR::ReadOnlyRange currIndRange = BlockRange().GetTreeRange(ind, &isClosedRange); - if (!isClosedRange) - { - return; - } - GenTree* prevTree = currIndRange.FirstNode()->gtPrev; + GenTree* prevTree = currData.rangeStart->gtPrev; // Now we need to find the previous STOREIND, // we can ignore any NOPs or IL_OFFSETs in-between while ((prevTree != nullptr) && prevTree->OperIs(GT_NOP, GT_IL_OFFSET)) @@ -8517,47 +8521,51 @@ void Lowering::LowerStoreIndirCoalescing(GenTreeStoreInd* ind) prevTree = prevTree->gtPrev; } - // It's not a STOREIND - bail out. - if ((prevTree == nullptr) || !prevTree->OperIs(GT_STOREIND)) + // It's not a store - bail out. + if ((prevTree == nullptr) || !prevTree->OperIs(GT_STOREIND, GT_STORE_BLK)) { return; } // Get coalescing data for the previous STOREIND - GenTreeStoreInd* prevInd = prevTree->AsStoreInd(); - if (!GetStoreCoalescingData(comp, prevInd->AsStoreInd(), &prevData)) + GenTreeIndir* prevInd = prevTree->AsIndir(); + if (!GetLoadStoreCoalescingData(prevInd, &prevData)) { return; } - // Same for the previous STOREIND, make sure there are no unexpected nodes around. - LIR::ReadOnlyRange prevIndRange = BlockRange().GetTreeRange(prevInd, &isClosedRange); - if (!isClosedRange) + if (!currData.IsAddressEqual(prevData, /*ignoreOffset*/ true)) { + // Non-offset part of the address is not the same - bail out. return; } - // STOREIND aren't value nodes. - LIR::Use use; - assert(!BlockRange().TryGetUse(prevInd, &use) && !BlockRange().TryGetUse(ind, &use)); + // The same offset means that we're storing to the same location of the same width. + // Just remove the previous store then. + if (prevData.offset == currData.offset) + { + BlockRange().Remove(prevData.rangeStart, prevData.rangeEnd); + continue; + } - // BaseAddr, Index, Scale and Type all have to match. - if ((prevData.scale != currData.scale) || (prevData.targetType != currData.targetType) || - !GenTree::Compare(prevData.baseAddr, currData.baseAddr) || - !GenTree::Compare(prevData.index, currData.index)) + // TODO-ARM64-CQ: enable TYP_REF if we find a case where it's beneficial. + // The algorithm does support TYP_REF (with null value), but it seems to be not worth + // it on ARM64 where it's pretty efficient to do "stp xzr, xzr, [addr]" to clear two + // items at once. Although, it may be profitable to do "stp q0, q0, [addr]". + if (!varTypeIsIntegral(ind) && !varTypeIsSIMD(ind)) { return; } - // At this point we know that we have two consecutive STOREINDs with the same base address, - // index and scale, the only variable thing is the offset (constant) + assert(ind->OperIs(GT_STOREIND)); + assert(prevInd->OperIs(GT_STOREIND)); + assert(prevData.IsStore()); + assert(currData.IsStore()); - // The same offset means that we're storing to the same location of the same width. - // Just remove the previous store then. - if (prevData.offset == currData.offset) + // For now, only constants are supported for data. + if (!prevData.value->OperIsConst() || !currData.value->OperIsConst()) { - BlockRange().Remove(std::move(prevIndRange)); - continue; + return; } // Otherwise, the difference between two offsets has to match the size of the type. @@ -8702,11 +8710,11 @@ void Lowering::LowerStoreIndirCoalescing(GenTreeStoreInd* ind) } // We should not be here for stores requiring write barriers. - assert(!comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(ind)); - assert(!comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(prevInd)); + assert(!comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(ind->AsStoreInd())); + assert(!comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(prevInd->AsStoreInd())); // Delete previous STOREIND entirely - BlockRange().Remove(std::move(prevIndRange)); + BlockRange().Remove(prevData.rangeStart, prevData.rangeEnd); // It's not expected to be contained yet, but just in case... ind->Data()->ClearContained(); @@ -9413,6 +9421,7 @@ void Lowering::LowerBlockStoreCommon(GenTreeBlk* blkNode) } LowerBlockStore(blkNode); + LowerStoreIndirCoalescing(blkNode); } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h index 055f425b664566..f13f9c2eeab106 100644 --- a/src/coreclr/jit/lower.h +++ b/src/coreclr/jit/lower.h @@ -315,6 +315,35 @@ class Lowering final : public Phase } #endif // defined(TARGET_XARCH) + struct LoadStoreCoalescingData + { + var_types targetType; + GenTree* baseAddr; + GenTree* index; + GenTree* value; + uint32_t scale; + int offset; + GenTree* rangeStart; + GenTree* rangeEnd; + + bool IsStore() const + { + return value != nullptr; + } + + bool IsAddressEqual(const LoadStoreCoalescingData& other, bool ignoreOffset) const + { + if ((scale != other.scale) || (targetType != other.targetType) || + !GenTree::Compare(baseAddr, other.baseAddr) || !GenTree::Compare(index, other.index)) + { + return false; + } + return ignoreOffset || (offset == other.offset); + } + }; + + bool GetLoadStoreCoalescingData(GenTreeIndir* ind, LoadStoreCoalescingData* data) const; + // Per tree node member functions void LowerStoreIndirCommon(GenTreeStoreInd* ind); GenTree* LowerIndir(GenTreeIndir* ind); @@ -323,7 +352,7 @@ class Lowering final : public Phase void MarkTree(GenTree* root); void UnmarkTree(GenTree* root); void LowerStoreIndir(GenTreeStoreInd* node); - void LowerStoreIndirCoalescing(GenTreeStoreInd* node); + void LowerStoreIndirCoalescing(GenTreeIndir* node); GenTree* LowerAdd(GenTreeOp* node); GenTree* LowerMul(GenTreeOp* mul); bool TryLowerAndNegativeOne(GenTreeOp* node, GenTree** nextNode); From 4326eb7ed4d03f30ce4a4de1eb028ee76fdaaa3c Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Wed, 1 May 2024 14:50:21 +0200 Subject: [PATCH 203/248] Fix unnecessary bounds check with ulong index (#101352) --- src/coreclr/jit/valuenum.cpp | 60 ++++++++++++++++++++++++++++-------- src/coreclr/jit/valuenum.h | 3 ++ 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 0808d9d9711178..909e5ab768af44 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -6521,6 +6521,7 @@ bool ValueNumStore::IsVNPositiveInt32Constant(ValueNum vn) // IsVNArrLenUnsignedBound: Checks if the specified vn represents an expression // of one of the following forms: // - "(uint)i < (uint)len" that implies (0 <= i < len) +// - "(ulong)i < (ulong)len" that implies (0 <= i < len) // - "const < (uint)len" that implies "len > const" // - "const <= (uint)len" that implies "len > const - 1" // @@ -6544,49 +6545,57 @@ bool ValueNumStore::IsVNUnsignedCompareCheckedBound(ValueNum vn, UnsignedCompare if ((funcApp.m_func == VNF_LT_UN) || (funcApp.m_func == VNF_GE_UN)) { // We only care about "(uint)i < (uint)len" and its negation "(uint)i >= (uint)len" - if (IsVNCheckedBound(funcApp.m_args[1])) + // Same for (ulong) + ValueNum vnBound = funcApp.m_args[1]; + ValueNum vnIdx = funcApp.m_args[0]; + ValueNum vnCastOp = NoVN; + if (IsVNCheckedBound(vnBound) || (IsVNCastToULong(vnBound, &vnCastOp) && IsVNCheckedBound(vnCastOp))) { - info->vnIdx = funcApp.m_args[0]; + info->vnIdx = vnIdx; info->cmpOper = funcApp.m_func; - info->vnBound = funcApp.m_args[1]; + info->vnBound = (vnCastOp != NoVN) ? vnCastOp : vnBound; return true; } // We care about (uint)len < constant and its negation "(uint)len >= constant" - else if (IsVNPositiveInt32Constant(funcApp.m_args[1]) && IsVNCheckedBound(funcApp.m_args[0])) + else if (IsVNPositiveInt32Constant(vnBound) && IsVNCheckedBound(vnIdx)) { // Change constant < len into (uint)len >= (constant - 1) // to make consuming this simpler (and likewise for it's negation). - INT32 validIndex = ConstantValue(funcApp.m_args[1]) - 1; + INT32 validIndex = ConstantValue(vnBound) - 1; assert(validIndex >= 0); info->vnIdx = VNForIntCon(validIndex); info->cmpOper = (funcApp.m_func == VNF_GE_UN) ? VNF_LT_UN : VNF_GE_UN; - info->vnBound = funcApp.m_args[0]; + info->vnBound = vnIdx; return true; } } else if ((funcApp.m_func == VNF_GT_UN) || (funcApp.m_func == VNF_LE_UN)) { // We only care about "(uint)a.len > (uint)i" and its negation "(uint)a.len <= (uint)i" - if (IsVNCheckedBound(funcApp.m_args[0])) + // Same for (ulong) + ValueNum vnBound = funcApp.m_args[0]; + ValueNum vnIdx = funcApp.m_args[1]; + ValueNum vnCastOp = NoVN; + if (IsVNCheckedBound(vnBound) || (IsVNCastToULong(vnBound, &vnCastOp) && IsVNCheckedBound(vnCastOp))) { - info->vnIdx = funcApp.m_args[1]; + info->vnIdx = vnIdx; // Let's keep a consistent operand order - it's always i < len, never len > i info->cmpOper = (funcApp.m_func == VNF_GT_UN) ? VNF_LT_UN : VNF_GE_UN; - info->vnBound = funcApp.m_args[0]; + info->vnBound = (vnCastOp != NoVN) ? vnCastOp : vnBound; return true; } // Look for constant > (uint)len and its negation "constant <= (uint)len" - else if (IsVNPositiveInt32Constant(funcApp.m_args[0]) && IsVNCheckedBound(funcApp.m_args[1])) + else if (IsVNPositiveInt32Constant(vnBound) && IsVNCheckedBound(vnIdx)) { // Change constant <= (uint)len to (constant - 1) < (uint)len // to make consuming this simpler (and likewise for it's negation). - INT32 validIndex = ConstantValue(funcApp.m_args[0]) - 1; + INT32 validIndex = ConstantValue(vnBound) - 1; assert(validIndex >= 0); info->vnIdx = VNForIntCon(validIndex); info->cmpOper = (funcApp.m_func == VNF_LE_UN) ? VNF_LT_UN : VNF_GE_UN; - info->vnBound = funcApp.m_args[1]; + info->vnBound = vnIdx; return true; } } @@ -6823,6 +6832,33 @@ bool ValueNumStore::IsVNCheckedBound(ValueNum vn) return false; } +//---------------------------------------------------------------------------------- +// IsVNCastToULong: checks whether the given VN represents (ulong)op cast +// +// Arguments: +// vn - VN, presumably, representing (ulong)op cast +// castedOp - [Out] VN of op being cast +// +// Return Value: +// true if the given VN represents (ulong)op cast +// +bool ValueNumStore::IsVNCastToULong(ValueNum vn, ValueNum* castedOp) +{ + VNFuncApp funcApp; + if (GetVNFunc(vn, &funcApp) && (funcApp.m_func == VNF_Cast)) + { + var_types castToType; + bool srcIsUnsigned; + GetCastOperFromVN(funcApp.m_args[1], &castToType, &srcIsUnsigned); + if (srcIsUnsigned && (castToType == TYP_LONG)) + { + *castedOp = funcApp.m_args[0]; + return true; + } + } + return false; +} + void ValueNumStore::SetVNIsCheckedBound(ValueNum vn) { // This is meant to flag VNs for lengths that aren't known at compile time, so we can diff --git a/src/coreclr/jit/valuenum.h b/src/coreclr/jit/valuenum.h index 799d36472b00c9..f88de8f55856d5 100644 --- a/src/coreclr/jit/valuenum.h +++ b/src/coreclr/jit/valuenum.h @@ -905,6 +905,9 @@ class ValueNumStore // of the length argument to a GT_BOUNDS_CHECK node. bool IsVNCheckedBound(ValueNum vn); + // Returns true if the VN is known to be a cast to ulong + bool IsVNCastToULong(ValueNum vn, ValueNum* castedOp); + // Record that a VN is known to appear as the conservative value number of the length // argument to a GT_BOUNDS_CHECK node. void SetVNIsCheckedBound(ValueNum vn); From b8abb6aefe443853774500a7b85c052c682c9420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Wed, 1 May 2024 10:40:50 -0400 Subject: [PATCH 204/248] [docs] Import mono manual page (#101765) Converted with Pandoc 3.1.13: ```console pandoc --from=man --to=gfm mono.1 --shift-heading-level-by=1 --strip-comments=false ``` And tweaked by hand --- docs/design/mono/mono-manpage-1.md | 2005 ++++++++++++++++++++++++++++ 1 file changed, 2005 insertions(+) create mode 100644 docs/design/mono/mono-manpage-1.md diff --git a/docs/design/mono/mono-manpage-1.md b/docs/design/mono/mono-manpage-1.md new file mode 100644 index 00000000000000..20ab43b7563a77 --- /dev/null +++ b/docs/design/mono/mono-manpage-1.md @@ -0,0 +1,2005 @@ +# Mono Manual Page + +Copyright 2003 Ximian, Inc. \ +Copyright 2004-2011 Novell, Inc. \ +Copyright 2011-2012 Xamarin Inc \ +Copyright 2013 7digital Media Ltd. \ +Copyright (c) .NET Foundation and Contributors + +Author: \ +Miguel de Icaza (miguel@gnu.org) + +## NAME + +mono - Mono's ECMA-CLI native code generator (Just-in-Time and +Ahead-of-Time) + +## SYNOPSIS + +**mono \[options\] file \[arguments...\]** + +**mono-sgen \[options\] file \[arguments...\]** + +## DESCRIPTION + +*mono* is a runtime implementation of the ECMA Common Language +Infrastructure. This can be used to run ECMA and .NET applications. + +The runtime loads the specified *file* and optionally passes the +*arguments* to it. The *file* is an ECMA assembly. They typically have a +.exe or .dll extension. + +These executables can reference additional functionality in the form of +assembly references. By default those assembly references are resolved +as follows: the **mscorlib.dll** is resolved from the system profile +that is configured by Mono, and other assemblies are loaded from the +Global Assembly Cache (GAC). + +The runtime contains a native code generator that transforms the Common +Intermediate Language into native code. + +The code generator can operate in two modes: Just-in-time compilation +(JIT) or Ahead-of-time compilation (AOT). Since code can be dynamically +loaded, the runtime environment and the JIT are always present, even if +code is compiled ahead of time. + +The runtime provides a number of configuration options for running +applications, for developing and debugging, and for testing and +debugging the runtime itself. + +The *mono* command uses the moving and generational SGen garbage +collector while the *mono-boehm* command uses the conservative Boehm +garbage collector. + +## PORTABILITY + +On Unix-based systems, Mono provides a mechanism to emulate the +Windows-style file access, this includes providing a case insensitive +view of the file system, directory separator mapping (from \\ to /) and +stripping the drive letters. + +This functionality is enabled by setting the **MONO_IOMAP** environment +variable to one of **all, drive** and **case.** + +See the description for **MONO_IOMAP** in the environment variables +section for more details. + +## METHOD DESCRIPTIONS + +A number of diagnostic command line options take as argument a method +description. A method description is a textual representation that can +be used to uniquely identify a method. The syntax is as follows: + + [namespace]classname:methodname[(arguments)] + +The values in brackets are optional, like the namespace and the +arguments. The arguments themselves are either empty, or a +comma-separated list of arguments. Both the **classname** and +**methodname** can be set to the special value '\*' to match any values +(Unix shell users should escape the argument to avoid the shell +interpreting this). + +The arguments, if present should be a comma separated list of types +either a full typename, or for built-in types it should use the +low-level ILAsm type names for the built-in types, like 'void', 'char', +'bool', 'byte', 'sbyte', 'uint16', 'int16', 'uint', + +Pointer types should be the name of the type, followed by a '\*', arrays +should be the typename followed by '\[' one or more commas (to indicate +the rank of the array), and '\]'. + +Generic values should use '\<', one or more type names, separated by +both a comma and a space and '\>'. + +By-reference arguments should include a "&" after the typename. + +Examples: + + *:ctor(int) // All constructors that take an int as an argument + *:Main // Methods named Main in any class + *:Main(string[]) // Methods named Main that take a string array in any class + +## RUNTIME OPTIONS + +The following options are available: + +**--aot**, **--aot\[=options\]** +This option is used to precompile the CIL code in the specified assembly +to native code. The generated code is stored in a file with the +extension .so. This file will be automatically picked up by the runtime +when the assembly is executed. + +Ahead-of-Time compilation is most useful if you use it in combination +with the -O=all,-shared flag which enables all of the optimizations in +the code generator to be performed. Some of those optimizations are not +practical for Just-in-Time compilation since they might be very time +consuming. + +Unlike the .NET Framework, Ahead-of-Time compilation will not generate +domain independent code: it generates the same code that the +Just-in-Time compiler would produce. Since most applications use a +single domain, this is fine. If you want to optimize the generated code +for use in multi-domain applications, consider using the -O=shared flag. + +This pre-compiles the methods, but the original assembly is still +required to execute as this one contains the metadata and exception +information which is not available on the generated file. When +precompiling code, you might want to compile with all optimizations +(-O=all). Pre-compiled code is position independent code. + +Precompilation is just a mechanism to reduce startup time, increase code +sharing across multiple mono processes and avoid just-in-time +compilation program startup costs. The original assembly must still be +present, as the metadata is contained there. + +AOT code typically can not be moved from one computer to another +(CPU-specific optimizations that are detected at runtime) so you should +not try to move the pre-generated assemblies or package the +pre-generated assemblies for deployment. + +A few options are available as a parameter to the **--aot** command line +option. The options are separated by commas, and more than one can be +specified: + +> *asmonly* +> Instructs the AOT compiler to output assembly code instead of an +> object file. +> +> *bind-to-runtime-version* +> +> If specified, forces the generated AOT files to be bound to the +> runtime version of the compiling Mono. This will prevent the AOT files +> from being consumed by a different Mono runtime. +> +> *data-outfile=FILE.dll.aotdata* +> +> This instructs the AOT code generator to output certain data +> constructs into a separate file. This can reduce the executable images +> some five to twenty percent. Developers need to then ship the +> resulting aotdata as a resource and register a hook to load the data +> on demand by using the *mono_install_load_aot_data_hook* method. +> +> *direct-icalls* +> +> When this option is specified, icalls (internal calls made from the +> standard library into the mono runtime code) are invoked directly +> instead of going through the operating system symbol lookup operation. +> This requires use of the *static* option. +> +> *direct-pinvoke* +> +> When this option is specified, P/Invoke methods are invoked directly +> instead of going through the operating system symbol lookup operation. +> This requires use of the *static* option. +> +> *dwarfdebug* +> Instructs the AOT compiler to emit DWARF debugging information. When +> used together with the nodebug option, only DWARF debugging +> information is emitted, but not the information that can be used at +> runtime. +> +> *full* +> +> This creates binaries which can be used with the --full-aot option. +> +> *hybrid* +> +> This creates binaries which can be used with the --hybrid-aot option. +> +> *llvm* +> AOT will be performed with the LLVM backend instead of the Mono +> backend where possible. This will be slower to compile but most likely +> result in a performance improvement. +> +> *llvmonly* +> AOT will be performed with the LLVM backend exclusively and the Mono +> backend will not be used. The only output in this mode will be the +> bitcode file normally specified with the *llvm-outfile* option. Use of +> *llvmonly* automatically enables the *full* and *llvm* options. This +> feature is experimental. +> +> *llvmopts=\[options\]* +> Use this option to add more flags to the built-in set of flags passed +> to the LLVM optimizer. When you invoke the *mono* command with the +> *--aot=llvm* it displays the current list of flags that are being +> passed to the *opt* command. *The list of possible flags that can be +> passed can be* obtained by calling the bundled *opt* program that +> comes with Mono, and calling it like this: +> +> +> +> +> opt --help +> +> *llvmllc=\[options\]* +> Use this option to add more flags to the built-in set of flags passed +> to the LLVM static compiler (llc). The list of possible flags that can +> be passed can be obtained by calling the bundled *llc* program that +> comes with Mono, and calling it like this: +> +> +> +> +> llc --help +> +> *mcpu=\[native o generic\]* +> cpu=native allows AOT mode to use all instructions current CPU +> supports, e.g. AVX2, SSE42, etc. Default value is 'generic'. +> *mattr=\[cpu feature\]* Allows AOT code generator to use specified CPU +> features where possible including \`System.Runtime.Intrinsics.\*'. +> E.g. \`mattr=+avx2,mattr=-lzcnt' unlocks sse1-4.2, avx1-2 and disables +> lzcnt. It's useful for cross-compilation or when it's not possible to +> use \`-mcpu=native' (which enables all cpu feature current cpu has). +> *llvm-outfile=\[filename\]* Gives the path for the temporary LLVM +> bitcode file created during AOT. *dedup* Each AOT module will +> typically contain the code for inflated methods and wrappers that are +> called by code in that module. In dedup mode, we identify and skip +> compiling all of those methods. When using this mode with fullaot, +> dedup-include is required or these methods will remain missing. +> +> *dedup-include=\[filename\]* +> In dedup-include mode, we are in the pass of compilation where we +> compile the methods that we had previously skipped. All of them are +> emitted into the assembly that is passed as this option. We +> consolidate the many duplicate skipped copies of the same method into +> one. +> +> +> +> *info* +> Print the architecture the AOT in this copy of Mono targets and quit. +> +> *interp* +> Generates all required wrappers, so that it is possible to run +> --interpreter without any code generation at runtime. This option only +> makes sense with **mscorlib.dll**. Embedders can set +> +> *depfile=\[filename\]* +> Outputs a gcc -M style dependency file. +> +> mono_jit_set_aot_mode (MONO_AOT_MODE_INTERP); +> +> +> +> *ld-flags* +> Additional flags to pass to the C linker (if the current AOT mode +> calls for invoking it). +> +> *llvm-path=\* +> Same for the llvm tools 'opt' and 'llc'. +> +> *msym-dir=\* +> Instructs the AOT compiler to generate offline sequence points .msym +> files. The generated .msym files will be stored into a subfolder of +> \ named as the compilation AOTID. +> +> *mtriple=\* +> Use the GNU style target triple \ to determine some code +> generation options, i.e. --mtriple=armv7-linux-gnueabi will generate +> code that targets ARMv7. This is currently only supported by the ARM +> backend. In LLVM mode, this triple is passed on to the LLVM llc +> compiler. +> +> *nimt-trampolines=\[number\]* +> When compiling in full aot mode, the IMT trampolines must be +> precreated in the AOT image. You can add additional method trampolines +> with this argument. Defaults to 512. +> +> *ngsharedvt-trampolines=\[number\]* +> When compiling in full aot mode, the value type generic sharing +> trampolines must be precreated in the AOT image. You can add +> additional method trampolines with this argument. Defaults to 512. +> +> *nodebug* +> Instructs the AOT compiler to not output any debugging information. +> +> *no-direct-calls* +> This prevents the AOT compiler from generating a direct calls to a +> method. The AOT compiler usually generates direct calls for certain +> methods that do not require going through the PLT (for example, +> methods that are known to not require a hook like a static +> constructor) or call into simple internal calls. +> +> *nrgctx-trampolines=\[number\]* +> When compiling in full aot mode, the generic sharing trampolines must +> be precreated in the AOT image. You can add additional method +> trampolines with this argument. Defaults to 4096. +> +> *nrgctx-fetch-trampolines=\[number\]* +> When compiling in full aot mode, the generic sharing fetch trampolines +> must be precreated in the AOT image. You can add additional method +> trampolines with this argument. Defaults to 128. +> +> *ntrampolines=\[number\]* +> When compiling in full aot mode, the method trampolines must be +> precreated in the AOT image. You can add additional method trampolines +> with this argument. Defaults to 4096. +> +> *outfile=\[filename\]* +> Instructs the AOT compiler to save the output to the specified file. +> +> *print-skipped-methods* +> If the AOT compiler cannot compile a method for any reason, enabling +> this flag will output the skipped methods to the console. +> +> *profile=\[file\]* +> Specify a file to use for profile-guided optimization. See the **AOT +> profiler** sub-section. To specify multiple files, include the +> *profile* option multiple times. +> +> *profile-only* +> AOT \*only\* the methods described in the files specified with the +> *profile* option. See the **AOT profiler** sub-section. +> +> *readonly-value=namespace.typename.fieldname=type/value* +> Override the value of a static readonly field. Usually, during JIT +> compilation, the static constructor is ran eagerly, so the value of a +> static readonly field is known at compilation time and the compiler +> can do a number of optimizations based on it. During AOT, instead, the +> static constructor can't be ran, so this option can be used to set the +> value of such a field and enable the same set of optimizations. Type +> can be any of i1, i2, i4 for integers of the respective sizes (in +> bytes). Note that signed/unsigned numbers do not matter here, just the +> storage size. This option can be specified multiple times and it +> doesn't prevent the static constructor for the type defining the field +> to execute with the usual rules at runtime (hence possibly computing a +> different value for the field). +> +> *save-temps,keep-temps* +> Instructs the AOT compiler to keep temporary files. +> +> *soft-debug* +> This instructs the compiler to generate sequence point checks that +> allow Mono's soft debugger to debug applications even on systems where +> it is not possible to set breakpoints or to single step (certain +> hardware configurations like the cell phones and video gaming +> consoles). +> +> *static* +> Create an ELF object file (.o) or .s file which can be statically +> linked into an executable when embedding the mono runtime. When this +> option is used, the object file needs to be registered with the +> embedded runtime using the mono_aot_register_module function which +> takes as its argument the mono_aot_module\_\\_info +> global symbol from the object file: +> +> extern void *mono_aot_module_hello_info; +> +> mono_aot_register_module (mono_aot_module_hello_info); +> +> +> +> *stats* +> Print various stats collected during AOT compilation. +> +> *temp-path=\[path\]* +> Explicitly specify path to store temporary files created during AOT +> compilation. +> +> *threads=\[number\]* +> This is an experimental option for the AOT compiler to use multiple +> threads when compiling the methods. +> +> *tool-prefix=\* +> Prepends \ to the name of tools ran by the AOT compiler, i.e. +> 'as'/'ld'. For example, --tool=prefix=arm-linux-gnueabi- will make the +> AOT compiler run +> +> +> +> *ld-name=NAME* +> One of the tools used for AOT builds is the linker. Its name differs +> between various systems and it may happen that the assumed default +> name of the binary is not present. If the toolchain used does not have +> a linker with the default name (e.g. Android NDK r22 does not have the +> default 'ld' linker prefixed with 'tool-prefix' above, instead it has +> prefixed 'ld.gold' and 'ld.bfd' linkers) this option can be used to +> set the linker binary name. It will be prefixed with 'tool-prefix' to +> form the full linker executable name. +> +> *verbose* +> Prints additional information about type loading failures. +> +> *write-symbols,no-write-symbols* +> Instructs the AOT compiler to emit (or not emit) debug symbol +> information. +> +> *no-opt* +> Instructs the AOT compiler tot no call opt when compiling with LLVM. +> +> For more information about AOT, see: +> http://www.mono-project.com/docs/advanced/aot/ + +**--aot-path=PATH** +List of additional directories to search for AOT images. + +**--apply-bindings=FILE** +Apply the assembly bindings from the specified configuration file when +running the AOT compiler. This is useful when compiling an auxiliary +assembly that is referenced by a main assembly that provides a +configuration file. For example, if app.exe uses lib.dll then in order +to make the assembly bindings from app.exe.config available when +compiling lib.dll ahead of time, use: + + + + mono --apply-bindings=app.exe.config --aot lib.dll + +**--assembly-loader=MODE** +If mode is **strict**, Mono will check that the public key token, +culture and version of a candidate assembly matches the requested strong +name. If mode is **legacy**, as long as the name matches, the candidate +will be allowed. **strict** is the behavior consistent with .NET +Framework but may break some existing mono-based applications. The +default is **legacy**. + +**--attach=\[options\]** +Currently the only option supported by this command line argument is +**disable** which disables the attach functionality. + +**--config filename** +Load the specified configuration file instead of the default one(s). The +default files are /etc/mono/config and ~/.mono/config or the file +specified in the MONO_CONFIG environment variable, if set. See the +mono-config(5) man page for details on the format of this file. + +**--debugger-agent=\[options\]** +This instructs the Mono runtime to start a debugging agent inside the +Mono runtime and connect it to a client user interface will control the +Mono process. This option is typically used by IDEs, like the +MonoDevelop or Visual Studio IDEs. + +The configuration is specified using one of more of the following +options: + +> *address=host:port* +> +> Use this option to specify the IP address where your debugger client +> is listening to. +> +> *loglevel=LEVEL* +> +> Specifies the diagnostics log level for +> +> *logfile=filename* +> +> Used to specify the file where the log will be stored, it defaults to +> standard output. +> +> *server=\[y/n\]* +> Defaults to no, with the default option Mono will actively connect to +> the host/port configured with the **address** option. If you set it to +> 'y', it instructs the Mono runtime to start debugging in server mode, +> where Mono actively waits for the debugger front end to connect to the +> Mono process. Mono will print out to stdout the IP address and port +> where it is listening. +> +> *setpgid=\[y/n\]* +> If set to yes, Mono will call **setpgid(0, 0)** on startup, if that +> function is available on the system. This is useful for ensuring that +> signals delivered to a process that is executing the debuggee are not +> propagated to the debuggee, e.g. when Ctrl-C sends **SIGINT** to the +> **sdb** tool. +> +> *suspend=\[y/n\]* +> Defaults to yes, with the default option Mono will suspend the vm on +> startup until it connects successfully to a debugger front end. If you +> set it to 'n', in conjunction with **server=y**, it instructs the Mono +> runtime to run as normal, while caching metadata to send to the +> debugger front end on connection.. +> +> *transport=transport_name* +> +> This is used to specify the transport that the debugger will use to +> communicate. It must be specified and currently requires this to be +> 'dt_socket'. + +**--desktop** +Configures the virtual machine to be better suited for desktop +applications. Currently this sets the GC system to avoid expanding the +heap as much as possible at the expense of slowing down garbage +collection a bit. + +**--full-aot** +This flag instructs the Mono runtime to not generate any code at runtime +and depend exclusively on the code generated from using mono --aot=full +previously. This is useful for platforms that do not permit dynamic code +generation, or if you need to run assemblies that have been stripped of +IL (for example using mono-cil-strip). + +Notice that this feature will abort execution at runtime if a codepath +in your program, or Mono's class libraries attempts to generate code +dynamically. You should test your software upfront and make sure that +you do not use any dynamic features. + +**--full-aot-interp** +Same as --full-aot with fallback to the interpreter. + +**--gc=boehm**, **--gc=sgen** +Selects the Garbage Collector engine for Mono to use, Boehm or SGen. +Currently this merely ensures that you are running either the *mono* or +*mono-sgen* commands. This flag can be set in the **MONO_ENV_OPTIONS** +environment variable to force all of your child processes to use one +particular kind of GC with the Mono runtime. + +**--gc-debug=\[options\]** +Command line equivalent of the **MONO_GC_DEBUG** environment variable. + +**--gc-params=\[options\]** +Command line equivalent of the **MONO_GC_PARAMS** environment variable. + +**--arch=32**, **--arch=64** +(Mac OS X only): Selects the bitness of the Mono binary used, if +available. If the binary used is already for the selected bitness, +nothing changes. If not, the execution switches to a binary with the +selected bitness suffix installed side by side (for example, '/bin/mono +--arch=64' will switch to '/bin/mono64' iff '/bin/mono' is a 32-bit +build). + +**--help**, **-h** +Displays usage instructions. + +**--interpreter** +The Mono runtime will use its interpreter to execute a given assembly. +The interpreter is usually slower than the JIT, but it can be useful on +platforms where code generation at runtime is not allowed. + +**--hybrid-aot** +This flag allows the Mono runtime to run assemblies that have been +stripped of IL, for example using mono-cil-strip. For this to work, the +assembly must have been AOT compiled with --aot=hybrid. + +This flag is similar to --full-aot, but it does not disable the JIT. +This means you can use dynamic features such as System.Reflection.Emit. + +**--llvm** +If the Mono runtime has been compiled with LLVM support (not available +in all configurations), Mono will use the LLVM optimization and code +generation engine to JIT or AOT compile. + +For more information, consult: +http://www.mono-project.com/docs/advanced/mono-llvm/ + +**--ffast-math** +This flag allows Mono and LLVM to apply aggressive floating point +optimizations. Can break IEEE754 compliance. + +**--nollvm** +When using a Mono that has been compiled with LLVM support, it forces +Mono to fallback to its JIT engine and not use the LLVM backend. + +**--optimize=MODE**, **-O=MODE** +MODE is a comma separated list of optimizations. They also allow +optimizations to be turned off by prefixing the optimization name with a +minus sign. + +In general, Mono has been tuned to use the default set of flags, before +using these flags for a deployment setting, you might want to actually +measure the benefits of using them. + +The following optimization flags are implemented in the core engine: + + abcrem Array bound checks removal + all Turn on all optimizations + aot Usage of Ahead Of Time compiled code + branch Branch optimizations + cfold Constant folding + cmov Conditional moves [arch-dependency] + deadce Dead code elimination + consprop Constant propagation + copyprop Copy propagation + fcmov Fast x86 FP compares [arch-dependency] + float32 Perform 32-bit float arithmetic using 32-bit operations + gshared Enable generic code sharing. + inline Inline method calls + intrins Intrinsic method implementations + linears Linear scan global reg allocation + leaf Leaf procedures optimizations + loop Loop related optimizations + peephole Peephole postpass + precomp Precompile all methods before executing Main + sched Instruction scheduling + shared Emit per-domain code + sse2 SSE2 instructions on x86 [arch-dependency] + tailc Tail recursion and tail calls + +For example, to enable all the optimization but dead code elimination +and inlining, you can use: + + -O=all,-deadce,-inline + +The flags that are flagged with \[arch-dependency\] indicate that the +given option if used in combination with Ahead of Time compilation +(--aot flag) would produce pre-compiled code that will depend on the +current CPU and might not be safely moved to another computer. + +> The following optimizations are supported +> +> *float32* +> Requests that the runtime performn 32-bit floating point operations +> using only 32-bits. By default the Mono runtime tries to use the +> highest precision available for floating point operations, but while +> this might render better results, the code might run slower. This +> options also affects the code generated by the LLVM backend. +> +> *inline* +> Controls whether the runtime should attempt to inline (the default), +> or not inline methods invocations + +**--response=FILE** Provides a response file, this instructs the Mono +command to read other command line options from the specified file, as +if the options had been specified on the command line. Useful when you +have very long command lines. + +**--runtime=VERSION** +Mono supports different runtime versions. The version used depends on +the program that is being run or on its configuration file (named +program.exe.config). This option can be used to override such +autodetection, by forcing a different runtime version to be used. Note +that this should only be used to select a later compatible runtime +version than the one the program was compiled against. A typical usage +is for running a 1.1 program on a 2.0 version: + + mono --runtime=v2.0.50727 program.exe + +**--server** +Configures the virtual machine to be better suited for server operations +(currently, allows a heavier threadpool initialization). + +**--use-map-jit** +Instructs Mono to generate code using MAP_JIT on MacOS. Necessary for +bundled applications. + +**--verify-all** +Verifies mscorlib and assemblies in the global assembly cache for valid +IL, and all user code for IL verifiability. + +This is different from **--security**'s verifiable or validil in that +these options only check user code and skip mscorlib and assemblies +located on the global assembly cache. + +**-V**, **--version** +Prints JIT version information (system configuration, release number and +branch names if available). + +**--version=number** +Print version number only. + +## DEVELOPMENT OPTIONS + +The following options are used to help when developing a JITed +application. + +**--debug**, **--debug=OPTIONS** +Turns on the debugging mode in the runtime. If an assembly was compiled +with debugging information, it will produce line number information for +stack traces. + +The optional OPTIONS argument is a comma separated list of debugging +options. These options are turned off by default since they generate +much larger and slower code at runtime. + +The following options are supported: +*casts* +Produces a detailed error when throwing a InvalidCastException. This +option needs to be enabled as this generates more verbose code at +execution time. + +*mdb-optimizations* +Disable some JIT optimizations which are usually only disabled when +running inside the debugger. This can be helpful if you want to attach +to the running process with mdb. + +*gdb* +Generate and register debugging information with gdb. This is only +supported on some platforms, and only when using gdb 7.0 or later. + +**--profile**\[=*profiler*\[:*profiler_args*\]\] +Loads a profiler module with the given arguments. For more information, +see the **PROFILING** section. + +This option can be used multiple times; each time will load an +additional profiler module. + +**--trace\[=expression\]** +Shows method names as they are invoked. By default all methods are +traced. + +The trace can be customized to include or exclude methods, classes or +assemblies. A trace expression is a comma separated list of targets, +each target can be prefixed with a minus sign to turn off a particular +target. The words \`program', \`all' and \`disabled' have special +meaning. \`program' refers to the main program being executed, and +\`all' means all the method calls. + +The \`disabled' option is used to start up with tracing disabled. It can +be enabled at a later point in time in the program by sending the +SIGUSR2 signal to the runtime. + +Assemblies are specified by their name, for example, to trace all calls +in the System assembly, use: + + + mono --trace=System app.exe + +Classes are specified with the T: prefix. For example, to trace all +calls to the System.String class, use: + + + mono --trace=T:System.String app.exe + +And individual methods are referenced with the M: prefix, and the +standard method notation: + + + mono --trace=M:System.Console:WriteLine app.exe + +Exceptions can also be traced, it will cause a stack trace to be printed +every time an exception of the specified type is thrown. The exception +type can be specified with or without the namespace, and to trace all +exceptions, specify 'all' as the type name. + + + mono --trace=E:System.Exception app.exe + +As previously noted, various rules can be specified at once: + + + mono --trace=T:System.String,T:System.Random app.exe + +You can exclude pieces, the next example traces calls to System.String +except for the System.String:Concat method. + + + mono --trace=T:System.String,-M:System.String:Concat + +You can trace managed to unmanaged transitions using the wrapper +qualifier: + + + mono --trace=wrapper app.exe + +Finally, namespaces can be specified using the N: prefix: + + + mono --trace=N:System.Xml + +**--no-x86-stack-align** +Don't align stack frames on the x86 architecture. By default, Mono +aligns stack frames to 16 bytes on x86, so that local floating point and +SIMD variables can be properly aligned. This option turns off the +alignment, which usually saves one instruction per call, but might +result in significantly lower floating point and SIMD performance. + +**--jitmap** +Generate a JIT method map in a /tmp/perf-PID.map file. This file is then +used, for example, by the perf tool included in recent Linux kernels. +Each line in the file has: + + + + + HEXADDR HEXSIZE methodname + +Currently this option is only supported on Linux. + +## JIT MAINTAINER OPTIONS + +The maintainer options are only used by those developing the runtime +itself, and not typically of interest to runtime users or developers. + +**--bisect=optimization:filename** +This flag is used by the automatic optimization bug bisector. It takes +an optimization flag and a filename of a file containing a list of full +method names, one per line. When it compiles one of the methods in the +file it will use the optimization given, in addition to the +optimizations that are otherwise enabled. Note that if the optimization +is enabled by default, you should disable it with \`-O\`, otherwise it +will just apply to every method, whether it's in the file or not. + +**--break method** +Inserts a breakpoint before the method whose name is \`method' +(namespace.class:methodname). Use \`Main' as method name to insert a +breakpoint on the application's main method. You can use it also with +generics, for example "System.Collections.Generic.Queue\`1:Peek" + +**--breakonex** +Inserts a breakpoint on exceptions. This allows you to debug your +application with a native debugger when an exception is thrown. + +**--compile name** +This compiles a method (namespace.name:methodname), this is used for +testing the compiler performance or to examine the output of the code +generator. + +**--compile-all** +Compiles all the methods in an assembly. This is used to test the +compiler performance or to examine the output of the code generator + +**--graph=TYPE METHOD** +This generates a postscript file with a graph with the details about the +specified method (namespace.name:methodname). This requires \`dot' and +ghostview to be installed (it expects Ghostview to be called "gv"). + +The following graphs are available: + + cfg Control Flow Graph (CFG) + dtree Dominator Tree + code CFG showing code + ssa CFG showing code after SSA translation + optcode CFG showing code after IR optimizations + +Some graphs will only be available if certain optimizations are turned +on. + +**--ncompile** +Instruct the runtime on the number of times that the method specified by +--compile (or all the methods if --compile-all is used) to be compiled. +This is used for testing the code generator performance. + +**--stats=\[method\]** +Displays information about the work done by the runtime during the +execution of an application. If a method (namespace.name:methodname) is +specified, it will display that information when the method is first run +in addition to the end of program execution. + +**--wapi=hps\|semdel** +Perform maintenance of the process shared data. + +semdel will delete the global semaphore. + +hps will list the currently used handles. + +**-v**, **--verbose** +Increases the verbosity level, each time it is listed, increases the +verbosity level to include more information (including, for example, a +disassembly of the native code produced, code selector info etc.). + +## ATTACH SUPPORT + +The Mono runtime allows external processes to attach to a running +process and load assemblies into the running program. To attach to the +process, a special protocol is implemented in the Mono.Management +assembly. + +With this support it is possible to load assemblies that have an entry +point (they are created with -target:exe or -target:winexe) to be loaded +and executed in the Mono process. + +The code is loaded into the root domain, and it starts execution on the +special runtime attach thread. The attached program should create its +own threads and return after invocation. + +This support allows for example debugging applications by having the +csharp shell attach to running processes. + +## PROFILING + +The Mono runtime includes a profiler API that dynamically loaded +profiler modules and embedders can use to collect performance-related +data about an application. Profiler modules are loaded by passing the +**--profile** command line argument to the Mono runtime. + +Mono ships with a few profiler modules, of which the **log** profiler is +the most feature-rich. It is also the default profiler if the *profiler* +argument is not given, or if **default** is given. It is possible to +write your own profiler modules; see the **Custom profilers** +sub-section. + +### Log profiler + +The log profiler can be used to collect a lot of information about a +program running in the Mono runtime. This data can be used (both while +the process is running and later) to do analyses of the program +behavior, determine resource usage, performance issues or even look for +particular execution patterns. + +This is accomplished by logging the events provided by the Mono runtime +through the profiler API and periodically writing them to a file which +can later be inspected with the **mprof-report**(1) tool. + +More information about how to use the log profiler is available on the +**mono-profilers**(1) page, under the **LOG PROFILER** section, as well +as the **mprof-report**(1) page. + +### Coverage profiler + +The code coverage profiler can instrument a program to help determine +which classes, methods, code paths, etc are actually executed. This is +most useful when running a test suite to determine whether the tests +actually cover the code they're expected to. + +More information about how to use the coverage profiler is available on +the **mono-profilers**(1) page, under the **COVERAGE** PROFILER section. + +### AOT profiler + +The AOT profiler can help improve startup performance by logging which +generic instantiations are used by a program, which the AOT compiler can +then use to compile those instantiations ahead of time so that they +won't have to be JIT compiled at startup. + +More information about how to use the AOT profiler is available on the +**mono-profilers**(1) page, under the **AOT PROFILER** section. + +### Custom profilers + +Custom profiler modules can be loaded in exactly the same way as the +standard modules that ship with Mono. They can also access the same +profiler API to gather all kinds of information about the code being +executed. + +For example, to use a third-party profiler called **custom**, you would +load it like this: + + mono --profile=custom program.exe + +You could also pass arguments to it: + + mono --profile=custom:arg1,arg2=arg3 program.exe + +In the above example, Mono will load the profiler from the shared +library called *libmono-profiler-custom.so* (name varies based on +platform, e.g., *libmono-profiler-custom.dylib* on OS X). This profiler +module must be on your dynamic linker library path (**LD_LIBRARY_PATH** +on most systems, **DYLD_LIBRARY_PATH** on OS X). + +For a sample of how to write your own custom profiler, look at the +*samples/profiler/sample.c* file in the Mono source tree. + +## DEBUGGING AIDS + +To debug managed applications, you can use the **mdb** command, a +command line debugger. + +It is possible to obtain a stack trace of all the active threads in Mono +by sending the QUIT signal to Mono, you can do this from the command +line, like this: + + + kill -QUIT pid + +Where pid is the Process ID of the Mono process you want to examine. The +process will continue running afterwards, but its state is not +guaranteed. + +**Important:** this is a last-resort mechanism for debugging +applications and should not be used to monitor or probe a production +application. The integrity of the runtime after sending this signal is +not guaranteed and the application might crash or terminate at any given +point afterwards. + +The **--debug=casts** option can be used to get more detailed +information for Invalid Cast operations, it will provide information +about the types involved. + +You can use the MONO_LOG_LEVEL and MONO_LOG_MASK environment variables +to get verbose debugging output about the execution of your application +within Mono. + +The *MONO_LOG_LEVEL* environment variable if set, the logging level is +changed to the set value. Possible values are "error", "critical", +"warning", "message", "info", "debug". The default value is "error". +Messages with a logging level greater then or equal to the log level +will be printed to stdout/stderr. + +Use "info" to track the dynamic loading of assemblies. + +Use the *MONO_LOG_MASK* environment variable to limit the extent of the +messages you get: If set, the log mask is changed to the set value. +Possible values are "asm" (assembly loader), "type", "dll" (native +library loader), "gc" (garbage collector), "cfg" (config file loader), +"aot" (precompiler), "security" (e.g. Moonlight CoreCLR support), +"threadpool" (thread pool generic), "io-selector" (async socket +operations), "io-layer" (I/O layer - processes, files, sockets, events, +semaphores, mutexes and handles), "io-layer-process", "io-layer-file", +"io-layer-socket", "io-layer-event", "io-layer-semaphore", +"io-layer-mutex", "io-layer-handle" and "all". The default value is +"all". Changing the mask value allows you to display only messages for a +certain component. You can use multiple masks by comma separating them. +For example to see config file messages and assembly loader messages set +you mask to "asm,cfg". + +The following is a common use to track down problems with P/Invoke: + + + $ MONO_LOG_LEVEL="debug" MONO_LOG_MASK="dll" mono glue.exe + +## DEBUGGING WITH LLDB + +If you are using LLDB, you can use the **mono.py** script to print some +internal data structures with it. To use this, add this to your +**\$HOME/.lldbinit** file: + + command script import $PREFIX/lib/mono/lldb/mono.py + +Where \$PREFIX is the prefix value that you used when you configured +Mono (typically /usr). + +Once this is done, then you can inspect some Mono Runtime data +structures, for example: + + (lldb) p method + + (MonoMethod *) $0 = 0x05026ac0 [mscorlib]System.OutOfMemoryException:.ctor() + +## SERIALIZATION + +Mono's XML serialization engine by default will use a reflection-based +approach to serialize which might be slow for continuous processing (web +service applications). The serialization engine will determine when a +class must use a hand-tuned serializer based on a few parameters and if +needed it will produce a customized C# serializer for your types at +runtime. This customized serializer then gets dynamically loaded into +your application. + +You can control this with the MONO_XMLSERIALIZER_THS environment +variable. + +The possible values are **\`no'** to disable the use of a C# customized +serializer, or an integer that is the minimum number of uses before the +runtime will produce a custom serializer (0 will produce a custom +serializer on the first access, 50 will produce a serializer on the 50th +use). Mono will fallback to an interpreted serializer if the serializer +generation somehow fails. This behavior can be disabled by setting the +option **\`nofallback'** (for example: +MONO_XMLSERIALIZER_THS=0,nofallback). + +## ENVIRONMENT VARIABLES + +**GC_DONT_GC** +Turns off the garbage collection in Mono. This should be only used for +debugging purposes + +**HTTP_PROXY** +(Also **http_proxy**) If set, web requests using the Mono Class Library +will be automatically proxied through the given URL. Not supported on +Windows, Mac OS, iOS or Android. See also **NO_PROXY**. + +**LLVM_COUNT** +When Mono is compiled with LLVM support, this instructs the runtime to +stop using LLVM after the specified number of methods are JITed. This is +a tool used in diagnostics to help isolate problems in the code +generation backend. For example **LLVM_COUNT=10** would only compile 10 +methods with LLVM and then switch to the Mono JIT engine. +**LLVM_COUNT=0** would disable the LLVM engine altogether. + +**MONO_ASPNET_INHIBIT_SETTINGSMAP** +Mono contains a feature which allows modifying settings in the .config +files shipped with Mono by using config section mappers. The mappers and +the mapping rules are defined in the \$prefix/etc/mono/2.0/settings.map +file and, optionally, in the settings.map file found in the top-level +directory of your ASP.NET application. Both files are read by System.Web +on application startup, if they are found at the above locations. If you +don't want the mapping to be performed you can set this variable in your +environment before starting the application and no action will be taken. + +**MONO_ASPNET_WEBCONFIG_CACHESIZE** +Mono has a cache of ConfigSection objects for speeding up +WebConfigurationManager queries. Its default size is 100 items, and when +more items are needed, cache evictions start happening. If evictions are +too frequent this could impose unnecessary overhead, which could be +avoided by using this environment variable to set up a higher cache size +(or to lower memory requirements by decreasing it). + +**MONO_CAIRO_DEBUG_DISPOSE** +If set, causes Mono.Cairo to collect stack traces when objects are +allocated, so that the finalization/Dispose warnings include information +about the instance's origin. + +**MONO_CFG_DIR** +If set, this variable overrides the default system configuration +directory (\$PREFIX/etc). It's used to locate machine.config file. + +**MONO_COM** +Sets the style of COM interop. If the value of this variable is "MS" +Mono will use string marhsalling routines from the liboleaut32 for the +BSTR type library, any other values will use the mono-builtin BSTR +string marshalling. + +**MONO_CONFIG** +If set, this variable overrides the default runtime configuration file +(\$PREFIX/etc/mono/config). The --config command line options overrides +the environment variable. + +**MONO_CPU_ARCH** +Override the automatic cpu detection mechanism. Currently used only on +arm. The format of the value is as follows: + + + + + "armvV [thumb[2]]" + +where V is the architecture number 4, 5, 6, 7 and the options can be +currently be "thumb" or "thumb2". Example: + + + MONO_CPU_ARCH="armv4 thumb" mono ... + +**MONO_ARM_FORCE_SOFT_FLOAT** +When Mono is built with a soft float fallback on ARM and this variable +is set to "1", Mono will always emit soft float code, even if a VFP unit +is detected. + +**MONO_DARWIN_USE_KQUEUE_FSW** +Fall back on the kqueue FileSystemWatcher implementation in Darwin. The +default is the FSEvent implementation. + +**MONO_DARWIN_WATCHER_MAXFDS** +This is a debugging aid used to force limits on the kqueue +FileSystemWatcher implementation in Darwin. There is no limit by +default. + +**MONO_DISABLE_MANAGED_COLLATION** +If this environment variable is \`yes', the runtime uses unmanaged +collation (which actually means no culture-sensitive collation). It +internally disables managed collation functionality invoked via the +members of System.Globalization.CompareInfo class. Collation is enabled +by default. + +**MONO_DISABLE_SHARED_AREA** +Unix only: If set, disable usage of shared memory for exposing +performance counters. This means it will not be possible to both +externally read performance counters from this processes or read those +of external processes. + +**MONO_DNS** +When set, enables the use of a fully managed DNS resolver instead of the +regular libc functions. This resolver performs much better when multiple +queries are run in parallel. + +Note that /etc/nsswitch.conf will be ignored. + +**MONO_EGD_SOCKET** +For platforms that do not otherwise have a way of obtaining random bytes +this can be set to the name of a file system socket on which an egd or +prngd daemon is listening. + +**MONO_ENABLE_AIO** +If set, tells mono to attempt using native asynchronous I/O services. If +not set, a default select/poll implementation is used. Currently epoll +and kqueue are supported. + +**MONO_THREADS_SUSPEND** Selects a mechanism that Mono will use to suspend +threads. May be set to "preemptive", "coop", or "hybrid". Threads may +need to be suspended by the debugger, or using some .NET threading APIs, +and most commonly when the SGen garbage collector needs to stop all +threads during a critical phase of garbage collection. Preemptive mode +is the mode that Mono has used historically, going back to the Boehm +days, where the garbage collector would run at any point and suspend +execution of all threads as required to perform a garbage collection. +The cooperative mode on the other hand requires the cooperation of all +threads to stop at a safe point. This makes for an easier to debug +garbage collector and it improves the stability of the runtime because +threads are not suspended when accessing critical resources. In +scenarios where Mono is embedded in another application, cooperative +suspend requires the embedder code to follow coding guidelines in order +to cooperate with the garbage collector. Cooperative suspend in embedded +Mono is currently experimental. Hybrid mode is a combination of the two +that retains better compatability with scenarios where Mono is embedded +in another application: threads that are running managed code or code +that comprises the Mono runtime will be cooperatively suspended, while +threads running embedder code will be preemptively suspended. Hybrid +suspend is the default on some desktop platforms. + +Alternatively, coop and hybrid mode can be enabled at compile time by +using the --enable-cooperative-suspend or --enable-hybrid-suspend flags, +respectively, when calling configure. The **MONO_THREADS_SUSPEND** +environment variable takes priority over the compiled default. + +**MONO_ENABLE_COOP_SUSPEND** +This environment variable is obsolete, but retained for backward +compatibility. Use **MONO_THREADS_SUSPEND** set to "coop" instead. Note +that if configure flags were provided to enable cooperative or hybrid +suspend, this variable is ignored. + +**MONO_ENV_OPTIONS** +This environment variable allows you to pass command line arguments to a +Mono process through the environment. This is useful for example to +force all of your Mono processes to use LLVM or SGEN without having to +modify any launch scripts. + +**MONO_SDB_ENV_OPTIONS** +Used to pass extra options to the debugger agent in the runtime, as they +were passed using --debugger-agent=. + +**MONO_EVENTLOG_TYPE** +Sets the type of event log provider to use (for +System.Diagnostics.EventLog). + +Possible values are: + +> *local\[:path\]* +> +> Persists event logs and entries to the local file system. +> +> The directory in which to persist the event logs, event sources and +> entries can be specified as part of the value. +> +> If the path is not explicitly set, it defaults to +> "/var/lib/mono/eventlog" on unix and "%APPDATA%no\ventlog" on Windows. +> +> *win32* +> +> **Uses the native win32 API to write events and registers event logs +> and** event sources in the registry. This is only available on +> Windows. +> +> On Unix, the directory permission for individual event log and event +> source directories is set to 777 (with +t bit) allowing everyone to +> read and write event log entries while only allowing entries to be +> deleted by the user(s) that created them. +> +> *null* +> +> Silently discards any events. +> +> The default is "null" on Unix (and versions of Windows before NT), and +> "win32" on Windows NT (and higher). + +**MONO_EXTERNAL_ENCODINGS** +If set, contains a colon-separated list of text encodings to try when +turning externally-generated text (e.g. command-line arguments or +filenames) into Unicode. The encoding names come from the list provided +by iconv, and the special case "default_locale" which refers to the +current locale's default encoding. + +When reading externally-generated text strings UTF-8 is tried first, and +then this list is tried in order with the first successful conversion +ending the search. When writing external text (e.g. new filenames or +arguments to new processes) the first item in this list is used, or +UTF-8 if the environment variable is not set. + +The problem with using MONO_EXTERNAL_ENCODINGS to process your files is +that it results in a problem: although its possible to get the right +file name it is not necessarily possible to open the file. In general if +you have problems with encodings in your filenames you should use the +"convmv" program. + +**MONO_GC_PARAMS** +When using Mono with the SGen garbage collector this variable controls +several parameters of the collector. The variable's value is a comma +separated list of words. + +**max-heap-size=***size* +Sets the maximum size of the heap. The size is specified in bytes and +must be a power of two. The suffixes \`k', \`m' and \`g' can be used to +specify kilo-, mega- and gigabytes, respectively. The limit is the sum +of the nursery, major heap and large object heap. Once the limit is +reached the application will receive OutOfMemoryExceptions when trying +to allocate. Not the full extent of memory set in max-heap-size could be +available to satisfy a single allocation due to internal fragmentation. +By default heap limits is disabled and the GC will try to use all +available memory. + +**nursery-size=***size* +Sets the size of the nursery. The size is specified in bytes and must be +a power of two. The suffixes \`k', \`m' and \`g' can be used to specify +kilo-, mega- and gigabytes, respectively. The nursery is the first +generation (of two). A larger nursery will usually speed up the program +but will obviously use more memory. The default nursery size 4 MB. + +**major=***collector* +Specifies which major collector to use. Options are \`marksweep' for the +Mark&Sweep collector, \`marksweep-conc' for concurrent Mark&Sweep and +\`marksweep-conc-par' for parallel and concurrent Mark&Sweep. The +concurrent Mark&Sweep collector is the default. + +**mode=balanced\|throughput\|pause**\[:*max-pause*\] +Specifies what should be the garbage collector's target. The +\`throughput' mode aims to reduce time spent in the garbage collector +and improve application speed, the \`pause' mode aims to keep pause +times to a minimum and it receives the argument *max-pause* which +specifies the maximum pause time in milliseconds that is acceptable and +the \`balanced' mode which is a general purpose optimal mode. + +**soft-heap-limit=***size* +Once the heap size gets larger than this size, ignore what the default +major collection trigger metric says and only allow four nursery size's +of major heap growth between major collections. + +**evacuation-threshold=***threshold* +Sets the evacuation threshold in percent. This option is only available +on the Mark&Sweep major collectors. The value must be an integer in the +range 0 to 100. The default is 66. If the sweep phase of the collection +finds that the occupancy of a specific heap block type is less than this +percentage, it will do a copying collection for that block type in the +next major collection, thereby restoring occupancy to close to 100 +percent. A value of 0 turns evacuation off. + +**(no-)lazy-sweep** +Enables or disables lazy sweep for the Mark&Sweep collector. If enabled, +the sweeping of individual major heap blocks is done piecemeal whenever +the need arises, typically during nursery collections. Lazy sweeping is +enabled by default. + +**(no-)concurrent-sweep** +Enables or disables concurrent sweep for the Mark&Sweep collector. If +enabled, the iteration of all major blocks to determine which ones can +be freed and which ones have to be kept and swept, is done concurrently +with the running program. Concurrent sweeping is enabled by default. + +**stack-mark=***mark-mode* +Specifies how application threads should be scanned. Options are +\`precise\` and \`conservative\`. Precise marking allow the collector to +know what values on stack are references and what are not. Conservative +marking threats all values as potentially references and leave them +untouched. Precise marking reduces floating garbage and can speed up +nursery collection and allocation rate, it has the downside of requiring +a significant extra memory per compiled method. The right option, +unfortunately, requires experimentation. + +**save-target-ratio=***ratio* +Specifies the target save ratio for the major collector. The collector +lets a given amount of memory to be promoted from the nursery due to +minor collections before it triggers a major collection. This amount is +based on how much memory it expects to free. It is represented as a +ratio of the size of the heap after a major collection. Valid values are +between 0.1 and 2.0. The default is 0.5. Smaller values will keep the +major heap size smaller but will trigger more major collections. +Likewise, bigger values will use more memory and result in less frequent +major collections. This option is EXPERIMENTAL, so it might disappear in +later versions of mono. + +**default-allowance-ratio=***ratio* +Specifies the default allocation allowance when the calculated size is +too small. The allocation allowance is how much memory the collector let +be promoted before triggered a major collection. It is a ratio of the +nursery size. Valid values are between 1.0 and 10.0. The default is 4.0. +Smaller values lead to smaller heaps and more frequent major +collections. Likewise, bigger values will allow the heap to grow faster +but use more memory when it reaches a stable size. This option is +EXPERIMENTAL, so it might disappear in later versions of mono. + +**minor=***minor-collector* +Specifies which minor collector to use. Options are \`simple' which +promotes all objects from the nursery directly to the old generation, +\`simple-par' which has same promotion behavior as \`simple' but using +multiple workers and \`split' which lets objects stay longer on the +nursery before promoting. + +**alloc-ratio=***ratio* +Specifies the ratio of memory from the nursery to be use by the alloc +space. This only can only be used with the split minor collector. Valid +values are integers between 1 and 100. Default is 60. + +**promotion-age=***age* +Specifies the required age of an object must reach inside the nursery +before been promoted to the old generation. This only can only be used +with the split minor collector. Valid values are integers between 1 +and 14. Default is 2. + +**(no-)cementing** +Enables or disables cementing. This can dramatically shorten nursery +collection times on some benchmarks where pinned objects are referred to +from the major heap. + +**allow-synchronous-major** +This forbids the major collector from performing synchronous major +collections. The major collector might want to do a synchronous +collection due to excessive fragmentation. Disabling this might trigger +OutOfMemory error in situations that would otherwise not happen. + +**MONO_GC_DEBUG** +When using Mono with the SGen garbage collector this environment +variable can be used to turn on various debugging features of the +collector. The value of this variable is a comma separated list of +words. Do not use these options in production. + +*number* +Sets the debug level to the specified number. + +**print-allowance** +After each major collection prints memory consumption for before and +after the collection and the allowance for the minor collector, i.e. how +much the heap is allowed to grow from minor collections before the next +major collection is triggered. + +**print-pinning** +Gathers statistics on the classes whose objects are pinned in the +nursery and for which global remset entries are added. Prints those +statistics when shutting down. + +**collect-before-allocs** +**check-remset-consistency** +This performs a remset consistency check at various opportunities, and +also clears the nursery at collection time, instead of the default, when +buffers are allocated (clear-at-gc). The consistency check ensures that +there are no major to minor references that are not on the remembered +sets. + +**mod-union-consistency-check** +Checks that the mod-union cardtable is consistent before each finishing +major collection pause. This check is only applicable to concurrent +major collectors. + +**check-mark-bits** +Checks that mark bits in the major heap are consistent at the end of +each major collection. Consistent mark bits mean that if an object is +marked, all objects that it had references to must also be marked. + +**check-nursery-untag** +After garbage collections, check whether all vtable pointers are no +longer tagged. + +**xdomain-checks** +Performs a check to make sure that no references are left to an unloaded +AppDomain. + +**clear-at-tlab-creation** +Clears the nursery incrementally when the thread local allocation +buffers (TLAB) are created. The default setting clears the whole nursery +at GC time. + +**debug-clear-at-tlab-creation** +Clears the nursery incrementally when the thread local allocation +buffers (TLAB) are created, but at GC time fills it with the byte +\`0xff\`, which should result in a crash more quickly if +\`clear-at-tlab-creation\` doesn't work properly. + +**clear-at-gc** +This clears the nursery at GC time instead of doing it when the thread +local allocation buffer (TLAB) is created. The default is to clear the +nursery at TLAB creation time. + +**disable-minor** +Don't do minor collections. If the nursery is full, a major collection +is triggered instead, unless it, too, is disabled. + +**disable-major** +Don't do major collections. + +**conservative-stack-mark** +Forces the GC to scan the stack conservatively, even if precise scanning +is available. + +**no-managed-allocator** +Disables the managed allocator. + +**managed-allocator** +Enables the managed allocator. + +**check-scan-starts** +If set, does a plausibility check on the scan_starts before and after +each collection + +**verify-nursery-at-minor-gc** +If set, does a complete object walk of the nursery at the start of each +minor collection. + +**dump-nursery-at-minor-gc** +If set, dumps the contents of the nursery at the start of each minor +collection. Requires verify-nursery-at-minor-gc to be set. + +**heap-dump=***file* +Dumps the heap contents to the specified file. To visualize the +information, use the mono-heapviz tool. + +**binary-protocol=***file* +Outputs the debugging output to the specified file. For this to work, +Mono needs to be compiled with the BINARY_PROTOCOL define on sgen-gc.c. +You can then use this command to explore the output + + sgen-grep-binprot 0x1234 0x5678 < file + +**nursery-canaries** +If set, objects allocated in the nursery are suffixed with a canary +(guard) word, which is checked on each minor collection. Can be used to +detect/debug heap corruption issues. This disables the usage of the +managed allocator, because allocation from full aot code is inconsistent +with this option. If the application is guaranteed not to use aot code, +the managed allocator can be enabled back with managed-allocator option. + +**do-not-finalize(=***classes***)** +If enabled, finalizers will not be run. Everything else will be +unaffected: finalizable objects will still be put into the finalization +queue where they survive until they're scheduled to finalize. Once +they're not in the queue anymore they will be collected regularly. If a +list of comma-separated class names is given, only objects from those +classes will not be finalized. + +**log-finalizers** +Log verbosely around the finalization process to aid debugging. + +**MONO_GAC_PREFIX** +Provides a prefix the runtime uses to look for Global Assembly Caches. +Directories are separated by the platform path separator (colons on +unix). MONO_GAC_PREFIX should point to the top directory of a prefixed +install. Or to the directory provided in the gacutil /gacdir command. +Example: **/home/username/.mono:/usr/local/mono/** + +**MONO_IOMAP** +(deprecated) Enabled some filename rewriting support to assist +badly-written applications that hard-code Windows paths. It no longer +works as of Mono 6.0. + +**MONO_LLVM** +When Mono is using the LLVM code generation backend you can use this +environment variable to pass code generation options to the LLVM +compiler. + +**MONO_MANAGED_WATCHER** +If set to "disabled", System.IO.FileSystemWatcher will use a file +watcher implementation which silently ignores all the watching requests. +If set to any other value, System.IO.FileSystemWatcher will use the +default managed implementation (slow). If unset, mono will try to use +inotify, FAM, Gamin, kevent under Unix systems and native API calls on +Windows, falling back to the managed implementation on error. + +**MONO_MESSAGING_PROVIDER** +Mono supports a plugin model for its implementation of System.Messaging +making it possible to support a variety of messaging implementations +(e.g. AMQP, ActiveMQ). To specify which messaging implementation is to +be used the evironement variable needs to be set to the full class name +for the provider. E.g. to use the RabbitMQ based AMQP implementation the +variable should be set to: + + Mono.Messaging.RabbitMQ.RabbitMQMessagingProvider,Mono.Messaging.RabbitMQ + MONO_NO_SMP + If set causes the mono process to be bound to a single processor. This may be + useful when debugging or working around race conditions. + MONO_NO_TLS + Disable inlining of thread local accesses. Try setting this if you get a segfault + early on in the execution of mono. + MONO_PATH + Provides a search path to the runtime where to look for library + files. This is a tool convenient for debugging applications, but + should not be used by deployed applications as it breaks the assembly + loader in subtle ways. + Directories are separated by the platform path separator (colons on unix). Example: + /home/username/lib:/usr/local/mono/lib + Relative paths are resolved based on the launch-time current directory. + Alternative solutions to MONO_PATH include: installing libraries into + the Global Assembly Cache (see gacutil(1)) or having the dependent + libraries side-by-side with the main executable. + For a complete description of recommended practices for application + deployment, see + http://www.mono-project.com/docs/getting-started/application-deployment/ + MONO_SHARED_DIR + If set its the directory where the ".wapi" handle state is stored. + This is the directory where the Windows I/O Emulation layer stores its + shared state data (files, events, mutexes, pipes). By default Mono + will store the ".wapi" directory in the users's home directory. + MONO_SHARED_HOSTNAME + Uses the string value of this variable as a replacement for the host name when + creating file names in the ".wapi" directory. This helps if the host name of + your machine is likely to be changed when a mono application is running or if + you have a .wapi directory shared among several different computers. + Mono typically uses the hostname to create the files that are used to + share state across multiple Mono processes. This is done to support + home directories that might be shared over the network. + MONO_STRICT_IO_EMULATION + If set, extra checks are made during IO operations. Currently, this + includes only advisory locks around file writes. + MONO_TLS_PROVIDER + This environment variable controls which TLS/SSL provider Mono will + use. The options are usually determined by the operating system where + Mono was compiled and the configuration options that were used for + it. + default + Uses the default TLS stack that the Mono runtime was configured with. + Usually this is configured to use Apple's SSL stack on Apple + platforms, and Boring SSL on other platforms. + apple + Forces the use of the Apple SSL stack, only works on Apple platforms. + btls + Forces the use of the BoringSSL stack. See + https://opensource.google.com/projects/boringssl for more information + about this stack. + legacy + This is the old Mono stack, which only supports SSL and TLS up to + version 1.0. It is deprecated and will be removed in the future. + MONO_TLS_SESSION_CACHE_TIMEOUT + The time, in seconds, that the SSL/TLS session cache will keep it's entry to + avoid a new negotiation between the client and a server. Negotiation are very + CPU intensive so an application-specific custom value may prove useful for + small embedded systems. + The default is 180 seconds. + MONO_THREADS_PER_CPU + The minimum number of threads in the general threadpool will be + MONO_THREADS_PER_CPU * number of CPUs. The default value for this + variable is 1. + MONO_XMLSERIALIZER_THS + Controls the threshold for the XmlSerializer to produce a custom + serializer for a given class instead of using the Reflection-based + interpreter. The possible values are `no' to disable the use of a + custom serializer or a number to indicate when the XmlSerializer + should start serializing. The default value is 50, which means that + the a custom serializer will be produced on the 50th use. + MONO_X509_REVOCATION_MODE + Sets the revocation mode used when validating a X509 certificate chain (https, + ftps, smtps...). The default is 'nocheck', which performs no revocation check + at all. The other possible values are 'offline', which performs CRL check (not + implemented yet) and 'online' which uses OCSP and CRL to verify the revocation + status (not implemented yet). + NO_PROXY + (Also no_proxy) If both HTTP_PROXY and NO_PROXY are + set, NO_PROXY will be treated as a comma-separated list of "bypass" domains + which will not be sent through the proxy. Domains in NO_PROXY may contain + wildcards, as in "*.mono-project.com" or "build????.local". Not supported on + Windows, Mac OS, iOS or Android. + +## ENVIRONMENT VARIABLES FOR DEBUGGING + +**MONO_ASPNET_NODELETE** +If set to any value, temporary source files generated by ASP.NET support +classes will not be removed. They will be kept in the user's temporary +directory. + +**MONO_DEBUG** +If set, enables some features of the runtime useful for debugging. This +variable should contain a comma separated list of debugging options. +Currently, the following options are supported: + +**align-small-structs** +Enables small structs alignment to 4/8 bytes. + +**arm-use-fallback-tls** +When this option is set on ARM, a fallback thread local store will be +used instead of the default fast thread local storage primitives. + +**break-on-unverified** +If this variable is set, when the Mono VM runs into a verification +problem, instead of throwing an exception it will break into the +debugger. This is useful when debugging verifier problems + +**casts** +This option can be used to get more detailed information from +InvalidCast exceptions, it will provide information about the types +involved. + +**check-pinvoke-callconv** +This option causes the runtime to check for calling convention +mismatches when using pinvoke, i.e. mixing cdecl/stdcall. It only works +on windows. If a mismatch is detected, an ExecutionEngineException is +thrown. + +**collect-pagefault-stats** +Collects information about pagefaults. This is used internally to track +the number of page faults produced to load metadata. To display this +information you must use this option with "--stats" command line option. + +**debug-domain-unload** +When this option is set, the runtime will invalidate the domain memory +pool instead of destroying it. + +**disable_omit_fp** +Disables a compiler optimization where the frame pointer is omitted from +the stack. This optimization can interact badly with debuggers. + +**dont-free-domains** +This is an Optimization for multi-AppDomain applications (most commonly +ASP.NET applications). Due to internal limitations Mono, Mono by default +does not use typed allocations on multi-appDomain applications as they +could leak memory when a domain is unloaded. + +Although this is a fine default, for applications that use more than on +AppDomain heavily (for example, ASP.NET applications) it is worth +trading off the small leaks for the increased performance (additionally, +since ASP.NET applications are not likely going to unload the +application domains on production systems, it is worth using this +feature). + +**dyn-runtime-invoke** +Instructs the runtime to try to use a generic runtime-invoke wrapper +instead of creating one invoke wrapper. + +**explicit-null-checks** +Makes the JIT generate an explicit NULL check on variable dereferences +instead of depending on the operating system to raise a SIGSEGV or +another form of trap event when an invalid memory location is accessed. + +**gdb** +Equivalent to setting the **MONO_XDEBUG** variable, this emits symbols +into a shared library as the code is JITed that can be loaded into GDB +to inspect symbols. + +**gen-seq-points** +Automatically generates sequence points where the IL stack is empty. +These are places where the debugger can set a breakpoint. + +**llvm-disable-implicit-null-checks** +Makes the LLVM backend use explicit NULL checks on variable dereferences +instead of depending on operating system support for signals or traps +when an invalid memory location is accessed. Unconditionally enabled by +explicit-null-checks. + +**no-compact-seq-points** +Unless the option is used, the runtime generates sequence points data +that maps native offsets to IL offsets. Sequence point data is used to +display IL offset in stacktraces. Stacktraces with IL offsets can be +symbolicated using mono-symbolicate tool. + +**handle-sigint** +Captures the interrupt signal (Control-C) and displays a stack trace +when pressed. Useful to find out where the program is executing at a +given point. This only displays the stack trace of a single thread. + +**init-stacks** +Instructs the runtime to initialize the stack with some known values +(0x2a on x86-64) at the start of a method to assist in debuggin the JIT +engine. + +**keep-delegates** +This option will leak delegate trampolines that are no longer referenced +as to present the user with more information about a delegate misuse. +Basically a delegate instance might be created, passed to unmanaged +code, and no references kept in managed code, which will garbage collect +the code. With this option it is possible to track down the source of +the problems. + +**no-gdb-backtrace** +This option will disable the GDB backtrace emitted by the runtime after +a SIGSEGV or SIGABRT in unmanaged code. + +**partial-sharing** +When this option is set, the runtime can share generated code between +generic types effectively reducing the amount of code generated. + +**reverse-pinvoke-exceptions** +This option will cause mono to abort with a descriptive message when +during stack unwinding after an exception it reaches a native stack +frame. This happens when a managed delegate is passed to native code, +and the managed delegate throws an exception. Mono will normally try to +unwind the stack to the first (managed) exception handler, and it will +skip any native stack frames in the process. This leads to undefined +behaviour (since mono doesn't know how to process native frames), leaks, +and possibly crashes too. + +**single-imm-size** +This guarantees that each time managed code is compiled the same +instructions and registers are used, regardless of the size of used +values. + +**soft-breakpoints** +This option allows using single-steps and breakpoints in hardware where +we cannot do it with signals. + +**suspend-on-native-crash** +This option will suspend the program when a native crash occurs +(SIGSEGV, SIGILL, ...). This is useful for debugging crashes which do +not happen under gdb, since a live process contains more information +than a core file. + +**suspend-on-sigsegv** +Same as **suspend-on-native-crash**. + +**suspend-on-exception** +This option will suspend the program when an exception occurs. + +**suspend-on-unhandled** +This option will suspend the program when an unhandled exception occurs. + +**thread-dump-dir=DIR** +Use DIR for storage thread dumps created by SIGQUIT. + +**weak-memory-model** +Don't enforce the CLR memory model on platforms with weak memory models. +This can introduce random crashes in some rare cases, for multithreaded +environments. This can be used for a performance boost on applications +that are single threaded. + +**verbose-gdb** +Make gdb output on native crashes more verbose. + +**MONO_LOG_LEVEL** +The logging level, possible values are \`error', \`critical', +\`warning', \`message', \`info' and \`debug'. See the DEBUGGING section +for more details. + +**MONO_LOG_MASK** +Controls the domain of the Mono runtime that logging will apply to. If +set, the log mask is changed to the set value. Possible values are "asm" +(assembly loader), "type", "dll" (native library loader), "gc" (garbage +collector), "cfg" (config file loader), "aot" (precompiler), "security" +(e.g. Moonlight CoreCLR support) and "all". The default value is "all". +Changing the mask value allows you to display only messages for a +certain component. You can use multiple masks by comma separating them. +For example to see config file messages and assembly loader messages set +you mask to "asm,cfg". + +**MONO_LOG_DEST** +Controls where trace log messages are written. If not set then the +messages go to stdout. If set, the string either specifies a path to a +file that will have messages appended to it, or the string "syslog" in +which case the messages will be written to the system log. Under +Windows, this is simulated by writing to a file called "mono.log". +**MONO_LOG_HEADER** Controls whether trace log messages not directed to +syslog have the id, timestamp, and pid as the prefix to the log message. +To enable a header this environment variable need just be non-null. + +**MONO_TRACE** +Used for runtime tracing of method calls. The format of the comma +separated trace options is: + + + + + [-]M:method name + [-]N:namespace + [-]T:class name + [-]all + [-]program + disabled Trace output off upon start. + +You can toggle trace output on/off sending a SIGUSR2 signal to the +program. + +**MONO_TRACE_LISTENER** +If set, enables the System.Diagnostics.DefaultTraceListener, which will +print the output of the System.Diagnostics Trace and Debug classes. It +can be set to a filename, and to Console.Out or Console.Error to display +output to standard output or standard error, respectively. If it's set +to Console.Out or Console.Error you can append an optional prefix that +will be used when writing messages like this: +Console.Error:MyProgramName. See the +System.Diagnostics.DefaultTraceListener documentation for more +information. + +**MONO_WCF_TRACE** +This eases WCF diagnostics functionality by simply outputs all log +messages from WCF engine to "stdout", "stderr" or any file passed to +this environment variable. The log format is the same as usual +diagnostic output. + +**MONO_XEXCEPTIONS** +This throws an exception when a X11 error is encountered; by default a +message is displayed but execution continues + +**MONO_XMLSERIALIZER_DEBUG** +Set this value to 1 to prevent the serializer from removing the +temporary files that are created for fast serialization; This might be +useful when debugging. + +**MONO_XSYNC** +This is used in the System.Windows.Forms implementation when running +with the X11 backend. This is used to debug problems in Windows.Forms as +it forces all of the commands send to X11 server to be done +synchronously. The default mode of operation is asynchronous which makes +it hard to isolate the root of certain problems. + +**MONO_XDEBUG** +When the the MONO_XDEBUG env var is set, debugging info for JITted code +is emitted into a shared library, loadable into gdb. This enables, for +example, to see managed frame names on gdb backtraces. + +**MONO_VERBOSE_METHOD** +Enables the maximum JIT verbosity for the specified method. This is very +helpfull to diagnose a miscompilation problems of a specific method. +This can be a semicolon-separated list of method names to match. If the +name is simple, this applies to any method with that name, otherwise you +can use a mono method description (see the section METHOD DESCRIPTIONS). + +**MONO_JIT_DUMP_METHOD** +Enables sending of the JITs intermediate representation for a specified +method to the IdealGraphVisualizer tool. + +**MONO_VERBOSE_HWCAP** +If set, makes the JIT output information about detected CPU features +(such as SSE, CMOV, FCMOV, etc) to stdout. + +**MONO_CONSERVATIVE_HWCAP** +If set, the JIT will not perform any hardware capability detection. This +may be useful to pinpoint the cause of JIT issues. This is the default +when Mono is built as an AOT cross compiler, so that the generated code +will run on most hardware. + +**MONO_PROFILE** +Equivalent to **--profile** argument. + +## VALGRIND + +If you want to use Valgrind, you will find the file \`mono.supp' useful, +it contains the suppressions for the GC which trigger incorrect +warnings. Use it like this: + + valgrind --suppressions=mono.supp mono ... + +## DTRACE + +On some platforms, Mono can expose a set of DTrace probes (also known as +user-land statically defined, USDT Probes). + +They are defined in the file \`mono.d'. +**ves-init-begin, ves-init-end** + +Begin and end of runtime initialization. + +**method-compile-begin, method-compile-end** + +Begin and end of method compilation. The probe arguments are class name, +method name and signature, and in case of method-compile-end success or +failure of compilation. + +**gc-begin, gc-end** + +Begin and end of Garbage Collection. + +To verify the availability of the probes, run: + dtrace -P mono'$target' -l -c mono + +## PERMISSIONS + +Mono's Ping implementation for detecting network reachability can create +the ICMP packets itself without requiring the system ping command to do +the work. If you want to enable this on Linux for non-root users, you +need to give the Mono binary special permissions. + +As root, run this command: + + # setcap cap_net_raw=+ep /usr/bin/mono + +## FILES + +On Unix assemblies are loaded from the installation lib directory. If +you set \`prefix' to /usr, the assemblies will be located in /usr/lib. +On Windows, the assemblies are loaded from the directory where mono and +mint live. + +**~/.mono/aot-cache** + +The directory for the ahead-of-time compiler demand creation assemblies +are located. + +**/etc/mono/config, ~/.mono/config** + +Mono runtime configuration file. See the mono-config(5) manual page for +more information. + +**~/.config/.mono/certs, /usr/share/.mono/certs** + +Contains Mono certificate stores for users / machine. See the certmgr(1) +manual page for more information on managing certificate stores and the +mozroots(1) page for information on how to import the Mozilla root +certificates into the Mono certificate store. + +**~/.mono/assemblies/ASSEMBLY/ASSEMBLY.config** + +Files in this directory allow a user to customize the configuration for +a given system assembly, the format is the one described in the +mono-config(5) page. + +**~/.config/.mono/keypairs, /usr/share/.mono/keypairs** + +Contains Mono cryptographic keypairs for users / machine. They can be +accessed by using a CspParameters object with DSACryptoServiceProvider +and RSACryptoServiceProvider classes. + +**~/.config/.isolatedstorage, ~/.local/share/.isolatedstorage, /usr/share/.isolatedstorage** + +Contains Mono isolated storage for non-roaming users, roaming users and +local machine. Isolated storage can be accessed using the classes from +the System.IO.IsolatedStorage namespace. + +**\.config** + +Configuration information for individual assemblies is loaded by the +runtime from side-by-side files with the .config files, see the +http://www.mono-project.com/Config for more information. + +**Web.config, web.config** + +ASP.NET applications are configured through these files, the +configuration is done on a per-directory basis. For more information on +this subject see the http://www.mono-project.com/Config_system.web page. + +## MAILING LISTS + +Mailing lists are listed at the +http://www.mono-project.com/community/help/mailing-lists/ + +## WEB SITE + +http://www.mono-project.com + +## SEE ALSO + +**certmgr**(1), **cert-sync**(1), **csharp**(1), **gacutil**(1), +**mcs**(1), **monodis**(1), **mono-config**(5), **mono-profilers**(1), +**mprof-report**(1), **pdb2mdb**(1), **xsp**(1), **mod_mono**(8) + +For more information on AOT: +http://www.mono-project.com/docs/advanced/aot/ + +For ASP.NET-related documentation, see the xsp(1) manual page From 889f5161942bfe4c91d87681aabb740a6af2df78 Mon Sep 17 00:00:00 2001 From: Brian Robbins Date: Wed, 1 May 2024 08:19:42 -0700 Subject: [PATCH 205/248] Remove perfinfo-%pid.map (#101697) * Remove perfinfo-%pid.map. It is no longer needed now that jitdump and r2rmap functionality exists. * Remove perfinfo.h from CMakeLists.txt. --------- Co-authored-by: Brian Robbins --- src/coreclr/vm/CMakeLists.txt | 2 - src/coreclr/vm/domainassembly.cpp | 9 -- src/coreclr/vm/perfinfo.cpp | 132 ------------------------------ src/coreclr/vm/perfinfo.h | 39 --------- src/coreclr/vm/perfmap.cpp | 45 ---------- src/coreclr/vm/perfmap.h | 11 --- 6 files changed, 238 deletions(-) delete mode 100644 src/coreclr/vm/perfinfo.cpp delete mode 100644 src/coreclr/vm/perfinfo.h diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 220e2684a0d7af..f60713ef587e1c 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -103,7 +103,6 @@ set(VM_SOURCES_DAC_AND_WKS_COMMON peassembly.cpp peimage.cpp perfmap.cpp - perfinfo.cpp pgo.cpp precode.cpp prestub.cpp @@ -206,7 +205,6 @@ set(VM_HEADERS_DAC_AND_WKS_COMMON peimagelayout.h peimagelayout.inl perfmap.h - perfinfo.h pgo.h precode.h rejit.h diff --git a/src/coreclr/vm/domainassembly.cpp b/src/coreclr/vm/domainassembly.cpp index ead21d61193433..75995f477a32f3 100644 --- a/src/coreclr/vm/domainassembly.cpp +++ b/src/coreclr/vm/domainassembly.cpp @@ -23,10 +23,6 @@ #include "dllimportcallback.h" #include "peimagelayout.inl" -#ifdef FEATURE_PERFMAP -#include "perfmap.h" -#endif // FEATURE_PERFMAP - #ifndef DACCESS_COMPILE DomainAssembly::DomainAssembly(PEAssembly* pPEAssembly, LoaderAllocator* pLoaderAllocator) : m_pAssembly(NULL), @@ -558,11 +554,6 @@ void DomainAssembly::FinishLoad() // Set a bit to indicate that the module has been loaded in some domain, and therefore // typeloads can involve types from this module. (Used for candidate instantiations.) GetModule()->SetIsReadyForTypeLoad(); - -#ifdef FEATURE_PERFMAP - // Notify the perfmap of the IL image load. - PerfMap::LogImageLoad(m_pPEAssembly); -#endif } void DomainAssembly::Activate() diff --git a/src/coreclr/vm/perfinfo.cpp b/src/coreclr/vm/perfinfo.cpp deleted file mode 100644 index 98fc667661a504..00000000000000 --- a/src/coreclr/vm/perfinfo.cpp +++ /dev/null @@ -1,132 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// =========================================================================== -// File: perfinfo.cpp -// - -#include "common.h" - -#if defined(FEATURE_PERFMAP) && !defined(DACCESS_COMPILE) -#include "perfinfo.h" -#include "pal.h" - -PerfInfo::PerfInfo(int pid, const char* basePath) - : m_Stream(nullptr) -{ - LIMITED_METHOD_CONTRACT; - - SString path; - path.Printf("%s/perfinfo-%d.map", basePath, pid); - OpenFile(path); -} - -// Logs image loads into the process' perfinfo-%d.map file -void PerfInfo::LogImage(PEAssembly* pPEAssembly, CHAR* guid) -{ - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - MODE_PREEMPTIVE; - PRECONDITION(pPEAssembly != nullptr); - PRECONDITION(guid != nullptr); - } CONTRACTL_END; - - // Nothing to log if the assembly path isn't present. - SString path{ pPEAssembly->GetPath() }; - if (path.IsEmpty()) - { - return; - } - - SIZE_T baseAddr = 0; - if (pPEAssembly->IsReadyToRun()) - { - PEImageLayout *pLoadedLayout = pPEAssembly->GetLoadedLayout(); - if (pLoadedLayout) - { - baseAddr = (SIZE_T)pLoadedLayout->GetBase(); - } - } - - SString value; - value.Printf("%s%c%s%c%p", path.GetUTF8(), sDelimiter, guid, sDelimiter, baseAddr); - - SString command{ SString::Literal, "ImageLoad" }; - WriteLine(command, value); -} - -// Writes a command line, with "type" being the type of command, with "value" as the command's corresponding instructions/values. This is to be used to log specific information, e.g. LogImage -void PerfInfo::WriteLine(SString& type, SString& value) -{ - - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - MODE_PREEMPTIVE; - } CONTRACTL_END; - - if (m_Stream == nullptr) - { - return; - } - - SString line; - line.Printf("%s%c%s%c\n", - type.GetUTF8(), sDelimiter, value.GetUTF8(), sDelimiter); - - EX_TRY - { - const char* strLine = line.GetUTF8(); - ULONG inCount = line.GetCount(); - ULONG outCount; - - m_Stream->Write(strLine, inCount, &outCount); - - if (inCount != outCount) - { - // error encountered - } - } - EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); -} - -// Opens a file ready to be written in. -void PerfInfo::OpenFile(SString& path) -{ - STANDARD_VM_CONTRACT; - - m_Stream = new (nothrow) CFileStream(); - - if (m_Stream != nullptr) - { - HRESULT hr = m_Stream->OpenForWrite(path.GetUnicode()); - if (FAILED(hr)) - { - delete m_Stream; - m_Stream = nullptr; - } - } -} - -PerfInfo::~PerfInfo() -{ - LIMITED_METHOD_CONTRACT; - - delete m_Stream; - m_Stream = nullptr; -} - - -#endif - - - - - - - - - - diff --git a/src/coreclr/vm/perfinfo.h b/src/coreclr/vm/perfinfo.h deleted file mode 100644 index ce54cc19faee60..00000000000000 --- a/src/coreclr/vm/perfinfo.h +++ /dev/null @@ -1,39 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// =========================================================================== -// File: perfinfo.h -// - -#ifndef PERFINFO_H -#define PERFINFO_H - - -#include "sstring.h" -#include "fstream.h" - -/* - A perfinfo-%d.map is created for every process that is created with manage code, the %d - being repaced with the process ID. - Every line in the perfinfo-%d.map is a type and value, separated by sDelimiter character: type;value - type represents what the user might want to do with its given value. value has a format chosen by - the user for parsing later on. -*/ -class PerfInfo { -public: - PerfInfo(int pid, const char* basePath); - ~PerfInfo(); - void LogImage(PEAssembly* pPEAssembly, CHAR* guid); - -private: - CFileStream* m_Stream; - - const char sDelimiter = ';'; - - void OpenFile(SString& path); - - void WriteLine(SString& type, SString& value); - -}; - - -#endif diff --git a/src/coreclr/vm/perfmap.cpp b/src/coreclr/vm/perfmap.cpp index 9e553a975da0a7..2d823e546fca51 100644 --- a/src/coreclr/vm/perfmap.cpp +++ b/src/coreclr/vm/perfmap.cpp @@ -9,7 +9,6 @@ #if defined(FEATURE_PERFMAP) && !defined(DACCESS_COMPILE) #include #include "perfmap.h" -#include "perfinfo.h" #include "pal.h" @@ -113,7 +112,6 @@ void PerfMap::Enable(PerfMapType type, bool sendExisting) while (assemblyIterator.Next(pDomainAssembly.This())) { CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetAssembly(); - PerfMap::LogImageLoad(pAssembly->GetPEAssembly()); // PerfMap does not log R2R methods so only proceed if we are emitting jitdumps if (type == PerfMapType::ALL || type == PerfMapType::JITDUMP) @@ -204,7 +202,6 @@ PerfMap::PerfMap() // Initialize with no failures. m_ErrorEncountered = false; - m_PerfInfo = nullptr; } // Clean-up resources. @@ -214,9 +211,6 @@ PerfMap::~PerfMap() delete m_FileStream; m_FileStream = nullptr; - - delete m_PerfInfo; - m_PerfInfo = nullptr; } void PerfMap::OpenFileForPid(int pid, const char* basePath) @@ -226,8 +220,6 @@ void PerfMap::OpenFileForPid(int pid, const char* basePath) // Open the map file for writing. OpenFile(fullPath); - - m_PerfInfo = new PerfInfo(pid, basePath); } // Open the specified destination map file. @@ -281,43 +273,6 @@ void PerfMap::WriteLine(SString& line) EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); } -void PerfMap::LogImageLoad(PEAssembly * pPEAssembly) -{ - CrstHolder ch(&(s_csPerfMap)); - - if (s_enabled && s_Current != nullptr) - { - s_Current->LogImage(pPEAssembly); - } -} - -// Log an image load to the map. -void PerfMap::LogImage(PEAssembly * pPEAssembly) -{ - CONTRACTL{ - THROWS; - GC_NOTRIGGER; - MODE_PREEMPTIVE; - PRECONDITION(pPEAssembly != nullptr); - } CONTRACTL_END; - - - if (m_FileStream == nullptr || m_ErrorEncountered) - { - // A failure occurred, do not log. - return; - } - - EX_TRY - { - CHAR szSignature[GUID_STR_BUFFER_LEN]; - GetNativeImageSignature(pPEAssembly, szSignature, ARRAY_SIZE(szSignature)); - - m_PerfInfo->LogImage(pPEAssembly, szSignature); - } - EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); -} - void PerfMap::LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, PrepareCodeConfig *pConfig) { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/perfmap.h b/src/coreclr/vm/perfmap.h index ffc7f3228b2cfa..f6eb8cfc73831b 100644 --- a/src/coreclr/vm/perfmap.h +++ b/src/coreclr/vm/perfmap.h @@ -10,8 +10,6 @@ #include "fstream.h" #include "volatile.h" -class PerfInfo; - // Generates a perfmap file. class PerfMap { @@ -32,9 +30,6 @@ class PerfMap // The file stream to write the map to. CFileStream * m_FileStream; - // The perfinfo file to log images to. - PerfInfo * m_PerfInfo; - // Set to true if an error is encountered when writing to the file. bool m_ErrorEncountered; @@ -57,9 +52,6 @@ class PerfMap // Does the actual work to log a method to the map. void LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, const char *optimizationTier); - // Does the actual work to log an image - void LogImage(PEAssembly * pPEAssembly); - // Get the image signature and store it as a string. static void GetNativeImageSignature(PEAssembly * pPEAssembly, CHAR * pszSig, unsigned int nSigSize); @@ -87,9 +79,6 @@ class PerfMap static void Enable(PerfMapType type, bool sendExisting); - // Log a native image load to the map. - static void LogImageLoad(PEAssembly * pPEAssembly); - static void LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, PrepareCodeConfig *pConfig); // Log a pre-compiled method to the map. From 132725d3702d51d78b5f68b0501c5e5845921d04 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 10:31:15 -0500 Subject: [PATCH 206/248] [main] Update dependencies from dotnet/source-build-externals (#101718) * Update dependencies from https://github.com/dotnet/source-build-externals build 20240429.1 Microsoft.SourceBuild.Intermediate.source-build-externals From Version 9.0.0-alpha.1.24222.1 -> To Version 9.0.0-alpha.1.24229.1 * Update dependencies from https://github.com/dotnet/source-build-externals build 20240429.1 Microsoft.SourceBuild.Intermediate.source-build-externals From Version 9.0.0-alpha.1.24222.1 -> To Version 9.0.0-alpha.1.24229.1 --------- Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 9aaf65a3ca51a8..5deb91fa663263 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -85,9 +85,9 @@ - + https://github.com/dotnet/source-build-externals - 1223ec47c74e79d44950d429a36386de6c7bf9c8 + b02769661c9a51985877819e8bdebfbcbee65710 From 0d6868f5d9ac46e99dd85e552825831e39041a13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Wed, 1 May 2024 10:13:58 -0700 Subject: [PATCH 207/248] Bump pre-release version to 5 (#101468) --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 854ddc25ee07e2..b35035d520cded 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -11,7 +11,7 @@ 7.0.$([MSBuild]::Add($([System.Version]::Parse('$(PackageVersionNet8)').Build),14)) 6.0.$([MSBuild]::Add($([System.Version]::Parse('$(PackageVersionNet7)').Build),11)) preview - 4 + 5 false release From 9e678f64a3e5bd15258b854ad15df9cbb9b570b5 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Wed, 1 May 2024 10:22:47 -0700 Subject: [PATCH 208/248] Run MethodOutParameterDataFlow tests in analyzer (#101735) And add a testcase to cover IL2068. This just ensures that this particular testcase runs without allowMissingWarnings for the analyzer, and adds one more testcase to track the specific missing warning that was encountered in https://github.com/dotnet/runtime/issues/101203 (tracked in https://github.com/dotnet/runtime/issues/101734). --- .../DataFlowTests.cs | 6 +++++ .../DataFlowTests.g.cs | 6 ----- .../DataFlow/MethodOutParameterDataFlow.cs | 24 ++++++++++++------- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs index 3a95e6ea046cbd..7b52477a365e1c 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs @@ -289,6 +289,12 @@ public Task MemberTypesRelationships () return RunTest (nameof (MemberTypesRelationships)); } + [Fact] + public Task MethodOutParameterDataFlow () + { + return RunTest (); + } + [Fact] public Task MethodParametersDataFlow () { diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs index 5c3bd5a9d6654f..8f435261c79396 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs @@ -25,12 +25,6 @@ public Task MethodByRefParameterDataFlow () return RunTest (allowMissingWarnings: true); } - [Fact] - public Task MethodOutParameterDataFlow () - { - return RunTest (allowMissingWarnings: true); - } - [Fact] public Task StaticInterfaceMethodDataflow () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodOutParameterDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodOutParameterDataFlow.cs index 22f7bd5e8b1274..911f2f48ec0582 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodOutParameterDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodOutParameterDataFlow.cs @@ -19,6 +19,7 @@ public static void Main () TestInitializedReadFromOutParameter_PassedTwice (); TestUninitializedReadFromOutParameter (); TestInitializedReadFromOutParameter_MismatchOnOutput (); + TestInitializedReturnOutParameter_MismatchOnOutput (); TestInitializedReadFromOutParameter_MismatchOnOutput_PassedTwice (); TestInitializedReadFromOutParameter_MismatchOnInput (); TestInitializedReadFromOutParameter_MismatchOnInput_PassedTwice (); @@ -55,7 +56,7 @@ static void TestUninitializedReadFromOutParameter () typeWithMethods.RequiresPublicMethods (); } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2632")] static void TestInitializedReadFromOutParameter_MismatchOnOutput () { Type typeWithMethods = null; @@ -63,9 +64,18 @@ static void TestInitializedReadFromOutParameter_MismatchOnOutput () typeWithMethods.RequiresPublicFields (); } - // https://github.com/dotnet/linker/issues/2632 // This test should generate a warning since there's mismatch on annotations - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields))] + [ExpectedWarning ("IL2068", nameof (TryGetAnnotatedValue), nameof (DynamicallyAccessedMemberTypes.PublicFields), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2632")] + [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] + static Type TestInitializedReturnOutParameter_MismatchOnOutput () + { + Type typeWithMethods = null; + TryGetAnnotatedValue (out typeWithMethods); + return typeWithMethods; + } + + // This test should generate a warning since there's mismatch on annotations + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2632")] static void TestInitializedReadFromOutParameter_MismatchOnOutput_PassedTwice () { Type typeWithMethods = null; @@ -73,10 +83,9 @@ static void TestInitializedReadFromOutParameter_MismatchOnOutput_PassedTwice () typeWithMethods.RequiresPublicFields (); } - // https://github.com/dotnet/linker/issues/2632 // This warning should not be generated, the value of typeWithMethods should have PublicMethods // after the call with out parameter. - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Analyzer, "https://github.com/dotnet/linker/issues/2632")] static void TestInitializedReadFromOutParameter_MismatchOnInput () { Type typeWithMethods = GetTypeWithFields (); @@ -86,10 +95,9 @@ static void TestInitializedReadFromOutParameter_MismatchOnInput () } [ExpectedWarning ("IL2072", nameof (TryGetAnnotatedValueFromValue))] - // https://github.com/dotnet/linker/issues/2632 // This warning should not be generated, the value of typeWithMethods should have PublicMethods // after the call with out parameter. - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Analyzer, "https://github.com/dotnet/linker/issues/2632")] static void TestInitializedReadFromOutParameter_MismatchOnInput_PassedTwice () { Type typeWithMethods = GetTypeWithFields (); @@ -103,7 +111,7 @@ static void TestPassingOutParameter ([DynamicallyAccessedMembers (DynamicallyAcc TryGetAnnotatedValue (out typeWithMethods); } - [ExpectedWarning ("IL2067", "typeWithFields", nameof (TryGetAnnotatedValue))] + [ExpectedWarning ("IL2067", "typeWithFields", nameof (TryGetAnnotatedValue), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2632")] static void TestPassingOutParameter_Mismatch ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] out Type typeWithFields) { TryGetAnnotatedValue (out typeWithFields); From 5d0536142062ffe5d1222b02f4ef1943f878cb4a Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Wed, 1 May 2024 10:24:56 -0700 Subject: [PATCH 209/248] Track unknown value as result of unimplemented operations (#101752) Up until now, the analyzer has been set up to return `TopValue` for operations which are not handled by their own `Visit` overrides, to avoid producing warnings that are not produced from ILLink or ILC. This changes the default handling to return `UnknownValue.Instance`, so that such operations produce warnings if the return value flows into a location with dataflow requirements. Fixes https://github.com/dotnet/runtime/issues/101733, where the return value of a string interpolation operation (which doesn't have special handling in a `Visit` override) was not producing warnings when passed to `Type.GetType`. --- .../TrimAnalysis/TrimAnalysisVisitor.cs | 12 +++++++++--- .../ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs | 2 +- .../DynamicallyAccessedMembersAnalyzerTests.cs | 8 ++++++-- ...dlerDataFlow.cs => InterpolatedStringDataFlow.cs} | 12 +++++++++--- 4 files changed, 25 insertions(+), 9 deletions(-) rename src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/{InterpolatedStringHandlerDataFlow.cs => InterpolatedStringDataFlow.cs} (77%) diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs index c3aaa62d99ba97..2d9cb6cd84160d 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs @@ -75,16 +75,22 @@ public override void ApplyCondition (FeatureChecksValue featureChecksValue, ref // - 'this' parameter (for annotated methods) // - field reference - public override MultiValue Visit (IOperation? operation, StateValue argument) + public override MultiValue DefaultVisit (IOperation operation, StateValue argument) { - var returnValue = base.Visit (operation, argument); + var returnValue = base.DefaultVisit (operation, argument); // If the return value is empty (TopValue basically) and the Operation tree // reports it as having a constant value, use that as it will automatically cover // cases we don't need/want to handle. - if (operation != null && returnValue.IsEmpty () && TryGetConstantValue (operation, out var constValue)) + if (!returnValue.IsEmpty ()) + return returnValue; + + if (TryGetConstantValue (operation, out var constValue)) return constValue; + if (operation.Type is not null) + return UnknownValue.Instance; + return returnValue; } diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs index 7b52477a365e1c..c59afbfd8fd5f7 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs @@ -186,7 +186,7 @@ public Task InlineArrayDataflow () } [Fact] - public Task InterpolatedStringHandlerDataFlow () + public Task InterpolatedStringDataFlow () { return RunTest (); } diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs index a06c8115c31584..fccb0de0d95e35 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs @@ -1309,7 +1309,9 @@ public static void Main() return VerifyDynamicallyAccessedMembersAnalyzer (Source, consoleApplication: false, // (12,34): error CS0103: The name 'type' does not exist in the current context - DiagnosticResult.CompilerError ("CS0103").WithSpan (12, 34, 12, 38).WithArguments ("type")); + DiagnosticResult.CompilerError ("CS0103").WithSpan (12, 34, 12, 38).WithArguments ("type"), + // (12,34): warning IL2063: Value returned from method 'C.GetTypeWithAll()' can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements. + VerifyCS.Diagnostic (DiagnosticId.MethodReturnValueCannotBeStaticallyDetermined).WithSpan(12, 34, 12, 38).WithArguments("C.GetTypeWithAll()")); } [Fact] @@ -1333,7 +1335,9 @@ public static void Main() return VerifyDynamicallyAccessedMembersAnalyzer (Source, consoleApplication: false, // (8,22): error CS0103: The name 'type' does not exist in the current context - DiagnosticResult.CompilerError ("CS0103").WithSpan (8, 22, 8, 26).WithArguments ("type")); + DiagnosticResult.CompilerError ("CS0103").WithSpan (8, 22, 8, 26).WithArguments ("type"), + // (8,3): warning IL2064: Value assigned to C.fieldRequiresAll can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements. + VerifyCS.Diagnostic(DiagnosticId.FieldValueCannotBeStaticallyDetermined).WithSpan(8, 3, 8, 26).WithArguments("C.fieldRequiresAll")); } [Fact] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InterpolatedStringHandlerDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InterpolatedStringDataFlow.cs similarity index 77% rename from src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InterpolatedStringHandlerDataFlow.cs rename to src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InterpolatedStringDataFlow.cs index 6e30b600d736a5..f862348ddec336 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InterpolatedStringHandlerDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InterpolatedStringDataFlow.cs @@ -15,14 +15,15 @@ namespace Mono.Linker.Tests.Cases.DataFlow [ExpectedNoWarnings] [SkipKeptItemsValidation] [Define ("DEBUG")] - public class InterpolatedStringHandlerDataFlow + public class InterpolatedStringDataFlow { public static void Main () { - Test (); + TestInterpolatedStringHandler (); + TestUnknownInterpolatedString (); } - static void Test(bool b = true) { + static void TestInterpolatedStringHandler (bool b = true) { // Creates a control-flow graph for the analyzer that has an // IFlowCaptureReferenceOperation that represents a capture // because it is used as an out param (so has IsInitialization = true). @@ -31,5 +32,10 @@ static void Test(bool b = true) { // where IsInitialization = true. Debug.Assert (b, $"Debug interpolated string handler {b}"); } + + [ExpectedWarning ("IL2057")] + static void TestUnknownInterpolatedString (string input = "test") { + Type.GetType ($"{input}"); + } } } From ccb22f38c837b2cc9f41b98d418e1e18583f0b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Wed, 1 May 2024 15:04:13 -0400 Subject: [PATCH 210/248] [mono][debug-helpers] Parse W: prefix in MONO_VERBOSE_METHOD to match wrappers (#101766) * [debug-helpers] parse W: prefix in MONO_VERBOSE_METHOD to match wrappers * update manpage --- docs/design/mono/mono-manpage-1.md | 9 ++++++++- src/mono/mono/metadata/debug-helpers.c | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/docs/design/mono/mono-manpage-1.md b/docs/design/mono/mono-manpage-1.md index 20ab43b7563a77..8f5bd56abb3d8e 100644 --- a/docs/design/mono/mono-manpage-1.md +++ b/docs/design/mono/mono-manpage-1.md @@ -70,7 +70,7 @@ A number of diagnostic command line options take as argument a method description. A method description is a textual representation that can be used to uniquely identify a method. The syntax is as follows: - [namespace]classname:methodname[(arguments)] + [W:][namespace]classname:methodname[(arguments)] The values in brackets are optional, like the namespace and the arguments. The arguments themselves are either empty, or a @@ -93,11 +93,18 @@ both a comma and a space and '\>'. By-reference arguments should include a "&" after the typename. +If the method description is prefixed by 'W:' (or 'w:'), then it will +match a *wrapper* method that may be created by the runtime for the +specified method. (For example imported P/Invoke methods may have a +wrapper generated by the runtime.) + + Examples: *:ctor(int) // All constructors that take an int as an argument *:Main // Methods named Main in any class *:Main(string[]) // Methods named Main that take a string array in any class + W:UnixSignal:install // Wrappers for the UnixSignal.install DllImport ## RUNTIME OPTIONS diff --git a/src/mono/mono/metadata/debug-helpers.c b/src/mono/mono/metadata/debug-helpers.c index ff2463300767fe..7ef728eadd5fa8 100644 --- a/src/mono/mono/metadata/debug-helpers.c +++ b/src/mono/mono/metadata/debug-helpers.c @@ -39,6 +39,7 @@ struct MonoMethodDesc { char *args; guint num_args; gboolean include_namespace, klass_glob, name_glob; + gboolean match_wrappers; }; // This, instead of an array of pointers, to optimize away a pointer and a relocation per string. @@ -341,7 +342,7 @@ mono_context_get_desc (MonoGenericContext *context) * Creates a method description for \p name, which conforms to the following * specification: * - * [namespace.]classname:methodname[(args...)] + * [w:][namespace.]classname:methodname[(args...)] * * in all the loaded assemblies. * @@ -356,7 +357,13 @@ mono_method_desc_new (const char *name, gboolean include_namespace) char *class_name, *class_nspace, *method_name, *use_args, *end; int use_namespace; int generic_delim_stack; + int match_wrappers = 0; + /* if the name starts with w: or W: allow matching wrappers */ + if (strstr(name, "W:") == name || strstr(name, "w:") == name) { + name += 2; + match_wrappers = 1; + } class_nspace = g_strdup (name); use_args = strchr (class_nspace, '('); if (use_args) { @@ -414,6 +421,8 @@ mono_method_desc_new (const char *name, gboolean include_namespace) ++end; } } + if (match_wrappers) + result->match_wrappers = TRUE; return result; } @@ -431,6 +440,8 @@ mono_method_desc_from_method (MonoMethod *method) result->name = g_strdup (method->name); result->klass = g_strdup (method->klass->name); result->name_space = g_strdup (method->klass->name_space); + if (method->wrapper_type) + result->match_wrappers = TRUE; return result; } @@ -466,6 +477,9 @@ mono_method_desc_match (MonoMethodDesc *desc, MonoMethod *method) char *sig; gboolean name_match; + if (desc->match_wrappers && method->wrapper_type == MONO_WRAPPER_NONE) { + return FALSE; + } if (desc->name_glob && !strcmp (desc->name, "*")) return TRUE; #if 0 From 48a7d5f5717d2188d041d83c7dd5d8bae9e4fdee Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 1 May 2024 14:53:49 -0700 Subject: [PATCH 211/248] Merging formats SVE_AB_3A and SVE_AD_3A into SVE_AA_3A (#101754) --- src/coreclr/jit/codegenarm64test.cpp | 28 ++++++-------- src/coreclr/jit/emitarm64sve.cpp | 55 +++++++++++++++++----------- src/coreclr/jit/emitfmtsarm64sve.h | 2 - src/coreclr/jit/instrsarm64sve.h | 30 +++++++-------- 4 files changed, 60 insertions(+), 55 deletions(-) diff --git a/src/coreclr/jit/codegenarm64test.cpp b/src/coreclr/jit/codegenarm64test.cpp index 2057a72323bf7b..dcd24539e9918d 100644 --- a/src/coreclr/jit/codegenarm64test.cpp +++ b/src/coreclr/jit/codegenarm64test.cpp @@ -4572,14 +4572,24 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_S); // EOR ., /M, ., . theEmitter->emitIns_R_R_R(INS_sve_orr, EA_SCALABLE, REG_V29, REG_P7, REG_V31, INS_OPTS_SCALABLE_D); // ORR ., /M, ., . - - // IF_SVE_AB_3A theEmitter->emitIns_R_R_R(INS_sve_add, EA_SCALABLE, REG_V5, REG_P6, REG_V7, INS_OPTS_SCALABLE_B); // ADD ., /M, ., . theEmitter->emitIns_R_R_R(INS_sve_sub, EA_SCALABLE, REG_V15, REG_P7, REG_V29, INS_OPTS_SCALABLE_H); // SUB ., /M, ., . theEmitter->emitIns_R_R_R(INS_sve_subr, EA_SCALABLE, REG_V2, REG_P0, REG_V13, INS_OPTS_SCALABLE_S); // SUBR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_smax, EA_SCALABLE, REG_V24, REG_P0, REG_V2, + INS_OPTS_SCALABLE_B); // SMAX ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_smin, EA_SCALABLE, REG_V9, REG_P1, REG_V27, + INS_OPTS_SCALABLE_H); // SMIN ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_sabd, EA_SCALABLE, REG_V5, REG_P2, REG_V6, + INS_OPTS_SCALABLE_B); // SABD ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_uabd, EA_SCALABLE, REG_V23, REG_P3, REG_V9, + INS_OPTS_SCALABLE_S); // UABD ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_umax, EA_SCALABLE, REG_V15, REG_P4, REG_V2, + INS_OPTS_SCALABLE_S); // UMAX ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_umin, EA_SCALABLE, REG_V12, REG_P7, REG_V0, + INS_OPTS_SCALABLE_D); // UMIN ., /M, ., . #ifdef ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED // IF_SVE_AB_3B @@ -4599,20 +4609,6 @@ void CodeGen::genArm64EmitterUnitTestsSve() theEmitter->emitIns_R_R_R(INS_sve_udivr, EA_SCALABLE, REG_V13, REG_P7, REG_V15, INS_OPTS_SCALABLE_D); // UDIVR ., /M, ., . - // IF_SVE_AD_3A - theEmitter->emitIns_R_R_R(INS_sve_smax, EA_SCALABLE, REG_V24, REG_P0, REG_V2, - INS_OPTS_SCALABLE_B); // SMAX ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_smin, EA_SCALABLE, REG_V9, REG_P1, REG_V27, - INS_OPTS_SCALABLE_H); // SMIN ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_sabd, EA_SCALABLE, REG_V5, REG_P2, REG_V6, - INS_OPTS_SCALABLE_B); // SABD ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_uabd, EA_SCALABLE, REG_V23, REG_P3, REG_V9, - INS_OPTS_SCALABLE_S); // UABD ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_umax, EA_SCALABLE, REG_V15, REG_P4, REG_V2, - INS_OPTS_SCALABLE_S); // UMAX ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_umin, EA_SCALABLE, REG_V12, REG_P7, REG_V0, - INS_OPTS_SCALABLE_D); // UMIN ., /M, ., . - // IF_SVE_AE_3A theEmitter->emitIns_R_R_R(INS_sve_mul, EA_SCALABLE, REG_V5, REG_P1, REG_V3, INS_OPTS_SCALABLE_D); // MUL ., /M, ., . diff --git a/src/coreclr/jit/emitarm64sve.cpp b/src/coreclr/jit/emitarm64sve.cpp index f7aa628e3f835f..160e87d0542756 100644 --- a/src/coreclr/jit/emitarm64sve.cpp +++ b/src/coreclr/jit/emitarm64sve.cpp @@ -347,7 +347,7 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static insFormat formatEncode4J[4] = {IF_SVE_BV_2A, IF_SVE_BV_2A_A, IF_SVE_CP_3A, IF_SVE_CQ_3A}; const static insFormat formatEncode4K[4] = {IF_SVE_IF_4A, IF_SVE_IF_4A_A, IF_SVE_IM_3A, IF_SVE_IN_4A}; const static insFormat formatEncode4L[4] = {IF_SVE_IZ_4A, IF_SVE_IZ_4A_A, IF_SVE_JB_4A, IF_SVE_JM_3A}; - const static insFormat formatEncode3A[3] = {IF_SVE_AB_3A, IF_SVE_AT_3A, IF_SVE_EC_1A}; + const static insFormat formatEncode3A[3] = {IF_SVE_AA_3A, IF_SVE_AT_3A, IF_SVE_EC_1A}; const static insFormat formatEncode3B[3] = {IF_SVE_BH_3A, IF_SVE_BH_3B, IF_SVE_BH_3B_A}; const static insFormat formatEncode3C[3] = {IF_SVE_BW_2A, IF_SVE_CB_2A, IF_SVE_EB_1A}; const static insFormat formatEncode3D[3] = {IF_SVE_BR_3A, IF_SVE_BR_3B, IF_SVE_CI_3A}; @@ -371,7 +371,7 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static insFormat formatEncode3V[3] = {IF_SVE_JA_4A, IF_SVE_JB_4A, IF_SVE_JM_3A}; const static insFormat formatEncode2AA[2] = {IF_SVE_ID_2A, IF_SVE_IE_2A}; const static insFormat formatEncode2AB[2] = {IF_SVE_JG_2A, IF_SVE_JH_2A}; - const static insFormat formatEncode2AC[2] = {IF_SVE_AD_3A, IF_SVE_ED_1A}; + const static insFormat formatEncode2AC[2] = {IF_SVE_AA_3A, IF_SVE_ED_1A}; const static insFormat formatEncode2AD[2] = {IF_SVE_AB_3B, IF_SVE_AT_3B}; const static insFormat formatEncode2AE[2] = {IF_SVE_CG_2A, IF_SVE_CJ_2A}; const static insFormat formatEncode2AF[2] = {IF_SVE_AE_3A, IF_SVE_BD_3A}; @@ -387,7 +387,7 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static insFormat formatEncode2AP[2] = {IF_SVE_GY_3B, IF_SVE_HA_3A}; const static insFormat formatEncode2AQ[2] = {IF_SVE_GO_3A, IF_SVE_HC_3A}; const static insFormat formatEncode2AR[2] = {IF_SVE_AP_3A, IF_SVE_CZ_4A}; - const static insFormat formatEncode2AT[2] = {IF_SVE_AB_3A, IF_SVE_EC_1A}; + const static insFormat formatEncode2AT[2] = {IF_SVE_AA_3A, IF_SVE_EC_1A}; const static insFormat formatEncode2AU[2] = {IF_SVE_AH_3A, IF_SVE_BI_2A}; const static insFormat formatEncode2AV[2] = {IF_SVE_BM_1A, IF_SVE_BN_1A}; const static insFormat formatEncode2AW[2] = {IF_SVE_BO_1A, IF_SVE_BP_1A}; @@ -2947,7 +2947,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, { assert(isLowPredicateRegister(reg2)); assert(insScalableOptsNone(sopt)); - fmt = IF_SVE_AB_3A; + fmt = IF_SVE_AA_3A; } break; @@ -2994,7 +2994,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg3)); assert(insOptsScalableStandard(opt)); assert(insScalableOptsNone(sopt)); - fmt = IF_SVE_AD_3A; + fmt = IF_SVE_AA_3A; break; case INS_sve_mul: @@ -8017,11 +8017,9 @@ void emitter::emitIns_PRFOP_R_R_I(instruction ins, case IF_SVE_HP_3B: case IF_SVE_AR_4A: case IF_SVE_BV_2A_A: - case IF_SVE_AB_3A: case IF_SVE_ET_3A: case IF_SVE_HU_4A: case IF_SVE_HL_3B: - case IF_SVE_AD_3A: case IF_SVE_AB_3B: case IF_SVE_AE_3A: case IF_SVE_EU_3A: @@ -9905,10 +9903,9 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id) switch (fmt) { // Scalable. - case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise logical operations (predicated) - case IF_SVE_AB_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer add/subtract vectors (predicated) + case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise logical operations + integer add/subtract + // vectors + SVE integer min/max/difference (predicated) case IF_SVE_AC_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer divide vectors (predicated) - case IF_SVE_AD_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer min/max/difference (predicated) case IF_SVE_AE_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer multiply vectors (predicated) case IF_SVE_AF_3A: // ........xx...... ...gggnnnnnddddd -- SVE bitwise logical reduction (predicated) case IF_SVE_AG_3A: // ........xx...... ...gggnnnnnddddd -- SVE bitwise logical reduction (quadwords) @@ -12556,9 +12553,8 @@ void emitter::emitInsSveSanityCheck(instrDesc* id) break; // Scalable. - case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise logical operations (predicated) - case IF_SVE_AB_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer add/subtract vectors (predicated) - case IF_SVE_AD_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer min/max/difference (predicated) + case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise logical operations + integer add/subtract + // vectors + SVE integer min/max/difference (predicated) case IF_SVE_AE_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer multiply vectors (predicated) case IF_SVE_AN_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise shift by vector (predicated) case IF_SVE_CM_3A: // ........xx...... ...gggmmmmmddddd -- SVE conditionally broadcast element to vector @@ -14484,10 +14480,9 @@ void emitter::emitDispInsSveHelp(instrDesc* id) bitMaskImm bmi; // ., /M, ., . - case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise logical operations (predicated) - case IF_SVE_AB_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer add/subtract vectors (predicated) + case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise logical operations + integer add/subtract + // vectors + SVE integer min/max/difference (predicated) case IF_SVE_AC_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer divide vectors (predicated) - case IF_SVE_AD_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer min/max/difference (predicated) case IF_SVE_AE_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer multiply vectors (predicated) case IF_SVE_AN_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise shift by vector (predicated) case IF_SVE_EP_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 integer halving add/subtract (predicated) @@ -16342,16 +16337,32 @@ void emitter::getInsSveExecutionCharacteristics(instrDesc* id, insExecutionChara switch (id->idInsFmt()) { // Predicate logical - case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise logical operations (predicated) - result.insLatency = PERFSCORE_LATENCY_1C; - result.insThroughput = PERFSCORE_THROUGHPUT_1C; + case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise logical operations + integer add/subtract + // vectors + SVE integer min/max/difference (predicated) + switch (ins) + { + case INS_sve_add: + case INS_sve_sub: + case INS_sve_subr: + case INS_sve_sabd: + case INS_sve_smax: + case INS_sve_smin: + case INS_sve_uabd: + case INS_sve_umax: + case INS_sve_umin: + result.insLatency = PERFSCORE_LATENCY_2C; + result.insThroughput = PERFSCORE_THROUGHPUT_2X; + break; + + default: + result.insLatency = PERFSCORE_LATENCY_1C; + result.insThroughput = PERFSCORE_THROUGHPUT_1C; + break; + } break; // Arithmetic, basic - case IF_SVE_AB_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer add/subtract vectors (predicated) case IF_SVE_EP_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 integer halving add/subtract (predicated) - // Max/min, basic and pairwise - case IF_SVE_AD_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer min/max/difference (predicated) result.insLatency = PERFSCORE_LATENCY_2C; result.insThroughput = PERFSCORE_THROUGHPUT_2X; break; diff --git a/src/coreclr/jit/emitfmtsarm64sve.h b/src/coreclr/jit/emitfmtsarm64sve.h index cd27f567478cf0..672f6ab529b006 100644 --- a/src/coreclr/jit/emitfmtsarm64sve.h +++ b/src/coreclr/jit/emitfmtsarm64sve.h @@ -138,10 +138,8 @@ IF_DEF(SVE_2BS, IS_NONE, NONE) // Instruction has 2 possible encoding types, ty *****************************************************************************/ IF_DEF(SVE_AA_3A, IS_NONE, NONE) // SVE_AA_3A ........xx...... ...gggmmmmmddddd -- SVE bitwise logical operations (predicated) -IF_DEF(SVE_AB_3A, IS_NONE, NONE) // SVE_AB_3A ........xx...... ...gggmmmmmddddd -- SVE integer add/subtract vectors (predicated) IF_DEF(SVE_AB_3B, IS_NONE, NONE) // SVE_AB_3B ................ ...gggmmmmmddddd -- SVE integer add/subtract vectors (predicated) IF_DEF(SVE_AC_3A, IS_NONE, NONE) // SVE_AC_3A ........xx...... ...gggmmmmmddddd -- SVE integer divide vectors (predicated) -IF_DEF(SVE_AD_3A, IS_NONE, NONE) // SVE_AD_3A ........xx...... ...gggmmmmmddddd -- SVE integer min/max/difference (predicated) IF_DEF(SVE_AE_3A, IS_NONE, NONE) // SVE_AE_3A ........xx...... ...gggmmmmmddddd -- SVE integer multiply vectors (predicated) IF_DEF(SVE_AF_3A, IS_NONE, NONE) // SVE_AF_3A ........xx...... ...gggnnnnnddddd -- SVE bitwise logical reduction (predicated) IF_DEF(SVE_AG_3A, IS_NONE, NONE) // SVE_AG_3A ........xx...... ...gggnnnnnddddd -- SVE bitwise logical reduction (quadwords) diff --git a/src/coreclr/jit/instrsarm64sve.h b/src/coreclr/jit/instrsarm64sve.h index fb469c0bfdc101..b017d23a0a1365 100644 --- a/src/coreclr/jit/instrsarm64sve.h +++ b/src/coreclr/jit/instrsarm64sve.h @@ -555,14 +555,14 @@ INST4(stnt1w, "stnt1w", 0, IF_SV // STNT1W {.S }, , [{, #, MUL VL}] SVE_JM_3A 111001010001iiii 111gggnnnnnttttt E510 E000 -// enum name info SVE_AB_3A SVE_AT_3A SVE_EC_1A +// enum name info SVE_AA_3A SVE_AT_3A SVE_EC_1A INST3(add, "add", 0, IF_SVE_3A, 0x04000000, 0x04200000, 0x2520C000 ) - // ADD ., /M, ., . SVE_AB_3A 00000100xx000000 000gggmmmmmddddd 0400 0000 + // ADD ., /M, ., . SVE_AA_3A 00000100xx000000 000gggmmmmmddddd 0400 0000 // ADD ., ., . SVE_AT_3A 00000100xx1mmmmm 000000nnnnnddddd 0420 0000 // ADD ., ., #{, } SVE_EC_1A 00100101xx100000 11hiiiiiiiiddddd 2520 C000 INST3(sub, "sub", 0, IF_SVE_3A, 0x04010000, 0x04200400, 0x2521C000 ) - // SUB ., /M, ., . SVE_AB_3A 00000100xx000001 000gggmmmmmddddd 0401 0000 + // SUB ., /M, ., . SVE_AA_3A 00000100xx000001 000gggmmmmmddddd 0401 0000 // SUB ., ., . SVE_AT_3A 00000100xx1mmmmm 000001nnnnnddddd 0420 0400 // SUB ., ., #{, } SVE_EC_1A 00100101xx100001 11hiiiiiiiiddddd 2521 C000 @@ -926,21 +926,21 @@ INST2(str, "str", 0, IF_SV // STR , [{, #, MUL VL}] SVE_JH_2A 1110010110iiiiii 010iiinnnnnttttt E580 4000 -// enum name info SVE_AD_3A SVE_ED_1A +// enum name info SVE_AA_3A SVE_ED_1A INST2(smax, "smax", 0, IF_SVE_2AC, 0x04080000, 0x2528C000 ) - // SMAX ., /M, ., . SVE_AD_3A 00000100xx001000 000gggmmmmmddddd 0408 0000 + // SMAX ., /M, ., . SVE_AA_3A 00000100xx001000 000gggmmmmmddddd 0408 0000 // SMAX ., ., # SVE_ED_1A 00100101xx101000 110iiiiiiiiddddd 2528 C000 INST2(smin, "smin", 0, IF_SVE_2AC, 0x040A0000, 0x252AC000 ) - // SMIN ., /M, ., . SVE_AD_3A 00000100xx001010 000gggmmmmmddddd 040A 0000 + // SMIN ., /M, ., . SVE_AA_3A 00000100xx001010 000gggmmmmmddddd 040A 0000 // SMIN ., ., # SVE_ED_1A 00100101xx101010 110iiiiiiiiddddd 252A C000 INST2(umax, "umax", 0, IF_SVE_2AC, 0x04090000, 0x2529C000 ) - // UMAX ., /M, ., . SVE_AD_3A 00000100xx001001 000gggmmmmmddddd 0409 0000 + // UMAX ., /M, ., . SVE_AA_3A 00000100xx001001 000gggmmmmmddddd 0409 0000 // UMAX ., ., # SVE_ED_1A 00100101xx101001 110iiiiiiiiddddd 2529 C000 INST2(umin, "umin", 0, IF_SVE_2AC, 0x040B0000, 0x252BC000 ) - // UMIN ., /M, ., . SVE_AD_3A 00000100xx001011 000gggmmmmmddddd 040B 0000 + // UMIN ., /M, ., . SVE_AA_3A 00000100xx001011 000gggmmmmmddddd 040B 0000 // UMIN ., ., # SVE_ED_1A 00100101xx101011 110iiiiiiiiddddd 252B C000 @@ -1094,9 +1094,9 @@ INST2(not, "not", 0, IF_SV // NOT .B, /Z, .B SVE_CZ_4A 001001010000MMMM 01gggg1NNNN0DDDD 2500 4200 -// enum name info SVE_AB_3A SVE_EC_1A +// enum name info SVE_AA_3A SVE_EC_1A INST2(subr, "subr", 0, IF_SVE_2AT, 0x04030000, 0x2523C000 ) - // SUBR ., /M, ., . SVE_AB_3A 00000100xx000011 000gggmmmmmddddd 0403 0000 + // SUBR ., /M, ., . SVE_AA_3A 00000100xx000011 000gggmmmmmddddd 0403 0000 // SUBR ., ., #{, } SVE_EC_1A 00100101xx100011 11hiiiiiiiiddddd 2523 C000 @@ -1882,12 +1882,12 @@ INST1(urhadd, "urhadd", 0, IF_SV // URHADD ., /M, ., . SVE_EP_3A 01000100xx010101 100gggmmmmmddddd 4415 8000 -// enum name info SVE_AD_3A -INST1(sabd, "sabd", 0, IF_SVE_AD_3A, 0x040C0000 ) - // SABD ., /M, ., . SVE_AD_3A 00000100xx001100 000gggmmmmmddddd 040C 0000 +// enum name info SVE_AA_3A +INST1(sabd, "sabd", 0, IF_SVE_AA_3A, 0x040C0000 ) + // SABD ., /M, ., . SVE_AA_3A 00000100xx001100 000gggmmmmmddddd 040C 0000 -INST1(uabd, "uabd", 0, IF_SVE_AD_3A, 0x040D0000 ) - // UABD ., /M, ., . SVE_AD_3A 00000100xx001101 000gggmmmmmddddd 040D 0000 +INST1(uabd, "uabd", 0, IF_SVE_AA_3A, 0x040D0000 ) + // UABD ., /M, ., . SVE_AA_3A 00000100xx001101 000gggmmmmmddddd 040D 0000 // enum name info SVE_FW_3A From 08fc3b9925bd3585456ff5f5b37236e732266fe9 Mon Sep 17 00:00:00 2001 From: Levi Broderick Date: Wed, 1 May 2024 15:59:09 -0700 Subject: [PATCH 212/248] Fix CodeQL issue cpp/enum-index in mono (#101751) --- src/mono/mono/mini/mini-amd64.c | 4 ++-- src/mono/mono/mini/mini-s390x.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mono/mono/mini/mini-amd64.c b/src/mono/mono/mini/mini-amd64.c index f019d35e387586..fbda85ae883a79 100644 --- a/src/mono/mono/mini/mini-amd64.c +++ b/src/mono/mono/mini/mini-amd64.c @@ -127,7 +127,7 @@ static const char * const single_xmmregs [] = { const char* mono_arch_fregname (int reg) { - if (reg < AMD64_XMM_NREG) + if (reg >= 0 && reg < AMD64_XMM_NREG) return single_xmmregs [reg]; else return "unknown"; @@ -136,7 +136,7 @@ mono_arch_fregname (int reg) const char * mono_arch_xregname (int reg) { - if (reg < AMD64_XMM_NREG) + if (reg >= 0 && reg < AMD64_XMM_NREG) return packed_xmmregs [reg]; else return "unknown"; diff --git a/src/mono/mono/mini/mini-s390x.c b/src/mono/mono/mini/mini-s390x.c index c084bdfb1be76e..e90a0e6770e151 100644 --- a/src/mono/mono/mini/mini-s390x.c +++ b/src/mono/mono/mini/mini-s390x.c @@ -464,7 +464,7 @@ mono_arch_fregname (int reg) const char * mono_arch_xregname (int reg) { - if (reg < s390_VR_NREG) + if (reg >= 0 && reg < s390_VR_NREG) return vrNames [reg]; else return "unknown"; From a2b1690346e94d434f112a7ccc587e58c88b8457 Mon Sep 17 00:00:00 2001 From: Parker Bibus Date: Wed, 1 May 2024 16:05:09 -0700 Subject: [PATCH 213/248] Use a version that will consistently be found. (#101780) --- eng/pipelines/coreclr/templates/run-performance-job.yml | 2 +- eng/pipelines/coreclr/templates/run-scenarios-job.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/pipelines/coreclr/templates/run-performance-job.yml b/eng/pipelines/coreclr/templates/run-performance-job.yml index 6b8fdc5f34ef25..e1bc7f283555bd 100644 --- a/eng/pipelines/coreclr/templates/run-performance-job.yml +++ b/eng/pipelines/coreclr/templates/run-performance-job.yml @@ -179,7 +179,7 @@ jobs: displayName: Performance Setup (Unix) condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} - - script: $(Python) $(PerformanceDirectory)/scripts/ci_setup.py $(SetupArguments) ${{ parameters.additionalSetupParameters }} --dotnet-versions 9.0.100-preview.5.24230.4 # Temporarily add a specific dotnet-version as Windows runs are currently failing to install the dotnet version + - script: $(Python) $(PerformanceDirectory)/scripts/ci_setup.py $(SetupArguments) ${{ parameters.additionalSetupParameters }} --dotnet-versions 9.0.100-preview.4.24215.2 # Temporarily add a specific dotnet-version as Windows runs are currently failing to install the dotnet version displayName: Run ci setup script # Run perf testing in helix - template: /eng/pipelines/coreclr/templates/perf-send-to-helix.yml diff --git a/eng/pipelines/coreclr/templates/run-scenarios-job.yml b/eng/pipelines/coreclr/templates/run-scenarios-job.yml index 13fdb47f15bc31..8567c76fe28aa4 100644 --- a/eng/pipelines/coreclr/templates/run-scenarios-job.yml +++ b/eng/pipelines/coreclr/templates/run-scenarios-job.yml @@ -135,7 +135,7 @@ jobs: condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} # run ci-setup - - script: $(Python) $(PerformanceDirectory)\scripts\ci_setup.py $(SetupArguments) $(ExtraSetupArguments) --dotnet-versions 9.0.100-preview.5.24230.4 --output-file $(WorkItemDirectory)\machine-setup.cmd # Temporarily add a specific dotnet-version as Windows runs are currently failing to install the dotnet version + - script: $(Python) $(PerformanceDirectory)\scripts\ci_setup.py $(SetupArguments) $(ExtraSetupArguments) --dotnet-versions 9.0.100-preview.4.24215.2 --output-file $(WorkItemDirectory)\machine-setup.cmd # Temporarily add a specific dotnet-version as Windows runs are currently failing to install the dotnet version displayName: Run ci setup script (Windows) condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) - script: $(Python) $(PerformanceDirectory)/scripts/ci_setup.py $(SetupArguments) $(ExtraSetupArguments) --output-file $(WorkItemDirectory)/machine-setup.sh From 71f8fb65a5a28018901823c19de57fe9451ab3b1 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Thu, 2 May 2024 01:23:45 +0200 Subject: [PATCH 214/248] Fix runtime lookup expansion in Tier0 (#101153) --- src/coreclr/jit/helperexpansion.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/helperexpansion.cpp b/src/coreclr/jit/helperexpansion.cpp index 17d6a6d4830077..b9dca67a1356c2 100644 --- a/src/coreclr/jit/helperexpansion.cpp +++ b/src/coreclr/jit/helperexpansion.cpp @@ -307,9 +307,8 @@ bool Compiler::fgExpandRuntimeLookupsForCall(BasicBlock** pBlock, Statement* stm // null-check basic block GenTree* fastPathValue = gtNewIndir(TYP_I_IMPL, gtCloneExpr(slotPtrTree), GTF_IND_NONFAULTING); // Save dictionary slot to a local (to be used by fast path) - GenTree* fastPathValueClone = - opts.OptimizationEnabled() ? fgMakeMultiUse(&fastPathValue) : gtCloneExpr(fastPathValue); - GenTree* nullcheckOp = gtNewOperNode(GT_EQ, TYP_INT, fastPathValue, gtNewIconNode(0, TYP_I_IMPL)); + GenTree* fastPathValueClone = fgMakeMultiUse(&fastPathValue); + GenTree* nullcheckOp = gtNewOperNode(GT_EQ, TYP_INT, fastPathValue, gtNewIconNode(0, TYP_I_IMPL)); nullcheckOp->gtFlags |= GTF_RELOP_JMP_USED; // nullcheckBb conditionally jumps to fallbackBb, but we need to initialize fallbackBb last From 507abdf5d67e98900f688288c3a3bca615d40785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Thu, 2 May 2024 18:23:12 +0900 Subject: [PATCH 215/248] Try to reduce cost of Async (#101605) Contributes to #79204. I don't know if this will be considered mergeable, but I wanted to at least try something. For apps that use async a lot (like the Stage2 app we use for Goldilocks), the async infrastructure can cost 10% of the entire executable. Shuffling a couple things in `GetStateMachineBox` I was able to get 0.23% saving. It's miniscule. In general async is death by a thousand papercuts so I don't see a silver bullet. --- .../AsyncMethodBuilderCore.cs | 6 ++ .../AsyncTaskMethodBuilderT.cs | 86 ++++++++++--------- 2 files changed, 51 insertions(+), 41 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs index 459fd26e6abb38..7cb85c290c7555 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs @@ -102,6 +102,12 @@ internal static string GetAsyncStateMachineDescription(IAsyncStateMachine stateM return sb.ToString(); } + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void LogTraceOperationBegin(Task t, Type stateMachineType) + { + TplEventSource.Log.TraceOperationBegin(t.Id, "Async: " + stateMachineType.Name, 0); + } + internal static Action CreateContinuationWrapper(Action continuation, Action invokeAction, Task innerTask) => new ContinuationWrapper(continuation, invokeAction, innerTask).Invoke; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncTaskMethodBuilderT.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncTaskMethodBuilderT.cs index c3064ad22114bd..5a2ccb1d635493 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncTaskMethodBuilderT.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncTaskMethodBuilderT.cs @@ -157,6 +157,8 @@ private static IAsyncStateMachineBox GetStateMachineBox( { ExecutionContext? currentContext = ExecutionContext.Capture(); + IAsyncStateMachineBox result; + // Check first for the most common case: not the first yield in an async method. // In this case, the first yield will have already "boxed" the state machine in // a strongly-typed manner into an AsyncStateMachineBox. It will already contain @@ -168,9 +170,8 @@ private static IAsyncStateMachineBox GetStateMachineBox( { stronglyTypedBox.Context = currentContext; } - return stronglyTypedBox; + result = stronglyTypedBox; } - // The least common case: we have a weakly-typed boxed. This results if the debugger // or some other use of reflection accesses a property like ObjectIdForDebugger or a // method like SetNotificationForWaitCompletion prior to the first await happening. In @@ -180,7 +181,7 @@ private static IAsyncStateMachineBox GetStateMachineBox( // result in a boxing allocation when storing the TStateMachine if it's a struct, but // this only happens in active debugging scenarios where such performance impact doesn't // matter. - if (taskField is AsyncStateMachineBox weaklyTypedBox) + else if (taskField is AsyncStateMachineBox weaklyTypedBox) { // If this is the first await, we won't yet have a state machine, so store it. if (weaklyTypedBox.StateMachine == null) @@ -192,52 +193,55 @@ private static IAsyncStateMachineBox GetStateMachineBox( // Update the context. This only happens with a debugger, so no need to spend // extra IL checking for equality before doing the assignment. weaklyTypedBox.Context = currentContext; - return weaklyTypedBox; + result = weaklyTypedBox; } - - // Alert a listening debugger that we can't make forward progress unless it slips threads. - // If we don't do this, and a method that uses "await foo;" is invoked through funceval, - // we could end up hooking up a callback to push forward the async method's state machine, - // the debugger would then abort the funceval after it takes too long, and then continuing - // execution could result in another callback being hooked up. At that point we have - // multiple callbacks registered to push the state machine, which could result in bad behavior. - Debugger.NotifyOfCrossThreadDependency(); - - // At this point, taskField should really be null, in which case we want to create the box. - // However, in a variety of debugger-related (erroneous) situations, it might be non-null, - // e.g. if the Task property is examined in a Watch window, forcing it to be lazily-initialized - // as a Task rather than as an AsyncStateMachineBox. The worst that happens in such - // cases is we lose the ability to properly step in the debugger, as the debugger uses that - // object's identity to track this specific builder/state machine. As such, we proceed to - // overwrite whatever's there anyway, even if it's non-null. + else + { + // Alert a listening debugger that we can't make forward progress unless it slips threads. + // If we don't do this, and a method that uses "await foo;" is invoked through funceval, + // we could end up hooking up a callback to push forward the async method's state machine, + // the debugger would then abort the funceval after it takes too long, and then continuing + // execution could result in another callback being hooked up. At that point we have + // multiple callbacks registered to push the state machine, which could result in bad behavior. + Debugger.NotifyOfCrossThreadDependency(); + + // At this point, taskField should really be null, in which case we want to create the box. + // However, in a variety of debugger-related (erroneous) situations, it might be non-null, + // e.g. if the Task property is examined in a Watch window, forcing it to be lazily-initialized + // as a Task rather than as an AsyncStateMachineBox. The worst that happens in such + // cases is we lose the ability to properly step in the debugger, as the debugger uses that + // object's identity to track this specific builder/state machine. As such, we proceed to + // overwrite whatever's there anyway, even if it's non-null. #if NATIVEAOT - // DebugFinalizableAsyncStateMachineBox looks like a small type, but it actually is not because - // it will have a copy of all the slots from its parent. It will add another hundred(s) bytes - // per each async method in NativeAOT binaries without adding much value. Avoid - // generating this extra code until a better solution is implemented. - var box = new AsyncStateMachineBox(); + // DebugFinalizableAsyncStateMachineBox looks like a small type, but it actually is not because + // it will have a copy of all the slots from its parent. It will add another hundred(s) bytes + // per each async method in NativeAOT binaries without adding much value. Avoid + // generating this extra code until a better solution is implemented. + var box = new AsyncStateMachineBox(); #else - AsyncStateMachineBox box = AsyncMethodBuilderCore.TrackAsyncMethodCompletion ? - CreateDebugFinalizableAsyncStateMachineBox() : - new AsyncStateMachineBox(); + AsyncStateMachineBox box = AsyncMethodBuilderCore.TrackAsyncMethodCompletion ? + CreateDebugFinalizableAsyncStateMachineBox() : + new AsyncStateMachineBox(); #endif - taskField = box; // important: this must be done before storing stateMachine into box.StateMachine! - box.StateMachine = stateMachine; - box.Context = currentContext; + taskField = box; // important: this must be done before storing stateMachine into box.StateMachine! + box.StateMachine = stateMachine; + box.Context = currentContext; - // Log the creation of the state machine box object / task for this async method. - if (TplEventSource.Log.IsEnabled()) - { - TplEventSource.Log.TraceOperationBegin(box.Id, "Async: " + stateMachine.GetType().Name, 0); - } + // Log the creation of the state machine box object / task for this async method. + if (TplEventSource.Log.IsEnabled()) + { + AsyncMethodBuilderCore.LogTraceOperationBegin(box, stateMachine.GetType()); + } - // And if async debugging is enabled, track the task. - if (Threading.Tasks.Task.s_asyncDebuggingEnabled) - { - Threading.Tasks.Task.AddToActiveTasks(box); + // And if async debugging is enabled, track the task. + if (Threading.Tasks.Task.s_asyncDebuggingEnabled) + { + Threading.Tasks.Task.AddToActiveTasks(box); + } + result = box; } - return box; + return result; } #if !NATIVEAOT From f95a76b58ec0d9af3179a6104eebf4744f42d778 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 2 May 2024 11:24:50 +0200 Subject: [PATCH 216/248] JIT: Process all register kills in bulk in LSRA (#101760) `RefTypeKill` is one of the most common types of ref position because we create a separate one for every register whenever registers are killed, and registers are killed with very high frequency (for example, all callee trashed registers at calls). This can be seen in metrics: in `libraries_tests.run`, `RefTypeKill` is as common as `RefTypeUse` and `RefTypeDef` combined on x64, and 3x as common as them combined on arm64 due to having more registers. The main complication around changing `RefTypeKill` to represent killing a full set of registers is the fact that we want to be able to easily look up the next `RefPosition` at which a particular register is killed or used. Today, this is very simple: all kills (`RefTypeKill`) and uses (`RefTypeFixedReg`) participate in an intrusive linked list, and finding the next `RefPosition` is as simple as following this list. This PR changes LSRA to model the kills in bulk instead of creating an individual `RefPosition` for every kill. To handle finding the next fixed reg ref position LSRA is updated to take into account that there can be `RefPosition`'s corresponding to a register from two different linked lists: the `RefTypeFixedReg` intrusive linked list, and also a linked list of all `RefTypeKill` ref positions. The latter linked list may take some searching (not every kill necessarily kills the register we are looking for), but the reduction in number of `RefPosition`'s created more than makes up for this. No codegen diffs, but significant throughput improvements. This change reduces memory usage of the JIT by around 12% for arm64, and by around 7% for x64. --- src/coreclr/jit/lsra.cpp | 264 ++++++++++++++++++-------------- src/coreclr/jit/lsra.h | 17 +- src/coreclr/jit/lsraarmarch.cpp | 2 +- src/coreclr/jit/lsrabuild.cpp | 33 ++-- src/coreclr/jit/lsraxarch.cpp | 2 +- 5 files changed, 173 insertions(+), 145 deletions(-) diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index efd861348223dc..8f0875d7b09fc9 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -271,20 +271,31 @@ regMaskTP LinearScan::lowSIMDRegs() #endif } -void LinearScan::updateNextFixedRef(RegRecord* regRecord, RefPosition* nextRefPosition) +void LinearScan::updateNextFixedRef(RegRecord* regRecord, RefPosition* nextRefPosition, RefPosition* nextKill) { - LsraLocation nextLocation; + LsraLocation nextLocation = nextRefPosition == nullptr ? MaxLocation : nextRefPosition->nodeLocation; - if (nextRefPosition == nullptr) + RefPosition* kill = nextKill; + while ((kill != nullptr) && (kill->nodeLocation < nextLocation)) + { + if ((kill->registerAssignment & genRegMask(regRecord->regNum)) != RBM_NONE) + { + nextLocation = kill->nodeLocation; + break; + } + + kill = kill->nextRefPosition; + } + + if (nextLocation == MaxLocation) { - nextLocation = MaxLocation; fixedRegs &= ~genRegMask(regRecord->regNum); } else { - nextLocation = nextRefPosition->nodeLocation; fixedRegs |= genRegMask(regRecord->regNum); } + nextFixedRef[regRecord->regNum] = nextLocation; } @@ -712,6 +723,8 @@ LinearScan::LinearScan(Compiler* theCompiler) , intervals(theCompiler->getAllocator(CMK_LSRA_Interval)) , allocationPassComplete(false) , refPositions(theCompiler->getAllocator(CMK_LSRA_RefPosition)) + , killHead(nullptr) + , killTail(&killHead) , listNodePool(theCompiler) { availableRegCount = ACTUAL_REG_COUNT; @@ -3948,6 +3961,41 @@ void LinearScan::unassignPhysReg(RegRecord* regRec, RefPosition* spillRefPositio } } +//------------------------------------------------------------------------ +// processKills: Handle that some registers are being killed. +// +// Arguments: +// killRefPosition - The RefPosition for the kill +// +void LinearScan::processKills(RefPosition* killRefPosition) +{ + RefPosition* nextKill = killRefPosition->nextRefPosition; + + regMaskTP killedRegs = killRefPosition->registerAssignment; + while (killedRegs != RBM_NONE) + { + regNumber killedReg = genFirstRegNumFromMaskAndToggle(killedRegs); + RegRecord* regRecord = getRegisterRecord(killedReg); + Interval* assignedInterval = regRecord->assignedInterval; + if (assignedInterval != nullptr) + { + unassignPhysReg(regRecord, assignedInterval->recentRefPosition); + clearConstantReg(regRecord->regNum, assignedInterval->registerType); + makeRegAvailable(regRecord->regNum, assignedInterval->registerType); + } + + assert((nextFixedRef[killedReg] == killRefPosition->nodeLocation) || (killedReg >= AVAILABLE_REG_COUNT)); + RefPosition* regNextRefPos = regRecord->recentRefPosition == nullptr + ? regRecord->firstRefPosition + : regRecord->recentRefPosition->nextRefPosition; + updateNextFixedRef(regRecord, regNextRefPos, nextKill); + } + + regsBusyUntilKill &= ~killRefPosition->registerAssignment; + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_KILL_REGS, nullptr, REG_NA, nullptr, NONE, + killRefPosition->registerAssignment)); +} + //------------------------------------------------------------------------ // spillGCRefs: Spill any GC-type intervals that are currently in registers. // @@ -4865,7 +4913,7 @@ void LinearScan::allocateRegistersMinimal() { RegRecord* physRegRecord = getRegisterRecord(reg); physRegRecord->recentRefPosition = nullptr; - updateNextFixedRef(physRegRecord, physRegRecord->firstRefPosition); + updateNextFixedRef(physRegRecord, physRegRecord->firstRefPosition, killHead); assert(physRegRecord->assignedInterval == nullptr); } @@ -4886,7 +4934,8 @@ void LinearScan::allocateRegistersMinimal() } #endif // DEBUG - BasicBlock* currentBlock = nullptr; + BasicBlock* currentBlock = nullptr; + RefPosition* nextKill = killHead; LsraLocation prevLocation = MinLocation; regMaskTP regsToFree = RBM_NONE; @@ -4906,8 +4955,6 @@ void LinearScan::allocateRegistersMinimal() for (RefPosition& currentRefPosition : refPositions) { - RefPosition* nextRefPosition = currentRefPosition.nextRefPosition; - // TODO: Can we combine this with the freeing of registers below? It might // mess with the dump, since this was previously being done before the call below // to dumpRegRecords. @@ -5017,7 +5064,7 @@ void LinearScan::allocateRegistersMinimal() } else { - assert((refType == RefTypeBB) || (refType == RefTypeKillGCRefs)); + assert((refType == RefTypeBB) || (refType == RefTypeKill) || (refType == RefTypeKillGCRefs)); } #ifdef DEBUG @@ -5066,65 +5113,59 @@ void LinearScan::allocateRegistersMinimal() continue; } + if (refType == RefTypeKill) + { + assert(nextKill == ¤tRefPosition); + processKills(¤tRefPosition); + nextKill = nextKill->nextRefPosition; + continue; + } + if (refType == RefTypeKillGCRefs) { spillGCRefs(¤tRefPosition); continue; } - if (currentRefPosition.isPhysRegRef) + if (refType == RefTypeFixedReg) { RegRecord* regRecord = currentRefPosition.getReg(); Interval* assignedInterval = regRecord->assignedInterval; - updateNextFixedRef(regRecord, currentRefPosition.nextRefPosition); + updateNextFixedRef(regRecord, currentRefPosition.nextRefPosition, nextKill); - // If this is a FixedReg, disassociate any inactive constant interval from this register. - // Otherwise, do nothing. - if (refType == RefTypeFixedReg) + // This is a FixedReg. Disassociate any inactive constant interval from this register. + if (assignedInterval != nullptr && !assignedInterval->isActive && assignedInterval->isConstant) { - if (assignedInterval != nullptr && !assignedInterval->isActive && assignedInterval->isConstant) - { - clearConstantReg(regRecord->regNum, assignedInterval->registerType); - regRecord->assignedInterval = nullptr; - spillCost[regRecord->regNum] = 0; + clearConstantReg(regRecord->regNum, assignedInterval->registerType); + regRecord->assignedInterval = nullptr; + spillCost[regRecord->regNum] = 0; #ifdef TARGET_ARM - // Update overlapping floating point register for TYP_DOUBLE - if (assignedInterval->registerType == TYP_DOUBLE) - { - RegRecord* otherRegRecord = findAnotherHalfRegRec(regRecord); - assert(otherRegRecord->assignedInterval == assignedInterval); - otherRegRecord->assignedInterval = nullptr; - spillCost[otherRegRecord->regNum] = 0; - } -#endif // TARGET_ARM - } - regsInUseThisLocation |= currentRefPosition.registerAssignment; - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_FIXED_REG, nullptr, currentRefPosition.assignedReg())); - -#ifdef SWIFT_SUPPORT - if (currentRefPosition.delayRegFree) + // Update overlapping floating point register for TYP_DOUBLE + if (assignedInterval->registerType == TYP_DOUBLE) { - regsInUseNextLocation |= currentRefPosition.registerAssignment; + RegRecord* otherRegRecord = findAnotherHalfRegRec(regRecord); + assert(otherRegRecord->assignedInterval == assignedInterval); + otherRegRecord->assignedInterval = nullptr; + spillCost[otherRegRecord->regNum] = 0; } -#endif // SWIFT_SUPPORT +#endif // TARGET_ARM } - else + regsInUseThisLocation |= currentRefPosition.registerAssignment; + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_FIXED_REG, nullptr, currentRefPosition.assignedReg())); + +#ifdef SWIFT_SUPPORT + if (currentRefPosition.delayRegFree) { - assert(refType == RefTypeKill); - if (assignedInterval != nullptr) - { - unassignPhysReg(regRecord, assignedInterval->recentRefPosition); - clearConstantReg(regRecord->regNum, assignedInterval->registerType); - makeRegAvailable(regRecord->regNum, assignedInterval->registerType); - } - clearRegBusyUntilKill(regRecord->regNum); - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_KEPT_ALLOCATION, nullptr, regRecord->regNum)); + regsInUseNextLocation |= currentRefPosition.registerAssignment; } +#endif // SWIFT_SUPPORT continue; } + assert(!currentRefPosition.isPhysRegRef); + regNumber assignedRegister = REG_NA; assert(currentRefPosition.isIntervalRef()); @@ -5532,7 +5573,7 @@ void LinearScan::allocateRegisters() { RegRecord* physRegRecord = getRegisterRecord(reg); physRegRecord->recentRefPosition = nullptr; - updateNextFixedRef(physRegRecord, physRegRecord->firstRefPosition); + updateNextFixedRef(physRegRecord, physRegRecord->firstRefPosition, killHead); // Is this an incoming arg register? (Note that we don't, currently, consider reassigning // an incoming arg register as having spill cost.) @@ -5573,7 +5614,8 @@ void LinearScan::allocateRegisters() } #endif // DEBUG - BasicBlock* currentBlock = nullptr; + BasicBlock* currentBlock = nullptr; + RefPosition* nextKill = killHead; LsraLocation prevLocation = MinLocation; regMaskTP regsToFree = RBM_NONE; @@ -5725,7 +5767,7 @@ void LinearScan::allocateRegisters() } else { - assert((refType == RefTypeBB) || (refType == RefTypeKillGCRefs)); + assert((refType == RefTypeBB) || (refType == RefTypeKill) || (refType == RefTypeKillGCRefs)); } #ifdef DEBUG @@ -5781,62 +5823,54 @@ void LinearScan::allocateRegisters() continue; } + if (refType == RefTypeKill) + { + assert(nextKill == ¤tRefPosition); + processKills(¤tRefPosition); + nextKill = nextKill->nextRefPosition; + continue; + } + if (refType == RefTypeKillGCRefs) { spillGCRefs(¤tRefPosition); continue; } - if (currentRefPosition.isPhysRegRef) + if (refType == RefTypeFixedReg) { RegRecord* regRecord = currentRefPosition.getReg(); Interval* assignedInterval = regRecord->assignedInterval; - updateNextFixedRef(regRecord, currentRefPosition.nextRefPosition); + updateNextFixedRef(regRecord, currentRefPosition.nextRefPosition, nextKill); - // If this is a FixedReg, disassociate any inactive constant interval from this register. - // Otherwise, do nothing. - if (refType == RefTypeFixedReg) + // This is a FixedReg. Disassociate any inactive constant interval from this register. + if (assignedInterval != nullptr && !assignedInterval->isActive && assignedInterval->isConstant) { - if (assignedInterval != nullptr && !assignedInterval->isActive && assignedInterval->isConstant) - { - clearConstantReg(regRecord->regNum, assignedInterval->registerType); - regRecord->assignedInterval = nullptr; - spillCost[regRecord->regNum] = 0; + clearConstantReg(regRecord->regNum, assignedInterval->registerType); + regRecord->assignedInterval = nullptr; + spillCost[regRecord->regNum] = 0; #ifdef TARGET_ARM - // Update overlapping floating point register for TYP_DOUBLE - if (assignedInterval->registerType == TYP_DOUBLE) - { - RegRecord* otherRegRecord = findAnotherHalfRegRec(regRecord); - assert(otherRegRecord->assignedInterval == assignedInterval); - otherRegRecord->assignedInterval = nullptr; - spillCost[otherRegRecord->regNum] = 0; - } -#endif // TARGET_ARM - } - regsInUseThisLocation |= currentRefPosition.registerAssignment; - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_FIXED_REG, nullptr, currentRefPosition.assignedReg())); - -#ifdef SWIFT_SUPPORT - if (currentRefPosition.delayRegFree) + // Update overlapping floating point register for TYP_DOUBLE + if (assignedInterval->registerType == TYP_DOUBLE) { - regsInUseNextLocation |= currentRefPosition.registerAssignment; + RegRecord* otherRegRecord = findAnotherHalfRegRec(regRecord); + assert(otherRegRecord->assignedInterval == assignedInterval); + otherRegRecord->assignedInterval = nullptr; + spillCost[otherRegRecord->regNum] = 0; } -#endif // SWIFT_SUPPORT +#endif // TARGET_ARM } - else + regsInUseThisLocation |= currentRefPosition.registerAssignment; + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_FIXED_REG, nullptr, currentRefPosition.assignedReg())); + +#ifdef SWIFT_SUPPORT + if (currentRefPosition.delayRegFree) { - assert(refType == RefTypeKill); - if (assignedInterval != nullptr) - { - unassignPhysReg(regRecord, assignedInterval->recentRefPosition); - clearConstantReg(regRecord->regNum, assignedInterval->registerType); - makeRegAvailable(regRecord->regNum, assignedInterval->registerType); - } - clearRegBusyUntilKill(regRecord->regNum); - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_KEPT_ALLOCATION, nullptr, regRecord->regNum)); + regsInUseNextLocation |= currentRefPosition.registerAssignment; } +#endif // SWIFT_SUPPORT continue; } @@ -7972,7 +8006,6 @@ void LinearScan::resolveRegisters() case RefTypeDef: // These are the ones we're interested in break; - case RefTypeKill: case RefTypeFixedReg: // These require no handling at resolution time assert(currentRefPosition->referent != nullptr); @@ -7988,6 +8021,7 @@ void LinearScan::resolveRegisters() currentRefPosition->getInterval()->getVarIndex(compiler))); currentRefPosition->referent->recentRefPosition = currentRefPosition; continue; + case RefTypeKill: case RefTypeKillGCRefs: // No action to take at resolution time, and no interval to update recentRefPosition for. continue; @@ -10937,7 +10971,7 @@ void LinearScan::TupleStyleDump(LsraTupleDumpMode mode) printf("\n Kill: "); killPrinted = true; } - printf(getRegName(currentRefPosition->assignedReg())); + compiler->dumpRegMask(currentRefPosition->registerAssignment); printf(" "); break; case RefTypeFixedReg: @@ -10965,8 +10999,12 @@ void LinearScan::TupleStyleDump(LsraTupleDumpMode mode) printf("\n\n"); } -void LinearScan::dumpLsraAllocationEvent( - LsraDumpEvent event, Interval* interval, regNumber reg, BasicBlock* currentBlock, RegisterScore registerScore) +void LinearScan::dumpLsraAllocationEvent(LsraDumpEvent event, + Interval* interval, + regNumber reg, + BasicBlock* currentBlock, + RegisterScore registerScore, + regMaskTP regMask) { if (!(VERBOSE)) { @@ -11171,6 +11209,15 @@ void LinearScan::dumpLsraAllocationEvent( printf("UVRes %-4s ", getRegName(reg)); break; + case LSRA_EVENT_KILL_REGS: + dumpRefPositionShort(activeRefPosition, currentBlock); + printf("None "); + dspRegMask(regMask); + printf("\n"); + dumpRefPositionShort(activeRefPosition, currentBlock); + printf(" "); + break; + // We currently don't dump anything for these events. case LSRA_EVENT_DEFUSE_FIXED_DELAY_USE: case LSRA_EVENT_SPILL_EXTENDED_LIFETIME: @@ -11560,7 +11607,7 @@ void LinearScan::dumpRefPositionShort(RefPosition* refPosition, BasicBlock* curr } else { - assert(refPosition->refType == RefTypeKillGCRefs); + assert((refPosition->refType == RefTypeKill) || (refPosition->refType == RefTypeKillGCRefs)); // There's no interval or reg name associated with this. printf(regNameFormat, " "); printf(" %s ", getRefTypeShortName(refPosition->refType)); @@ -11726,8 +11773,6 @@ void LinearScan::verifyFreeRegisters(regMaskTP regsToFree) assert(nextIntervalRef[reg] == MaxLocation); assert(spillCost[reg] == 0); } - LsraLocation thisNextFixedRef = physRegRecord->getNextRefLocation(); - assert(nextFixedRef[reg] == thisNextFixedRef); #ifdef TARGET_ARM // If this is occupied by a double interval, skip the corresponding float reg. if ((assignedInterval != nullptr) && (assignedInterval->registerType == TYP_DOUBLE)) @@ -11933,10 +11978,10 @@ void LinearScan::verifyFinalAllocation() break; case RefTypeKill: - assert(regRecord != nullptr); - assert(regRecord->assignedInterval == nullptr); - dumpLsraAllocationEvent(LSRA_EVENT_KEPT_ALLOCATION, nullptr, regRecord->regNum, currentBlock); + dumpLsraAllocationEvent(LSRA_EVENT_KILL_REGS, nullptr, REG_NA, currentBlock, NONE, + currentRefPosition.registerAssignment); break; + case RefTypeFixedReg: assert(regRecord != nullptr); dumpLsraAllocationEvent(LSRA_EVENT_KEPT_ALLOCATION, nullptr, regRecord->regNum, currentBlock); @@ -13258,18 +13303,13 @@ regMaskTP LinearScan::RegisterSelection::select(Interval* current else if (refPosition->isFixedRegRef && nextRefPos != nullptr && RefTypeIsUse(nextRefPos->refType) && !nextRefPos->isFixedRegRef && genMaxOneBit(refPosition->registerAssignment)) { - regNumber defReg = refPosition->assignedReg(); - RegRecord* defRegRecord = linearScan->getRegisterRecord(defReg); - - RefPosition* currFixedRegRefPosition = defRegRecord->recentRefPosition; - assert(currFixedRegRefPosition != nullptr && - currFixedRegRefPosition->nodeLocation == refPosition->nodeLocation); + regNumber defReg = refPosition->assignedReg(); // If there is another fixed reference to this register before the use, change the candidates // on this RefPosition to include that of nextRefPos. - RefPosition* nextFixedRegRefPosition = defRegRecord->getNextRefPosition(); - if (nextFixedRegRefPosition != nullptr && - nextFixedRegRefPosition->nodeLocation <= nextRefPos->getRefEndLocation()) + // TODO-Quirk: Should pass right type here, but previously this didn't consider TYP_DOUBLE case for arm32. + unsigned nextFixedRegRefLocation = linearScan->getNextFixedRef(defReg, TYP_I_IMPL); + if (nextFixedRegRefLocation <= nextRefPos->getRefEndLocation()) { candidates |= nextRefPos->registerAssignment; if (preferences == refPosition->registerAssignment) @@ -13724,18 +13764,12 @@ regMaskTP LinearScan::RegisterSelection::selectMinimal(Interval* else if (refPosition->isFixedRegRef && nextRefPos != nullptr && RefTypeIsUse(nextRefPos->refType) && !nextRefPos->isFixedRegRef && genMaxOneBit(refPosition->registerAssignment)) { - regNumber defReg = refPosition->assignedReg(); - RegRecord* defRegRecord = linearScan->getRegisterRecord(defReg); - - RefPosition* currFixedRegRefPosition = defRegRecord->recentRefPosition; - assert(currFixedRegRefPosition != nullptr && - currFixedRegRefPosition->nodeLocation == refPosition->nodeLocation); + regNumber defReg = refPosition->assignedReg(); // If there is another fixed reference to this register before the use, change the candidates // on this RefPosition to include that of nextRefPos. - RefPosition* nextFixedRegRefPosition = defRegRecord->getNextRefPosition(); - if (nextFixedRegRefPosition != nullptr && - nextFixedRegRefPosition->nodeLocation <= nextRefPos->getRefEndLocation()) + unsigned nextFixedRegRefLocation = linearScan->getNextFixedRef(defReg, TYP_I_IMPL); + if (nextFixedRegRefLocation <= nextRefPos->getRefEndLocation()) { candidates |= nextRefPos->registerAssignment; } diff --git a/src/coreclr/jit/lsra.h b/src/coreclr/jit/lsra.h index 797c9d69c91d8f..fe09a2e4564410 100644 --- a/src/coreclr/jit/lsra.h +++ b/src/coreclr/jit/lsra.h @@ -1083,8 +1083,7 @@ class LinearScan : public LinearScanInterface // insert refpositions representing prolog zero-inits which will be added later void insertZeroInitRefPositions(); - // add physreg refpositions for a tree node, based on calling convention and instruction selection predictions - void addRefsForPhysRegMask(regMaskTP mask, LsraLocation currentLoc, RefType refType, bool isLastUse); + void addKillForRegs(regMaskTP mask, LsraLocation currentLoc); void resolveConflictingDefAndUse(Interval* interval, RefPosition* defRefPosition); @@ -1262,6 +1261,7 @@ class LinearScan : public LinearScanInterface void setIntervalAsSplit(Interval* interval); void spillInterval(Interval* interval, RefPosition* fromRefPosition DEBUGARG(RefPosition* toRefPosition)); + void processKills(RefPosition* killRefPosition); void spillGCRefs(RefPosition* killRefPosition); /***************************************************************************** @@ -1581,6 +1581,7 @@ class LinearScan : public LinearScanInterface LSRA_EVENT_FREE_REGS, LSRA_EVENT_UPPER_VECTOR_SAVE, LSRA_EVENT_UPPER_VECTOR_RESTORE, + LSRA_EVENT_KILL_REGS, // Characteristics of the current RefPosition LSRA_EVENT_INCREMENT_RANGE_END, // ??? @@ -1606,7 +1607,8 @@ class LinearScan : public LinearScanInterface Interval* interval = nullptr, regNumber reg = REG_NA, BasicBlock* currentBlock = nullptr, - RegisterScore registerScore = NONE); + RegisterScore registerScore = NONE, + regMaskTP regMask = RBM_NONE); void validateIntervals(); @@ -1733,6 +1735,11 @@ class LinearScan : public LinearScanInterface // Ordered list of RefPositions RefPositionList refPositions; + // Head of linked list of RefTypeKill ref positions + RefPosition* killHead; + // Tail slot of linked list of RefTypeKill ref positions + RefPosition** killTail; + // Per-block variable location mappings: an array indexed by block number that yields a // pointer to an array of regNumber, one per variable. VarToRegMap* inVarToRegMaps; @@ -1897,7 +1904,7 @@ class LinearScan : public LinearScanInterface regMaskTP fixedRegs; LsraLocation nextFixedRef[REG_COUNT]; - void updateNextFixedRef(RegRecord* regRecord, RefPosition* nextRefPosition); + void updateNextFixedRef(RegRecord* regRecord, RefPosition* nextRefPosition, RefPosition* nextKill); LsraLocation getNextFixedRef(regNumber regNum, var_types regType) { LsraLocation loc = nextFixedRef[regNum]; @@ -2717,7 +2724,7 @@ class RefPosition bool IsPhysRegRef() { - return ((refType == RefTypeFixedReg) || (refType == RefTypeKill)); + return (refType == RefTypeFixedReg); } void setRegOptional(bool val) diff --git a/src/coreclr/jit/lsraarmarch.cpp b/src/coreclr/jit/lsraarmarch.cpp index f88173e05e2092..cf5302dee9c711 100644 --- a/src/coreclr/jit/lsraarmarch.cpp +++ b/src/coreclr/jit/lsraarmarch.cpp @@ -419,7 +419,7 @@ int LinearScan::BuildCall(GenTreeCall* call) // We could use RefTypeKill, but RefTypeFixedReg is used less commonly, so the check for delayRegFree // during register allocation should be cheaper in terms of TP. - RefPosition* pos = newRefPosition(REG_SWIFT_ERROR, currentLoc, RefTypeFixedReg, call, RBM_SWIFT_ERROR); + RefPosition* pos = newRefPosition(REG_SWIFT_ERROR, currentLoc + 1, RefTypeFixedReg, call, RBM_SWIFT_ERROR); setDelayFree(pos); } #endif // SWIFT_SUPPORT diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 22cba5900a7ddd..4a4af7725dd4da 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -498,7 +498,7 @@ void LinearScan::associateRefPosWithInterval(RefPosition* rp) } else { - assert((rp->refType == RefTypeBB) || (rp->refType == RefTypeKillGCRefs)); + assert((rp->refType == RefTypeBB) || (rp->refType == RefTypeKillGCRefs) || (rp->refType == RefTypeKill)); } } @@ -570,7 +570,7 @@ RefPosition* LinearScan::newRefPosition(Interval* theInterval, } else { - assert(theRefType == RefTypeBB || theRefType == RefTypeKillGCRefs); + assert(theRefType == RefTypeBB || theRefType == RefTypeKillGCRefs || theRefType == RefTypeKill); } #ifdef DEBUG if (theInterval != nullptr && regType(theInterval->registerType) == FloatRegisterType) @@ -689,18 +689,14 @@ bool LinearScan::isContainableMemoryOp(GenTree* node) } //------------------------------------------------------------------------ -// addRefsForPhysRegMask: Adds RefPositions of the given type for all the registers in 'mask'. +// addKillForRegs: Adds a RefTypeKill ref position for the given registers. // // Arguments: // mask - the mask (set) of registers. // currentLoc - the location at which they should be added -// refType - the type of refposition -// isLastUse - true IFF this is a last use of the register // -void LinearScan::addRefsForPhysRegMask(regMaskTP mask, LsraLocation currentLoc, RefType refType, bool isLastUse) +void LinearScan::addKillForRegs(regMaskTP mask, LsraLocation currentLoc) { - assert(refType == RefTypeKill); - // The mask identifies a set of registers that will be used during // codegen. Mark these as modified here, so when we do final frame // layout, we'll know about all these registers. This is especially @@ -712,19 +708,10 @@ void LinearScan::addRefsForPhysRegMask(regMaskTP mask, LsraLocation currentLoc, // modified until codegen, which is too late. compiler->codeGen->regSet.rsSetRegsModified(mask DEBUGARG(true)); - for (regMaskTP candidates = mask; candidates != RBM_NONE;) - { - regNumber reg = genFirstRegNumFromMaskAndToggle(candidates); - // This assumes that these are all "special" RefTypes that - // don't need to be recorded on the tree (hence treeNode is nullptr) - RefPosition* pos = newRefPosition(reg, currentLoc, refType, nullptr, - genRegMask(reg)); // This MUST occupy the physical register (obviously) + RefPosition* pos = newRefPosition((Interval*)nullptr, currentLoc, RefTypeKill, nullptr, mask); - if (isLastUse) - { - pos->lastUse = true; - } - } + *killTail = pos; + killTail = &pos->nextRefPosition; } //------------------------------------------------------------------------ @@ -1127,7 +1114,7 @@ bool LinearScan::buildKillPositionsForNode(GenTree* tree, LsraLocation currentLo if (killMask != RBM_NONE) { - addRefsForPhysRegMask(killMask, currentLoc, RefTypeKill, true); + addKillForRegs(killMask, currentLoc); // TODO-CQ: It appears to be valuable for both fp and int registers to avoid killing the callee // save regs on infrequently executed paths. However, it results in a large number of asmDiffs, @@ -2546,7 +2533,7 @@ void LinearScan::buildIntervals() if ((block == compiler->fgFirstBB) && compiler->lvaHasAnySwiftStackParamToReassemble()) { assert(compiler->fgFirstBBisScratch()); - addRefsForPhysRegMask(genRegMask(REG_SCRATCH), currentLoc + 1, RefTypeKill, true); + addKillForRegs(genRegMask(REG_SCRATCH), currentLoc + 1); currentLoc += 2; } @@ -2564,7 +2551,7 @@ void LinearScan::buildIntervals() // Poisoning uses REG_SCRATCH for small vars and memset helper for big vars. killed = genRegMask(REG_SCRATCH) | compiler->compHelperCallKillSet(CORINFO_HELP_NATIVE_MEMSET); #endif - addRefsForPhysRegMask(killed, currentLoc + 1, RefTypeKill, true); + addKillForRegs(killed, currentLoc + 1); currentLoc += 2; } diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index 6abc86aab0ed5e..7109c9087ac4e1 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -1395,7 +1395,7 @@ int LinearScan::BuildCall(GenTreeCall* call) // We could use RefTypeKill, but RefTypeFixedReg is used less commonly, so the check for delayRegFree // during register allocation should be cheaper in terms of TP. - RefPosition* pos = newRefPosition(REG_SWIFT_ERROR, currentLoc, RefTypeFixedReg, call, RBM_SWIFT_ERROR); + RefPosition* pos = newRefPosition(REG_SWIFT_ERROR, currentLoc + 1, RefTypeFixedReg, call, RBM_SWIFT_ERROR); setDelayFree(pos); } #endif // SWIFT_SUPPORT From fc76b1cac3f02cc9729f6682d6850fd7982e9fe5 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Thu, 2 May 2024 08:36:08 -0400 Subject: [PATCH 217/248] Fix some TensorPrimitives tests failing for me locally with checked builds (#101745) This is just: - Adding tolerance checks for NFloat that are the same as for float/double - Adding tolerance for MultiplyAddEstimate that matches our other tolerances for "Estimate" functions This addresses everything failing for me locally, but it doesn't match the failure spike recently highlighted in CI. --- .../System.Numerics.Tensors/tests/Helpers.cs | 13 ++- .../tests/TensorPrimitives.Generic.cs | 105 +++++++++++------- 2 files changed, 78 insertions(+), 40 deletions(-) diff --git a/src/libraries/System.Numerics.Tensors/tests/Helpers.cs b/src/libraries/System.Numerics.Tensors/tests/Helpers.cs index a43f770bd16bd4..b78d0eb01bda27 100644 --- a/src/libraries/System.Numerics.Tensors/tests/Helpers.cs +++ b/src/libraries/System.Numerics.Tensors/tests/Helpers.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; namespace System.Numerics.Tensors.Tests { @@ -72,8 +73,18 @@ public static bool IsEqualWithTolerance(float expected, float actual, float? tol { return (T?)(object)halfTolerance; } + else if (typeof(T) == typeof(NFloat)) + { + if (IntPtr.Size == 8 && doubleTolerance != null) + { + return (T?)(object)(NFloat)doubleTolerance; + } + else if (IntPtr.Size == 4 && floatTolerance != null) + { + return (T?)(object)(NFloat)doubleTolerance; + } + } #endif - return null; } } diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs b/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs index 0ad762f9401ed9..1875b6059b7fa9 100644 --- a/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs +++ b/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs @@ -480,8 +480,11 @@ public void SpanDestinationFunctions_ValueRange(SpanDestinationDelegate tensorPr #pragma warning disable xUnit1026 // Theory methods should use all of their parameters [Theory] [MemberData(nameof(SpanDestinationFunctionsToTest))] - public void SpanDestinationFunctions_ThrowsForTooShortDestination(SpanDestinationDelegate tensorPrimitivesMethod, Func _, T? __ = null) + public void SpanDestinationFunctions_ThrowsForTooShortDestination(SpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + Assert.All(Helpers.TensorLengths, tensorLength => { using BoundedMemory x = CreateAndFillTensor(tensorLength); @@ -493,8 +496,11 @@ public void SpanDestinationFunctions_ThrowsForTooShortDestination(SpanDestinatio [Theory] [MemberData(nameof(SpanDestinationFunctionsToTest))] - public void SpanDestinationFunctions_ThrowsForOverlapppingInputsWithOutputs(SpanDestinationDelegate tensorPrimitivesMethod, Func _, T? __ = null) + public void SpanDestinationFunctions_ThrowsForOverlapppingInputsWithOutputs(SpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + T[] array = new T[10]; AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(0, 2))); AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(2, 2))); @@ -946,15 +952,15 @@ public static IEnumerable SpanSpanSpanDestinationFunctionsToTest() { yield return Create(TensorPrimitives.FusedMultiplyAdd, T.FusedMultiplyAdd); yield return Create(TensorPrimitives.Lerp, T.Lerp); - yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available + yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd, T.CreateTruncating(Helpers.DefaultToleranceForEstimates)); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available - static object[] Create(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) - => new object[] { tensorPrimitivesMethod, expectedMethod }; + static object[] Create(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) + => new object[] { tensorPrimitivesMethod, expectedMethod, tolerance }; } [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_AllLengths(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanSpanDestination_AllLengths(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -966,14 +972,14 @@ public void SpanSpanSpanDestination_AllLengths(SpanSpanSpanDestinationDelegate t tensorPrimitivesMethod(x, y, z, destination); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_InPlace(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanSpanDestination_InPlace(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -984,14 +990,14 @@ public void SpanSpanSpanDestination_InPlace(SpanSpanSpanDestinationDelegate tens for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(xOrig[i], xOrig[i], xOrig[i]), x[i]); + AssertEqualTolerance(expectedMethod(xOrig[i], xOrig[i], xOrig[i]), x[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengths, tensorLength => { @@ -1005,7 +1011,7 @@ public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegat tensorPrimitivesMethod(x.Span, y.Span, z.Span, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i], tolerance); } }, x); @@ -1014,7 +1020,7 @@ public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegat tensorPrimitivesMethod(x.Span, y.Span, z.Span, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i], tolerance); } }, y); @@ -1023,7 +1029,7 @@ public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegat tensorPrimitivesMethod(x.Span, y.Span, z.Span, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i], tolerance); } }, z); }); @@ -1031,8 +1037,11 @@ public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegat [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_ThrowsForMismatchedLengths(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanSpanSpanDestination_ThrowsForMismatchedLengths(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + Assert.All(Helpers.TensorLengths, tensorLength => { using BoundedMemory x = CreateAndFillTensor(tensorLength); @@ -1051,8 +1060,11 @@ public void SpanSpanSpanDestination_ThrowsForMismatchedLengths(SpanSpanSpanDesti [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_ThrowsForTooShortDestination(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanSpanSpanDestination_ThrowsForTooShortDestination(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + Assert.All(Helpers.TensorLengths, tensorLength => { using BoundedMemory x = CreateAndFillTensor(tensorLength); @@ -1066,8 +1078,11 @@ public void SpanSpanSpanDestination_ThrowsForTooShortDestination(SpanSpanSpanDes [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_ThrowsForOverlapppingInputsWithOutputs(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanSpanSpanDestination_ThrowsForOverlapppingInputsWithOutputs(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + T[] array = new T[10]; AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(5, 2), array.AsSpan(7, 2), array.AsSpan(0, 2))); AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(5, 2), array.AsSpan(7, 2), array.AsSpan(2, 2))); @@ -1082,15 +1097,15 @@ public static IEnumerable SpanSpanScalarDestinationFunctionsToTest() { yield return Create(TensorPrimitives.FusedMultiplyAdd, T.FusedMultiplyAdd); yield return Create(TensorPrimitives.Lerp, T.Lerp); - yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available + yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd, T.CreateTruncating(Helpers.DefaultToleranceForEstimates)); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available - static object[] Create(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) - => new object[] { tensorPrimitivesMethod, expectedMethod }; + static object[] Create(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) + => new object[] { tensorPrimitivesMethod, expectedMethod, tolerance }; } [Theory] [MemberData(nameof(SpanSpanScalarDestinationFunctionsToTest))] - public void SpanSpanScalarDestination_AllLengths(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanScalarDestination_AllLengths(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -1103,14 +1118,14 @@ public void SpanSpanScalarDestination_AllLengths(SpanSpanScalarDestinationDelega for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanSpanScalarDestinationFunctionsToTest))] - public void SpanSpanScalarDestination_InPlace(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanScalarDestination_InPlace(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -1122,14 +1137,14 @@ public void SpanSpanScalarDestination_InPlace(SpanSpanScalarDestinationDelegate for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(xOrig[i], xOrig[i], z), x[i]); + AssertEqualTolerance(expectedMethod(xOrig[i], xOrig[i], z), x[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanSpanScalarDestinationFunctionsToTest))] - public void SpanSpanScalarDestination_SpecialValues(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanScalarDestination_SpecialValues(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengths, tensorLength => { @@ -1143,7 +1158,7 @@ public void SpanSpanScalarDestination_SpecialValues(SpanSpanScalarDestinationDel tensorPrimitivesMethod(x.Span, y.Span, z, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i], tolerance); } }, x); @@ -1152,7 +1167,7 @@ public void SpanSpanScalarDestination_SpecialValues(SpanSpanScalarDestinationDel tensorPrimitivesMethod(x.Span, y.Span, z, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i], tolerance); } }, y); }); @@ -1160,8 +1175,11 @@ public void SpanSpanScalarDestination_SpecialValues(SpanSpanScalarDestinationDel [Theory] [MemberData(nameof(SpanSpanScalarDestinationFunctionsToTest))] - public void SpanSpanScalarDestination_ThrowsForTooShortDestination(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanSpanScalarDestination_ThrowsForTooShortDestination(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + Assert.All(Helpers.TensorLengths, tensorLength => { using BoundedMemory x = CreateAndFillTensor(tensorLength); @@ -1175,8 +1193,11 @@ public void SpanSpanScalarDestination_ThrowsForTooShortDestination(SpanSpanScala [Theory] [MemberData(nameof(SpanSpanScalarDestinationFunctionsToTest))] - public void SpanSpanScalarDestination_ThrowsForOverlapppingInputsWithOutputs(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanSpanScalarDestination_ThrowsForOverlapppingInputsWithOutputs(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + T[] array = new T[10]; AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(4, 2), default, array.AsSpan(0, 2))); AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(4, 2), default, array.AsSpan(2, 2))); @@ -1190,15 +1211,15 @@ public static IEnumerable SpanScalarSpanDestinationFunctionsToTest() { yield return Create(TensorPrimitives.FusedMultiplyAdd, T.FusedMultiplyAdd); yield return Create(TensorPrimitives.Lerp, T.Lerp); - yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available + yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd, T.CreateTruncating(Helpers.DefaultToleranceForEstimates)); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available - static object[] Create(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + static object[] Create(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) => new object[] { tensorPrimitivesMethod, expectedMethod }; } [Theory] [MemberData(nameof(SpanScalarSpanDestinationFunctionsToTest))] - public void SpanScalarSpanDestination_AllLengths(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanScalarSpanDestination_AllLengths(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -1211,14 +1232,14 @@ public void SpanScalarSpanDestination_AllLengths(SpanScalarSpanDestinationDelega for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanScalarSpanDestinationFunctionsToTest))] - public void SpanScalarSpanDestination_InPlace(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanScalarSpanDestination_InPlace(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -1230,14 +1251,14 @@ public void SpanScalarSpanDestination_InPlace(SpanScalarSpanDestinationDelegate for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(xOrig[i], y, xOrig[i]), x[i]); + AssertEqualTolerance(expectedMethod(xOrig[i], y, xOrig[i]), x[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanScalarSpanDestinationFunctionsToTest))] - public void SpanScalarSpanDestination_SpecialValues(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanScalarSpanDestination_SpecialValues(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengths, tensorLength => { @@ -1251,7 +1272,7 @@ public void SpanScalarSpanDestination_SpecialValues(SpanScalarSpanDestinationDel tensorPrimitivesMethod(x.Span, y, z.Span, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i], tolerance); } }, x); @@ -1260,7 +1281,7 @@ public void SpanScalarSpanDestination_SpecialValues(SpanScalarSpanDestinationDel tensorPrimitivesMethod(x.Span, y, z.Span, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i], tolerance); } }, z); }); @@ -1268,8 +1289,11 @@ public void SpanScalarSpanDestination_SpecialValues(SpanScalarSpanDestinationDel [Theory] [MemberData(nameof(SpanScalarSpanDestinationFunctionsToTest))] - public void SpanScalarSpanDestination_ThrowsForTooShortDestination(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanScalarSpanDestination_ThrowsForTooShortDestination(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + Assert.All(Helpers.TensorLengths, tensorLength => { using BoundedMemory x = CreateAndFillTensor(tensorLength); @@ -1283,8 +1307,11 @@ public void SpanScalarSpanDestination_ThrowsForTooShortDestination(SpanScalarSpa [Theory] [MemberData(nameof(SpanScalarSpanDestinationFunctionsToTest))] - public void SpanScalarSpanDestination_ThrowsForOverlapppingInputsWithOutputs(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanScalarSpanDestination_ThrowsForOverlapppingInputsWithOutputs(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + T[] array = new T[10]; AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), default, array.AsSpan(4, 2), array.AsSpan(0, 2))); AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), default, array.AsSpan(4, 2), array.AsSpan(2, 2))); From ee93104aa0e7ac77ca7e4c6db9873356a9e3e622 Mon Sep 17 00:00:00 2001 From: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Thu, 2 May 2024 16:38:14 +0200 Subject: [PATCH 218/248] Removed unused sessions from SSL_CTX internal cache (#101684) * Disable OpenSSL internal SSL_SESSION cache for clients * Attempt no. 2 * Revert "Disable OpenSSL internal SSL_SESSION cache for clients" This reverts commit 56a308e88171bb797d13d50953b83262cd8289cd. --- .../Interop.OpenSsl.cs | 2 +- .../Interop.SslCtx.cs | 36 +++++++++++++------ .../entrypoints.c | 1 + .../opensslshim.h | 2 ++ .../pal_ssl.c | 5 +++ .../pal_ssl.h | 5 +++ 6 files changed, 40 insertions(+), 11 deletions(-) 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 8636bbe4884866..171980d0a7654a 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 @@ -748,7 +748,7 @@ private static unsafe void RemoveSessionCallback(IntPtr ctx, IntPtr session) IntPtr name = Ssl.SessionGetHostname(session); Debug.Assert(name != IntPtr.Zero); - ctxHandle.RemoveSession(name); + ctxHandle.RemoveSession(name, session); } [UnmanagedCallersOnly] diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs index 5baa776d9d5a8a..d92e15e940e65e 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs @@ -39,6 +39,9 @@ internal static partial class Ssl [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetCaching")] internal static unsafe partial int SslCtxSetCaching(SafeSslContextHandle ctx, int mode, int cacheSize, int contextIdLength, Span contextId, delegate* unmanaged neewSessionCallback, delegate* unmanaged removeSessionCallback); + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxRemoveSession")] + internal static unsafe partial void SslCtxRemoveSession(SafeSslContextHandle ctx, IntPtr session); + internal static bool AddExtraChainCertificates(SafeSslContextHandle ctx, ReadOnlyCollection chain) { // send pre-computed list of intermediates. @@ -142,27 +145,38 @@ internal bool TryAddSession(IntPtr namePtr, IntPtr session) // This will use strdup() so it is safe to pass in raw pointer. Interop.Ssl.SessionSetHostname(session, namePtr); + IntPtr oldSession = IntPtr.Zero; + lock (_sslSessions) { if (!_sslSessions.TryAdd(targetName, session)) { - if (_sslSessions.Remove(targetName, out IntPtr oldSession)) - { - Interop.Ssl.SessionFree(oldSession); - } - + // session to this target host exists, replace it + _sslSessions.Remove(targetName, out oldSession); bool added = _sslSessions.TryAdd(targetName, session); Debug.Assert(added); } } + if (oldSession != IntPtr.Zero) + { + // remove old session also from the internal OpenSSL cache + // and drop reference count. Since SSL_CTX_remove_session + // will call session_remove_cb, we need to do this outside + // of _sslSessions lock to avoid deadlock with another thread + // which could be holding SSL_CTX lock and trying to acquire + // _sslSessions lock. + Interop.Ssl.SslCtxRemoveSession(this, oldSession); + Interop.Ssl.SessionFree(oldSession); + } + return true; } return false; } - internal void RemoveSession(IntPtr namePtr) + internal void RemoveSession(IntPtr namePtr, IntPtr session) { Debug.Assert(_sslSessions != null); @@ -171,11 +185,14 @@ internal void RemoveSession(IntPtr namePtr) if (_sslSessions != null && targetName != null) { - IntPtr oldSession; - bool removed; + IntPtr oldSession = IntPtr.Zero; + bool removed = false; lock (_sslSessions) { - removed = _sslSessions.Remove(targetName, out oldSession); + if (_sslSessions.TryGetValue(targetName, out IntPtr existingSession) && existingSession == session) + { + removed = _sslSessions.Remove(targetName, out oldSession); + } } if (removed) @@ -209,7 +226,6 @@ internal bool TrySetSession(SafeSslHandle sslHandle, string name) // This will increase reference count on the session as needed. // We need to hold lock here to prevent session being deleted before the call is done. Interop.Ssl.SslSetSession(sslHandle, session); - return true; } } diff --git a/src/native/libs/System.Security.Cryptography.Native/entrypoints.c b/src/native/libs/System.Security.Cryptography.Native/entrypoints.c index a8bcbde96e5116..cb4b621e27fa37 100644 --- a/src/native/libs/System.Security.Cryptography.Native/entrypoints.c +++ b/src/native/libs/System.Security.Cryptography.Native/entrypoints.c @@ -312,6 +312,7 @@ static const Entry s_cryptoNative[] = DllImportEntry(CryptoNative_IsSslStateOK) DllImportEntry(CryptoNative_SslCtxAddExtraChainCert) DllImportEntry(CryptoNative_SslCtxSetCaching) + DllImportEntry(CryptoNative_SslCtxRemoveSession) DllImportEntry(CryptoNative_SslCtxSetCiphers) DllImportEntry(CryptoNative_SslCtxSetDefaultOcspCallback) DllImportEntry(CryptoNative_SslCtxSetEncryptionPolicy) diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h index 9dd878858822b7..7837810de715e2 100644 --- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h @@ -555,6 +555,7 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen); REQUIRED_FUNCTION(SSL_CTX_new) \ REQUIRED_FUNCTION(SSL_CTX_sess_set_new_cb) \ REQUIRED_FUNCTION(SSL_CTX_sess_set_remove_cb) \ + REQUIRED_FUNCTION(SSL_CTX_remove_session) \ LIGHTUP_FUNCTION(SSL_CTX_set_alpn_protos) \ LIGHTUP_FUNCTION(SSL_CTX_set_alpn_select_cb) \ REQUIRED_FUNCTION(SSL_CTX_set_cipher_list) \ @@ -1083,6 +1084,7 @@ FOR_ALL_OPENSSL_FUNCTIONS #define SSL_CTX_new SSL_CTX_new_ptr #define SSL_CTX_sess_set_new_cb SSL_CTX_sess_set_new_cb_ptr #define SSL_CTX_sess_set_remove_cb SSL_CTX_sess_set_remove_cb_ptr +#define SSL_CTX_remove_session SSL_CTX_remove_session_ptr #define SSL_CTX_set_alpn_protos SSL_CTX_set_alpn_protos_ptr #define SSL_CTX_set_alpn_select_cb SSL_CTX_set_alpn_select_cb_ptr #define SSL_CTX_set_cipher_list SSL_CTX_set_cipher_list_ptr diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c index e6bd41143c1655..e320d1c73d776b 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c @@ -701,6 +701,11 @@ int CryptoNative_SslCtxSetCaching(SSL_CTX* ctx, int mode, int cacheSize, int con return retValue; } +int CryptoNative_SslCtxRemoveSession(SSL_CTX* ctx, SSL_SESSION* session) +{ + return SSL_CTX_remove_session(ctx, session); +} + const char* CryptoNative_SslGetServerName(SSL* ssl) { return SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h index 3c63564cc4e59f..9c9d7026119c5c 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h @@ -167,6 +167,11 @@ Sets session caching. 0 is disabled. */ PALEXPORT int CryptoNative_SslCtxSetCaching(SSL_CTX* ctx, int mode, int cacheSize, int contextIdLength, uint8_t* contextId, SslCtxNewSessionCallback newSessionCb, SslCtxRemoveSessionCallback removeSessionCb); +/* +Removes a session from internal cache. +*/ +PALEXPORT int CryptoNative_SslCtxRemoveSession(SSL_CTX* ctx, SSL_SESSION* session); + /* Sets callback to log TLS session keys */ From 71e9c462d8603df86105935649e9c2275e3e91b6 Mon Sep 17 00:00:00 2001 From: Koundinya Veluri Date: Thu, 2 May 2024 09:51:50 -0700 Subject: [PATCH 219/248] Notify the debugger of a cross-thread dependency in Lock (#101501) * Notify the debugger of a cross-thread dependency in Lock When a FuncEval tries to acquire a Lock that is held by a different thread, notify the debugger of a cross-thread dependency. --- .../src/System/Threading/Lock.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs index 8658ab6caafb11..4dadf49bdfd4a4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs @@ -334,6 +334,17 @@ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) return new ThreadId(0); } + // + // At this point, a full lock attempt has been made, and it's time to retry or wait for the lock. + // + + // Notify the debugger that this thread is about to wait for a lock that is likely held by another thread. The + // debugger may choose to enable other threads to run to help resolve the dependency, or it may choose to abort the + // FuncEval here. The lock state is consistent here for an abort, whereas letting a FuncEval continue to run could + // lead to the FuncEval timing out and potentially aborting at an arbitrary place where the lock state may not be + // consistent. + Debugger.NotifyOfCrossThreadDependency(); + if (LazyInitializeOrEnter() == TryLockResult.Locked) { goto Locked; From 2d2a5a2c75fcf078c408982dca7c056a02ca3a2a Mon Sep 17 00:00:00 2001 From: Koundinya Veluri Date: Thu, 2 May 2024 09:52:48 -0700 Subject: [PATCH 220/248] Fix Lock spin-waiting on single-proc machines (#101513) * Fix Lock spin-waiting on single-proc machines Small fix to check for a single proc during initialization. Also renamed things referring to "minSpinCount" to clarify it a bit. --- .../src/System/Threading/Lock.NativeAot.cs | 4 +- .../src/System/Threading/Lock.NonNativeAot.cs | 2 +- .../src/System/Threading/Lock.cs | 50 +++++++++++++------ 3 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs index 6e68125f07e32f..999d4061543ed5 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs @@ -18,7 +18,7 @@ public sealed partial class Lock private static int s_staticsInitializationStage; private static bool s_isSingleProcessor; private static short s_maxSpinCount; - private static short s_minSpinCount; + private static short s_minSpinCountForAdaptiveSpin; /// /// Initializes a new instance of the class. @@ -202,7 +202,7 @@ private static bool TryInitializeStatics() // here. Initialize s_isSingleProcessor first, as it may be used by other initialization afterwards. s_isSingleProcessor = RuntimeImports.RhGetProcessCpuCount() == 1; s_maxSpinCount = DetermineMaxSpinCount(); - s_minSpinCount = DetermineMinSpinCount(); + s_minSpinCountForAdaptiveSpin = DetermineMinSpinCountForAdaptiveSpin(); } // Also initialize some types that are used later to prevent potential class construction cycles. If diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.NonNativeAot.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.NonNativeAot.cs index 8a05f1e7fddc70..bd3a0be6902af9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.NonNativeAot.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.NonNativeAot.cs @@ -9,7 +9,7 @@ namespace System.Threading public sealed partial class Lock { private static readonly short s_maxSpinCount = DetermineMaxSpinCount(); - private static readonly short s_minSpinCount = DetermineMinSpinCount(); + private static readonly short s_minSpinCountForAdaptiveSpin = DetermineMinSpinCountForAdaptiveSpin(); /// /// Initializes a new instance of the class. diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs index 4dadf49bdfd4a4..4572c9c310ecef 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs @@ -37,7 +37,15 @@ public sealed partial class Lock private uint _state; // see State for layout private uint _recursionCount; + + // This field serves a few purposes currently: + // - When positive, it indicates the number of spin-wait iterations that most threads would do upon contention + // - When zero, it indicates that spin-waiting is to be attempted by a thread to test if it is successful + // - When negative, it serves as a rough counter for contentions that would increment it towards zero + // + // See references to this field and "AdaptiveSpin" in TryEnterSlow for more information. private short _spinCount; + private ushort _waiterStartTimeMs; private AutoResetEvent? _waitEvent; @@ -297,7 +305,7 @@ private void ExitImpl() } } - private static bool IsAdaptiveSpinEnabled(short minSpinCount) => minSpinCount <= 0; + private static bool IsAdaptiveSpinEnabled(short minSpinCountForAdaptiveSpin) => minSpinCountForAdaptiveSpin <= 0; [MethodImpl(MethodImplOptions.NoInlining)] private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) @@ -350,20 +358,19 @@ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) goto Locked; } - bool isSingleProcessor = IsSingleProcessor; short maxSpinCount = s_maxSpinCount; if (maxSpinCount == 0) { goto Wait; } - short minSpinCount = s_minSpinCount; + short minSpinCountForAdaptiveSpin = s_minSpinCountForAdaptiveSpin; short spinCount = _spinCount; if (spinCount < 0) { // When negative, the spin count serves as a counter for contentions such that a spin-wait can be attempted // periodically to see if it would be beneficial. Increment the spin count and skip spin-waiting. - Debug.Assert(IsAdaptiveSpinEnabled(minSpinCount)); + Debug.Assert(IsAdaptiveSpinEnabled(minSpinCountForAdaptiveSpin)); _spinCount = (short)(spinCount + 1); goto Wait; } @@ -388,7 +395,7 @@ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) for (short spinIndex = 0; ;) { - LowLevelSpinWaiter.Wait(spinIndex, SpinSleep0Threshold, isSingleProcessor); + LowLevelSpinWaiter.Wait(spinIndex, SpinSleep0Threshold, isSingleProcessor: false); if (++spinIndex >= spinCount) { @@ -405,7 +412,7 @@ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) if (tryLockResult == TryLockResult.Locked) { - if (isFirstSpinner && IsAdaptiveSpinEnabled(minSpinCount)) + if (isFirstSpinner && IsAdaptiveSpinEnabled(minSpinCountForAdaptiveSpin)) { // Since the first spinner does a full-length spin-wait, and to keep upward and downward changes to the // spin count more balanced, only the first spinner adjusts the spin count @@ -426,7 +433,7 @@ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) // Unregister the spinner and try to acquire the lock tryLockResult = State.TryLockAfterSpinLoop(this); - if (isFirstSpinner && IsAdaptiveSpinEnabled(minSpinCount)) + if (isFirstSpinner && IsAdaptiveSpinEnabled(minSpinCountForAdaptiveSpin)) { // Since the first spinner does a full-length spin-wait, and to keep upward and downward changes to the // spin count more balanced, only the first spinner adjusts the spin count @@ -444,7 +451,7 @@ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) // number of contentions, the first spinner will attempt a spin-wait again to see if it is effective. Debug.Assert(tryLockResult == TryLockResult.Wait); spinCount = _spinCount; - _spinCount = spinCount > 0 ? (short)(spinCount - 1) : minSpinCount; + _spinCount = spinCount > 0 ? (short)(spinCount - 1) : minSpinCountForAdaptiveSpin; } } @@ -517,7 +524,7 @@ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) break; } - LowLevelSpinWaiter.Wait(spinIndex, SpinSleep0Threshold, isSingleProcessor); + LowLevelSpinWaiter.Wait(spinIndex, SpinSleep0Threshold, isSingleProcessor: false); } if (acquiredLock) @@ -661,14 +668,25 @@ internal nint LockIdForEvents internal ulong OwningThreadId => _owningThreadId; - private static short DetermineMaxSpinCount() => - AppContextConfigHelper.GetInt16Config( - "System.Threading.Lock.SpinCount", - "DOTNET_Lock_SpinCount", - DefaultMaxSpinCount, - allowNegative: false); + private static short DetermineMaxSpinCount() + { + if (IsSingleProcessor) + { + return 0; + } + + return + AppContextConfigHelper.GetInt16Config( + "System.Threading.Lock.SpinCount", + "DOTNET_Lock_SpinCount", + DefaultMaxSpinCount, + allowNegative: false); + } - private static short DetermineMinSpinCount() + // When the returned value is zero or negative, indicates the lowest value that the _spinCount field will have when + // adaptive spin chooses to pause spin-waiting, see the comment on the _spinCount field for more information. When the + // returned value is positive, adaptive spin is disabled. + private static short DetermineMinSpinCountForAdaptiveSpin() { // The config var can be set to -1 to disable adaptive spin short adaptiveSpinPeriod = From 06ae8ff0c7b1070aa5a641e70adb1891c896388b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Thu, 2 May 2024 19:23:58 +0200 Subject: [PATCH 221/248] Don't run smoke AOT tests on Firefox (#101802) --- eng/pipelines/common/templates/wasm-library-aot-tests.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/eng/pipelines/common/templates/wasm-library-aot-tests.yml b/eng/pipelines/common/templates/wasm-library-aot-tests.yml index cbafd9c6b35531..2336f98401515a 100644 --- a/eng/pipelines/common/templates/wasm-library-aot-tests.yml +++ b/eng/pipelines/common/templates/wasm-library-aot-tests.yml @@ -35,6 +35,5 @@ jobs: - WasmTestOnV8 - ${{ if eq(platform, 'browser_wasm_win') }}: - WasmTestOnChrome - - WasmTestOnFirefox - ${{ if or(eq(platform, 'wasi_wasm_win'), eq(platform, 'wasi_wasm')) }}: - WasmTestOnWasmtime From 5da5873e19efc26e90f142fad5db7c337097daf0 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Thu, 2 May 2024 21:18:40 +0200 Subject: [PATCH 222/248] ARM64: Optimize Volatile.Read/Write for floats (#101359) --- src/coreclr/jit/lower.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index a3f1ca141af0dc..a35c921facfcf0 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -8871,6 +8871,27 @@ GenTree* Lowering::LowerIndir(GenTreeIndir* ind) } #endif +#ifdef TARGET_ARM64 + LIR::Use use; + if (ind->OperIs(GT_IND) && ind->IsVolatile() && varTypeIsFloating(ind) && BlockRange().TryGetUse(ind, &use)) + { + // Convert "IND(addr)" to "BitCast(IND(addr))" + // for volatile loads since there is no ldar for SIMD regs + var_types targetType = ind->TypeGet(); + ind->ChangeType(ind->TypeIs(TYP_DOUBLE) ? TYP_LONG : TYP_INT); + + // Now it might be eligible for some addressing modes with LDAPUR: + const bool isContainable = IsInvariantInRange(ind->Addr(), ind); + TryCreateAddrMode(ind->Addr(), isContainable, ind); + + // Wrap the resulting IND into BITCAST: + GenTree* castOp = comp->gtNewBitCastNode(targetType, ind); + BlockRange().InsertAfter(ind, castOp); + use.ReplaceWith(castOp); + return castOp; + } +#endif + // TODO-Cleanup: We're passing isContainable = true but ContainCheckIndir rejects // address containment in some cases so we end up creating trivial (reg + offfset) // or (reg + reg) LEAs that are not necessary. @@ -9524,6 +9545,21 @@ void Lowering::TryRetypingFloatingPointStoreToIntegerStore(GenTree* store) return; } + // Convert "STOREIND(addr, floatVal)" to "STORIND(addr, BitCast(floatVal))" + // for volatile stores since there is no stlr for SIMD regs +#ifdef TARGET_ARM64 + if (store->OperIs(GT_STOREIND) && store->AsStoreInd()->IsVolatile()) + { + GenTreeStoreInd* ind = store->AsStoreInd(); + ind->ChangeType(ind->TypeIs(TYP_DOUBLE) ? TYP_LONG : TYP_INT); + GenTree* castOp = comp->gtNewBitCastNode(ind->TypeGet(), ind->Data()); + BlockRange().InsertAfter(ind->Data(), castOp); + ind->Data() = castOp; + LowerNode(castOp); + return; + } +#endif + // We only want to transform memory stores, not definitions of candidate locals. // if (store->OperIs(GT_STORE_LCL_VAR) && !comp->lvaGetDesc(store->AsLclVar())->lvDoNotEnregister) From 24ded2865fe62786ea4ad4c38f42f6a0083b34e6 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 2 May 2024 21:21:15 +0200 Subject: [PATCH 223/248] JIT: Remove LSRA arm32 quirk (#101791) For arm32 this query can return an earlier location if the upper half register assigned to a TYP_DOUBLE interval has an earlier ref. --- src/coreclr/jit/lsra.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 8f0875d7b09fc9..2bbccaf2b6b1bd 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -5874,6 +5874,8 @@ void LinearScan::allocateRegisters() continue; } + assert(!currentRefPosition.isPhysRegRef); + // If this is an exposed use, do nothing - this is merely a placeholder to attempt to // ensure that a register is allocated for the full lifetime. The resolution logic // will take care of moving to the appropriate register if needed. @@ -13307,8 +13309,7 @@ regMaskTP LinearScan::RegisterSelection::select(Interval* current // If there is another fixed reference to this register before the use, change the candidates // on this RefPosition to include that of nextRefPos. - // TODO-Quirk: Should pass right type here, but previously this didn't consider TYP_DOUBLE case for arm32. - unsigned nextFixedRegRefLocation = linearScan->getNextFixedRef(defReg, TYP_I_IMPL); + unsigned nextFixedRegRefLocation = linearScan->getNextFixedRef(defReg, currentInterval->registerType); if (nextFixedRegRefLocation <= nextRefPos->getRefEndLocation()) { candidates |= nextRefPos->registerAssignment; @@ -13768,7 +13769,7 @@ regMaskTP LinearScan::RegisterSelection::selectMinimal(Interval* // If there is another fixed reference to this register before the use, change the candidates // on this RefPosition to include that of nextRefPos. - unsigned nextFixedRegRefLocation = linearScan->getNextFixedRef(defReg, TYP_I_IMPL); + unsigned nextFixedRegRefLocation = linearScan->getNextFixedRef(defReg, currentInterval->registerType); if (nextFixedRegRefLocation <= nextRefPos->getRefEndLocation()) { candidates |= nextRefPos->registerAssignment; From 40c024f69ab1c39982c043277e2bb90d2e510a24 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Thu, 2 May 2024 15:48:48 -0500 Subject: [PATCH 224/248] Fix PublishAot single warning issue for ProjectReferences (#101799) When publishing for native AOT and a ProjectReference has trim/AOT warnings, all the warnings are being collapsed into a single "warning IL2104: Assembly 'X' produced trim warnings." The issue is that we are using FileName, which cuts off the file extension of the item. But the items we are working with already cut off the `.dll` extension, so it this is cutting off important parts of the assembly name. The fix is to just use Identity, which is the whole item id. --- .../nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index 2c9a4e02aa496d..0df29b62a37287 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -281,7 +281,7 @@ The .NET Foundation licenses this file to you under the MIT license. - + From 28c39bc2805cdb952d8a7b0f14f5018b5f368c16 Mon Sep 17 00:00:00 2001 From: Aman Khalid Date: Thu, 2 May 2024 21:04:11 +0000 Subject: [PATCH 225/248] JIT: Implement greedy RPO-based block layout (#101473) Part of #93020. Compiler::fgDoReversePostOrderLayout reorders blocks based on a RPO of the flowgraph's successor edges. When reordering based on the RPO, we only reorder blocks within the same EH region to avoid breaking up their contiguousness. After establishing an RPO-based layout, we do another pass to move cold blocks to the ends of their regions in fgMoveColdBlocks. The "greedy" part of this layout isn't all that greedy just yet. For now, we use edge likelihoods to make placement decisions only for BBJ_COND blocks' successors. I plan to extend this greediness to other multi-successor block kinds (BBJ_SWITCH, etc) in a follow-up so we can independently evaluate the value in doing so. This new layout is disabled by default for now. --- src/coreclr/jit/block.cpp | 21 +- src/coreclr/jit/block.h | 4 +- src/coreclr/jit/compiler.h | 8 +- src/coreclr/jit/compiler.hpp | 32 +- src/coreclr/jit/fgopt.cpp | 514 +++++++++++++++++++++++++++++- src/coreclr/jit/flowgraph.cpp | 17 +- src/coreclr/jit/jitconfigvalues.h | 3 + 7 files changed, 576 insertions(+), 23 deletions(-) diff --git a/src/coreclr/jit/block.cpp b/src/coreclr/jit/block.cpp index 60dbce6aaf00a0..ecee292264ec85 100644 --- a/src/coreclr/jit/block.cpp +++ b/src/coreclr/jit/block.cpp @@ -137,14 +137,17 @@ void FlowEdge::addLikelihood(weight_t addedLikelihood) // AllSuccessorEnumerator: Construct an instance of the enumerator. // // Arguments: -// comp - Compiler instance -// block - The block whose successors are to be iterated +// comp - Compiler instance +// block - The block whose successors are to be iterated +// useProfile - If true, determines the order of successors visited using profile data // -AllSuccessorEnumerator::AllSuccessorEnumerator(Compiler* comp, BasicBlock* block) +AllSuccessorEnumerator::AllSuccessorEnumerator(Compiler* comp, BasicBlock* block, const bool useProfile /* = false */) : m_block(block) { m_numSuccs = 0; - block->VisitAllSuccs(comp, [this](BasicBlock* succ) { + block->VisitAllSuccs( + comp, + [this](BasicBlock* succ) { if (m_numSuccs < ArrLen(m_successors)) { m_successors[m_numSuccs] = succ; @@ -152,18 +155,22 @@ AllSuccessorEnumerator::AllSuccessorEnumerator(Compiler* comp, BasicBlock* block m_numSuccs++; return BasicBlockVisit::Continue; - }); + }, + useProfile); if (m_numSuccs > ArrLen(m_successors)) { m_pSuccessors = new (comp, CMK_BasicBlock) BasicBlock*[m_numSuccs]; unsigned numSuccs = 0; - block->VisitAllSuccs(comp, [this, &numSuccs](BasicBlock* succ) { + block->VisitAllSuccs( + comp, + [this, &numSuccs](BasicBlock* succ) { assert(numSuccs < m_numSuccs); m_pSuccessors[numSuccs++] = succ; return BasicBlockVisit::Continue; - }); + }, + useProfile); assert(numSuccs == m_numSuccs); } diff --git a/src/coreclr/jit/block.h b/src/coreclr/jit/block.h index 37c97bfdca6485..6ff2bb31b2a856 100644 --- a/src/coreclr/jit/block.h +++ b/src/coreclr/jit/block.h @@ -1799,7 +1799,7 @@ struct BasicBlock : private LIR::Range BasicBlockVisit VisitEHEnclosedHandlerSecondPassSuccs(Compiler* comp, TFunc func); template - BasicBlockVisit VisitAllSuccs(Compiler* comp, TFunc func); + BasicBlockVisit VisitAllSuccs(Compiler* comp, TFunc func, const bool useProfile = false); template BasicBlockVisit VisitEHSuccs(Compiler* comp, TFunc func); @@ -2497,7 +2497,7 @@ class AllSuccessorEnumerator public: // Constructs an enumerator of all `block`'s successors. - AllSuccessorEnumerator(Compiler* comp, BasicBlock* block); + AllSuccessorEnumerator(Compiler* comp, BasicBlock* block, const bool useProfile = false); // Gets the block whose successors are enumerated. BasicBlock* Block() diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index deb7b97943dc81..050f2e001ea294 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -2793,6 +2793,9 @@ class Compiler EHblkDsc* ehIsBlockHndLast(BasicBlock* block); bool ehIsBlockEHLast(BasicBlock* block); + template + void ehUpdateTryLasts(GetTryLast getTryLast, SetTryLast setTryLast); + bool ehBlockHasExnFlowDsc(BasicBlock* block); // Return the region index of the most nested EH region this block is in. @@ -6054,6 +6057,8 @@ class Compiler bool fgComputeCalledCount(weight_t returnWeight); bool fgReorderBlocks(bool useProfile); + void fgDoReversePostOrderLayout(); + void fgMoveColdBlocks(); bool fgFuncletsAreCold(); @@ -6074,9 +6079,10 @@ class Compiler PhaseStatus fgSetBlockOrder(); bool fgHasCycleWithoutGCSafePoint(); - template + template unsigned fgRunDfs(VisitPreorder assignPreorder, VisitPostorder assignPostorder, VisitEdge visitEdge); + template FlowGraphDfsTree* fgComputeDfs(); void fgInvalidateDfsTree(); diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 022a92bd740a3f..d8844c2e35afb8 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -623,12 +623,13 @@ BasicBlockVisit BasicBlock::VisitEHSuccs(Compiler* comp, TFunc func) // Arguments: // comp - Compiler instance // func - Callback +// useProfile - If true, determines the order of successors visited using profile data // // Returns: // Whether or not the visiting was aborted. // template -BasicBlockVisit BasicBlock::VisitAllSuccs(Compiler* comp, TFunc func) +BasicBlockVisit BasicBlock::VisitAllSuccs(Compiler* comp, TFunc func, const bool useProfile /* = false */) { switch (bbKind) { @@ -662,10 +663,22 @@ BasicBlockVisit BasicBlock::VisitAllSuccs(Compiler* comp, TFunc func) return VisitEHSuccs(comp, func); case BBJ_COND: - RETURN_ON_ABORT(func(GetFalseTarget())); - - if (!TrueEdgeIs(GetFalseEdge())) + if (TrueEdgeIs(GetFalseEdge())) { + RETURN_ON_ABORT(func(GetFalseTarget())); + } + else if (useProfile && (GetTrueEdge()->getLikelihood() < GetFalseEdge()->getLikelihood())) + { + // When building an RPO-based block layout, we want to visit the unlikely successor first + // so that in the DFS computation, the likely successor will be processed right before this block, + // meaning the RPO-based layout will enable fall-through into the likely successor. + // + RETURN_ON_ABORT(func(GetTrueTarget())); + RETURN_ON_ABORT(func(GetFalseTarget())); + } + else + { + RETURN_ON_ABORT(func(GetFalseTarget())); RETURN_ON_ABORT(func(GetTrueTarget())); } @@ -696,8 +709,8 @@ BasicBlockVisit BasicBlock::VisitAllSuccs(Compiler* comp, TFunc func) // VisitRegularSuccs: Visit regular successors of this block. // // Arguments: -// comp - Compiler instance -// func - Callback +// comp - Compiler instance +// func - Callback // // Returns: // Whether or not the visiting was aborted. @@ -4745,6 +4758,7 @@ inline bool Compiler::compCanHavePatchpoints(const char** reason) // VisitPreorder - Functor type that takes a BasicBlock* and its preorder number // VisitPostorder - Functor type that takes a BasicBlock* and its postorder number // VisitEdge - Functor type that takes two BasicBlock*. +// useProfile - If true, determines order of successors visited using profile data // // Parameters: // visitPreorder - Functor to visit block in its preorder @@ -4755,7 +4769,7 @@ inline bool Compiler::compCanHavePatchpoints(const char** reason) // Returns: // Number of blocks visited. // -template +template unsigned Compiler::fgRunDfs(VisitPreorder visitPreorder, VisitPostorder visitPostorder, VisitEdge visitEdge) { BitVecTraits traits(fgBBNumMax + 1, this); @@ -4768,7 +4782,7 @@ unsigned Compiler::fgRunDfs(VisitPreorder visitPreorder, VisitPostorder visitPos auto dfsFrom = [&](BasicBlock* firstBB) { BitVecOps::AddElemD(&traits, visited, firstBB->bbNum); - blocks.Emplace(this, firstBB); + blocks.Emplace(this, firstBB, useProfile); visitPreorder(firstBB, preOrderIndex++); while (!blocks.Empty()) @@ -4780,7 +4794,7 @@ unsigned Compiler::fgRunDfs(VisitPreorder visitPreorder, VisitPostorder visitPos { if (BitVecOps::TryAddElemD(&traits, visited, succ->bbNum)) { - blocks.Emplace(this, succ); + blocks.Emplace(this, succ, useProfile); visitPreorder(succ, preOrderIndex++); } diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index ac008eb140f9d7..88dd717fab6934 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -3412,9 +3412,22 @@ bool Compiler::fgReorderBlocks(bool useProfile) } } - // If we will be reordering blocks, ensure the false target of a BBJ_COND block is its next block if (useProfile) { + if (JitConfig.JitDoReversePostOrderLayout()) + { + fgDoReversePostOrderLayout(); + fgMoveColdBlocks(); + + // Renumber blocks to facilitate LSRA's order of block visitation + // TODO: Consider removing this, and using traversal order in lSRA + // + fgRenumberBlocks(); + + return true; + } + + // We will be reordering blocks, so ensure the false target of a BBJ_COND block is its next block for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->Next()) { if (block->KindIs(BBJ_COND) && !block->NextIs(block->GetFalseTarget())) @@ -4522,6 +4535,505 @@ bool Compiler::fgReorderBlocks(bool useProfile) #pragma warning(pop) #endif +//----------------------------------------------------------------------------- +// fgDoReversePostOrderLayout: Reorder blocks using a greedy RPO traversal. +// +void Compiler::fgDoReversePostOrderLayout() +{ +#ifdef DEBUG + if (verbose) + { + printf("*************** In fgDoReversePostOrderLayout()\n"); + + printf("\nInitial BasicBlocks"); + fgDispBasicBlocks(verboseTrees); + printf("\n"); + } +#endif // DEBUG + + // Compute DFS of all blocks in the method, using profile data to determine the order successors are visited in + // + FlowGraphDfsTree* const dfsTree = fgComputeDfs(); + + // Fast path: We don't have any EH regions, so just reorder the blocks + // + if (compHndBBtabCount == 0) + { + for (unsigned i = dfsTree->GetPostOrderCount() - 1; i != 0; i--) + { + BasicBlock* const block = dfsTree->GetPostOrder(i); + BasicBlock* const blockToMove = dfsTree->GetPostOrder(i - 1); + fgUnlinkBlock(blockToMove); + fgInsertBBafter(block, blockToMove); + } + + return; + } + + // The RPO will scramble the EH regions, requiring us to correct their state. + // To do so, we will need to determine the new end blocks of each region. + // + struct EHLayoutInfo + { + BasicBlock* tryRegionEnd; + BasicBlock* hndRegionEnd; + bool tryRegionInMainBody; + + // Default constructor provided so we can call ArrayStack::Emplace + // + EHLayoutInfo() = default; + }; + + ArrayStack regions(getAllocator(CMK_ArrayStack), compHndBBtabCount); + + // The RPO will break up call-finally pairs, so save them before re-ordering + // + struct CallFinallyPair + { + BasicBlock* callFinally; + BasicBlock* callFinallyRet; + + // Constructor provided so we can call ArrayStack::Emplace + // + CallFinallyPair(BasicBlock* first, BasicBlock* second) + : callFinally(first) + , callFinallyRet(second) + { + } + }; + + ArrayStack callFinallyPairs(getAllocator()); + + for (EHblkDsc* const HBtab : EHClauses(this)) + { + // Default-initialize a EHLayoutInfo for each EH clause + regions.Emplace(); + + if (HBtab->HasFinallyHandler()) + { + for (BasicBlock* const pred : HBtab->ebdHndBeg->PredBlocks()) + { + assert(pred->KindIs(BBJ_CALLFINALLY)); + if (pred->isBBCallFinallyPair()) + { + callFinallyPairs.Emplace(pred, pred->Next()); + } + } + } + } + + // Reorder blocks + // + for (unsigned i = dfsTree->GetPostOrderCount() - 1; i != 0; i--) + { + BasicBlock* const block = dfsTree->GetPostOrder(i); + BasicBlock* const blockToMove = dfsTree->GetPostOrder(i - 1); + + // Only reorder blocks within the same EH region -- we don't want to make them non-contiguous + // + if (BasicBlock::sameEHRegion(block, blockToMove)) + { + // Don't reorder EH regions with filter handlers -- we want the filter to come first + // + if (block->hasHndIndex() && ehGetDsc(block->getHndIndex())->HasFilter()) + { + continue; + } + + fgUnlinkBlock(blockToMove); + fgInsertBBafter(block, blockToMove); + } + } + + // Fix up call-finally pairs + // + for (int i = 0; i < callFinallyPairs.Height(); i++) + { + const CallFinallyPair& pair = callFinallyPairs.BottomRef(i); + fgUnlinkBlock(pair.callFinallyRet); + fgInsertBBafter(pair.callFinally, pair.callFinallyRet); + } + + // The RPO won't change the entry blocks of any EH regions, but reordering can change the last block in a region + // (for example, by pushing throw blocks unreachable via normal flow to the end of the region). + // First, determine the new EH region ends. + // + + for (BasicBlock* const block : Blocks(fgFirstBB, fgLastBBInMainFunction())) + { + if (block->hasTryIndex()) + { + EHLayoutInfo& layoutInfo = regions.BottomRef(block->getTryIndex()); + layoutInfo.tryRegionEnd = block; + layoutInfo.tryRegionInMainBody = true; + } + + if (block->hasHndIndex()) + { + regions.BottomRef(block->getHndIndex()).hndRegionEnd = block; + } + } + + for (BasicBlock* const block : Blocks(fgFirstFuncletBB)) + { + if (block->hasHndIndex()) + { + regions.BottomRef(block->getHndIndex()).hndRegionEnd = block; + } + + if (block->hasTryIndex()) + { + EHLayoutInfo& layoutInfo = regions.BottomRef(block->getTryIndex()); + + if (!layoutInfo.tryRegionInMainBody) + { + layoutInfo.tryRegionEnd = block; + } + } + } + + // Now, update the EH descriptors, starting with the try regions + // + auto getTryLast = [®ions](const unsigned index) -> BasicBlock* { + return regions.BottomRef(index).tryRegionEnd; + }; + + auto setTryLast = [®ions](const unsigned index, BasicBlock* const block) { + regions.BottomRef(index).tryRegionEnd = block; + }; + + ehUpdateTryLasts(getTryLast, setTryLast); + + // Now, do the handler regions + // + unsigned XTnum = 0; + for (EHblkDsc* const HBtab : EHClauses(this)) + { + // The end of each handler region should have been visited by iterating the blocklist above + // + BasicBlock* const hndEnd = regions.BottomRef(XTnum++).hndRegionEnd; + assert(hndEnd != nullptr); + + // Update the end pointer of this handler region to the new last block + // + HBtab->ebdHndLast = hndEnd; + const unsigned enclosingHndIndex = HBtab->ebdEnclosingHndIndex; + + // If this handler region is nested in another one, we might need to update its enclosing region's end block + // + if (enclosingHndIndex != EHblkDsc::NO_ENCLOSING_INDEX) + { + BasicBlock* const enclosingHndEnd = regions.BottomRef(enclosingHndIndex).hndRegionEnd; + assert(enclosingHndEnd != nullptr); + + // If the enclosing region ends right before the nested region begins, + // extend the enclosing region's last block to the end of the nested region. + // + BasicBlock* const hndBeg = HBtab->HasFilter() ? HBtab->ebdFilter : HBtab->ebdHndBeg; + if (enclosingHndEnd->NextIs(hndBeg)) + { + regions.BottomRef(enclosingHndIndex).hndRegionEnd = hndEnd; + } + } + } +} + +//----------------------------------------------------------------------------- +// fgMoveColdBlocks: Move rarely-run blocks to the end of their respective regions. +// +// Notes: +// Exception handlers are assumed to be cold, so we won't move blocks within them. +// +void Compiler::fgMoveColdBlocks() +{ +#ifdef DEBUG + if (verbose) + { + printf("*************** In fgMoveColdBlocks()\n"); + + printf("\nInitial BasicBlocks"); + fgDispBasicBlocks(verboseTrees); + printf("\n"); + } +#endif // DEBUG + + auto moveColdMainBlocks = [this]() { + // Find the last block in the main body that isn't part of an EH region + // + BasicBlock* lastMainBB; + for (lastMainBB = this->fgLastBBInMainFunction(); lastMainBB != nullptr; lastMainBB = lastMainBB->Prev()) + { + if (!lastMainBB->hasTryIndex() && !lastMainBB->hasHndIndex()) + { + break; + } + } + + // Nothing to do if there are two or fewer non-EH blocks + // + if ((lastMainBB == nullptr) || lastMainBB->IsFirst() || lastMainBB->PrevIs(fgFirstBB)) + { + return; + } + + // Search the main method body for rarely-run blocks to move + // + BasicBlock* prev; + for (BasicBlock* block = lastMainBB->Prev(); block != fgFirstBB; block = prev) + { + prev = block->Prev(); + + // We only want to move cold blocks. + // Also, don't consider blocks in EH regions for now; only move blocks in the main method body. + // Finally, don't move block if it is the beginning of a call-finally pair, + // as we want to keep these pairs contiguous + // (if we encounter the end of a pair below, we'll move the whole pair). + // + if (!block->isRunRarely() || block->hasTryIndex() || block->hasHndIndex() || block->isBBCallFinallyPair()) + { + continue; + } + + this->fgUnlinkBlock(block); + this->fgInsertBBafter(lastMainBB, block); + + // If block is the end of a call-finally pair, prev is the beginning of the pair. + // Move prev to before block to keep the pair contiguous. + // + if (block->KindIs(BBJ_CALLFINALLYRET)) + { + BasicBlock* const callFinally = prev; + prev = prev->Prev(); + assert(callFinally->KindIs(BBJ_CALLFINALLY)); + assert(!callFinally->HasFlag(BBF_RETLESS_CALL)); + this->fgUnlinkBlock(callFinally); + this->fgInsertBBafter(lastMainBB, callFinally); + } + } + + // We have moved all cold main blocks before lastMainBB to after lastMainBB. + // If lastMainBB itself is cold, move it to the end of the method to restore its relative ordering. + // + if (lastMainBB->isRunRarely()) + { + BasicBlock* const newLastMainBB = this->fgLastBBInMainFunction(); + if (lastMainBB != newLastMainBB) + { + BasicBlock* const prev = lastMainBB->Prev(); + this->fgUnlinkBlock(lastMainBB); + this->fgInsertBBafter(newLastMainBB, lastMainBB); + + // Call-finally check + // + if (lastMainBB->KindIs(BBJ_CALLFINALLYRET)) + { + assert(prev->KindIs(BBJ_CALLFINALLY)); + assert(!prev->HasFlag(BBF_RETLESS_CALL)); + assert(prev != newLastMainBB); + this->fgUnlinkBlock(prev); + this->fgInsertBBafter(newLastMainBB, prev); + } + } + } + }; + + moveColdMainBlocks(); + + // No EH regions + // + if (compHndBBtabCount == 0) + { + return; + } + + // We assume exception handlers are cold, so we won't bother moving blocks within them. + // We will move blocks only within try regions. + // First, determine where each try region ends, without considering nested regions. + // We will use these end blocks as insertion points. + // + BasicBlock** const tryRegionEnds = new (this, CMK_Generic) BasicBlock* [compHndBBtabCount] {}; + + for (BasicBlock* const block : Blocks(fgFirstBB, fgLastBBInMainFunction())) + { + if (block->hasTryIndex()) + { + tryRegionEnds[block->getTryIndex()] = block; + } + } + + // Search all try regions in the main method body for cold blocks to move + // + BasicBlock* prev; + for (BasicBlock* block = fgLastBBInMainFunction(); block != fgFirstBB; block = prev) + { + prev = block->Prev(); + + // Only consider rarely-run blocks in try regions. + // If we have such a block that is also part of an exception handler, don't bother moving it. + // Finally, don't move block if it is the beginning of a call-finally pair, + // as we want to keep these pairs contiguous + // (if we encounter the end of a pair below, we'll move the whole pair). + // + if (!block->hasTryIndex() || !block->isRunRarely() || block->hasHndIndex() || block->isBBCallFinallyPair()) + { + continue; + } + + const unsigned tryIndex = block->getTryIndex(); + EHblkDsc* const HBtab = ehGetDsc(tryIndex); + + // Don't move the beginning of a try region. + // Also, if this try region's entry is cold, don't bother moving its blocks. + // + if ((HBtab->ebdTryBeg == block) || (HBtab->ebdTryBeg->isRunRarely())) + { + continue; + } + + BasicBlock* const insertionPoint = tryRegionEnds[tryIndex]; + assert(insertionPoint != nullptr); + + // Don't move the end of this try region + // + if (block == insertionPoint) + { + continue; + } + + fgUnlinkBlock(block); + fgInsertBBafter(insertionPoint, block); + + // Keep call-finally pairs contiguous + // + if (block->KindIs(BBJ_CALLFINALLYRET)) + { + BasicBlock* const callFinally = prev; + prev = prev->Prev(); + assert(callFinally->KindIs(BBJ_CALLFINALLY)); + assert(!callFinally->HasFlag(BBF_RETLESS_CALL)); + fgUnlinkBlock(callFinally); + fgInsertBBafter(insertionPoint, callFinally); + } + } + + // Before updating EH descriptors, find the new try region ends + // + for (unsigned XTnum = 0; XTnum < compHndBBtabCount; XTnum++) + { + BasicBlock* const tryEnd = tryRegionEnds[XTnum]; + + // This try region isn't in the main method body + // + if (tryEnd == nullptr) + { + continue; + } + + // If we moved cold blocks to the end of this try region, + // search for the new end block + // + BasicBlock* newTryEnd = tryEnd; + for (BasicBlock* const block : Blocks(tryEnd, fgLastBBInMainFunction())) + { + if (!BasicBlock::sameTryRegion(tryEnd, block)) + { + break; + } + + newTryEnd = block; + } + + // We moved cold blocks to the end of this try region, but the old end block is cold, too. + // Move the old end block to the end of the region to preserve its relative ordering. + // + if ((tryEnd != newTryEnd) && tryEnd->isRunRarely() && !tryEnd->hasHndIndex()) + { + BasicBlock* const prev = tryEnd->Prev(); + fgUnlinkBlock(tryEnd); + fgInsertBBafter(newTryEnd, tryEnd); + + // Keep call-finally pairs contiguous + // + if (tryEnd->KindIs(BBJ_CALLFINALLYRET)) + { + assert(prev->KindIs(BBJ_CALLFINALLY)); + assert(!prev->HasFlag(BBF_RETLESS_CALL)); + fgUnlinkBlock(prev); + fgInsertBBafter(newTryEnd, prev); + } + } + else + { + // Otherwise, just update the try region end + // + tryRegionEnds[XTnum] = newTryEnd; + } + } + + // Now, update EH descriptors + // + auto getTryLast = [tryRegionEnds](const unsigned index) -> BasicBlock* { + return tryRegionEnds[index]; + }; + + auto setTryLast = [tryRegionEnds](const unsigned index, BasicBlock* const block) { + tryRegionEnds[index] = block; + }; + + ehUpdateTryLasts(getTryLast, setTryLast); +} + +//------------------------------------------------------------- +// ehUpdateTryLasts: Iterates EH descriptors, updating each try region's +// end block as determined by getTryLast. +// +// Type parameters: +// GetTryLast - Functor type that takes an EH index, +// and returns the corresponding region's new try end block +// SetTryLast - Functor type that takes an EH index and a BasicBlock*, +// and updates some internal state tracking the new try end block of each EH region +// +// Parameters: +// getTryLast - Functor to get new try end block for an EH region +// setTryLast - Functor to update the new try end block for an EH region +// +template +void Compiler::ehUpdateTryLasts(GetTryLast getTryLast, SetTryLast setTryLast) +{ + unsigned XTnum = 0; + for (EHblkDsc* const HBtab : EHClauses(this)) + { + BasicBlock* const tryEnd = getTryLast(XTnum++); + + if (tryEnd == nullptr) + { + continue; + } + + // Update the end pointer of this try region to the new last block + // + HBtab->ebdTryLast = tryEnd; + const unsigned enclosingTryIndex = HBtab->ebdEnclosingTryIndex; + + // If this try region is nested in another one, we might need to update its enclosing region's end block + // + if (enclosingTryIndex != EHblkDsc::NO_ENCLOSING_INDEX) + { + BasicBlock* const enclosingTryEnd = getTryLast(enclosingTryIndex); + + // If multiple EH descriptors map to the same try region, + // then the enclosing region's last block might be null in the table, so set it here. + // Similarly, if the enclosing region ends right before the nested region begins, + // extend the enclosing region's last block to the end of the nested region. + // + if ((enclosingTryEnd == nullptr) || enclosingTryEnd->NextIs(HBtab->ebdTryBeg)) + { + setTryLast(enclosingTryIndex, tryEnd); + } + } + } +} + //------------------------------------------------------------- // fgUpdateFlowGraphPhase: run flow graph optimization as a // phase, with no tail duplication diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 2a185d9e47b1d1..151729b0950514 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -4029,8 +4029,8 @@ bool FlowGraphDfsTree::Contains(BasicBlock* block) const // block `descendant` // // Arguments: -// ancestor -- block that is possible ancestor -// descendant -- block that is possible descendant +// ancestor - block that is possible ancestor +// descendant - block that is possible descendant // // Returns: // True if `ancestor` is ancestor of `descendant` in the depth first spanning @@ -4049,6 +4049,9 @@ bool FlowGraphDfsTree::IsAncestor(BasicBlock* ancestor, BasicBlock* descendant) //------------------------------------------------------------------------ // fgComputeDfs: Compute a depth-first search tree for the flow graph. // +// Type parameters: +// useProfile - If true, determines order of successors visited using profile data +// // Returns: // The tree. // @@ -4056,6 +4059,7 @@ bool FlowGraphDfsTree::IsAncestor(BasicBlock* ancestor, BasicBlock* descendant) // Preorder and postorder numbers are assigned into the BasicBlock structure. // The tree returned contains a postorder of the basic blocks. // +template FlowGraphDfsTree* Compiler::fgComputeDfs() { BasicBlock** postOrder = new (this, CMK_DepthFirstSearch) BasicBlock*[fgBBcount]; @@ -4081,10 +4085,17 @@ FlowGraphDfsTree* Compiler::fgComputeDfs() } }; - unsigned numBlocks = fgRunDfs(visitPreorder, visitPostorder, visitEdge); + unsigned numBlocks = + fgRunDfs(visitPreorder, + visitPostorder, + visitEdge); return new (this, CMK_DepthFirstSearch) FlowGraphDfsTree(this, postOrder, numBlocks, hasCycle); } +// Add explicit instantiations. +template FlowGraphDfsTree* Compiler::fgComputeDfs(); +template FlowGraphDfsTree* Compiler::fgComputeDfs(); + //------------------------------------------------------------------------ // fgInvalidateDfsTree: Invalidate computed DFS tree and dependent annotations // (like loops, dominators and SSA). diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index 700cd33bd6bf2f..81345191ce5f88 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -754,6 +754,9 @@ RELEASE_CONFIG_INTEGER(JitEnablePhysicalPromotion, W("JitEnablePhysicalPromotion // Enable cross-block local assertion prop RELEASE_CONFIG_INTEGER(JitEnableCrossBlockLocalAssertionProp, W("JitEnableCrossBlockLocalAssertionProp"), 1) +// Do greedy RPO-based layout in Compiler::fgReorderBlocks. +RELEASE_CONFIG_INTEGER(JitDoReversePostOrderLayout, W("JitDoReversePostOrderLayout"), 0); + // JitFunctionFile: Name of a file that contains a list of functions. If the currently compiled function is in the // file, certain other JIT config variables will be active. If the currently compiled function is not in the file, // the specific JIT config variables will not be active. From 7cde9aaae61e10eba9974e52e8b876da94a8b38b Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Thu, 2 May 2024 15:00:56 -0700 Subject: [PATCH 226/248] GC: Fix survival rates for LOH/POH (#100716) The survival rate calculation for BGCs includes objects allocated during the BGC in the numerator but not denominator. This fixes that by adding them to size_before. The existing counters are reset mid-BGC, so the mark and sweep phases need to be added at separate points. I verified the fix over several gcperfsim runs and watched the counters getting updated in the debugger. This includes some new and moved comments from going through the phases of BGC and putting similarly ifdef-ed code together. Partial fix for #100594 --- src/coreclr/gc/gc.cpp | 144 +++++++++++++++++++++++----------------- src/coreclr/gc/gc.h | 5 +- src/coreclr/gc/gcpriv.h | 17 +++-- 3 files changed, 96 insertions(+), 70 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 0861a15d274d7c..9b6f5515e37a5e 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -388,7 +388,7 @@ int relative_index_power2_free_space (size_t power2) #ifdef BACKGROUND_GC uint32_t bgc_alloc_spin_count = 140; -uint32_t bgc_alloc_spin_count_loh = 16; +uint32_t bgc_alloc_spin_count_uoh = 16; uint32_t bgc_alloc_spin = 2; inline @@ -2657,13 +2657,10 @@ size_t gc_heap::end_loh_size = 0; size_t gc_heap::bgc_begin_poh_size = 0; size_t gc_heap::end_poh_size = 0; +size_t gc_heap::uoh_a_no_bgc[uoh_generation_count] = {}; +size_t gc_heap::uoh_a_bgc_marking[uoh_generation_count] = {}; +size_t gc_heap::uoh_a_bgc_planning[uoh_generation_count] = {}; #ifdef BGC_SERVO_TUNING -uint64_t gc_heap::loh_a_no_bgc = 0; - -uint64_t gc_heap::loh_a_bgc_marking = 0; - -uint64_t gc_heap::loh_a_bgc_planning = 0; - size_t gc_heap::bgc_maxgen_end_fl_size = 0; #endif //BGC_SERVO_TUNING @@ -2794,9 +2791,9 @@ FinalizerWorkItem* gc_heap::finalizer_work; BOOL gc_heap::proceed_with_gc_p = FALSE; GCSpinLock gc_heap::gc_lock; -#ifdef BGC_SERVO_TUNING -uint64_t gc_heap::total_loh_a_last_bgc = 0; -#endif //BGC_SERVO_TUNING +#ifdef BACKGROUND_GC +uint64_t gc_heap::total_uoh_a_last_bgc = 0; +#endif //BACKGROUND_GC #ifdef USE_REGIONS region_free_list gc_heap::global_regions_to_decommit[count_free_region_kinds]; @@ -15039,10 +15036,13 @@ gc_heap::init_gc_heap (int h_number) make_mark_stack(arr); #ifdef BACKGROUND_GC + for (int i = uoh_start_generation; i < total_generation_count; i++) + { + uoh_a_no_bgc[i - uoh_start_generation] = 0; + uoh_a_bgc_marking[i - uoh_start_generation] = 0; + uoh_a_bgc_planning[i - uoh_start_generation] = 0; + } #ifdef BGC_SERVO_TUNING - loh_a_no_bgc = 0; - loh_a_bgc_marking = 0; - loh_a_bgc_planning = 0; bgc_maxgen_end_fl_size = 0; #endif //BGC_SERVO_TUNING freeable_soh_segment = 0; @@ -18424,6 +18424,29 @@ bool gc_heap::should_retry_other_heap (int gen_number, size_t size) } } +void gc_heap::bgc_record_uoh_allocation(int gen_number, size_t size) +{ + assert((gen_number >= uoh_start_generation) && (gen_number < total_generation_count)); + + if (gc_heap::background_running_p()) + { + background_uoh_alloc_count++; + + if (current_c_gc_state == c_gc_state_planning) + { + uoh_a_bgc_planning[gen_number - uoh_start_generation] += size; + } + else + { + uoh_a_bgc_marking[gen_number - uoh_start_generation] += size; + } + } + else + { + uoh_a_no_bgc[gen_number - uoh_start_generation] += size; + } +} + allocation_state gc_heap::allocate_uoh (int gen_number, size_t size, alloc_context* acontext, @@ -18446,26 +18469,12 @@ allocation_state gc_heap::allocate_uoh (int gen_number, #endif //RECORD_LOH_STATE #ifdef BACKGROUND_GC + bgc_record_uoh_allocation(gen_number, size); + if (gc_heap::background_running_p()) { -#ifdef BGC_SERVO_TUNING - bool planning_p = (current_c_gc_state == c_gc_state_planning); -#endif //BGC_SERVO_TUNING - - background_uoh_alloc_count++; - //if ((background_loh_alloc_count % bgc_alloc_spin_count_loh) == 0) + //if ((background_uoh_alloc_count % bgc_alloc_spin_count_uoh) == 0) { -#ifdef BGC_SERVO_TUNING - if (planning_p) - { - loh_a_bgc_planning += size; - } - else - { - loh_a_bgc_marking += size; - } -#endif //BGC_SERVO_TUNING - int spin_for_allocation = (gen_number == loh_generation) ? bgc_loh_allocate_spin() : bgc_poh_allocate_spin(); @@ -18491,12 +18500,6 @@ allocation_state gc_heap::allocate_uoh (int gen_number, } } } -#ifdef BGC_SERVO_TUNING - else - { - loh_a_no_bgc += size; - } -#endif //BGC_SERVO_TUNING #endif //BACKGROUND_GC gc_reason gr = reason_oos_loh; @@ -40624,7 +40627,7 @@ void gc_heap::bgc_tuning::record_and_adjust_bgc_end() calculate_tuning (max_generation, true); - if (total_loh_a_last_bgc > 0) + if (total_uoh_a_last_bgc > 0) { calculate_tuning (loh_generation, true); } @@ -45821,9 +45824,6 @@ void gc_heap::background_sweep() concurrent_print_time_delta ("Sw"); dprintf (2, ("---- (GC%zu)Background Sweep Phase ----", VolatileLoad(&settings.gc_index))); - //block concurrent allocation for large objects - dprintf (3, ("lh state: planning")); - for (int i = 0; i <= max_generation; i++) { generation* gen_to_reset = generation_of (i); @@ -45872,6 +45872,9 @@ void gc_heap::background_sweep() sweep_ro_segments(); #endif //FEATURE_BASICFREEZE + dprintf (3, ("lh state: planning")); + + // Multiple threads may reach here. This conditional partially avoids multiple volatile writes. if (current_c_gc_state != c_gc_state_planning) { current_c_gc_state = c_gc_state_planning; @@ -45902,9 +45905,7 @@ void gc_heap::background_sweep() if (heap_number == 0) { -#ifdef BGC_SERVO_TUNING - get_and_reset_loh_alloc_info(); -#endif //BGC_SERVO_TUNING + get_and_reset_uoh_alloc_info(); uint64_t suspended_end_ts = GetHighPrecisionTimeStamp(); last_bgc_info[last_bgc_info_index].pause_durations[1] = (size_t)(suspended_end_ts - suspended_start_time); total_suspended_time += last_bgc_info[last_bgc_info_index].pause_durations[1]; @@ -46233,6 +46234,7 @@ void gc_heap::background_sweep() concurrent_print_time_delta ("Swe SOH"); FIRE_EVENT(BGC1stSweepEnd, 0); + //block concurrent allocation for UOH objects enter_spin_lock (&more_space_lock_uoh); add_saved_spinlock_info (true, me_acquire, mt_bgc_uoh_sweep, msl_entered); @@ -46288,6 +46290,15 @@ void gc_heap::background_sweep() // be accurate. compute_new_dynamic_data (max_generation); + // We also need to adjust size_before for UOH allocations that occurred during sweeping. + gc_history_per_heap* current_gc_data_per_heap = get_gc_data_per_heap(); + for (int i = uoh_start_generation; i < total_generation_count; i++) + { + assert(uoh_a_bgc_marking[i - uoh_start_generation] == 0); + assert(uoh_a_no_bgc[i - uoh_start_generation] == 0); + current_gc_data_per_heap->gen_data[i].size_before += uoh_a_bgc_planning[i - uoh_start_generation]; + } + #ifdef DOUBLY_LINKED_FL current_bgc_state = bgc_not_in_process; @@ -50257,17 +50268,15 @@ void gc_heap::check_and_adjust_bgc_tuning (int gen_number, size_t physical_size, } } } +#endif //BGC_SERVO_TUNING -void gc_heap::get_and_reset_loh_alloc_info() +void gc_heap::get_and_reset_uoh_alloc_info() { - if (!bgc_tuning::enable_fl_tuning) - return; + total_uoh_a_last_bgc = 0; - total_loh_a_last_bgc = 0; - - uint64_t total_loh_a_no_bgc = 0; - uint64_t total_loh_a_bgc_marking = 0; - uint64_t total_loh_a_bgc_planning = 0; + uint64_t total_uoh_a_no_bgc = 0; + uint64_t total_uoh_a_bgc_marking = 0; + uint64_t total_uoh_a_bgc_planning = 0; #ifdef MULTIPLE_HEAPS for (int i = 0; i < gc_heap::n_heaps; i++) { @@ -50276,21 +50285,32 @@ void gc_heap::get_and_reset_loh_alloc_info() { gc_heap* hp = pGenGCHeap; #endif //MULTIPLE_HEAPS - total_loh_a_no_bgc += hp->loh_a_no_bgc; - hp->loh_a_no_bgc = 0; - total_loh_a_bgc_marking += hp->loh_a_bgc_marking; - hp->loh_a_bgc_marking = 0; - total_loh_a_bgc_planning += hp->loh_a_bgc_planning; - hp->loh_a_bgc_planning = 0; + + // We need to adjust size_before for UOH allocations that occurred during marking + // before we lose the values here. + gc_history_per_heap* current_gc_data_per_heap = hp->get_gc_data_per_heap(); + // loh/poh_a_bgc_planning should be the same as they were when init_records set size_before. + for (int i = uoh_start_generation; i < total_generation_count; i++) + { + current_gc_data_per_heap->gen_data[i].size_before += hp->uoh_a_bgc_marking[i - uoh_start_generation]; + + total_uoh_a_no_bgc += hp->uoh_a_no_bgc[i - uoh_start_generation]; + hp->uoh_a_no_bgc[i - uoh_start_generation] = 0; + + total_uoh_a_bgc_marking += hp->uoh_a_bgc_marking[i - uoh_start_generation]; + hp->uoh_a_bgc_marking[i - uoh_start_generation] = 0; + + total_uoh_a_bgc_planning += hp->uoh_a_bgc_planning[i - uoh_start_generation]; + hp->uoh_a_bgc_planning[i - uoh_start_generation] = 0; + } } dprintf (2, ("LOH alloc: outside bgc: %zd; bm: %zd; bp: %zd", - total_loh_a_no_bgc, - total_loh_a_bgc_marking, - total_loh_a_bgc_planning)); + total_uoh_a_no_bgc, + total_uoh_a_bgc_marking, + total_uoh_a_bgc_planning)); - total_loh_a_last_bgc = total_loh_a_no_bgc + total_loh_a_bgc_marking + total_loh_a_bgc_planning; + total_uoh_a_last_bgc = total_uoh_a_no_bgc + total_uoh_a_bgc_marking + total_uoh_a_bgc_planning; } -#endif //BGC_SERVO_TUNING bool gc_heap::is_pm_ratio_exceeded() { diff --git a/src/coreclr/gc/gc.h b/src/coreclr/gc/gc.h index a1093b5e76ceca..e80853489a2410 100644 --- a/src/coreclr/gc/gc.h +++ b/src/coreclr/gc/gc.h @@ -124,7 +124,10 @@ enum gc_generation_num ephemeral_generation_count = max_generation, // number of all generations - total_generation_count = poh_generation + 1 + total_generation_count = poh_generation + 1, + + // number of uoh generations + uoh_generation_count = total_generation_count - uoh_start_generation }; #ifdef GC_CONFIG_DRIVEN diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index a7199e5d220ac0..757f816c639fd3 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -1752,6 +1752,8 @@ class gc_heap PER_HEAP_ISOLATED_METHOD void add_to_history(); + PER_HEAP_ISOLATED_METHOD void get_and_reset_uoh_alloc_info(); + #ifdef BGC_SERVO_TUNING // Currently BGC servo tuning is an experimental feature. class bgc_tuning @@ -1997,7 +1999,6 @@ class gc_heap }; PER_HEAP_ISOLATED_METHOD void check_and_adjust_bgc_tuning (int gen_number, size_t physical_size, ptrdiff_t virtual_fl_size); - PER_HEAP_ISOLATED_METHOD void get_and_reset_loh_alloc_info(); #endif //BGC_SERVO_TUNING #ifndef USE_REGIONS @@ -2230,6 +2231,8 @@ class gc_heap PER_HEAP_METHOD BOOL bgc_loh_allocate_spin(); PER_HEAP_METHOD BOOL bgc_poh_allocate_spin(); + + PER_HEAP_METHOD void bgc_record_uoh_allocation(int gen_number, size_t size); #endif //BACKGROUND_GC PER_HEAP_METHOD void add_saved_spinlock_info ( @@ -3436,6 +3439,11 @@ class gc_heap PER_HEAP_FIELD_SINGLE_GC uint8_t* next_sweep_obj; PER_HEAP_FIELD_SINGLE_GC uint8_t* current_sweep_pos; + + PER_HEAP_FIELD_SINGLE_GC size_t uoh_a_no_bgc[uoh_generation_count]; + PER_HEAP_FIELD_SINGLE_GC size_t uoh_a_bgc_marking[uoh_generation_count]; + PER_HEAP_FIELD_SINGLE_GC size_t uoh_a_bgc_planning[uoh_generation_count]; + #ifdef DOUBLY_LINKED_FL PER_HEAP_FIELD_SINGLE_GC heap_segment* current_sweep_seg; #endif //DOUBLY_LINKED_FL @@ -3461,9 +3469,6 @@ class gc_heap #endif //SNOOP_STATS #ifdef BGC_SERVO_TUNING - PER_HEAP_FIELD_SINGLE_GC uint64_t loh_a_no_bgc; - PER_HEAP_FIELD_SINGLE_GC uint64_t loh_a_bgc_marking; - PER_HEAP_FIELD_SINGLE_GC uint64_t loh_a_bgc_planning; PER_HEAP_FIELD_SINGLE_GC size_t bgc_maxgen_end_fl_size; #endif //BGC_SERVO_TUNING #endif //BACKGROUND_GC @@ -4097,11 +4102,9 @@ class gc_heap PER_HEAP_ISOLATED_FIELD_SINGLE_GC GCEvent bgc_start_event; -#ifdef BGC_SERVO_TUNING // Total allocated last BGC's plan + between last and this bgc + // this bgc's mark - PER_HEAP_ISOLATED_FIELD_SINGLE_GC uint64_t total_loh_a_last_bgc; -#endif //BGC_SERVO_TUNING + PER_HEAP_ISOLATED_FIELD_SINGLE_GC uint64_t total_uoh_a_last_bgc; #endif //BACKGROUND_GC #ifdef USE_REGIONS From a2635e1f4ef75cd2a21e9250e3d5b97fd6e2c6d2 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 2 May 2024 15:52:26 -0700 Subject: [PATCH 227/248] Use the standard nothrow tag instead of our own type (#101811) --- src/coreclr/debug/ee/debugger.h | 4 +- src/coreclr/inc/new.hpp | 12 +----- src/coreclr/inc/stresslog.h | 2 +- src/coreclr/inc/utilcode.h | 8 ++-- .../utilcode/clrhost_nodependencies.cpp | 38 +++++-------------- src/coreclr/utilcode/stresslog.cpp | 2 +- src/coreclr/vm/stackingallocator.cpp | 4 +- src/coreclr/vm/stackingallocator.h | 4 +- 8 files changed, 24 insertions(+), 50 deletions(-) diff --git a/src/coreclr/debug/ee/debugger.h b/src/coreclr/debug/ee/debugger.h index 43f56c00dc7932..d66307fb146422 100644 --- a/src/coreclr/debug/ee/debugger.h +++ b/src/coreclr/debug/ee/debugger.h @@ -3613,7 +3613,7 @@ inline void * __cdecl operator new[](size_t n, const InteropSafe&) return result; } -inline void * __cdecl operator new(size_t n, const InteropSafe&, const NoThrow&) throw() +inline void * __cdecl operator new(size_t n, const InteropSafe&, const std::nothrow_t&) noexcept { CONTRACTL { @@ -3632,7 +3632,7 @@ inline void * __cdecl operator new(size_t n, const InteropSafe&, const NoThrow&) return result; } -inline void * __cdecl operator new[](size_t n, const InteropSafe&, const NoThrow&) throw() +inline void * __cdecl operator new[](size_t n, const InteropSafe&, const std::nothrow_t&) noexcept { CONTRACTL { diff --git a/src/coreclr/inc/new.hpp b/src/coreclr/inc/new.hpp index 09eec5d1ffcf82..037ceb3c667c20 100644 --- a/src/coreclr/inc/new.hpp +++ b/src/coreclr/inc/new.hpp @@ -7,17 +7,9 @@ #ifndef __new__hpp #define __new__hpp -#if defined(_MSC_VER) && _MSC_VER < 1900 -#define NOEXCEPT -#else -#define NOEXCEPT noexcept -#endif - -struct NoThrow { int x; }; -extern const NoThrow nothrow; +#include -void * __cdecl operator new(size_t n, const NoThrow&) NOEXCEPT; -void * __cdecl operator new[](size_t n, const NoThrow&) NOEXCEPT; +using std::nothrow; #ifdef _DEBUG void DisableThrowCheck(); diff --git a/src/coreclr/inc/stresslog.h b/src/coreclr/inc/stresslog.h index 8e89a06a838dcf..998c62254f6eca 100644 --- a/src/coreclr/inc/stresslog.h +++ b/src/coreclr/inc/stresslog.h @@ -807,7 +807,7 @@ class ThreadStressLog { #endif //!STRESS_LOG_READONLY && !STRESS_LOG_ANALYZER #if defined(MEMORY_MAPPED_STRESSLOG) && !defined(STRESS_LOG_ANALYZER) - void* __cdecl operator new(size_t n, const NoThrow&) NOEXCEPT; + void* __cdecl operator new(size_t n, const std::nothrow_t&) noexcept; void __cdecl operator delete (void * chunk); #endif diff --git a/src/coreclr/inc/utilcode.h b/src/coreclr/inc/utilcode.h index ed15764b970e74..d4416a36919bd6 100644 --- a/src/coreclr/inc/utilcode.h +++ b/src/coreclr/inc/utilcode.h @@ -316,10 +316,10 @@ _Ret_bytecap_(n) void * __cdecl operator new[](size_t n); void __cdecl -operator delete(void *p) NOEXCEPT; +operator delete(void *p) noexcept; void __cdecl -operator delete[](void *p) NOEXCEPT; +operator delete[](void *p) noexcept; #ifdef _DEBUG_IMPL HRESULT _OutOfMemory(LPCSTR szFile, int iLine); @@ -3728,8 +3728,8 @@ extern const CExecutable executable; void * __cdecl operator new(size_t n, const CExecutable&); void * __cdecl operator new[](size_t n, const CExecutable&); -void * __cdecl operator new(size_t n, const CExecutable&, const NoThrow&); -void * __cdecl operator new[](size_t n, const CExecutable&, const NoThrow&); +void * __cdecl operator new(size_t n, const CExecutable&, const std::nothrow_t&) noexcept; +void * __cdecl operator new[](size_t n, const CExecutable&, const std::nothrow_t&) noexcept; // diff --git a/src/coreclr/utilcode/clrhost_nodependencies.cpp b/src/coreclr/utilcode/clrhost_nodependencies.cpp index 7aceae763c43b8..3cc4badd9e3aa3 100644 --- a/src/coreclr/utilcode/clrhost_nodependencies.cpp +++ b/src/coreclr/utilcode/clrhost_nodependencies.cpp @@ -202,12 +202,8 @@ ClrDebugState *CLRInitDebugState() #endif //defined(_DEBUG_IMPL) && defined(ENABLE_CONTRACTS_IMPL) -const NoThrow nothrow = { 0 }; - -#if defined(HAS_ADDRESS_SANITIZER) || defined(DACCESS_COMPILE) -// use standard heap functions for address sanitizer -#else - +// use standard heap functions for AddressSanitizer and for the DAC build. +#if !defined(HAS_ADDRESS_SANITIZER) && !defined(DACCESS_COMPILE) #ifdef _DEBUG #ifdef TARGET_X86 #define OS_HEAP_ALIGN 8 @@ -221,7 +217,7 @@ const NoThrow nothrow = { 0 }; static HANDLE g_hProcessHeap; #endif -FORCEINLINE void* ClrMalloc(size_t size) +static FORCEINLINE void* ClrMalloc(size_t size) { STATIC_CONTRACT_NOTHROW; @@ -339,14 +335,9 @@ operator new[](size_t n) return result; }; -#endif // HAS_ADDRESS_SANITIZER || DACCESS_COMPILE -void * __cdecl operator new(size_t n, const NoThrow&) NOEXCEPT +void * __cdecl operator new(size_t n, const std::nothrow_t&) noexcept { -#if defined(HAS_ADDRESS_SANITIZER) || defined(DACCESS_COMPILE) - // use standard heap functions for address sanitizer (which doesn't provide for NoThrow) - void * result = operator new(n); -#else STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_FAULT; @@ -355,17 +346,12 @@ void * __cdecl operator new(size_t n, const NoThrow&) NOEXCEPT INCONTRACT(_ASSERTE(!ARE_FAULTS_FORBIDDEN())); void* result = ClrMalloc(n); -#endif // HAS_ADDRESS_SANITIZER || DACCESS_COMPILE TRASH_LASTERROR; return result; } -void * __cdecl operator new[](size_t n, const NoThrow&) NOEXCEPT +void * __cdecl operator new[](size_t n, const std::nothrow_t&) noexcept { -#if defined(HAS_ADDRESS_SANITIZER) || defined(DACCESS_COMPILE) - // use standard heap functions for address sanitizer (which doesn't provide for NoThrow) - void * result = operator new[](n); -#else STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_FAULT; @@ -374,16 +360,12 @@ void * __cdecl operator new[](size_t n, const NoThrow&) NOEXCEPT INCONTRACT(_ASSERTE(!ARE_FAULTS_FORBIDDEN())); void* result = ClrMalloc(n); -#endif // HAS_ADDRESS_SANITIZER || DACCESS_COMPILE TRASH_LASTERROR; return result; } -#if defined(HAS_ADDRESS_SANITIZER) || defined(DACCESS_COMPILE) -// use standard heap functions for address sanitizer -#else void __cdecl -operator delete(void *p) NOEXCEPT +operator delete(void *p) noexcept { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; @@ -395,7 +377,7 @@ operator delete(void *p) NOEXCEPT } void __cdecl -operator delete[](void *p) NOEXCEPT +operator delete[](void *p) noexcept { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; @@ -405,7 +387,7 @@ operator delete[](void *p) NOEXCEPT TRASH_LASTERROR; } -#endif // HAS_ADDRESS_SANITIZER || DACCESS_COMPILE +#endif // !HAS_ADDRESS_SANITIZER && !DACCESS_COMPILE /* ------------------------------------------------------------------------ * * New operator overloading for the executable heap @@ -494,7 +476,7 @@ void * __cdecl operator new[](size_t n, const CExecutable&) return result; } -void * __cdecl operator new(size_t n, const CExecutable&, const NoThrow&) +void * __cdecl operator new(size_t n, const CExecutable&, const std::nothrow_t&) noexcept { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; @@ -511,7 +493,7 @@ void * __cdecl operator new(size_t n, const CExecutable&, const NoThrow&) return result; } -void * __cdecl operator new[](size_t n, const CExecutable&, const NoThrow&) +void * __cdecl operator new[](size_t n, const CExecutable&, const std::nothrow_t&) noexcept { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; diff --git a/src/coreclr/utilcode/stresslog.cpp b/src/coreclr/utilcode/stresslog.cpp index 37abeb2cb92f4e..443be4ade177bc 100644 --- a/src/coreclr/utilcode/stresslog.cpp +++ b/src/coreclr/utilcode/stresslog.cpp @@ -963,7 +963,7 @@ void* StressLog::AllocMemoryMapped(size_t n) return nullptr; } -void* __cdecl ThreadStressLog::operator new(size_t n, const NoThrow&) NOEXCEPT +void* __cdecl ThreadStressLog::operator new(size_t n, const std::nothrow_t&) noexcept { if (StressLogChunk::s_memoryMapped) return StressLog::AllocMemoryMapped(n); diff --git a/src/coreclr/vm/stackingallocator.cpp b/src/coreclr/vm/stackingallocator.cpp index 7db829eb1b441a..c5d1ea2ad79d26 100644 --- a/src/coreclr/vm/stackingallocator.cpp +++ b/src/coreclr/vm/stackingallocator.cpp @@ -399,7 +399,7 @@ void * __cdecl operator new[](size_t n, StackingAllocator * alloc) return retval; } -void * __cdecl operator new(size_t n, StackingAllocator * alloc, const NoThrow&) throw() +void * __cdecl operator new(size_t n, StackingAllocator * alloc, const std::nothrow_t&) noexcept { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; @@ -412,7 +412,7 @@ void * __cdecl operator new(size_t n, StackingAllocator * alloc, const NoThrow&) return alloc->UnsafeAllocNoThrow((unsigned)n); } -void * __cdecl operator new[](size_t n, StackingAllocator * alloc, const NoThrow&) throw() +void * __cdecl operator new[](size_t n, StackingAllocator * alloc, const std::nothrow_t&) noexcept { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; diff --git a/src/coreclr/vm/stackingallocator.h b/src/coreclr/vm/stackingallocator.h index c306e1b482d38e..1878433a7748ef 100644 --- a/src/coreclr/vm/stackingallocator.h +++ b/src/coreclr/vm/stackingallocator.h @@ -271,8 +271,8 @@ class StackingAllocatorHolder void * __cdecl operator new(size_t n, StackingAllocator *alloc); void * __cdecl operator new[](size_t n, StackingAllocator *alloc); -void * __cdecl operator new(size_t n, StackingAllocator *alloc, const NoThrow&) throw(); -void * __cdecl operator new[](size_t n, StackingAllocator *alloc, const NoThrow&) throw(); +void * __cdecl operator new(size_t n, StackingAllocator *alloc, const std::nothrow_t&) noexcept; +void * __cdecl operator new[](size_t n, StackingAllocator *alloc, const std::nothrow_t&) noexcept; #ifdef _MSC_VER #pragma warning(pop) From af889b9efd454c4ed513edbc59e92e22c78e3608 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Thu, 2 May 2024 17:32:11 -0700 Subject: [PATCH 228/248] JIT: synthesize PGO if no schema, when dynamic PGO is active (#101739) If we know dynamic PGO is active, and we do not find a PGO schema for a method, synthesize PGO data. The schema may be missing if the method was prejitted but not covered by static PGO, or was considered too simple to need profiling (aka minimal profiling). This synthesis removes the possibility of a mixed PGO/no PGO situation. These are problematic, especially in methods that do a lot of inlining. Now when dynamic PGO is active all methods that get optimized will have some form of PGO data. Only run profile incorporation when optimizing. Reset BBOPT/pgo vars if we switch away from optimization or have a min opts failover. Contributes to #93020. --- src/coreclr/jit/compiler.cpp | 12 ++++++++++ src/coreclr/jit/fgprofile.cpp | 44 +++++++++++++++++++++-------------- src/coreclr/jit/optimizer.cpp | 2 +- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index f15820a7dc5746..8e82707adbbbfd 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -4088,7 +4088,18 @@ void Compiler::compSetOptimizationLevel() { info.compCompHnd->setMethodAttribs(info.compMethodHnd, CORINFO_FLG_SWITCHED_TO_MIN_OPT); opts.jitFlags->Clear(JitFlags::JIT_FLAG_TIER1); + opts.jitFlags->Clear(JitFlags::JIT_FLAG_BBOPT); compSwitchedToMinOpts = true; + + // We may have read PGO data. Clear it out because we won't be using it. + // + fgPgoFailReason = "method switched to min-opts"; + fgPgoQueryResult = E_FAIL; + fgPgoHaveWeights = false; + fgPgoData = nullptr; + fgPgoSchema = nullptr; + fgPgoDisabled = true; + fgPgoDynamic = false; } #ifdef DEBUG @@ -8056,6 +8067,7 @@ if (!inlineInfo && compileFlags->Set(JitFlags::JIT_FLAG_MIN_OPT); compileFlags->Clear(JitFlags::JIT_FLAG_SIZE_OPT); compileFlags->Clear(JitFlags::JIT_FLAG_SPEED_OPT); + compileFlags->Clear(JitFlags::JIT_FLAG_BBOPT); goto START; } diff --git a/src/coreclr/jit/fgprofile.cpp b/src/coreclr/jit/fgprofile.cpp index 10fdd6035e0b3f..6d7ef484fe9a87 100644 --- a/src/coreclr/jit/fgprofile.cpp +++ b/src/coreclr/jit/fgprofile.cpp @@ -18,26 +18,15 @@ // true if so // // Note: -// This now returns true for inlinees. We might consider preserving the -// old behavior for crossgen, since crossgen BBINSTRs still do inlining -// and don't instrument the inlinees. +// In most cases it is more appropriate to call fgHaveProfileWeights, +// since that tells you if blocks have profile-based weights. // -// Thus if BBINSTR and BBOPT do the same inlines (which can happen) -// profile data for an inlinee (if available) will not fully reflect -// the behavior of the inlinee when called from this method. +// This method literally checks if the runtime had a profile schema, +// from which we can derive weights. // -// If this inlinee was not inlined by the BBINSTR run then the -// profile data for the inlinee will reflect this method's influence. -// -// * for ALWAYS_INLINE and FORCE_INLINE cases it is unlikely we'll find -// any profile data, as BBINSTR and BBOPT callers will both inline; -// only indirect callers will invoke the instrumented version to run. -// * for DISCRETIONARY_INLINE cases we may or may not find relevant -// data, depending, but chances are the data is relevant. -// -// TieredPGO data comes from Tier0 methods, which currently do not do -// any inlining; thus inlinee profile data should be available and -// representative. +// Schema-based data comes from Tier0 methods, which currently do not do +// any inlining; thus inlinee profile data should be available and +// representative. // bool Compiler::fgHaveProfileData() { @@ -47,6 +36,9 @@ bool Compiler::fgHaveProfileData() //------------------------------------------------------------------------ // fgHaveProfileWeights: Check if we have a profile that has weights. // +// Notes: +// These weights may come from instrumentation or from synthesis. +// bool Compiler::fgHaveProfileWeights() { return fgPgoHaveWeights; @@ -2848,6 +2840,14 @@ PhaseStatus Compiler::fgIncorporateProfileData() return PhaseStatus::MODIFIED_EVERYTHING; } + // For now we only rely on profile data when optimizing. + // + if (!opts.OptimizationEnabled()) + { + JITDUMP("not optimizing, so not incorporating any profile data\n"); + return PhaseStatus::MODIFIED_NOTHING; + } + #ifdef DEBUG // Optionally run synthesis // @@ -2887,6 +2887,14 @@ PhaseStatus Compiler::fgIncorporateProfileData() JITDUMP("BBOPT not set\n"); } + // Is dynamic PGO active? If so, run synthesis. + // + if (fgPgoDynamic) + { + JITDUMP("Dynamic PGO active, synthesizing profile data\n"); + ProfileSynthesis::Run(this, ProfileSynthesisOption::AssignLikelihoods); + } + // Scale the "synthetic" block weights. // fgApplyProfileScale(); diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index 7f2ef4bf95d6e6..fae61fbf9b1c48 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -234,7 +234,7 @@ void Compiler::optScaleLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk) for (BasicBlock* const curBlk : BasicBlockRangeList(begBlk, endBlk)) { // Don't change the block weight if it came from profile data. - if (curBlk->hasProfileWeight() && fgHaveProfileData()) + if (curBlk->hasProfileWeight() && fgHaveProfileWeights()) { reportBlockWeight(curBlk, "; unchanged: has profile weight"); continue; From 9e9667500701fd27b54ffc06ec6a5ec0583f8651 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Thu, 2 May 2024 20:29:51 -0500 Subject: [PATCH 229/248] Disable the wasi-aot-library tests on windows (#101827) The clang in the wasi-sdk is a 32bit exe and it is failing to do aot compilation correctly so disable the lane until that is fixed https://github.com/dotnet/runtime/issues/101533 --- eng/pipelines/runtime.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index dbf8e0a7fcc1e4..cb7aadde9fab6d 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -888,7 +888,6 @@ extends: - browser_wasm - browser_wasm_win - wasi_wasm - - wasi_wasm_win nameSuffix: _Smoke_AOT runAOT: true shouldRunSmokeOnly: true From e965312582a33c0acf2020648b54a152a80c139a Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 21:25:46 -0500 Subject: [PATCH 230/248] [main] Update dependencies from dotnet/cecil, dotnet/icu, dotnet/runtime-assets, dotnet/xharness (#101716) * Update dependencies from https://github.com/dotnet/icu build 20240429.1 Microsoft.NETCore.Runtime.ICU.Transport From Version 9.0.0-preview.5.24223.2 -> To Version 9.0.0-preview.5.24229.1 * Update dependencies from https://github.com/dotnet/xharness build 20240429.1 Microsoft.DotNet.XHarness.CLI , Microsoft.DotNet.XHarness.TestRunners.Common , Microsoft.DotNet.XHarness.TestRunners.Xunit From Version 9.0.0-prerelease.24224.1 -> To Version 9.0.0-prerelease.24229.1 * Update dependencies from https://github.com/dotnet/runtime-assets build 20240429.1 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 9.0.0-beta.24222.1 -> To Version 9.0.0-beta.24229.1 * Update dependencies from https://github.com/dotnet/cecil build 20240429.1 Microsoft.SourceBuild.Intermediate.cecil , Microsoft.DotNet.Cecil From Version 0.11.4-alpha.24222.1 -> To Version 0.11.4-alpha.24229.1 * Update dependencies from https://github.com/dotnet/icu build 20240430.1 Microsoft.NETCore.Runtime.ICU.Transport From Version 9.0.0-preview.5.24223.2 -> To Version 9.0.0-preview.5.24230.1 * Update dependencies from https://github.com/dotnet/xharness build 20240429.1 Microsoft.DotNet.XHarness.CLI , Microsoft.DotNet.XHarness.TestRunners.Common , Microsoft.DotNet.XHarness.TestRunners.Xunit From Version 9.0.0-prerelease.24224.1 -> To Version 9.0.0-prerelease.24229.1 * Update dependencies from https://github.com/dotnet/runtime-assets build 20240429.1 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 9.0.0-beta.24222.1 -> To Version 9.0.0-beta.24229.1 * Update dependencies from https://github.com/dotnet/cecil build 20240430.1 Microsoft.SourceBuild.Intermediate.cecil , Microsoft.DotNet.Cecil From Version 0.11.4-alpha.24222.1 -> To Version 0.11.4-alpha.24230.1 * Update dependencies from https://github.com/dotnet/icu build 20240430.1 Microsoft.NETCore.Runtime.ICU.Transport From Version 9.0.0-preview.5.24223.2 -> To Version 9.0.0-preview.5.24230.1 * Update dependencies from https://github.com/dotnet/xharness build 20240429.1 Microsoft.DotNet.XHarness.CLI , Microsoft.DotNet.XHarness.TestRunners.Common , Microsoft.DotNet.XHarness.TestRunners.Xunit From Version 9.0.0-prerelease.24224.1 -> To Version 9.0.0-prerelease.24229.1 * Update dependencies from https://github.com/dotnet/runtime-assets build 20240429.1 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 9.0.0-beta.24222.1 -> To Version 9.0.0-beta.24229.1 * Update dependencies from https://github.com/dotnet/cecil build 20240430.1 Microsoft.SourceBuild.Intermediate.cecil , Microsoft.DotNet.Cecil From Version 0.11.4-alpha.24222.1 -> To Version 0.11.4-alpha.24230.1 --------- Co-authored-by: dotnet-maestro[bot] --- .config/dotnet-tools.json | 2 +- eng/Version.Details.xml | 80 +++++++++++++++++++-------------------- eng/Versions.props | 38 +++++++++---------- 3 files changed, 60 insertions(+), 60 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 1315a20dd66bec..fa97153cf17731 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "9.0.0-prerelease.24224.1", + "version": "9.0.0-prerelease.24229.1", "commands": [ "xharness" ] diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 5deb91fa663263..55491731acd59b 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/icu - 88c4ff85536a2397ba3945dd4a7cdc860c584914 + 3230636546e2b2dc9648c4385c201e28a550f0ea https://github.com/dotnet/msquic @@ -58,14 +58,14 @@ a045dd54a4c44723c215d992288160eb1401bb7f - + https://github.com/dotnet/cecil - 4abe3e63a5d4653ca098c633644432c1395411c1 + 7a4a59f9f66baf6711a6ce2de01d3b2c62ed72d8 - + https://github.com/dotnet/cecil - 4abe3e63a5d4653ca098c633644432c1395411c1 + 7a4a59f9f66baf6711a6ce2de01d3b2c62ed72d8 @@ -174,57 +174,57 @@ https://github.com/dotnet/arcade be933308b9024d798a9a22c0b8f3c8e3616ffbd8 - + https://github.com/dotnet/runtime-assets - 6e78861f1f307cd9f0e64a45b1d7884fa4470930 + 422b5e7d39642735eacc85b2a060abb3899ce497 - + https://github.com/dotnet/runtime-assets - 6e78861f1f307cd9f0e64a45b1d7884fa4470930 + 422b5e7d39642735eacc85b2a060abb3899ce497 - + https://github.com/dotnet/runtime-assets - 6e78861f1f307cd9f0e64a45b1d7884fa4470930 + 422b5e7d39642735eacc85b2a060abb3899ce497 - + https://github.com/dotnet/runtime-assets - 6e78861f1f307cd9f0e64a45b1d7884fa4470930 + 422b5e7d39642735eacc85b2a060abb3899ce497 - + https://github.com/dotnet/runtime-assets - 6e78861f1f307cd9f0e64a45b1d7884fa4470930 + 422b5e7d39642735eacc85b2a060abb3899ce497 - + https://github.com/dotnet/runtime-assets - 6e78861f1f307cd9f0e64a45b1d7884fa4470930 + 422b5e7d39642735eacc85b2a060abb3899ce497 - + https://github.com/dotnet/runtime-assets - 6e78861f1f307cd9f0e64a45b1d7884fa4470930 + 422b5e7d39642735eacc85b2a060abb3899ce497 - + https://github.com/dotnet/runtime-assets - 6e78861f1f307cd9f0e64a45b1d7884fa4470930 + 422b5e7d39642735eacc85b2a060abb3899ce497 - + https://github.com/dotnet/runtime-assets - 6e78861f1f307cd9f0e64a45b1d7884fa4470930 + 422b5e7d39642735eacc85b2a060abb3899ce497 - + https://github.com/dotnet/runtime-assets - 6e78861f1f307cd9f0e64a45b1d7884fa4470930 + 422b5e7d39642735eacc85b2a060abb3899ce497 - + https://github.com/dotnet/runtime-assets - 6e78861f1f307cd9f0e64a45b1d7884fa4470930 + 422b5e7d39642735eacc85b2a060abb3899ce497 - + https://github.com/dotnet/runtime-assets - 6e78861f1f307cd9f0e64a45b1d7884fa4470930 + 422b5e7d39642735eacc85b2a060abb3899ce497 - + https://github.com/dotnet/runtime-assets - 6e78861f1f307cd9f0e64a45b1d7884fa4470930 + 422b5e7d39642735eacc85b2a060abb3899ce497 https://github.com/dotnet/llvm-project @@ -320,17 +320,17 @@ https://github.com/dotnet/runtime 7745b5ec3db34cd358b26710c0ec32db8b0b23f7 - + https://github.com/dotnet/xharness - ec633d9ddbdb86dd3d772989889690821f790484 + ff14b0c0b6d72bf4447d57758a40dbf9494f1ac0 - + https://github.com/dotnet/xharness - ec633d9ddbdb86dd3d772989889690821f790484 + ff14b0c0b6d72bf4447d57758a40dbf9494f1ac0 - + https://github.com/dotnet/xharness - ec633d9ddbdb86dd3d772989889690821f790484 + ff14b0c0b6d72bf4447d57758a40dbf9494f1ac0 https://github.com/dotnet/arcade @@ -356,9 +356,9 @@ https://github.com/dotnet/hotreload-utils 249050528f8ac9882f04b2c719bda3e5a532b258 - + https://github.com/dotnet/runtime-assets - 6e78861f1f307cd9f0e64a45b1d7884fa4470930 + 422b5e7d39642735eacc85b2a060abb3899ce497 https://github.com/dotnet/roslyn diff --git a/eng/Versions.props b/eng/Versions.props index b35035d520cded..a5758b9356e247 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -138,20 +138,20 @@ 8.0.0 8.0.0 - 9.0.0-beta.24222.1 - 9.0.0-beta.24222.1 - 9.0.0-beta.24222.1 - 9.0.0-beta.24222.1 - 9.0.0-beta.24222.1 - 9.0.0-beta.24222.1 - 9.0.0-beta.24222.1 - 9.0.0-beta.24222.1 - 9.0.0-beta.24222.1 - 9.0.0-beta.24222.1 - 9.0.0-beta.24222.1 - 9.0.0-beta.24222.1 - 9.0.0-beta.24222.1 - 9.0.0-beta.24222.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 + 9.0.0-beta.24229.1 1.0.0-prerelease.24223.3 1.0.0-prerelease.24223.3 @@ -179,9 +179,9 @@ 1.4.0 17.4.0-preview-20220707-01 - 9.0.0-prerelease.24224.1 - 9.0.0-prerelease.24224.1 - 9.0.0-prerelease.24224.1 + 9.0.0-prerelease.24229.1 + 9.0.0-prerelease.24229.1 + 9.0.0-prerelease.24229.1 9.0.0-alpha.0.24222.1 3.12.0 4.5.0 @@ -208,11 +208,11 @@ 8.0.0-preview-20230918.1 - 0.11.4-alpha.24222.1 + 0.11.4-alpha.24230.1 9.0.0-preview.4.24229.1 - 9.0.0-preview.5.24223.2 + 9.0.0-preview.5.24230.1 2.3.5 9.0.0-alpha.1.24167.3 From 15e98e58e6023be3121dcb0ed2e701d1d5cd098e Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Fri, 3 May 2024 09:38:31 +0200 Subject: [PATCH 231/248] JIT: Mark swift error as busy before call definition RefPosition (#101792) The RefPosition we were inserting here was inserted too late to actually protect the call definition from being allocated into the error register. Instead, we can just mark the existing `RefTypeFixedReg` created for the argument use as delay freed, which will have the intended effect of keeping the error register busy until after the call definition. --- src/coreclr/jit/lsra.h | 1 + src/coreclr/jit/lsraarmarch.cpp | 18 +----------------- src/coreclr/jit/lsrabuild.cpp | 33 +++++++++++++++++++++++++++++++++ src/coreclr/jit/lsraxarch.cpp | 18 +----------------- 4 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/coreclr/jit/lsra.h b/src/coreclr/jit/lsra.h index fe09a2e4564410..09f8b8d63e581a 100644 --- a/src/coreclr/jit/lsra.h +++ b/src/coreclr/jit/lsra.h @@ -2062,6 +2062,7 @@ class LinearScan : public LinearScanInterface #endif int BuildPutArgReg(GenTreeUnOp* node); int BuildCall(GenTreeCall* call); + void MarkSwiftErrorBusyForCall(GenTreeCall* call); int BuildCmp(GenTree* tree); int BuildCmpOperands(GenTree* tree); int BuildBlockStore(GenTreeBlk* blkNode); diff --git a/src/coreclr/jit/lsraarmarch.cpp b/src/coreclr/jit/lsraarmarch.cpp index cf5302dee9c711..64bbe23b06a667 100644 --- a/src/coreclr/jit/lsraarmarch.cpp +++ b/src/coreclr/jit/lsraarmarch.cpp @@ -404,23 +404,7 @@ int LinearScan::BuildCall(GenTreeCall* call) #ifdef SWIFT_SUPPORT if (call->HasSwiftErrorHandling()) { - // Tree is a Swift call with error handling; error register should have been killed - assert((killMask & RBM_SWIFT_ERROR) != 0); - - // After a Swift call that might throw returns, we expect the error register to be consumed - // by a GT_SWIFT_ERROR node. However, we want to ensure the error register won't be trashed - // before GT_SWIFT_ERROR can consume it. - // (For example, the PInvoke epilog comes before the error register store.) - // To do so, delay the freeing of the error register until the next node. - // This only works if the next node after the call is the GT_SWIFT_ERROR node. - // (InsertPInvokeCallEpilog should have moved the GT_SWIFT_ERROR node during lowering.) - assert(call->gtNext != nullptr); - assert(call->gtNext->OperIs(GT_SWIFT_ERROR)); - - // We could use RefTypeKill, but RefTypeFixedReg is used less commonly, so the check for delayRegFree - // during register allocation should be cheaper in terms of TP. - RefPosition* pos = newRefPosition(REG_SWIFT_ERROR, currentLoc + 1, RefTypeFixedReg, call, RBM_SWIFT_ERROR); - setDelayFree(pos); + MarkSwiftErrorBusyForCall(call); } #endif // SWIFT_SUPPORT diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 4a4af7725dd4da..41b375acd43929 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -4479,3 +4479,36 @@ int LinearScan::BuildCmpOperands(GenTree* tree) srcCount += BuildOperandUses(op2, op2Candidates); return srcCount; } + +#ifdef SWIFT_SUPPORT +//------------------------------------------------------------------------ +// MarkSwiftErrorBusyForCall: Given a call set the appropriate RefTypeFixedReg +// RefPosition for the Swift error register as delay free to ensure the error +// register does not get allocated by LSRA before it has been consumed. +// +// Arguments: +// call - The call node +// +void LinearScan::MarkSwiftErrorBusyForCall(GenTreeCall* call) +{ + assert(call->HasSwiftErrorHandling()); + // After a Swift call that might throw returns, we expect the error register to be consumed + // by a GT_SWIFT_ERROR node. However, we want to ensure the error register won't be trashed + // before GT_SWIFT_ERROR can consume it. + // (For example, by LSRA allocating the call's result to the same register.) + // To do so, delay the freeing of the error register until the next node. + // This only works if the next node after the call is the GT_SWIFT_ERROR node. + // (LowerNonvirtPinvokeCall should have moved the GT_SWIFT_ERROR node.) + assert(call->gtNext != nullptr); + assert(call->gtNext->OperIs(GT_SWIFT_ERROR)); + + // Conveniently we model the zeroing of the register as a non-standard constant zero argument, + // which will have created a RefPosition corresponding to the use of the error at the location + // of the uses. Marking this RefPosition as delay freed has the effect of keeping the register + // busy at the location of the definition of the call. + RegRecord* swiftErrorRegRecord = getRegisterRecord(REG_SWIFT_ERROR); + assert((swiftErrorRegRecord != nullptr) && (swiftErrorRegRecord->lastRefPosition != nullptr) && + (swiftErrorRegRecord->lastRefPosition->nodeLocation == currentLoc)); + setDelayFree(swiftErrorRegRecord->lastRefPosition); +} +#endif diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index 7109c9087ac4e1..3d19214f8acbdd 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -1380,23 +1380,7 @@ int LinearScan::BuildCall(GenTreeCall* call) #ifdef SWIFT_SUPPORT if (call->HasSwiftErrorHandling()) { - // Tree is a Swift call with error handling; error register should have been killed - assert((killMask & RBM_SWIFT_ERROR) != 0); - - // After a Swift call that might throw returns, we expect the error register to be consumed - // by a GT_SWIFT_ERROR node. However, we want to ensure the error register won't be trashed - // before GT_SWIFT_ERROR can consume it. - // (For example, the PInvoke epilog comes before the error register store.) - // To do so, delay the freeing of the error register until the next node. - // This only works if the next node after the call is the GT_SWIFT_ERROR node. - // (InsertPInvokeCallEpilog should have moved the GT_SWIFT_ERROR node during lowering.) - assert(call->gtNext != nullptr); - assert(call->gtNext->OperIs(GT_SWIFT_ERROR)); - - // We could use RefTypeKill, but RefTypeFixedReg is used less commonly, so the check for delayRegFree - // during register allocation should be cheaper in terms of TP. - RefPosition* pos = newRefPosition(REG_SWIFT_ERROR, currentLoc + 1, RefTypeFixedReg, call, RBM_SWIFT_ERROR); - setDelayFree(pos); + MarkSwiftErrorBusyForCall(call); } #endif // SWIFT_SUPPORT From 4a9507335e4b071a7082182871dd09cbfcf24b83 Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Fri, 3 May 2024 14:13:45 +0300 Subject: [PATCH 232/248] Trim instructionset name in helper (#101794) --- src/coreclr/tools/Common/InstructionSetHelpers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/tools/Common/InstructionSetHelpers.cs b/src/coreclr/tools/Common/InstructionSetHelpers.cs index 718053f13d0c33..8a7303f15f3711 100644 --- a/src/coreclr/tools/Common/InstructionSetHelpers.cs +++ b/src/coreclr/tools/Common/InstructionSetHelpers.cs @@ -122,7 +122,7 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru string[] instructionSetParamsInput = instructionSet.Split(','); for (int i = 0; i < instructionSetParamsInput.Length; i++) { - instructionSet = instructionSetParamsInput[i]; + instructionSet = instructionSetParamsInput[i].Trim(); if (string.IsNullOrEmpty(instructionSet)) throw new CommandLineException(string.Format(mustNotBeMessage, "")); From f01a14686845e6d58ebe6ccf173653a02b3ec6dc Mon Sep 17 00:00:00 2001 From: Alan Hayward Date: Fri, 3 May 2024 13:54:00 +0100 Subject: [PATCH 233/248] JIT ARM64-SVE: Add simple bitwise ops (#101762) * JIT ARM64-SVE: Add simple bitwise ops And,AndAcross,Or,OrAcross,Xor,XorAcross * Fix fadda * Fix unpkh/fexpa/frecpe * Reorder System.Runtime.Intrinsics.cs * Fix API head comments --- src/coreclr/jit/codegenarm64test.cpp | 46 +- src/coreclr/jit/emitarm64sve.cpp | 19 +- src/coreclr/jit/hwintrinsiclistarm64sve.h | 6 + .../Arm/Sve.PlatformNotSupported.cs | 428 ++++++++++++++++++ .../src/System/Runtime/Intrinsics/Arm/Sve.cs | 428 ++++++++++++++++++ .../ref/System.Runtime.Intrinsics.cs | 54 +++ .../GenerateHWIntrinsicTests_Arm.cs | 54 +++ .../HardwareIntrinsics/Arm/Shared/Helpers.cs | 48 ++ 8 files changed, 1055 insertions(+), 28 deletions(-) diff --git a/src/coreclr/jit/codegenarm64test.cpp b/src/coreclr/jit/codegenarm64test.cpp index dcd24539e9918d..ddc7d831f228df 100644 --- a/src/coreclr/jit/codegenarm64test.cpp +++ b/src/coreclr/jit/codegenarm64test.cpp @@ -4798,11 +4798,11 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_D); // CLASTB ., , ., . // IF_SVE_CN_3A - theEmitter->emitIns_R_R_R(INS_sve_clasta, EA_2BYTE, REG_V12, REG_P1, REG_V15, INS_OPTS_SCALABLE_H, + theEmitter->emitIns_R_R_R(INS_sve_clasta, EA_SCALABLE, REG_V12, REG_P1, REG_V15, INS_OPTS_SCALABLE_H, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // CLASTA , , , . - theEmitter->emitIns_R_R_R(INS_sve_clastb, EA_4BYTE, REG_V13, REG_P2, REG_V16, INS_OPTS_SCALABLE_S, + theEmitter->emitIns_R_R_R(INS_sve_clastb, EA_SCALABLE, REG_V13, REG_P2, REG_V16, INS_OPTS_SCALABLE_S, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // CLASTB , , , . - theEmitter->emitIns_R_R_R(INS_sve_clastb, EA_8BYTE, REG_V14, REG_P0, REG_V17, INS_OPTS_SCALABLE_D, + theEmitter->emitIns_R_R_R(INS_sve_clastb, EA_SCALABLE, REG_V14, REG_P0, REG_V17, INS_OPTS_SCALABLE_D, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // CLASTB , , , . // IF_SVE_CO_3A @@ -5112,11 +5112,11 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_H); // FMINP ., /M, ., . // IF_SVE_HJ_3A - theEmitter->emitIns_R_R_R(INS_sve_fadda, EA_2BYTE, REG_V21, REG_P6, REG_V14, + theEmitter->emitIns_R_R_R(INS_sve_fadda, EA_SCALABLE, REG_V21, REG_P6, REG_V14, INS_OPTS_SCALABLE_H); // FADDA , , , . - theEmitter->emitIns_R_R_R(INS_sve_fadda, EA_4BYTE, REG_V22, REG_P5, REG_V13, + theEmitter->emitIns_R_R_R(INS_sve_fadda, EA_SCALABLE, REG_V22, REG_P5, REG_V13, INS_OPTS_SCALABLE_S); // FADDA , , , . - theEmitter->emitIns_R_R_R(INS_sve_fadda, EA_8BYTE, REG_V23, REG_P4, REG_V12, + theEmitter->emitIns_R_R_R(INS_sve_fadda, EA_SCALABLE, REG_V23, REG_P4, REG_V12, INS_OPTS_SCALABLE_D); // FADDA , , , . // IF_SVE_HL_3A @@ -5288,13 +5288,13 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_H); // FNMLS ., /M, ., . // IF_SVE_AF_3A - theEmitter->emitIns_R_R_R(INS_sve_andv, EA_1BYTE, REG_V0, REG_P0, REG_V0, + theEmitter->emitIns_R_R_R(INS_sve_andv, EA_SCALABLE, REG_V0, REG_P0, REG_V0, INS_OPTS_SCALABLE_B); // ANDV , , . - theEmitter->emitIns_R_R_R(INS_sve_eorv, EA_2BYTE, REG_V1, REG_P1, REG_V1, + theEmitter->emitIns_R_R_R(INS_sve_eorv, EA_SCALABLE, REG_V1, REG_P1, REG_V1, INS_OPTS_SCALABLE_H); // EORV , , . - theEmitter->emitIns_R_R_R(INS_sve_orv, EA_4BYTE, REG_V2, REG_P2, REG_V2, + theEmitter->emitIns_R_R_R(INS_sve_orv, EA_SCALABLE, REG_V2, REG_P2, REG_V2, INS_OPTS_SCALABLE_S); // ORV , , . - theEmitter->emitIns_R_R_R(INS_sve_orv, EA_8BYTE, REG_V3, REG_P3, REG_V3, + theEmitter->emitIns_R_R_R(INS_sve_orv, EA_SCALABLE, REG_V3, REG_P3, REG_V3, INS_OPTS_SCALABLE_D); // ORV , , . // IF_SVE_AG_3A @@ -5324,13 +5324,13 @@ void CodeGen::genArm64EmitterUnitTestsSve() #endif // ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED // IF_SVE_AK_3A - theEmitter->emitIns_R_R_R(INS_sve_smaxv, EA_8BYTE, REG_V15, REG_P7, REG_V4, + theEmitter->emitIns_R_R_R(INS_sve_smaxv, EA_SCALABLE, REG_V15, REG_P7, REG_V4, INS_OPTS_SCALABLE_D); // SMAXV , , . - theEmitter->emitIns_R_R_R(INS_sve_sminv, EA_4BYTE, REG_V16, REG_P6, REG_V14, + theEmitter->emitIns_R_R_R(INS_sve_sminv, EA_SCALABLE, REG_V16, REG_P6, REG_V14, INS_OPTS_SCALABLE_S); // SMINV , , . - theEmitter->emitIns_R_R_R(INS_sve_umaxv, EA_2BYTE, REG_V17, REG_P5, REG_V24, + theEmitter->emitIns_R_R_R(INS_sve_umaxv, EA_SCALABLE, REG_V17, REG_P5, REG_V24, INS_OPTS_SCALABLE_H); // UMAXV , , . - theEmitter->emitIns_R_R_R(INS_sve_uminv, EA_1BYTE, REG_V18, REG_P4, REG_V31, + theEmitter->emitIns_R_R_R(INS_sve_uminv, EA_SCALABLE, REG_V18, REG_P4, REG_V31, INS_OPTS_SCALABLE_B); // UMINV , , . // IF_SVE_AL_3A @@ -6218,13 +6218,13 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_D); // COMPACT ., , . // IF_SVE_CP_3A - theEmitter->emitIns_R_R_R(INS_sve_cpy, EA_1BYTE, REG_V14, REG_P1, REG_V11, INS_OPTS_SCALABLE_B, + theEmitter->emitIns_R_R_R(INS_sve_cpy, EA_SCALABLE, REG_V14, REG_P1, REG_V11, INS_OPTS_SCALABLE_B, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // CPY ., /M, - theEmitter->emitIns_R_R_R(INS_sve_cpy, EA_4BYTE, REG_V13, REG_P2, REG_V10, INS_OPTS_SCALABLE_S, + theEmitter->emitIns_R_R_R(INS_sve_cpy, EA_SCALABLE, REG_V13, REG_P2, REG_V10, INS_OPTS_SCALABLE_S, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // CPY ., /M, - theEmitter->emitIns_R_R_R(INS_sve_mov, EA_2BYTE, REG_V12, REG_P3, REG_V9, INS_OPTS_SCALABLE_H, + theEmitter->emitIns_R_R_R(INS_sve_mov, EA_SCALABLE, REG_V12, REG_P3, REG_V9, INS_OPTS_SCALABLE_H, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // MOV ., /M, - theEmitter->emitIns_R_R_R(INS_sve_mov, EA_8BYTE, REG_V11, REG_P4, REG_V8, INS_OPTS_SCALABLE_D, + theEmitter->emitIns_R_R_R(INS_sve_mov, EA_SCALABLE, REG_V11, REG_P4, REG_V8, INS_OPTS_SCALABLE_D, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // MOV ., /M, // IF_SVE_CQ_3A @@ -6239,13 +6239,13 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_B); // MOV ., /M, // IF_SVE_CR_3A - theEmitter->emitIns_R_R_R(INS_sve_lasta, EA_1BYTE, REG_V6, REG_P1, REG_V27, INS_OPTS_SCALABLE_B, + theEmitter->emitIns_R_R_R(INS_sve_lasta, EA_SCALABLE, REG_V6, REG_P1, REG_V27, INS_OPTS_SCALABLE_B, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // LASTA , , . - theEmitter->emitIns_R_R_R(INS_sve_lasta, EA_2BYTE, REG_V5, REG_P2, REG_V26, INS_OPTS_SCALABLE_H, + theEmitter->emitIns_R_R_R(INS_sve_lasta, EA_SCALABLE, REG_V5, REG_P2, REG_V26, INS_OPTS_SCALABLE_H, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // LASTA , , . - theEmitter->emitIns_R_R_R(INS_sve_lastb, EA_4BYTE, REG_V4, REG_P3, REG_V25, INS_OPTS_SCALABLE_S, + theEmitter->emitIns_R_R_R(INS_sve_lastb, EA_SCALABLE, REG_V4, REG_P3, REG_V25, INS_OPTS_SCALABLE_S, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // LASTB , , . - theEmitter->emitIns_R_R_R(INS_sve_lastb, EA_8BYTE, REG_V3, REG_P4, REG_V24, INS_OPTS_SCALABLE_D, + theEmitter->emitIns_R_R_R(INS_sve_lastb, EA_SCALABLE, REG_V3, REG_P4, REG_V24, INS_OPTS_SCALABLE_D, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // LASTB , , . // IF_SVE_CS_3A @@ -8905,7 +8905,7 @@ void CodeGen::genArm64EmitterUnitTestsSve() // SUNPKLO ., . theEmitter->emitIns_R_R(INS_sve_sunpklo, EA_SCALABLE, REG_V1, REG_V5, INS_OPTS_SCALABLE_S); // UUNPKHI ., . - theEmitter->emitIns_R_R(INS_sve_uunpkhi, EA_SCALABLE, REG_V5, REG_V1, INS_OPTS_SCALABLE_D); + theEmitter->emitIns_R_R(INS_sve_uunpkhi, EA_SCALABLE, REG_V5, REG_V1, INS_OPTS_SCALABLE_B); // UUNPKLO ., . theEmitter->emitIns_R_R(INS_sve_uunpklo, EA_SCALABLE, REG_V8, REG_V6, INS_OPTS_SCALABLE_S); diff --git a/src/coreclr/jit/emitarm64sve.cpp b/src/coreclr/jit/emitarm64sve.cpp index 160e87d0542756..0c8485a459b5a8 100644 --- a/src/coreclr/jit/emitarm64sve.cpp +++ b/src/coreclr/jit/emitarm64sve.cpp @@ -2919,7 +2919,10 @@ void emitter::emitInsSve_R_R_R(instruction ins, if (sopt == INS_SCALABLE_OPTS_UNPREDICATED) { - assert(opt == INS_OPTS_SCALABLE_D); + // The instruction only has a .D variant. However, this doesn't matter as + // it operates on bits not lanes. Effectively this means all standard opt + // sizes are supported. + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg2)); // nnnnn fmt = IF_SVE_AU_3A; } @@ -3728,7 +3731,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, else if (sopt == INS_SCALABLE_OPTS_WITH_SIMD_SCALAR) { assert(isFloatReg(reg1)); - assert(isValidVectorElemsize(size)); + assert(isScalableVectorSize(size)); fmt = IF_SVE_CN_3A; } else @@ -3748,7 +3751,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, if (sopt == INS_SCALABLE_OPTS_UNPREDICATED) { assert(ins == INS_sve_mov); - assert(opt == INS_OPTS_SCALABLE_D); + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg1)); // ddddd assert(isVectorRegister(reg2)); // nnnnn assert(isVectorRegister(reg3)); // mmmmm @@ -11817,6 +11820,7 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id) code |= insEncodeSveElemsize(optGetSveElemsize((insOpts)(id->idInsOpt() + 1))); // xx dst += emitOutput_Instr(dst, code); break; + case IF_SVE_BF_2A: // ........xx.xxiii ......nnnnnddddd -- SVE bitwise shift by immediate (unpredicated) case IF_SVE_FT_2A: // ........xx.xxiii ......nnnnnddddd -- SVE2 bitwise shift and insert case IF_SVE_FU_2A: // ........xx.xxiii ......nnnnnddddd -- SVE2 bitwise shift right and accumulate @@ -12618,7 +12622,7 @@ void emitter::emitInsSveSanityCheck(instrDesc* id) assert(isVectorRegister(id->idReg1())); // ddddd assert(isLowPredicateRegister(id->idReg2())); // ggg assert(isVectorRegister(id->idReg3())); // mmmmm - assert(isValidVectorElemsize(id->idOpSize())); + assert(isScalableVectorSize(id->idOpSize())); break; // Scalable to FP SIMD scalar. @@ -14389,8 +14393,13 @@ void emitter::emitInsSveSanityCheck(instrDesc* id) break; case IF_SVE_BJ_2A: // ........xx...... ......nnnnnddddd -- SVE floating-point exponential accelerator - case IF_SVE_CH_2A: // ........xx...... ......nnnnnddddd -- SVE unpack vector elements case IF_SVE_HF_2A: // ........xx...... ......nnnnnddddd -- SVE floating-point reciprocal estimate (unpredicated) + assert(insOptsScalableAtLeastHalf(id->idInsOpt())); + assert(isVectorRegister(id->idReg1())); + assert(isVectorRegister(id->idReg2())); + break; + + case IF_SVE_CH_2A: // ........xx...... ......nnnnnddddd -- SVE unpack vector elements assert(insOptsScalableWide(id->idInsOpt())); assert(isVectorRegister(id->idReg1())); assert(isVectorRegister(id->idReg2())); diff --git a/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/coreclr/jit/hwintrinsiclistarm64sve.h index 6a8346c216282c..7bb1789175a1a0 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64sve.h +++ b/src/coreclr/jit/hwintrinsiclistarm64sve.h @@ -20,6 +20,8 @@ HARDWARE_INTRINSIC(Sve, Abs, -1, -1, false, {INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_fabs, INS_sve_fabs}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation) HARDWARE_INTRINSIC(Sve, Add, -1, -1, false, {INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_fadd, INS_sve_fadd}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, AddAcross, -1, 1, true, {INS_sve_saddv, INS_sve_uaddv, INS_sve_saddv, INS_sve_uaddv, INS_sve_saddv, INS_sve_uaddv, INS_sve_uaddv, INS_sve_uaddv, INS_sve_faddv, INS_sve_faddv}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbeddedMaskedOperation) +HARDWARE_INTRINSIC(Sve, And, -1, -1, false, {INS_sve_and, INS_sve_and, INS_sve_and, INS_sve_and, INS_sve_and, INS_sve_and, INS_sve_and, INS_sve_and, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, AndAcross, -1, -1, false, {INS_sve_andv, INS_sve_andv, INS_sve_andv, INS_sve_andv, INS_sve_andv, INS_sve_andv, INS_sve_andv, INS_sve_andv, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, ConditionalSelect, -1, 3, true, {INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(Sve, Count16BitElements, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_cnth, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_SpecialCodeGen|HW_Flag_NoFloatingPointUsed) HARDWARE_INTRINSIC(Sve, Count32BitElements, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_cntw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_SpecialCodeGen|HW_Flag_NoFloatingPointUsed) @@ -70,6 +72,8 @@ HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToUInt64, HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, Multiply, -1, 2, true, {INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_fmul, INS_sve_fmul}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sve, Or, -1, -1, false, {INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, OrAcross, -1, -1, false, {INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, SignExtend16, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sxth, INS_invalid, INS_sve_sxth, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, SignExtend32, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sxtw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, SignExtend8, -1, -1, false, {INS_invalid, INS_invalid, INS_sve_sxtb, INS_invalid, INS_sve_sxtb, INS_invalid, INS_sve_sxtb, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) @@ -78,6 +82,8 @@ HARDWARE_INTRINSIC(Sve, SignExtendWideningUpper, HARDWARE_INTRINSIC(Sve, Subtract, -1, 2, true, {INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_fsub, INS_sve_fsub}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve, UnzipEven, -1, 2, true, {INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Sve, UnzipOdd, -1, 2, true, {INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, Xor, -1, -1, false, {INS_sve_eor, INS_sve_eor, INS_sve_eor, INS_sve_eor, INS_sve_eor, INS_sve_eor, INS_sve_eor, INS_sve_eor, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, XorAcross, -1, -1, false, {INS_sve_eorv, INS_sve_eorv, INS_sve_eorv, INS_sve_eorv, INS_sve_eorv, INS_sve_eorv, INS_sve_eorv, INS_sve_eorv, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, ZeroExtend16, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_uxth, INS_invalid, INS_sve_uxth, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, ZeroExtend32, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_uxtw, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, ZeroExtend8, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_uxtb, INS_invalid, INS_sve_uxtb, INS_invalid, INS_sve_uxtb, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs index 5cc1d3df2f7cb7..b4f28f01193ea6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs @@ -211,6 +211,148 @@ internal Arm64() { } public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + /// And : Bitwise AND + + /// + /// svuint8_t svand[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svand[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svand[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// AND Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svand[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svand[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svand[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// AND Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svand[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svand[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svand[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// AND Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svand[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svand[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svand[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// AND Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svand[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svand[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svand[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// AND Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svand[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svand[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svand[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// AND Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svand[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svand[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svand[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// AND Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svand[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svand[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svand[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// AND Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// AndAcross : Bitwise AND reduction to scalar + + /// + /// uint8_t svandv[_u8](svbool_t pg, svuint8_t op) + /// ANDV Bresult, Pg, Zop.B + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int16_t svandv[_s16](svbool_t pg, svint16_t op) + /// ANDV Hresult, Pg, Zop.H + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int32_t svandv[_s32](svbool_t pg, svint32_t op) + /// ANDV Sresult, Pg, Zop.S + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svandv[_s64](svbool_t pg, svint64_t op) + /// ANDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int8_t svandv[_s8](svbool_t pg, svint8_t op) + /// ANDV Bresult, Pg, Zop.B + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t svandv[_u16](svbool_t pg, svuint16_t op) + /// ANDV Hresult, Pg, Zop.H + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t svandv[_u32](svbool_t pg, svuint32_t op) + /// ANDV Sresult, Pg, Zop.S + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svandv[_u64](svbool_t pg, svuint64_t op) + /// ANDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// ConditionalSelect : Conditionally select elements /// @@ -1072,6 +1214,149 @@ internal Arm64() { } /// public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// Or : Bitwise inclusive OR + + /// + /// svuint8_t svorr[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svorr[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svorr[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// ORR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svorr[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svorr[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svorr[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// ORR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svorr[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svorr[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svorr[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// ORR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svorr[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svorr[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svorr[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// ORR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svorr[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svorr[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svorr[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// ORR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svorr[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svorr[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svorr[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// ORR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svorr[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svorr[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svorr[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// ORR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svorr[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svorr[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svorr[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// ORR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// OrAcross : Bitwise inclusive OR reduction to scalar + + /// + /// uint8_t svorv[_u8](svbool_t pg, svuint8_t op) + /// ORV Bresult, Pg, Zop.B + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int16_t svorv[_s16](svbool_t pg, svint16_t op) + /// ORV Hresult, Pg, Zop.H + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int32_t svorv[_s32](svbool_t pg, svint32_t op) + /// ORV Sresult, Pg, Zop.S + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svorv[_s64](svbool_t pg, svint64_t op) + /// ORV Dresult, Pg, Zop.D + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int8_t svorv[_s8](svbool_t pg, svint8_t op) + /// ORV Bresult, Pg, Zop.B + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t svorv[_u16](svbool_t pg, svuint16_t op) + /// ORV Hresult, Pg, Zop.H + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t svorv[_u32](svbool_t pg, svuint32_t op) + /// ORV Sresult, Pg, Zop.S + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svorv[_u64](svbool_t pg, svuint64_t op) + /// ORV Dresult, Pg, Zop.D + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// SignExtend16 : Sign-extend the low 16 bits /// @@ -1432,6 +1717,149 @@ internal Arm64() { } /// public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// Xor : Bitwise exclusive OR + + /// + /// svuint8_t sveor[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t sveor[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t sveor[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// EOR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t sveor[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t sveor[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t sveor[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// EOR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t sveor[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t sveor[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t sveor[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// EOR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t sveor[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t sveor[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t sveor[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// EOR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t sveor[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t sveor[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t sveor[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// EOR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t sveor[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t sveor[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t sveor[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// EOR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t sveor[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t sveor[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t sveor[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// EOR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t sveor[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t sveor[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t sveor[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// EOR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// XorAcross : Bitwise exclusive OR reduction to scalar + + /// + /// uint8_t sveorv[_u8](svbool_t pg, svuint8_t op) + /// EORV Bresult, Pg, Zop.B + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int16_t sveorv[_s16](svbool_t pg, svint16_t op) + /// EORV Hresult, Pg, Zop.H + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int32_t sveorv[_s32](svbool_t pg, svint32_t op) + /// EORV Sresult, Pg, Zop.S + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t sveorv[_s64](svbool_t pg, svint64_t op) + /// EORV Dresult, Pg, Zop.D + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int8_t sveorv[_s8](svbool_t pg, svint8_t op) + /// EORV Bresult, Pg, Zop.B + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t sveorv[_u16](svbool_t pg, svuint16_t op) + /// EORV Hresult, Pg, Zop.H + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t sveorv[_u32](svbool_t pg, svuint32_t op) + /// EORV Sresult, Pg, Zop.S + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t sveorv[_u64](svbool_t pg, svuint64_t op) + /// EORV Dresult, Pg, Zop.D + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// ZeroExtend16 : Zero-extend the low 16 bits /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs index d195dd03dfb484..39380f8a50f9aa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs @@ -240,6 +240,148 @@ internal Arm64() { } public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + /// And : Bitwise AND + + /// + /// svuint8_t svand[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svand[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svand[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// AND Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + /// + /// svint16_t svand[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svand[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svand[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// AND Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + /// + /// svint32_t svand[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svand[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svand[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// AND Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + /// + /// svint64_t svand[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svand[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svand[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// AND Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + /// + /// svint8_t svand[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svand[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svand[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// AND Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + /// + /// svuint16_t svand[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svand[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svand[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// AND Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + /// + /// svuint32_t svand[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svand[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svand[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// AND Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + /// + /// svuint64_t svand[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svand[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svand[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// AND Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + + /// AndAcross : Bitwise AND reduction to scalar + + /// + /// uint8_t svandv[_u8](svbool_t pg, svuint8_t op) + /// ANDV Bresult, Pg, Zop.B + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + /// + /// int16_t svandv[_s16](svbool_t pg, svint16_t op) + /// ANDV Hresult, Pg, Zop.H + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + /// + /// int32_t svandv[_s32](svbool_t pg, svint32_t op) + /// ANDV Sresult, Pg, Zop.S + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + /// + /// int64_t svandv[_s64](svbool_t pg, svint64_t op) + /// ANDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + /// + /// int8_t svandv[_s8](svbool_t pg, svint8_t op) + /// ANDV Bresult, Pg, Zop.B + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + /// + /// uint16_t svandv[_u16](svbool_t pg, svuint16_t op) + /// ANDV Hresult, Pg, Zop.H + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + /// + /// uint32_t svandv[_u32](svbool_t pg, svuint32_t op) + /// ANDV Sresult, Pg, Zop.S + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + /// + /// uint64_t svandv[_u64](svbool_t pg, svuint64_t op) + /// ANDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + /// ConditionalSelect : Conditionally select elements /// @@ -1128,6 +1270,149 @@ internal Arm64() { } /// public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// Or : Bitwise inclusive OR + + /// + /// svuint8_t svorr[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svorr[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svorr[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// ORR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + /// + /// svint16_t svorr[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svorr[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svorr[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// ORR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + /// + /// svint32_t svorr[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svorr[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svorr[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// ORR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + /// + /// svint64_t svorr[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svorr[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svorr[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// ORR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + /// + /// svint8_t svorr[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svorr[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svorr[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// ORR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + /// + /// svuint16_t svorr[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svorr[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svorr[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// ORR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + /// + /// svuint32_t svorr[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svorr[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svorr[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// ORR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + /// + /// svuint64_t svorr[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svorr[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svorr[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// ORR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + + /// OrAcross : Bitwise inclusive OR reduction to scalar + + /// + /// uint8_t svorv[_u8](svbool_t pg, svuint8_t op) + /// ORV Bresult, Pg, Zop.B + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + /// + /// int16_t svorv[_s16](svbool_t pg, svint16_t op) + /// ORV Hresult, Pg, Zop.H + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + /// + /// int32_t svorv[_s32](svbool_t pg, svint32_t op) + /// ORV Sresult, Pg, Zop.S + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + /// + /// int64_t svorv[_s64](svbool_t pg, svint64_t op) + /// ORV Dresult, Pg, Zop.D + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + /// + /// int8_t svorv[_s8](svbool_t pg, svint8_t op) + /// ORV Bresult, Pg, Zop.B + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + /// + /// uint16_t svorv[_u16](svbool_t pg, svuint16_t op) + /// ORV Hresult, Pg, Zop.H + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + /// + /// uint32_t svorv[_u32](svbool_t pg, svuint32_t op) + /// ORV Sresult, Pg, Zop.S + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + /// + /// uint64_t svorv[_u64](svbool_t pg, svuint64_t op) + /// ORV Dresult, Pg, Zop.D + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + /// SignExtend16 : Sign-extend the low 16 bits /// @@ -1514,6 +1799,149 @@ internal Arm64() { } /// public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + + /// Xor : Bitwise exclusive OR + + /// + /// svuint8_t sveor[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t sveor[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t sveor[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// EOR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); + + /// + /// svint16_t sveor[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t sveor[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t sveor[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// EOR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); + + /// + /// svint32_t sveor[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t sveor[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t sveor[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// EOR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); + + /// + /// svint64_t sveor[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t sveor[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t sveor[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// EOR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); + + /// + /// svint8_t sveor[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t sveor[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t sveor[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// EOR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); + + /// + /// svuint16_t sveor[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t sveor[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t sveor[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// EOR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); + + /// + /// svuint32_t sveor[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t sveor[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t sveor[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// EOR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); + + /// + /// svuint64_t sveor[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t sveor[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t sveor[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// EOR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); + + + /// XorAcross : Bitwise exclusive OR reduction to scalar + + /// + /// uint8_t sveorv[_u8](svbool_t pg, svuint8_t op) + /// EORV Bresult, Pg, Zop.B + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + + /// + /// int16_t sveorv[_s16](svbool_t pg, svint16_t op) + /// EORV Hresult, Pg, Zop.H + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + + /// + /// int32_t sveorv[_s32](svbool_t pg, svint32_t op) + /// EORV Sresult, Pg, Zop.S + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + + /// + /// int64_t sveorv[_s64](svbool_t pg, svint64_t op) + /// EORV Dresult, Pg, Zop.D + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + + /// + /// int8_t sveorv[_s8](svbool_t pg, svint8_t op) + /// EORV Bresult, Pg, Zop.B + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + + /// + /// uint16_t sveorv[_u16](svbool_t pg, svuint16_t op) + /// EORV Hresult, Pg, Zop.H + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + + /// + /// uint32_t sveorv[_u32](svbool_t pg, svuint32_t op) + /// EORV Sresult, Pg, Zop.S + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + + /// + /// uint64_t sveorv[_u64](svbool_t pg, svuint64_t op) + /// EORV Dresult, Pg, Zop.D + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + + /// ZeroExtend16 : Zero-extend the low 16 bits /// diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 1262604f92895b..dee510b5c22eb8 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -4197,6 +4197,24 @@ internal Arm64() { } public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + public static ulong Count16BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } public static ulong Count32BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } public static ulong Count64BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } @@ -4290,6 +4308,24 @@ internal Arm64() { } public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendToInt64(System.Numerics.Vector mask, uint* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendToUInt64(System.Numerics.Vector mask, uint* address) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtend16(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector SignExtend16(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector SignExtend32(System.Numerics.Vector value) { throw null; } @@ -4348,6 +4384,24 @@ internal Arm64() { } public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtend16(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector ZeroExtend16(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector ZeroExtend32(System.Numerics.Vector value) { throw null; } diff --git a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs index 9b769782295623..0713ac24af2110 100644 --- a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs +++ b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs @@ -2921,6 +2921,24 @@ ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_ulong_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossWidening(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), @@ -3020,6 +3038,24 @@ ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend16_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, false)"}), ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend16_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, false)"}), ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend32_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 32, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 32, false)"}), @@ -3045,6 +3081,24 @@ ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs index f8c86732969119..faf6d504ece6bc 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs @@ -5118,10 +5118,16 @@ private static double Pairwise(Func pairOp, double[] op1 public static sbyte AddAcross(sbyte[] op1) => Reduce(Add, op1); + public static sbyte AndAcross(sbyte[] op1) => Reduce(And, op1); + public static sbyte MaxAcross(sbyte[] op1) => Reduce(Max, op1); public static sbyte MinAcross(sbyte[] op1) => Reduce(Min, op1); + public static sbyte OrAcross(sbyte[] op1) => Reduce(Or, op1); + + public static sbyte XorAcross(sbyte[] op1) => Reduce(Xor, op1); + private static sbyte Reduce(Func reduceOp, sbyte[] op1) { sbyte acc = op1[0]; @@ -5136,10 +5142,16 @@ private static sbyte Reduce(Func reduceOp, sbyte[] op1) public static byte AddAcross(byte[] op1) => Reduce(Add, op1); + public static byte AndAcross(byte[] op1) => Reduce(And, op1); + public static byte MaxAcross(byte[] op1) => Reduce(Max, op1); public static byte MinAcross(byte[] op1) => Reduce(Min, op1); + public static byte OrAcross(byte[] op1) => Reduce(Or, op1); + + public static byte XorAcross(byte[] op1) => Reduce(Xor, op1); + private static byte Reduce(Func reduceOp, byte[] op1) { byte acc = op1[0]; @@ -5154,10 +5166,16 @@ private static byte Reduce(Func reduceOp, byte[] op1) public static short AddAcross(short[] op1) => Reduce(Add, op1); + public static short AndAcross(short[] op1) => Reduce(And, op1); + public static short MaxAcross(short[] op1) => Reduce(Max, op1); public static short MinAcross(short[] op1) => Reduce(Min, op1); + public static short OrAcross(short[] op1) => Reduce(Or, op1); + + public static short XorAcross(short[] op1) => Reduce(Xor, op1); + private static short Reduce(Func reduceOp, short[] op1) { short acc = op1[0]; @@ -5172,10 +5190,16 @@ private static short Reduce(Func reduceOp, short[] op1) public static ushort AddAcross(ushort[] op1) => Reduce(Add, op1); + public static ushort AndAcross(ushort[] op1) => Reduce(And, op1); + public static ushort MaxAcross(ushort[] op1) => Reduce(Max, op1); public static ushort MinAcross(ushort[] op1) => Reduce(Min, op1); + public static ushort OrAcross(ushort[] op1) => Reduce(Or, op1); + + public static ushort XorAcross(ushort[] op1) => Reduce(Xor, op1); + private static ushort Reduce(Func reduceOp, ushort[] op1) { ushort acc = op1[0]; @@ -5190,10 +5214,16 @@ private static ushort Reduce(Func reduceOp, ushort[] op1 public static int AddAcross(int[] op1) => Reduce(Add, op1); + public static int AndAcross(int[] op1) => Reduce(And, op1); + public static int MaxAcross(int[] op1) => Reduce(Max, op1); public static int MinAcross(int[] op1) => Reduce(Min, op1); + public static int OrAcross(int[] op1) => Reduce(Or, op1); + + public static int XorAcross(int[] op1) => Reduce(Xor, op1); + private static int Reduce(Func reduceOp, int[] op1) { int acc = op1[0]; @@ -5208,10 +5238,16 @@ private static int Reduce(Func reduceOp, int[] op1) public static uint AddAcross(uint[] op1) => Reduce(Add, op1); + public static uint AndAcross(uint[] op1) => Reduce(And, op1); + public static uint MaxAcross(uint[] op1) => Reduce(Max, op1); public static uint MinAcross(uint[] op1) => Reduce(Min, op1); + public static uint OrAcross(uint[] op1) => Reduce(Or, op1); + + public static uint XorAcross(uint[] op1) => Reduce(Xor, op1); + private static uint Reduce(Func reduceOp, uint[] op1) { uint acc = op1[0]; @@ -5226,10 +5262,16 @@ private static uint Reduce(Func reduceOp, uint[] op1) public static long AddAcross(long[] op1) => Reduce(Add, op1); + public static long AndAcross(long[] op1) => Reduce(And, op1); + public static long MaxAcross(long[] op1) => Reduce(Max, op1); public static long MinAcross(long[] op1) => Reduce(Min, op1); + public static long OrAcross(long[] op1) => Reduce(Or, op1); + + public static long XorAcross(long[] op1) => Reduce(Xor, op1); + private static long Reduce(Func reduceOp, long[] op1) { long acc = op1[0]; @@ -5244,10 +5286,16 @@ private static long Reduce(Func reduceOp, long[] op1) public static ulong AddAcross(ulong[] op1) => Reduce(Add, op1); + public static ulong AndAcross(ulong[] op1) => Reduce(And, op1); + public static ulong MaxAcross(ulong[] op1) => Reduce(Max, op1); public static ulong MinAcross(ulong[] op1) => Reduce(Min, op1); + public static ulong OrAcross(ulong[] op1) => Reduce(Or, op1); + + public static ulong XorAcross(ulong[] op1) => Reduce(Xor, op1); + private static ulong Reduce(Func reduceOp, ulong[] op1) { ulong acc = op1[0]; From 43a341a8177a0223f5ff0edf35c4b6cdd6f8af8f Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 3 May 2024 06:00:15 -0700 Subject: [PATCH 234/248] Remove assert (#101824) --- src/coreclr/jit/lsra.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 2bbccaf2b6b1bd..685186550793b7 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -7427,7 +7427,6 @@ void LinearScan::insertCopyOrReload(BasicBlock* block, GenTree* tree, unsigned m // child needs to be copied or reloaded to that reg. if (parent->IsCopyOrReload()) { - noway_assert(parent->OperGet() == oper); noway_assert(tree->IsMultiRegNode()); GenTreeCopyOrReload* copyOrReload = parent->AsCopyOrReload(); noway_assert(copyOrReload->GetRegNumByIdx(multiRegIdx) == REG_NA); From 40878c881bded3b119865417da157ac8ab5267cb Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 3 May 2024 07:18:18 -0700 Subject: [PATCH 235/248] Don't enable use-after-return checking on Apple's Clang (#101781) --- eng/native/configurecompiler.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index 4675a8b07cb6b4..ea2ace16727509 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -211,8 +211,8 @@ if (CLR_CMAKE_ENABLE_SANITIZERS) # Disable the use-after-return check for ASAN on Clang. This is because we have a lot of code that # depends on the fact that our locals are not saved in a parallel stack, so we can't enable this today. # If we ever have a way to detect a parallel stack and track its bounds, we can re-enable this check. - add_compile_options($<$:-fsanitize-address-use-after-return=never>) - add_compile_options($<$:-fsanitize-address-use-after-return=never>) + add_compile_options($<$:-fsanitize-address-use-after-return=never>) + add_compile_options($<$:-fsanitize-address-use-after-return=never>) endif() endif() From c754a25f8c2ca9bb72fa5dda65e35ac2a7b63db0 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Fri, 3 May 2024 16:28:52 +0200 Subject: [PATCH 236/248] Expose DOTNET_JitNoInline in Release (#101798) --- src/coreclr/jit/importercalls.cpp | 2 -- src/coreclr/jit/jitconfigvalues.h | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 4dc64523217230..83f363e9953013 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -8575,13 +8575,11 @@ void Compiler::impCheckCanInline(GenTreeCall* call, CORINFO_METHOD_HANDLE ftn = pParam->fncHandle; InlineResult* const inlineResult = pParam->result; -#ifdef DEBUG if (JitConfig.JitNoInline()) { inlineResult->NoteFatal(InlineObservation::CALLEE_IS_JIT_NOINLINE); return; } -#endif JITDUMP("\nCheckCanInline: fetching method info for inline candidate %s -- context %p\n", compiler->eeGetMethodName(ftn), compiler->dspPtr(pParam->exactContextHnd)); diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index 81345191ce5f88..d2ea1deca5166a 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -138,7 +138,6 @@ CONFIG_INTEGER(JitNoForceFallback, W("JitNoForceFallback"), 0) // Set to non-zer // flags. CONFIG_INTEGER(JitNoForwardSub, W("JitNoForwardSub"), 0) // Disables forward sub CONFIG_INTEGER(JitNoHoist, W("JitNoHoist"), 0) -CONFIG_INTEGER(JitNoInline, W("JitNoInline"), 0) // Disables inlining of all methods CONFIG_INTEGER(JitNoMemoryBarriers, W("JitNoMemoryBarriers"), 0) // If 1, don't generate memory barriers CONFIG_INTEGER(JitNoStructPromotion, W("JitNoStructPromotion"), 0) // Disables struct promotion 1 - for all, 2 - for // params. @@ -358,6 +357,9 @@ RELEASE_CONFIG_INTEGER(EnableEHWriteThru, W("EnableEHWriteThru"), 1) // Enable the enregistration of locals that are defined or used in a multireg context. RELEASE_CONFIG_INTEGER(EnableMultiRegLocals, W("EnableMultiRegLocals"), 1) +// Disables inlining of all methods +RELEASE_CONFIG_INTEGER(JitNoInline, W("JitNoInline"), 0) + // Enable EVEX encoding for SIMD instructions when AVX-512VL is available. CONFIG_INTEGER(JitStressEvexEncoding, W("JitStressEvexEncoding"), 0) From 7ac5ef959579da0202e6ad618924dfc8fe129e89 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Fri, 3 May 2024 17:54:35 +0200 Subject: [PATCH 237/248] JIT: Bulk copy of byrefs (#101761) --- src/coreclr/inc/corinfo.h | 2 +- src/coreclr/inc/jiteeversionguid.h | 10 +- src/coreclr/inc/jithelpers.h | 3 +- src/coreclr/inc/readytorun.h | 4 +- src/coreclr/inc/readytorunhelpers.h | 1 + src/coreclr/jit/codegencommon.cpp | 2 +- src/coreclr/jit/lower.cpp | 111 ++++++++++++++++++ src/coreclr/jit/lower.h | 1 + src/coreclr/jit/lowerarmarch.cpp | 6 + src/coreclr/jit/lowerloongarch64.cpp | 6 + src/coreclr/jit/lowerriscv64.cpp | 6 + src/coreclr/jit/lowerxarch.cpp | 6 + src/coreclr/jit/utils.cpp | 2 +- .../nativeaot/Runtime/inc/ModuleHeaders.h | 2 +- .../Common/Internal/Runtime/ModuleHeaders.cs | 2 +- .../Internal/Runtime/ReadyToRunConstants.cs | 1 + .../Common/JitInterface/CorInfoHelpFunc.cs | 2 +- .../ILCompiler.Compiler/Compiler/JitHelper.cs | 3 + .../JitInterface/CorInfoImpl.ReadyToRun.cs | 3 + .../ReadyToRunSignature.cs | 4 + .../JitInterface/CorInfoImpl.RyuJit.cs | 3 + src/coreclr/vm/corelib.h | 1 + src/coreclr/vm/ecall.cpp | 4 + src/coreclr/vm/jithelpers.cpp | 17 +-- .../src/System/Buffer.cs | 3 + 25 files changed, 175 insertions(+), 30 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index ff82759f6aab64..2d526105164b6b 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -496,7 +496,7 @@ enum CorInfoHelpFunc CORINFO_HELP_ASSIGN_REF_ENSURE_NONHEAP, // Do the store, and ensure that the target was not in the heap. CORINFO_HELP_ASSIGN_BYREF, - CORINFO_HELP_ASSIGN_STRUCT, + CORINFO_HELP_BULK_WRITEBARRIER, /* Accessing fields */ diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 79b6397a9111e2..122906341d00b4 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 = { /* 32d71f8e-c1f5-41cb-88cc-4e8504cabf40 */ - 0x32d71f8e, - 0xc1f5, - 0x41cb, - {0x88, 0xcc, 0x4e, 0x85, 0x04, 0xca, 0xbf, 0x40} +constexpr GUID JITEEVersionIdentifier = { /* bd8c41d4-8531-49c1-a600-0ae9bfe05de1 */ + 0xbd8c41d4, + 0x8531, + 0x49c1, + {0xa6, 0x00, 0x0a, 0xe9, 0xbf, 0xe0, 0x5d, 0xe1} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/inc/jithelpers.h b/src/coreclr/inc/jithelpers.h index f1711a9acfd9b2..2ee49994538592 100644 --- a/src/coreclr/inc/jithelpers.h +++ b/src/coreclr/inc/jithelpers.h @@ -153,8 +153,7 @@ JITHELPER(CORINFO_HELP_ASSIGN_REF_ENSURE_NONHEAP, JIT_WriteBarrierEnsureNonHeapTarget,CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_ASSIGN_BYREF, JIT_ByRefWriteBarrier,CORINFO_HELP_SIG_NO_ALIGN_STUB) - - JITHELPER(CORINFO_HELP_ASSIGN_STRUCT, JIT_StructWriteBarrier,CORINFO_HELP_SIG_4_STACK) + DYNAMICJITHELPER(CORINFO_HELP_BULK_WRITEBARRIER, NULL, CORINFO_HELP_SIG_REG_ONLY) // Accessing fields JITHELPER(CORINFO_HELP_GETFIELD8, JIT_GetField8,CORINFO_HELP_SIG_REG_ONLY) diff --git a/src/coreclr/inc/readytorun.h b/src/coreclr/inc/readytorun.h index 88219146a123a4..1c3ce8237ef7fc 100644 --- a/src/coreclr/inc/readytorun.h +++ b/src/coreclr/inc/readytorun.h @@ -20,7 +20,7 @@ // If you update this, ensure you run `git grep MINIMUM_READYTORUN_MAJOR_VERSION` // and handle pending work. #define READYTORUN_MAJOR_VERSION 0x0009 -#define READYTORUN_MINOR_VERSION 0x0002 +#define READYTORUN_MINOR_VERSION 0x0003 #define MINIMUM_READYTORUN_MAJOR_VERSION 0x009 @@ -34,6 +34,7 @@ // R2R Version 9.0 adds support for the Vector512 type // R2R Version 9.1 adds new helpers to allocate objects on frozen segments // R2R Version 9.2 adds MemZero and NativeMemSet helpers +// R2R Version 9.3 adds BulkWriteBarrier helper struct READYTORUN_CORE_HEADER @@ -321,6 +322,7 @@ enum ReadyToRunHelper READYTORUN_HELPER_WriteBarrier = 0x30, READYTORUN_HELPER_CheckedWriteBarrier = 0x31, READYTORUN_HELPER_ByRefWriteBarrier = 0x32, + READYTORUN_HELPER_BulkWriteBarrier = 0x33, // Array helpers READYTORUN_HELPER_Stelem_Ref = 0x38, diff --git a/src/coreclr/inc/readytorunhelpers.h b/src/coreclr/inc/readytorunhelpers.h index bbb586e8eb4a30..a1fcef8fbaf835 100644 --- a/src/coreclr/inc/readytorunhelpers.h +++ b/src/coreclr/inc/readytorunhelpers.h @@ -24,6 +24,7 @@ HELPER(READYTORUN_HELPER_ThrowDivZero, CORINFO_HELP_THROWDIVZERO, HELPER(READYTORUN_HELPER_WriteBarrier, CORINFO_HELP_ASSIGN_REF, ) HELPER(READYTORUN_HELPER_CheckedWriteBarrier, CORINFO_HELP_CHECKED_ASSIGN_REF, ) HELPER(READYTORUN_HELPER_ByRefWriteBarrier, CORINFO_HELP_ASSIGN_BYREF, ) +HELPER(READYTORUN_HELPER_BulkWriteBarrier, CORINFO_HELP_BULK_WRITEBARRIER, ) HELPER(READYTORUN_HELPER_Stelem_Ref, CORINFO_HELP_ARRADDR_ST, ) HELPER(READYTORUN_HELPER_Ldelema_Ref, CORINFO_HELP_LDELEMA_REF, ) diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 6ec296a1391bb5..6dcbba13b48533 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -1772,7 +1772,7 @@ void CodeGen::genGenerateCode(void** codePtr, uint32_t* nativeSizeOfCode) if (genWriteBarrierUsed && JitConfig.EnableExtraSuperPmiQueries() && !compiler->opts.IsReadyToRun()) { void* ignored; - for (int i = CORINFO_HELP_ASSIGN_REF; i <= CORINFO_HELP_ASSIGN_STRUCT; i++) + for (int i = CORINFO_HELP_ASSIGN_REF; i <= CORINFO_HELP_BULK_WRITEBARRIER; i++) { compiler->compGetHelperFtn((CorInfoHelpFunc)i, &ignored); } diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index a35c921facfcf0..28538fc2b9053f 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -8212,6 +8212,117 @@ void Lowering::ContainCheckBitCast(GenTree* node) } } +//------------------------------------------------------------------------ +// TryLowerBlockStoreAsGcBulkCopyCall: Lower a block store node as a CORINFO_HELP_BULK_WRITEBARRIER call +// +// Arguments: +// blkNode - The block store node to lower +// +bool Lowering::TryLowerBlockStoreAsGcBulkCopyCall(GenTreeBlk* blk) +{ + if (comp->opts.OptimizationDisabled()) + { + return false; + } + + // Replace STORE_BLK (struct copy) with CORINFO_HELP_BULK_WRITEBARRIER which performs + // bulk copy for byrefs. + const unsigned bulkCopyThreshold = 4; + if (!blk->OperIs(GT_STORE_BLK) || blk->OperIsInitBlkOp() || blk->IsVolatile() || + (blk->GetLayout()->GetGCPtrCount() < bulkCopyThreshold)) + { + return false; + } + + GenTree* dest = blk->Addr(); + GenTree* data = blk->Data(); + + if (data->OperIs(GT_IND)) + { + if (data->AsIndir()->IsVolatile()) + { + return false; + } + + // Drop GT_IND nodes + BlockRange().Remove(data); + data = data->AsIndir()->Addr(); + } + else + { + assert(data->OperIs(GT_LCL_VAR, GT_LCL_FLD)); + + // Convert local to LCL_ADDR + unsigned lclOffset = data->AsLclVarCommon()->GetLclOffs(); + data->ChangeOper(GT_LCL_ADDR); + data->ChangeType(TYP_I_IMPL); + data->AsLclFld()->SetLclOffs(lclOffset); + data->ClearContained(); + } + + // Size is a constant + GenTreeIntCon* size = comp->gtNewIconNode((ssize_t)blk->GetLayout()->GetSize(), TYP_I_IMPL); + BlockRange().InsertBefore(data, size); + + // A hacky way to safely call fgMorphTree in Lower + GenTree* destPlaceholder = comp->gtNewZeroConNode(dest->TypeGet()); + GenTree* dataPlaceholder = comp->gtNewZeroConNode(genActualType(data)); + GenTree* sizePlaceholder = comp->gtNewZeroConNode(genActualType(size)); + + GenTreeCall* call = comp->gtNewHelperCallNode(CORINFO_HELP_BULK_WRITEBARRIER, TYP_VOID, destPlaceholder, + dataPlaceholder, sizePlaceholder); + comp->fgMorphArgs(call); + + LIR::Range range = LIR::SeqTree(comp, call); + GenTree* rangeStart = range.FirstNode(); + GenTree* rangeEnd = range.LastNode(); + + BlockRange().InsertBefore(blk, std::move(range)); + blk->gtBashToNOP(); + + LIR::Use destUse; + LIR::Use sizeUse; + BlockRange().TryGetUse(destPlaceholder, &destUse); + BlockRange().TryGetUse(sizePlaceholder, &sizeUse); + destUse.ReplaceWith(dest); + sizeUse.ReplaceWith(size); + destPlaceholder->SetUnusedValue(); + sizePlaceholder->SetUnusedValue(); + + LIR::Use dataUse; + BlockRange().TryGetUse(dataPlaceholder, &dataUse); + dataUse.ReplaceWith(data); + dataPlaceholder->SetUnusedValue(); + + LowerRange(rangeStart, rangeEnd); + + // Finally move all GT_PUTARG_* nodes + // Re-use the existing logic for CFG call args here + MoveCFGCallArgs(call); + + BlockRange().Remove(destPlaceholder); + BlockRange().Remove(sizePlaceholder); + BlockRange().Remove(dataPlaceholder); + + // Add implicit nullchecks for dest and data if needed: + // + auto wrapWithNullcheck = [&](GenTree* node) { + if (comp->fgAddrCouldBeNull(node)) + { + LIR::Use nodeUse; + BlockRange().TryGetUse(node, &nodeUse); + GenTree* nodeClone = comp->gtNewLclvNode(nodeUse.ReplaceWithLclVar(comp), genActualType(node)); + GenTree* nullcheck = comp->gtNewNullCheck(nodeClone, comp->compCurBB); + BlockRange().InsertAfter(nodeUse.Def(), nodeClone, nullcheck); + LowerNode(nullcheck); + } + }; + wrapWithNullcheck(dest); + wrapWithNullcheck(data); + + return true; +} + //------------------------------------------------------------------------ // LowerBlockStoreAsHelperCall: Lower a block store node as a memset/memcpy call // diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h index f13f9c2eeab106..dc32f7941f53dc 100644 --- a/src/coreclr/jit/lower.h +++ b/src/coreclr/jit/lower.h @@ -363,6 +363,7 @@ class Lowering final : public Phase void LowerBlockStore(GenTreeBlk* blkNode); void LowerBlockStoreCommon(GenTreeBlk* blkNode); void LowerBlockStoreAsHelperCall(GenTreeBlk* blkNode); + bool TryLowerBlockStoreAsGcBulkCopyCall(GenTreeBlk* blkNode); void LowerLclHeap(GenTree* node); void ContainBlockStoreAddress(GenTreeBlk* blkNode, unsigned size, GenTree* addr, GenTree* addrParent); void LowerPutArgStkOrSplit(GenTreePutArgStk* putArgNode); diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 6456b2b972ea9a..36b5e08f0afd67 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -737,6 +737,12 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) if (doCpObj) { + // Try to use bulk copy helper + if (TryLowerBlockStoreAsGcBulkCopyCall(blkNode)) + { + return; + } + assert((dstAddr->TypeGet() == TYP_BYREF) || (dstAddr->TypeGet() == TYP_I_IMPL)); blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindCpObjUnroll; } diff --git a/src/coreclr/jit/lowerloongarch64.cpp b/src/coreclr/jit/lowerloongarch64.cpp index 4e826be0b22574..d3552e478fdfef 100644 --- a/src/coreclr/jit/lowerloongarch64.cpp +++ b/src/coreclr/jit/lowerloongarch64.cpp @@ -370,6 +370,12 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) // CopyObj or CopyBlk if (doCpObj) { + // Try to use bulk copy helper + if (TryLowerBlockStoreAsGcBulkCopyCall(blkNode)) + { + return; + } + assert((dstAddr->TypeGet() == TYP_BYREF) || (dstAddr->TypeGet() == TYP_I_IMPL)); blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindCpObjUnroll; } diff --git a/src/coreclr/jit/lowerriscv64.cpp b/src/coreclr/jit/lowerriscv64.cpp index aa8342ee1af5a4..5b0bd99df484f3 100644 --- a/src/coreclr/jit/lowerriscv64.cpp +++ b/src/coreclr/jit/lowerriscv64.cpp @@ -319,6 +319,12 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) // CopyObj or CopyBlk if (doCpObj) { + // Try to use bulk copy helper + if (TryLowerBlockStoreAsGcBulkCopyCall(blkNode)) + { + return; + } + assert((dstAddr->TypeGet() == TYP_BYREF) || (dstAddr->TypeGet() == TYP_I_IMPL)); blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindCpObjUnroll; } diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 0e18c5685066fc..156992b89e9d46 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -457,6 +457,12 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) if (doCpObj) { + // Try to use bulk copy helper + if (TryLowerBlockStoreAsGcBulkCopyCall(blkNode)) + { + return; + } + assert((dstAddr->TypeGet() == TYP_BYREF) || (dstAddr->TypeGet() == TYP_I_IMPL)); // If we have a long enough sequence of slots that do not require write barriers then diff --git a/src/coreclr/jit/utils.cpp b/src/coreclr/jit/utils.cpp index e3b99463b466de..07ca1fb6dc09c9 100644 --- a/src/coreclr/jit/utils.cpp +++ b/src/coreclr/jit/utils.cpp @@ -1746,7 +1746,7 @@ void HelperCallProperties::init() case CORINFO_HELP_CHECKED_ASSIGN_REF: case CORINFO_HELP_ASSIGN_REF_ENSURE_NONHEAP: case CORINFO_HELP_ASSIGN_BYREF: - case CORINFO_HELP_ASSIGN_STRUCT: + case CORINFO_HELP_BULK_WRITEBARRIER: mutatesHeap = true; break; diff --git a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h index 6a3b24a3944870..d4360273d28ac8 100644 --- a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h +++ b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h @@ -12,7 +12,7 @@ struct ReadyToRunHeaderConstants static const uint32_t Signature = 0x00525452; // 'RTR' static const uint32_t CurrentMajorVersion = 9; - static const uint32_t CurrentMinorVersion = 2; + static const uint32_t CurrentMinorVersion = 3; }; struct ReadyToRunHeader diff --git a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs index 6fc5d9542e1609..8420c9a4803b28 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs @@ -16,7 +16,7 @@ internal struct ReadyToRunHeaderConstants public const uint Signature = 0x00525452; // 'RTR' public const ushort CurrentMajorVersion = 9; - public const ushort CurrentMinorVersion = 2; + public const ushort CurrentMinorVersion = 3; } #if READYTORUN #pragma warning disable 0169 diff --git a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs index 0ca8b74c85229b..af86b107e5b31e 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs @@ -233,6 +233,7 @@ public enum ReadyToRunHelper WriteBarrier = 0x30, CheckedWriteBarrier = 0x31, ByRefWriteBarrier = 0x32, + BulkWriteBarrier = 0x33, // Array helpers Stelem_Ref = 0x38, diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs index 5346806c1aff60..14bf90a9aaaed4 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs @@ -138,7 +138,7 @@ which is the right helper to use to allocate an object of a given type. */ CORINFO_HELP_ASSIGN_REF_ENSURE_NONHEAP, // Do the store, and ensure that the target was not in the heap. CORINFO_HELP_ASSIGN_BYREF, - CORINFO_HELP_ASSIGN_STRUCT, + CORINFO_HELP_BULK_WRITEBARRIER, /* Accessing fields */ diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs index 8faf4cf3fcfe7c..67cfd6cbe4f7a8 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs @@ -67,6 +67,9 @@ public static void GetEntryPoint(TypeSystemContext context, ReadyToRunHelper id, case ReadyToRunHelper.CheckedWriteBarrier: mangledName = context.Target.Architecture == TargetArchitecture.ARM64 ? "RhpCheckedAssignRefArm64" : "RhpCheckedAssignRef"; break; + case ReadyToRunHelper.BulkWriteBarrier: + mangledName = "RhBuffer_BulkMoveWithWriteBarrier"; + break; case ReadyToRunHelper.ByRefWriteBarrier: mangledName = context.Target.Architecture == TargetArchitecture.ARM64 ? "RhpByRefAssignRefArm64" : "RhpByRefAssignRef"; break; 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 e1b1b359c0878a..7f702fd6b764aa 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -1000,6 +1000,9 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) case CorInfoHelpFunc.CORINFO_HELP_ASSIGN_BYREF: id = ReadyToRunHelper.ByRefWriteBarrier; break; + case CorInfoHelpFunc.CORINFO_HELP_BULK_WRITEBARRIER: + id = ReadyToRunHelper.BulkWriteBarrier; + break; case CorInfoHelpFunc.CORINFO_HELP_ARRADDR_ST: id = ReadyToRunHelper.Stelem_Ref; diff --git a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs index 0eae2f10cb8f00..329b95f5d3c4e2 100644 --- a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs +++ b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs @@ -1672,6 +1672,10 @@ private void ParseHelper(StringBuilder builder) builder.Append("BYREF_WRITE_BARRIER"); break; + case ReadyToRunHelper.BulkWriteBarrier: + builder.Append("BULK_WRITE_BARRIER"); + break; + // Array helpers case ReadyToRunHelper.Stelem_Ref: builder.Append("STELEM_REF"); diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 2dfa5d9d88f67d..d344dd431fb557 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -497,6 +497,9 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) case CorInfoHelpFunc.CORINFO_HELP_CHECKED_ASSIGN_REF: id = ReadyToRunHelper.CheckedWriteBarrier; break; + case CorInfoHelpFunc.CORINFO_HELP_BULK_WRITEBARRIER: + id = ReadyToRunHelper.BulkWriteBarrier; + break; case CorInfoHelpFunc.CORINFO_HELP_ASSIGN_BYREF: id = ReadyToRunHelper.ByRefWriteBarrier; break; diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index d5af8bdb3cb64e..2f9049aea8d710 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -891,6 +891,7 @@ DEFINE_METHOD(DEBUGGER, BREAK, Break, DEFINE_CLASS(BUFFER, System, Buffer) DEFINE_METHOD(BUFFER, MEMCPY_PTRBYTE_ARRBYTE, Memcpy, SM_PtrByte_Int_ArrByte_Int_Int_RetVoid) DEFINE_METHOD(BUFFER, MEMCPY, Memcpy, SM_PtrByte_PtrByte_Int_RetVoid) +DEFINE_METHOD(BUFFER, MEMCOPYGC, BulkMoveWithWriteBarrier, SM_RefByte_RefByte_UIntPtr_RetVoid) DEFINE_CLASS(STUBHELPERS, StubHelpers, StubHelpers) DEFINE_METHOD(STUBHELPERS, GET_DELEGATE_TARGET, GetDelegateTarget, SM_Delegate_RetIntPtr) diff --git a/src/coreclr/vm/ecall.cpp b/src/coreclr/vm/ecall.cpp index 35a5d36eae4d76..56a28a7a57ddb8 100644 --- a/src/coreclr/vm/ecall.cpp +++ b/src/coreclr/vm/ecall.cpp @@ -157,6 +157,10 @@ void ECall::PopulateManagedHelpers() pDest = pMD->GetMultiCallableAddrOfCode(); SetJitHelperFunction(CORINFO_HELP_MEMCPY, pDest); + pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__BUFFER__MEMCOPYGC)); + pDest = pMD->GetMultiCallableAddrOfCode(); + SetJitHelperFunction(CORINFO_HELP_BULK_WRITEBARRIER, pDest); + pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__MATH__ROUND)); pDest = pMD->GetMultiCallableAddrOfCode(); SetJitHelperFunction(CORINFO_HELP_DBLROUND, pDest); diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 98d6780258a6c6..05d2ad18b5bd94 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -55,8 +55,8 @@ #ifndef FEATURE_EH_FUNCLETS #include "excep.h" #endif - #include "exinfo.h" +#include "arraynative.inl" using std::isfinite; using std::isnan; @@ -4779,21 +4779,6 @@ HCIMPLEND // //======================================================================== -/*************************************************************/ -HCIMPL3(VOID, JIT_StructWriteBarrier, void *dest, void* src, CORINFO_CLASS_HANDLE typeHnd_) -{ - FCALL_CONTRACT; - - TypeHandle typeHnd(typeHnd_); - MethodTable *pMT = typeHnd.AsMethodTable(); - - HELPER_METHOD_FRAME_BEGIN_NOPOLL(); // Set up a frame - CopyValueClass(dest, src, pMT); - HELPER_METHOD_FRAME_END_POLL(); - -} -HCIMPLEND - /*************************************************************/ // Slow helper to tailcall from the fast one NOINLINE HCIMPL0(void, JIT_PollGC_Framed) diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffer.cs b/src/libraries/System.Private.CoreLib/src/System/Buffer.cs index 24f8794d852afd..d07df58bb23769 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffer.cs @@ -177,6 +177,9 @@ ref Unsafe.As(ref source), private const uint BulkMoveWithWriteBarrierChunk = 0x4000; #endif +#if NATIVEAOT + [System.Runtime.RuntimeExport("RhBuffer_BulkMoveWithWriteBarrier")] +#endif internal static void BulkMoveWithWriteBarrier(ref byte destination, ref byte source, nuint byteCount) { if (byteCount <= BulkMoveWithWriteBarrierChunk) From 6f18b5ef46a8fbc6675b07d4b256c35b36fc4e3c Mon Sep 17 00:00:00 2001 From: Parker Bibus Date: Fri, 3 May 2024 11:38:50 -0700 Subject: [PATCH 238/248] Revert using specific dotnet-version changes. (#101860) --- eng/pipelines/coreclr/templates/run-performance-job.yml | 2 +- eng/pipelines/coreclr/templates/run-scenarios-job.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/pipelines/coreclr/templates/run-performance-job.yml b/eng/pipelines/coreclr/templates/run-performance-job.yml index e1bc7f283555bd..2b61558e2fc97f 100644 --- a/eng/pipelines/coreclr/templates/run-performance-job.yml +++ b/eng/pipelines/coreclr/templates/run-performance-job.yml @@ -179,7 +179,7 @@ jobs: displayName: Performance Setup (Unix) condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} - - script: $(Python) $(PerformanceDirectory)/scripts/ci_setup.py $(SetupArguments) ${{ parameters.additionalSetupParameters }} --dotnet-versions 9.0.100-preview.4.24215.2 # Temporarily add a specific dotnet-version as Windows runs are currently failing to install the dotnet version + - script: $(Python) $(PerformanceDirectory)/scripts/ci_setup.py $(SetupArguments) ${{ parameters.additionalSetupParameters }} displayName: Run ci setup script # Run perf testing in helix - template: /eng/pipelines/coreclr/templates/perf-send-to-helix.yml diff --git a/eng/pipelines/coreclr/templates/run-scenarios-job.yml b/eng/pipelines/coreclr/templates/run-scenarios-job.yml index 8567c76fe28aa4..78db1ae8cbd091 100644 --- a/eng/pipelines/coreclr/templates/run-scenarios-job.yml +++ b/eng/pipelines/coreclr/templates/run-scenarios-job.yml @@ -135,7 +135,7 @@ jobs: condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} # run ci-setup - - script: $(Python) $(PerformanceDirectory)\scripts\ci_setup.py $(SetupArguments) $(ExtraSetupArguments) --dotnet-versions 9.0.100-preview.4.24215.2 --output-file $(WorkItemDirectory)\machine-setup.cmd # Temporarily add a specific dotnet-version as Windows runs are currently failing to install the dotnet version + - script: $(Python) $(PerformanceDirectory)\scripts\ci_setup.py $(SetupArguments) $(ExtraSetupArguments) --output-file $(WorkItemDirectory)\machine-setup.cmd displayName: Run ci setup script (Windows) condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) - script: $(Python) $(PerformanceDirectory)/scripts/ci_setup.py $(SetupArguments) $(ExtraSetupArguments) --output-file $(WorkItemDirectory)/machine-setup.sh From 5b11bb2692506bc85daf76811b9133b30ad72114 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 3 May 2024 14:04:57 -0500 Subject: [PATCH 239/248] Update dependencies from https://github.com/dotnet/arcade build 20240503.1 (#101842) Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XliffTasks , Microsoft.DotNet.XUnitAssert , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 9.0.0-beta.24229.1 -> To Version 9.0.0-beta.24253.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 84 +++++++++---------- eng/Versions.props | 32 +++---- eng/common/native/init-compiler.sh | 2 +- .../steps/publish-pipeline-artifacts.yml | 2 +- .../steps/publish-pipeline-artifacts.yml | 2 +- global.json | 6 +- 6 files changed, 64 insertions(+), 64 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 55491731acd59b..1f961bfe2544fc 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -92,87 +92,87 @@ - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 https://github.com/dotnet/runtime-assets @@ -332,9 +332,9 @@ https://github.com/dotnet/xharness ff14b0c0b6d72bf4447d57758a40dbf9494f1ac0 - + https://github.com/dotnet/arcade - be933308b9024d798a9a22c0b8f3c8e3616ffbd8 + 020255bcf7d0b8beed7de05338d97396982ae527 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index a5758b9356e247..3f0cf7c4d63ade 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -83,22 +83,22 @@ 9.0.100-preview.5.24227.1 - 9.0.0-beta.24229.1 - 9.0.0-beta.24229.1 - 9.0.0-beta.24229.1 - 9.0.0-beta.24229.1 - 2.6.7-beta.24229.1 - 9.0.0-beta.24229.1 - 2.6.7-beta.24229.1 - 9.0.0-beta.24229.1 - 9.0.0-beta.24229.1 - 9.0.0-beta.24229.1 - 9.0.0-beta.24229.1 - 9.0.0-beta.24229.1 - 9.0.0-beta.24229.1 - 9.0.0-beta.24229.1 - 9.0.0-beta.24229.1 - 9.0.0-beta.24229.1 + 9.0.0-beta.24253.1 + 9.0.0-beta.24253.1 + 9.0.0-beta.24253.1 + 9.0.0-beta.24253.1 + 2.6.7-beta.24253.1 + 9.0.0-beta.24253.1 + 2.6.7-beta.24253.1 + 9.0.0-beta.24253.1 + 9.0.0-beta.24253.1 + 9.0.0-beta.24253.1 + 9.0.0-beta.24253.1 + 9.0.0-beta.24253.1 + 9.0.0-beta.24253.1 + 9.0.0-beta.24253.1 + 9.0.0-beta.24253.1 + 9.0.0-beta.24253.1 1.4.0 diff --git a/eng/common/native/init-compiler.sh b/eng/common/native/init-compiler.sh index afdeb7a4d54aee..ccd3a17268e243 100644 --- a/eng/common/native/init-compiler.sh +++ b/eng/common/native/init-compiler.sh @@ -64,7 +64,7 @@ if [ -z "$CLR_CC" ]; then if [ -z "$majorVersion" ]; then # note: gcc (all versions) and clang versions higher than 6 do not have minor version in file name, if it is zero. if [ "$compiler" = "clang" ]; then versions="18 17 16 15 14 13 12 11 10 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5" - elif [ "$compiler" = "gcc" ]; then versions="13 12 11 10 9 8 7 6 5 4.9"; fi + elif [ "$compiler" = "gcc" ]; then versions="14 13 12 11 10 9 8 7 6 5 4.9"; fi for version in $versions; do _major="${version%%.*}" diff --git a/eng/common/templates-official/steps/publish-pipeline-artifacts.yml b/eng/common/templates-official/steps/publish-pipeline-artifacts.yml index 15d74a9d91616d..d71eb0c7439862 100644 --- a/eng/common/templates-official/steps/publish-pipeline-artifacts.yml +++ b/eng/common/templates-official/steps/publish-pipeline-artifacts.yml @@ -23,4 +23,4 @@ steps: ${{ if parameters.args.artifactName }}: artifactName: ${{ parameters.args.artifactName }} ${{ if parameters.args.properties }}: - properties: ${{ properties.args.properties }} \ No newline at end of file + properties: ${{ parameters.args.properties }} \ No newline at end of file diff --git a/eng/common/templates/steps/publish-pipeline-artifacts.yml b/eng/common/templates/steps/publish-pipeline-artifacts.yml index 815c86038e3ab3..5dd698b212fc6b 100644 --- a/eng/common/templates/steps/publish-pipeline-artifacts.yml +++ b/eng/common/templates/steps/publish-pipeline-artifacts.yml @@ -31,4 +31,4 @@ steps: ${{ if parameters.args.parallelCount }}: parallelCount: ${{ parameters.args.parallelCount }} ${{ if parameters.args.properties }}: - properties: ${{ properties.args.properties }} \ No newline at end of file + properties: ${{ parameters.args.properties }} \ No newline at end of file diff --git a/global.json b/global.json index 55e7657f79c437..a62f147f01c51e 100644 --- a/global.json +++ b/global.json @@ -8,9 +8,9 @@ "dotnet": "9.0.100-preview.3.24204.13" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24229.1", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.24229.1", - "Microsoft.DotNet.SharedFramework.Sdk": "9.0.0-beta.24229.1", + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24253.1", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.24253.1", + "Microsoft.DotNet.SharedFramework.Sdk": "9.0.0-beta.24253.1", "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.Build.Traversal": "3.4.0", "Microsoft.NET.Sdk.IL": "9.0.0-preview.4.24229.1" From e1f98a13be27efbe0ee3b69aa4673e7e98c5c003 Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Fri, 3 May 2024 17:28:03 -0400 Subject: [PATCH 240/248] Generic types are invalid target types (#101850) --- src/mono/mono/metadata/marshal-lightweight.c | 24 ++++++++++++------- .../UnsafeAccessorsTests.Generics.cs | 1 - 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index 245b5dbe572507..4094d8fbcb1e83 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -2355,6 +2355,8 @@ unsafe_accessor_target_type_forbidden (MonoType *target_type) case MONO_TYPE_VOID: case MONO_TYPE_PTR: case MONO_TYPE_FNPTR: + case MONO_TYPE_VAR: + case MONO_TYPE_MVAR: return TRUE; default: return FALSE; @@ -2422,16 +2424,17 @@ emit_unsafe_accessor_ctor_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_m } MonoType *target_type = sig->ret; // for constructors the return type is the target type - if (target_type == NULL || m_type_is_byref (target_type) || unsafe_accessor_target_type_forbidden (target_type)) { - mono_mb_emit_exception_full (mb, "System", "BadImageFormatException", "Invalid usage of UnsafeAccessorAttribute."); - return; - } - MonoClass *target_class = mono_class_from_mono_type_internal (target_type); ERROR_DECL(find_method_error); if (accessor_method->is_inflated) { sig = update_signature(accessor_method); + target_type = sig->ret; + } + + if (target_type == NULL || m_type_is_byref (target_type) || unsafe_accessor_target_type_forbidden (target_type)) { + mono_mb_emit_exception_full (mb, "System", "BadImageFormatException", "Invalid usage of UnsafeAccessorAttribute."); + return; } MonoMethodSignature *member_sig = ctor_sig_from_accessor_sig (mb, sig, ctx); @@ -2467,10 +2470,7 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor // We explicitly allow calling a constructor as if it was an instance method, but we need some hacks in a couple of places gboolean ctor_as_method = !strcmp (member_name, ".ctor"); - if (sig->param_count < 1 || sig->params[0] == NULL || unsafe_accessor_target_type_forbidden (sig->params[0])) { - mono_mb_emit_exception_full (mb, "System", "BadImageFormatException", "Invalid usage of UnsafeAccessorAttribute."); - return; - } + MonoType *target_type = sig->params[0]; gboolean hasthis = kind == MONO_UNSAFE_ACCESSOR_METHOD; @@ -2484,6 +2484,12 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor ERROR_DECL(find_method_error); if (accessor_method->is_inflated) { sig = update_signature(accessor_method); + target_type = sig->params[0]; + } + + if (sig->param_count < 1 || target_type == NULL || unsafe_accessor_target_type_forbidden (target_type)) { + mono_mb_emit_exception_full (mb, "System", "BadImageFormatException", "Invalid usage of UnsafeAccessorAttribute."); + return; } MonoMethodSignature *member_sig = method_sig_from_accessor_sig (mb, hasthis, sig, ctx); diff --git a/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs b/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs index fd867ef222b693..c64306a27bdcb0 100644 --- a/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs +++ b/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs @@ -437,7 +437,6 @@ class Invalid } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_InvalidUseUnsafeAccessor() { Console.WriteLine($"Running {nameof(Verify_Generic_InvalidUseUnsafeAccessor)}"); From f82fb709a8721c765b84e18688dc3346f5432490 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Fri, 3 May 2024 18:12:36 -0700 Subject: [PATCH 241/248] JIT: profile checking through inlining (#101834) Advance profile consistency check through inlining. Turns out there are five reasons why inlining may make profile data inconsistent. Account for these and add metrics. Also add separate metrics for consistency before and after inlining, since pre-inline phases are run on inlinees and so don't give us good insight into overall consistency rates. And add some metrics for inlining itself. Contributes to #93020. Co-authored-by: Aman Khalid --- src/coreclr/jit/compiler.cpp | 10 +- src/coreclr/jit/compiler.h | 3 +- src/coreclr/jit/fgbasic.cpp | 38 ++--- src/coreclr/jit/fginline.cpp | 150 +++++++++++++++++++- src/coreclr/jit/fgprofile.cpp | 41 ++++-- src/coreclr/jit/importer.cpp | 28 ++-- src/coreclr/jit/indirectcalltransformer.cpp | 10 +- src/coreclr/jit/inline.h | 6 + src/coreclr/jit/jitmetadatalist.h | 10 ++ 9 files changed, 252 insertions(+), 44 deletions(-) diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 8e82707adbbbfd..0c812ffd935dbb 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -4697,11 +4697,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl return; } - // Drop back to just checking profile likelihoods. - // - activePhaseChecks &= ~PhaseChecks::CHECK_PROFILE; - activePhaseChecks |= PhaseChecks::CHECK_LIKELIHOODS; - // At this point in the phase list, all the inlinee phases have // been run, and inlinee compiles have exited, so we should only // get this far if we are jitting the root method. @@ -4718,6 +4713,11 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // Record "start" values for post-inlining cycles and elapsed time. RecordStateAtEndOfInlining(); + // Drop back to just checking profile likelihoods. + // + activePhaseChecks &= ~PhaseChecks::CHECK_PROFILE; + activePhaseChecks |= PhaseChecks::CHECK_LIKELIHOODS; + // Transform each GT_ALLOCOBJ node into either an allocation helper call or // local variable allocation on the stack. ObjectAllocator objectAllocator(this); // PHASE_ALLOCATE_OBJECTS diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 050f2e001ea294..1c6950a55296cc 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -5284,6 +5284,7 @@ class Compiler // The number of separate return points in the method. unsigned fgReturnCount; + unsigned fgThrowCount; PhaseStatus fgAddInternal(); @@ -6228,7 +6229,7 @@ class Compiler void fgLinkBasicBlocks(); - unsigned fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, FixedBitVect* jumpTarget); + void fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, FixedBitVect* jumpTarget); void fgCheckBasicBlockControlFlow(); diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index af02d257d5dc29..538c49e530ecb1 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -50,6 +50,7 @@ void Compiler::fgInit() fgDomBBcount = 0; fgBBVarSetsInited = false; fgReturnCount = 0; + fgThrowCount = 0; m_dfsTree = nullptr; m_loops = nullptr; @@ -233,8 +234,9 @@ bool Compiler::fgEnsureFirstBBisScratch() { // If the result is clearly nonsensical, just inherit // - JITDUMP("\fgEnsureFirstBBisScratch: Profile data could not be locally repaired. Data %s inconsisent.\n", - fgPgoConsistent ? "is now" : "was already"); + JITDUMP( + "\fgEnsureFirstBBisScratch: Profile data could not be locally repaired. Data %s inconsistent.\n", + fgPgoConsistent ? "is now" : "was already"); if (fgPgoConsistent) { @@ -3099,19 +3101,18 @@ void Compiler::fgLinkBasicBlocks() // codeSize -- length of the IL stream // jumpTarget -- [in] bit vector of jump targets found by fgFindJumpTargets // -// Returns: -// number of return blocks (BBJ_RETURN) in the method (may be zero) -// // Notes: -// Invoked for prejited and jitted methods, and for all inlinees - -unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, FixedBitVect* jumpTarget) +// Invoked for prejitted and jitted methods, and for all inlinees. +// Sets fgReturnCount and fgThrowCount +// +void Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, FixedBitVect* jumpTarget) { - unsigned retBlocks = 0; - const BYTE* codeBegp = codeAddr; - const BYTE* codeEndp = codeAddr + codeSize; - bool tailCall = false; - unsigned curBBoffs = 0; + unsigned retBlocks = 0; + unsigned throwBlocks = 0; + const BYTE* codeBegp = codeAddr; + const BYTE* codeEndp = codeAddr + codeSize; + bool tailCall = false; + unsigned curBBoffs = 0; BasicBlock* curBBdesc; // Keep track of where we are in the scope lists, as we will also @@ -3312,7 +3313,8 @@ unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, F // can be dispatched as tail calls from the caller. compInlineResult->NoteFatal(InlineObservation::CALLEE_EXPLICIT_TAIL_PREFIX); retBlocks++; - return retBlocks; + fgReturnCount = retBlocks; + return; } FALLTHROUGH; @@ -3415,6 +3417,7 @@ unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, F case CEE_THROW: case CEE_RETHROW: + throwBlocks++; jmpKind = BBJ_THROW; break; @@ -3597,7 +3600,8 @@ unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, F fgLinkBasicBlocks(); - return retBlocks; + fgReturnCount = retBlocks; + fgThrowCount = throwBlocks; } /***************************************************************************** @@ -3709,7 +3713,7 @@ void Compiler::fgFindBasicBlocks() /* Now create the basic blocks */ - fgReturnCount = fgMakeBasicBlocks(info.compCode, info.compILCodeSize, jumpTarget); + fgMakeBasicBlocks(info.compCode, info.compILCodeSize, jumpTarget); if (compIsForInlining()) { @@ -4269,7 +4273,7 @@ void Compiler::fgFixEntryFlowForOSR() // if ((fgEntryBB->bbPreds != nullptr) && (fgEntryBB != fgOSREntryBB)) { - JITDUMP("OSR: profile data could not be locally repaired. Data %s inconsisent.\n", + JITDUMP("OSR: profile data could not be locally repaired. Data %s inconsistent.\n", fgPgoConsistent ? "is now" : "was already"); fgPgoConsistent = false; } diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp index 8fcea689c6c993..7a6246a988fda3 100644 --- a/src/coreclr/jit/fginline.cpp +++ b/src/coreclr/jit/fginline.cpp @@ -624,24 +624,86 @@ class SubstitutePlaceholdersAndDevirtualizeWalker : public GenTreeVisitordspTreeID(tree), block->bbNum); + m_compiler->Metrics.InlinerBranchFold++; // We have a constant operand, and should have the all clear to optimize. // Update side effects on the tree, assert there aren't any, and bash to nop. m_compiler->gtUpdateNodeSideEffects(tree); assert((tree->gtFlags & GTF_SIDE_EFFECT) == 0); tree->gtBashToNOP(); - m_madeChanges = true; + m_madeChanges = true; + FlowEdge* removedEdge = nullptr; if (condTree->IsIntegralConst(0)) { - m_compiler->fgRemoveRefPred(block->GetTrueEdge()); + removedEdge = block->GetTrueEdge(); + m_compiler->fgRemoveRefPred(removedEdge); block->SetKindAndTargetEdge(BBJ_ALWAYS, block->GetFalseEdge()); } else { - m_compiler->fgRemoveRefPred(block->GetFalseEdge()); + removedEdge = block->GetFalseEdge(); + m_compiler->fgRemoveRefPred(removedEdge); block->SetKindAndTargetEdge(BBJ_ALWAYS, block->GetTrueEdge()); } + + // Update profile; make it consistent if possible + // + if (block->hasProfileWeight()) + { + bool repairWasComplete = true; + weight_t const weight = removedEdge->getLikelyWeight(); + + if (weight > 0) + { + // Target block weight will increase. + // + BasicBlock* const target = block->GetTarget(); + assert(target->hasProfileWeight()); + target->setBBProfileWeight(target->bbWeight + weight); + + // Alternate weight will decrease + // + BasicBlock* const alternate = removedEdge->getDestinationBlock(); + assert(alternate->hasProfileWeight()); + weight_t const alternateNewWeight = alternate->bbWeight - weight; + + // If profile weights are consistent, expect at worst a slight underflow. + // + if (m_compiler->fgPgoConsistent && (alternateNewWeight < 0)) + { + assert(m_compiler->fgProfileWeightsEqual(alternateNewWeight, 0)); + } + alternate->setBBProfileWeight(max(0.0, alternateNewWeight)); + + // This will affect profile transitively, so in general + // the profile will become inconsistent. + // + repairWasComplete = false; + + // But we can check for the special case where the + // block's postdominator is target's target (simple + // if/then/else/join). + // + if (target->KindIs(BBJ_ALWAYS)) + { + repairWasComplete = + alternate->KindIs(BBJ_ALWAYS) && alternate->TargetIs(target->GetTarget()); + } + } + + if (!repairWasComplete) + { + JITDUMP("Profile data could not be locally repaired. Data %s inconsistent.\n", + m_compiler->fgPgoConsistent ? "is now" : "was already"); + + if (m_compiler->fgPgoConsistent) + { + m_compiler->Metrics.ProfileInconsistentInlinerBranchFold++; + m_compiler->fgPgoConsistent = false; + } + } + } } } else @@ -692,6 +754,11 @@ PhaseStatus Compiler::fgInline() JitConfig.JitPrintInlinedMethods().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args); #endif // DEBUG + if (fgPgoConsistent) + { + Metrics.ProfileConsistentBeforeInline++; + } + noway_assert(fgFirstBB != nullptr); BasicBlock* block = fgFirstBB; @@ -822,6 +889,14 @@ PhaseStatus Compiler::fgInline() fgRenumberBlocks(); } + if (fgPgoConsistent) + { + Metrics.ProfileConsistentAfterInline++; + } + + Metrics.InlineCount = m_inlineStrategy->GetInlineCount(); + Metrics.InlineAttempt = m_inlineStrategy->GetImportCount(); + return madeChanges ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING; } @@ -1611,6 +1686,75 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) } #endif + // Update profile consistency + // + // If inlinee is inconsistent, root method will be inconsistent too. + // + if (!InlineeCompiler->fgPgoConsistent) + { + if (fgPgoConsistent) + { + JITDUMP("INLINER: profile data in root now inconsistent -- inlinee had inconsistency\n"); + Metrics.ProfileInconsistentInlinee++; + fgPgoConsistent = false; + } + } + + // If we inline a no-return call at a site with profile weight, + // we will introduce inconsistency. + // + if (InlineeCompiler->fgReturnCount == 0) + { + JITDUMP("INLINER: no-return inlinee\n"); + + if (iciBlock->bbWeight > 0) + { + if (fgPgoConsistent) + { + JITDUMP("INLINER: profile data in root now inconsistent -- no-return inlinee at call site in " FMT_BB + " with weight " FMT_WT "\n", + iciBlock->bbNum, iciBlock->bbWeight); + Metrics.ProfileInconsistentNoReturnInlinee++; + fgPgoConsistent = false; + } + } + else + { + // Inlinee scaling should assure this is so. + // + assert(InlineeCompiler->fgFirstBB->bbWeight == 0); + } + } + + // If the call site is not in a try and the callee has a throw, + // we may introduce inconsistency. + // + // Technically we should check if the callee has a throw not in a try, but since + // we can't inline methods with EH yet we don't see those. + // + if (InlineeCompiler->fgThrowCount > 0) + { + JITDUMP("INLINER: may-throw inlinee\n"); + + if (iciBlock->bbWeight > 0) + { + if (fgPgoConsistent) + { + JITDUMP("INLINER: profile data in root now inconsistent -- may-throw inlinee at call site in " FMT_BB + " with weight " FMT_WT "\n", + iciBlock->bbNum, iciBlock->bbWeight); + Metrics.ProfileInconsistentMayThrowInlinee++; + fgPgoConsistent = false; + } + } + else + { + // Inlinee scaling should assure this is so. + // + assert(InlineeCompiler->fgFirstBB->bbWeight == 0); + } + } + // If an inlinee needs GS cookie we need to make sure that the cookie will not be allocated at zero stack offset. // Note that if the root method needs GS cookie then this has already been taken care of. if (!getNeedsGSSecurityCookie() && InlineeCompiler->getNeedsGSSecurityCookie()) diff --git a/src/coreclr/jit/fgprofile.cpp b/src/coreclr/jit/fgprofile.cpp index 6d7ef484fe9a87..1afd6bcda76316 100644 --- a/src/coreclr/jit/fgprofile.cpp +++ b/src/coreclr/jit/fgprofile.cpp @@ -141,22 +141,39 @@ void Compiler::fgApplyProfileScale() JITDUMP(" ... no callee profile data, will use non-pgo weight to scale\n"); } - // Ostensibly this should be fgCalledCount for the callee, but that's not available - // as it requires some analysis. + // Determine the weight of the first block preds, if any. + // (only happens if the first block is a loop head). // - // For most callees it will be the same as the entry block count. - // - // Note when/if we early do normalization this may need to change. + weight_t firstBlockPredWeight = 0; + for (FlowEdge* const firstBlockPred : fgFirstBB->PredEdges()) + { + firstBlockPredWeight += firstBlockPred->getLikelyWeight(); + } + + // Determine the "input" weight for the callee // weight_t calleeWeight = fgFirstBB->bbWeight; - // Callee entry weight is nonzero? + // Callee entry weight is zero or negative (taking backedges into account)? // If so, just choose the smallest plausible weight. // - if (calleeWeight == BB_ZERO_WEIGHT) + if (calleeWeight <= firstBlockPredWeight) { calleeWeight = fgHaveProfileWeights() ? 1.0 : BB_UNITY_WEIGHT; - JITDUMP(" ... callee entry has weight zero, will use weight of " FMT_WT " to scale\n", calleeWeight); + JITDUMP(" ... callee entry has zero or negative weight, will use weight of " FMT_WT " to scale\n", + calleeWeight); + JITDUMP("Profile data could not be scaled consistently. Data %s inconsistent.\n", + fgPgoConsistent ? "is now" : "was already"); + + if (fgPgoConsistent) + { + Metrics.ProfileInconsistentInlineeScale++; + fgPgoConsistent = false; + } + } + else + { + calleeWeight -= firstBlockPredWeight; } // Call site has profile weight? @@ -2829,6 +2846,14 @@ PhaseStatus Compiler::fgInstrumentMethod() // PhaseStatus Compiler::fgIncorporateProfileData() { + // For now we only rely on profile data when optimizing. + // + if (!opts.OptimizationEnabled()) + { + JITDUMP("not optimizing, so not incorporating any profile data\n"); + return PhaseStatus::MODIFIED_NOTHING; + } + // Are we doing profile stress? // if (fgStressBBProf() > 0) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 4998dbd6293fa9..97aa8af7f2d5f8 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -5136,10 +5136,14 @@ void Compiler::impResetLeaveBlock(BasicBlock* block, unsigned jmpAddr) // We are unlikely to be able to repair the profile. // For now we don't even try. // - JITDUMP("\nimpResetLeaveBlock: Profile data could not be locally repaired. Data %s inconsisent.\n", + JITDUMP("\nimpResetLeaveBlock: Profile data could not be locally repaired. Data %s inconsistent.\n", fgPgoConsistent ? "is now" : "was already"); - fgPgoConsistent = false; - Metrics.ProfileInconsistentResetLeave++; + + if (fgPgoConsistent) + { + Metrics.ProfileInconsistentResetLeave++; + fgPgoConsistent = false; + } } } @@ -7371,8 +7375,12 @@ void Compiler::impImportBlockCode(BasicBlock* block) { JITDUMP("Profile data could not be locally repaired. Data %s inconsistent.\n", fgPgoConsistent ? "is now" : "was already"); - fgPgoConsistent = false; - Metrics.ProfileInconsistentImporterBranchFold++; + + if (fgPgoConsistent) + { + Metrics.ProfileInconsistentImporterBranchFold++; + fgPgoConsistent = false; + } } } } @@ -7657,10 +7665,14 @@ void Compiler::impImportBlockCode(BasicBlock* block) // We are unlikely to be able to repair the profile. // For now we don't even try. // - JITDUMP("Profile data could not be locally repaired. Data %s inconsisent.\n", + JITDUMP("Profile data could not be locally repaired. Data %s inconsistent.\n", fgPgoConsistent ? "is now" : "was already"); - fgPgoConsistent = false; - Metrics.ProfileInconsistentImporterSwitchFold++; + + if (fgPgoConsistent) + { + Metrics.ProfileInconsistentImporterSwitchFold++; + fgPgoConsistent = false; + } } // Create a NOP node diff --git a/src/coreclr/jit/indirectcalltransformer.cpp b/src/coreclr/jit/indirectcalltransformer.cpp index 3f0c311e84a614..92cac9245fc638 100644 --- a/src/coreclr/jit/indirectcalltransformer.cpp +++ b/src/coreclr/jit/indirectcalltransformer.cpp @@ -1248,8 +1248,14 @@ class IndirectCallTransformer if (!isReasonableUnderflow) { - compiler->fgPgoConsistent = false; - compiler->Metrics.ProfileInconsistentChainedGDV++; + JITDUMP("Profile data could not be locally repaired. Data %s inconsistent.\n", + compiler->fgPgoConsistent ? "is now" : "was already"); + + if (compiler->fgPgoConsistent) + { + compiler->Metrics.ProfileInconsistentChainedGDV++; + compiler->fgPgoConsistent = false; + } } } diff --git a/src/coreclr/jit/inline.h b/src/coreclr/jit/inline.h index 8c1cb56124ad2e..a2aeba6fed7254 100644 --- a/src/coreclr/jit/inline.h +++ b/src/coreclr/jit/inline.h @@ -993,6 +993,12 @@ class InlineStrategy m_ImportCount++; } + // Return number of import attempts + unsigned GetImportCount() const + { + return m_ImportCount; + } + // Inform strategy about the inline decision for a prejit root void NotePrejitDecision(const InlineResult& r) { diff --git a/src/coreclr/jit/jitmetadatalist.h b/src/coreclr/jit/jitmetadatalist.h index 43afa6384d4c67..e077f9f57b2559 100644 --- a/src/coreclr/jit/jitmetadatalist.h +++ b/src/coreclr/jit/jitmetadatalist.h @@ -53,6 +53,11 @@ JITMETADATAMETRIC(ClassGDV, int, 0) JITMETADATAMETRIC(MethodGDV, int, 0) JITMETADATAMETRIC(MultiGuessGDV, int, 0) JITMETADATAMETRIC(ChainedGDV, int, 0) +JITMETADATAMETRIC(InlinerBranchFold, int, 0) +JITMETADATAMETRIC(InlineAttempt, int, 0) +JITMETADATAMETRIC(InlineCount, int, 0) +JITMETADATAMETRIC(ProfileConsistentBeforeInline, int, 0) +JITMETADATAMETRIC(ProfileConsistentAfterInline, int, 0) JITMETADATAMETRIC(ProfileSynthesizedBlendedOrRepaired, int, 0) JITMETADATAMETRIC(ProfileInconsistentInitially, int, 0) JITMETADATAMETRIC(ProfileInconsistentResetLeave, int, 0) @@ -60,6 +65,11 @@ JITMETADATAMETRIC(ProfileInconsistentImporterBranchFold, int, 0) JITMETADATAMETRIC(ProfileInconsistentImporterSwitchFold, int, 0) JITMETADATAMETRIC(ProfileInconsistentChainedGDV, int, 0) JITMETADATAMETRIC(ProfileInconsistentScratchBB, int, 0) +JITMETADATAMETRIC(ProfileInconsistentInlinerBranchFold, int, 0) +JITMETADATAMETRIC(ProfileInconsistentInlineeScale, int, 0) +JITMETADATAMETRIC(ProfileInconsistentInlinee, int, 0) +JITMETADATAMETRIC(ProfileInconsistentNoReturnInlinee, int, 0) +JITMETADATAMETRIC(ProfileInconsistentMayThrowInlinee, int, 0) #undef JITMETADATA #undef JITMETADATAINFO From 00f409f0f16739fae17b527bcbc09177fcf8a743 Mon Sep 17 00:00:00 2001 From: Aman Khalid Date: Sat, 4 May 2024 01:14:03 +0000 Subject: [PATCH 242/248] JIT: Test RPO-based block layout in runtime-jit-experimental (#101851) --- eng/pipelines/common/templates/runtimes/run-test-job.yml | 2 ++ src/tests/Common/testenvironment.proj | 2 ++ 2 files changed, 4 insertions(+) diff --git a/eng/pipelines/common/templates/runtimes/run-test-job.yml b/eng/pipelines/common/templates/runtimes/run-test-job.yml index d6404617a3e1ad..0899b32fe524d9 100644 --- a/eng/pipelines/common/templates/runtimes/run-test-job.yml +++ b/eng/pipelines/common/templates/runtimes/run-test-job.yml @@ -537,6 +537,7 @@ jobs: - jitosr_stress - jitpartialcompilation_pgo - jitoptrepeat + - jitrpolayout ${{ else }}: scenarios: - jitosr_stress @@ -549,6 +550,7 @@ jobs: - jitphysicalpromotion_full - jitrlcse - jitoptrepeat + - jitrpolayout ${{ if in(parameters.testGroup, 'jit-cfg') }}: scenarios: - jitcfg diff --git a/src/tests/Common/testenvironment.proj b/src/tests/Common/testenvironment.proj index 73c5bf8a151c4f..8333973b0c0cf9 100644 --- a/src/tests/Common/testenvironment.proj +++ b/src/tests/Common/testenvironment.proj @@ -84,6 +84,7 @@ DOTNET_JitEnableOptRepeat; DOTNET_JitOptRepeat; DOTNET_JitOptRepeatCount; + DOTNET_JitDoReversePostOrderLayout; @@ -243,6 +244,7 @@ + From 64d537accd7aa54094a34b104db35ad8d5e4e0b4 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 3 May 2024 18:29:20 -0700 Subject: [PATCH 243/248] Ensure the scalar Reciprocal*Estimate APIs use AVX512 where possible (#101800) * Ensure the scalar Reciprocal*Estimate APIs use AVX512 where possible * Ensure that TensorPrimitives.Reciprocal APIs consistently use AVX512 * Move the implementation of ReciprocalEstimate and ReciprocalSqrtEstimate to the JIT so R2R works * Ensure the relevant math intrinsics are marked betterToExpand * Apply formatting patch * Fixing the method header for impEstimateIntrinsic * Don't use the AVX512 paths for TensorPrimitives.Reciprocal*Estimate APIs on .NET 8 * Workaround an issue where the TensorPrimitives net8 tests are not running on net8 --- src/coreclr/jit/compiler.h | 7 +- src/coreclr/jit/importercalls.cpp | 163 +++++++++++++++++- src/coreclr/jit/namedintrinsiclist.h | 2 + .../netcore/TensorPrimitives.Reciprocal.cs | 36 ++++ .../System.Numerics.Tensors.Net8.Tests.csproj | 1 + .../tests/TensorPrimitives.Generic.cs | 5 + .../src/System/Double.cs | 2 + .../System.Private.CoreLib/src/System/Math.cs | 24 +-- .../src/System/MathF.cs | 28 +-- .../src/System/Single.cs | 2 + 10 files changed, 217 insertions(+), 53 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 1c6950a55296cc..47ba6143c54666 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -1594,7 +1594,7 @@ enum class ProfileChecks : unsigned int { CHECK_NONE = 0, CHECK_HASLIKELIHOOD = 1 << 0, // check all FlowEdges for hasLikelihood - CHECK_LIKELIHOODSUM = 1 << 1, // check block succesor likelihoods sum to 1 + CHECK_LIKELIHOODSUM = 1 << 1, // check block succesor likelihoods sum to 1 CHECK_LIKELY = 1 << 2, // fully check likelihood based weights RAISE_ASSERT = 1 << 3, // assert on check failure CHECK_ALL_BLOCKS = 1 << 4, // check blocks even if bbHasProfileWeight is false @@ -4528,6 +4528,11 @@ class Compiler CORINFO_THIS_TRANSFORM constraintCallThisTransform, NamedIntrinsic* pIntrinsicName, bool* isSpecialIntrinsic = nullptr); + GenTree* impEstimateIntrinsic(CORINFO_METHOD_HANDLE method, + CORINFO_SIG_INFO* sig, + CorInfoType callJitType, + NamedIntrinsic intrinsicName, + bool tailCall); GenTree* impMathIntrinsic(CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, var_types callType, diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 83f363e9953013..943c75d2639bf1 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -3125,7 +3125,15 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, // To be fixed in https://github.com/dotnet/runtime/pull/77465 const bool tier0opts = !opts.compDbgCode && !opts.jitFlags->IsSet(JitFlags::JIT_FLAG_MIN_OPT); - if (!mustExpand && tier0opts) + if (tier0opts) + { + // The *Estimate APIs are allowed to differ in behavior across hardware + // so ensure we treat them as "betterToExpand" to get deterministic behavior + + betterToExpand |= (ni == NI_System_Math_ReciprocalEstimate); + betterToExpand |= (ni == NI_System_Math_ReciprocalSqrtEstimate); + } + else if (!mustExpand) { switch (ni) { @@ -3189,9 +3197,9 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, break; default: - // Unsafe.* are all small enough to prefer expansions. + // Various intrinsics are all small enough to prefer expansions. + betterToExpand |= ni >= NI_SYSTEM_MATH_START && ni <= NI_SYSTEM_MATH_END; betterToExpand |= ni >= NI_SRCS_UNSAFE_START && ni <= NI_SRCS_UNSAFE_END; - // Same for these betterToExpand |= ni >= NI_PRIMITIVE_START && ni <= NI_PRIMITIVE_END; break; } @@ -4146,6 +4154,13 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, break; } + case NI_System_Math_ReciprocalEstimate: + case NI_System_Math_ReciprocalSqrtEstimate: + { + retNode = impEstimateIntrinsic(method, sig, callJitType, ni, tailCall); + break; + } + case NI_System_Array_Clone: case NI_System_Collections_Generic_Comparer_get_Default: case NI_System_Collections_Generic_EqualityComparer_get_Default: @@ -7413,13 +7428,15 @@ bool Compiler::IsTargetIntrinsic(NamedIntrinsic intrinsicName) // instructions to directly compute round/ceiling/floor/truncate. case NI_System_Math_Abs: + case NI_System_Math_ReciprocalEstimate: + case NI_System_Math_ReciprocalSqrtEstimate: case NI_System_Math_Sqrt: return true; case NI_System_Math_Ceiling: case NI_System_Math_Floor: - case NI_System_Math_Truncate: case NI_System_Math_Round: + case NI_System_Math_Truncate: return compOpportunisticallyDependsOn(InstructionSet_SSE41); case NI_System_Math_FusedMultiplyAdd: @@ -7434,11 +7451,13 @@ bool Compiler::IsTargetIntrinsic(NamedIntrinsic intrinsicName) case NI_System_Math_Abs: case NI_System_Math_Ceiling: case NI_System_Math_Floor: - case NI_System_Math_Truncate: - case NI_System_Math_Round: - case NI_System_Math_Sqrt: case NI_System_Math_Max: case NI_System_Math_Min: + case NI_System_Math_ReciprocalEstimate: + case NI_System_Math_ReciprocalSqrtEstimate: + case NI_System_Math_Round: + case NI_System_Math_Sqrt: + case NI_System_Math_Truncate: return true; case NI_System_Math_FusedMultiplyAdd: @@ -7513,6 +7532,8 @@ bool Compiler::IsMathIntrinsic(NamedIntrinsic intrinsicName) case NI_System_Math_MinMagnitudeNumber: case NI_System_Math_MinNumber: case NI_System_Math_Pow: + case NI_System_Math_ReciprocalEstimate: + case NI_System_Math_ReciprocalSqrtEstimate: case NI_System_Math_Round: case NI_System_Math_Sin: case NI_System_Math_Sinh: @@ -8728,6 +8749,119 @@ void Compiler::impCheckCanInline(GenTreeCall* call, } } +//------------------------------------------------------------------------ +// impEstimateIntrinsic: Imports one of the *Estimate intrinsics which are +// explicitly allowed to differ in result based on the hardware they're running +// against +// +// Arguments: +// method - The handle of the method being imported +// callType - The underlying type for the call +// intrinsicName - The intrinsic being imported +// tailCall - true if the method is a tail call; otherwise false +// +GenTree* Compiler::impEstimateIntrinsic(CORINFO_METHOD_HANDLE method, + CORINFO_SIG_INFO* sig, + CorInfoType callJitType, + NamedIntrinsic intrinsicName, + bool tailCall) +{ + var_types callType = JITtype2varType(callJitType); + + assert(varTypeIsFloating(callType)); + assert(sig->numArgs == 1); + +#if defined(FEATURE_HW_INTRINSICS) + // We use compExactlyDependsOn since these are estimate APIs where + // the behavior is explicitly allowed to differ across machines and + // we want to ensure that it gets marked as such in R2R. + + var_types simdType = TYP_UNKNOWN; + NamedIntrinsic intrinsicId = NI_Illegal; + + switch (intrinsicName) + { + case NI_System_Math_ReciprocalEstimate: + { +#if defined(TARGET_XARCH) + if (compExactlyDependsOn(InstructionSet_AVX512F)) + { + simdType = TYP_SIMD16; + intrinsicId = NI_AVX512F_Reciprocal14Scalar; + } + else if ((callType == TYP_FLOAT) && compExactlyDependsOn(InstructionSet_SSE)) + { + simdType = TYP_SIMD16; + intrinsicId = NI_SSE_ReciprocalScalar; + } +#elif defined(TARGET_ARM64) + if (compExactlyDependsOn(InstructionSet_AdvSimd_Arm64)) + { + simdType = TYP_SIMD8; + intrinsicId = NI_AdvSimd_Arm64_ReciprocalEstimateScalar; + } +#endif // TARGET_ARM64 + break; + } + + case NI_System_Math_ReciprocalSqrtEstimate: + { +#if defined(TARGET_XARCH) + if (compExactlyDependsOn(InstructionSet_AVX512F)) + { + simdType = TYP_SIMD16; + intrinsicId = NI_AVX512F_ReciprocalSqrt14Scalar; + } + else if ((callType == TYP_FLOAT) && compExactlyDependsOn(InstructionSet_SSE)) + { + simdType = TYP_SIMD16; + intrinsicId = NI_SSE_ReciprocalSqrtScalar; + } +#elif defined(TARGET_ARM64) + if (compExactlyDependsOn(InstructionSet_AdvSimd_Arm64)) + { + simdType = TYP_SIMD8; + intrinsicId = NI_AdvSimd_Arm64_ReciprocalSquareRootEstimateScalar; + } +#endif // TARGET_ARM64 + break; + } + + default: + { + unreached(); + } + } + + if (intrinsicId != NI_Illegal) + { + unsigned simdSize = 0; + + if (simdType == TYP_SIMD8) + { + simdSize = 8; + } + else + { + assert(simdType == TYP_SIMD16); + simdSize = 16; + } + + GenTree* op1 = impPopStack().val; + + op1 = gtNewSimdCreateScalarUnsafeNode(simdType, op1, callJitType, simdSize); + op1 = gtNewSimdHWIntrinsicNode(simdType, op1, intrinsicId, callJitType, simdSize); + + return gtNewSimdToScalarNode(callType, op1, callJitType, simdSize); + } +#endif // FEATURE_HW_INTRINSICS + + // TODO-CQ: Returning this as an intrinsic blocks inlining and is undesirable + // return impMathIntrinsic(method, sig, callType, intrinsicName, tailCall); + + return nullptr; +} + GenTree* Compiler::impMathIntrinsic(CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, var_types callType, @@ -10337,7 +10471,20 @@ NamedIntrinsic Compiler::lookupPrimitiveFloatNamedIntrinsic(CORINFO_METHOD_HANDL case 'R': { - if (strcmp(methodName, "Round") == 0) + if (strncmp(methodName, "Reciprocal", 10) == 0) + { + methodName += 10; + + if (strcmp(methodName, "Estimate") == 0) + { + result = NI_System_Math_ReciprocalEstimate; + } + else if (strcmp(methodName, "SqrtEstimate") == 0) + { + result = NI_System_Math_ReciprocalSqrtEstimate; + } + } + else if (strcmp(methodName, "Round") == 0) { result = NI_System_Math_Round; } diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index 67eec1059e82e8..25c0521461d854 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -51,6 +51,8 @@ enum NamedIntrinsic : unsigned short NI_System_Math_MinMagnitudeNumber, NI_System_Math_MinNumber, NI_System_Math_Pow, + NI_System_Math_ReciprocalEstimate, + NI_System_Math_ReciprocalSqrtEstimate, NI_System_Math_Round, NI_System_Math_Sin, NI_System_Math_Sinh, diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Reciprocal.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Reciprocal.cs index 50ef635a21addc..16d0df26157cb2 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Reciprocal.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Reciprocal.cs @@ -95,6 +95,14 @@ public static void ReciprocalSqrtEstimate(ReadOnlySpan x, Span destinat public static Vector128 Invoke(Vector128 x) { +#if NET9_0_OR_GREATER + if (Avx512F.VL.IsSupported) + { + if (typeof(T) == typeof(float)) return Avx512F.VL.Reciprocal14(x.AsSingle()).As(); + if (typeof(T) == typeof(double)) return Avx512F.VL.Reciprocal14(x.AsDouble()).As(); + } +#endif + if (Sse.IsSupported) { if (typeof(T) == typeof(float)) return Sse.Reciprocal(x.AsSingle()).As(); @@ -115,6 +123,14 @@ public static Vector128 Invoke(Vector128 x) public static Vector256 Invoke(Vector256 x) { +#if NET9_0_OR_GREATER + if (Avx512F.VL.IsSupported) + { + if (typeof(T) == typeof(float)) return Avx512F.VL.Reciprocal14(x.AsSingle()).As(); + if (typeof(T) == typeof(double)) return Avx512F.VL.Reciprocal14(x.AsDouble()).As(); + } +#endif + if (Avx.IsSupported) { if (typeof(T) == typeof(float)) return Avx.Reciprocal(x.AsSingle()).As(); @@ -125,11 +141,13 @@ public static Vector256 Invoke(Vector256 x) public static Vector512 Invoke(Vector512 x) { +#if NET9_0_OR_GREATER if (Avx512F.IsSupported) { if (typeof(T) == typeof(float)) return Avx512F.Reciprocal14(x.AsSingle()).As(); if (typeof(T) == typeof(double)) return Avx512F.Reciprocal14(x.AsDouble()).As(); } +#endif return Vector512.One / x; } @@ -143,6 +161,14 @@ public static Vector512 Invoke(Vector512 x) public static Vector128 Invoke(Vector128 x) { +#if NET9_0_OR_GREATER + if (Avx512F.VL.IsSupported) + { + if (typeof(T) == typeof(float)) return Avx512F.VL.ReciprocalSqrt14(x.AsSingle()).As(); + if (typeof(T) == typeof(double)) return Avx512F.VL.ReciprocalSqrt14(x.AsDouble()).As(); + } +#endif + if (Sse.IsSupported) { if (typeof(T) == typeof(float)) return Sse.ReciprocalSqrt(x.AsSingle()).As(); @@ -163,6 +189,14 @@ public static Vector128 Invoke(Vector128 x) public static Vector256 Invoke(Vector256 x) { +#if NET9_0_OR_GREATER + if (Avx512F.VL.IsSupported) + { + if (typeof(T) == typeof(float)) return Avx512F.VL.ReciprocalSqrt14(x.AsSingle()).As(); + if (typeof(T) == typeof(double)) return Avx512F.VL.ReciprocalSqrt14(x.AsDouble()).As(); + } +#endif + if (Avx.IsSupported) { if (typeof(T) == typeof(float)) return Avx.ReciprocalSqrt(x.AsSingle()).As(); @@ -173,11 +207,13 @@ public static Vector256 Invoke(Vector256 x) public static Vector512 Invoke(Vector512 x) { +#if NET9_0_OR_GREATER if (Avx512F.IsSupported) { if (typeof(T) == typeof(float)) return Avx512F.ReciprocalSqrt14(x.AsSingle()).As(); if (typeof(T) == typeof(double)) return Avx512F.ReciprocalSqrt14(x.AsDouble()).As(); } +#endif return Vector512.One / Vector512.Sqrt(x); } diff --git a/src/libraries/System.Numerics.Tensors/tests/Net8Tests/System.Numerics.Tensors.Net8.Tests.csproj b/src/libraries/System.Numerics.Tensors/tests/Net8Tests/System.Numerics.Tensors.Net8.Tests.csproj index eb08d0e5974a6f..3b8f867b355c0a 100644 --- a/src/libraries/System.Numerics.Tensors/tests/Net8Tests/System.Numerics.Tensors.Net8.Tests.csproj +++ b/src/libraries/System.Numerics.Tensors/tests/Net8Tests/System.Numerics.Tensors.Net8.Tests.csproj @@ -10,6 +10,7 @@ $(NetCoreAppCurrent) true + $(DefineConstants);SNT_NET8_TESTS diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs b/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs index 1875b6059b7fa9..2768a03a070475 100644 --- a/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs +++ b/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs @@ -386,7 +386,12 @@ public static IEnumerable SpanDestinationFunctionsToTest() yield return Create(TensorPrimitives.Reciprocal, f => T.One / f); yield return Create(TensorPrimitives.ReciprocalEstimate, T.ReciprocalEstimate, T.CreateTruncating(Helpers.DefaultToleranceForEstimates)); yield return Create(TensorPrimitives.ReciprocalSqrt, f => T.One / T.Sqrt(f)); + +#if !SNT_NET8_TESTS + // Avoid running with the net8 tests due to: https://github.com/dotnet/runtime/issues/101846 yield return Create(TensorPrimitives.ReciprocalSqrtEstimate, T.ReciprocalSqrtEstimate, T.CreateTruncating(Helpers.DefaultToleranceForEstimates)); +#endif + yield return Create(TensorPrimitives.Round, T.Round); yield return Create(TensorPrimitives.Sin, T.Sin, trigTolerance); yield return Create(TensorPrimitives.Sinh, T.Sinh, Helpers.DetermineTolerance(doubleTolerance: 1e-14)); diff --git a/src/libraries/System.Private.CoreLib/src/System/Double.cs b/src/libraries/System.Private.CoreLib/src/System/Double.cs index 04e8269c78f464..81a6792b599cd5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Double.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Double.cs @@ -865,9 +865,11 @@ bool IFloatingPoint.TryWriteSignificandLittleEndian(Span destinati public static double Lerp(double value1, double value2, double amount) => (value1 * (1.0 - amount)) + (value2 * amount); /// + [Intrinsic] public static double ReciprocalEstimate(double x) => Math.ReciprocalEstimate(x); /// + [Intrinsic] public static double ReciprocalSqrtEstimate(double x) => Math.ReciprocalSqrtEstimate(x); /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs index e2fe2051ce5c9e..521abb22465e7b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Math.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Math.cs @@ -1195,19 +1195,11 @@ public static double MinMagnitude(double x, double y) /// On ARM64 hardware this may use the FRECPE instruction which performs a single Newton-Raphson iteration. /// On hardware without specialized support, this may just return 1.0 / d. /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double ReciprocalEstimate(double d) { - // x86 doesn't provide an estimate instruction for double-precision reciprocal - - if (AdvSimd.Arm64.IsSupported) - { - return AdvSimd.Arm64.ReciprocalEstimateScalar(Vector64.CreateScalar(d)).ToScalar(); - } - else - { - return 1.0 / d; - } + return 1.0 / d; } /// Returns an estimate of the reciprocal square root of a specified number. @@ -1217,19 +1209,11 @@ public static double ReciprocalEstimate(double d) /// On ARM64 hardware this may use the FRSQRTE instruction which performs a single Newton-Raphson iteration. /// On hardware without specialized support, this may just return 1.0 / Sqrt(d). /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double ReciprocalSqrtEstimate(double d) { - // x86 doesn't provide an estimate instruction for double-precision reciprocal square root - - if (AdvSimd.Arm64.IsSupported) - { - return AdvSimd.Arm64.ReciprocalSquareRootEstimateScalar(Vector64.CreateScalar(d)).ToScalar(); - } - else - { - return 1.0 / Sqrt(d); - } + return 1.0 / Sqrt(d); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/libraries/System.Private.CoreLib/src/System/MathF.cs b/src/libraries/System.Private.CoreLib/src/System/MathF.cs index cc0795255d0c89..05b404abccc51a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MathF.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MathF.cs @@ -313,21 +313,11 @@ public static float MinMagnitude(float x, float y) /// On ARM64 hardware this may use the FRECPE instruction which performs a single Newton-Raphson iteration. /// On hardware without specialized support, this may just return 1.0 / x. /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float ReciprocalEstimate(float x) { - if (Sse.IsSupported) - { - return Sse.ReciprocalScalar(Vector128.CreateScalarUnsafe(x)).ToScalar(); - } - else if (AdvSimd.Arm64.IsSupported) - { - return AdvSimd.Arm64.ReciprocalEstimateScalar(Vector64.CreateScalarUnsafe(x)).ToScalar(); - } - else - { - return 1.0f / x; - } + return 1.0f / x; } /// Returns an estimate of the reciprocal square root of a specified number. @@ -338,21 +328,11 @@ public static float ReciprocalEstimate(float x) /// On ARM64 hardware this may use the FRSQRTE instruction which performs a single Newton-Raphson iteration. /// On hardware without specialized support, this may just return 1.0 / Sqrt(x). /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float ReciprocalSqrtEstimate(float x) { - if (Sse.IsSupported) - { - return Sse.ReciprocalSqrtScalar(Vector128.CreateScalarUnsafe(x)).ToScalar(); - } - else if (AdvSimd.Arm64.IsSupported) - { - return AdvSimd.Arm64.ReciprocalSquareRootEstimateScalar(Vector64.CreateScalarUnsafe(x)).ToScalar(); - } - else - { - return 1.0f / Sqrt(x); - } + return 1.0f / Sqrt(x); } [Intrinsic] diff --git a/src/libraries/System.Private.CoreLib/src/System/Single.cs b/src/libraries/System.Private.CoreLib/src/System/Single.cs index 8a8a38aa2c0b48..fe96bb1b419f7a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Single.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Single.cs @@ -848,9 +848,11 @@ bool IFloatingPoint.TryWriteSignificandLittleEndian(Span destinatio public static float Lerp(float value1, float value2, float amount) => (value1 * (1.0f - amount)) + (value2 * amount); /// + [Intrinsic] public static float ReciprocalEstimate(float x) => MathF.ReciprocalEstimate(x); /// + [Intrinsic] public static float ReciprocalSqrtEstimate(float x) => MathF.ReciprocalSqrtEstimate(x); /// From 358b0a4d350a6c72ccc825a0ac668620f849365a Mon Sep 17 00:00:00 2001 From: Dan Moseley Date: Fri, 3 May 2024 22:29:12 -0700 Subject: [PATCH 244/248] [browser] Fix ConvertDllsToWebCil stack dump on bad input to be error message with input path (#101162) --- .../ConvertDllsToWebCil.cs | 89 +++++++++++-------- 1 file changed, 52 insertions(+), 37 deletions(-) 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 2d21f3820a5584..01c5d4dda4dd0f 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Collections.Generic; using System.IO; using Microsoft.Build.Framework; @@ -59,52 +60,66 @@ public override bool Execute() continue; } - var dllFilePath = candidate.ItemSpec; - var webcilFileName = Path.GetFileNameWithoutExtension(dllFilePath) + Utils.WebcilInWasmExtension; - string candidatePath = candidate.GetMetadata("AssetTraitName") == "Culture" - ? Path.Combine(OutputPath, candidate.GetMetadata("AssetTraitValue")) - : OutputPath; - - string finalWebcil = Path.Combine(candidatePath, webcilFileName); - - if (Utils.IsNewerThan(dllFilePath, finalWebcil)) + try { - var tmpWebcil = Path.Combine(tmpDir, webcilFileName); - var logAdapter = new LogAdapter(Log); - var webcilWriter = Microsoft.WebAssembly.Build.Tasks.WebcilConverter.FromPortableExecutable(inputPath: dllFilePath, outputPath: tmpWebcil, logger: logAdapter); - webcilWriter.ConvertToWebcil(); - - if (!Directory.Exists(candidatePath)) - Directory.CreateDirectory(candidatePath); - - if (Utils.CopyIfDifferent(tmpWebcil, finalWebcil, useHash: true)) - Log.LogMessage(MessageImportance.Low, $"Generated {finalWebcil} ."); - else - Log.LogMessage(MessageImportance.Low, $"Skipped generating {finalWebcil} as the contents are unchanged."); + TaskItem webcilItem = ConvertDll(tmpDir, candidate); + webCilCandidates.Add(webcilItem); } - else + catch (Exception ex) { - Log.LogMessage(MessageImportance.Low, $"Skipping {dllFilePath} as it is older than the output file {finalWebcil}"); + Log.LogError($"Failed to convert '{candidate.ItemSpec}' to webcil: {ex.Message}"); + return false; } + } + + WebCilCandidates = webCilCandidates.ToArray(); + return true; + } - _fileWrites.Add(finalWebcil); + private TaskItem ConvertDll(string tmpDir, ITaskItem candidate) + { + var dllFilePath = candidate.ItemSpec; + var webcilFileName = Path.GetFileNameWithoutExtension(dllFilePath) + Utils.WebcilInWasmExtension; + string candidatePath = candidate.GetMetadata("AssetTraitName") == "Culture" + ? Path.Combine(OutputPath, candidate.GetMetadata("AssetTraitValue")) + : OutputPath; - var webcilItem = new TaskItem(finalWebcil, candidate.CloneCustomMetadata()); - webcilItem.SetMetadata("RelativePath", Path.ChangeExtension(candidate.GetMetadata("RelativePath"), Utils.WebcilInWasmExtension)); - webcilItem.SetMetadata("OriginalItemSpec", finalWebcil); + string finalWebcil = Path.Combine(candidatePath, webcilFileName); - if (webcilItem.GetMetadata("AssetTraitName") == "Culture") - { - string relatedAsset = webcilItem.GetMetadata("RelatedAsset"); - relatedAsset = Path.ChangeExtension(relatedAsset, Utils.WebcilInWasmExtension); - webcilItem.SetMetadata("RelatedAsset", relatedAsset); - Log.LogMessage(MessageImportance.Low, $"Changing related asset of {webcilItem} to {relatedAsset}."); - } + if (Utils.IsNewerThan(dllFilePath, finalWebcil)) + { + var tmpWebcil = Path.Combine(tmpDir, webcilFileName); + var logAdapter = new LogAdapter(Log); + var webcilWriter = Microsoft.WebAssembly.Build.Tasks.WebcilConverter.FromPortableExecutable(inputPath: dllFilePath, outputPath: tmpWebcil, logger: logAdapter); + webcilWriter.ConvertToWebcil(); - webCilCandidates.Add(webcilItem); + if (!Directory.Exists(candidatePath)) + Directory.CreateDirectory(candidatePath); + + if (Utils.CopyIfDifferent(tmpWebcil, finalWebcil, useHash: true)) + Log.LogMessage(MessageImportance.Low, $"Generated {finalWebcil} ."); + else + Log.LogMessage(MessageImportance.Low, $"Skipped generating {finalWebcil} as the contents are unchanged."); + } + else + { + Log.LogMessage(MessageImportance.Low, $"Skipping {dllFilePath} as it is older than the output file {finalWebcil}"); } - WebCilCandidates = webCilCandidates.ToArray(); - return true; + _fileWrites.Add(finalWebcil); + + var webcilItem = new TaskItem(finalWebcil, candidate.CloneCustomMetadata()); + webcilItem.SetMetadata("RelativePath", Path.ChangeExtension(candidate.GetMetadata("RelativePath"), Utils.WebcilInWasmExtension)); + webcilItem.SetMetadata("OriginalItemSpec", finalWebcil); + + if (webcilItem.GetMetadata("AssetTraitName") == "Culture") + { + string relatedAsset = webcilItem.GetMetadata("RelatedAsset"); + relatedAsset = Path.ChangeExtension(relatedAsset, Utils.WebcilInWasmExtension); + webcilItem.SetMetadata("RelatedAsset", relatedAsset); + Log.LogMessage(MessageImportance.Low, $"Changing related asset of {webcilItem} to {relatedAsset}."); + } + + return webcilItem; } } From deb7c1707c00dd14bd9cd179c976ccfc1e70544d Mon Sep 17 00:00:00 2001 From: ophura <61603742+ophura@users.noreply.github.com> Date: Sat, 4 May 2024 17:19:56 +0200 Subject: [PATCH 245/248] `explosed` -> `exposed` (#101836) --- src/libraries/System.Private.CoreLib/src/System/Buffer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffer.cs b/src/libraries/System.Private.CoreLib/src/System/Buffer.cs index d07df58bb23769..25b6965ee2d12e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffer.cs @@ -62,7 +62,7 @@ public static int ByteLength(Array array) nuint byteLength = array.NativeLength * (nuint)array.GetElementSize(); - // This API is explosed both as Buffer.ByteLength and also used indirectly in argument + // This API is exposed both as Buffer.ByteLength and also used indirectly in argument // checks for Buffer.GetByte/SetByte. // // If somebody called Get/SetByte on 2GB+ arrays, there is a decent chance that From 5962fd511e3eacf7fe91520392c041e94e5d31cc Mon Sep 17 00:00:00 2001 From: Aman Khalid Date: Sat, 4 May 2024 20:08:54 +0000 Subject: [PATCH 246/248] Remove old experiments; add layout experiment (#101852) --- eng/pipelines/coreclr/perf-non-wasm-jobs.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/eng/pipelines/coreclr/perf-non-wasm-jobs.yml b/eng/pipelines/coreclr/perf-non-wasm-jobs.yml index c48103af929c81..574728cfed7eae 100644 --- a/eng/pipelines/coreclr/perf-non-wasm-jobs.yml +++ b/eng/pipelines/coreclr/perf-non-wasm-jobs.yml @@ -306,7 +306,7 @@ jobs: runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml logicalmachine: 'perfviper' - # run coreclr perfowl microbenchmarks perf gdv3 jobs + # run coreclr perfowl microbenchmarks perf rlcse jobs - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml @@ -322,9 +322,9 @@ jobs: runKind: micro runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml logicalmachine: 'perfowl' - experimentName: 'gdv3' + experimentName: 'rlcse' - # run coreclr perfowl microbenchmarks perf rlcse jobs + # run coreclr perfowl microbenchmarks perf jitoptrepeat jobs - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml @@ -340,9 +340,9 @@ jobs: runKind: micro runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml logicalmachine: 'perfowl' - experimentName: 'rlcse' + experimentName: 'jitoptrepeat' - # run coreclr perfowl microbenchmarks perf jitoptrepeat jobs + # run coreclr perfowl microbenchmarks perf rpolayout jobs - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml @@ -358,7 +358,7 @@ jobs: runKind: micro runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml logicalmachine: 'perfowl' - experimentName: 'jitoptrepeat' + experimentName: 'rpolayout' # run coreclr crossgen perf job - template: /eng/pipelines/common/platform-matrix.yml From a225c6f34aa65154e37569d906779a715f6dd1b8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 5 May 2024 10:22:07 +0800 Subject: [PATCH 247/248] Add tests for OAVariantLib (#101841) * Add native return test for basic supported types --------- Co-authored-by: Aaron Robinson --- .../COM/NETClients/IDispatch/Program.cs | 62 ++++ .../COM/NETServer/DispatchCoerceTesting.cs | 39 +++ .../COM/NativeClients/Dispatch/Client.cpp | 110 +++++++ .../Dispatch/CoreShim.X.manifest | 5 + .../NativeServer/COMNativeServer.X.manifest | 5 + .../COM/NativeServer/DispatchCoerceTesting.h | 278 ++++++++++++++++++ .../Interop/COM/NativeServer/Servers.cpp | 5 + src/tests/Interop/COM/NativeServer/Servers.h | 4 + .../COM/ServerContracts/Server.CoClasses.cs | 19 ++ .../COM/ServerContracts/Server.Contracts.cs | 16 + .../COM/ServerContracts/Server.Contracts.h | 6 + .../COM/ServerContracts/ServerGuids.cs | 1 + 12 files changed, 550 insertions(+) create mode 100644 src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs create mode 100644 src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h diff --git a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs index 3de48ae59b7944..c57f8c5149f27e 100644 --- a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs +++ b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs @@ -215,6 +215,67 @@ System.Collections.Generic.IEnumerable GetEnumerable(System.Collections.IEn } } + static void Validate_ValueCoerce_ReturnToManaged() + { + var dispatchCoerceTesting = (DispatchCoerceTesting)new DispatchCoerceTestingClass(); + + Console.WriteLine($"Calling {nameof(DispatchCoerceTesting.ReturnToManaged)} ..."); + + // Supported types + // See returned values in DispatchCoerceTesting.h + (VarEnum type, int expectedValue)[] supportedTypes = + { + (VarEnum.VT_EMPTY, 0), + (VarEnum.VT_I2, 123), + (VarEnum.VT_I4, 123), + (VarEnum.VT_R4, 1), + (VarEnum.VT_R8, 1), + (VarEnum.VT_CY, 123), + (VarEnum.VT_DATE, 1), + (VarEnum.VT_BSTR, 123), + (VarEnum.VT_ERROR, 123), + (VarEnum.VT_BOOL, -1), + (VarEnum.VT_DECIMAL, 123), + }; + + foreach (var (vt, expected) in supportedTypes) + { + Console.WriteLine($"Converting {vt} to int should be supported."); + int result = dispatchCoerceTesting.ReturnToManaged((short)vt); + Assert.Equal(expected, result); + } + + // Invalid: Rejected before reaching coerce + Console.WriteLine("Invalid variant type should throw InvalidOleVariantTypeException."); + var variantException = Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged(0x7FFF)); + Assert.Equal(unchecked((int)0x80131531), variantException.HResult); + + // Not supported source or destination type: COMException { HResult: 0x80020005 } + + // DISP_E_PARAMNOTFOUND: Converts to Missing + Console.WriteLine("Converting from VT_ERROR with DISP_E_PARAMNOTFOUND should be rejected."); + var comException = Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged(unchecked((short)((short)VarEnum.VT_ERROR | 0x8000)))); + Assert.Equal(unchecked((int)0x80020005), comException.HResult); + + Console.WriteLine("Converting int to VT_MISSING should be rejected."); + comException = Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged_Missing()); + Assert.Equal(unchecked((int)0x80020005), comException.HResult); + + Console.WriteLine("Converting int to VT_NULL should be rejected."); + comException = Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged_DBNull()); + Assert.Equal(unchecked((int)0x80020005), comException.HResult); + + // Rejected by VariantChangeTypeEx + Console.WriteLine("Converting VT_UNKNOWN to int should fail from VariantChangeTypeEx."); + Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged((short)VarEnum.VT_UNKNOWN)); + Console.WriteLine("Converting VT_NULL to int should fail from VariantChangeTypeEx."); + Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged((short)VarEnum.VT_NULL)); + + // LOCAL_BOOL + Console.WriteLine("VARIANT_BOOL should convert to non-numeric string."); + Assert.Equal("True", dispatchCoerceTesting.BoolToString()); + } + [Fact] public static int TestEntryPoint() { @@ -233,6 +294,7 @@ public static int TestEntryPoint() Validate_StructNotSupported(); Validate_LCID_Marshaled(); Validate_Enumerator(); + Validate_ValueCoerce_ReturnToManaged(); } catch (Exception e) { diff --git a/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs new file mode 100644 index 00000000000000..0367c605df4830 --- /dev/null +++ b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; +using Server.Contract; + +[ComVisible(true)] +[Guid(Server.Contract.Guids.DispatchCoerceTesting)] +public class DispatchCoerceTesting : Server.Contract.IDispatchCoerceTesting +{ + public int ReturnToManaged(short vt) + { + throw new NotImplementedException(); + } + + public int ManagedArgument(int arg) + { + return arg; + } + + public System.Reflection.Missing ReturnToManaged_Missing() + { + return System.Reflection.Missing.Value; + } + + public DBNull ReturnToManaged_DBNull() + { + return DBNull.Value; + } + + public string BoolToString() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp b/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp index 827b8d22876326..4c509a3df16240 100644 --- a/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp +++ b/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp @@ -11,6 +11,7 @@ void Validate_Float_In_ReturnAndUpdateByRef(); void Validate_Double_In_ReturnAndUpdateByRef(); void Validate_LCID_Marshaled(); void Validate_Enumerator(); +void Validate_ParamCoerce(); template struct ComInit @@ -48,6 +49,7 @@ int __cdecl main() Validate_Double_In_ReturnAndUpdateByRef(); Validate_LCID_Marshaled(); Validate_Enumerator(); + Validate_ParamCoerce(); } catch (HRESULT hr) { @@ -459,3 +461,111 @@ void Validate_Enumerator() ::printf(" -- Validate returned IEnumVARIANT\n"); ValidateReturnedEnumerator(&result); } + +void Validate_ParamCoerce_Type(ComSmartPtr& dispatchCoerceTesting, VARENUM type, int lcid, DISPID methodId) +{ + HRESULT hr; + + DISPPARAMS params; + VARIANTARG arg; + params.cArgs = 1; + params.rgvarg = &arg; + params.cNamedArgs = 0; + params.rgdispidNamedArgs = nullptr; + + VARIANT result; + + V_VT(&arg) = type; + + switch (type) + { + case VT_BSTR: + { + BSTR str = ::SysAllocString(L"123"); + V_BSTR(&arg) = str; + break; + } + case VT_R4: + { + V_R4(&arg) = 1.23f; + break; + } + case VT_DATE: + case VT_R8: + { + V_R8(&arg) = 1.23; + break; + } + case VT_CY: + { + VarCyFromI4(123, &V_CY(&arg)); + break; + } + case VT_DECIMAL: + { + VarDecFromI4(123, &V_DECIMAL(&arg)); + break; + } + default: + { + V_I1(&arg) = 123; + break; + } + } + + THROW_IF_FAILED(dispatchCoerceTesting->Invoke( + methodId, + IID_NULL, + lcid, + DISPATCH_METHOD, + ¶ms, + &result, + nullptr, + nullptr + )); + + THROW_FAIL_IF_FALSE(V_I4(&result) != 0); +} + +void Validate_ParamCoerce() +{ + HRESULT hr; + + CoreShimComActivation csact{ W("NETServer"), W("DispatchCoerceTesting") }; + + ComSmartPtr dispatchCoerceTesting; + THROW_IF_FAILED(::CoCreateInstance(CLSID_DispatchCoerceTesting, nullptr, CLSCTX_INPROC, IID_IDispatchCoerceTesting, (void**)&dispatchCoerceTesting)); + + LPOLESTR numericMethodName = (LPOLESTR)W("ManagedArgument"); + LCID lcid = MAKELCID(LANG_USER_DEFAULT, SORT_DEFAULT); + DISPID methodId; + + ::wprintf(W("Invoke %s\n"), numericMethodName); + THROW_IF_FAILED(dispatchCoerceTesting->GetIDsOfNames( + IID_NULL, + &numericMethodName, + 1, + lcid, + &methodId)); + + ::wprintf(W("Validating VT_I2\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_I2, lcid, methodId); + ::wprintf(W("Validating VT_I4\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_I4, lcid, methodId); + ::wprintf(W("Validating VT_R4\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_R4, lcid, methodId); + ::wprintf(W("Validating VT_R8\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_R8, lcid, methodId); + ::wprintf(W("Validating VT_CY\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_CY, lcid, methodId); + ::wprintf(W("Validating VT_DATE\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_DATE, lcid, methodId); + ::wprintf(W("Validating VT_BSTR\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_BSTR, lcid, methodId); + ::wprintf(W("Validating VT_ERROR\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_ERROR, lcid, methodId); + ::wprintf(W("Validating VT_BOOL\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_BOOL, lcid, methodId); + ::wprintf(W("Validating VT_DECIMAL\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_DECIMAL, lcid, methodId); +} diff --git a/src/tests/Interop/COM/NativeClients/Dispatch/CoreShim.X.manifest b/src/tests/Interop/COM/NativeClients/Dispatch/CoreShim.X.manifest index 0e635e03c3ee0d..94105dbcbf72fb 100644 --- a/src/tests/Interop/COM/NativeClients/Dispatch/CoreShim.X.manifest +++ b/src/tests/Interop/COM/NativeClients/Dispatch/CoreShim.X.manifest @@ -11,6 +11,11 @@ + + + diff --git a/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest b/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest index 9f688bc8e22bab..12ac7bd541cdeb 100644 --- a/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest +++ b/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest @@ -42,6 +42,11 @@ clsid="{4DBD9B61-E372-499F-84DE-EFC70AA8A009}" threadingModel="Both" /> + + + cArgs)); + + if (pVarResult == nullptr) + return E_POINTER; + + VARENUM currType; + VARIANTARG *currArg; + size_t argIdx = expectedArgCount - 1; + + // Extract args + { + currType = VT_I2; + currArg = NextArg(pDispParams->rgvarg, argIdx); + RETURN_IF_FAILED(VerifyValues(VARENUM(currType), VARENUM(currArg->vt))); + args[0] = &currArg->iVal; + } + + VARENUM resultType = (VARENUM)*args[0]; + VariantInit(pVarResult); + V_VT(pVarResult) = resultType & 0x7FFF; + + switch ((uint16_t)resultType) + { + case VT_BSTR: + { + BSTR str = ::SysAllocString(L"123"); + V_BSTR(pVarResult) = str; + break; + } + case VT_R4: + { + V_R4(pVarResult) = 1.23f; + break; + } + case VT_DATE: + case VT_R8: + { + V_R8(pVarResult) = 1.23; + break; + } + case VT_CY: + { + VarCyFromI4(123, &V_CY(pVarResult)); + break; + } + case VT_DECIMAL: + { + VarDecFromI4(123, &V_DECIMAL(pVarResult)); + break; + } + case ((VT_ERROR | 0x8000)): + { + V_I4(pVarResult) = DISP_E_PARAMNOTFOUND; + break; + } + case VT_UNKNOWN: + { + V_UNKNOWN(pVarResult) = static_cast(this); + break; + } + default: + { + V_I1(pVarResult) = 123; + break; + } + } + + return S_OK; + } + + HRESULT ManagedArgument_Dispatch(_In_ DISPPARAMS *pDispParams, _Inout_ VARIANT *pVarResult) + { + HRESULT hr; + + int *args[1]; + size_t expectedArgCount = 1; + RETURN_IF_FAILED(VerifyValues(uint32_t(expectedArgCount), pDispParams->cArgs)); + + if (pVarResult == nullptr) + return E_POINTER; + + VARENUM currType; + VARIANTARG *currArg; + size_t argIdx = expectedArgCount - 1; + + // Extract args + { + currType = VT_I4; + currArg = NextArg(pDispParams->rgvarg, argIdx); + RETURN_IF_FAILED(VerifyValues(VARENUM(currType), VARENUM(currArg->vt))); + args[0] = &currArg->intVal; + } + + V_VT(pVarResult) = VT_I2; + V_I2(pVarResult) = *args[0]; + return S_OK; + } + + HRESULT ReturnToManaged_Missing_Dispatch(_In_ DISPPARAMS *pDispParams, _Inout_ VARIANT *pVarResult) + { + HRESULT hr; + + size_t expectedArgCount = 0; + RETURN_IF_FAILED(VerifyValues(uint32_t(expectedArgCount), pDispParams->cArgs)); + + if (pVarResult == nullptr) + return E_POINTER; + + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = 1234; + return S_OK; + } + + HRESULT ReturnToManaged_DBNull_Dispatch(_In_ DISPPARAMS *pDispParams, _Inout_ VARIANT *pVarResult) + { + HRESULT hr; + + size_t expectedArgCount = 0; + RETURN_IF_FAILED(VerifyValues(uint32_t(expectedArgCount), pDispParams->cArgs)); + + if (pVarResult == nullptr) + return E_POINTER; + + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = 1234; + return S_OK; + } + + HRESULT BoolToString_Dispatch(_In_ DISPPARAMS *pDispParams, _Inout_ VARIANT *pVarResult) + { + HRESULT hr; + + size_t expectedArgCount = 0; + RETURN_IF_FAILED(VerifyValues(uint32_t(expectedArgCount), pDispParams->cArgs)); + + if (pVarResult == nullptr) + return E_POINTER; + + V_VT(pVarResult) = VT_BOOL; + V_BOOL(pVarResult) = VARIANT_TRUE; + return S_OK; + } + +public: // IUnknown + STDMETHOD(QueryInterface)( + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject) + { + return DoQueryInterface(riid, ppvObject, static_cast(this), static_cast(this)); + } + + DEFINE_REF_COUNTING(); +}; + +const WCHAR * const DispatchCoerceTesting::Names[] = +{ + W("__RESERVED__"), + W("ReturnToManaged"), + W("ManagedArgument"), + W("ReturnToManaged_Missing"), + W("ReturnToManaged_DBNull"), + W("BoolToString") +}; + +const int DispatchCoerceTesting::NamesCount = ARRAY_SIZE(DispatchCoerceTesting::Names); diff --git a/src/tests/Interop/COM/NativeServer/Servers.cpp b/src/tests/Interop/COM/NativeServer/Servers.cpp index 05f26be8d4741d..ebe4f9df5acde2 100644 --- a/src/tests/Interop/COM/NativeServer/Servers.cpp +++ b/src/tests/Interop/COM/NativeServer/Servers.cpp @@ -166,6 +166,7 @@ STDAPI DllRegisterServer(void) RETURN_IF_FAILED(RegisterClsid(__uuidof(ErrorMarshalTesting), L"Both")); RETURN_IF_FAILED(RegisterClsid(__uuidof(DispatchTesting), L"Both")); RETURN_IF_FAILED(RegisterClsid(__uuidof(EventTesting), L"Both")); + RETURN_IF_FAILED(RegisterClsid(__uuidof(DispatchCoerceTesting), L"Both")); RETURN_IF_FAILED(RegisterClsid(__uuidof(AggregationTesting), L"Both")); RETURN_IF_FAILED(RegisterClsid(__uuidof(ColorTesting), L"Both")); RETURN_IF_FAILED(RegisterClsid(__uuidof(InspectableTesting), L"Both")); @@ -185,6 +186,7 @@ STDAPI DllUnregisterServer(void) RETURN_IF_FAILED(RemoveClsid(__uuidof(ErrorMarshalTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(DispatchTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(EventTesting))); + RETURN_IF_FAILED(RemoveClsid(__uuidof(DispatchCoerceTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(AggregationTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(ColorTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(InspectableTesting))); @@ -216,6 +218,9 @@ STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Out_ LPVOID FA if (rclsid == __uuidof(EventTesting)) return ClassFactoryBasic::Create(riid, ppv); + if (rclsid == __uuidof(DispatchCoerceTesting)) + return ClassFactoryBasic::Create(riid, ppv); + if (rclsid == __uuidof(AggregationTesting)) return ClassFactoryAggregate::Create(riid, ppv); diff --git a/src/tests/Interop/COM/NativeServer/Servers.h b/src/tests/Interop/COM/NativeServer/Servers.h index c87288d2535b1a..44e5070a25a6b2 100644 --- a/src/tests/Interop/COM/NativeServer/Servers.h +++ b/src/tests/Interop/COM/NativeServer/Servers.h @@ -16,6 +16,7 @@ class DECLSPEC_UUID("CCFF894B-A27C-45E0-9B30-6C88D722E843") MiscTypesTesting; class DECLSPEC_UUID("71CF5C45-106C-4B32-B418-43A463C6041F") ErrorMarshalTesting; class DECLSPEC_UUID("0F8ACD0C-ECE0-4F2A-BD1B-6BFCA93A0726") DispatchTesting; class DECLSPEC_UUID("4DBD9B61-E372-499F-84DE-EFC70AA8A009") EventTesting; +class DECLSPEC_UUID("661F9962-3477-416B-BE40-4CBA3190A562") DispatchCoerceTesting; class DECLSPEC_UUID("4CEFE36D-F377-4B6E-8C34-819A8BB9CB04") AggregationTesting; class DECLSPEC_UUID("C222F472-DA5A-4FC6-9321-92F4F7053A65") ColorTesting; class DECLSPEC_UUID("66DB7882-E2B0-471D-92C7-B2B52A0EA535") LicenseTesting; @@ -30,6 +31,7 @@ class DECLSPEC_UUID("4F54231D-9E11-4C0B-8E0B-2EBD8B0E5811") TrackMyLifetimeTesti #define CLSID_ErrorMarshalTesting __uuidof(ErrorMarshalTesting) #define CLSID_DispatchTesting __uuidof(DispatchTesting) #define CLSID_EventTesting __uuidof(EventTesting) +#define CLSID_DispatchCoerceTesting __uuidof(DispatchCoerceTesting) #define CLSID_AggregationTesting __uuidof(AggregationTesting) #define CLSID_ColorTesting __uuidof(ColorTesting) #define CLSID_LicenseTesting __uuidof(LicenseTesting) @@ -45,6 +47,7 @@ class DECLSPEC_UUID("4F54231D-9E11-4C0B-8E0B-2EBD8B0E5811") TrackMyLifetimeTesti #define IID_IDispatchTesting __uuidof(IDispatchTesting) #define IID_TestingEvents __uuidof(TestingEvents) #define IID_IEventTesting __uuidof(IEventTesting) +#define IID_IDispatchCoerceTesting __uuidof(IDispatchCoerceTesting) #define IID_IAggregationTesting __uuidof(IAggregationTesting) #define IID_IColorTesting __uuidof(IColorTesting) #define IID_ILicenseTesting __uuidof(ILicenseTesting) @@ -89,6 +92,7 @@ struct CoreShimComActivation #include "ErrorMarshalTesting.h" #include "DispatchTesting.h" #include "EventTesting.h" + #include "DispatchCoerceTesting.h" #include "AggregationTesting.h" #include "ColorTesting.h" #include "LicenseTesting.h" diff --git a/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs b/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs index 2479e6cd6f083a..f2c44e4cab4b85 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs +++ b/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs @@ -123,6 +123,25 @@ internal class DispatchTestingClass { } + /// + /// Managed definition of CoClass + /// + [ComImport] + [CoClass(typeof(DispatchCoerceTestingClass))] + [Guid("B630A508-4DA5-4C14-A7AB-618AD66B2EBF")] + internal interface DispatchCoerceTesting : Server.Contract.IDispatchCoerceTesting + { + } + + /// + /// Managed activation for CoClass + /// + [ComImport] + [Guid(Server.Contract.Guids.DispatchCoerceTesting)] + internal class DispatchCoerceTestingClass + { + } + /// /// Managed definition of CoClass /// diff --git a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs index dd0f71634e2bdc..27ee5b3bfc3db4 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs +++ b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs @@ -319,6 +319,22 @@ public interface TestingEvents void OnEvent([MarshalAs(UnmanagedType.BStr)] string msg); }; + [ComVisible(true)] + [Guid("B630A508-4DA5-4C14-A7AB-618AD66B2EBF")] + [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IDispatchCoerceTesting + { + int ReturnToManaged(short vt); + + int ManagedArgument(int arg); + + System.Reflection.Missing ReturnToManaged_Missing(); + + DBNull ReturnToManaged_DBNull(); + + string BoolToString(); + } + [ComVisible(true)] [Guid("98cc27f0-d521-4f79-8b63-e980e3a92974")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] diff --git a/src/tests/Interop/COM/ServerContracts/Server.Contracts.h b/src/tests/Interop/COM/ServerContracts/Server.Contracts.h index d2c26884589efa..719659b7ed905e 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.Contracts.h +++ b/src/tests/Interop/COM/ServerContracts/Server.Contracts.h @@ -452,6 +452,12 @@ TestingEvents : IDispatch // void OnEvent(_In_z_ BSTR t); }; +struct __declspec(uuid("b630a508-4da5-4c14-a7ab-618ad66b2ebf")) +IDispatchCoerceTesting : IDispatch +{ + // Methods should only be invoked via IDispatch +}; + struct __declspec(uuid("98cc27f0-d521-4f79-8b63-e980e3a92974")) IAggregationTesting : IUnknown { diff --git a/src/tests/Interop/COM/ServerContracts/ServerGuids.cs b/src/tests/Interop/COM/ServerContracts/ServerGuids.cs index 8b0c65a3ce1532..6c6b6569b634a7 100644 --- a/src/tests/Interop/COM/ServerContracts/ServerGuids.cs +++ b/src/tests/Interop/COM/ServerContracts/ServerGuids.cs @@ -15,6 +15,7 @@ internal sealed class Guids public const string ErrorMarshalTesting = "71CF5C45-106C-4B32-B418-43A463C6041F"; public const string DispatchTesting = "0F8ACD0C-ECE0-4F2A-BD1B-6BFCA93A0726"; public const string EventTesting = "4DBD9B61-E372-499F-84DE-EFC70AA8A009"; + public const string DispatchCoerceTesting = "661F9962-3477-416B-BE40-4CBA3190A562"; public const string AggregationTesting = "4CEFE36D-F377-4B6E-8C34-819A8BB9CB04"; public const string ColorTesting = "C222F472-DA5A-4FC6-9321-92F4F7053A65"; public const string LicenseTesting = "66DB7882-E2B0-471D-92C7-B2B52A0EA535"; From 042d3e94f23ba6300bc925dee2bc9d056c03dc50 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Sat, 4 May 2024 20:40:56 -0700 Subject: [PATCH 248/248] Arm64/Sve: Implement SVE Math Min*/Max* APIs (#101859) * Add the missing else * Max, MaxAcross, MaxNumber, MaxNumberAcross, Min, MinAcross, MinNumber, MinNumberAcross * Map APIs to instruction * Add test cases * Remove the space * fix the test case --- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 6 + src/coreclr/jit/hwintrinsiclistarm64sve.h | 8 + .../Arm/Sve.PlatformNotSupported.cs | 383 ++++++++++++++++++ .../src/System/Runtime/Intrinsics/Arm/Sve.cs | 383 ++++++++++++++++++ .../ref/System.Runtime.Intrinsics.cs | 71 +++- .../GenerateHWIntrinsicTests_Arm.cs | 56 +++ 6 files changed, 896 insertions(+), 11 deletions(-) diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index 1f7f2865631c10..6098d39e6efbc2 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -550,6 +550,12 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // and `embMaskOp2Reg` is the second operand. GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, opt); } + else + { + // Just perform the actual "predicated" operation so that `targetReg` is the first operand + // and `embMaskOp2Reg` is the second operand. + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, opt); + } break; diff --git a/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/coreclr/jit/hwintrinsiclistarm64sve.h index 7bb1789175a1a0..a2af0bec711392 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64sve.h +++ b/src/coreclr/jit/hwintrinsiclistarm64sve.h @@ -71,6 +71,14 @@ HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToUInt32, HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1h, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, Max, -1, -1, false, {INS_sve_smax, INS_sve_umax, INS_sve_smax, INS_sve_umax, INS_sve_smax, INS_sve_umax, INS_sve_smax, INS_sve_umax, INS_sve_fmax, INS_sve_fmax}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sve, MaxAcross, -1, -1, false, {INS_sve_smaxv, INS_sve_umaxv, INS_sve_smaxv, INS_sve_umaxv, INS_sve_smaxv, INS_sve_umaxv, INS_sve_smaxv, INS_sve_umaxv, INS_sve_fmaxv, INS_sve_fmaxv}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation) +HARDWARE_INTRINSIC(Sve, MaxNumber, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fmaxnm, INS_sve_fmaxnm}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sve, MaxNumberAcross, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fmaxnmv, INS_sve_fmaxnmv}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation) +HARDWARE_INTRINSIC(Sve, Min, -1, -1, false, {INS_sve_smin, INS_sve_umin, INS_sve_smin, INS_sve_umin, INS_sve_smin, INS_sve_umin, INS_sve_smin, INS_sve_umin, INS_sve_fmin, INS_sve_fmin}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sve, MinAcross, -1, -1, false, {INS_sve_sminv, INS_sve_uminv, INS_sve_sminv, INS_sve_uminv, INS_sve_sminv, INS_sve_uminv, INS_sve_sminv, INS_sve_uminv, INS_sve_fminv, INS_sve_fminv}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation) +HARDWARE_INTRINSIC(Sve, MinNumber, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fminnm, INS_sve_fminnm}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sve, MinNumberAcross, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fminnmv, INS_sve_fminnmv}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation) HARDWARE_INTRINSIC(Sve, Multiply, -1, 2, true, {INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_fmul, INS_sve_fmul}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve, Or, -1, -1, false, {INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, OrAcross, -1, -1, false, {INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs index b4f28f01193ea6..43eec348f76fc5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs @@ -1070,6 +1070,389 @@ internal Arm64() { } /// public static unsafe Vector LoadVectorUInt32ZeroExtendToUInt64(Vector mask, uint* address) { throw new PlatformNotSupportedException(); } + /// Max : Maximum + + /// + /// svuint8_t svmax[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmax[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmax[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// UMAX Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UMAX Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svmax[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmax[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmax[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMAX Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMAX Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svmax[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmax[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmax[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// SMAX Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SMAX Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svmax[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmax[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmax[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// SMAX Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SMAX Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svmax[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmax[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmax[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// SMAX Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SMAX Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svmax[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmax[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmax[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// SMAX Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SMAX Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svmax[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmax[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmax[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMAX Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMAX Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svmax[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmax[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmax[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// UMAX Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UMAX Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svmax[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmax[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmax[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// UMAX Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UMAX Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svmax[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmax[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmax[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// UMAX Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UMAX Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// MaxAcross : Maximum reduction to scalar + + /// + /// uint8_t svmaxv[_u8](svbool_t pg, svuint8_t op) + /// UMAXV Bresult, Pg, Zop.B + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// float64_t svmaxv[_f64](svbool_t pg, svfloat64_t op) + /// FMAXV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int16_t svmaxv[_s16](svbool_t pg, svint16_t op) + /// SMAXV Hresult, Pg, Zop.H + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int32_t svmaxv[_s32](svbool_t pg, svint32_t op) + /// SMAXV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svmaxv[_s64](svbool_t pg, svint64_t op) + /// SMAXV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int8_t svmaxv[_s8](svbool_t pg, svint8_t op) + /// SMAXV Bresult, Pg, Zop.B + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// float32_t svmaxv[_f32](svbool_t pg, svfloat32_t op) + /// FMAXV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t svmaxv[_u16](svbool_t pg, svuint16_t op) + /// UMAXV Hresult, Pg, Zop.H + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t svmaxv[_u32](svbool_t pg, svuint32_t op) + /// UMAXV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svmaxv[_u64](svbool_t pg, svuint64_t op) + /// UMAXV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + + /// MaxNumber : Maximum number + + /// + /// svfloat64_t svmaxnm[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmaxnm[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmaxnm[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMAXNM Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMAXNM Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector MaxNumber(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svmaxnm[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmaxnm[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmaxnm[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMAXNM Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMAXNM Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector MaxNumber(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// MaxNumberAcross : Maximum number reduction to scalar + + /// + /// float64_t svmaxnmv[_f64](svbool_t pg, svfloat64_t op) + /// FMAXNMV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxNumberAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// float32_t svmaxnmv[_f32](svbool_t pg, svfloat32_t op) + /// FMAXNMV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxNumberAcross(Vector value) { throw new PlatformNotSupportedException(); } + + + /// Min : Minimum + + /// + /// svuint8_t svmin[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmin[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmin[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// UMIN Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UMIN Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svmin[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmin[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmin[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMIN Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMIN Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svmin[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmin[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmin[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// SMIN Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SMIN Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svmin[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmin[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmin[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// SMIN Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SMIN Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svmin[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmin[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmin[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// SMIN Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SMIN Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svmin[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmin[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmin[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// SMIN Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SMIN Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svmin[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmin[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmin[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMIN Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMIN Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svmin[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmin[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmin[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// UMIN Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UMIN Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svmin[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmin[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmin[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// UMIN Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UMIN Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svmin[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmin[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmin[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// UMIN Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UMIN Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// MinAcross : Minimum reduction to scalar + + /// + /// uint8_t svminv[_u8](svbool_t pg, svuint8_t op) + /// UMINV Bresult, Pg, Zop.B + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// float64_t svminv[_f64](svbool_t pg, svfloat64_t op) + /// FMINV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int16_t svminv[_s16](svbool_t pg, svint16_t op) + /// SMINV Hresult, Pg, Zop.H + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int32_t svminv[_s32](svbool_t pg, svint32_t op) + /// SMINV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svminv[_s64](svbool_t pg, svint64_t op) + /// SMINV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int8_t svminv[_s8](svbool_t pg, svint8_t op) + /// SMINV Bresult, Pg, Zop.B + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// float32_t svminv[_f32](svbool_t pg, svfloat32_t op) + /// FMINV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t svminv[_u16](svbool_t pg, svuint16_t op) + /// UMINV Hresult, Pg, Zop.H + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t svminv[_u32](svbool_t pg, svuint32_t op) + /// UMINV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svminv[_u64](svbool_t pg, svuint64_t op) + /// UMINV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + + /// MinNumber : Minimum number + + /// + /// svfloat64_t svminnm[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svminnm[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svminnm[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMINNM Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMINNM Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector MinNumber(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svminnm[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svminnm[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svminnm[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMINNM Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMINNM Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector MinNumber(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// MinNumberAcross : Minimum number reduction to scalar + + /// + /// float64_t svminnmv[_f64](svbool_t pg, svfloat64_t op) + /// FMINNMV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinNumberAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// float32_t svminnmv[_f32](svbool_t pg, svfloat32_t op) + /// FMINNMV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinNumberAcross(Vector value) { throw new PlatformNotSupportedException(); } + /// Multiply : Multiply /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs index 39380f8a50f9aa..6814d2f8317aa7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs @@ -1127,6 +1127,389 @@ internal Arm64() { } /// public static unsafe Vector LoadVectorUInt32ZeroExtendToUInt64(Vector mask, uint* address) => LoadVectorUInt32ZeroExtendToUInt64(mask, address); + /// Max : Maximum + + /// + /// svuint8_t svmax[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmax[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmax[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// UMAX Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UMAX Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svfloat64_t svmax[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmax[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmax[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMAX Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMAX Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svint16_t svmax[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmax[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmax[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// SMAX Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SMAX Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svint32_t svmax[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmax[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmax[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// SMAX Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SMAX Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svint64_t svmax[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmax[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmax[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// SMAX Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SMAX Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svint8_t svmax[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmax[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmax[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// SMAX Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SMAX Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svfloat32_t svmax[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmax[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmax[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMAX Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMAX Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svuint16_t svmax[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmax[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmax[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// UMAX Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UMAX Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svuint32_t svmax[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmax[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmax[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// UMAX Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UMAX Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svuint64_t svmax[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmax[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmax[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// UMAX Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UMAX Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + + /// MaxAcross : Maximum reduction to scalar + + /// + /// uint8_t svmaxv[_u8](svbool_t pg, svuint8_t op) + /// UMAXV Bresult, Pg, Zop.B + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// float64_t svmaxv[_f64](svbool_t pg, svfloat64_t op) + /// FMAXV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// int16_t svmaxv[_s16](svbool_t pg, svint16_t op) + /// SMAXV Hresult, Pg, Zop.H + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// int32_t svmaxv[_s32](svbool_t pg, svint32_t op) + /// SMAXV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// int64_t svmaxv[_s64](svbool_t pg, svint64_t op) + /// SMAXV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// int8_t svmaxv[_s8](svbool_t pg, svint8_t op) + /// SMAXV Bresult, Pg, Zop.B + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// float32_t svmaxv[_f32](svbool_t pg, svfloat32_t op) + /// FMAXV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// uint16_t svmaxv[_u16](svbool_t pg, svuint16_t op) + /// UMAXV Hresult, Pg, Zop.H + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// uint32_t svmaxv[_u32](svbool_t pg, svuint32_t op) + /// UMAXV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// uint64_t svmaxv[_u64](svbool_t pg, svuint64_t op) + /// UMAXV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + + /// MaxNumber : Maximum number + + /// + /// svfloat64_t svmaxnm[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmaxnm[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmaxnm[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMAXNM Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMAXNM Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector MaxNumber(Vector left, Vector right) => MaxNumber(left, right); + + /// + /// svfloat32_t svmaxnm[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmaxnm[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmaxnm[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMAXNM Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMAXNM Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector MaxNumber(Vector left, Vector right) => MaxNumber(left, right); + + + /// MaxNumberAcross : Maximum number reduction to scalar + + /// + /// float64_t svmaxnmv[_f64](svbool_t pg, svfloat64_t op) + /// FMAXNMV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxNumberAcross(Vector value) => MaxNumberAcross(value); + + /// + /// float32_t svmaxnmv[_f32](svbool_t pg, svfloat32_t op) + /// FMAXNMV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxNumberAcross(Vector value) => MaxNumberAcross(value); + + + /// Min : Minimum + + /// + /// svuint8_t svmin[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmin[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmin[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// UMIN Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UMIN Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svfloat64_t svmin[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmin[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmin[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMIN Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMIN Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svint16_t svmin[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmin[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmin[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// SMIN Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SMIN Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svint32_t svmin[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmin[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmin[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// SMIN Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SMIN Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svint64_t svmin[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmin[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmin[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// SMIN Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SMIN Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svint8_t svmin[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmin[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmin[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// SMIN Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SMIN Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svfloat32_t svmin[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmin[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmin[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMIN Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMIN Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svuint16_t svmin[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmin[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmin[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// UMIN Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UMIN Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svuint32_t svmin[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmin[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmin[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// UMIN Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UMIN Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svuint64_t svmin[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmin[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmin[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// UMIN Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UMIN Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + + /// MinAcross : Minimum reduction to scalar + + /// + /// uint8_t svminv[_u8](svbool_t pg, svuint8_t op) + /// UMINV Bresult, Pg, Zop.B + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// float64_t svminv[_f64](svbool_t pg, svfloat64_t op) + /// FMINV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// int16_t svminv[_s16](svbool_t pg, svint16_t op) + /// SMINV Hresult, Pg, Zop.H + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// int32_t svminv[_s32](svbool_t pg, svint32_t op) + /// SMINV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// int64_t svminv[_s64](svbool_t pg, svint64_t op) + /// SMINV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// int8_t svminv[_s8](svbool_t pg, svint8_t op) + /// SMINV Bresult, Pg, Zop.B + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// float32_t svminv[_f32](svbool_t pg, svfloat32_t op) + /// FMINV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// uint16_t svminv[_u16](svbool_t pg, svuint16_t op) + /// UMINV Hresult, Pg, Zop.H + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// uint32_t svminv[_u32](svbool_t pg, svuint32_t op) + /// UMINV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// uint64_t svminv[_u64](svbool_t pg, svuint64_t op) + /// UMINV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + + /// MinNumber : Minimum number + + /// + /// svfloat64_t svminnm[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svminnm[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svminnm[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMINNM Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMINNM Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector MinNumber(Vector left, Vector right) => MinNumber(left, right); + + /// + /// svfloat32_t svminnm[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svminnm[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svminnm[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMINNM Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMINNM Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector MinNumber(Vector left, Vector right) => MinNumber(left, right); + + + /// MinNumberAcross : Minimum number reduction to scalar + + /// + /// float64_t svminnmv[_f64](svbool_t pg, svfloat64_t op) + /// FMINNMV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinNumberAcross(Vector value) => MinNumberAcross(value); + + /// + /// float32_t svminnmv[_f32](svbool_t pg, svfloat32_t op) + /// FMINNMV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinNumberAcross(Vector value) => MinNumberAcross(value); + /// /// svint8_t svmul[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index dee510b5c22eb8..e4f5e1d215802d 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -4308,6 +4308,66 @@ internal Arm64() { } public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendToInt64(System.Numerics.Vector mask, uint* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendToUInt64(System.Numerics.Vector mask, uint* address) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxNumber(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MaxNumber(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MaxNumberAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxNumberAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinNumber(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MinNumber(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MinNumberAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinNumberAcross(System.Numerics.Vector value) { throw null; } + + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -4351,17 +4411,6 @@ internal Arm64() { } public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } diff --git a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs index 0713ac24af2110..5701becf7c486c 100644 --- a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs +++ b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs @@ -3027,6 +3027,62 @@ ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt32ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt32ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxNumber_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxNumber", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxNumber_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxNumber", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxNumberAcross_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxNumberAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxNumberAcross_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxNumberAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_MinNumber_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinNumber", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_MinNumber_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinNumber", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinNumberAcross_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinNumberAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinNumberAcross_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinNumberAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}),