Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/coreclr/tools/Common/Compiler/EventPseudoDesc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ public EventPseudoDesc(EcmaType type, EventDefinitionHandle handle)

public override int GetHashCode() => _type.GetHashCode() ^ _handle.GetHashCode();

public override string ToString() => $"{_type}.{Name}";

public static bool operator ==(EventPseudoDesc a, EventPseudoDesc b) => a._type == b._type && a._handle == b._handle;

public static bool operator !=(EventPseudoDesc a, EventPseudoDesc b) => !(a == b);
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/tools/Common/Compiler/PropertyPseudoDesc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ public PropertyPseudoDesc(EcmaType type, PropertyDefinitionHandle handle)

public override int GetHashCode() => _type.GetHashCode() ^ _handle.GetHashCode();

public override string ToString() => $"{_type}.{Name}";

public static bool operator ==(PropertyPseudoDesc a, PropertyPseudoDesc b) => a._type == b._type && a._handle == b._handle;

public static bool operator !=(PropertyPseudoDesc a, PropertyPseudoDesc b) => !(a == b);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
using DependencyListEntry = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore<ILCompiler.DependencyAnalysis.NodeFactory>.DependencyListEntry;
using CombinedDependencyList = System.Collections.Generic.List<ILCompiler.DependencyAnalysisFramework.DependencyNodeCore<ILCompiler.DependencyAnalysis.NodeFactory>.CombinedDependencyListEntry>;
using CombinedDependencyListEntry = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore<ILCompiler.DependencyAnalysis.NodeFactory>.CombinedDependencyListEntry;
using MethodAttributes = System.Reflection.MethodAttributes;

namespace ILCompiler.DependencyAnalysis
{
Expand Down Expand Up @@ -54,37 +53,7 @@ public static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyLi
AddDependenciesDueToCustomAttributes(ref dependencies, genericParameterCondition, factory, method.Module, parameter.GetCustomAttributes(), method);
}

// We don't model properties and events as separate entities within the compiler, so ensuring
// we can generate custom attributes for the associated events and properties from here
// is as good as any other place.
//
// As a performance optimization, we look for associated events and properties only
// if the method is SpecialName. This is required for CLS compliance and compilers we
// care about emit accessors like this.
object propertyCondition = GetMetadataApiDependency(factory, "Property"u8);
if ((methodDef.Attributes & MethodAttributes.SpecialName) != 0)
{
TypeDefinition declaringType = reader.GetTypeDefinition(methodDef.GetDeclaringType());

foreach (PropertyDefinitionHandle propertyHandle in declaringType.GetProperties())
{
PropertyDefinition property = reader.GetPropertyDefinition(propertyHandle);
PropertyAccessors accessors = property.GetAccessors();

if (accessors.Getter == methodHandle || accessors.Setter == methodHandle)
AddDependenciesDueToCustomAttributes(ref dependencies, propertyCondition, factory, method.Module, property.GetCustomAttributes(), new PropertyPseudoDesc(method.OwningType, propertyHandle));
}

object eventCondition = GetMetadataApiDependency(factory, "Event"u8);
foreach (EventDefinitionHandle eventHandle in declaringType.GetEvents())
{
EventDefinition @event = reader.GetEventDefinition(eventHandle);
EventAccessors accessors = @event.GetAccessors();

if (accessors.Adder == methodHandle || accessors.Remover == methodHandle || accessors.Raiser == methodHandle)
AddDependenciesDueToCustomAttributes(ref dependencies, eventCondition, factory, method.Module, @event.GetCustomAttributes(), new EventPseudoDesc(method.OwningType, eventHandle));
}
}
}

public static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyList dependencies, NodeFactory factory, EcmaType type)
Expand All @@ -108,6 +77,16 @@ public static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyLi
AddDependenciesDueToCustomAttributes(ref dependencies, GetMetadataApiDependency(factory, "Field"u8), factory, field.Module, fieldDef.GetCustomAttributes(), field);
}

public static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyList dependencies, NodeFactory factory, PropertyPseudoDesc property)
{
AddDependenciesDueToCustomAttributes(ref dependencies, GetMetadataApiDependency(factory, "Property"u8), factory, property.OwningType.Module, property.GetCustomAttributes, property);
}

public static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyList dependencies, NodeFactory factory, EventPseudoDesc @event)
{
AddDependenciesDueToCustomAttributes(ref dependencies, GetMetadataApiDependency(factory, "Event"u8), factory, @event.OwningType.Module, @event.GetCustomAttributes, @event);
}

public static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyList dependencies, NodeFactory factory, EcmaAssembly assembly)
{
AssemblyDefinition asmDef = assembly.MetadataReader.GetAssemblyDefinition();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;

using ILCompiler.DependencyAnalysisFramework;

namespace ILCompiler.DependencyAnalysis
{
/// <summary>
/// Represents an event that has metadata generated in the current compilation.
/// This corresponds to an ECMA-335 Event record. Unlike fields and methods,
/// events are not first-class entities in the compiler's type system (there is no
/// interned EventDesc).
/// </summary>
/// <remarks>
/// Only expected to be used during ILScanning when scanning for reflection.
/// </remarks>
internal sealed class EventMetadataNode : DependencyNodeCore<NodeFactory>
{
private readonly EventPseudoDesc _event;

public EventMetadataNode(EventPseudoDesc @event)
{
_event = @event;
}

public EventPseudoDesc Event => _event;

public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory) => null;

public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory)
{
var dependencies = new List<CombinedDependencyListEntry>();
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _event);
return dependencies;
}

protected override string GetName(NodeFactory factory)
{
return "Event metadata: " + _event.ToString();
}

public override bool InterestingForDynamicDependencyAnalysis => false;
public override bool HasDynamicDependencies => false;
public override bool HasConditionalStaticDependencies => true;
public override bool StaticDependenciesAreComputed => true;
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata;

using ILCompiler.Dataflow;
using ILCompiler.DependencyAnalysisFramework;
Expand All @@ -11,6 +13,7 @@

using Debug = System.Diagnostics.Debug;
using EcmaMethod = Internal.TypeSystem.Ecma.EcmaMethod;
using EcmaType = Internal.TypeSystem.Ecma.EcmaType;

namespace ILCompiler.DependencyAnalysis
{
Expand Down Expand Up @@ -85,6 +88,38 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
{
dependencies.Add(factory.AnalysisCharacteristic("StackTraceHiddenMetadataPresent"), "Method is StackTraceHidden");
}

// If this method is a property or event accessor, ensure metadata for the associated
// property or event is generated as well. Properties/events are not modeled as first-class
// entities in the type system, so we discover them here from their accessors.
// As a performance optimization, only SpecialName methods can be accessors.
if ((_method.Attributes & MethodAttributes.SpecialName) != 0)
{
MetadataReader reader = _method.MetadataReader;
MethodDefinitionHandle methodHandle = _method.Handle;
TypeDefinition declaringType = reader.GetTypeDefinition(reader.GetMethodDefinition(methodHandle).GetDeclaringType());
foreach (PropertyDefinitionHandle propertyHandle in declaringType.GetProperties())
{
PropertyAccessors accessors = reader.GetPropertyDefinition(propertyHandle).GetAccessors();
if (accessors.Getter == methodHandle || accessors.Setter == methodHandle)
{
dependencies.Add(
factory.PropertyMetadata(new PropertyPseudoDesc((EcmaType)owningType, propertyHandle)),
"Property associated with reflectable accessor");
}
}

foreach (EventDefinitionHandle eventHandle in declaringType.GetEvents())
{
EventAccessors accessors = reader.GetEventDefinition(eventHandle).GetAccessors();
if (accessors.Adder == methodHandle || accessors.Remover == methodHandle || accessors.Raiser == methodHandle)
{
dependencies.Add(
factory.EventMetadata(new EventPseudoDesc((EcmaType)owningType, eventHandle)),
"Event associated with reflectable accessor");
}
}
}
}

return dependencies;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,16 @@ private void CreateNodeCaches()
return new FieldMetadataNode(field);
});

_propertiesWithMetadata = new NodeCache<PropertyPseudoDesc, PropertyMetadataNode>(property =>
{
return new PropertyMetadataNode(property);
});

_eventsWithMetadata = new NodeCache<EventPseudoDesc, EventMetadataNode>(@event =>
{
return new EventMetadataNode(@event);
});

_modulesWithMetadata = new NodeCache<ModuleDesc, ModuleMetadataNode>(module =>
{
return new ModuleMetadataNode(module);
Expand Down Expand Up @@ -1462,6 +1472,26 @@ internal FieldMetadataNode FieldMetadata(FieldDesc field)
return _fieldsWithMetadata.GetOrAdd(field);
}

private NodeCache<PropertyPseudoDesc, PropertyMetadataNode> _propertiesWithMetadata;

internal PropertyMetadataNode PropertyMetadata(PropertyPseudoDesc property)
{
// These are only meaningful for UsageBasedMetadataManager. We should not have them
// in the dependency graph otherwise.
Debug.Assert(MetadataManager is UsageBasedMetadataManager);
return _propertiesWithMetadata.GetOrAdd(property);
}

private NodeCache<EventPseudoDesc, EventMetadataNode> _eventsWithMetadata;

internal EventMetadataNode EventMetadata(EventPseudoDesc @event)
{
// These are only meaningful for UsageBasedMetadataManager. We should not have them
// in the dependency graph otherwise.
Debug.Assert(MetadataManager is UsageBasedMetadataManager);
return _eventsWithMetadata.GetOrAdd(@event);
}

private NodeCache<ModuleDesc, ModuleMetadataNode> _modulesWithMetadata;

internal ModuleMetadataNode ModuleMetadata(ModuleDesc module)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;

using ILCompiler.DependencyAnalysisFramework;

namespace ILCompiler.DependencyAnalysis
{
/// <summary>
/// Represents a property that has metadata generated in the current compilation.
/// This corresponds to an ECMA-335 Property record. Unlike fields and methods,
/// properties are not first-class entities in the compiler's type system (there is no
/// interned PropertyDesc).
/// </summary>
/// <remarks>
/// Only expected to be used during ILScanning when scanning for reflection.
/// </remarks>
internal sealed class PropertyMetadataNode : DependencyNodeCore<NodeFactory>
{
private readonly PropertyPseudoDesc _property;

public PropertyMetadataNode(PropertyPseudoDesc property)
{
_property = property;
}

public PropertyPseudoDesc Property => _property;

public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory) => null;

public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory)
{
var dependencies = new List<CombinedDependencyListEntry>();
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _property);
return dependencies;
}

protected override string GetName(NodeFactory factory)
{
return "Property metadata: " + _property.ToString();
}

public override bool InterestingForDynamicDependencyAnalysis => false;
public override bool HasDynamicDependencies => false;
public override bool HasConditionalStaticDependencies => true;
public override bool StaticDependenciesAreComputed => true;
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,9 @@
<Compile Include="Compiler\DependencyAnalysis\TrimmingDescriptorNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\VariantInterfaceMethodUseNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\CustomAttributeBasedDependencyAlgorithm.cs" />
<Compile Include="Compiler\DependencyAnalysis\EventMetadataNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\FieldMetadataNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\PropertyMetadataNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\ILScanNodeFactory.cs" />
<Compile Include="Compiler\DictionaryLayoutProvider.cs" />
<Compile Include="Compiler\Disassembler.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ class AttributesOnProperty
[Kept]
[KeptAttributeAttribute(typeof(KeepsPublicMethodsAttribute))]
[ExpectedWarning("IL2026", "--ClassWithKeptPublicMethods--")]
[UnexpectedWarning("IL2026", "--ClassWithKeptPublicMethods--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/120004")]
[KeepsPublicMethods(Type = typeof(ClassWithKeptPublicMethods))]
public static bool Property { [Kept] get; [Kept] set; }

Expand Down Expand Up @@ -175,7 +174,6 @@ class AttributesOnEvent
[KeptEventRemoveMethod]
[KeptAttributeAttribute(typeof(KeepsPublicMethodsAttribute))]
[ExpectedWarning("IL2026", "--ClassWithKeptPublicMethods--")]
[UnexpectedWarning("IL2026", "--ClassWithKeptPublicMethods--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/120004")]
[KeepsPublicMethods(Type = typeof(ClassWithKeptPublicMethods))]
public static event EventHandler Event_FieldSyntax;

Expand All @@ -185,7 +183,6 @@ class AttributesOnEvent
[KeptEventRemoveMethod]
[KeptAttributeAttribute(typeof(KeepsPublicMethodsAttribute))]
[ExpectedWarning("IL2026", "--ClassWithKeptPublicMethods--")]
[UnexpectedWarning("IL2026", "--ClassWithKeptPublicMethods--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/120004")]
[KeepsPublicMethods(Type = typeof(ClassWithKeptPublicMethods))]
public static event EventHandler Event_PropertySyntax
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,11 @@ static void MethodWithAttributeWhichRequires() { }
static int _fieldWithAttributeWhichRequires;

[ExpectedWarning("IL2026", "--AttributeWhichRequiresAttribute.ctor--")]
[UnexpectedWarning("IL2026", "--AttributeWhichRequiresAttribute.ctor--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/120004")]
[ExpectedWarning("IL3002", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "NativeAOT-specific warning")]
[UnexpectedWarning("IL3002", "--AttributeWhichRequiresAttribute.ctor--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/120004")]
[ExpectedWarning("IL3050", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "NativeAOT-specific warning")]
[UnexpectedWarning("IL3050", "--AttributeWhichRequiresAttribute.ctor--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/120004")]
[ExpectedWarning("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")]
[UnexpectedWarning("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/120004")]
[ExpectedWarning("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT-specific warning")]
[UnexpectedWarning("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/120004")]
[ExpectedWarning("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT-specific warning")]
[UnexpectedWarning("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/120004")]
[AttributeWhichRequires]
[AttributeWhichRequiresOnProperty(PropertyWhichRequires = true)]
static bool PropertyWithAttributeWhichRequires { get; set; }
Expand Down
Loading