From cc5577778d101507dc0a9210ce2ec18f3868af29 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Thu, 24 Oct 2024 23:29:50 +0000 Subject: [PATCH 1/4] Fix stack overflow in CompilerGeneratedState --- .../Linker.Dataflow/CompilerGeneratedState.cs | 4 +- ...MultipleMethodsUseSameAsyncStateMachine.il | 123 ++++++++++++++++++ ...MultipleMethodsUseSameAsyncStateMachine.cs | 27 ++++ 3 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Dependencies/MultipleMethodsUseSameAsyncStateMachine.il create mode 100644 src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/MultipleMethodsUseSameAsyncStateMachine.cs diff --git a/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs b/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs index d246e4a6c54e1d..5cc98b4479fb02 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs @@ -122,7 +122,7 @@ public static bool TryGetStateMachineType (MethodDefinition method, [NotNullWhen return null; // Avoid repeat scans of the same type - if (_cachedTypeToCompilerGeneratedMembers.ContainsKey (type)) + if (!_cachedTypeToCompilerGeneratedMembers.TryAdd (type, null)) return type; var callGraph = new CompilerGeneratedCallGraph (); @@ -297,7 +297,7 @@ referencedMethod.DeclaringType is var generatedType && } } - _cachedTypeToCompilerGeneratedMembers.Add (type, compilerGeneratedCallees); + _cachedTypeToCompilerGeneratedMembers[type] = compilerGeneratedCallees; return type; /// diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Dependencies/MultipleMethodsUseSameAsyncStateMachine.il b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Dependencies/MultipleMethodsUseSameAsyncStateMachine.il new file mode 100644 index 00000000000000..2cccc0af884aab --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Dependencies/MultipleMethodsUseSameAsyncStateMachine.il @@ -0,0 +1,123 @@ +.assembly extern System.Runtime +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) +} + +.assembly 'library' +{ + .hash algorithm 0x00008004 + .ver 1:0:0:0 +} + +.namespace Mono.Linker.Tests.Cases.Warnings.Dependencies +{ + .class public auto ansi beforefieldinit MultipleMethodsUseSameAsyncStateMachine + extends [System.Runtime]System.Object + { + // Nested Types + .class nested public sequential ansi sealed beforefieldinit 'd' + extends [System.Runtime]System.ValueType + implements [System.Runtime]System.Runtime.CompilerServices.IAsyncStateMachine + { + // Fields + .field public static int32 'field' + + // Methods + .method public final hidebysig newslot virtual + instance void MoveNext () cil managed + { + // Method begins at RVA 0x207a + // Code size 9 (0x9) + .maxstack 8 + + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.1 + IL_0003: stfld int32 Mono.Linker.Tests.Cases.Warnings.Dependencies.MultipleMethodsUseSameAsyncStateMachine/'d'::'field' + IL_0008: ret + } // end of method 'd'::MoveNext + + .method private final hidebysig newslot virtual + instance void System.Runtime.CompilerServices.IAsyncStateMachine.SetStateMachine ( + class [System.Runtime]System.Runtime.CompilerServices.IAsyncStateMachine stateMachine + ) cil managed + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( + 01 00 01 00 00 + ) + .override method instance void [System.Runtime]System.Runtime.CompilerServices.IAsyncStateMachine::SetStateMachine(class [System.Runtime]System.Runtime.CompilerServices.IAsyncStateMachine) + // Method begins at RVA 0x2050 + // Code size 2 (0x2) + .maxstack 8 + + IL_0000: nop + IL_0001: ret + } // end of method 'd'::System.Runtime.CompilerServices.IAsyncStateMachine.SetStateMachine + + } // end of class 'd' + + + // Methods + .method public hidebysig static + void M () cil managed + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.AsyncStateMachineAttribute::.ctor(class [System.Runtime]System.Type) = ( + 01 00 65 4D 6F 6E 6F 2E 4C 69 6E 6B 65 72 2E 54 + 65 73 74 73 2E 43 61 73 65 73 2E 57 61 72 6E 69 + 6E 67 73 2E 44 65 70 65 6E 64 65 6E 63 69 65 73 + 2E 4D 75 6C 74 69 70 6C 65 4D 65 74 68 6F 64 73 + 55 73 65 53 61 6D 65 41 73 79 6E 63 53 74 61 74 + 65 4D 61 63 68 69 6E 65 2B 3C 53 74 61 74 65 4D + 61 63 68 69 6E 65 3E 64 00 00 + ) + .maxstack 8 + + IL_0000: call void Mono.Linker.Tests.Cases.Warnings.Dependencies.MultipleMethodsUseSameAsyncStateMachine::'g__LocalFunction'() + IL_0005: ret + } // end of method MultipleMethodsUseSameAsyncStateMachine::M + + .method public hidebysig static + void 'g__LocalFunction' () cil managed + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.AsyncStateMachineAttribute::.ctor(class [System.Runtime]System.Type) = ( + 01 00 65 4D 6F 6E 6F 2E 4C 69 6E 6B 65 72 2E 54 + 65 73 74 73 2E 43 61 73 65 73 2E 57 61 72 6E 69 + 6E 67 73 2E 44 65 70 65 6E 64 65 6E 63 69 65 73 + 2E 4D 75 6C 74 69 70 6C 65 4D 65 74 68 6F 64 73 + 55 73 65 53 61 6D 65 41 73 79 6E 63 53 74 61 74 + 65 4D 61 63 68 69 6E 65 2B 3C 53 74 61 74 65 4D + 61 63 68 69 6E 65 3E 64 00 00 + ) + .maxstack 2 + .locals init ( + [0] valuetype Mono.Linker.Tests.Cases.Warnings.Dependencies.MultipleMethodsUseSameAsyncStateMachine/'d' s + ) + + IL_0000: nop + IL_0001: ldloca.s 0 + IL_0003: initobj Mono.Linker.Tests.Cases.Warnings.Dependencies.MultipleMethodsUseSameAsyncStateMachine/'d' + IL_0009: ldloca.s 0 + IL_000b: ldc.i4.0 + IL_000c: stfld int32 Mono.Linker.Tests.Cases.Warnings.Dependencies.MultipleMethodsUseSameAsyncStateMachine/'d'::'field' + IL_0011: ldloca.s 0 + IL_0013: call instance void Mono.Linker.Tests.Cases.Warnings.Dependencies.MultipleMethodsUseSameAsyncStateMachine/'d'::MoveNext() + IL_0018: nop + IL_0019: ret + } // end of method MultipleMethodsUseSameAsyncStateMachine::'g__LocalFunction' + + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + // Method begins at RVA 0x2053 + // Code size 8 (0x8) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: call instance void [System.Runtime]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method MultipleMethodsUseSameAsyncStateMachine::.ctor + + } // end of class Mono.Linker.Tests.Cases.Warnings.Dependencies.MultipleMethodsUseSameAsyncStateMachine + +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/MultipleMethodsUseSameAsyncStateMachine.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/MultipleMethodsUseSameAsyncStateMachine.cs new file mode 100644 index 00000000000000..a8767d6cfba3de --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/MultipleMethodsUseSameAsyncStateMachine.cs @@ -0,0 +1,27 @@ +// 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.Linq; +using System.Text; +using System.Threading.Tasks; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.Warnings +{ + [Define ("IL_ASSEMBLY_AVAILABLE")] + [SetupCompileBefore ("library.dll", new[] { "Dependencies/MultipleMethodsUseSameAsyncStateMachine.il" })] + [ExpectedNoWarnings] + [LogContains ("IL2107.*g__LocalFunction().*M().*both associated with state machine type.*d", regexMatch: true)] + class MultipleMethodsUseSameAsyncStateMachine + { + public static void Main () + { +#if IL_ASSEMBLY_AVAILABLE + Dependencies.MultipleMethodsUseSameAsyncStateMachine.M(); +#endif + } + } +} From 7489de59550297d1802176398344cc29567db148 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Thu, 24 Oct 2024 23:30:01 +0000 Subject: [PATCH 2/4] Trigger stack overflow in ILC --- .../MultipleMethodsUseSameAsyncStateMachine.il | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Dependencies/MultipleMethodsUseSameAsyncStateMachine.il b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Dependencies/MultipleMethodsUseSameAsyncStateMachine.il index 2cccc0af884aab..087e3e42890396 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Dependencies/MultipleMethodsUseSameAsyncStateMachine.il +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Dependencies/MultipleMethodsUseSameAsyncStateMachine.il @@ -72,10 +72,24 @@ ) .maxstack 8 - IL_0000: call void Mono.Linker.Tests.Cases.Warnings.Dependencies.MultipleMethodsUseSameAsyncStateMachine::'g__LocalFunction'() - IL_0005: ret + IL_0000: call void Mono.Linker.Tests.Cases.Warnings.Dependencies.MultipleMethodsUseSameAsyncStateMachine::RUC(); + IL_0005: call void Mono.Linker.Tests.Cases.Warnings.Dependencies.MultipleMethodsUseSameAsyncStateMachine::'g__LocalFunction'() + IL_000a: ret } // end of method MultipleMethodsUseSameAsyncStateMachine::M + .method private hidebysig static + void RUC () cil managed + { + .custom instance void [System.Runtime]System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute::.ctor(string) = ( + 01 00 03 52 55 43 00 00 + ) + // Method begins at RVA 0x205c + // Code size 1 (0x1) + .maxstack 8 + + IL_0000: ret + } // end of method MultipleMethodsUseSameAsyncStateMachine::RUC + .method public hidebysig static void 'g__LocalFunction' () cil managed { From 6ab32838c436295db51e72247f4c92f7c59e83a1 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Mon, 6 Jan 2025 19:53:34 +0000 Subject: [PATCH 3/4] Fix issue same way for ILC and ILLink Delay processing of warnings from building compiler-generated type info --- .../Dataflow/CompilerGeneratedState.cs | 63 ++++++++++++++++--- .../Linker.Dataflow/CompilerGeneratedState.cs | 27 ++++++-- 2 files changed, 74 insertions(+), 16 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs index def7db6138c99c..72a5e29b285880 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs @@ -29,17 +29,19 @@ private readonly record struct TypeArgumentInfo( private readonly TypeCacheHashtable _typeCacheHashtable; + private readonly Logger _logger; + public CompilerGeneratedState(ILProvider ilProvider, Logger logger) { - _typeCacheHashtable = new TypeCacheHashtable(ilProvider, logger); + _typeCacheHashtable = new TypeCacheHashtable(ilProvider); + _logger = logger; } private sealed class TypeCacheHashtable : LockFreeReaderHashtable { private ILProvider _ilProvider; - private Logger? _logger; - public TypeCacheHashtable(ILProvider ilProvider, Logger logger) => (_ilProvider, _logger) = (ilProvider, logger); + public TypeCacheHashtable(ILProvider ilProvider) => _ilProvider = ilProvider; protected override bool CompareKeyToValue(MetadataType key, TypeCache value) => key == value.Type; protected override bool CompareValueToValue(TypeCache value1, TypeCache value2) => value1.Type == value2.Type; @@ -47,7 +49,27 @@ private sealed class TypeCacheHashtable : LockFreeReaderHashtable value.Type.GetHashCode(); protected override TypeCache CreateValueFromKey(MetadataType key) - => new TypeCache(key, _logger, _ilProvider); + => new TypeCache(key, _ilProvider); + + public TypeCache GetOrCreateValue(MetadataType key, out bool created) + { + TypeCache existingValue; + created = false; + if (TryGetValue(key, out existingValue)) + return existingValue; + + var newValue = CreateValueFromKey(key); + if (TryAdd(newValue)) + { + created = true; + return newValue; + } + + if (!TryGetValue(key, out existingValue)) + throw new InvalidOperationException(); + + return existingValue; + } } private sealed class TypeCache @@ -64,6 +86,18 @@ private sealed class TypeCache // or null if the type has no methods with compiler-generated members. private Dictionary>? _compilerGeneratedMembers; + // Stores a list of warnings to be emitted at the end of the cache construction + private List<(MessageOrigin, DiagnosticId, string[])>? _warnings; + + internal void LogWarnings(Logger? logger) + { + if (_warnings == null || logger == null) + return; + + foreach (var (origin, id, messageArgs) in _warnings) + logger.LogWarning(origin, id, messageArgs); + } + /// /// Walks the type and its descendents to find Roslyn-compiler generated /// code and gather information to map it back to original user code. If @@ -71,7 +105,7 @@ private sealed class TypeCache /// up and find the nearest containing user type. Returns the nearest user type, /// or null if none was found. /// - internal TypeCache(MetadataType type, Logger? logger, ILProvider ilProvider) + internal TypeCache(MetadataType type, ILProvider ilProvider) { Debug.Assert(type == type.GetTypeDefinition()); Debug.Assert(!CompilerGeneratedNames.IsStateMachineOrDisplayClass(type.Name)); @@ -82,6 +116,12 @@ internal TypeCache(MetadataType type, Logger? logger, ILProvider ilProvider) var userDefinedMethods = new HashSet(); var generatedTypeToTypeArgs = new Dictionary(); + void AddWarning(MessageOrigin origin, DiagnosticId id, params string[] messageArgs) + { + _warnings ??= new List<(MessageOrigin, DiagnosticId, string[])>(); + _warnings.Add((origin, id, messageArgs)); + } + void ProcessMethod(MethodDesc method) { Debug.Assert(method == method.GetTypicalMethodDefinition()); @@ -139,7 +179,7 @@ referencedMethod.OwningType is MetadataType generatedType && if (!generatedTypeToTypeArgs.TryAdd(generatedType, new TypeArgumentInfo(method, null))) { var alreadyAssociatedMethod = generatedTypeToTypeArgs[generatedType].CreatingMethod; - logger?.LogWarning(new MessageOrigin(method), DiagnosticId.MethodsAreAssociatedWithUserMethod, method.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), generatedType.GetDisplayName()); + AddWarning(new MessageOrigin(method), DiagnosticId.MethodsAreAssociatedWithUserMethod, method.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), generatedType.GetDisplayName()); } continue; } @@ -207,7 +247,7 @@ referencedMethod.OwningType is MetadataType generatedType && if (!_compilerGeneratedTypeToUserCodeMethod.TryAdd(stateMachineType, method)) { var alreadyAssociatedMethod = _compilerGeneratedTypeToUserCodeMethod[stateMachineType]; - logger?.LogWarning(new MessageOrigin(method), DiagnosticId.MethodsAreAssociatedWithStateMachine, method.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), stateMachineType.GetDisplayName()); + AddWarning(new MessageOrigin(method), DiagnosticId.MethodsAreAssociatedWithStateMachine, method.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), stateMachineType.GetDisplayName()); } // Already warned above if multiple methods map to the same type // Fill in null for argument providers now, the real providers will be filled in later @@ -263,7 +303,7 @@ referencedMethod.OwningType is MetadataType generatedType && if (!_compilerGeneratedMethodToUserCodeMethod.TryAdd(nestedFunction, userDefinedMethod)) { var alreadyAssociatedMethod = _compilerGeneratedMethodToUserCodeMethod[nestedFunction]; - logger?.LogWarning(new MessageOrigin(userDefinedMethod), DiagnosticId.MethodsAreAssociatedWithUserMethod, userDefinedMethod.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), nestedFunction.GetDisplayName()); + AddWarning(new MessageOrigin(userDefinedMethod), DiagnosticId.MethodsAreAssociatedWithUserMethod, userDefinedMethod.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), nestedFunction.GetDisplayName()); } break; case MetadataType stateMachineType: @@ -295,7 +335,7 @@ referencedMethod.OwningType is MetadataType generatedType && { var method = info.CreatingMethod; var alreadyAssociatedMethod = _generatedTypeToTypeArgumentInfo[generatedType].CreatingMethod; - logger?.LogWarning(new MessageOrigin(method), DiagnosticId.MethodsAreAssociatedWithUserMethod, method.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), generatedType.GetDisplayName()); + AddWarning(new MessageOrigin(method), DiagnosticId.MethodsAreAssociatedWithUserMethod, method.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), generatedType.GetDisplayName()); } } } @@ -575,7 +615,10 @@ public static bool TryGetStateMachineType(MethodDesc method, [NotNullWhen(true)] if (userType is null) return null; - return _typeCacheHashtable.GetOrCreateValue(userType); + var typeCache = _typeCacheHashtable.GetOrCreateValue(userType, out bool created); + if (created) + typeCache.LogWarnings(_logger); + return typeCache; } private static TypeDesc? GetFirstConstructorArgumentAsType(CustomAttributeValue attribute) diff --git a/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs b/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs index 5cc98b4479fb02..2539ec02aebc4a 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs @@ -122,13 +122,21 @@ public static bool TryGetStateMachineType (MethodDefinition method, [NotNullWhen return null; // Avoid repeat scans of the same type - if (!_cachedTypeToCompilerGeneratedMembers.TryAdd (type, null)) + if (_cachedTypeToCompilerGeneratedMembers.ContainsKey (type)) return type; var callGraph = new CompilerGeneratedCallGraph (); var userDefinedMethods = new HashSet (); var generatedTypeToTypeArgs = new Dictionary (); + List<(MessageOrigin, DiagnosticId, string[])>? _warnings = null; + + void AddWarning (MessageOrigin origin, DiagnosticId id, params string[] messageArgs) + { + _warnings ??= new List<(MessageOrigin, DiagnosticId, string[])> (); + _warnings.Add ((origin, id, messageArgs)); + } + void ProcessMethod (MethodDefinition method) { bool isStateMachineMember = CompilerGeneratedNames.IsStateMachineType (method.DeclaringType.Name); @@ -163,7 +171,7 @@ referencedMethod.DeclaringType is var generatedType && // fill in null for now, attribute providers will be filled in later if (!generatedTypeToTypeArgs.TryAdd (generatedType, new TypeArgumentInfo (method, null))) { var alreadyAssociatedMethod = generatedTypeToTypeArgs[generatedType].CreatingMethod; - _context.LogWarning (new MessageOrigin (method), DiagnosticId.MethodsAreAssociatedWithUserMethod, method.GetDisplayName (), alreadyAssociatedMethod.GetDisplayName (), generatedType.GetDisplayName ()); + AddWarning (new MessageOrigin (method), DiagnosticId.MethodsAreAssociatedWithUserMethod, method.GetDisplayName (), alreadyAssociatedMethod.GetDisplayName (), generatedType.GetDisplayName ()); } continue; } @@ -214,7 +222,7 @@ referencedMethod.DeclaringType is var generatedType && if (!_compilerGeneratedTypeToUserCodeMethod.TryAdd (stateMachineType, method)) { var alreadyAssociatedMethod = _compilerGeneratedTypeToUserCodeMethod[stateMachineType]; - _context.LogWarning (new MessageOrigin (method), DiagnosticId.MethodsAreAssociatedWithStateMachine, method.GetDisplayName (), alreadyAssociatedMethod.GetDisplayName (), stateMachineType.GetDisplayName ()); + AddWarning (new MessageOrigin (method), DiagnosticId.MethodsAreAssociatedWithStateMachine, method.GetDisplayName (), alreadyAssociatedMethod.GetDisplayName (), stateMachineType.GetDisplayName ()); } // Already warned above if multiple methods map to the same type // Fill in null for argument providers now, the real providers will be filled in later @@ -265,7 +273,7 @@ referencedMethod.DeclaringType is var generatedType && // Nested functions get suppressions from the user method only. if (!_compilerGeneratedMethodToUserCodeMethod.TryAdd (nestedFunction, userDefinedMethod)) { var alreadyAssociatedMethod = _compilerGeneratedMethodToUserCodeMethod[nestedFunction]; - _context.LogWarning (new MessageOrigin (userDefinedMethod), DiagnosticId.MethodsAreAssociatedWithUserMethod, userDefinedMethod.GetDisplayName (), alreadyAssociatedMethod.GetDisplayName (), nestedFunction.GetDisplayName ()); + AddWarning (new MessageOrigin (userDefinedMethod), DiagnosticId.MethodsAreAssociatedWithUserMethod, userDefinedMethod.GetDisplayName (), alreadyAssociatedMethod.GetDisplayName (), nestedFunction.GetDisplayName ()); } break; case TypeDefinition stateMachineType: @@ -292,12 +300,19 @@ referencedMethod.DeclaringType is var generatedType && if (!_generatedTypeToTypeArgumentInfo.TryAdd (generatedType, info)) { var method = info.CreatingMethod; var alreadyAssociatedMethod = _generatedTypeToTypeArgumentInfo[generatedType].CreatingMethod; - _context.LogWarning (new MessageOrigin (method), DiagnosticId.MethodsAreAssociatedWithUserMethod, method.GetDisplayName (), alreadyAssociatedMethod.GetDisplayName (), generatedType.GetDisplayName ()); + AddWarning (new MessageOrigin (method), DiagnosticId.MethodsAreAssociatedWithUserMethod, method.GetDisplayName (), alreadyAssociatedMethod.GetDisplayName (), generatedType.GetDisplayName ()); } } } - _cachedTypeToCompilerGeneratedMembers[type] = compilerGeneratedCallees; + _cachedTypeToCompilerGeneratedMembers.Add (type, compilerGeneratedCallees); + + if (_warnings != null) { + foreach (var (origin, id, messageArgs) in _warnings) { + _context.LogWarning (origin, id, messageArgs); + } + } + return type; /// From 59f8df7644bf6ddf09fae5a6e093460d9608b5bc Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Wed, 8 Jan 2025 23:06:54 +0000 Subject: [PATCH 4/4] PR feedback --- .../Compiler/Dataflow/CompilerGeneratedState.cs | 3 +++ .../src/linker/Linker.Dataflow/CompilerGeneratedState.cs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs index 72a5e29b285880..24707c75f8c293 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs @@ -116,6 +116,9 @@ internal TypeCache(MetadataType type, ILProvider ilProvider) var userDefinedMethods = new HashSet(); var generatedTypeToTypeArgs = new Dictionary(); + // We delay actually logging the warnings until the compiler-generated type info is + // populated for this type, because the type info is needed to determine whether a warning + // is suppressed. void AddWarning(MessageOrigin origin, DiagnosticId id, params string[] messageArgs) { _warnings ??= new List<(MessageOrigin, DiagnosticId, string[])>(); diff --git a/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs b/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs index 2539ec02aebc4a..8f6ca7356dcf4f 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs @@ -131,6 +131,9 @@ public static bool TryGetStateMachineType (MethodDefinition method, [NotNullWhen List<(MessageOrigin, DiagnosticId, string[])>? _warnings = null; + // We delay actually logging the warnings until the compiler-generated type info is + // populated for this type, because the type info is needed to determine whether a warning + // is suppressed. void AddWarning (MessageOrigin origin, DiagnosticId id, params string[] messageArgs) { _warnings ??= new List<(MessageOrigin, DiagnosticId, string[])> ();