Skip to content

Commit

Permalink
Support static abstract interface members. (#930)
Browse files Browse the repository at this point in the history
  • Loading branch information
lostmsu authored Feb 16, 2023
1 parent d090ff3 commit 851670d
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 67 deletions.
2 changes: 1 addition & 1 deletion Src/ILGPU.Tests/Configurations.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ DisassemblerTests
EnumValues
FixedBuffers
GetKernelTests
GenericMath
Indices
KernelEntryPoints
MemoryBufferOperations
Expand All @@ -14,6 +13,7 @@ ProfilingMarkers
SharedMemory
SizeOfValues
SpecializedKernels
StaticAbstractInterfaceMembers
StructureValues
ValueTuples
InteropTests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Copyright (c) 2022-2023 ILGPU Project
// www.ilgpu.net
//
// File: GenericMath.cs
// File: StaticAbstractInterfaceMembers.cs
//
// This file is part of ILGPU and is distributed under the University of Illinois Open
// Source License. See LICENSE.txt for details.
Expand All @@ -17,9 +17,11 @@

namespace ILGPU.Tests
{
public abstract class GenericMath : TestBase
public abstract class StaticAbstractInterfaceMembers : TestBase
{
protected GenericMath(ITestOutputHelper output, TestContext testContext)
protected StaticAbstractInterfaceMembers(
ITestOutputHelper output,
TestContext testContext)
: base(output, testContext)
{ }

Expand All @@ -34,6 +36,8 @@ public static T GeZeroIfBigger<T>(T value, T max) where T : INumber<T>
return value;
}

#region Generic math

internal static void GenericMathKernel<T>(
Index1D index,
ArrayView1D<T, Stride1D.Dense> input,
Expand Down Expand Up @@ -94,6 +98,56 @@ public void GenericMathDoubleTest()
TestGenericMathKernel(input, expected, MaxValue);
}

#endregion

internal static void IncrementingKernel<T>(
Index1D index,
ArrayView1D<int, Stride1D.Dense> input,
ArrayView1D<int, Stride1D.Dense> output)
where T : IStaticAbstract
{
output[index] = T.Inc(input[index]);
}

private void TestIncrementingKernel<T>(int[] inputValues, int[] expected)
where T : IStaticAbstract
{
using var input = Accelerator.Allocate1D<int>(inputValues);
using var output = Accelerator.Allocate1D<int>(Length);

using var start = Accelerator.DefaultStream.AddProfilingMarker();
Accelerator.LaunchAutoGrouped<
Index1D,
ArrayView1D<int, Stride1D.Dense>,
ArrayView1D<int, Stride1D.Dense>>(
IncrementingKernel<T>,
Accelerator.DefaultStream,
(int)input.Length,
input.View,
output.View);

Verify(output.View, expected);
}

public interface IStaticAbstract
{
static abstract int Inc(int x);
}

public class Incrementer: IStaticAbstract
{
public static int Inc(int x) => x + 1;
}

[Fact]
public void StaticInterfaceTest()
{
int[] input = Enumerable.Range(0, Length).ToArray();

int[] expected = input.Select(Incrementer.Inc).ToArray();

TestIncrementingKernel<Incrementer>(input, expected);
}
#endif
}
}
18 changes: 17 additions & 1 deletion Src/ILGPU/Frontend/CodeGenerator/Calls.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// ---------------------------------------------------------------------------------------
// ILGPU
// Copyright (c) 2018-2021 ILGPU Project
// Copyright (c) 2018-2023 ILGPU Project
// www.ilgpu.net
//
// File: Calls.cs
Expand Down Expand Up @@ -66,6 +66,22 @@ private void CreateCall(
}
}

/// <summary>
/// Realizes a call instruction.
/// </summary>
/// <param name="instruction">The instruction to realize.</param>
private void MakeCall(ILInstruction instruction)
{
var method = instruction.GetArgumentAs<MethodBase>();
if (instruction.HasFlags(ILInstructionFlags.Constrained)
&& method is MethodInfo methodInfo)
{
var constrainedType = instruction.FlagsContext.Argument as Type;
method = ResolveVirtualCallTarget(methodInfo, constrainedType);
}
MakeCall(method);
}

/// <summary>
/// Realizes a call instruction.
/// </summary>
Expand Down
5 changes: 2 additions & 3 deletions Src/ILGPU/Frontend/CodeGenerator/CodeGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// ---------------------------------------------------------------------------------------
// ILGPU
// Copyright (c) 2018-2022 ILGPU Project
// Copyright (c) 2018-2023 ILGPU Project
// www.ilgpu.net
//
// File: CodeGenerator.cs
Expand Down Expand Up @@ -142,8 +142,7 @@ private void SetupVariables()
}

// Initialize locals
var methodBody = Disassembler.ExtractMethodBody(Method);
var localVariables = methodBody.LocalVariables;
var localVariables = Method.GetMethodBody().LocalVariables;
for (int i = 0, e = localVariables.Count; i < e; ++i)
{
var variable = localVariables[i];
Expand Down
4 changes: 2 additions & 2 deletions Src/ILGPU/Frontend/CodeGenerator/Driver.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// ---------------------------------------------------------------------------------------
// ILGPU
// Copyright (c) 2018-2021 ILGPU Project
// Copyright (c) 2018-2023 ILGPU Project
// www.ilgpu.net
//
// File: Driver.cs
Expand Down Expand Up @@ -129,7 +129,7 @@ private bool TryGenerateCode(ILInstruction instruction)
MakeReturn();
return true;
case ILInstructionType.Call:
MakeCall(instruction.GetArgumentAs<MethodBase>());
MakeCall(instruction);
return true;
case ILInstructionType.Callvirt:
MakeVirtualCall(instruction);
Expand Down
60 changes: 3 additions & 57 deletions Src/ILGPU/Frontend/Disassembler.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// ---------------------------------------------------------------------------------------
// ILGPU
// Copyright (c) 2018-2022 ILGPU Project
// Copyright (c) 2018-2023 ILGPU Project
// www.ilgpu.net
//
// File: Disassembler.cs
Expand All @@ -15,7 +15,6 @@
using ILGPU.Util;
using System;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
Expand All @@ -28,60 +27,7 @@ namespace ILGPU.Frontend
/// <remarks>Members of this class are not thread safe.</remarks>
public sealed partial class Disassembler : ILocation
{
#region Static

/// <summary>
/// Indicates whether the .NET runtime has support for Static Abstract methods
/// in Interfaces.
/// </summary>
[SuppressMessage("Performance", "CA1802:Use literals where appropriate")]
private static readonly bool UsingStaticAbstractMethodsInInterfaces =
#if NET7_0_OR_GREATER
RuntimeFeature.IsSupported(RuntimeFeature.VirtualStaticsInInterfaces);
#else
false;
#endif

/// <summary>
/// Extracts the method body for the given method.
/// </summary>
/// <param name="method">The method.</param>
/// <returns>The method body.</returns>
public static MethodBody ExtractMethodBody(MethodBase method)
{
var methodBody = method.GetMethodBody();
if (methodBody == null &&
UsingStaticAbstractMethodsInInterfaces &&
method.DeclaringType.IsInterface &&
method.IsStatic &&
method.IsAbstract)
{
// Support for Static Abstract methods in Interfaces was introduced in
// C# 11, in particular, adding support for Generic Math. The interface
// itself does not contain the method implementation itself. Instead, we
// need to find the concrete type that implements the interface, and find
// the matching method.
var concreteType = method.DeclaringType.GetGenericArguments()[0];
var interfaceMap = concreteType.GetInterfaceMap(method.DeclaringType);

for (int i = 0; i < interfaceMap.InterfaceMethods.Length; i++)
{
if (interfaceMap.InterfaceMethods[i].Name.Equals(
method.Name,
StringComparison.OrdinalIgnoreCase))
{
methodBody = interfaceMap.TargetMethods[i].GetMethodBody();
break;
}
}
}

return methodBody;
}

#endregion

#region Constants
#region Constants

/// <summary>
/// Represents the native pointer type that is used during the
Expand Down Expand Up @@ -152,7 +98,7 @@ public Disassembler(
? MethodBase.GetGenericArguments()
: Array.Empty<Type>();
TypeGenericArguments = MethodBase.DeclaringType.GetGenericArguments();
MethodBody = ExtractMethodBody(MethodBase);
MethodBody = MethodBase.GetMethodBody();
if (MethodBody == null)
{
throw new NotSupportedException(string.Format(
Expand Down

0 comments on commit 851670d

Please sign in to comment.