Skip to content

Commit

Permalink
Improve Generics Unstripping
Browse files Browse the repository at this point in the history
  • Loading branch information
ds5678 committed Sep 14, 2024
1 parent 89b8d31 commit bba128e
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 22 deletions.
5 changes: 4 additions & 1 deletion Il2CppInterop.Generator/Passes/Pass80UnstripMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,12 @@ private static PropertyDefinition GetOrCreateProperty(MethodDefinition unityMeth
internal static TypeSignature? ResolveTypeInNewAssembliesRaw(RewriteGlobalContext context, TypeSignature? unityType,
RuntimeAssemblyReferences imports)
{
if (unityType is null or GenericParameterSignature)
if (unityType is null)
return null;

if (unityType is GenericParameterSignature genericParameterSignature)
return new GenericParameterSignature(imports.Module, genericParameterSignature.ParameterType, genericParameterSignature.Index);

if (unityType is ByReferenceTypeSignature)
{
var resolvedElementType = ResolveTypeInNewAssemblies(context, unityType.GetElementType(), imports);
Expand Down
46 changes: 25 additions & 21 deletions Il2CppInterop.Generator/Utils/UnstripTranslator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public static bool TranslateMethod(MethodDefinition original, MethodDefinition t
var methodDeclarer =
Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, methodArg.DeclaringType?.ToTypeSignature(), imports);
if (methodDeclarer == null)
return false; // todo: generic methods
return false;

var newReturnType =
Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, methodArg.Signature?.ReturnType, imports);
Expand All @@ -166,36 +166,40 @@ public static bool TranslateMethod(MethodDefinition original, MethodDefinition t
newMethodSignature.ParameterTypes.Add(newParamType);
}

var newMethod = new MemberReference(methodDeclarer.ToTypeDefOrRef(), methodArg.Name, newMethodSignature);
var memberReference = new MemberReference(methodDeclarer.ToTypeDefOrRef(), methodArg.Name, newMethodSignature);

var newInstruction = targetBuilder.Add(bodyInstruction.OpCode, imports.Module.DefaultImporter.ImportMethod(newMethod));
instructionMap.Add(bodyInstruction, newInstruction);
}
else if (bodyInstruction.OpCode.OperandType == CilOperandType.InlineType)
{
var targetType = ((ITypeDefOrRef)bodyInstruction.Operand).ToTypeSignature();
if (targetType is GenericParameterSignature genericParam)
IMethodDescriptor newMethod;
if (methodArg is MethodSpecification genericMethod)
{
if (genericParam.ParameterType is GenericParameterType.Type)
if (genericMethod.Signature is null)
return false;

TypeSignature[] typeArguments = new TypeSignature[genericMethod.Signature.TypeArguments.Count];
for (var i = 0; i < genericMethod.Signature.TypeArguments.Count; i++)
{
var newTypeOwner =
Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, original.DeclaringType?.ToTypeSignature(), imports)?.Resolve();
if (newTypeOwner == null)
var newTypeArgument = Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, genericMethod.Signature.TypeArguments[i], imports);
if (newTypeArgument == null)
return false;
targetType = newTypeOwner.GenericParameters.Single(it => it.Name == targetType.Name).ToTypeSignature();
}
else
{
targetType = target.GenericParameters.Single(it => it.Name == targetType.Name).ToTypeSignature();

typeArguments[i] = newTypeArgument;
}

newMethod = memberReference.MakeGenericInstanceMethod(typeArguments);
}
else
{
targetType = Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, targetType, imports);
if (targetType == null)
return false;
newMethod = memberReference;
}

var newInstruction = targetBuilder.Add(bodyInstruction.OpCode, imports.Module.DefaultImporter.ImportMethod(newMethod));
instructionMap.Add(bodyInstruction, newInstruction);
}
else if (bodyInstruction.OpCode.OperandType == CilOperandType.InlineType)
{
var targetType = Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, ((ITypeDefOrRef)bodyInstruction.Operand).ToTypeSignature(), imports);
if (targetType == null)
return false;

if (bodyInstruction.OpCode == OpCodes.Castclass && !targetType.IsValueType)
{
var newInstruction = targetBuilder.Add(OpCodes.Call,
Expand Down

0 comments on commit bba128e

Please sign in to comment.