diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs index 63dc6aca117670..c7df8e767d0899 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs @@ -901,7 +901,7 @@ Stack currentStack ParameterProxy param = new(methodBody.OwningMethod, paramNum); var targetValue = GetMethodParameterValue(param); if (targetValue is MethodParameterValue targetParameterValue) - HandleStoreParameter(methodBody, offset, targetParameterValue, valueToStore.Value); + HandleStoreParameter(methodBody, offset, targetParameterValue, valueToStore.Value, null); // If the targetValue is MethodThisValue do nothing - it should never happen really, and if it does, there's nothing we can track there } @@ -1007,7 +1007,7 @@ private void ScanIndirectStore( StackSlot valueToStore = PopUnknown(currentStack, 1, methodBody, offset); StackSlot destination = PopUnknown(currentStack, 1, methodBody, offset); - StoreInReference(destination.Value, valueToStore.Value, methodBody, offset, locals, curBasicBlock, ref ipState); + StoreInReference(destination.Value, valueToStore.Value, methodBody, offset, locals, curBasicBlock, ref ipState, null); } /// @@ -1018,7 +1018,7 @@ private void ScanIndirectStore( /// The method body that contains the operation causing the store /// The instruction offset causing the store /// Throws if is not a valid target for an indirect store. - protected void StoreInReference(MultiValue target, MultiValue source, MethodIL method, int offset, ValueBasicBlockPair?[] locals, int curBasicBlock, ref InterproceduralState ipState) + protected void StoreInReference(MultiValue target, MultiValue source, MethodIL method, int offset, ValueBasicBlockPair?[] locals, int curBasicBlock, ref InterproceduralState ipState, int? parameterIndex) { foreach (var value in target.AsEnumerable ()) { @@ -1029,18 +1029,18 @@ protected void StoreInReference(MultiValue target, MultiValue source, MethodIL m break; case FieldReferenceValue fieldReference when HandleGetField(method, offset, fieldReference.FieldDefinition).AsSingleValue() is FieldValue fieldValue: - HandleStoreField(method, offset, fieldValue, source); + HandleStoreField(method, offset, fieldValue, source, parameterIndex); break; case ParameterReferenceValue parameterReference when GetMethodParameterValue(parameterReference.Parameter) is MethodParameterValue parameterValue: - HandleStoreParameter(method, offset, parameterValue, source); + HandleStoreParameter(method, offset, parameterValue, source, parameterIndex); break; case MethodReturnValue methodReturnValue: // Ref returns don't have special ReferenceValue values, so assume if the target here is a MethodReturnValue then it must be a ref return value HandleReturnValue(method, offset, methodReturnValue, source); break; case FieldValue fieldValue: - HandleStoreField(method, offset, fieldValue, DereferenceValue(method, offset, source, locals, ref ipState)); + HandleStoreField(method, offset, fieldValue, DereferenceValue(method, offset, source, locals, ref ipState), parameterIndex); break; case IValueWithStaticType valueWithStaticType: if (valueWithStaticType.StaticType is not null && FlowAnnotations.IsTypeInterestingForDataflow(valueWithStaticType.StaticType.Value.Type)) @@ -1108,11 +1108,11 @@ private void ScanLdfld( currentStack.Push(new StackSlot(value)); } - protected virtual void HandleStoreField(MethodIL method, int offset, FieldValue field, MultiValue valueToStore) + protected virtual void HandleStoreField(MethodIL method, int offset, FieldValue field, MultiValue valueToStore, int? parameterIndex) { } - protected virtual void HandleStoreParameter(MethodIL method, int offset, MethodParameterValue parameter, MultiValue valueToStore) + protected virtual void HandleStoreParameter(MethodIL method, int offset, MethodParameterValue parameter, MultiValue valueToStore, int? parameterIndex) { } @@ -1149,7 +1149,7 @@ private void ScanStfld( // Incomplete handling of ref fields -- if we're storing a reference to a value, pretend it's just the value MultiValue valueToStore = DereferenceValue(methodBody, offset, valueToStoreSlot.Value, locals, ref interproceduralState); - HandleStoreField(methodBody, offset, fieldValue, valueToStore); + HandleStoreField(methodBody, offset, fieldValue, valueToStore, null); } } @@ -1241,7 +1241,7 @@ protected void AssignRefAndOutParameters( if (parameter.GetReferenceKind() is not (ReferenceKind.Ref or ReferenceKind.Out)) continue; var newByRefValue = _annotations.GetMethodParameterValue(parameter); - StoreInReference(methodArguments[(int)parameter.Index], newByRefValue, callingMethodBody, offset, locals, curBasicBlock, ref ipState); + StoreInReference(methodArguments[(int)parameter.Index], newByRefValue, callingMethodBody, offset, locals, curBasicBlock, ref ipState, parameter.Index.Index); } } 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 31646035ff8b2b..ce3493118082a9 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs @@ -208,23 +208,23 @@ protected override MultiValue HandleGetField(MethodIL methodBody, int offset, Fi return _annotations.GetFieldValue(field); } - private void HandleStoreValueWithDynamicallyAccessedMembers(MethodIL methodBody, int offset, ValueWithDynamicallyAccessedMembers targetValue, MultiValue sourceValue, string reason) + private void HandleStoreValueWithDynamicallyAccessedMembers(MethodIL methodBody, int offset, ValueWithDynamicallyAccessedMembers targetValue, MultiValue sourceValue, int? parameterIndex, string reason) { if (targetValue.DynamicallyAccessedMemberTypes != 0) { _origin = _origin.WithInstructionOffset(methodBody, offset); - TrimAnalysisPatterns.Add(new TrimAnalysisAssignmentPattern(sourceValue, targetValue, _origin, reason)); + TrimAnalysisPatterns.Add(new TrimAnalysisAssignmentPattern(sourceValue, targetValue, _origin, parameterIndex, reason)); } } - protected override void HandleStoreField(MethodIL methodBody, int offset, FieldValue field, MultiValue valueToStore) - => HandleStoreValueWithDynamicallyAccessedMembers(methodBody, offset, field, valueToStore, field.Field.GetDisplayName()); + protected override void HandleStoreField(MethodIL methodBody, int offset, FieldValue field, MultiValue valueToStore, int? parameterIndex) + => HandleStoreValueWithDynamicallyAccessedMembers(methodBody, offset, field, valueToStore, parameterIndex, field.Field.GetDisplayName()); - protected override void HandleStoreParameter(MethodIL methodBody, int offset, MethodParameterValue parameter, MultiValue valueToStore) - => HandleStoreValueWithDynamicallyAccessedMembers(methodBody, offset, parameter, valueToStore, parameter.Parameter.Method.GetDisplayName()); + protected override void HandleStoreParameter(MethodIL methodBody, int offset, MethodParameterValue parameter, MultiValue valueToStore, int? parameterIndex) + => HandleStoreValueWithDynamicallyAccessedMembers(methodBody, offset, parameter, valueToStore, parameterIndex, parameter.Parameter.Method.GetDisplayName()); protected override void HandleReturnValue(MethodIL methodBody, int offset, MethodReturnValue returnValue, MultiValue valueToStore) - => HandleStoreValueWithDynamicallyAccessedMembers(methodBody, offset, returnValue, valueToStore, returnValue.Method.GetDisplayName()); + => HandleStoreValueWithDynamicallyAccessedMembers(methodBody, offset, returnValue, valueToStore, null, returnValue.Method.GetDisplayName()); protected override void HandleTypeTokenAccess(MethodIL methodBody, int offset, TypeDesc accessedType) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisAssignmentPattern.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisAssignmentPattern.cs index afb09e131a31de..2f44acb76c90b6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisAssignmentPattern.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisAssignmentPattern.cs @@ -18,24 +18,31 @@ public readonly record struct TrimAnalysisAssignmentPattern public MultiValue Source { get; init; } public MultiValue Target { get; init; } public MessageOrigin Origin { get; init; } + + // For assignment of a method parameter, we store the parameter index to disambiguate + // assignments from different out parameters of a single method call. + public int? ParameterIndex { get; init; } internal string Reason { get; init; } - internal TrimAnalysisAssignmentPattern(MultiValue source, MultiValue target, MessageOrigin origin, string reason) + internal TrimAnalysisAssignmentPattern(MultiValue source, MultiValue target, MessageOrigin origin, int? parameterIndex, string reason) { Source = source.DeepCopy(); Target = target.DeepCopy(); Origin = origin; + ParameterIndex = parameterIndex; Reason = reason; } public TrimAnalysisAssignmentPattern Merge(ValueSetLattice lattice, TrimAnalysisAssignmentPattern other) { Debug.Assert(Origin == other.Origin); + Debug.Assert(ParameterIndex == other.ParameterIndex); return new TrimAnalysisAssignmentPattern( lattice.Meet(Source, other.Source), lattice.Meet(Target, other.Target), Origin, + ParameterIndex, Reason); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisPatternStore.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisPatternStore.cs index 76bc92cf80e4c7..9293fdd7e87b61 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisPatternStore.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisPatternStore.cs @@ -13,7 +13,7 @@ namespace ILCompiler.Dataflow { public readonly struct TrimAnalysisPatternStore { - private readonly Dictionary AssignmentPatterns; + private readonly Dictionary<(MessageOrigin, int?), TrimAnalysisAssignmentPattern> AssignmentPatterns; private readonly Dictionary MethodCallPatterns; private readonly Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisTokenAccessPattern> TokenAccessPatterns; private readonly Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisGenericInstantiationAccessPattern> GenericInstantiations; @@ -23,7 +23,7 @@ public readonly struct TrimAnalysisPatternStore public TrimAnalysisPatternStore(ValueSetLattice lattice, Logger logger) { - AssignmentPatterns = new Dictionary(); + AssignmentPatterns = new Dictionary<(MessageOrigin, int?), TrimAnalysisAssignmentPattern>(); MethodCallPatterns = new Dictionary(); TokenAccessPatterns = new Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisTokenAccessPattern>(); GenericInstantiations = new Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisGenericInstantiationAccessPattern>(); @@ -34,13 +34,14 @@ public TrimAnalysisPatternStore(ValueSetLattice lattice, Logger log public void Add(TrimAnalysisAssignmentPattern pattern) { - if (!AssignmentPatterns.TryGetValue(pattern.Origin, out var existingPattern)) + var key = (pattern.Origin, pattern.ParameterIndex); + if (!AssignmentPatterns.TryGetValue(key, out var existingPattern)) { - AssignmentPatterns.Add(pattern.Origin, pattern); + AssignmentPatterns.Add(key, pattern); return; } - AssignmentPatterns[pattern.Origin] = pattern.Merge(Lattice, existingPattern); + AssignmentPatterns[key] = pattern.Merge(Lattice, existingPattern); } public void Add(TrimAnalysisMethodCallPattern pattern) diff --git a/src/tools/illink/src/linker/Linker.Dataflow/MethodBodyScanner.cs b/src/tools/illink/src/linker/Linker.Dataflow/MethodBodyScanner.cs index cb8869f40dd993..9f939bef8f40ec 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/MethodBodyScanner.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/MethodBodyScanner.cs @@ -750,7 +750,7 @@ private void ScanStarg ( ParameterProxy param = new (thisMethod, paramNum); var targetValue = GetMethodParameterValue (param); if (targetValue is MethodParameterValue targetParameterValue) - HandleStoreParameter (thisMethod, targetParameterValue, operation, valueToStore.Value); + HandleStoreParameter (thisMethod, targetParameterValue, operation, valueToStore.Value, null); // If the targetValue is MethodThisValue do nothing - it should never happen really, and if it does, there's nothing we can track there } @@ -846,7 +846,7 @@ private void ScanIndirectStore ( StackSlot valueToStore = PopUnknown (currentStack, 1, methodBody, operation.Offset); StackSlot destination = PopUnknown (currentStack, 1, methodBody, operation.Offset); - StoreInReference (destination.Value, valueToStore.Value, methodBody.Method, operation, locals, curBasicBlock, ref ipState); + StoreInReference (destination.Value, valueToStore.Value, methodBody.Method, operation, locals, curBasicBlock, ref ipState, null); } /// @@ -856,8 +856,9 @@ private void ScanIndirectStore ( /// The value to store /// The method body that contains the operation causing the store /// The instruction causing the store + /// For assignment due to a call to a method with out params, the index of the out parameter. /// Throws if is not a valid target for an indirect store. - protected void StoreInReference (MultiValue target, MultiValue source, MethodDefinition method, Instruction operation, LocalVariableStore locals, int curBasicBlock, ref InterproceduralState ipState) + protected void StoreInReference (MultiValue target, MultiValue source, MethodDefinition method, Instruction operation, LocalVariableStore locals, int curBasicBlock, ref InterproceduralState ipState, int? parameterIndex) { foreach (var value in target.AsEnumerable ()) { switch (value) { @@ -866,18 +867,18 @@ protected void StoreInReference (MultiValue target, MultiValue source, MethodDef break; case FieldReferenceValue fieldReference when GetFieldValue (fieldReference.FieldDefinition).AsSingleValue () is FieldValue fieldValue: - HandleStoreField (method, fieldValue, operation, source); + HandleStoreField (method, fieldValue, operation, source, parameterIndex); break; case ParameterReferenceValue parameterReference when GetMethodParameterValue (parameterReference.Parameter) is MethodParameterValue parameterValue: - HandleStoreParameter (method, parameterValue, operation, source); + HandleStoreParameter (method, parameterValue, operation, source, parameterIndex); break; case MethodReturnValue methodReturnValue: // Ref returns don't have special ReferenceValue values, so assume if the target here is a MethodReturnValue then it must be a ref return value HandleReturnValue (method, methodReturnValue, operation, source); break; case FieldValue fieldValue: - HandleStoreField (method, fieldValue, operation, DereferenceValue (source, locals, ref ipState)); + HandleStoreField (method, fieldValue, operation, DereferenceValue (source, locals, ref ipState), parameterIndex); break; case IValueWithStaticType valueWithStaticType: if (valueWithStaticType.StaticType is not null && _context.Annotations.FlowAnnotations.IsTypeInterestingForDataflow (valueWithStaticType.StaticType.Value.Type)) @@ -927,11 +928,11 @@ private void ScanLdfld ( currentStack.Push (new StackSlot (value)); } - protected virtual void HandleStoreField (MethodDefinition method, FieldValue field, Instruction operation, MultiValue valueToStore) + protected virtual void HandleStoreField (MethodDefinition method, FieldValue field, Instruction operation, MultiValue valueToStore, int? parameterIndex) { } - protected virtual void HandleStoreParameter (MethodDefinition method, MethodParameterValue parameter, Instruction operation, MultiValue valueToStore) + protected virtual void HandleStoreParameter (MethodDefinition method, MethodParameterValue parameter, Instruction operation, MultiValue valueToStore, int? parameterIndex) { } @@ -967,7 +968,7 @@ private void ScanStfld ( // Incomplete handling of ref fields -- if we're storing a reference to a value, pretend it's just the value MultiValue valueToStore = DereferenceValue (valueToStoreSlot.Value, locals, ref interproceduralState); - HandleStoreField (thisMethod, fieldValue, operation, valueToStore); + HandleStoreField (thisMethod, fieldValue, operation, valueToStore, null); } } } @@ -1062,15 +1063,17 @@ protected void AssignRefAndOutParameters ( if (parameter.GetReferenceKind () is not (ReferenceKind.Ref or ReferenceKind.Out)) continue; var newByRefValue = _context.Annotations.FlowAnnotations.GetMethodParameterValue (parameter); - StoreInReference (methodArguments[(int) parameter.Index], newByRefValue, callingMethodBody.Method, operation, locals, curBasicBlock, ref ipState); + StoreInReference (methodArguments[(int) parameter.Index], newByRefValue, callingMethodBody.Method, operation, locals, curBasicBlock, ref ipState, parameter.Index.Index); } } else { // We couldn't resolve the method, so we put unknown values into the ref and out arguments // Should be a very cold path, so using Linq.Zip should be okay - foreach (var (argument, refKind) in methodArguments.Zip (calledMethod.GetParameterReferenceKinds ())) { + var argumentRefKinds = methodArguments.Zip (calledMethod.GetParameterReferenceKinds ()).ToList (); + for (int index = 0; index < argumentRefKinds.Count; index++) { + var (argument, refKind) = argumentRefKinds[index]; if (refKind is not (ReferenceKind.Ref or ReferenceKind.Out)) continue; - StoreInReference (argument, UnknownValue.Instance, callingMethodBody.Method, operation, locals, curBasicBlock, ref ipState); + StoreInReference (argument, UnknownValue.Instance, callingMethodBody.Method, operation, locals, curBasicBlock, ref ipState, index); } } } diff --git a/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs index 832358f2181467..e22d97c91b52d6 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs @@ -95,22 +95,22 @@ MethodParameterValue GetMethodParameterValue (ParameterProxy parameter, Dynamica protected override MethodReturnValue GetReturnValue (MethodDefinition method) => _annotations.GetMethodReturnValue (method, isNewObj: false); - private void HandleStoreValueWithDynamicallyAccessedMembers (ValueWithDynamicallyAccessedMembers targetValue, Instruction operation, MultiValue sourceValue) + private void HandleStoreValueWithDynamicallyAccessedMembers (ValueWithDynamicallyAccessedMembers targetValue, Instruction operation, MultiValue sourceValue, int? parameterIndex) { if (targetValue.DynamicallyAccessedMemberTypes != 0) { _origin = _origin.WithInstructionOffset (operation.Offset); - TrimAnalysisPatterns.Add (new TrimAnalysisAssignmentPattern (sourceValue, targetValue, _origin)); + TrimAnalysisPatterns.Add (new TrimAnalysisAssignmentPattern (sourceValue, targetValue, _origin, parameterIndex)); } } - protected override void HandleStoreField (MethodDefinition method, FieldValue field, Instruction operation, MultiValue valueToStore) - => HandleStoreValueWithDynamicallyAccessedMembers (field, operation, valueToStore); + protected override void HandleStoreField (MethodDefinition method, FieldValue field, Instruction operation, MultiValue valueToStore, int? parameterIndex) + => HandleStoreValueWithDynamicallyAccessedMembers (field, operation, valueToStore, parameterIndex); - protected override void HandleStoreParameter (MethodDefinition method, MethodParameterValue parameter, Instruction operation, MultiValue valueToStore) - => HandleStoreValueWithDynamicallyAccessedMembers (parameter, operation, valueToStore); + protected override void HandleStoreParameter (MethodDefinition method, MethodParameterValue parameter, Instruction operation, MultiValue valueToStore, int? parameterIndex) + => HandleStoreValueWithDynamicallyAccessedMembers (parameter, operation, valueToStore, parameterIndex); protected override void HandleReturnValue (MethodDefinition method, MethodReturnValue returnValue, Instruction operation, MultiValue valueToStore) - => HandleStoreValueWithDynamicallyAccessedMembers (returnValue, operation, valueToStore); + => HandleStoreValueWithDynamicallyAccessedMembers (returnValue, operation, valueToStore, null); public override MultiValue HandleCall (MethodBody callingMethodBody, MethodReference calledMethod, Instruction operation, ValueNodeList methodParams) { diff --git a/src/tools/illink/src/linker/Linker.Dataflow/TrimAnalysisAssignmentPattern.cs b/src/tools/illink/src/linker/Linker.Dataflow/TrimAnalysisAssignmentPattern.cs index 90e742381e5572..2d76af158a09c2 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/TrimAnalysisAssignmentPattern.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/TrimAnalysisAssignmentPattern.cs @@ -15,21 +15,28 @@ public readonly record struct TrimAnalysisAssignmentPattern public MultiValue Target { get; init; } public MessageOrigin Origin { get; init; } - public TrimAnalysisAssignmentPattern (MultiValue source, MultiValue target, MessageOrigin origin) + // For assignment of a method parameter, we store the parameter index to disambiguate + // assignments from different out parameters of a single method call. + public int? ParameterIndex { get; init; } + + public TrimAnalysisAssignmentPattern (MultiValue source, MultiValue target, MessageOrigin origin, int? parameterIndex) { Source = source.DeepCopy (); Target = target.DeepCopy (); Origin = origin; + ParameterIndex = parameterIndex; } public TrimAnalysisAssignmentPattern Merge (ValueSetLattice lattice, TrimAnalysisAssignmentPattern other) { Debug.Assert (Origin == other.Origin); + Debug.Assert (ParameterIndex == other.ParameterIndex); return new TrimAnalysisAssignmentPattern ( lattice.Meet (Source, other.Source), lattice.Meet (Target, other.Target), - Origin); + Origin, + ParameterIndex); } public void MarkAndProduceDiagnostics (ReflectionMarker reflectionMarker, LinkContext context) diff --git a/src/tools/illink/src/linker/Linker.Dataflow/TrimAnalysisPatternStore.cs b/src/tools/illink/src/linker/Linker.Dataflow/TrimAnalysisPatternStore.cs index 48a09f466410f0..6c53694e1d9927 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/TrimAnalysisPatternStore.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/TrimAnalysisPatternStore.cs @@ -10,14 +10,14 @@ namespace Mono.Linker.Dataflow { public readonly struct TrimAnalysisPatternStore { - readonly Dictionary AssignmentPatterns; + readonly Dictionary<(MessageOrigin, int?), TrimAnalysisAssignmentPattern> AssignmentPatterns; readonly Dictionary MethodCallPatterns; readonly ValueSetLattice Lattice; readonly LinkContext _context; public TrimAnalysisPatternStore (ValueSetLattice lattice, LinkContext context) { - AssignmentPatterns = new Dictionary (); + AssignmentPatterns = new Dictionary<(MessageOrigin, int?), TrimAnalysisAssignmentPattern> (); MethodCallPatterns = new Dictionary (); Lattice = lattice; _context = context; @@ -25,12 +25,13 @@ public TrimAnalysisPatternStore (ValueSetLattice lattice, LinkConte public void Add (TrimAnalysisAssignmentPattern pattern) { - if (!AssignmentPatterns.TryGetValue (pattern.Origin, out var existingPattern)) { - AssignmentPatterns.Add (pattern.Origin, pattern); + var key = (pattern.Origin, pattern.ParameterIndex); + if (!AssignmentPatterns.TryGetValue (key, out var existingPattern)) { + AssignmentPatterns.Add (key, pattern); return; } - AssignmentPatterns[pattern.Origin] = pattern.Merge (Lattice, existingPattern); + AssignmentPatterns[key] = pattern.Merge (Lattice, existingPattern); } public void Add (TrimAnalysisMethodCallPattern pattern) 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 a268d1f70b2e4a..a0a1463ee753e7 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 @@ -181,8 +181,6 @@ static void TwoOutRefs ( } [Kept] - [ExpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85464")] - [ExpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85464")] public static void Test () { TwoOutRefs (out _publicMethodsField, out _publicPropertiesField); 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 94db35301c6b7c..65b37ce09aeb16 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/RefFieldDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/RefFieldDataFlow.cs @@ -13,10 +13,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow class RefFieldDataFlow { [Kept] - [UnexpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85464")] - [UnexpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85464")] - [UnexpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85464")] - [UnexpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85464")] public static void Main () { RefFieldWithMethods withMethods = new (ref fieldWithMethods);