Skip to content

Commit

Permalink
Add allows ref struct
Browse files Browse the repository at this point in the history
  • Loading branch information
ltrzesniewski committed Nov 12, 2024
1 parent c672114 commit 2f9851f
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 4 deletions.
24 changes: 24 additions & 0 deletions src/InlineIL.Tests.AssemblyToProcess/BasicTestCases.cs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,22 @@ public void ValidPushUsageWithEnsureLocal()
Call(new MethodRef(typeof(BasicTestCases), nameof(ValidatePushUsageWithEnsureLocal)));
}

#if NET9_0_OR_GREATER && CSHARP_13_OR_GREATER
public int PushAndPopRefStruct()
{
var input = new RefStruct
{
Value = 42
};

IL.Push(input);
input.Value = 0;

IL.Pop(out RefStruct output);
return output.Value;
}
#endif

private static void ValidatePushUsageWithEnsureLocal(int value, Guid guid)
{
if (value != 42 || guid == Guid.Empty)
Expand All @@ -318,4 +334,12 @@ public static int Call()
}
}
}

[SuppressMessage("ReSharper", "UnusedType.Local")]
private ref struct RefStruct
{
#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value
public int Value;
#pragma warning restore CS0649 // Field is never assigned to, and will always have its default value
}
}
13 changes: 13 additions & 0 deletions src/InlineIL.Tests.AssemblyToProcess/TypeRefTestCases.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ public RuntimeTypeHandle ReturnTypeHandleGeneric()
return IL.Return<RuntimeTypeHandle>();
}

#if NET9_0_OR_GREATER && CSHARP_13_OR_GREATER
public RuntimeTypeHandle ReturnTypeHandleGenericRefStruct()
{
Ldtoken<RefStruct>();
return IL.Return<RuntimeTypeHandle>();
}
#endif

public bool IsString(object obj)
{
Ldarg(nameof(obj));
Expand Down Expand Up @@ -216,4 +224,9 @@ public string ReturnCoreLibrary()
private class NestedType
{
}

[SuppressMessage("ReSharper", "UnusedType.Local")]
private ref struct RefStruct
{
}
}
20 changes: 19 additions & 1 deletion src/InlineIL.Tests/Weaving/BasicTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@

namespace InlineIL.Tests.Weaving;

public class BasicTests() : ClassTestsBase("BasicTestCases")
public abstract class BasicTestsBase() : ClassTestsBase("BasicTestCases");

public class BasicTests : BasicTestsBase
{
[Fact]
public void should_push_value()
Expand Down Expand Up @@ -521,6 +523,22 @@ public void should_detect_invalid_ensure_local_usage_3()
}
}

#if NET
[UsedImplicitly]
public class BasicTestsCore : BasicTestsBase
{
#if CSHARP_13_OR_GREATER
[Fact]
public void should_push_and_pop_ref_struct()
{
var result = (int)GetInstance().PushAndPopRefStruct();

result.ShouldEqual(42);
}
#endif
}
#endif

[UsedImplicitly]
public class BasicTestsStandard : BasicTests
{
Expand Down
9 changes: 9 additions & 0 deletions src/InlineIL.Tests/Weaving/TypeRefTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,15 @@ public void should_map_forwarded_type_to_forwarder()
var assemblyName = typeRef.Scope.ShouldBe<AssemblyNameReference>();
assemblyName.Name.ShouldEqual("System.Runtime.Extensions");
}

#if CSHARP_13_OR_GREATER
[Fact]
public void should_handle_type_token_load_generic_ref_struct()
{
var handle = (RuntimeTypeHandle)GetInstance().ReturnTypeHandleGenericRefStruct();
Type.GetTypeFromHandle(handle).ShouldNotBeNull().FullName.ShouldEqual($"{_verifiableAssembly}.TypeRefTestCases+RefStruct");
}
#endif
}
#endif

Expand Down
54 changes: 54 additions & 0 deletions src/InlineIL/IL.Emit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,9 @@ public static void Cpobj(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Cpobj<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand All @@ -1162,6 +1165,9 @@ public static void Ldobj(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Ldobj<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand Down Expand Up @@ -1202,6 +1208,9 @@ public static void Castclass(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Castclass<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand All @@ -1222,6 +1231,9 @@ public static void Isinst(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Isinst<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand Down Expand Up @@ -1251,6 +1263,9 @@ public static void Unbox(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Unbox<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand Down Expand Up @@ -1340,6 +1355,9 @@ public static void Stobj(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Stobj<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand Down Expand Up @@ -1450,6 +1468,9 @@ public static void Box(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Box<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand All @@ -1470,6 +1491,9 @@ public static void Newarr(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Newarr<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand Down Expand Up @@ -1499,6 +1523,9 @@ public static void Ldelema(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Ldelema<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand Down Expand Up @@ -1690,6 +1717,9 @@ public static void Ldelem_Any(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Ldelem_Any<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand All @@ -1710,6 +1740,9 @@ public static void Stelem_Any(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Stelem_Any<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand All @@ -1730,6 +1763,9 @@ public static void Unbox_Any(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Unbox_Any<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand Down Expand Up @@ -1822,6 +1858,9 @@ public static void Refanyval(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Refanyval<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand Down Expand Up @@ -1851,6 +1890,9 @@ public static void Mkrefany(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Mkrefany<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand All @@ -1871,6 +1913,9 @@ public static void Ldtoken(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Ldtoken<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand Down Expand Up @@ -2297,6 +2342,9 @@ public static void Initobj(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Initobj<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand All @@ -2317,6 +2365,9 @@ public static void Constrained(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Constrained<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand Down Expand Up @@ -2364,6 +2415,9 @@ public static void Sizeof(TypeRef type)
/// </remarks>
/// <typeparam name="T">The type reference.</typeparam>
public static void Sizeof<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <summary>
Expand Down
10 changes: 8 additions & 2 deletions src/InlineIL/IL.Emit.tt
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
var cecilCodes = typeof(OpCodes)
.GetFields(BindingFlags.Public | BindingFlags.Static)
.Where(field => field.IsInitOnly && field.FieldType == typeof(OpCode))
.Select(field => (fieldName: field.Name, opCode: (OpCode)field.GetValue(null)))
.Select(field => new { fieldName = field.Name, opCode = (OpCode)field.GetValue(null) })
.OrderBy(i => unchecked((ushort)i.opCode.Value))
.ToList();

var reflectionEmitCodes = typeof(System.Reflection.Emit.OpCodes)
.GetFields(BindingFlags.Public | BindingFlags.Static)
.Where(field => field.IsInitOnly && field.FieldType == typeof(System.Reflection.Emit.OpCode))
.Select(field => (fieldName: field.Name, opCode: (System.Reflection.Emit.OpCode)field.GetValue(null)))
.Select(field => new { fieldName = field.Name, opCode = (System.Reflection.Emit.OpCode)field.GetValue(null) })
.ToDictionary(i => i.opCode.Value);

var xmlDocs = XDocument.Load(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.X\mscorlib.xml"))!
Expand Down Expand Up @@ -268,6 +268,9 @@ partial class IL
/// <#= xmlDoc #>
/// <typeparam name="T">The type reference.</typeparam>
public static void <#= item.fieldName #><T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();
<#
break;
Expand Down Expand Up @@ -300,6 +303,9 @@ partial class IL
/// <#= xmlDoc #>
/// <typeparam name="T">The type reference.</typeparam>
public static void <#= item.fieldName #><T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> IL.Throw();

/// <#= xmlDoc #>
Expand Down
Loading

0 comments on commit 2f9851f

Please sign in to comment.