7 Commits
Author SHA1 Message Date
ds5678 c164acde5f Bump version 2025-01-23 14:28:47 -08:00
ds5678 8935137a6f Expand type check to include PointerTypeSignature
Modified conditions in CilInstructionCollectionExtensions.cs to check for both ByReferenceTypeSignature and PointerTypeSignature. This ensures null references are added and stored for both types.
2025-01-23 14:27:38 -08:00
ds5678 7e3e7bfa8c Bump version 2025-01-11 01:07:46 -08:00
ds5678 777fb5ea1c Fix AddLoadIndirect and AddStoreIndirect
* Resolves #1
2025-01-11 01:07:24 -08:00
ds5678 be8f11f6b5 Fix incorrect field references for generic types 2025-01-10 23:47:59 -08:00
ds5678 1338ca2f95 Add method stubbing tool 2025-01-10 23:46:05 -08:00
ds5678 e95ff3bae6 Bump tools to .NET 9 2025-01-10 23:45:32 -08:00
11 changed files with 372 additions and 17 deletions

No files matched your search

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\AssetRipper.CIL\AssetRipper.CIL.csproj" />
</ItemGroup>
</Project>
+18
View File
@@ -0,0 +1,18 @@
using AsmResolver.DotNet;
namespace AssetRipper.CIL.Stubber
{
internal class Program
{
static void Main(string[] args)
{
ModuleDefinition module = ModuleDefinition.FromFile(args[0]);
foreach (MethodDefinition method in module.GetAllTypes().SelectMany(t => t.Methods))
{
method.ReplaceMethodBodyWithMinimalImplementation();
}
module.Write(args[1]);
Console.WriteLine("Done!");
}
}
}
@@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="NUnit" Version="4.3.2" />
<PackageReference Include="NUnit.Analyzers" Version="4.6.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AssetRipper.CIL\AssetRipper.CIL.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="NUnit.Framework" />
</ItemGroup>
</Project>
+113
View File
@@ -0,0 +1,113 @@
using AsmResolver.DotNet;
using AsmResolver.DotNet.Code.Cil;
using AsmResolver.DotNet.Signatures;
using AsmResolver.PE.DotNet.Cil;
using AsmResolver.PE.DotNet.Metadata.Tables;
namespace AssetRipper.CIL.Tests;
public class LoadIndirectTests
{
[TestCase(ElementType.I1, CilCode.Ldind_I1)]
[TestCase(ElementType.I2, CilCode.Ldind_I2)]
[TestCase(ElementType.I4, CilCode.Ldind_I4)]
[TestCase(ElementType.I8, CilCode.Ldind_I8)]
[TestCase(ElementType.U1, CilCode.Ldind_U1)]
[TestCase(ElementType.U2, CilCode.Ldind_U2)]
[TestCase(ElementType.U4, CilCode.Ldind_U4)]
[TestCase(ElementType.U8, CilCode.Ldind_I8)]
[TestCase(ElementType.I, CilCode.Ldind_I)]
[TestCase(ElementType.U, CilCode.Ldind_I)]
[TestCase(ElementType.R4, CilCode.Ldind_R4)]
[TestCase(ElementType.R8, CilCode.Ldind_R8)]
[TestCase(ElementType.Boolean, CilCode.Ldind_U1)]
[TestCase(ElementType.Char, CilCode.Ldind_U2)]
[TestCase(ElementType.Object, CilCode.Ldind_Ref)]
[TestCase(ElementType.String, CilCode.Ldind_Ref)]
[TestCase(ElementType.TypedByRef, CilCode.Ldobj)]
public void CorlibLoadIndirect(ElementType type, CilCode code)
{
ModuleDefinition module = new ModuleDefinition("TestModule");
CorLibTypeSignature? typeToLoad = module.CorLibTypeFactory.FromElementType(type);
Assert.That(typeToLoad, Is.Not.Null);
AssertCorrectLoadIndirect(typeToLoad, code);
}
[TestCase(ElementType.I1, CilCode.Ldind_I1)]
[TestCase(ElementType.I2, CilCode.Ldind_I2)]
[TestCase(ElementType.I4, CilCode.Ldind_I4)]
[TestCase(ElementType.I8, CilCode.Ldind_I8)]
[TestCase(ElementType.U1, CilCode.Ldind_U1)]
[TestCase(ElementType.U2, CilCode.Ldind_U2)]
[TestCase(ElementType.U4, CilCode.Ldind_U4)]
[TestCase(ElementType.U8, CilCode.Ldind_I8)]
public void EnumLoadIndirect(ElementType type, CilCode code)
{
ModuleDefinition module = new ModuleDefinition("TestModule");
TypeSignature? typeToLoad = CreateEnum(module, type).ToTypeSignature();
Assert.That(typeToLoad, Is.Not.Null);
AssertCorrectLoadIndirect(typeToLoad, code);
}
[Test]
public void PointerLoadIndirect()
{
ModuleDefinition module = new ModuleDefinition("TestModule");
PointerTypeSignature typeToLoad = module.CorLibTypeFactory.Void.MakePointerType();
AssertCorrectLoadIndirect(typeToLoad, CilCode.Ldind_I);
}
[Test]
public void GenericParameterLoadIndirect()
{
ModuleDefinition module = new ModuleDefinition("TestModule");
GenericParameterSignature typeToLoad = new GenericParameterSignature(module, GenericParameterType.Type, 0);
AssertCorrectLoadIndirect(typeToLoad, CilCode.Ldobj);
}
[Test]
public void SzArrayLoadIndirect()
{
ModuleDefinition module = new ModuleDefinition("TestModule");
TypeSignature typeToLoad = module.CorLibTypeFactory.Int32.MakeSzArrayType();
AssertCorrectLoadIndirect(typeToLoad, CilCode.Ldind_Ref);
}
[Test]
public void ClassLoadIndirect()
{
ModuleDefinition module = new ModuleDefinition("TestModule");
TypeDefinition type = new TypeDefinition("TestNamespace", "TestName", TypeAttributes.Public, module.CorLibTypeFactory.Object.ToTypeDefOrRef());
module.TopLevelTypes.Add(type);
AssertCorrectLoadIndirect(type.ToTypeSignature(), CilCode.Ldind_Ref);
}
[Test]
public void StructLoadIndirect()
{
ModuleDefinition module = new ModuleDefinition("TestModule");
TypeDefinition type = new TypeDefinition("TestNamespace", "TestName", TypeAttributes.Public | TypeAttributes.SequentialLayout | TypeAttributes.Sealed, module.DefaultImporter.ImportType(typeof(ValueType)));
module.TopLevelTypes.Add(type);
AssertCorrectLoadIndirect(type.ToTypeSignature(), CilCode.Ldobj);
}
private static void AssertCorrectLoadIndirect(TypeSignature typeToLoad, CilCode expectedOpCode)
{
MethodDefinition method = new MethodDefinition("Test", MethodAttributes.Public | MethodAttributes.Static, null);
method.CilMethodBody = new(method);
CilInstructionCollection instructions = method.CilMethodBody.Instructions;
instructions.AddLoadIndirect(typeToLoad);
Assert.That(instructions, Has.Count.EqualTo(1));
Assert.That(instructions[0].OpCode.Code, Is.EqualTo(expectedOpCode));
}
private static TypeDefinition CreateEnum(ModuleDefinition module, ElementType underlyingType)
{
TypeDefinition enumType = new TypeDefinition("TestNamespace", "TestEnum", TypeAttributes.Public, module.DefaultImporter.ImportType(typeof(Enum)));
module.TopLevelTypes.Add(enumType);
CorLibTypeSignature underlyingTypeSignature = module.CorLibTypeFactory.FromElementType(underlyingType) ?? throw new NullReferenceException();
FieldDefinition valueField = new FieldDefinition("value__", FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RuntimeSpecialName, underlyingTypeSignature);
enumType.Fields.Add(valueField);
return enumType;
}
}
+113
View File
@@ -0,0 +1,113 @@
using AsmResolver.DotNet;
using AsmResolver.DotNet.Code.Cil;
using AsmResolver.DotNet.Signatures;
using AsmResolver.PE.DotNet.Cil;
using AsmResolver.PE.DotNet.Metadata.Tables;
namespace AssetRipper.CIL.Tests;
public class StoreIndirectTests
{
[TestCase(ElementType.I1, CilCode.Stind_I1)]
[TestCase(ElementType.I2, CilCode.Stind_I2)]
[TestCase(ElementType.I4, CilCode.Stind_I4)]
[TestCase(ElementType.I8, CilCode.Stind_I8)]
[TestCase(ElementType.U1, CilCode.Stind_I1)]
[TestCase(ElementType.U2, CilCode.Stind_I2)]
[TestCase(ElementType.U4, CilCode.Stind_I4)]
[TestCase(ElementType.U8, CilCode.Stind_I8)]
[TestCase(ElementType.I, CilCode.Stind_I)]
[TestCase(ElementType.U, CilCode.Stind_I)]
[TestCase(ElementType.R4, CilCode.Stind_R4)]
[TestCase(ElementType.R8, CilCode.Stind_R8)]
[TestCase(ElementType.Boolean, CilCode.Stind_I1)]
[TestCase(ElementType.Char, CilCode.Stind_I2)]
[TestCase(ElementType.Object, CilCode.Stind_Ref)]
[TestCase(ElementType.String, CilCode.Stind_Ref)]
[TestCase(ElementType.TypedByRef, CilCode.Stobj)]
public void CorlibStoreIndirect(ElementType type, CilCode code)
{
ModuleDefinition module = new ModuleDefinition("TestModule");
CorLibTypeSignature? typeToStore = module.CorLibTypeFactory.FromElementType(type);
Assert.That(typeToStore, Is.Not.Null);
AssertCorrectStoreIndirect(typeToStore, code);
}
[TestCase(ElementType.I1, CilCode.Stind_I1)]
[TestCase(ElementType.I2, CilCode.Stind_I2)]
[TestCase(ElementType.I4, CilCode.Stind_I4)]
[TestCase(ElementType.I8, CilCode.Stind_I8)]
[TestCase(ElementType.U1, CilCode.Stind_I1)]
[TestCase(ElementType.U2, CilCode.Stind_I2)]
[TestCase(ElementType.U4, CilCode.Stind_I4)]
[TestCase(ElementType.U8, CilCode.Stind_I8)]
public void EnumStoreIndirect(ElementType type, CilCode code)
{
ModuleDefinition module = new ModuleDefinition("TestModule");
TypeSignature? typeToStore = CreateEnum(module, type).ToTypeSignature();
Assert.That(typeToStore, Is.Not.Null);
AssertCorrectStoreIndirect(typeToStore, code);
}
[Test]
public void PointerStoreIndirect()
{
ModuleDefinition module = new ModuleDefinition("TestModule");
PointerTypeSignature typeToStore = module.CorLibTypeFactory.Void.MakePointerType();
AssertCorrectStoreIndirect(typeToStore, CilCode.Stind_I);
}
[Test]
public void GenericParameterStoreIndirect()
{
ModuleDefinition module = new ModuleDefinition("TestModule");
GenericParameterSignature typeToStore = new GenericParameterSignature(module, GenericParameterType.Type, 0);
AssertCorrectStoreIndirect(typeToStore, CilCode.Stobj);
}
[Test]
public void SzArrayStoreIndirect()
{
ModuleDefinition module = new ModuleDefinition("TestModule");
TypeSignature typeToStore = module.CorLibTypeFactory.Int32.MakeSzArrayType();
AssertCorrectStoreIndirect(typeToStore, CilCode.Stind_Ref);
}
[Test]
public void ClassStoreIndirect()
{
ModuleDefinition module = new ModuleDefinition("TestModule");
TypeDefinition type = new TypeDefinition("TestNamespace", "TestName", TypeAttributes.Public, module.CorLibTypeFactory.Object.ToTypeDefOrRef());
module.TopLevelTypes.Add(type);
AssertCorrectStoreIndirect(type.ToTypeSignature(), CilCode.Stind_Ref);
}
[Test]
public void StructStoreIndirect()
{
ModuleDefinition module = new ModuleDefinition("TestModule");
TypeDefinition type = new TypeDefinition("TestNamespace", "TestName", TypeAttributes.Public | TypeAttributes.SequentialLayout | TypeAttributes.Sealed, module.DefaultImporter.ImportType(typeof(ValueType)));
module.TopLevelTypes.Add(type);
AssertCorrectStoreIndirect(type.ToTypeSignature(), CilCode.Stobj);
}
private static void AssertCorrectStoreIndirect(TypeSignature typeToStore, CilCode expectedOpCode)
{
MethodDefinition method = new MethodDefinition("Test", MethodAttributes.Public | MethodAttributes.Static, null);
method.CilMethodBody = new(method);
CilInstructionCollection instructions = method.CilMethodBody.Instructions;
instructions.AddStoreIndirect(typeToStore);
Assert.That(instructions, Has.Count.EqualTo(1));
Assert.That(instructions[0].OpCode.Code, Is.EqualTo(expectedOpCode));
}
private static TypeDefinition CreateEnum(ModuleDefinition module, ElementType underlyingType)
{
TypeDefinition enumType = new TypeDefinition("TestNamespace", "TestEnum", TypeAttributes.Public, module.DefaultImporter.ImportType(typeof(Enum)));
module.TopLevelTypes.Add(enumType);
CorLibTypeSignature underlyingTypeSignature = module.CorLibTypeFactory.FromElementType(underlyingType) ?? throw new NullReferenceException();
FieldDefinition valueField = new FieldDefinition("value__", FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RuntimeSpecialName, underlyingTypeSignature);
enumType.Fields.Add(valueField);
return enumType;
}
}
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
+12
View File
@@ -18,6 +18,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetRipper.CIL.Validator",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetRipper.CIL.Standardizer", "AssetRipper.CIL.Standardizer\AssetRipper.CIL.Standardizer.csproj", "{9E6D8580-5C3C-4AA8-89C9-34F475B79B24}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetRipper.CIL.Stubber", "AssetRipper.CIL.Stubber\AssetRipper.CIL.Stubber.csproj", "{A35A3452-2211-4DF5-A5A5-406FDF1E1A76}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetRipper.CIL.Tests", "AssetRipper.CIL.Tests\AssetRipper.CIL.Tests.csproj", "{FC03589F-7457-45E7-9628-F9E003F30BAB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -36,6 +40,14 @@ Global
{9E6D8580-5C3C-4AA8-89C9-34F475B79B24}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9E6D8580-5C3C-4AA8-89C9-34F475B79B24}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9E6D8580-5C3C-4AA8-89C9-34F475B79B24}.Release|Any CPU.Build.0 = Release|Any CPU
{A35A3452-2211-4DF5-A5A5-406FDF1E1A76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A35A3452-2211-4DF5-A5A5-406FDF1E1A76}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A35A3452-2211-4DF5-A5A5-406FDF1E1A76}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A35A3452-2211-4DF5-A5A5-406FDF1E1A76}.Release|Any CPU.Build.0 = Release|Any CPU
{FC03589F-7457-45E7-9628-F9E003F30BAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC03589F-7457-45E7-9628-F9E003F30BAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC03589F-7457-45E7-9628-F9E003F30BAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC03589F-7457-45E7-9628-F9E003F30BAB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -22,7 +22,7 @@ public static class CilInstructionCollectionExtensions
{
instructions.AddDefaultPrimitiveValue(corLibTypeSignature);
}
else if (type is ByReferenceTypeSignature)
else if (type is ByReferenceTypeSignature or PointerTypeSignature)
{
instructions.AddNullRef();
}
@@ -43,7 +43,7 @@ public static class CilInstructionCollectionExtensions
{
instructions.InitializeDefaultPrimitiveValue(corLibTypeSignature, localVariable);
}
else if (type is ByReferenceTypeSignature)
else if (type is ByReferenceTypeSignature or PointerTypeSignature)
{
instructions.AddNullRef();
instructions.Add(CilOpCodes.Stloc, localVariable);
@@ -129,17 +129,36 @@ public static class CilInstructionCollectionExtensions
ElementType.I2 => instructions.Add(CilOpCodes.Ldind_I2),
ElementType.I4 => instructions.Add(CilOpCodes.Ldind_I4),
ElementType.I8 or ElementType.U8 => instructions.Add(CilOpCodes.Ldind_I8),
ElementType.U1 => instructions.Add(CilOpCodes.Ldind_U1),
ElementType.U2 => instructions.Add(CilOpCodes.Ldind_U2),
ElementType.U1 or ElementType.Boolean => instructions.Add(CilOpCodes.Ldind_U1),
ElementType.U2 or ElementType.Char => instructions.Add(CilOpCodes.Ldind_U2),
ElementType.U4 => instructions.Add(CilOpCodes.Ldind_U4),
ElementType.R4 => instructions.Add(CilOpCodes.Ldind_R4),
ElementType.R8 => instructions.Add(CilOpCodes.Ldind_R8),
ElementType.I or ElementType.U => instructions.Add(CilOpCodes.Ldind_I),
ElementType.Object or ElementType.String => instructions.Add(CilOpCodes.Ldind_Ref),
_ => instructions.Add(CilOpCodes.Ldobj, type.ToTypeDefOrRef()),
},
PointerTypeSignature => instructions.Add(CilOpCodes.Ldind_I),
_ => instructions.Add(CilOpCodes.Ldobj, type.ToTypeDefOrRef()),
GenericParameterSignature => instructions.Add(CilOpCodes.Ldobj, type.ToTypeDefOrRef()),
TypeDefOrRefSignature t => AddTypeDefOrRef(instructions, t),
_ => AddUnknown(instructions, type),
};
static CilInstruction AddUnknown(CilInstructionCollection instructions, TypeSignature type)
{
return type.IsValueType
? instructions.Add(CilOpCodes.Ldobj, type.ToTypeDefOrRef())
: instructions.Add(CilOpCodes.Ldind_Ref);
}
static CilInstruction AddTypeDefOrRef(CilInstructionCollection instructions, TypeDefOrRefSignature type)
{
// Check if the type is an enum
TypeSignature underlyingType = type.GetUnderlyingType();
return underlyingType is CorLibTypeSignature
? instructions.AddLoadIndirect(underlyingType)
: AddUnknown(instructions, underlyingType);
}
}
public static CilInstruction AddStoreIndirect(this CilInstructionCollection instructions, TypeSignature type)
@@ -152,17 +171,36 @@ public static class CilInstructionCollectionExtensions
ElementType.I2 => instructions.Add(CilOpCodes.Stind_I2),
ElementType.I4 => instructions.Add(CilOpCodes.Stind_I4),
ElementType.I8 or ElementType.U8 => instructions.Add(CilOpCodes.Stind_I8),
ElementType.U1 => instructions.Add(CilOpCodes.Stind_I1),
ElementType.U2 => instructions.Add(CilOpCodes.Stind_I2),
ElementType.U1 or ElementType.Boolean => instructions.Add(CilOpCodes.Stind_I1),
ElementType.U2 or ElementType.Char => instructions.Add(CilOpCodes.Stind_I2),
ElementType.U4 => instructions.Add(CilOpCodes.Stind_I4),
ElementType.R4 => instructions.Add(CilOpCodes.Stind_R4),
ElementType.R8 => instructions.Add(CilOpCodes.Stind_R8),
ElementType.I or ElementType.U => instructions.Add(CilOpCodes.Stind_I),
ElementType.Object or ElementType.String => instructions.Add(CilOpCodes.Stind_Ref),
_ => instructions.Add(CilOpCodes.Stobj, type.ToTypeDefOrRef()),
},
PointerTypeSignature => instructions.Add(CilOpCodes.Stind_I),
_ => instructions.Add(CilOpCodes.Stobj, type.ToTypeDefOrRef()),
GenericParameterSignature => instructions.Add(CilOpCodes.Stobj, type.ToTypeDefOrRef()),
TypeDefOrRefSignature t => AddTypeDefOrRef(instructions, t),
_ => AddUnknown(instructions, type),
};
static CilInstruction AddUnknown(CilInstructionCollection instructions, TypeSignature type)
{
return type.IsValueType
? instructions.Add(CilOpCodes.Stobj, type.ToTypeDefOrRef())
: instructions.Add(CilOpCodes.Stind_Ref);
}
static CilInstruction AddTypeDefOrRef(CilInstructionCollection instructions, TypeDefOrRefSignature type)
{
// Check if the type is an enum
TypeSignature underlyingType = type.GetUnderlyingType();
return underlyingType is CorLibTypeSignature
? instructions.AddStoreIndirect(underlyingType)
: AddUnknown(instructions, underlyingType);
}
}
/// <summary>
+19 -5
View File
@@ -23,12 +23,12 @@ internal static class MethodStubber
{
if (methodDefinition.IsStatic)
{
methodInstructions.Add(CilOpCodes.Ldsfld, backingField);
methodInstructions.Add(CilOpCodes.Ldsfld, backingField.MakeGenericIfNecessary());
}
else
{
methodInstructions.Add(CilOpCodes.Ldarg_0);
methodInstructions.Add(CilOpCodes.Ldfld, backingField);
methodInstructions.Add(CilOpCodes.Ldfld, backingField.MakeGenericIfNecessary());
}
methodInstructions.Add(CilOpCodes.Ret);
return;
@@ -38,13 +38,13 @@ internal static class MethodStubber
if (methodDefinition.IsStatic)
{
methodInstructions.Add(CilOpCodes.Ldarg_0);
methodInstructions.Add(CilOpCodes.Stsfld, backingField);
methodInstructions.Add(CilOpCodes.Stsfld, backingField.MakeGenericIfNecessary());
}
else
{
methodInstructions.Add(CilOpCodes.Ldarg_0);
methodInstructions.Add(CilOpCodes.Ldarg_1);
methodInstructions.Add(CilOpCodes.Stfld, backingField);
methodInstructions.Add(CilOpCodes.Stfld, backingField.MakeGenericIfNecessary());
}
methodInstructions.Add(CilOpCodes.Ret);
return;
@@ -62,7 +62,7 @@ internal static class MethodStubber
methodInstructions.Add(CilOpCodes.Ldarg_0);
methodInstructions.AddDefaultValue(field.Signature.FieldType);
methodInstructions.Add(CilOpCodes.Stfld, field);
methodInstructions.Add(CilOpCodes.Stfld, field.MakeGenericIfNecessary());
}
}
@@ -181,4 +181,18 @@ internal static class MethodStubber
baseConstructor = TryGetBaseConstructor(methodDefinition);
return baseConstructor is not null;
}
private static IFieldDescriptor MakeGenericIfNecessary(this FieldDefinition field)
{
if (field.DeclaringType is null or { GenericParameters.Count: 0 })
{
return field;
}
TypeSignature[] typeArguments = Enumerable.Range(0, field.DeclaringType.GenericParameters.Count)
.Select(i => new GenericParameterSignature(field.Module, GenericParameterType.Type, i))
.ToArray();
return new MemberReference(field.DeclaringType.MakeGenericInstanceType(typeArguments).ToTypeDefOrRef(), field.Name, field.Signature);
}
}
+2 -2
View File
@@ -6,9 +6,9 @@
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<PolySharpIncludeRuntimeSupportedAttributes>true</PolySharpIncludeRuntimeSupportedAttributes>
<Version>1.1.3</Version>
<Version>1.1.5</Version>
<AssemblyVersion>$(Version)</AssemblyVersion>
<Copyright>Copyright (c) 2024 ds5678</Copyright>
<Copyright>Copyright (c) 2025 ds5678</Copyright>
<Authors>ds5678</Authors>
<Company>AssetRipper</Company>
<PackageLicenseExpression>MIT</PackageLicenseExpression>