diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/README.md b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/README.md index 56774aa84932..b894c9dc1f1c 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/README.md +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/README.md @@ -1 +1 @@ -Sources from the mono/linker repo at commit 6a82d56a9e95858005aca83891f2992edf665eb6. \ No newline at end of file +Sources from the mono/linker repo at commit 012efef292663aa38f9047896942cdcc8765b8e0. \ No newline at end of file diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/DynamicallyAccessedMembersBinder.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/DynamicallyAccessedMembersBinder.cs index a2800947d334..f71e7c9d2972 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/DynamicallyAccessedMembersBinder.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/DynamicallyAccessedMembersBinder.cs @@ -15,7 +15,7 @@ internal static class DynamicallyAccessedMembersBinder // Returns the members of the type bound by memberTypes. For MemberTypes.All, this returns a single null result. // This sentinel value allows callers to handle the case where MemberTypes.All conceptually binds to the entire type // including all recursive nested members. - public static IEnumerable GetDynamicallyAccessedMembers (this TypeDefinition typeDefinition, DynamicallyAccessedMemberTypes memberTypes) + public static IEnumerable GetDynamicallyAccessedMembers (this TypeDefinition typeDefinition, LinkContext context, DynamicallyAccessedMemberTypes memberTypes) { if (memberTypes == DynamicallyAccessedMemberTypes.All) { yield return null; @@ -38,22 +38,22 @@ public static IEnumerable GetDynamicallyAccessedMembers (this } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicMethods)) { - foreach (var m in typeDefinition.GetMethodsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic)) + foreach (var m in typeDefinition.GetMethodsOnTypeHierarchy (context, filter: null, bindingFlags: BindingFlags.NonPublic)) yield return m; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicMethods)) { - foreach (var m in typeDefinition.GetMethodsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.Public)) + foreach (var m in typeDefinition.GetMethodsOnTypeHierarchy (context, filter: null, bindingFlags: BindingFlags.Public)) yield return m; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicFields)) { - foreach (var f in typeDefinition.GetFieldsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic)) + foreach (var f in typeDefinition.GetFieldsOnTypeHierarchy (context, filter: null, bindingFlags: BindingFlags.NonPublic)) yield return f; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicFields)) { - foreach (var f in typeDefinition.GetFieldsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.Public)) + foreach (var f in typeDefinition.GetFieldsOnTypeHierarchy (context, filter: null, bindingFlags: BindingFlags.Public)) yield return f; } @@ -68,22 +68,22 @@ public static IEnumerable GetDynamicallyAccessedMembers (this } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicProperties)) { - foreach (var p in typeDefinition.GetPropertiesOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic)) + foreach (var p in typeDefinition.GetPropertiesOnTypeHierarchy (context, filter: null, bindingFlags: BindingFlags.NonPublic)) yield return p; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicProperties)) { - foreach (var p in typeDefinition.GetPropertiesOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.Public)) + foreach (var p in typeDefinition.GetPropertiesOnTypeHierarchy (context, filter: null, bindingFlags: BindingFlags.Public)) yield return p; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicEvents)) { - foreach (var e in typeDefinition.GetEventsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic)) + foreach (var e in typeDefinition.GetEventsOnTypeHierarchy (context, filter: null, bindingFlags: BindingFlags.NonPublic)) yield return e; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicEvents)) { - foreach (var e in typeDefinition.GetEventsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.Public)) + foreach (var e in typeDefinition.GetEventsOnTypeHierarchy (context, filter: null, bindingFlags: BindingFlags.Public)) yield return e; } } @@ -113,7 +113,7 @@ public static IEnumerable GetConstructorsOnType (this TypeDefi } } - public static IEnumerable GetMethodsOnTypeHierarchy (this TypeDefinition type, Func filter, BindingFlags? bindingFlags = null) + public static IEnumerable GetMethodsOnTypeHierarchy (this TypeDefinition type, LinkContext context, Func filter, BindingFlags? bindingFlags = null) { bool onBaseType = false; while (type != null) { @@ -148,12 +148,12 @@ public static IEnumerable GetMethodsOnTypeHierarchy (this Type yield return method; } - type = type.BaseType?.Resolve (); + type = context.TryResolveTypeDefinition (type.BaseType); onBaseType = true; } } - public static IEnumerable GetFieldsOnTypeHierarchy (this TypeDefinition type, Func filter, BindingFlags? bindingFlags = BindingFlags.Default) + public static IEnumerable GetFieldsOnTypeHierarchy (this TypeDefinition type, LinkContext context, Func filter, BindingFlags? bindingFlags = BindingFlags.Default) { bool onBaseType = false; while (type != null) { @@ -184,7 +184,7 @@ public static IEnumerable GetFieldsOnTypeHierarchy (this TypeDe yield return field; } - type = type.BaseType?.Resolve (); + type = context.TryResolveTypeDefinition (type.BaseType); onBaseType = true; } } @@ -209,7 +209,7 @@ public static IEnumerable GetNestedTypesOnType (this TypeDefinit } } - public static IEnumerable GetPropertiesOnTypeHierarchy (this TypeDefinition type, Func filter, BindingFlags? bindingFlags = BindingFlags.Default) + public static IEnumerable GetPropertiesOnTypeHierarchy (this TypeDefinition type, LinkContext context, Func filter, BindingFlags? bindingFlags = BindingFlags.Default) { bool onBaseType = false; while (type != null) { @@ -249,12 +249,12 @@ public static IEnumerable GetPropertiesOnTypeHierarchy (this yield return property; } - type = type.BaseType?.Resolve (); + type = context.TryResolveTypeDefinition (type.BaseType); onBaseType = true; } } - public static IEnumerable GetEventsOnTypeHierarchy (this TypeDefinition type, Func filter, BindingFlags? bindingFlags = BindingFlags.Default) + public static IEnumerable GetEventsOnTypeHierarchy (this TypeDefinition type, LinkContext context, Func filter, BindingFlags? bindingFlags = BindingFlags.Default) { bool onBaseType = false; while (type != null) { @@ -294,7 +294,7 @@ public static IEnumerable GetEventsOnTypeHierarchy (this TypeDe yield return @event; } - type = type.BaseType?.Resolve (); + type = context.TryResolveTypeDefinition (type.BaseType); onBaseType = true; } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/FlowAnnotations.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/FlowAnnotations.cs index 45dcd5181068..9fd7f3514149 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/FlowAnnotations.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/FlowAnnotations.cs @@ -15,11 +15,12 @@ class FlowAnnotations { readonly LinkContext _context; readonly Dictionary _annotations = new Dictionary (); - readonly TypeHierarchyCache _hierarchyInfo = new TypeHierarchyCache (); + readonly TypeHierarchyCache _hierarchyInfo; public FlowAnnotations (LinkContext context) { _context = context; + _hierarchyInfo = new TypeHierarchyCache (context); } public bool RequiresDataFlowAnalysis (MethodDefinition method) @@ -76,7 +77,7 @@ public DynamicallyAccessedMemberTypes GetTypeAnnotation (TypeDefinition type) public DynamicallyAccessedMemberTypes GetGenericParameterAnnotation (GenericParameter genericParameter) { - TypeDefinition declaringType = genericParameter.DeclaringType?.Resolve (); + TypeDefinition declaringType = _context.ResolveTypeDefinition (genericParameter.DeclaringType); if (declaringType != null) { if (GetAnnotations (declaringType).TryGetAnnotation (genericParameter, out var annotation)) return annotation; @@ -84,7 +85,7 @@ public DynamicallyAccessedMemberTypes GetGenericParameterAnnotation (GenericPara return DynamicallyAccessedMemberTypes.None; } - MethodDefinition declaringMethod = genericParameter.DeclaringMethod?.Resolve (); + MethodDefinition declaringMethod = _context.ResolveMethodDefinition (genericParameter.DeclaringMethod); if (declaringMethod != null && GetAnnotations (declaringMethod.DeclaringType).TryGetAnnotation (declaringMethod, out var methodTypeAnnotations) && methodTypeAnnotations.TryGetAnnotation (genericParameter, out var methodAnnotation)) return methodAnnotation; @@ -349,7 +350,7 @@ TypeAnnotations BuildTypeAnnotations (TypeDefinition type) return new TypeAnnotations (type, typeAnnotation, annotatedMethods.ToArray (), annotatedFields.ToArray (), typeGenericParameterAnnotations); } - static bool ScanMethodBodyForFieldAccess (MethodBody body, bool write, out FieldDefinition found) + bool ScanMethodBodyForFieldAccess (MethodBody body, bool write, out FieldDefinition found) { // Tries to find the backing field for a property getter/setter. // Returns true if this is a method body that we can unambiguously analyze. @@ -383,7 +384,7 @@ static bool ScanMethodBodyForFieldAccess (MethodBody body, bool write, out Field return true; } - found = foundReference.Resolve (); + found = _context.ResolveFieldDefinition (foundReference); if (found == null) { // If the field doesn't resolve, it can't be a field on the current type @@ -405,9 +406,13 @@ static bool ScanMethodBodyForFieldAccess (MethodBody body, bool write, out Field bool IsTypeInterestingForDataflow (TypeReference typeReference) { - return typeReference.MetadataType == MetadataType.String || - _hierarchyInfo.IsSystemType (typeReference) || - _hierarchyInfo.IsSystemReflectionIReflect (typeReference); + if (typeReference.MetadataType == MetadataType.String) + return true; + + TypeDefinition type = _context.TryResolveTypeDefinition (typeReference); + return type != null && ( + _hierarchyInfo.IsSystemType (type) || + _hierarchyInfo.IsSystemReflectionIReflect (type)); } internal void ValidateMethodAnnotationsAreSame (MethodDefinition method, MethodDefinition baseMethod) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/MethodBodyScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/MethodBodyScanner.cs index a13773f3fc8f..6fd11ad35717 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/MethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/MethodBodyScanner.cs @@ -32,6 +32,13 @@ public StackSlot (ValueNode value, bool isByRef = false) abstract partial class MethodBodyScanner { + protected readonly LinkContext _context; + + protected MethodBodyScanner (LinkContext context) + { + this._context = context; + } + internal ValueNode MethodReturnValue { private set; get; } protected virtual void WarnAboutInvalidILInMethod (MethodBody method, int ilOffset) @@ -706,7 +713,7 @@ private void ScanLdloc ( } } - private static void ScanLdtoken (Instruction operation, Stack currentStack) + void ScanLdtoken (Instruction operation, Stack currentStack) { if (operation.Operand is GenericParameter genericParameter) { StackSlot slot = new StackSlot (new RuntimeTypeHandleForGenericParameterValue (genericParameter)); @@ -715,14 +722,14 @@ private static void ScanLdtoken (Instruction operation, Stack current } if (operation.Operand is TypeReference typeReference) { - var resolvedReference = typeReference.ResolveToMainTypeDefinition (); + var resolvedReference = ResolveToTypeDefinition (typeReference); if (resolvedReference != null) { StackSlot slot = new StackSlot (new RuntimeTypeHandleValue (resolvedReference)); currentStack.Push (slot); return; } } else if (operation.Operand is MethodReference methodReference) { - var resolvedMethod = methodReference.Resolve (); + var resolvedMethod = _context.TryResolveMethodDefinition (methodReference); if (resolvedMethod != null) { StackSlot slot = new StackSlot (new RuntimeMethodHandleValue (resolvedMethod)); currentStack.Push (slot); @@ -782,7 +789,7 @@ private void ScanLdfld ( bool isByRef = code == Code.Ldflda || code == Code.Ldsflda; - FieldDefinition field = (operation.Operand as FieldReference)?.Resolve (); + FieldDefinition field = _context.TryResolveFieldDefinition (operation.Operand as FieldReference); if (field != null) { StackSlot slot = new StackSlot (GetFieldValue (thisMethod, field), isByRef); currentStack.Push (slot); @@ -810,7 +817,7 @@ private void ScanStfld ( if (operation.OpCode.Code == Code.Stfld) PopUnknown (currentStack, 1, methodBody, operation.Offset); - FieldDefinition field = (operation.Operand as FieldReference)?.Resolve (); + FieldDefinition field = _context.TryResolveFieldDefinition (operation.Operand as FieldReference); if (field != null) { HandleStoreField (thisMethod, field, operation, valueToStoreSlot.Value); } @@ -901,6 +908,17 @@ private void HandleCall ( } } + // Array types that are dynamically accessed should resolve to System.Array instead of its element type - which is what Cecil resolves to. + // Any data flow annotations placed on a type parameter which receives an array type apply to the array itself. None of the members in its + // element type should be marked. + public TypeDefinition ResolveToTypeDefinition (TypeReference typeReference) + { + if (typeReference is ArrayType) + return BCL.FindPredefinedType ("System", "Array", _context); + + return _context.TryResolveTypeDefinition (typeReference); + } + public abstract bool HandleCall ( MethodBody callingMethodBody, MethodReference calledMethod, diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/README.md b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/README.md index 9fdddd271e81..4e81e66264e9 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/README.md +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/README.md @@ -1 +1 @@ -Sources taken from https://github.com/mono/linker/tree/6a82d56a9e95858005aca83891f2992edf665eb6/src/linker/Linker.Dataflow. +Sources taken from https://github.com/mono/linker/tree/012efef292663aa38f9047896942cdcc8765b8e0/src/linker/Linker.Dataflow. diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/ReflectionMethodBodyScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/ReflectionMethodBodyScanner.cs index 9d087c05c9c8..500e9be1892c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/ReflectionMethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/ReflectionMethodBodyScanner.cs @@ -17,41 +17,34 @@ namespace Mono.Linker.Dataflow { class ReflectionMethodBodyScanner : MethodBodyScanner { - readonly LinkContext _context; readonly MarkStep _markStep; public static bool RequiresReflectionMethodBodyScannerForCallSite (LinkContext context, MethodReference calledMethod) { - MethodDefinition methodDefinition = calledMethod.Resolve (); - if (methodDefinition != null) { - return - GetIntrinsicIdForMethod (methodDefinition) > IntrinsicId.RequiresReflectionBodyScanner_Sentinel || - context.Annotations.FlowAnnotations.RequiresDataFlowAnalysis (methodDefinition) || - context.Annotations.HasLinkerAttribute (methodDefinition); - } + MethodDefinition methodDefinition = context.TryResolveMethodDefinition (calledMethod); + if (methodDefinition == null) + return false; - return false; + return + GetIntrinsicIdForMethod (methodDefinition) > IntrinsicId.RequiresReflectionBodyScanner_Sentinel || + context.Annotations.FlowAnnotations.RequiresDataFlowAnalysis (methodDefinition) || + context.Annotations.HasLinkerAttribute (methodDefinition); } - public static bool RequiresReflectionMethodBodyScannerForMethodBody (FlowAnnotations flowAnnotations, MethodReference method) + public static bool RequiresReflectionMethodBodyScannerForMethodBody (FlowAnnotations flowAnnotations, MethodDefinition methodDefinition) { - MethodDefinition methodDefinition = method.Resolve (); - if (methodDefinition != null) { - return - GetIntrinsicIdForMethod (methodDefinition) > IntrinsicId.RequiresReflectionBodyScanner_Sentinel || - flowAnnotations.RequiresDataFlowAnalysis (methodDefinition); - } - - return false; + return + GetIntrinsicIdForMethod (methodDefinition) > IntrinsicId.RequiresReflectionBodyScanner_Sentinel || + flowAnnotations.RequiresDataFlowAnalysis (methodDefinition); } - public static bool RequiresReflectionMethodBodyScannerForAccess (FlowAnnotations flowAnnotations, FieldReference field) + public static bool RequiresReflectionMethodBodyScannerForAccess (LinkContext context, FieldReference field) { - FieldDefinition fieldDefinition = field.Resolve (); - if (fieldDefinition != null) - return flowAnnotations.RequiresDataFlowAnalysis (fieldDefinition); + FieldDefinition fieldDefinition = context.TryResolveFieldDefinition (field); + if (fieldDefinition == null) + return false; - return false; + return context.Annotations.FlowAnnotations.RequiresDataFlowAnalysis (fieldDefinition); } bool ShouldEnableReflectionPatternReporting (MethodDefinition method) @@ -60,8 +53,8 @@ bool ShouldEnableReflectionPatternReporting (MethodDefinition method) } public ReflectionMethodBodyScanner (LinkContext context, MarkStep parent) + : base (context) { - _context = context; _markStep = parent; } @@ -118,11 +111,11 @@ public void ApplyDynamicallyAccessedMembersToType (ref ReflectionPatternContext MarkTypeForDynamicallyAccessedMembers (ref reflectionPatternContext, type, annotation); } - static ValueNode GetValueNodeForCustomAttributeArgument (CustomAttributeArgument argument) + ValueNode GetValueNodeForCustomAttributeArgument (CustomAttributeArgument argument) { ValueNode valueNode; if (argument.Type.Name == "Type") { - TypeDefinition referencedType = ((TypeReference) argument.Value).ResolveToMainTypeDefinition (); + TypeDefinition referencedType = ResolveToTypeDefinition ((TypeReference) argument.Value); if (referencedType == null) valueNode = UnknownValue.Instance; else @@ -159,7 +152,7 @@ ValueNode GetTypeValueNodeFromGenericArgument (TypeReference genericArgument) // That said we only use it to perform the dynamically accessed members checks and for that purpose treating it as System.Type is perfectly valid. return new SystemTypeForGenericParameterValue (inputGenericParameter, _context.Annotations.FlowAnnotations.GetGenericParameterAnnotation (inputGenericParameter)); } else { - TypeDefinition genericArgumentTypeDef = genericArgument.ResolveToMainTypeDefinition (); + TypeDefinition genericArgumentTypeDef = ResolveToTypeDefinition (genericArgument); if (genericArgumentTypeDef != null) { return new SystemTypeValue (genericArgumentTypeDef); } else { @@ -182,10 +175,21 @@ protected override void WarnAboutInvalidILInMethod (MethodBody method, int ilOff Debug.Fail ("Invalid IL or a bug in the scanner"); } + MethodReturnValue CreateMethodReturnValue (MethodReference method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes = DynamicallyAccessedMemberTypes.None) + { + return new MethodReturnValue (ResolveToTypeDefinition (method.ReturnType), dynamicallyAccessedMemberTypes, method.MethodReturnType); + } + protected override ValueNode GetMethodParameterValue (MethodDefinition method, int parameterIndex) { DynamicallyAccessedMemberTypes memberTypes = _context.Annotations.FlowAnnotations.GetParameterAnnotation (method, parameterIndex); - return new MethodParameterValue (method, parameterIndex, memberTypes, DiagnosticUtilities.GetMethodParameterFromIndex (method, parameterIndex)); + + var staticType = + !method.HasImplicitThis () ? ResolveToTypeDefinition (method.Parameters[parameterIndex].ParameterType) : + parameterIndex == 0 ? method.DeclaringType : + ResolveToTypeDefinition (method.Parameters[parameterIndex - 1].ParameterType); + + return new MethodParameterValue (staticType, parameterIndex, memberTypes, DiagnosticUtilities.GetMethodParameterFromIndex (method, parameterIndex)); } protected override ValueNode GetFieldValue (MethodDefinition method, FieldDefinition field) @@ -200,7 +204,7 @@ protected override ValueNode GetFieldValue (MethodDefinition method, FieldDefini default: { DynamicallyAccessedMemberTypes memberTypes = _context.Annotations.FlowAnnotations.GetFieldAnnotation (field); - return new LoadFieldValue (field, memberTypes); + return new LoadFieldValue (ResolveToTypeDefinition (field.FieldType), field, memberTypes); } } } @@ -612,19 +616,19 @@ public override bool HandleCall (MethodBody callingMethodBody, MethodReference c return false; var callingMethodDefinition = callingMethodBody.Method; + var calledMethodDefinition = _context.TryResolveMethodDefinition (calledMethod); + if (calledMethodDefinition == null) + return false; + var reflectionContext = new ReflectionPatternContext ( _context, ShouldEnableReflectionPatternReporting (callingMethodDefinition), callingMethodDefinition, - calledMethod.Resolve (), + calledMethodDefinition, operation); DynamicallyAccessedMemberTypes returnValueDynamicallyAccessedMemberTypes = 0; - var calledMethodDefinition = calledMethod.Resolve (); - if (calledMethodDefinition == null) - return false; - try { bool requiresDataFlowAnalysis = _context.Annotations.FlowAnnotations.RequiresDataFlowAnalysis (calledMethodDefinition); @@ -818,7 +822,7 @@ public override bool HandleCall (MethodBody callingMethodBody, MethodReference c if (value is SystemTypeValue systemTypeValue) { foreach (var stringParam in methodParams[1].UniqueValues ()) { if (stringParam is KnownStringValue stringValue) { - foreach (var method in systemTypeValue.TypeRepresented.GetMethodsOnTypeHierarchy (m => m.Name == stringValue.Contents, bindingFlags)) { + foreach (var method in systemTypeValue.TypeRepresented.GetMethodsOnTypeHierarchy (_context, m => m.Name == stringValue.Contents, bindingFlags)) { ValidateGenericMethodInstantiation (ref reflectionContext, method, methodParams[2], calledMethod); MarkMethod (ref reflectionContext, method); } @@ -955,8 +959,8 @@ public override bool HandleCall (MethodBody callingMethodBody, MethodReference c foreach (var valueNode in methodParams[0].UniqueValues ()) { TypeDefinition staticType = valueNode.StaticType; 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” - methodReturnValue = MergePointValue.MergeValues (methodReturnValue, new MethodReturnValue (calledMethod.MethodReturnType, DynamicallyAccessedMemberTypes.None)); + // 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 + methodReturnValue = MergePointValue.MergeValues (methodReturnValue, CreateMethodReturnValue (calledMethod)); } else if (staticType.IsSealed || staticType.IsTypeOf ("System", "Delegate")) { // We can treat this one the same as if it was a typeof() expression @@ -987,7 +991,7 @@ public override bool HandleCall (MethodBody callingMethodBody, MethodReference c // 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. - methodReturnValue = MergePointValue.MergeValues (methodReturnValue, new MethodReturnValue (calledMethod.MethodReturnType, annotation)); + methodReturnValue = MergePointValue.MergeValues (methodReturnValue, CreateMethodReturnValue (calledMethod, annotation)); } } } @@ -1015,12 +1019,12 @@ public override bool HandleCall (MethodBody callingMethodBody, MethodReference c foreach (var typeNameValue in methodParams[0].UniqueValues ()) { if (typeNameValue is KnownStringValue knownStringValue) { TypeReference foundTypeRef = _context.TypeNameResolver.ResolveTypeName (knownStringValue.Contents, callingMethodDefinition, out AssemblyDefinition typeAssembly, false); - TypeDefinition foundType = foundTypeRef?.ResolveToMainTypeDefinition (); + TypeDefinition foundType = ResolveToTypeDefinition (foundTypeRef); if (foundType == null) { // Intentionally ignore - it's not wrong for code to call Type.GetType on non-existing name, the code might expect null/exception back. reflectionContext.RecordHandledPattern (); } else { - reflectionContext.RecordRecognizedPattern (foundType, () => _markStep.MarkTypeVisibleToReflection (foundTypeRef, new DependencyInfo (DependencyKind.AccessedViaReflection, callingMethodDefinition), callingMethodDefinition)); + reflectionContext.RecordRecognizedPattern (foundType, () => _markStep.MarkTypeVisibleToReflection (foundTypeRef, foundType, new DependencyInfo (DependencyKind.AccessedViaReflection, callingMethodDefinition), callingMethodDefinition)); methodReturnValue = MergePointValue.MergeValues (methodReturnValue, new SystemTypeValue (foundType)); _context.MarkingHelpers.MarkMatchingExportedType (foundType, typeAssembly, new DependencyInfo (DependencyKind.AccessedViaReflection, foundType)); } @@ -1030,7 +1034,7 @@ public override bool HandleCall (MethodBody callingMethodBody, MethodReference c // Propagate the annotation from the type name to the return value. Annotation on a string value will be fullfilled 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. reflectionContext.RecordHandledPattern (); - methodReturnValue = MergePointValue.MergeValues (methodReturnValue, new MethodReturnValue (calledMethodDefinition.MethodReturnType, valueWithDynamicallyAccessedMember.DynamicallyAccessedMemberTypes)); + methodReturnValue = MergePointValue.MergeValues (methodReturnValue, CreateMethodReturnValue (calledMethodDefinition, valueWithDynamicallyAccessedMember.DynamicallyAccessedMemberTypes)); } else { reflectionContext.RecordUnrecognizedPattern (2057, $"Unrecognized value passed to the parameter 'typeName' of method '{calledMethod.GetDisplayName ()}'. It's not possible to guarantee the availability of the target type."); } @@ -1201,7 +1205,7 @@ public override bool HandleCall (MethodBody callingMethodBody, MethodReference c // Note it's OK to blindly overwrite any potential annotation on the return value from the method definition // since DynamicallyAccessedMemberTypes.All is a superset of any other annotation. if (everyParentTypeHasAll && methodReturnValue == null) - methodReturnValue = new MethodReturnValue (calledMethodDefinition.MethodReturnType, DynamicallyAccessedMemberTypes.All); + methodReturnValue = CreateMethodReturnValue (calledMethodDefinition, DynamicallyAccessedMemberTypes.All); } break; @@ -1264,19 +1268,19 @@ public override bool HandleCall (MethodBody callingMethodBody, MethodReference c propagatedMemberTypes |= DynamicallyAccessedMemberTypes.PublicProperties; } - methodReturnValue = MergePointValue.MergeValues (methodReturnValue, new MethodReturnValue (calledMethod.MethodReturnType, propagatedMemberTypes)); + methodReturnValue = MergePointValue.MergeValues (methodReturnValue, CreateMethodReturnValue (calledMethod, propagatedMemberTypes)); } else if (value is SystemTypeValue systemTypeValue) { - TypeDefinition baseTypeDefinition = systemTypeValue.TypeRepresented.BaseType.Resolve (); + TypeDefinition baseTypeDefinition = _context.TryResolveTypeDefinition (systemTypeValue.TypeRepresented.BaseType); if (baseTypeDefinition != null) methodReturnValue = MergePointValue.MergeValues (methodReturnValue, new SystemTypeValue (baseTypeDefinition)); else - methodReturnValue = MergePointValue.MergeValues (methodReturnValue, new MethodReturnValue (calledMethod.MethodReturnType, DynamicallyAccessedMemberTypes.None)); + methodReturnValue = MergePointValue.MergeValues (methodReturnValue, CreateMethodReturnValue (calledMethod)); } else if (value == NullValue.Instance) { // Ignore nulls - null.BaseType will fail at runtime, but it has no effect on static analysis continue; } else { // Unknown input - propagate a return value without any annotation - we know it's a Type but we know nothing about it - methodReturnValue = MergePointValue.MergeValues (methodReturnValue, new MethodReturnValue (calledMethod.MethodReturnType, DynamicallyAccessedMemberTypes.None)); + methodReturnValue = MergePointValue.MergeValues (methodReturnValue, CreateMethodReturnValue (calledMethod)); } } } @@ -1683,7 +1687,7 @@ methodParams[argsParam] is ArrayValue arrayValue && // To get good reporting of errors we need to track the origin of the value for all method calls // but except Newobj as those are special. if (calledMethodDefinition.ReturnType.MetadataType != MetadataType.Void) { - methodReturnValue = new MethodReturnValue (calledMethodDefinition.MethodReturnType, returnValueDynamicallyAccessedMemberTypes); + methodReturnValue = CreateMethodReturnValue (calledMethodDefinition, returnValueDynamicallyAccessedMemberTypes); return true; } @@ -1699,7 +1703,7 @@ methodParams[argsParam] is ArrayValue arrayValue && // unknown value with the return type of the method. if (methodReturnValue == null) { if (calledMethod.ReturnType.MetadataType != MetadataType.Void) { - methodReturnValue = new MethodReturnValue (calledMethodDefinition.MethodReturnType, returnValueDynamicallyAccessedMemberTypes); + methodReturnValue = CreateMethodReturnValue (calledMethodDefinition, returnValueDynamicallyAccessedMemberTypes); } } @@ -1796,7 +1800,7 @@ void ProcessCreateInstanceByName (ref ReflectionPatternContext reflectionContext } var typeRef = _context.TypeNameResolver.ResolveTypeName (resolvedAssembly, typeNameStringValue.Contents); - var resolvedType = typeRef?.Resolve (); + var resolvedType = _context.TryResolveTypeDefinition (typeRef); if (resolvedType == null || typeRef is ArrayType) { // It's not wrong to have a reference to non-existing type - the code may well expect to get an exception in this case // Note that we did find the assembly, so it's not a linker config problem, it's either intentional, or wrong versions of assemblies @@ -1825,7 +1829,7 @@ void ProcessGetMethodByName ( ref ValueNode methodReturnValue) { bool foundAny = false; - foreach (var method in typeDefinition.GetMethodsOnTypeHierarchy (m => m.Name == methodName, bindingFlags)) { + foreach (var method in typeDefinition.GetMethodsOnTypeHierarchy (_context, m => m.Name == methodName, bindingFlags)) { MarkMethod (ref reflectionContext, method); methodReturnValue = MergePointValue.MergeValues (methodReturnValue, new SystemReflectionMethodBaseValue (method)); foundAny = true; @@ -2061,7 +2065,7 @@ void RequireDynamicallyAccessedMembers (ref ReflectionPatternContext reflectionC MarkTypeForDynamicallyAccessedMembers (ref reflectionContext, systemTypeValue.TypeRepresented, requiredMemberTypes); } else if (uniqueValue is KnownStringValue knownStringValue) { TypeReference typeRef = _context.TypeNameResolver.ResolveTypeName (knownStringValue.Contents, reflectionContext.Source, out AssemblyDefinition typeAssembly); - TypeDefinition foundType = typeRef?.ResolveToMainTypeDefinition (); + TypeDefinition foundType = ResolveToTypeDefinition (typeRef); if (foundType == null) { // Intentionally ignore - it's not wrong for code to call Type.GetType on non-existing name, the code might expect null/exception back. reflectionContext.RecordHandledPattern (); @@ -2095,7 +2099,7 @@ void RequireDynamicallyAccessedMembers (ref ReflectionPatternContext reflectionC $"Value passed to implicit 'this' parameter of method '{methodDefinition.GetDisplayName ()}' can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements."); break; case GenericParameter genericParameter: - // Unknown value to generic parameter - this is possible if the generic argumnet fails to resolve + // Unknown value to generic parameter - this is possible if the generic argument fails to resolve reflectionContext.RecordUnrecognizedPattern ( 2066, $"Type passed to generic parameter '{genericParameter.Name}' of '{DiagnosticUtilities.GetGenericParameterDeclaringMemberDisplayName (genericParameter)}' can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements."); @@ -2116,7 +2120,7 @@ void RequireDynamicallyAccessedMembers (ref ReflectionPatternContext reflectionC void MarkTypeForDynamicallyAccessedMembers (ref ReflectionPatternContext reflectionContext, TypeDefinition typeDefinition, DynamicallyAccessedMemberTypes requiredMemberTypes) { - foreach (var member in typeDefinition.GetDynamicallyAccessedMembers (requiredMemberTypes)) { + foreach (var member in typeDefinition.GetDynamicallyAccessedMembers (_context, requiredMemberTypes)) { switch (member) { case MethodDefinition method: MarkMethod (ref reflectionContext, method, DependencyKind.DynamicallyAccessedMember); @@ -2144,7 +2148,8 @@ void MarkTypeForDynamicallyAccessedMembers (ref ReflectionPatternContext reflect void MarkType (ref ReflectionPatternContext reflectionContext, TypeReference typeReference) { var source = reflectionContext.Source; - reflectionContext.RecordRecognizedPattern (typeReference?.Resolve (), () => _markStep.MarkTypeVisibleToReflection (typeReference, new DependencyInfo (DependencyKind.AccessedViaReflection, source), source)); + TypeDefinition type = _context.TryResolveTypeDefinition (typeReference); + reflectionContext.RecordRecognizedPattern (type, () => _markStep.MarkTypeVisibleToReflection (typeReference, type, new DependencyInfo (DependencyKind.AccessedViaReflection, source), source)); } void MarkMethod (ref ReflectionPatternContext reflectionContext, MethodDefinition method, DependencyKind dependencyKind = DependencyKind.AccessedViaReflection) @@ -2157,7 +2162,8 @@ void MarkMethod (ref ReflectionPatternContext reflectionContext, MethodDefinitio void MarkNestedType (ref ReflectionPatternContext reflectionContext, TypeDefinition nestedType, DependencyKind dependencyKind = DependencyKind.AccessedViaReflection) { var source = reflectionContext.Source; - reflectionContext.RecordRecognizedPattern (nestedType, () => _markStep.MarkTypeVisibleToReflection (nestedType, new DependencyInfo (dependencyKind, source), source)); + TypeDefinition type = _context.TryResolveTypeDefinition (nestedType); + reflectionContext.RecordRecognizedPattern (nestedType, () => _markStep.MarkTypeVisibleToReflection (nestedType, type, new DependencyInfo (dependencyKind, source), source)); } void MarkField (ref ReflectionPatternContext reflectionContext, FieldDefinition field, DependencyKind dependencyKind = DependencyKind.AccessedViaReflection) @@ -2200,7 +2206,7 @@ void MarkConstructorsOnType (ref ReflectionPatternContext reflectionContext, Typ void MarkFieldsOnTypeHierarchy (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func filter, BindingFlags? bindingFlags = BindingFlags.Default) { - foreach (var field in type.GetFieldsOnTypeHierarchy (filter, bindingFlags)) + foreach (var field in type.GetFieldsOnTypeHierarchy (_context, filter, bindingFlags)) MarkField (ref reflectionContext, field); } @@ -2218,13 +2224,13 @@ TypeDefinition[] MarkNestedTypesOnType (ref ReflectionPatternContext reflectionC void MarkPropertiesOnTypeHierarchy (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func filter, BindingFlags? bindingFlags = BindingFlags.Default) { - foreach (var property in type.GetPropertiesOnTypeHierarchy (filter, bindingFlags)) + foreach (var property in type.GetPropertiesOnTypeHierarchy (_context, filter, bindingFlags)) MarkProperty (ref reflectionContext, property); } void MarkEventsOnTypeHierarchy (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func filter, BindingFlags? bindingFlags = BindingFlags.Default) { - foreach (var @event in type.GetEventsOnTypeHierarchy (filter, bindingFlags)) + foreach (var @event in type.GetEventsOnTypeHierarchy (_context, filter, bindingFlags)) MarkEvent (ref reflectionContext, @event); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/ValueNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/ValueNode.cs index f1b5b3b6d913..7545571486a0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/ValueNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/ValueNode.cs @@ -833,14 +833,10 @@ public override bool Equals (ValueNode other) /// class MethodParameterValue : LeafValueWithDynamicallyAccessedMemberNode { - public MethodParameterValue (MethodDefinition method, int parameterIndex, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes, IMetadataTokenProvider sourceContext) + public MethodParameterValue (TypeDefinition staticType, int parameterIndex, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes, IMetadataTokenProvider sourceContext) { Kind = ValueNodeKind.MethodParameter; - StaticType = method.HasImplicitThis () - ? (parameterIndex == 0 - ? method.DeclaringType - : method.Parameters[parameterIndex - 1].ParameterType.ResolveToMainTypeDefinition ()) - : method.Parameters[parameterIndex].ParameterType.ResolveToMainTypeDefinition (); + StaticType = staticType; ParameterIndex = parameterIndex; DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; SourceContext = sourceContext; @@ -905,12 +901,12 @@ protected override string NodeToString () /// class MethodReturnValue : LeafValueWithDynamicallyAccessedMemberNode { - public MethodReturnValue (MethodReturnType methodReturnType, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + public MethodReturnValue (TypeDefinition staticType, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes, IMetadataTokenProvider sourceContext) { Kind = ValueNodeKind.MethodReturn; - StaticType = methodReturnType.ReturnType.ResolveToMainTypeDefinition (); + StaticType = staticType; DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; - SourceContext = methodReturnType; + SourceContext = sourceContext; } public override bool Equals (ValueNode other) @@ -1144,10 +1140,10 @@ protected override string NodeToString () /// class LoadFieldValue : LeafValueWithDynamicallyAccessedMemberNode { - public LoadFieldValue (FieldDefinition fieldToLoad, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + public LoadFieldValue (TypeDefinition staticType, FieldDefinition fieldToLoad, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) { Kind = ValueNodeKind.LoadField; - StaticType = fieldToLoad.FieldType.ResolveToMainTypeDefinition (); + StaticType = staticType; Field = fieldToLoad; DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; SourceContext = fieldToLoad; @@ -1227,7 +1223,7 @@ public ArrayValue (ValueNode size, TypeReference elementType) StaticType = null; Size = size ?? UnknownValue.Instance; - ElementType = elementType.ResolveToMainTypeDefinition (); + ElementType = elementType; IndexValues = new Dictionary (); } 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 5bc97bc5c057..0c6c2d365e58 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs @@ -1232,7 +1232,7 @@ public override bool HandleCall(MethodIL callingMethodBody, MethodDesc calledMet TypeDesc staticType = valueNode.StaticType; 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” + // 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" methodReturnValue = MergePointValue.MergeValues(methodReturnValue, new MethodReturnValue(calledMethod, DynamicallyAccessedMemberTypes.None)); } else if (staticType.IsSealed() || staticType.IsTypeOf("System", "Delegate"))