Skip to content

Commit

Permalink
Initial work to support virtual static interface methods (dotnet/link…
Browse files Browse the repository at this point in the history
…er#2072)

* Initial work to support static interface methods

* commit to allow Tlakaelel help me with the il test

* support for the runtime il test

* Incorporating feedback

* reverting a file that was checked in by mistake

* test updates

* generics tests restructuring

* tests

* fixed tests

* added a comment to clarify

* FB

Commit migrated from dotnet/linker@3fc88d4
  • Loading branch information
LakshanF authored Jun 10, 2021
1 parent 4e7c449 commit 6e2e0c9
Show file tree
Hide file tree
Showing 16 changed files with 53,003 additions and 3 deletions.
8 changes: 7 additions & 1 deletion src/tools/illink/src/linker/Linker.Steps/MarkStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,7 @@ void ProcessOverride (OverrideInformation overrideInformation)
if (IsInterfaceOverrideThatDoesNotNeedMarked (overrideInformation, isInstantiated))
return;

// Interface static veitual methods will be abstract and will also by pass this check to get marked
if (!isInstantiated && !@base.IsAbstract && _context.IsOptimizationEnabled (CodeOptimizations.OverrideRemoval, method))
return;

Expand All @@ -703,14 +704,19 @@ void ProcessOverride (OverrideInformation overrideInformation)
MarkMethod (method, new DependencyInfo (DependencyKind.Override, @base));
}

ProcessVirtualMethod (method);
if (method.IsVirtual)
ProcessVirtualMethod (method);
}

bool IsInterfaceOverrideThatDoesNotNeedMarked (OverrideInformation overrideInformation, bool isInstantiated)
{
if (!overrideInformation.IsOverrideOfInterfaceMember || isInstantiated)
return false;

// This is a static interface method and these checks should all be true
if (overrideInformation.Override.IsStatic && overrideInformation.Base.IsStatic && overrideInformation.Base.IsAbstract && !overrideInformation.Override.IsVirtual)
return false;

if (overrideInformation.MatchingInterfaceImplementation != null)
return !Annotations.IsMarked (overrideInformation.MatchingInterfaceImplementation);

Expand Down
7 changes: 5 additions & 2 deletions src/tools/illink/src/linker/Linker/TypeMapInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,13 @@ void MapVirtualMethods (TypeDefinition type)
return;

foreach (MethodDefinition method in type.Methods) {
if (!method.IsVirtual)
// We do not proceed unless a method is virtual or is static
// A static method with a .override could be implementing a static interface method
if (!(method.IsStatic || method.IsVirtual))
continue;

MapVirtualMethod (method);
if (method.IsVirtual)
MapVirtualMethod (method);

if (method.HasOverrides)
MapOverrides (method);
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

.assembly extern System.Runtime
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A)
}

.assembly 'library' { }

.class interface public abstract auto ansi InterfaceScenario1
{
.method public newslot virtual abstract static int32 Method() cil managed noinlining
{
} // end of method Method
} // end of class InterfaceScenario1
.class public auto ansi BaseScenario1
extends [System.Runtime]System.Object
implements InterfaceScenario1
{
.method public static int32 Method() cil managed noinlining
{
.override method int32 InterfaceScenario1::Method()
.locals init (int32 V_O)
ldloca.s 0
initobj int32
ldloc.0
ret
} // end of method Method
} // end of class BaseScenario1
.class public auto ansi DerivedScenario1
extends BaseScenario1
{
} // end of class DerivedScenario1
.class interface public abstract auto ansi InterfaceScenario2
{
.method public newslot virtual abstract static int32 Method() cil managed noinlining
{
} // end of method Method
} // end of class InterfaceScenario2
.class public auto ansi BaseScenario2
extends [System.Runtime]System.Object
implements InterfaceScenario2
{
.method public static int32 Method() cil managed noinlining
{
.override method int32 InterfaceScenario2::Method()
.locals init (int32 V_O)
ldloca.s 0
initobj int32
ldloc.0
ret
} // end of method Method
} // end of class BaseScenario2
.class public auto ansi DerivedScenario2
extends BaseScenario2
implements InterfaceScenario2
{
} // end of class DerivedScenario2
.class interface public abstract auto ansi InterfaceScenario3
{
.method public newslot virtual abstract static int32 Method() cil managed noinlining
{
} // end of method Method
} // end of class InterfaceScenario3
.class public abstract auto ansi BaseScenario3
extends [System.Runtime]System.Object
implements InterfaceScenario3
{
} // end of class BaseScenario3
.class public auto ansi DerivedScenario3
extends BaseScenario3
implements InterfaceScenario3
{
.method public static int32 MethodImplOnDerived() cil managed noinlining
{
.override method int32 InterfaceScenario3::Method()
.locals init (int32 V_O)
ldloca.s 0
initobj int32
ldloc.0
ret
} // end of method MethodImplOnDerived
} // end of class DerivedScenario3

.class public auto ansi TestEntrypoint
extends [System.Runtime]System.Object
{
.method public static void Test_Scenario1() cil managed noinlining
{
constrained. DerivedScenario1
call int32 InterfaceScenario1::Method()
pop
ret
} // end of method Test_Scenario1
.method public static void Test_Scenario2() cil managed noinlining
{
constrained. DerivedScenario2
call int32 InterfaceScenario2::Method()
pop
ret
} // end of method Test_Scenario2
.method public static void Test_Scenario3() cil managed noinlining
{
constrained. DerivedScenario3
call int32 InterfaceScenario3::Method()
pop
ret
} // end of method Test_Scenario3
.method public static int32 Test() cil managed noinlining
{
.locals init (class [System.Runtime]System.Exception V_0)
.try {
call void TestEntrypoint::Test_Scenario1()
call void TestEntrypoint::Test_Scenario2()
call void TestEntrypoint::Test_Scenario3()
leave.s Scenario1Done
} catch [System.Runtime]System.Exception {
stloc.0
leave.s Scenario1Done
}
Scenario1Done: nop
ret
} // end of method Test
} // end of class TestEntrypoint


Loading

0 comments on commit 6e2e0c9

Please sign in to comment.