diff --git a/Il2CppInterop.Generator/Contexts/RewriteGlobalContext.cs b/Il2CppInterop.Generator/Contexts/RewriteGlobalContext.cs index a6e86f47..b38fc93c 100644 --- a/Il2CppInterop.Generator/Contexts/RewriteGlobalContext.cs +++ b/Il2CppInterop.Generator/Contexts/RewriteGlobalContext.cs @@ -13,6 +13,7 @@ public class RewriteGlobalContext : IDisposable private readonly Dictionary myAssemblies = new(); private readonly Dictionary myAssembliesByOld = new(); + private readonly Dictionary myAssembliesByNew = new(); internal readonly Dictionary PreviousRenamedTypes = new(); internal readonly Dictionary RenamedTypes = new(); @@ -65,6 +66,7 @@ internal void AddAssemblyContext(string assemblyName, AssemblyRewriteContext con myAssemblies[assemblyName] = context; if (context.OriginalAssembly != null) myAssembliesByOld[context.OriginalAssembly] = context; + myAssembliesByNew[context.NewAssembly] = context; } public AssemblyRewriteContext GetNewAssemblyForOriginal(AssemblyDefinition oldAssembly) @@ -120,9 +122,14 @@ public AssemblyRewriteContext GetAssemblyByName(string name) return null; } + public AssemblyRewriteContext GetContextForNewAssembly(AssemblyDefinition assembly) + { + return myAssembliesByNew[assembly]; + } + public TypeRewriteContext GetContextForNewType(TypeDefinition type) { - return GetAssemblyByName(type.Module!.Assembly!.Name!).GetContextForNewType(type); + return GetContextForNewAssembly(type.Module!.Assembly!).GetContextForNewType(type); } public MethodDefinition? CreateParamsMethod(MethodDefinition originalMethod, MethodDefinition newMethod, diff --git a/Il2CppInterop.Generator/Extensions/AsmResolverExtensions.cs b/Il2CppInterop.Generator/Extensions/AsmResolverExtensions.cs index 452168b5..aaddb2b6 100644 --- a/Il2CppInterop.Generator/Extensions/AsmResolverExtensions.cs +++ b/Il2CppInterop.Generator/Extensions/AsmResolverExtensions.cs @@ -7,10 +7,20 @@ namespace Il2CppInterop.Generator.Extensions; internal static class AsmResolverExtensions { + /// + /// Boolean, Char, or numeric type + /// public static bool IsPrimitive(this TypeSignature type) { - //https://github.com/jbevain/cecil/blob/8e1ae7b4ea67ccc38cb8db3ded6802643109ffd7/Mono.Cecil/TypeReference.cs#L286 - return type is CorLibTypeSignature { ElementType: >= ElementType.Boolean and <= ElementType.R8 or ElementType.I or ElementType.U }; + return (type as CorLibTypeSignature)?.ElementType.IsPrimitive() ?? false; + } + + /// + /// Boolean, Char, or numeric type + /// + public static bool IsPrimitive(this ElementType elementType) + { + return elementType is >= ElementType.Boolean and <= ElementType.R8 or ElementType.I or ElementType.U; } public static TypeSignature GetElementType(this TypeSignature type) => type switch diff --git a/Il2CppInterop.Generator/Passes/Pass80UnstripMethods.cs b/Il2CppInterop.Generator/Passes/Pass80UnstripMethods.cs index a5e304b1..d42dd1dd 100644 --- a/Il2CppInterop.Generator/Passes/Pass80UnstripMethods.cs +++ b/Il2CppInterop.Generator/Passes/Pass80UnstripMethods.cs @@ -172,14 +172,14 @@ private static PropertyDefinition GetOrCreateProperty(MethodDefinition unityMeth } internal static TypeSignature? ResolveTypeInNewAssemblies(RewriteGlobalContext context, TypeSignature? unityType, - RuntimeAssemblyReferences imports) + RuntimeAssemblyReferences imports, bool useSystemCorlibPrimitives = true) { - var resolved = ResolveTypeInNewAssembliesRaw(context, unityType, imports); + var resolved = ResolveTypeInNewAssembliesRaw(context, unityType, imports, useSystemCorlibPrimitives); return resolved != null ? imports.Module.DefaultImporter.ImportTypeSignature(resolved) : null; } internal static TypeSignature? ResolveTypeInNewAssembliesRaw(RewriteGlobalContext context, TypeSignature? unityType, - RuntimeAssemblyReferences imports) + RuntimeAssemblyReferences imports, bool useSystemCorlibPrimitives = true) { if (unityType is null) return null; @@ -264,10 +264,9 @@ private static PropertyDefinition GetOrCreateProperty(MethodDefinition unityMeth var targetAssemblyName = unityType.Scope!.Name!; if (targetAssemblyName.EndsWith(".dll")) targetAssemblyName = targetAssemblyName.Substring(0, targetAssemblyName.Length - 4); - if ((targetAssemblyName == "mscorlib" || targetAssemblyName == "netstandard") && - (unityType.IsValueType || unityType.FullName == "System.String" || - unityType.FullName == "System.Void") && unityType.FullName != "System.RuntimeTypeHandle") - return imports.Module.ImportCorlibReference(unityType.FullName); + + if (useSystemCorlibPrimitives && (unityType.IsPrimitive() || unityType.ElementType is ElementType.String or ElementType.Void)) + return imports.Module.CorLibTypeFactory.FromElementType(unityType.ElementType); if (targetAssemblyName == "UnityEngine") foreach (var assemblyRewriteContext in context.Assemblies) diff --git a/Il2CppInterop.Generator/Utils/UnstripTranslator.cs b/Il2CppInterop.Generator/Utils/UnstripTranslator.cs index f4749057..4688f5df 100644 --- a/Il2CppInterop.Generator/Utils/UnstripTranslator.cs +++ b/Il2CppInterop.Generator/Utils/UnstripTranslator.cs @@ -103,9 +103,13 @@ public static bool TranslateMethod(MethodDefinition original, MethodDefinition t } else if (bodyInstruction.OpCode.OperandType == CilOperandType.InlineField) { + // This code doesn't handle fields in the corlib types well. + // Static fields are fine, but references to instance fields can't be redirected. + var fieldArg = (IFieldDescriptor)bodyInstruction.Operand; + var useSystemCorlibType = fieldArg.Signature?.HasThis ?? true; var fieldDeclarer = - Pass80UnstripMethods.ResolveTypeInNewAssembliesRaw(globalContext, fieldArg.DeclaringType!.ToTypeSignature(), imports); + Pass80UnstripMethods.ResolveTypeInNewAssembliesRaw(globalContext, fieldArg.DeclaringType!.ToTypeSignature(), imports, useSystemCorlibType); if (fieldDeclarer == null) return false; var fieldDeclarerDefinition = fieldDeclarer.Resolve(); @@ -157,9 +161,13 @@ public static bool TranslateMethod(MethodDefinition original, MethodDefinition t } else if (bodyInstruction.OpCode.OperandType == CilOperandType.InlineMethod) { + // This code doesn't handle methods in the corlib types well. + // Static methods are fine, but references to instance methods can't be redirected. + var methodArg = (IMethodDescriptor)bodyInstruction.Operand; + var useSystemCorlibType = methodArg.Signature?.HasThis ?? true; var methodDeclarer = - Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, methodArg.DeclaringType?.ToTypeSignature(), imports); + Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, methodArg.DeclaringType?.ToTypeSignature(), imports, useSystemCorlibType); if (methodDeclarer == null) return false;