Skip to content
Merged
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
56 changes: 30 additions & 26 deletions src/tools/illink/src/linker/Linker.Steps/MarkStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ protected LinkContext Context {
}

protected Queue<(MethodDefinition, DependencyInfo, MessageOrigin)> _methods;
protected Dictionary<MethodDefinition, MarkScopeStack.Scope> _virtual_methods;
protected Dictionary<MethodDefinition, MarkScopeStack.Scope> _interface_methods;
protected Queue<AttributeProviderPair> _assemblyLevelAttributes;
protected Queue<(AttributeProviderPair, DependencyInfo, MarkScopeStack.Scope)> _lateMarkedAttributes;
protected List<(TypeDefinition, MarkScopeStack.Scope)> _typesWithInterfaces;
Expand Down Expand Up @@ -219,7 +219,7 @@ internal DynamicallyAccessedMembersTypeHierarchy DynamicallyAccessedMembersTypeH
public MarkStep ()
{
_methods = new Queue<(MethodDefinition, DependencyInfo, MessageOrigin)> ();
_virtual_methods = new Dictionary<MethodDefinition, MarkScopeStack.Scope> ();
_interface_methods = new Dictionary<MethodDefinition, MarkScopeStack.Scope> ();
_assemblyLevelAttributes = new Queue<AttributeProviderPair> ();
_lateMarkedAttributes = new Queue<(AttributeProviderPair, DependencyInfo, MarkScopeStack.Scope)> ();
_typesWithInterfaces = new List<(TypeDefinition, MarkScopeStack.Scope)> ();
Expand Down Expand Up @@ -437,7 +437,7 @@ bool ProcessPrimaryQueue ()

while (!QueueIsEmpty ()) {
ProcessQueue ();
ProcessVirtualMethods ();
ProcessInterfaceMethods ();
ProcessMarkedTypesWithInterfaces ();
ProcessDynamicCastableImplementationInterfaces ();
ProcessPendingBodies ();
Expand Down Expand Up @@ -530,11 +530,11 @@ protected virtual void EnqueueMethod (MethodDefinition method, in DependencyInfo
_methods.Enqueue ((method, reason, origin));
}

void ProcessVirtualMethods ()
void ProcessInterfaceMethods ()
{
foreach ((var method, var scope) in _virtual_methods) {
foreach ((var method, var scope) in _interface_methods) {
using (ScopeStack.PushLocalScope (scope)) {
ProcessVirtualMethod (method);
ProcessInterfaceMethod (method);
}
}
}
Expand Down Expand Up @@ -568,7 +568,7 @@ void ProcessMarkedTypesWithInterfaces ()
continue;
foreach (var ov in baseMethods) {
if (ov.Base.DeclaringType is not null && ov.Base.DeclaringType.IsInterface && IgnoreScope (ov.Base.DeclaringType.Scope)) {
_virtual_methods.TryAdd (ov.Base, ScopeStack.CurrentScope);
MarkMethodAsVirtual (ov.Base, ScopeStack.CurrentScope);
}
}
}
Expand Down Expand Up @@ -651,28 +651,32 @@ void ProcessPendingBodies ()
}
}
}

void ProcessVirtualMethod (MethodDefinition method)
void MarkMethodAsVirtual (MethodDefinition method, MarkScopeStack.Scope scope)
{
Annotations.EnqueueVirtualMethod (method);

if (method.DeclaringType.IsInterface) {
var defaultImplementations = Annotations.GetDefaultInterfaceImplementations (method);
if (defaultImplementations is not null) {
foreach (var dimInfo in defaultImplementations) {
ProcessDefaultImplementation (dimInfo);
_interface_methods.TryAdd (method, scope);
}
}

if (IsInterfaceImplementationMethodNeededByTypeDueToInterface (dimInfo))
MarkMethod (dimInfo.Override, new DependencyInfo (DependencyKind.Override, dimInfo.Base), ScopeStack.CurrentScope.Origin);
}
void ProcessInterfaceMethod (MethodDefinition method)
{
Debug.Assert (method.DeclaringType.IsInterface);
var defaultImplementations = Annotations.GetDefaultInterfaceImplementations (method);
if (defaultImplementations is not null) {
foreach (var dimInfo in defaultImplementations) {
ProcessDefaultImplementation (dimInfo);

if (IsInterfaceImplementationMethodNeededByTypeDueToInterface (dimInfo))
MarkMethod (dimInfo.Override, new DependencyInfo (DependencyKind.Override, dimInfo.Base), ScopeStack.CurrentScope.Origin);
}
List<OverrideInformation>? overridingMethods = (List<OverrideInformation>?)Annotations.GetOverrides (method);
if (overridingMethods is not null) {
for (int i = 0; i < overridingMethods.Count; i++) {
OverrideInformation ov = overridingMethods[i];
if (IsInterfaceImplementationMethodNeededByTypeDueToInterface (ov))
MarkMethod (ov.Override, new DependencyInfo (DependencyKind.Override, ov.Base), ScopeStack.CurrentScope.Origin);
}
}
List<OverrideInformation>? overridingMethods = (List<OverrideInformation>?)Annotations.GetOverrides (method);
if (overridingMethods is not null) {
for (int i = 0; i < overridingMethods.Count; i++) {
OverrideInformation ov = overridingMethods[i];
if (IsInterfaceImplementationMethodNeededByTypeDueToInterface (ov))
MarkMethod (ov.Override, new DependencyInfo (DependencyKind.Override, ov.Base), ScopeStack.CurrentScope.Origin);
}
}
}
Expand Down Expand Up @@ -3227,7 +3231,7 @@ protected virtual void ProcessMethod (MethodDefinition method, in DependencyInfo
MarkMethodSpecialCustomAttributes (method);

if (method.IsVirtual)
_virtual_methods.TryAdd (method, ScopeStack.CurrentScope);
MarkMethodAsVirtual (method, ScopeStack.CurrentScope);

MarkNewCodeDependencies (method);

Expand Down Expand Up @@ -3435,7 +3439,7 @@ void MarkBaseMethods (MethodDefinition method)
// This will produce warnings for all interface methods and virtual methods regardless of whether the interface, interface implementation, or interface method is kept or not.
if (ov.Base.DeclaringType.IsInterface && !method.DeclaringType.IsInterface) {
// These are all virtual, no need to check IsVirtual before adding to list
_virtual_methods.TryAdd (ov.Base, ScopeStack.CurrentScope);
MarkMethodAsVirtual (ov.Base, ScopeStack.CurrentScope);
continue;
}

Expand Down