diff --git a/Il2CppInterop.CLI/Utils.cs b/Il2CppInterop.CLI/Utils.cs index 65c1b2e2..6fa7fa1e 100644 --- a/Il2CppInterop.CLI/Utils.cs +++ b/Il2CppInterop.CLI/Utils.cs @@ -1,4 +1,4 @@ -using Mono.Cecil; +using AsmResolver.DotNet; namespace Il2CppInterop; @@ -6,20 +6,9 @@ internal static class Utils { public static List LoadAssembliesFrom(DirectoryInfo directoryInfo) { - var resolver = new BasicResolver(); - var inputAssemblies = directoryInfo.EnumerateFiles("*.dll").Select(f => AssemblyDefinition.ReadAssembly( - f.FullName, - new ReaderParameters { AssemblyResolver = resolver })).ToList(); - foreach (var assembly in inputAssemblies) - { - resolver.Register(assembly); - } + var inputAssemblies = directoryInfo.EnumerateFiles("*.dll").Select(f => AssemblyDefinition.FromFile( + f.FullName)).ToList(); return inputAssemblies; } - - private class BasicResolver : DefaultAssemblyResolver - { - public void Register(AssemblyDefinition ad) => RegisterAssembly(ad); - } } diff --git a/Il2CppInterop.Generator/Contexts/AssemblyRewriteContext.cs b/Il2CppInterop.Generator/Contexts/AssemblyRewriteContext.cs index a2b8caac..e6e3afab 100644 --- a/Il2CppInterop.Generator/Contexts/AssemblyRewriteContext.cs +++ b/Il2CppInterop.Generator/Contexts/AssemblyRewriteContext.cs @@ -1,7 +1,7 @@ -using System.Collections.Generic; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; namespace Il2CppInterop.Generator.Contexts; @@ -28,7 +28,7 @@ public AssemblyRewriteContext(RewriteGlobalContext globalContext, AssemblyDefini NewAssembly = newAssembly; GlobalContext = globalContext; - Imports = ImportsMap.GetOrCreate(newAssembly.MainModule, + Imports = ImportsMap.GetOrCreate(newAssembly.ManifestModule!, mod => new RuntimeAssemblyReferences(mod, globalContext)); } @@ -57,63 +57,66 @@ public void RegisterTypeRewrite(TypeRewriteContext context) myNameTypeMap[(context.OriginalType ?? context.NewType).FullName] = context; } - public MethodReference RewriteMethodRef(MethodReference methodRef) + public IMethodDefOrRef RewriteMethodRef(IMethodDefOrRef methodRef) { - var newType = GlobalContext.GetNewTypeForOriginal(methodRef.DeclaringType.Resolve()); - return newType.GetMethodByOldMethod(methodRef.Resolve()).NewMethod; + var newType = GlobalContext.GetNewTypeForOriginal(methodRef.DeclaringType!.Resolve()!); + var newMethod = newType.GetMethodByOldMethod(methodRef.Resolve()!).NewMethod; + return NewAssembly.ManifestModule!.DefaultImporter.ImportMethod(newMethod); } - public TypeReference RewriteTypeRef(TypeReference? typeRef) + public ITypeDefOrRef RewriteTypeRef(ITypeDescriptor typeRef) { - if (typeRef == null) return Imports.Il2CppObjectBase; + return RewriteTypeRef(typeRef?.ToTypeSignature()).ToTypeDefOrRef(); + } + + public TypeSignature RewriteTypeRef(TypeSignature? typeRef) + { + if (typeRef == null) + return Imports.Il2CppObjectBase; - var sourceModule = NewAssembly.MainModule; + var sourceModule = NewAssembly.ManifestModule!; - if (typeRef is ArrayType arrayType) + if (typeRef is ArrayBaseTypeSignature arrayType) { if (arrayType.Rank != 1) return Imports.Il2CppObjectBase; - var elementType = arrayType.ElementType; + var elementType = arrayType.BaseType; if (elementType.FullName == "System.String") return Imports.Il2CppStringArray; var convertedElementType = RewriteTypeRef(elementType); - if (elementType.IsGenericParameter) - return new GenericInstanceType(Imports.Il2CppArrayBase) { GenericArguments = { convertedElementType } }; + if (elementType is GenericParameterSignature) + return new GenericInstanceTypeSignature(Imports.Il2CppArrayBase.ToTypeDefOrRef(), false, convertedElementType); - return new GenericInstanceType(convertedElementType.IsValueType - ? Imports.Il2CppStructArray - : Imports.Il2CppReferenceArray) - { GenericArguments = { convertedElementType } }; + return new GenericInstanceTypeSignature(convertedElementType.IsValueType + ? Imports.Il2CppStructArray.ToTypeDefOrRef() + : Imports.Il2CppReferenceArray.ToTypeDefOrRef(), false, convertedElementType); } - if (typeRef is GenericParameter genericParameter) + if (typeRef is GenericParameterSignature genericParameter) { - var genericParameterDeclaringType = genericParameter.DeclaringType; - if (genericParameterDeclaringType != null) - return RewriteTypeRef(genericParameterDeclaringType).GenericParameters[genericParameter.Position]; - - return RewriteMethodRef(genericParameter.DeclaringMethod).GenericParameters[genericParameter.Position]; + return new GenericParameterSignature(sourceModule, genericParameter.ParameterType, genericParameter.Index); } - if (typeRef is ByReferenceType byRef) - return new ByReferenceType(RewriteTypeRef(byRef.ElementType)); + if (typeRef is ByReferenceTypeSignature byRef) + return new ByReferenceTypeSignature(RewriteTypeRef(byRef.BaseType)); - if (typeRef is PointerType pointerType) - return new PointerType(RewriteTypeRef(pointerType.ElementType)); + if (typeRef is PointerTypeSignature pointerType) + return new PointerTypeSignature(RewriteTypeRef(pointerType.BaseType)); - if (typeRef is GenericInstanceType genericInstance) + if (typeRef is GenericInstanceTypeSignature genericInstance) { - var newRef = new GenericInstanceType(RewriteTypeRef(genericInstance.ElementType)); - foreach (var originalParameter in genericInstance.GenericArguments) - newRef.GenericArguments.Add(RewriteTypeRef(originalParameter)); + var genericType = RewriteTypeRef(genericInstance.GenericType.ToTypeSignature()).ToTypeDefOrRef(); + var newRef = new GenericInstanceTypeSignature(genericType, genericType.IsValueType); + foreach (var originalParameter in genericInstance.TypeArguments) + newRef.TypeArguments.Add(RewriteTypeRef(originalParameter)); return newRef; } - if (typeRef.IsPrimitive || typeRef.FullName == "System.TypedReference") - return sourceModule.ImportCorlibReference(typeRef.Namespace, typeRef.Name); + if (typeRef.IsPrimitive() || typeRef.FullName == "System.TypedReference") + return sourceModule.ImportCorlibReference(typeRef.FullName); if (typeRef.FullName == "System.Void") return Imports.Module.Void(); @@ -122,18 +125,18 @@ public TypeReference RewriteTypeRef(TypeReference? typeRef) return Imports.Module.String(); if (typeRef.FullName == "System.Object") - return sourceModule.ImportReference(GlobalContext.GetAssemblyByName("mscorlib") - .GetTypeByName("System.Object").NewType); + return sourceModule.DefaultImporter.ImportType(GlobalContext.GetAssemblyByName("mscorlib") + .GetTypeByName("System.Object").NewType).ToTypeSignature(); if (typeRef.FullName == "System.Attribute") - return sourceModule.ImportReference(GlobalContext.GetAssemblyByName("mscorlib") - .GetTypeByName("System.Attribute").NewType); + return sourceModule.DefaultImporter.ImportType(GlobalContext.GetAssemblyByName("mscorlib") + .GetTypeByName("System.Attribute").NewType).ToTypeSignature(); - var originalTypeDef = typeRef.Resolve(); - var targetAssembly = GlobalContext.GetNewAssemblyForOriginal(originalTypeDef.Module.Assembly); + var originalTypeDef = typeRef.Resolve()!; + var targetAssembly = GlobalContext.GetNewAssemblyForOriginal(originalTypeDef.Module!.Assembly!); var target = targetAssembly.GetContextForOriginalType(originalTypeDef).NewType; - return sourceModule.ImportReference(target); + return sourceModule.DefaultImporter.ImportType(target).ToTypeSignature(); } public TypeRewriteContext GetTypeByName(string name) diff --git a/Il2CppInterop.Generator/Contexts/FieldRewriteContext.cs b/Il2CppInterop.Generator/Contexts/FieldRewriteContext.cs index 12a5657f..0d890367 100644 --- a/Il2CppInterop.Generator/Contexts/FieldRewriteContext.cs +++ b/Il2CppInterop.Generator/Contexts/FieldRewriteContext.cs @@ -1,8 +1,9 @@ -using System; -using System.Collections.Generic; +using System.Diagnostics; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; namespace Il2CppInterop.Generator.Contexts; @@ -14,7 +15,7 @@ public class FieldRewriteContext public readonly TypeRewriteContext DeclaringType; public readonly FieldDefinition OriginalField; - public readonly FieldReference PointerField; + public readonly MemberReference PointerField; public readonly string UnmangledName; public FieldRewriteContext(TypeRewriteContext declaringType, FieldDefinition originalField, @@ -31,35 +32,39 @@ public FieldRewriteContext(TypeRewriteContext declaringType, FieldDefinition ori declaringType.NewType.Fields.Add(pointerField); - PointerField = new FieldReference(pointerField.Name, pointerField.FieldType, DeclaringType.SelfSubstitutedRef); + Debug.Assert(pointerField.Signature is not null); + PointerField = new MemberReference(DeclaringType.SelfSubstitutedRef, pointerField.Name, new FieldSignature(pointerField.Signature!.FieldType)); } private string UnmangleFieldNameBase(FieldDefinition field, GeneratorOptions options) { - if (options.PassthroughNames) return field.Name; + if (options.PassthroughNames) + return field.Name!; if (!field.Name.IsObfuscated(options)) { if (!field.Name.IsInvalidInSource()) - return field.Name; + return field.Name!; return field.Name.FilterInvalidInSourceChars(); } + Debug.Assert(field.Signature is not null); var accessModString = MethodAccessTypeLabels[(int)(field.Attributes & FieldAttributes.FieldAccessMask)]; var staticString = field.IsStatic ? "_Static" : ""; return "field_" + accessModString + staticString + "_" + - DeclaringType.AssemblyContext.RewriteTypeRef(field.FieldType).GetUnmangledName(); + DeclaringType.AssemblyContext.RewriteTypeRef(field.Signature!.FieldType).GetUnmangledName(field.DeclaringType); } private string UnmangleFieldName(FieldDefinition field, GeneratorOptions options, Dictionary? renamedFieldCounts) { - if (options.PassthroughNames) return field.Name; + if (options.PassthroughNames) + return field.Name!; if (!field.Name.IsObfuscated(options)) { if (!field.Name.IsInvalidInSource()) - return field.Name; + return field.Name!; return field.Name.FilterInvalidInSourceChars(); } diff --git a/Il2CppInterop.Generator/Contexts/MethodRewriteContext.cs b/Il2CppInterop.Generator/Contexts/MethodRewriteContext.cs index b20fffe2..3eae86a9 100644 --- a/Il2CppInterop.Generator/Contexts/MethodRewriteContext.cs +++ b/Il2CppInterop.Generator/Contexts/MethodRewriteContext.cs @@ -1,12 +1,12 @@ -using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; using System.Text; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Common.XrefScans; using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Passes; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; namespace Il2CppInterop.Generator.Contexts; @@ -47,28 +47,31 @@ public MethodRewriteContext(TypeRewriteContext declaringType, MethodDefinition o var passthroughNames = declaringType.AssemblyContext.GlobalContext.Options.PassthroughNames; OriginalNameObfuscated = !passthroughNames && - (OriginalMethod?.Name?.IsObfuscated(declaringType.AssemblyContext.GlobalContext + (OriginalMethod.Name?.IsObfuscated(declaringType.AssemblyContext.GlobalContext .Options) ?? false); - var newMethod = new MethodDefinition("", - AdjustAttributes(originalMethod.Attributes, originalMethod.Name == "Finalize"), - declaringType.AssemblyContext.Imports.Module.Void()); + var newAttributes = AdjustAttributes(originalMethod.Attributes, originalMethod.Name == "Finalize"); + var newSignature = (newAttributes & MethodAttributes.Static) != 0 + ? MethodSignature.CreateStatic(declaringType.AssemblyContext.Imports.Module.Void(), originalMethod.GenericParameters.Count) + : MethodSignature.CreateInstance(declaringType.AssemblyContext.Imports.Module.Void(), originalMethod.GenericParameters.Count); + var newMethod = new MethodDefinition("", newAttributes, newSignature); + newMethod.CilMethodBody = new(newMethod); NewMethod = newMethod; HasExtensionAttribute = - originalMethod.CustomAttributes.Any(x => x.AttributeType.FullName == typeof(ExtensionAttribute).FullName); + originalMethod.CustomAttributes.Any(x => x.AttributeType()?.FullName == typeof(ExtensionAttribute).FullName); if (HasExtensionAttribute) newMethod.CustomAttributes.Add( new CustomAttribute(declaringType.AssemblyContext.Imports.Module.ExtensionAttributeCtor())); - if (originalMethod.HasGenericParameters) + if (originalMethod.HasGenericParameters()) { var genericParams = originalMethod.GenericParameters; foreach (var oldParameter in genericParams) { - var genericParameter = new GenericParameter(oldParameter.Name, newMethod); + var genericParameter = new GenericParameter(oldParameter.Name); genericParameter.Attributes = oldParameter.Attributes.StripValueTypeConstraint(); newMethod.GenericParameters.Add(genericParameter); } @@ -86,13 +89,13 @@ public MethodRewriteContext(TypeRewriteContext declaringType, MethodDefinition o declaringType.AssemblyContext.GlobalContext.MethodStartAddresses.Add(FileOffset); } - public string UnmangledName { get; private set; } - public string UnmangledNameWithSignature { get; private set; } + public string? UnmangledName { get; private set; } + public string? UnmangledNameWithSignature { get; private set; } public TypeDefinition? GenericInstantiationsStore { get; private set; } - public TypeReference? GenericInstantiationsStoreSelfSubstRef { get; private set; } - public TypeReference? GenericInstantiationsStoreSelfSubstMethodRef { get; private set; } - public FieldReference NonGenericMethodInfoPointerField { get; private set; } + public ITypeDefOrRef? GenericInstantiationsStoreSelfSubstRef { get; private set; } + public ITypeDefOrRef? GenericInstantiationsStoreSelfSubstMethodRef { get; private set; } + public MemberReference NonGenericMethodInfoPointerField { get; private set; } = null!; // Initialized in CtorPhase2 public bool HasExtensionAttribute { get; } @@ -102,7 +105,7 @@ public void CtorPhase2() UnmangledNameWithSignature = UnmangleMethodNameWithSignature(); NewMethod.Name = UnmangledName; - NewMethod.ReturnType = DeclaringType.AssemblyContext.RewriteTypeRef(OriginalMethod.ReturnType); + NewMethod.Signature!.ReturnType = DeclaringType.AssemblyContext.RewriteTypeRef(OriginalMethod.Signature?.ReturnType); var nonGenericMethodInfoPointerField = new FieldDefinition( "NativeMethodInfoPtr_" + UnmangledNameWithSignature, @@ -110,39 +113,38 @@ public void CtorPhase2() DeclaringType.AssemblyContext.Imports.Module.IntPtr()); DeclaringType.NewType.Fields.Add(nonGenericMethodInfoPointerField); - NonGenericMethodInfoPointerField = new FieldReference(nonGenericMethodInfoPointerField.Name, - nonGenericMethodInfoPointerField.FieldType, DeclaringType.SelfSubstitutedRef); + NonGenericMethodInfoPointerField = new MemberReference(DeclaringType.SelfSubstitutedRef, nonGenericMethodInfoPointerField.Name, + new FieldSignature(nonGenericMethodInfoPointerField.Signature!.FieldType)); - if (OriginalMethod.HasGenericParameters) + if (OriginalMethod.HasGenericParameters()) { var genericParams = OriginalMethod.GenericParameters; var genericMethodInfoStoreType = new TypeDefinition("", "MethodInfoStoreGeneric_" + UnmangledNameWithSignature + "`" + genericParams.Count, TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, - DeclaringType.AssemblyContext.Imports.Module.Object()); - genericMethodInfoStoreType.DeclaringType = DeclaringType.NewType; + DeclaringType.AssemblyContext.Imports.Module.Object().ToTypeDefOrRef()); DeclaringType.NewType.NestedTypes.Add(genericMethodInfoStoreType); GenericInstantiationsStore = genericMethodInfoStoreType; - var selfSubstRef = new GenericInstanceType(genericMethodInfoStoreType); - var selfSubstMethodRef = new GenericInstanceType(genericMethodInfoStoreType); + var selfSubstRef = new GenericInstanceTypeSignature(genericMethodInfoStoreType, false); + var selfSubstMethodRef = new GenericInstanceTypeSignature(genericMethodInfoStoreType, false); for (var index = 0; index < genericParams.Count; index++) { var oldParameter = genericParams[index]; - var genericParameter = new GenericParameter(oldParameter.Name, genericMethodInfoStoreType); + var genericParameter = new GenericParameter(oldParameter.Name); genericMethodInfoStoreType.GenericParameters.Add(genericParameter); - selfSubstRef.GenericArguments.Add(genericParameter); + selfSubstRef.TypeArguments.Add(genericParameter.ToTypeSignature()); var newParameter = NewMethod.GenericParameters[index]; - selfSubstMethodRef.GenericArguments.Add(newParameter); + selfSubstMethodRef.TypeArguments.Add(newParameter.ToTypeSignature()); foreach (var oldConstraint in oldParameter.Constraints) { - if (oldConstraint.ConstraintType.FullName == "System.ValueType" || - oldConstraint.ConstraintType.Resolve()?.IsInterface == true) continue; + if (oldConstraint.Constraint?.FullName == "System.ValueType" || + oldConstraint.Constraint?.Resolve()?.IsInterface == true) continue; newParameter.Constraints.Add(new GenericParameterConstraint( - DeclaringType.AssemblyContext.RewriteTypeRef(oldConstraint.ConstraintType))); + DeclaringType.AssemblyContext.RewriteTypeRef(oldConstraint.Constraint?.ToTypeSignature()).ToTypeDefOrRef())); } } @@ -150,9 +152,9 @@ public void CtorPhase2() DeclaringType.AssemblyContext.Imports.Module.IntPtr()); genericMethodInfoStoreType.Fields.Add(pointerField); - GenericInstantiationsStoreSelfSubstRef = DeclaringType.NewType.Module.ImportReference(selfSubstRef); + GenericInstantiationsStoreSelfSubstRef = DeclaringType.NewType.Module!.DefaultImporter.ImportType(selfSubstRef.ToTypeDefOrRef()); GenericInstantiationsStoreSelfSubstMethodRef = - DeclaringType.NewType.Module.ImportReference(selfSubstMethodRef); + DeclaringType.NewType.Module.DefaultImporter.ImportType(selfSubstMethodRef.ToTypeDefOrRef()); } DeclaringType.NewType.Methods.Add(NewMethod); @@ -180,7 +182,7 @@ private string UnmangleMethodName() return "GetIl2CppType"; if (DeclaringType.AssemblyContext.GlobalContext.Options.PassthroughNames) - return method.Name; + return method.Name!; if (method.Name == ".ctor") return ".ctor"; @@ -191,7 +193,7 @@ private string UnmangleMethodName() if (method.Name.IsInvalidInSource()) return method.Name.FilterInvalidInSourceChars(); - return method.Name; + return method.Name!; } private string ProduceMethodSignatureBase() @@ -217,17 +219,18 @@ private string ProduceMethodSignatureBase() if (method.IsStatic) builder.Append("_Static"); if (method.IsFinal) builder.Append("_Final"); if (method.IsNewSlot) builder.Append("_New"); - foreach (var (semantic, str) in SemanticsToCheck) - if ((semantic & method.SemanticsAttributes) != 0) - builder.Append(str); + if (method.Semantics is not null) + foreach (var (semantic, str) in SemanticsToCheck) + if ((semantic & method.Semantics.Attributes) != 0) + builder.Append(str); builder.Append('_'); - builder.Append(DeclaringType.AssemblyContext.RewriteTypeRef(method.ReturnType).GetUnmangledName()); + builder.Append(DeclaringType.AssemblyContext.RewriteTypeRef(method.Signature?.ReturnType).GetUnmangledName(method.DeclaringType, method)); foreach (var param in method.Parameters) { builder.Append('_'); - builder.Append(DeclaringType.AssemblyContext.RewriteTypeRef(param.ParameterType).GetUnmangledName()); + builder.Append(DeclaringType.AssemblyContext.RewriteTypeRef(param.ParameterType).GetUnmangledName(method.DeclaringType, method)); } var address = Rva; @@ -271,10 +274,10 @@ private bool ParameterSignatureMatchesThis(MethodRewriteContext otherRewriteCont (bM.Attributes & comparisonMask)) return false; - if (aM.SemanticsAttributes != bM.SemanticsAttributes) + if (aM.Semantics?.Attributes != bM.Semantics?.Attributes) return false; - if (aM.ReturnType.FullName != bM.ReturnType.FullName) + if (aM.Signature?.ReturnType.FullName != bM.Signature?.ReturnType.FullName) return false; var a = aM.Parameters; diff --git a/Il2CppInterop.Generator/Contexts/RewriteGlobalContext.cs b/Il2CppInterop.Generator/Contexts/RewriteGlobalContext.cs index 843f5842..bbf503f7 100644 --- a/Il2CppInterop.Generator/Contexts/RewriteGlobalContext.cs +++ b/Il2CppInterop.Generator/Contexts/RewriteGlobalContext.cs @@ -1,12 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.MetadataAccess; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; -using Mono.Cecil.Cil; namespace Il2CppInterop.Generator.Contexts; @@ -19,7 +16,7 @@ public class RewriteGlobalContext : IDisposable internal readonly Dictionary PreviousRenamedTypes = new(); internal readonly Dictionary RenamedTypes = new(); - internal readonly Dictionary<(object, string, int), List> RenameGroups = new(); + internal readonly Dictionary<(object?, string, int), List> RenameGroups = new(); public RewriteGlobalContext(GeneratorOptions options, IIl2CppMetadataAccess gameAssemblies, IMetadataAccess unityAssemblies) @@ -28,18 +25,22 @@ public RewriteGlobalContext(GeneratorOptions options, IIl2CppMetadataAccess game GameAssemblies = gameAssemblies; UnityAssemblies = unityAssemblies; + Il2CppAssemblyResolver assemblyResolver = new(); + foreach (var sourceAssembly in gameAssemblies.Assemblies) { - var assemblyName = sourceAssembly.Name.Name; + var assemblyName = sourceAssembly.Name!; if (assemblyName == "Il2CppDummyDll") { - sourceAssembly.Dispose(); continue; } - var newAssembly = AssemblyDefinition.CreateAssembly( - new AssemblyNameDefinition(sourceAssembly.Name.Name.UnSystemify(options), sourceAssembly.Name.Version), - sourceAssembly.MainModule.Name.UnSystemify(options), sourceAssembly.MainModule.Kind); + var newAssembly = new AssemblyDefinition(sourceAssembly.Name.UnSystemify(options), sourceAssembly.Version); + var newModule = new ModuleDefinition(sourceAssembly.ManifestModule?.Name.UnSystemify(options), CorlibReferences.TargetCorlib); + newAssembly.Modules.Add(newModule); + + newModule.MetadataResolver = new DefaultMetadataResolver(assemblyResolver); + assemblyResolver.AddToCache(newAssembly); var assemblyRewriteContext = new AssemblyRewriteContext(this, sourceAssembly, newAssembly); AddAssemblyContext(assemblyName, assemblyRewriteContext); @@ -56,22 +57,6 @@ public RewriteGlobalContext(GeneratorOptions options, IIl2CppMetadataAccess game public void Dispose() { - var resolverCacheField = - typeof(DefaultAssemblyResolver).GetField("cache", BindingFlags.Instance | BindingFlags.NonPublic); - - foreach (var assembly in Assemblies) - { - foreach (var module in assembly.NewAssembly.Modules) - { - var resolver = (DefaultAssemblyResolver)module.AssemblyResolver; - var cache = (Dictionary)resolverCacheField!.GetValue(resolver); - cache.Clear(); - } - - assembly.NewAssembly.Dispose(); - assembly.OriginalAssembly.Dispose(); - } - UnityAssemblies.Dispose(); } @@ -89,26 +74,30 @@ public AssemblyRewriteContext GetNewAssemblyForOriginal(AssemblyDefinition oldAs public TypeRewriteContext GetNewTypeForOriginal(TypeDefinition originalType) { - return GetNewAssemblyForOriginal(originalType.Module.Assembly) + return GetNewAssemblyForOriginal(originalType.Module!.Assembly!) .GetContextForOriginalType(originalType); } public TypeRewriteContext? TryGetNewTypeForOriginal(TypeDefinition originalType) { - if (!myAssembliesByOld.TryGetValue(originalType.Module.Assembly, out var assembly)) + if (!myAssembliesByOld.TryGetValue(originalType.Module!.Assembly!, out var assembly)) return null; return assembly.TryGetContextForOriginalType(originalType); } - public TypeRewriteContext.TypeSpecifics JudgeSpecificsByOriginalType(TypeReference typeRef) + public TypeRewriteContext.TypeSpecifics JudgeSpecificsByOriginalType(TypeSignature typeRef) { - if (typeRef.IsPrimitive || typeRef.IsPointer || typeRef.FullName == "System.TypedReference") + if (typeRef.IsPrimitive() || typeRef is PointerTypeSignature || typeRef.FullName == "System.TypedReference") return TypeRewriteContext.TypeSpecifics.BlittableStruct; - if (typeRef.FullName == "System.String" || typeRef.FullName == "System.Object" || typeRef.IsArray || - typeRef.IsByReference || typeRef.IsGenericParameter || typeRef.IsGenericInstance) + if (typeRef + is CorLibTypeSignature { ElementType: ElementType.String or ElementType.Object } + or ArrayBaseTypeSignature + or ByReferenceTypeSignature + or GenericParameterSignature + or GenericInstanceTypeSignature) return TypeRewriteContext.TypeSpecifics.ReferenceType; - var fieldTypeContext = GetNewTypeForOriginal(typeRef.Resolve()); + var fieldTypeContext = GetNewTypeForOriginal(typeRef.Resolve() ?? throw new($"Could not resolve {typeRef.FullName}")); return fieldTypeContext.ComputedTypeSpecifics; } @@ -117,8 +106,11 @@ public AssemblyRewriteContext GetAssemblyByName(string name) return myAssemblies[name]; } - public AssemblyRewriteContext? TryGetAssemblyByName(string name) + public AssemblyRewriteContext? TryGetAssemblyByName(string? name) { + if (name is null) + return null; + if (myAssemblies.TryGetValue(name, out var result)) return result; @@ -129,63 +121,83 @@ public AssemblyRewriteContext GetAssemblyByName(string name) } public MethodDefinition? CreateParamsMethod(MethodDefinition originalMethod, MethodDefinition newMethod, - RuntimeAssemblyReferences imports, Func resolve) + RuntimeAssemblyReferences imports, Func resolve) { if (newMethod.Name == "Invoke") return null; var paramsParameters = originalMethod.Parameters.Where(parameter => - parameter.IsParamsArray() && !(resolve(((ArrayType)parameter.ParameterType).ElementType)?.IsGenericParameter ?? true) + parameter.IsParamsArray() && resolve(((ArrayBaseTypeSignature)parameter.ParameterType).BaseType) is not null and not GenericParameterSignature ).ToArray(); if (paramsParameters.Any()) { - var paramsMethod = new MethodDefinition(newMethod.Name, newMethod.Attributes, newMethod.ReturnType); - foreach (var genericParameter in newMethod.GenericParameters) - paramsMethod.GenericParameters.Add(genericParameter); + var paramsMethod = new MethodDefinition(newMethod.Name, newMethod.Attributes, MethodSignatureCreator.CreateMethodSignature(newMethod.Attributes, newMethod.Signature!.ReturnType, newMethod.Signature.GenericParameterCount)); + foreach (var genericParameter in originalMethod.GenericParameters) + { + var newGenericParameter = new GenericParameter(genericParameter.Name, genericParameter.Attributes); + + foreach (var constraint in genericParameter.Constraints) + { + var newConstraintType = constraint.Constraint != null ? resolve(constraint.Constraint.ToTypeSignature())?.ToTypeDefOrRef() : null; + var newConstraint = new GenericParameterConstraint(newConstraintType); + + // We don't need to copy custom attributes on constraints for generic parameters because Il2Cpp doesn't support them. + + newGenericParameter.Constraints.Add(newConstraint); + } + + // Similarly, custom attributes on generic parameters are also stripped by Il2Cpp, so we don't need to copy them. + + paramsMethod.GenericParameters.Add(newGenericParameter); + } foreach (var originalParameter in originalMethod.Parameters) { var isParams = paramsParameters.Contains(originalParameter); - TypeReference? convertedType; - if (isParams && originalParameter.ParameterType is ArrayType arrayType) + TypeSignature? convertedType; + if (isParams && originalParameter.ParameterType is ArrayBaseTypeSignature arrayType) { var resolvedElementType = resolve(arrayType.GetElementType()); - convertedType = resolvedElementType == null - ? null - : new ArrayType(resolvedElementType, arrayType.Rank); + convertedType = arrayType is SzArrayTypeSignature + ? resolvedElementType?.MakeSzArrayType() + : resolvedElementType?.MakeArrayType(arrayType.Rank); } else { convertedType = resolve(originalParameter.ParameterType); } - var parameter = - new ParameterDefinition(originalParameter.Name, originalParameter.Attributes, convertedType); + if (convertedType == null) + { + throw new($"Could not resolve parameter type {originalParameter.ParameterType.FullName}"); + } - if (isParams) - parameter.CustomAttributes.Add(new CustomAttribute(newMethod.Module.ParamArrayAttributeCtor())); + var parameter = paramsMethod.AddParameter(convertedType, originalParameter.Name, originalParameter.Definition?.Attributes ?? default); - paramsMethod.Parameters.Add(parameter); + if (isParams) + parameter.Definition!.CustomAttributes.Add(new CustomAttribute(newMethod.Module!.ParamArrayAttributeCtor())); } - var body = paramsMethod.Body.GetILProcessor(); + paramsMethod.CilMethodBody = new(paramsMethod); + var body = paramsMethod.CilMethodBody.Instructions; - if (newMethod.HasThis) body.Emit(OpCodes.Ldarg_0); - - var argOffset = newMethod.HasThis ? 1 : 0; + if (!newMethod.IsStatic) + { + body.Add(OpCodes.Ldarg_0); + } for (var i = 0; i < newMethod.Parameters.Count; i++) { - body.Emit(OpCodes.Ldarg, argOffset + i); + body.Add(OpCodes.Ldarg, newMethod.Parameters[i]); var parameter = originalMethod.Parameters[i]; if (paramsParameters.Contains(parameter)) { - var parameterType = (ArrayType)parameter.ParameterType; + var parameterType = (ArrayBaseTypeSignature)parameter.ParameterType; - MethodReference constructorReference; + IMethodDescriptor constructorReference; var elementType = parameterType.GetElementType(); if (elementType.FullName == "System.String") @@ -196,17 +208,17 @@ public AssemblyRewriteContext GetAssemblyByName(string name) { var convertedElementType = resolve(elementType)!; - constructorReference = imports.Module.ImportReference(convertedElementType.IsValueType + constructorReference = imports.Module.DefaultImporter.ImportMethod(convertedElementType.IsValueType ? imports.Il2CppStructArrayctor.Get(convertedElementType) : imports.Il2CppRefrenceArrayctor.Get(convertedElementType)); } - body.Emit(OpCodes.Newobj, constructorReference); + body.Add(OpCodes.Newobj, constructorReference); } } - body.Emit(OpCodes.Call, newMethod); - body.Emit(OpCodes.Ret); + body.Add(OpCodes.Call, newMethod); + body.Add(OpCodes.Ret); return paramsMethod; } diff --git a/Il2CppInterop.Generator/Contexts/TypeRewriteContext.cs b/Il2CppInterop.Generator/Contexts/TypeRewriteContext.cs index 2d7941d3..8ae63c4f 100644 --- a/Il2CppInterop.Generator/Contexts/TypeRewriteContext.cs +++ b/Il2CppInterop.Generator/Contexts/TypeRewriteContext.cs @@ -1,7 +1,8 @@ -using System; -using System.Collections.Generic; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; +using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; namespace Il2CppInterop.Generator.Contexts; @@ -24,11 +25,15 @@ public enum TypeSpecifics public readonly TypeDefinition NewType; public readonly bool OriginalNameWasObfuscated; +#nullable disable + // OriginalType is null for unstripped types, but we don't want to warn anywhere, + // including in the constructor, so we disable all null tracking for this field. public readonly TypeDefinition OriginalType; +#nullable enable public TypeSpecifics ComputedTypeSpecifics; - public TypeRewriteContext(AssemblyRewriteContext assemblyContext, TypeDefinition originalType, + public TypeRewriteContext(AssemblyRewriteContext assemblyContext, TypeDefinition? originalType, TypeDefinition newType) { AssemblyContext = assemblyContext ?? throw new ArgumentNullException(nameof(assemblyContext)); @@ -39,50 +44,53 @@ public TypeRewriteContext(AssemblyRewriteContext assemblyContext, TypeDefinition OriginalNameWasObfuscated = OriginalType.Name != NewType.Name; if (OriginalNameWasObfuscated) - NewType.CustomAttributes.Add(new CustomAttribute(assemblyContext.Imports.ObfuscatedNameAttributector.Value) - { - ConstructorArguments = - {new CustomAttributeArgument(assemblyContext.Imports.Module.String(), originalType.FullName)} - }); + NewType.CustomAttributes.Add(new CustomAttribute( + (ICustomAttributeType)assemblyContext.Imports.ObfuscatedNameAttributector.Value, + new CustomAttributeSignature(new CustomAttributeArgument(assemblyContext.Imports.Module.String(), OriginalType.FullName)))); if (!OriginalType.IsValueType) ComputedTypeSpecifics = TypeSpecifics.ReferenceType; else if (OriginalType.IsEnum) ComputedTypeSpecifics = TypeSpecifics.BlittableStruct; - else if (OriginalType.HasGenericParameters) + else if (OriginalType.HasGenericParameters()) ComputedTypeSpecifics = TypeSpecifics.NonBlittableStruct; // not reference type, covered by first if } - public FieldReference ClassPointerFieldRef { get; private set; } - public TypeReference SelfSubstitutedRef { get; private set; } + // These are initialized in AddMembers, which is called from an early rewrite pass. + public IFieldDescriptor ClassPointerFieldRef { get; private set; } = null!; + public ITypeDefOrRef SelfSubstitutedRef { get; private set; } = null!; public IEnumerable Fields => myFieldContexts.Values; public IEnumerable Methods => myMethodContexts.Values; public void AddMembers() { - if (NewType.HasGenericParameters) + if (NewType.HasGenericParameters()) { - var genericInstanceType = new GenericInstanceType(NewType); + var genericInstanceType = new GenericInstanceTypeSignature(NewType, NewType.IsValueType); foreach (var newTypeGenericParameter in NewType.GenericParameters) - genericInstanceType.GenericArguments.Add(newTypeGenericParameter); - SelfSubstitutedRef = NewType.Module.ImportReference(genericInstanceType); - var genericTypeRef = new GenericInstanceType(AssemblyContext.Imports.Il2CppClassPointerStore) - { GenericArguments = { SelfSubstitutedRef } }; - ClassPointerFieldRef = new FieldReference("NativeClassPtr", AssemblyContext.Imports.Module.IntPtr(), - NewType.Module.ImportReference(genericTypeRef)); + genericInstanceType.TypeArguments.Add(newTypeGenericParameter.ToTypeSignature()); + SelfSubstitutedRef = NewType.Module!.DefaultImporter.ImportTypeSignature(genericInstanceType).ToTypeDefOrRef(); + var genericTypeRef = new GenericInstanceTypeSignature( + AssemblyContext.Imports.Il2CppClassPointerStore.ToTypeDefOrRef(), + AssemblyContext.Imports.Il2CppClassPointerStore.IsValueType, + SelfSubstitutedRef.ToTypeSignature()); + ClassPointerFieldRef = ReferenceCreator.CreateFieldReference("NativeClassPtr", AssemblyContext.Imports.Module.IntPtr(), + NewType.Module.DefaultImporter.ImportType(genericTypeRef.ToTypeDefOrRef())); } else { SelfSubstitutedRef = NewType; - var genericTypeRef = new GenericInstanceType(AssemblyContext.Imports.Il2CppClassPointerStore); - if (OriginalType.IsPrimitive || OriginalType.FullName == "System.String") - genericTypeRef.GenericArguments.Add( - NewType.Module.ImportCorlibReference(OriginalType.Namespace, OriginalType.Name)); + var genericTypeRef = new GenericInstanceTypeSignature( + AssemblyContext.Imports.Il2CppClassPointerStore.ToTypeDefOrRef(), + AssemblyContext.Imports.Il2CppClassPointerStore.IsValueType); + if (OriginalType.ToTypeSignature().IsPrimitive() || OriginalType.FullName == "System.String") + genericTypeRef.TypeArguments.Add( + NewType.Module!.ImportCorlibReference(OriginalType.FullName)); else - genericTypeRef.GenericArguments.Add(SelfSubstitutedRef); - ClassPointerFieldRef = new FieldReference("NativeClassPtr", AssemblyContext.Imports.Module.IntPtr(), - NewType.Module.ImportReference(genericTypeRef)); + genericTypeRef.TypeArguments.Add(SelfSubstitutedRef.ToTypeSignature()); + ClassPointerFieldRef = ReferenceCreator.CreateFieldReference("NativeClassPtr", AssemblyContext.Imports.Module.IntPtr(), + NewType.Module!.DefaultImporter.ImportType(genericTypeRef.ToTypeDefOrRef())); } if (OriginalType.IsEnum) return; @@ -96,14 +104,16 @@ public void AddMembers() foreach (var originalTypeMethod in OriginalType.Methods) { - if (originalTypeMethod.Name == ".cctor") continue; - if (originalTypeMethod.Name == ".ctor" && originalTypeMethod.Parameters.Count == 1 && - originalTypeMethod.Parameters[0].ParameterType.FullName == "System.IntPtr") continue; - if (originalTypeMethod.HasOverrides) continue; + if (originalTypeMethod.IsStatic && originalTypeMethod.IsConstructor) + continue; + if (originalTypeMethod.IsConstructor + && originalTypeMethod.Parameters is [{ ParameterType: CorLibTypeSignature { ElementType: ElementType.I } }]) + continue; + var modules = this.AssemblyContext.GlobalContext.Assemblies.Select(a => a.OriginalAssembly.ManifestModule!); var methodRewriteContext = new MethodRewriteContext(this, originalTypeMethod); myMethodContexts[originalTypeMethod] = methodRewriteContext; - myMethodContextsByName[originalTypeMethod.Name] = methodRewriteContext; + myMethodContextsByName[originalTypeMethod.Name!] = methodRewriteContext; if (methodRewriteContext.HasExtensionAttribute) hasExtensionMethods = true; } @@ -162,7 +172,7 @@ public MethodRewriteContext GetMethodByOldMethod(MethodDefinition method) var originalField = fieldRewriteContext.Value.OriginalField; if (originalField.Name != field.Name) continue; - if (originalField.FieldType.FullName != field.FieldType.FullName) + if (originalField.Signature?.FieldType.FullName != field.Signature?.FieldType.FullName) continue; return fieldRewriteContext.Value; diff --git a/Il2CppInterop.Generator/Extensions/AsmResolverExtensions.cs b/Il2CppInterop.Generator/Extensions/AsmResolverExtensions.cs new file mode 100644 index 00000000..81a7473b --- /dev/null +++ b/Il2CppInterop.Generator/Extensions/AsmResolverExtensions.cs @@ -0,0 +1,84 @@ +using AsmResolver.DotNet; +using AsmResolver.DotNet.Collections; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; + +namespace Il2CppInterop.Generator.Extensions; + +internal static class AsmResolverExtensions +{ + 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 }; + } + + public static TypeSignature GetElementType(this TypeSignature type) => type switch + { + TypeSpecificationSignature specification => specification.BaseType, + _ => type, + }; + + public static void AddLoadArgument(this ILProcessor instructions, int argumentIndex) + { + instructions.Add(OpCodes.Ldarg, instructions.GetArgument(argumentIndex)); + } + + public static void AddLoadArgumentAddress(this ILProcessor instructions, int argumentIndex) + { + instructions.Add(OpCodes.Ldarga, instructions.GetArgument(argumentIndex)); + } + + private static Parameter GetArgument(this ILProcessor instructions, int argumentIndex) + { + var method = instructions.Owner.Owner; + return method.IsStatic + ? method.Parameters[argumentIndex] + : argumentIndex == 0 + ? method.Parameters.ThisParameter! + : method.Parameters[argumentIndex - 1]; + } + + public static bool HasGenericParameters(this TypeDefinition type) => type.GenericParameters.Count > 0; + + public static bool HasGenericParameters(this MethodDefinition method) => method.GenericParameters.Count > 0; + + public static bool HasConstant(this FieldDefinition field) => field.Constant is not null; + + public static bool HasMethods(this TypeDefinition type) => type.Methods.Count > 0; + + public static bool HasFields(this TypeDefinition type) => type.Fields.Count > 0; + + public static bool IsNested(this ITypeDefOrRef type) => type.DeclaringType is not null; + + public static bool IsNested(this TypeSignature type) => type.DeclaringType is not null; + + public static ITypeDefOrRef? AttributeType(this CustomAttribute attribute) => attribute.Constructor?.DeclaringType; + + public static Parameter AddParameter(this MethodDefinition method, TypeSignature parameterSignature, string parameterName, ParameterAttributes parameterAttributes = default) + { + var parameterDefinition = new ParameterDefinition((ushort)(method.Signature!.ParameterTypes.Count + 1), parameterName, parameterAttributes); + method.Signature.ParameterTypes.Add(parameterSignature); + method.ParameterDefinitions.Add(parameterDefinition); + + method.Parameters.PullUpdatesFromMethodSignature(); + return method.Parameters.Single(parameter => parameter.Name == parameterName && parameter.ParameterType == parameterSignature); + } + + public static Parameter AddParameter(this MethodDefinition method, TypeSignature parameterSignature) + { + method.Signature!.ParameterTypes.Add(parameterSignature); + method.Parameters.PullUpdatesFromMethodSignature(); + return method.Parameters[method.Parameters.Count - 1]; + } + + public static TypeDefinition GetType(this ModuleDefinition module, string fullName) + { + return module.TopLevelTypes.First(t => t.FullName == fullName); + } + + public static GenericParameterSignature ToTypeSignature(this GenericParameter genericParameter) + { + return new GenericParameterSignature(genericParameter.Owner is ITypeDescriptor ? GenericParameterType.Type : GenericParameterType.Method, genericParameter.Number); + } +} diff --git a/Il2CppInterop.Generator/Extensions/CollectionEx.cs b/Il2CppInterop.Generator/Extensions/CollectionEx.cs index 57bc78ba..818cc58b 100644 --- a/Il2CppInterop.Generator/Extensions/CollectionEx.cs +++ b/Il2CppInterop.Generator/Extensions/CollectionEx.cs @@ -1,6 +1,3 @@ -using System; -using System.Collections.Generic; - namespace Il2CppInterop.Generator.Extensions; public static class CollectionEx diff --git a/Il2CppInterop.Generator/Extensions/CustomAttributeEx.cs b/Il2CppInterop.Generator/Extensions/CustomAttributeEx.cs index 57f0ddf3..97709c7e 100644 --- a/Il2CppInterop.Generator/Extensions/CustomAttributeEx.cs +++ b/Il2CppInterop.Generator/Extensions/CustomAttributeEx.cs @@ -1,46 +1,45 @@ -using Mono.Cecil; +using AsmResolver; +using AsmResolver.DotNet; namespace Il2CppInterop.Generator.Extensions; public static class CustomAttributeEx { - public static long ExtractOffset(this ICustomAttributeProvider originalMethod) + public static long ExtractOffset(this IHasCustomAttribute originalMethod) { return ExtractLong(originalMethod, "AddressAttribute", "Offset"); } - public static long ExtractRva(this ICustomAttributeProvider originalMethod) + public static long ExtractRva(this IHasCustomAttribute originalMethod) { return ExtractLong(originalMethod, "AddressAttribute", "RVA"); } - public static long ExtractToken(this ICustomAttributeProvider originalMethod) + public static long ExtractToken(this IHasCustomAttribute originalMethod) { return ExtractLong(originalMethod, "TokenAttribute", "Token"); } - public static int ExtractFieldOffset(this ICustomAttributeProvider originalField) + public static int ExtractFieldOffset(this IHasCustomAttribute originalField) { return ExtractInt(originalField, "FieldOffsetAttribute", "Offset"); } - private static string Extract(this ICustomAttributeProvider originalMethod, string attributeName, + private static string? Extract(this IHasCustomAttribute originalMethod, string attributeName, string parameterName) { - var attribute = originalMethod.CustomAttributes.SingleOrDefault(it => it.AttributeType.Name == attributeName); - var field = attribute?.Fields.SingleOrDefault(it => it.Name == parameterName); + var attribute = originalMethod.CustomAttributes.SingleOrDefault(it => it.Constructor?.DeclaringType?.Name == attributeName); + var field = attribute?.Signature?.NamedArguments.SingleOrDefault(it => it.MemberName == parameterName); - if (field?.Name == null) return null; - - return (string)field.Value.Argument.Value; + return (Utf8String?)field?.Argument.Element; } - private static long ExtractLong(this ICustomAttributeProvider originalMethod, string attributeName, string parameterName) + private static long ExtractLong(this IHasCustomAttribute originalMethod, string attributeName, string parameterName) { return Convert.ToInt64(Extract(originalMethod, attributeName, parameterName), 16); } - private static int ExtractInt(this ICustomAttributeProvider originalMethod, string attributeName, string parameterName) + private static int ExtractInt(this IHasCustomAttribute originalMethod, string attributeName, string parameterName) { return Convert.ToInt32(Extract(originalMethod, attributeName, parameterName), 16); } diff --git a/Il2CppInterop.Generator/Extensions/EnumEx.cs b/Il2CppInterop.Generator/Extensions/EnumEx.cs index e6bb058e..b305c61d 100644 --- a/Il2CppInterop.Generator/Extensions/EnumEx.cs +++ b/Il2CppInterop.Generator/Extensions/EnumEx.cs @@ -1,4 +1,4 @@ -using Mono.Cecil; +using AsmResolver.PE.DotNet.Metadata.Tables; namespace Il2CppInterop.Generator.Extensions; diff --git a/Il2CppInterop.Generator/Extensions/ILGeneratorEx.cs b/Il2CppInterop.Generator/Extensions/ILGeneratorEx.cs index dd2cc1ae..75d4002f 100644 --- a/Il2CppInterop.Generator/Extensions/ILGeneratorEx.cs +++ b/Il2CppInterop.Generator/Extensions/ILGeneratorEx.cs @@ -1,42 +1,23 @@ +using System.Diagnostics; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Code.Cil; +using AsmResolver.DotNet.Collections; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Cil; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; -using Mono.Cecil.Cil; namespace Il2CppInterop.Generator.Extensions; public static class ILGeneratorEx { - private static readonly OpCode[] I4Constants = - { - OpCodes.Ldc_I4_M1, - OpCodes.Ldc_I4_0, - OpCodes.Ldc_I4_1, - OpCodes.Ldc_I4_2, - OpCodes.Ldc_I4_3, - OpCodes.Ldc_I4_4, - OpCodes.Ldc_I4_5, - OpCodes.Ldc_I4_6, - OpCodes.Ldc_I4_7, - OpCodes.Ldc_I4_8 - }; - - public static void EmitLdcI4(this ILProcessor body, int constant) - { - if (constant >= -1 && constant <= 8) - body.Emit(I4Constants[constant + 1]); - else if (constant >= byte.MinValue && constant <= byte.MaxValue) - body.Emit(OpCodes.Ldc_I4_S, (sbyte)constant); - else - body.Emit(OpCodes.Ldc_I4, constant); - } - - public static void EmitObjectStore(this ILProcessor body, TypeReference originalType, TypeReference newType, + public static void EmitObjectStore(this ILProcessor body, TypeSignature originalType, TypeSignature newType, TypeRewriteContext enclosingType, int argumentIndex) { // input stack: object address, target address // output: nothing - if (originalType is GenericParameter) + if (originalType is GenericParameterSignature) { EmitObjectStoreGeneric(body, originalType, newType, enclosingType, argumentIndex); return; @@ -46,45 +27,44 @@ public static void EmitObjectStore(this ILProcessor body, TypeReference original if (originalType.FullName == "System.String") { - body.Emit(OpCodes.Ldarg, argumentIndex); - body.Emit(OpCodes.Call, imports.IL2CPP_ManagedStringToIl2Cpp.Value); - body.Emit(OpCodes.Call, imports.WriteFieldWBarrier); + body.AddLoadArgument(argumentIndex); + body.Add(OpCodes.Call, imports.IL2CPP_ManagedStringToIl2Cpp.Value); + body.Add(OpCodes.Call, imports.WriteFieldWBarrier); } else if (originalType.IsValueType) { var typeSpecifics = enclosingType.AssemblyContext.GlobalContext.JudgeSpecificsByOriginalType(originalType); if (typeSpecifics == TypeRewriteContext.TypeSpecifics.BlittableStruct) { - body.Emit(OpCodes.Ldarg, argumentIndex); - body.Emit(OpCodes.Stobj, newType); - body.Emit(OpCodes.Pop); + body.AddLoadArgument(argumentIndex); + body.Add(OpCodes.Stobj, newType.ToTypeDefOrRef()); + body.Add(OpCodes.Pop); } else { - body.Emit(OpCodes.Ldarg, argumentIndex); - body.Emit(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtr.Value); - body.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_object_unbox.Value); - var classPointerTypeRef = new GenericInstanceType(imports.Il2CppClassPointerStore) - { GenericArguments = { newType } }; + body.AddLoadArgument(argumentIndex); + body.Add(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtr.Value); + body.Add(OpCodes.Call, imports.IL2CPP_il2cpp_object_unbox.Value); + var classPointerTypeRef = new GenericInstanceTypeSignature(imports.Il2CppClassPointerStore.ToTypeDefOrRef(), imports.Il2CppClassPointerStore.IsValueType, newType); var classPointerFieldRef = - new FieldReference("NativeClassPtr", imports.Module.IntPtr(), classPointerTypeRef); - body.Emit(OpCodes.Ldsfld, enclosingType.NewType.Module.ImportReference(classPointerFieldRef)); - body.Emit(OpCodes.Ldc_I4_0); - body.Emit(OpCodes.Conv_U); - body.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_class_value_size.Value); - body.Emit(OpCodes.Cpblk); - body.Emit(OpCodes.Pop); + ReferenceCreator.CreateFieldReference("NativeClassPtr", imports.Module.IntPtr(), classPointerTypeRef.ToTypeDefOrRef()); + body.Add(OpCodes.Ldsfld, enclosingType.NewType.Module!.DefaultImporter.ImportField(classPointerFieldRef)); + body.Add(OpCodes.Ldc_I4_0); + body.Add(OpCodes.Conv_U); + body.Add(OpCodes.Call, imports.IL2CPP_il2cpp_class_value_size.Value); + body.Add(OpCodes.Cpblk); + body.Add(OpCodes.Pop); } } else { - body.Emit(OpCodes.Ldarg, argumentIndex); - body.Emit(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtr.Value); - body.Emit(OpCodes.Call, imports.WriteFieldWBarrier); + body.AddLoadArgument(argumentIndex); + body.Add(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtr.Value); + body.Add(OpCodes.Call, imports.WriteFieldWBarrier); } } - private static void EmitObjectStoreGeneric(ILProcessor body, TypeReference originalType, TypeReference newType, + private static void EmitObjectStoreGeneric(ILProcessor body, TypeSignature originalType, TypeSignature newType, TypeRewriteContext enclosingType, int argumentIndex) { // input stack: object address, target address @@ -92,79 +72,80 @@ private static void EmitObjectStoreGeneric(ILProcessor body, TypeReference origi var imports = enclosingType.AssemblyContext.Imports; - body.Emit(OpCodes.Ldtoken, newType); - body.Emit(OpCodes.Call, enclosingType.NewType.Module.TypeGetTypeFromHandle()); - body.Emit(OpCodes.Dup); - body.Emit(OpCodes.Callvirt, enclosingType.NewType.Module.TypeGetIsValueType()); - - var finalNop = body.Create(OpCodes.Nop); - var stringNop = body.Create(OpCodes.Nop); - var valueTypeNop = body.Create(OpCodes.Nop); - var storePointerNop = body.Create(OpCodes.Nop); - - body.Emit(OpCodes.Brtrue, valueTypeNop); - - body.Emit(OpCodes.Callvirt, enclosingType.NewType.Module.TypeGetFullName()); - body.Emit(OpCodes.Ldstr, "System.String"); - body.Emit(OpCodes.Call, enclosingType.NewType.Module.StringEquals()); - body.Emit(OpCodes.Brtrue_S, stringNop); - - body.Emit(OpCodes.Ldarg, argumentIndex); - body.Emit(OpCodes.Box, newType); - body.Emit(OpCodes.Isinst, imports.Il2CppObjectBase); - body.Emit(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtr.Value); - body.Emit(OpCodes.Dup); - body.Emit(OpCodes.Brfalse_S, storePointerNop); - - body.Emit(OpCodes.Dup); - body.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_object_get_class.Value); - body.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_class_is_valuetype.Value); - body.Emit(OpCodes.Brfalse_S, storePointerNop); - - body.Emit(OpCodes.Dup); - var tempLocal = new VariableDefinition(imports.Module.IntPtr()); - body.Body.Variables.Add(tempLocal); - body.Emit(OpCodes.Stloc, tempLocal); - body.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_object_unbox.Value); - body.Emit(OpCodes.Ldloc, tempLocal); - body.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_object_get_class.Value); - body.Emit(OpCodes.Ldc_I4_0); - body.Emit(OpCodes.Conv_U); - body.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_class_value_size.Value); - body.Emit(OpCodes.Cpblk); - body.Emit(OpCodes.Pop); - body.Emit(OpCodes.Br_S, finalNop); - - body.Append(storePointerNop); - body.Emit(OpCodes.Call, imports.WriteFieldWBarrier); - body.Emit(OpCodes.Br_S, finalNop); - - body.Append(stringNop); - body.Emit(OpCodes.Ldarg, argumentIndex); - body.Emit(OpCodes.Box, newType); - body.Emit(OpCodes.Isinst, imports.Module.String()); - body.Emit(OpCodes.Call, imports.IL2CPP_ManagedStringToIl2Cpp.Value); - body.Emit(OpCodes.Call, imports.WriteFieldWBarrier); - body.Emit(OpCodes.Br_S, finalNop); - - body.Append(valueTypeNop); - body.Emit(OpCodes.Pop); // pop extra typeof(T) - body.Emit(OpCodes.Ldarg, argumentIndex); - body.Emit(OpCodes.Stobj, newType); - body.Emit(OpCodes.Pop); - - body.Append(finalNop); + Debug.Assert(enclosingType.NewType.Module is not null); + body.Add(OpCodes.Ldtoken, newType.ToTypeDefOrRef()); + body.Add(OpCodes.Call, enclosingType.NewType.Module!.TypeGetTypeFromHandle()); + body.Add(OpCodes.Dup); + body.Add(OpCodes.Callvirt, enclosingType.NewType.Module!.TypeGetIsValueType()); + + var finalNop = new CilInstructionLabel(); + var stringNop = new CilInstructionLabel(); + var valueTypeNop = new CilInstructionLabel(); + var storePointerNop = new CilInstructionLabel(); + + body.Add(OpCodes.Brtrue, valueTypeNop); + + body.Add(OpCodes.Callvirt, enclosingType.NewType.Module!.TypeGetFullName()); + body.Add(OpCodes.Ldstr, "System.String"); + body.Add(OpCodes.Call, enclosingType.NewType.Module!.StringEquals()); + body.Add(OpCodes.Brtrue_S, stringNop); + + body.AddLoadArgument(argumentIndex); + body.Add(OpCodes.Box, newType.ToTypeDefOrRef()); + body.Add(OpCodes.Isinst, imports.Il2CppObjectBase.ToTypeDefOrRef()); + body.Add(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtr.Value); + body.Add(OpCodes.Dup); + body.Add(OpCodes.Brfalse_S, storePointerNop); + + body.Add(OpCodes.Dup); + body.Add(OpCodes.Call, imports.IL2CPP_il2cpp_object_get_class.Value); + body.Add(OpCodes.Call, imports.IL2CPP_il2cpp_class_is_valuetype.Value); + body.Add(OpCodes.Brfalse_S, storePointerNop); + + body.Add(OpCodes.Dup); + var tempLocal = new CilLocalVariable(imports.Module.IntPtr()); + body.Owner.LocalVariables.Add(tempLocal); + body.Add(OpCodes.Stloc, tempLocal); + body.Add(OpCodes.Call, imports.IL2CPP_il2cpp_object_unbox.Value); + body.Add(OpCodes.Ldloc, tempLocal); + body.Add(OpCodes.Call, imports.IL2CPP_il2cpp_object_get_class.Value); + body.Add(OpCodes.Ldc_I4_0); + body.Add(OpCodes.Conv_U); + body.Add(OpCodes.Call, imports.IL2CPP_il2cpp_class_value_size.Value); + body.Add(OpCodes.Cpblk); + body.Add(OpCodes.Pop); + body.Add(OpCodes.Br_S, finalNop); + + storePointerNop.Instruction = body.Add(OpCodes.Nop); + body.Add(OpCodes.Call, imports.WriteFieldWBarrier); + body.Add(OpCodes.Br_S, finalNop); + + stringNop.Instruction = body.Add(OpCodes.Nop); + body.AddLoadArgument(argumentIndex); + body.Add(OpCodes.Box, newType.ToTypeDefOrRef()); + body.Add(OpCodes.Isinst, imports.Module.String().ToTypeDefOrRef()); + body.Add(OpCodes.Call, imports.IL2CPP_ManagedStringToIl2Cpp.Value); + body.Add(OpCodes.Call, imports.WriteFieldWBarrier); + body.Add(OpCodes.Br_S, finalNop); + + valueTypeNop.Instruction = body.Add(OpCodes.Nop); + body.Add(OpCodes.Pop); // pop extra typeof(T) + body.AddLoadArgument(argumentIndex); + body.Add(OpCodes.Stobj, newType.ToTypeDefOrRef()); + body.Add(OpCodes.Pop); + + finalNop.Instruction = body.Add(OpCodes.Nop); } - public static void EmitObjectToPointer(this ILProcessor body, TypeReference originalType, TypeReference newType, + public static void EmitObjectToPointer(this ILProcessor body, TypeSignature originalType, TypeSignature newType, TypeRewriteContext enclosingType, int argumentIndex, bool valueTypeArgument0IsAPointer, bool allowNullable, - bool unboxNonBlittableType, bool unboxNonBlittableGeneric, out VariableDefinition? refVariable) + bool unboxNonBlittableType, bool unboxNonBlittableGeneric, out CilLocalVariable? refVariable) { // input stack: not used // output stack: IntPtr to either Il2CppObject or IL2CPP value type refVariable = null; - if (originalType is GenericParameter) + if (originalType is GenericParameterSignature) { EmitObjectToPointerGeneric(body, originalType, newType, enclosingType, argumentIndex, valueTypeArgument0IsAPointer, allowNullable, unboxNonBlittableGeneric); @@ -172,33 +153,33 @@ public static void EmitObjectToPointer(this ILProcessor body, TypeReference orig } var imports = enclosingType.AssemblyContext.Imports; - if (originalType is ByReferenceType) + if (originalType is ByReferenceTypeSignature) { if (newType.GetElementType().IsValueType) { - body.Emit(OpCodes.Ldarg, argumentIndex); - body.Emit(OpCodes.Conv_I); + body.AddLoadArgument(argumentIndex); + body.Add(OpCodes.Conv_I); } else if (originalType.GetElementType().IsValueType) { - body.Emit(OpCodes.Ldarg, argumentIndex); - body.Emit(OpCodes.Ldind_Ref); - body.Emit(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtrNotNull.Value); + body.AddLoadArgument(argumentIndex); + body.Add(OpCodes.Ldind_Ref); + body.Add(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtrNotNull.Value); } else { - var pointerVar = new VariableDefinition(imports.Module.IntPtr()); + var pointerVar = new CilLocalVariable(imports.Module.IntPtr()); refVariable = pointerVar; - body.Body.Variables.Add(pointerVar); - body.Emit(OpCodes.Ldarg, argumentIndex); - body.Emit(OpCodes.Ldind_Ref); + body.Owner.LocalVariables.Add(pointerVar); + body.AddLoadArgument(argumentIndex); + body.Add(OpCodes.Ldind_Ref); if (originalType.GetElementType().FullName == "System.String") - body.Emit(OpCodes.Call, imports.IL2CPP_ManagedStringToIl2Cpp.Value); + body.Add(OpCodes.Call, imports.IL2CPP_ManagedStringToIl2Cpp.Value); else - body.Emit(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtr.Value); - body.Emit(OpCodes.Stloc, pointerVar); - body.Emit(OpCodes.Ldloca, pointerVar); - body.Emit(OpCodes.Conv_I); + body.Add(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtr.Value); + body.Add(OpCodes.Stloc, pointerVar); + body.Add(OpCodes.Ldloca, pointerVar); + body.Add(OpCodes.Conv_I); } } else if (originalType.IsValueType) @@ -206,94 +187,95 @@ public static void EmitObjectToPointer(this ILProcessor body, TypeReference orig if (newType.IsValueType) { if (argumentIndex == 0 && valueTypeArgument0IsAPointer) - body.Emit(OpCodes.Ldarg_0); + body.Add(OpCodes.Ldarg_0); else - body.Emit(OpCodes.Ldarga, argumentIndex); + body.AddLoadArgumentAddress(argumentIndex); } else { - body.Emit(OpCodes.Ldarg, argumentIndex); - body.Emit(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtrNotNull.Value); + body.AddLoadArgument(argumentIndex); + body.Add(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtrNotNull.Value); if (unboxNonBlittableType) - body.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_object_unbox.Value); + body.Add(OpCodes.Call, imports.IL2CPP_il2cpp_object_unbox.Value); } } else if (originalType.FullName == "System.String") { - body.Emit(OpCodes.Ldarg, argumentIndex); - body.Emit(OpCodes.Call, imports.IL2CPP_ManagedStringToIl2Cpp.Value); + body.AddLoadArgument(argumentIndex); + body.Add(OpCodes.Call, imports.IL2CPP_ManagedStringToIl2Cpp.Value); } else { - body.Emit(OpCodes.Ldarg, argumentIndex); - body.Emit(OpCodes.Call, + body.AddLoadArgument(argumentIndex); + body.Add(OpCodes.Call, allowNullable ? imports.IL2CPP_Il2CppObjectBaseToPtr.Value : imports.IL2CPP_Il2CppObjectBaseToPtrNotNull.Value); } } - private static void EmitObjectToPointerGeneric(ILProcessor body, TypeReference originalType, - TypeReference newType, TypeRewriteContext enclosingType, int argumentIndex, + private static void EmitObjectToPointerGeneric(ILProcessor body, TypeSignature originalType, + TypeSignature newType, TypeRewriteContext enclosingType, int argumentIndex, bool valueTypeArgument0IsAPointer, bool allowNullable, bool unboxNonBlittableType) { var imports = enclosingType.AssemblyContext.Imports; - body.Emit(OpCodes.Ldtoken, newType); - body.Emit(OpCodes.Call, enclosingType.NewType.Module.TypeGetTypeFromHandle()); - body.Emit(OpCodes.Callvirt, enclosingType.NewType.Module.TypeGetIsValueType()); + Debug.Assert(enclosingType.NewType.Module is not null); + body.Add(OpCodes.Ldtoken, newType.ToTypeDefOrRef()); + body.Add(OpCodes.Call, enclosingType.NewType.Module!.TypeGetTypeFromHandle()); + body.Add(OpCodes.Callvirt, enclosingType.NewType.Module!.TypeGetIsValueType()); - var finalNop = body.Create(OpCodes.Nop); - var valueTypeNop = body.Create(OpCodes.Nop); - var stringNop = body.Create(OpCodes.Nop); + var finalNop = new CilInstructionLabel(); + var valueTypeNop = new CilInstructionLabel(); + var stringNop = new CilInstructionLabel(); - body.Emit(OpCodes.Brtrue, valueTypeNop); + body.Add(OpCodes.Brtrue, valueTypeNop); - body.Emit(OpCodes.Ldarg, argumentIndex); - body.Emit(OpCodes.Box, newType); - body.Emit(OpCodes.Dup); - body.Emit(OpCodes.Isinst, imports.Module.String()); - body.Emit(OpCodes.Brtrue_S, stringNop); + body.AddLoadArgument(argumentIndex); + body.Add(OpCodes.Box, newType.ToTypeDefOrRef()); + body.Add(OpCodes.Dup); + body.Add(OpCodes.Isinst, imports.Module.String().ToTypeDefOrRef()); + body.Add(OpCodes.Brtrue_S, stringNop); - body.Emit(OpCodes.Isinst, imports.Il2CppObjectBase); - body.Emit(OpCodes.Call, + body.Add(OpCodes.Isinst, imports.Il2CppObjectBase.ToTypeDefOrRef()); + body.Add(OpCodes.Call, allowNullable ? imports.IL2CPP_Il2CppObjectBaseToPtr.Value : imports.IL2CPP_Il2CppObjectBaseToPtrNotNull.Value); if (unboxNonBlittableType) { - body.Emit(OpCodes.Dup); - body.Emit(OpCodes.Brfalse_S, finalNop); // return null immediately - body.Emit(OpCodes.Dup); - body.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_object_get_class.Value); - body.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_class_is_valuetype.Value); - body.Emit(OpCodes.Brfalse_S, finalNop); // return reference types immediately - body.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_object_unbox.Value); + body.Add(OpCodes.Dup); + body.Add(OpCodes.Brfalse_S, finalNop); // return null immediately + body.Add(OpCodes.Dup); + body.Add(OpCodes.Call, imports.IL2CPP_il2cpp_object_get_class.Value); + body.Add(OpCodes.Call, imports.IL2CPP_il2cpp_class_is_valuetype.Value); + body.Add(OpCodes.Brfalse_S, finalNop); // return reference types immediately + body.Add(OpCodes.Call, imports.IL2CPP_il2cpp_object_unbox.Value); } - body.Emit(OpCodes.Br, finalNop); + body.Add(OpCodes.Br, finalNop); - body.Append(stringNop); - body.Emit(OpCodes.Isinst, imports.Module.String()); - body.Emit(OpCodes.Call, imports.IL2CPP_ManagedStringToIl2Cpp.Value); - body.Emit(OpCodes.Br_S, finalNop); + stringNop.Instruction = body.Add(OpCodes.Nop); + body.Add(OpCodes.Isinst, imports.Module.String().ToTypeDefOrRef()); + body.Add(OpCodes.Call, imports.IL2CPP_ManagedStringToIl2Cpp.Value); + body.Add(OpCodes.Br_S, finalNop); - body.Append(valueTypeNop); - body.Emit(OpCodes.Ldarga, argumentIndex); + valueTypeNop.Instruction = body.Add(OpCodes.Nop); + body.AddLoadArgumentAddress(argumentIndex); - body.Append(finalNop); + finalNop.Instruction = body.Add(OpCodes.Nop); } - public static void EmitPointerToObject(this ILProcessor body, TypeReference originalReturnType, - TypeReference convertedReturnType, TypeRewriteContext enclosingType, Instruction loadPointer, + public static void EmitPointerToObject(this ILProcessor body, TypeSignature originalReturnType, + TypeSignature convertedReturnType, TypeRewriteContext enclosingType, CilLocalVariable pointerVariable, bool extraDerefForNonValueTypes, bool unboxValueType) { // input stack: not used // output stack: converted result - if (originalReturnType is GenericParameter) + if (originalReturnType is GenericParameterSignature) { - EmitPointerToObjectGeneric(body, originalReturnType, convertedReturnType, enclosingType, loadPointer, + EmitPointerToObjectGeneric(body, originalReturnType, convertedReturnType, enclosingType, pointerVariable, extraDerefForNonValueTypes, unboxValueType); return; } @@ -307,143 +289,141 @@ public static void EmitPointerToObject(this ILProcessor body, TypeReference orig { if (convertedReturnType.IsValueType) { - body.Append(loadPointer); - if (unboxValueType) body.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_object_unbox.Value); - body.Emit(OpCodes.Ldobj, convertedReturnType); + body.Add(OpCodes.Ldloc, pointerVariable); + if (unboxValueType) body.Add(OpCodes.Call, imports.IL2CPP_il2cpp_object_unbox.Value); + body.Add(OpCodes.Ldobj, convertedReturnType.ToTypeDefOrRef()); } else { if (unboxValueType) { - body.Append(loadPointer); + body.Add(OpCodes.Ldloc, pointerVariable); } else { - var classPointerTypeRef = new GenericInstanceType(imports.Il2CppClassPointerStore) - { GenericArguments = { convertedReturnType } }; + Debug.Assert(enclosingType.NewType.Module is not null); + var classPointerTypeRef = new GenericInstanceTypeSignature(imports.Il2CppClassPointerStore.ToTypeDefOrRef(), imports.Il2CppClassPointerStore.IsValueType, convertedReturnType); var classPointerFieldRef = - new FieldReference("NativeClassPtr", imports.Module.IntPtr(), - classPointerTypeRef); - body.Emit(OpCodes.Ldsfld, enclosingType.NewType.Module.ImportReference(classPointerFieldRef)); - body.Append(loadPointer); - body.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_value_box.Value); + ReferenceCreator.CreateFieldReference("NativeClassPtr", imports.Module.IntPtr(), + classPointerTypeRef.ToTypeDefOrRef()); + body.Add(OpCodes.Ldsfld, enclosingType.NewType.Module!.DefaultImporter.ImportField(classPointerFieldRef)); + body.Add(OpCodes.Ldloc, pointerVariable); + body.Add(OpCodes.Call, imports.IL2CPP_il2cpp_value_box.Value); } - body.Emit(OpCodes.Newobj, - new MethodReference(".ctor", imports.Module.Void(), convertedReturnType) - { Parameters = { new ParameterDefinition(imports.Module.IntPtr()) }, HasThis = true }); + body.Add(OpCodes.Newobj, + ReferenceCreator.CreateInstanceMethodReference(".ctor", imports.Module.Void(), convertedReturnType.ToTypeDefOrRef(), imports.Module.IntPtr())); } } else if (originalReturnType.FullName == "System.String") { - body.Append(loadPointer); - if (extraDerefForNonValueTypes) body.Emit(OpCodes.Ldind_I); - body.Emit(OpCodes.Call, imports.IL2CPP_Il2CppStringToManaged.Value); + body.Add(OpCodes.Ldloc, pointerVariable); + if (extraDerefForNonValueTypes) body.Add(OpCodes.Ldind_I); + body.Add(OpCodes.Call, imports.IL2CPP_Il2CppStringToManaged.Value); } - else if (originalReturnType.IsArray && originalReturnType.GetElementType().IsGenericParameter) + else if (originalReturnType is ArrayBaseTypeSignature && originalReturnType.GetElementType() is GenericParameterSignature genericParameterSignature) { - body.Append(loadPointer); - if (extraDerefForNonValueTypes) body.Emit(OpCodes.Ldind_I); - var actualReturnType = imports.Module.ImportReference(new GenericInstanceType(imports.Il2CppArrayBase) - { GenericArguments = { imports.Il2CppArrayBase.GenericParameters[0] } }); - var methodRef = new MethodReference("WrapNativeGenericArrayPointer", + // Note: + // The method reference parent is constructed relative to the calling method. + // The return type and parameter types are constructed relative to the called method. + body.Add(OpCodes.Ldloc, pointerVariable); + if (extraDerefForNonValueTypes) body.Add(OpCodes.Ldind_I); + var actualReturnType = imports.Module.DefaultImporter.ImportTypeSignature(imports.Il2CppArrayBase.MakeGenericInstanceType(new GenericParameterSignature(GenericParameterType.Type, 0))); + var methodRef = ReferenceCreator.CreateStaticMethodReference("WrapNativeGenericArrayPointer", actualReturnType, - convertedReturnType) - { HasThis = false, Parameters = { new ParameterDefinition(imports.Module.IntPtr()) } }; - body.Emit(OpCodes.Call, methodRef); + convertedReturnType.ToTypeDefOrRef(), + imports.Module.IntPtr()); + body.Add(OpCodes.Call, methodRef); } else { - var createPoolObject = body.Create(OpCodes.Call, - imports.Module.ImportReference(new GenericInstanceMethod(imports.Il2CppObjectPool_Get.Value) - { GenericArguments = { convertedReturnType } })); - var endNop = body.Create(OpCodes.Nop); - - body.Append(loadPointer); - if (extraDerefForNonValueTypes) body.Emit(OpCodes.Ldind_I); - body.Emit(OpCodes.Dup); - body.Emit(OpCodes.Brtrue_S, createPoolObject); - body.Emit(OpCodes.Pop); - body.Emit(OpCodes.Ldnull); - body.Emit(OpCodes.Br, endNop); - - body.Append(createPoolObject); - body.Append(endNop); + var createPoolObject = new CilInstructionLabel(); + var endNop = new CilInstructionLabel(); + + body.Add(OpCodes.Ldloc, pointerVariable); + if (extraDerefForNonValueTypes) body.Add(OpCodes.Ldind_I); + body.Add(OpCodes.Dup); + body.Add(OpCodes.Brtrue_S, createPoolObject); + body.Add(OpCodes.Pop); + body.Add(OpCodes.Ldnull); + body.Add(OpCodes.Br, endNop); + + createPoolObject.Instruction = body.Add(OpCodes.Call, + imports.Module.DefaultImporter.ImportMethod(imports.Il2CppObjectPool_Get.Value.MakeGenericInstanceMethod(convertedReturnType))); + endNop.Instruction = body.Add(OpCodes.Nop); } } - private static void EmitPointerToObjectGeneric(ILProcessor body, TypeReference originalReturnType, - TypeReference newReturnType, - TypeRewriteContext enclosingType, Instruction loadPointer, bool extraDerefForNonValueTypes, + private static void EmitPointerToObjectGeneric(ILProcessor body, TypeSignature originalReturnType, + TypeSignature newReturnType, + TypeRewriteContext enclosingType, CilLocalVariable pointerVariable, bool extraDerefForNonValueTypes, bool unboxValueType) { var imports = enclosingType.AssemblyContext.Imports; - body.Append(loadPointer); + body.Add(OpCodes.Ldloc, pointerVariable); - body.Emit(extraDerefForNonValueTypes ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); - body.Emit(unboxValueType ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); - body.Emit(OpCodes.Call, - imports.Module.ImportReference(new GenericInstanceMethod(imports.IL2CPP_PointerToValueGeneric.Value) - { GenericArguments = { newReturnType } })); + body.Add(extraDerefForNonValueTypes ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); + body.Add(unboxValueType ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); + body.Add(OpCodes.Call, + imports.Module.DefaultImporter.ImportMethod(imports.IL2CPP_PointerToValueGeneric.Value.MakeGenericInstanceMethod(newReturnType))); } public static void GenerateBoxMethod(RuntimeAssemblyReferences imports, TypeDefinition targetType, - FieldReference classHandle, TypeReference il2CppObjectTypeDef) + IFieldDescriptor classHandle, TypeSignature il2CppObjectTypeDef) { + Debug.Assert(targetType.Module is not null); var method = new MethodDefinition("BoxIl2CppObject", MethodAttributes.Public | MethodAttributes.HideBySig, - targetType.Module.ImportReference(il2CppObjectTypeDef)); + MethodSignature.CreateInstance(targetType.Module!.DefaultImporter.ImportTypeSignature(il2CppObjectTypeDef))); targetType.Methods.Add(method); - var methodBody = method.Body.GetILProcessor(); - methodBody.Emit(OpCodes.Ldsfld, classHandle); - methodBody.Emit(OpCodes.Ldarg_0); - methodBody.Emit(OpCodes.Call, targetType.Module.ImportReference(imports.IL2CPP_il2cpp_value_box.Value)); + method.CilMethodBody = new CilMethodBody(method); + var methodBody = method.CilMethodBody.Instructions; + methodBody.Add(OpCodes.Ldsfld, classHandle); + methodBody.Add(OpCodes.Ldarg_0); + methodBody.Add(OpCodes.Call, targetType.Module.DefaultImporter.ImportMethod(imports.IL2CPP_il2cpp_value_box.Value)); - methodBody.Emit(OpCodes.Newobj, - new MethodReference(".ctor", targetType.Module.Void(), il2CppObjectTypeDef) - { Parameters = { new ParameterDefinition(targetType.Module.IntPtr()) }, HasThis = true }); + methodBody.Add(OpCodes.Newobj, + new MemberReference(il2CppObjectTypeDef.ToTypeDefOrRef(), ".ctor", MethodSignature.CreateInstance(targetType.Module.Void(), targetType.Module.IntPtr()))); - methodBody.Emit(OpCodes.Ret); + methodBody.Add(OpCodes.Ret); } - public static void EmitUpdateRef(this ILProcessor body, ParameterDefinition newMethodParameter, int argIndex, - VariableDefinition paramVariable, RuntimeAssemblyReferences imports) + public static void EmitUpdateRef(this ILProcessor body, Parameter newMethodParameter, int argIndex, + CilLocalVariable paramVariable, RuntimeAssemblyReferences imports) { - body.Emit(OpCodes.Ldarg, argIndex); - body.Emit(OpCodes.Ldloc, paramVariable); + body.AddLoadArgument(argIndex); + body.Add(OpCodes.Ldloc, paramVariable); if (newMethodParameter.ParameterType.GetElementType().FullName == "System.String") { - body.Emit(OpCodes.Call, imports.IL2CPP_Il2CppStringToManaged.Value); + body.Add(OpCodes.Call, imports.IL2CPP_Il2CppStringToManaged.Value); } else { - body.Emit(OpCodes.Dup); - var nullbr = body.Create(OpCodes.Pop); - var stnop = body.Create(OpCodes.Nop); - body.Emit(OpCodes.Brfalse_S, nullbr); + body.Add(OpCodes.Dup); + var nullbr = new CilInstructionLabel(); + var stnop = new CilInstructionLabel(); + body.Add(OpCodes.Brfalse_S, nullbr); - if (newMethodParameter.ParameterType.GetElementType() is GenericParameter) + if (newMethodParameter.ParameterType.GetElementType() is GenericParameterSignature) { - body.Emit(OpCodes.Ldc_I4_0); - body.Emit(OpCodes.Ldc_I4_0); - body.Emit(OpCodes.Call, - imports.Module.ImportReference(new GenericInstanceMethod(imports.IL2CPP_PointerToValueGeneric.Value) - { GenericArguments = { newMethodParameter.ParameterType.GetElementType() } })); + body.Add(OpCodes.Ldc_I4_0); + body.Add(OpCodes.Ldc_I4_0); + body.Add(OpCodes.Call, + imports.Module.DefaultImporter.ImportMethod(imports.IL2CPP_PointerToValueGeneric.Value.MakeGenericInstanceMethod(newMethodParameter.ParameterType.GetElementType()))); } else { - body.Emit(OpCodes.Newobj, - new MethodReference(".ctor", imports.Module.Void(), newMethodParameter.ParameterType.GetElementType()) - { HasThis = true, Parameters = { new ParameterDefinition(imports.Module.IntPtr()) } }); + body.Add(OpCodes.Newobj, + ReferenceCreator.CreateInstanceMethodReference(".ctor", imports.Module.Void(), newMethodParameter.ParameterType.GetElementType().ToTypeDefOrRef(), imports.Module.IntPtr())); } - body.Emit(OpCodes.Br_S, stnop); + body.Add(OpCodes.Br_S, stnop); - body.Append(nullbr); - body.Emit(OpCodes.Ldnull); - body.Append(stnop); + nullbr.Instruction = body.Add(OpCodes.Pop); + body.Add(OpCodes.Ldnull); + stnop.Instruction = body.Add(OpCodes.Nop); } - body.Emit(OpCodes.Stind_Ref); + body.Add(OpCodes.Stind_Ref); } } diff --git a/Il2CppInterop.Generator/Extensions/ParameterDefinitionEx.cs b/Il2CppInterop.Generator/Extensions/ParameterDefinitionEx.cs index 2275d5f9..a32f1719 100644 --- a/Il2CppInterop.Generator/Extensions/ParameterDefinitionEx.cs +++ b/Il2CppInterop.Generator/Extensions/ParameterDefinitionEx.cs @@ -1,12 +1,13 @@ -using Mono.Cecil; +using AsmResolver.DotNet.Collections; +using AsmResolver.DotNet.Signatures; namespace Il2CppInterop.Generator.Extensions; internal static class ParameterDefinitionEx { - public static bool IsParamsArray(this ParameterDefinition self) + public static bool IsParamsArray(this Parameter self) { - return self.ParameterType is ArrayType { Rank: 1 } && self.CustomAttributes.Any(attribute => - attribute.AttributeType.FullName == typeof(ParamArrayAttribute).FullName); + return self.ParameterType is SzArrayTypeSignature && (self.Definition?.CustomAttributes.Any(attribute => + attribute.Constructor?.DeclaringType?.FullName == typeof(ParamArrayAttribute).FullName) ?? false); } } diff --git a/Il2CppInterop.Generator/Extensions/StringEx.cs b/Il2CppInterop.Generator/Extensions/StringEx.cs index c6fe91d9..9d9287e5 100644 --- a/Il2CppInterop.Generator/Extensions/StringEx.cs +++ b/Il2CppInterop.Generator/Extensions/StringEx.cs @@ -1,5 +1,8 @@ +using System.Diagnostics.CodeAnalysis; using System.Text; -using Mono.Cecil; +using AsmResolver; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; namespace Il2CppInterop.Generator.Extensions; @@ -23,12 +26,23 @@ public static bool NameShouldBePrefixed(this string str, GeneratorOptions option return true; } } + + public static bool NameShouldBePrefixed(this Utf8String? str, GeneratorOptions options) + { + return NameShouldBePrefixed(str?.Value ?? "", options); + } + public static string UnSystemify(this string str, GeneratorOptions options) { const string Il2CppPrefix = "Il2Cpp"; return str.NameShouldBePrefixed(options) ? Il2CppPrefix + str : str; } + public static string UnSystemify(this Utf8String? str, GeneratorOptions options) + { + return UnSystemify(str?.Value ?? "", options); + } + public static string FilterInvalidInSourceChars(this string str) { var chars = str.ToCharArray(); @@ -42,6 +56,11 @@ public static string FilterInvalidInSourceChars(this string str) return new string(chars); } + public static string FilterInvalidInSourceChars(this Utf8String? str) + { + return str?.Value.FilterInvalidInSourceChars() ?? ""; + } + public static bool IsInvalidInSource(this string str) { for (var i = 0; i < str.Length; i++) @@ -54,8 +73,15 @@ public static bool IsInvalidInSource(this string str) return false; } - public static bool IsObfuscated(this string str, GeneratorOptions options) + public static bool IsInvalidInSource(this Utf8String? str) + { + return IsInvalidInSource(str?.Value ?? ""); + } + + public static bool IsObfuscated([NotNullWhen(true)] this string? str, GeneratorOptions options) { + if (str is null) + return false; if (options.ObfuscatedNamesRegex != null) return options.ObfuscatedNamesRegex.IsMatch(str); @@ -67,6 +93,11 @@ public static bool IsObfuscated(this string str, GeneratorOptions options) return false; } + public static bool IsObfuscated(this Utf8String? str, GeneratorOptions options) + { + return IsObfuscated(str?.Value ?? "", options); + } + public static ulong StableHash(this string str) { ulong hash = 0; @@ -76,35 +107,59 @@ public static ulong StableHash(this string str) return hash; } - public static string GetUnmangledName(this TypeReference typeRef) + public static ulong StableHash(this Utf8String? str) + { + return StableHash(str?.Value ?? ""); + } + + public static bool StartsWith([NotNullWhen(true)] this Utf8String? str, string value) + { + return str is not null && str.Value.StartsWith(value, StringComparison.Ordinal); + } + + /// + /// Construct an unmangled name for a type signature. + /// + /// + /// The declaring type to use for resolving generic type parameter names. + /// The declaring method to use for resolving generic method parameter names. + /// + public static string GetUnmangledName(this TypeSignature typeRef, TypeDefinition? declaringType = null, MethodDefinition? declaringMethod = null) { var builder = new StringBuilder(); - if (typeRef is GenericInstanceType genericInstance) + if (typeRef is GenericInstanceTypeSignature genericInstance) { - builder.Append(genericInstance.ElementType.GetUnmangledName()); - foreach (var genericArgument in genericInstance.GenericArguments) + builder.Append(genericInstance.GenericType.ToTypeSignature().GetUnmangledName(declaringType, declaringMethod)); + foreach (var genericArgument in genericInstance.TypeArguments) { builder.Append("_"); - builder.Append(genericArgument.GetUnmangledName()); + builder.Append(genericArgument.GetUnmangledName(declaringType, declaringMethod)); } } - else if (typeRef is ByReferenceType byRef) + else if (typeRef is ByReferenceTypeSignature byRef) { builder.Append("byref_"); - builder.Append(byRef.ElementType.GetUnmangledName()); + builder.Append(byRef.BaseType.GetUnmangledName(declaringType, declaringMethod)); } - else if (typeRef is PointerType pointer) + else if (typeRef is PointerTypeSignature pointer) { builder.Append("ptr_"); - builder.Append(pointer.ElementType.GetUnmangledName()); + builder.Append(pointer.BaseType.GetUnmangledName(declaringType, declaringMethod)); + } + else if (typeRef is GenericParameterSignature genericParameter) + { + if (genericParameter.ParameterType == GenericParameterType.Type) + builder.Append(declaringType!.GenericParameters[genericParameter.Index].Name); + else + builder.Append(declaringMethod!.GenericParameters[genericParameter.Index].Name); } else { - if (typeRef.Namespace == "Il2CppInterop.Runtime" && typeRef.Name.StartsWith("Il2Cpp") && + if (typeRef.Namespace == "Il2CppInterop.Runtime" && (typeRef.Name?.StartsWith("Il2Cpp") ?? false) && typeRef.Name.Contains("Array")) builder.Append("ArrayOf"); else - builder.Append(typeRef.Name.Replace('`', '_')); + builder.Append(typeRef.Name?.Replace('`', '_')); } return builder.ToString(); diff --git a/Il2CppInterop.Generator/Extensions/TypeReferenceEx.cs b/Il2CppInterop.Generator/Extensions/TypeReferenceEx.cs index 63faad93..e898eda4 100644 --- a/Il2CppInterop.Generator/Extensions/TypeReferenceEx.cs +++ b/Il2CppInterop.Generator/Extensions/TypeReferenceEx.cs @@ -1,36 +1,37 @@ -using Mono.Cecil; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; namespace Il2CppInterop.Generator.Extensions; public static class TypeReferenceEx { - public static bool UnmangledNamesMatch(this TypeReference typeRefA, TypeReference typeRefB) + public static bool UnmangledNamesMatch(this TypeSignature typeRefA, TypeSignature typeRefB) { - var aIsDefOrRef = typeRefA.GetType() == typeof(TypeReference) || typeRefA.GetType() == typeof(TypeDefinition); - var bIsDefOrRef = typeRefB.GetType() == typeof(TypeReference) || typeRefB.GetType() == typeof(TypeDefinition); + var aIsDefOrRef = typeRefA.GetType() == typeof(TypeDefOrRefSignature); + var bIsDefOrRef = typeRefB.GetType() == typeof(TypeDefOrRefSignature); if (!(aIsDefOrRef && bIsDefOrRef) && typeRefA.GetType() != typeRefB.GetType()) return false; switch (typeRefA) { - case PointerType pointer: - return pointer.ElementType.UnmangledNamesMatch(((PointerType)typeRefB).ElementType); - case ByReferenceType byRef: - return byRef.ElementType.UnmangledNamesMatch(((ByReferenceType)typeRefB).ElementType); - case ArrayType array: - return array.ElementType.UnmangledNamesMatch(((ArrayType)typeRefB).ElementType); - case GenericInstanceType genericInstance: + case PointerTypeSignature pointer: + return pointer.BaseType.UnmangledNamesMatch(((PointerTypeSignature)typeRefB).BaseType); + case ByReferenceTypeSignature byRef: + return byRef.BaseType.UnmangledNamesMatch(((ByReferenceTypeSignature)typeRefB).BaseType); + case ArrayBaseTypeSignature array: + return array.BaseType.UnmangledNamesMatch(((ArrayBaseTypeSignature)typeRefB).BaseType); + case GenericInstanceTypeSignature genericInstance: { - var elementA = genericInstance.ElementType; - var genericInstanceB = (GenericInstanceType)typeRefB; - var elementB = genericInstanceB.ElementType; + var elementA = genericInstance.GenericType.ToTypeSignature(); + var genericInstanceB = (GenericInstanceTypeSignature)typeRefB; + var elementB = genericInstanceB.GenericType.ToTypeSignature(); if (!elementA.UnmangledNamesMatch(elementB)) return false; - if (genericInstance.GenericArguments.Count != genericInstanceB.GenericArguments.Count) + if (genericInstance.TypeArguments.Count != genericInstanceB.TypeArguments.Count) return false; - for (var i = 0; i < genericInstance.GenericArguments.Count; i++) - if (!genericInstance.GenericArguments[i].UnmangledNamesMatch(genericInstanceB.GenericArguments[i])) + for (var i = 0; i < genericInstance.TypeArguments.Count; i++) + if (!genericInstance.TypeArguments[i].UnmangledNamesMatch(genericInstanceB.TypeArguments[i])) return false; return true; @@ -40,10 +41,10 @@ public static bool UnmangledNamesMatch(this TypeReference typeRefA, TypeReferenc } } - public static string GetNamespacePrefix(this TypeReference type) + public static string? GetNamespacePrefix(this ITypeDefOrRef type) { - if (type.IsNested) - return GetNamespacePrefix(type.DeclaringType) + "." + type.DeclaringType.Name; + if (type.DeclaringType is not null) + return $"{GetNamespacePrefix(type.DeclaringType)}.{type.DeclaringType.Name}"; return type.Namespace; } diff --git a/Il2CppInterop.Generator/Extensions/WriterEx.cs b/Il2CppInterop.Generator/Extensions/WriterEx.cs index 9a2f6400..1c31abda 100644 --- a/Il2CppInterop.Generator/Extensions/WriterEx.cs +++ b/Il2CppInterop.Generator/Extensions/WriterEx.cs @@ -1,5 +1,3 @@ -using System; -using System.IO; using System.Runtime.InteropServices; namespace Il2CppInterop.Generator.Extensions; diff --git a/Il2CppInterop.Generator/GeneratorOptions.cs b/Il2CppInterop.Generator/GeneratorOptions.cs index e335882c..59fe941e 100644 --- a/Il2CppInterop.Generator/GeneratorOptions.cs +++ b/Il2CppInterop.Generator/GeneratorOptions.cs @@ -1,7 +1,7 @@ using System.IO.Compression; using System.Text; using System.Text.RegularExpressions; -using Mono.Cecil; +using AsmResolver.DotNet; namespace Il2CppInterop.Generator; diff --git a/Il2CppInterop.Generator/Il2CppInterop.Generator.csproj b/Il2CppInterop.Generator/Il2CppInterop.Generator.csproj index 5fa4fb52..9eaf64a0 100644 --- a/Il2CppInterop.Generator/Il2CppInterop.Generator.csproj +++ b/Il2CppInterop.Generator/Il2CppInterop.Generator.csproj @@ -8,17 +8,19 @@ Il2CppInterop.Generator Debug;Release AnyCPU + latest + enable - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + diff --git a/Il2CppInterop.Generator/Il2CppInteropGenerator.cs b/Il2CppInterop.Generator/Il2CppInteropGenerator.cs index 832e3f05..a1a1aca5 100644 --- a/Il2CppInterop.Generator/Il2CppInteropGenerator.cs +++ b/Il2CppInterop.Generator/Il2CppInteropGenerator.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using Il2CppInterop.Common; +using Il2CppInterop.Common; using Il2CppInterop.Common.Host; using Il2CppInterop.Common.XrefScans; using Il2CppInterop.Generator.Runners; @@ -14,11 +13,14 @@ public sealed class Il2CppInteropGenerator : BaseHost private readonly List _runners = new(); - private Il2CppInteropGenerator() { } + private Il2CppInteropGenerator(GeneratorOptions options) + { + Options = options; + } public static Il2CppInteropGenerator Create(GeneratorOptions options) { - var generator = new Il2CppInteropGenerator { Options = options }; + var generator = new Il2CppInteropGenerator(options); generator.AddXrefScanner(); return generator; } diff --git a/Il2CppInterop.Generator/MetadataAccess/CecilMetadataAccess.cs b/Il2CppInterop.Generator/MetadataAccess/AssemblyMetadataAccess.cs similarity index 55% rename from Il2CppInterop.Generator/MetadataAccess/CecilMetadataAccess.cs rename to Il2CppInterop.Generator/MetadataAccess/AssemblyMetadataAccess.cs index 55b63c0c..e0cbd108 100644 --- a/Il2CppInterop.Generator/MetadataAccess/CecilMetadataAccess.cs +++ b/Il2CppInterop.Generator/MetadataAccess/AssemblyMetadataAccess.cs @@ -1,25 +1,21 @@ -using System.Collections.Generic; -using System.Linq; -using Mono.Cecil; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; namespace Il2CppInterop.Generator.MetadataAccess; -public class CecilMetadataAccess : IIl2CppMetadataAccess +public class AssemblyMetadataAccess : IIl2CppMetadataAccess { + private readonly Il2CppAssemblyResolver myAssemblyResolver = new(); private readonly List myAssemblies = new(); private readonly Dictionary myAssembliesByName = new(); - private readonly Resolver myAssemblyResolver = new(); private readonly Dictionary<(string AssemblyName, string TypeName), TypeDefinition> myTypesByName = new(); - public CecilMetadataAccess(IEnumerable assemblyPaths) + public AssemblyMetadataAccess(IEnumerable assemblyPaths) { - var metadataResolver = new MetadataResolver(myAssemblyResolver); - - Load(assemblyPaths.Select(path => AssemblyDefinition.ReadAssembly(path, - new ReaderParameters(ReadingMode.Deferred) { MetadataResolver = metadataResolver }))); + Load(assemblyPaths.Select(AssemblyDefinition.FromFile)); } - public CecilMetadataAccess(IEnumerable assemblies) + public AssemblyMetadataAccess(IEnumerable assemblies) { // Note: At the moment this assumes that passed assemblies have their own assembly resolver set up // If this is not true, this can cause issues with reference resolving @@ -28,12 +24,9 @@ public CecilMetadataAccess(IEnumerable assemblies) public void Dispose() { - foreach (var assemblyDefinition in myAssemblies) - assemblyDefinition.Dispose(); - + myAssemblyResolver.ClearCache(); myAssemblies.Clear(); myAssembliesByName.Clear(); - myAssemblyResolver.Dispose(); } public AssemblyDefinition? GetAssemblyBySimpleName(string name) @@ -48,7 +41,7 @@ public void Dispose() public IList Assemblies => myAssemblies; - public IList? GetKnownInstantiationsFor(TypeDefinition genericDeclaration) + public IList? GetKnownInstantiationsFor(TypeDefinition genericDeclaration) { return null; } @@ -58,7 +51,7 @@ public void Dispose() return null; } - public MethodReference? GetMethodRefStoredAt(long offsetInMemory) + public MemberReference? GetMethodRefStoredAt(long offsetInMemory) { return null; } @@ -67,25 +60,18 @@ private void Load(IEnumerable assemblies) { foreach (var sourceAssembly in assemblies) { - myAssemblyResolver.Register(sourceAssembly); myAssemblies.Add(sourceAssembly); - myAssembliesByName[sourceAssembly.Name.Name] = sourceAssembly; + myAssembliesByName[sourceAssembly.Name!] = sourceAssembly; + sourceAssembly.ManifestModule!.MetadataResolver = new DefaultMetadataResolver(myAssemblyResolver); + myAssemblyResolver.AddToCache(sourceAssembly); } foreach (var sourceAssembly in myAssemblies) { - var sourceAssemblyName = sourceAssembly.Name.Name; - foreach (var type in sourceAssembly.MainModule.Types) + var sourceAssemblyName = sourceAssembly.Name!; + foreach (var type in sourceAssembly.ManifestModule!.TopLevelTypes) // todo: nested types? myTypesByName[(sourceAssemblyName, type.FullName)] = type; } } - - private class Resolver : DefaultAssemblyResolver - { - public void Register(AssemblyDefinition ass) - { - RegisterAssembly(ass); - } - } } diff --git a/Il2CppInterop.Generator/MetadataAccess/IIl2CppMetadataAccess.cs b/Il2CppInterop.Generator/MetadataAccess/IIl2CppMetadataAccess.cs index 970ea8e0..f4f09d26 100644 --- a/Il2CppInterop.Generator/MetadataAccess/IIl2CppMetadataAccess.cs +++ b/Il2CppInterop.Generator/MetadataAccess/IIl2CppMetadataAccess.cs @@ -1,11 +1,11 @@ -using System.Collections.Generic; -using Mono.Cecil; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; namespace Il2CppInterop.Generator.MetadataAccess; public interface IIl2CppMetadataAccess : IMetadataAccess { - IList? GetKnownInstantiationsFor(TypeDefinition genericDeclaration); + IList? GetKnownInstantiationsFor(TypeDefinition genericDeclaration); string? GetStringStoredAtAddress(long offsetInMemory); - MethodReference? GetMethodRefStoredAt(long offsetInMemory); + MemberReference? GetMethodRefStoredAt(long offsetInMemory); } diff --git a/Il2CppInterop.Generator/MetadataAccess/IMetadataAccess.cs b/Il2CppInterop.Generator/MetadataAccess/IMetadataAccess.cs index 01a8ee4b..63f0b585 100644 --- a/Il2CppInterop.Generator/MetadataAccess/IMetadataAccess.cs +++ b/Il2CppInterop.Generator/MetadataAccess/IMetadataAccess.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using Mono.Cecil; +using AsmResolver.DotNet; namespace Il2CppInterop.Generator.MetadataAccess; diff --git a/Il2CppInterop.Generator/MetadataAccess/Il2CppAssemblyResolver.cs b/Il2CppInterop.Generator/MetadataAccess/Il2CppAssemblyResolver.cs new file mode 100644 index 00000000..8874998a --- /dev/null +++ b/Il2CppInterop.Generator/MetadataAccess/Il2CppAssemblyResolver.cs @@ -0,0 +1,18 @@ +using AsmResolver.DotNet; +using AsmResolver.IO; + +namespace Il2CppInterop.Generator.MetadataAccess; + +internal sealed class Il2CppAssemblyResolver : AssemblyResolverBase +{ + public Il2CppAssemblyResolver() : base(new ByteArrayFileService()) + { + } + + protected override string? ProbeRuntimeDirectories(AssemblyDescriptor assembly) => null; + + public void AddToCache(AssemblyDefinition assembly) + { + AddToCache(assembly, assembly); + } +} diff --git a/Il2CppInterop.Generator/MetadataAccess/NullMetadataAccess.cs b/Il2CppInterop.Generator/MetadataAccess/NullMetadataAccess.cs index 2528f885..dc1e4682 100644 --- a/Il2CppInterop.Generator/MetadataAccess/NullMetadataAccess.cs +++ b/Il2CppInterop.Generator/MetadataAccess/NullMetadataAccess.cs @@ -1,6 +1,5 @@ -using System.Collections.Generic; -using Mono.Cecil; -using Mono.Collections.Generic; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; namespace Il2CppInterop.Generator.MetadataAccess; @@ -12,7 +11,7 @@ public void Dispose() { } - public IList Assemblies => ReadOnlyCollection.Empty; + public IList Assemblies => Array.Empty(); public AssemblyDefinition? GetAssemblyBySimpleName(string name) { @@ -24,7 +23,7 @@ public void Dispose() return null; } - public IList? GetKnownInstantiationsFor(TypeReference genericDeclaration) + public IList? GetKnownInstantiationsFor(TypeReference genericDeclaration) { return null; } @@ -34,7 +33,7 @@ public void Dispose() return null; } - public MethodReference? GetMethodRefStoredAt(long offsetInMemory) + public MemberReference? GetMethodRefStoredAt(long offsetInMemory) { return null; } diff --git a/Il2CppInterop.Generator/Passes/Pass05CreateRenameGroups.cs b/Il2CppInterop.Generator/Passes/Pass05CreateRenameGroups.cs index 70d12a10..ce84eb82 100644 --- a/Il2CppInterop.Generator/Passes/Pass05CreateRenameGroups.cs +++ b/Il2CppInterop.Generator/Passes/Pass05CreateRenameGroups.cs @@ -1,11 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; using System.Text; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -17,7 +16,7 @@ public static class Pass05CreateRenameGroups public static void DoPass(RewriteGlobalContext context) { foreach (var assemblyContext in context.Assemblies) - foreach (var originalType in assemblyContext.OriginalAssembly.MainModule.Types) + foreach (var originalType in assemblyContext.OriginalAssembly.ManifestModule!.TopLevelTypes) ProcessType(context, originalType, false); var typesToRemove = context.RenameGroups.Where(it => it.Value.Count > 1).ToList(); @@ -32,7 +31,7 @@ public static void DoPass(RewriteGlobalContext context) context.PreviousRenamedTypes[contextRenamedType.Key] = contextRenamedType.Value; foreach (var assemblyContext in context.Assemblies) - foreach (var originalType in assemblyContext.OriginalAssembly.MainModule.Types) + foreach (var originalType in assemblyContext.OriginalAssembly.ManifestModule!.TopLevelTypes) ProcessType(context, originalType, true); } @@ -49,7 +48,7 @@ private static void ProcessType(RewriteGlobalContext context, TypeDefinition ori context.RenameGroups .GetOrCreate( - ((object)originalType.DeclaringType ?? originalType.Namespace, unobfuscatedName, + ((object?)originalType.DeclaringType ?? originalType.Namespace, unobfuscatedName, originalType.GenericParameters.Count), _ => new List()).Add(originalType); context.RenamedTypes[originalType] = unobfuscatedName; } @@ -64,12 +63,12 @@ private static void ProcessType(RewriteGlobalContext context, TypeDefinition ori var firstUnobfuscatedType = typeDefinition.BaseType; while (firstUnobfuscatedType != null && firstUnobfuscatedType.Name.IsObfuscated(context.Options)) { - firstUnobfuscatedType = firstUnobfuscatedType.Resolve().BaseType?.Resolve(); + firstUnobfuscatedType = firstUnobfuscatedType.Resolve()?.BaseType?.Resolve(); inheritanceDepth++; } - var unobfuscatedInterfacesList = typeDefinition.Interfaces.Select(it => it.InterfaceType) - .Where(it => !it.Name.IsObfuscated(context.Options)); + var unobfuscatedInterfacesList = typeDefinition.Interfaces.Select(it => it.Interface!) + .Where(it => !it!.Name.IsObfuscated(context.Options)); var accessName = ClassAccessNames[(int)(typeDefinition.Attributes & TypeAttributes.VisibilityMask)]; var classifier = typeDefinition.IsInterface ? "Interface" : typeDefinition.IsValueType ? "Struct" : "Class"; @@ -79,7 +78,7 @@ private static void ProcessType(RewriteGlobalContext context, TypeDefinition ori var specialNameString = typeDefinition.IsSpecialName ? "SpecialName" : ""; var nameBuilder = new StringBuilder(); - nameBuilder.Append(firstUnobfuscatedType?.GenericNameToStrings(context)?.ConcatAll() ?? classifier); + nameBuilder.Append(firstUnobfuscatedType?.ToTypeSignature().GenericNameToStrings(context)?.ConcatAll() ?? classifier); if (inheritanceDepth > 0) nameBuilder.Append(inheritanceDepth); nameBuilder.Append(compilerGenertaedString); @@ -88,15 +87,15 @@ private static void ProcessType(RewriteGlobalContext context, TypeDefinition ori nameBuilder.Append(sealedString); nameBuilder.Append(specialNameString); foreach (var interfaceRef in unobfuscatedInterfacesList) - nameBuilder.Append(interfaceRef.GenericNameToStrings(context).ConcatAll()); + nameBuilder.Append(interfaceRef.ToTypeSignature().GenericNameToStrings(context).ConcatAll()); var uniqContext = new UniquificationContext(options); foreach (var fieldDef in typeDefinition.Fields) { if (!typeDefinition.IsEnum) - uniqContext.Push(fieldDef.FieldType.GenericNameToStrings(context)); + uniqContext.Push(fieldDef.Signature!.FieldType.GenericNameToStrings(context)); - uniqContext.Push(fieldDef.Name); + uniqContext.Push(fieldDef.Name!); if (uniqContext.CheckFull()) break; } @@ -106,8 +105,8 @@ private static void ProcessType(RewriteGlobalContext context, TypeDefinition ori foreach (var propertyDef in typeDefinition.Properties) { - uniqContext.Push(propertyDef.PropertyType.GenericNameToStrings(context)); - uniqContext.Push(propertyDef.Name); + uniqContext.Push(propertyDef.Signature!.ReturnType.GenericNameToStrings(context)); + uniqContext.Push(propertyDef.Name!); if (uniqContext.CheckFull()) break; } @@ -117,7 +116,7 @@ private static void ProcessType(RewriteGlobalContext context, TypeDefinition ori var invokeMethod = typeDefinition.Methods.SingleOrDefault(it => it.Name == "Invoke"); if (invokeMethod != null) { - uniqContext.Push(invokeMethod.ReturnType.GenericNameToStrings(context)); + uniqContext.Push(invokeMethod.Signature!.ReturnType.GenericNameToStrings(context)); foreach (var parameterDef in invokeMethod.Parameters) { @@ -131,8 +130,8 @@ private static void ProcessType(RewriteGlobalContext context, TypeDefinition ori allowExtraHeuristics) // method order on non-interface types appears to be unstable foreach (var methodDefinition in typeDefinition.Methods) { - uniqContext.Push(methodDefinition.Name); - uniqContext.Push(methodDefinition.ReturnType.GenericNameToStrings(context)); + uniqContext.Push(methodDefinition.Name!); + uniqContext.Push(methodDefinition.Signature!.ReturnType.GenericNameToStrings(context)); foreach (var parameter in methodDefinition.Parameters) { @@ -155,24 +154,27 @@ private static string ConcatAll(this List strings) return string.Concat(strings); } - private static string NameOrRename(this TypeReference typeRef, RewriteGlobalContext context) + private static string NameOrRename(this TypeSignature typeRef, RewriteGlobalContext context) { var resolved = typeRef.Resolve(); if (resolved != null && context.PreviousRenamedTypes.TryGetValue(resolved, out var rename)) return (rename.StableHash() % (ulong)Math.Pow(10, context.Options.TypeDeobfuscationCharsPerUniquifier)) .ToString(); - return typeRef.Name; + return typeRef.Name!; } - private static List GenericNameToStrings(this TypeReference typeRef, RewriteGlobalContext context) + private static List GenericNameToStrings(this TypeSignature typeRef, RewriteGlobalContext context) { - if (typeRef is ArrayType arrayType) - return arrayType.ElementType.GenericNameToStrings(context); + if (typeRef is SzArrayTypeSignature szArrayType) + return szArrayType.BaseType.GenericNameToStrings(context); - if (typeRef is GenericInstanceType genericInstance) + if (typeRef is ArrayTypeSignature arrayType) + return arrayType.BaseType.GenericNameToStrings(context); + + if (typeRef is GenericInstanceTypeSignature genericInstance) { - var baseTypeName = genericInstance.GetElementType().NameOrRename(context); + var baseTypeName = genericInstance.GenericType.ToTypeSignature().NameOrRename(context); var indexOfBacktick = baseTypeName.IndexOf('`'); if (indexOfBacktick >= 0) baseTypeName = baseTypeName.Substring(0, indexOfBacktick); @@ -180,8 +182,8 @@ private static List GenericNameToStrings(this TypeReference typeRef, Rew var entries = new List(); entries.Add(baseTypeName); - entries.Add(genericInstance.GenericArguments.Count.ToString()); - foreach (var genericArgument in genericInstance.GenericArguments) + entries.Add(genericInstance.TypeArguments.Count.ToString()); + foreach (var genericArgument in genericInstance.TypeArguments) entries.AddRange(genericArgument.GenericNameToStrings(context)); return entries; } diff --git a/Il2CppInterop.Generator/Passes/Pass10CreateTypedefs.cs b/Il2CppInterop.Generator/Passes/Pass10CreateTypedefs.cs index a2124525..63cc04b1 100644 --- a/Il2CppInterop.Generator/Passes/Pass10CreateTypedefs.cs +++ b/Il2CppInterop.Generator/Passes/Pass10CreateTypedefs.cs @@ -1,9 +1,9 @@ -using System.Linq; +using AsmResolver.DotNet; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Common; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; using Microsoft.Extensions.Logging; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -12,11 +12,11 @@ public static class Pass10CreateTypedefs public static void DoPass(RewriteGlobalContext context) { foreach (var assemblyContext in context.Assemblies) - foreach (var type in assemblyContext.OriginalAssembly.MainModule.Types) + foreach (var type in assemblyContext.OriginalAssembly.ManifestModule!.TopLevelTypes) if (!IsCpp2ILInjectedType(type) && type.Name != "") ProcessType(type, assemblyContext, null); - static bool IsCpp2ILInjectedType(TypeDefinition type) => type.Namespace?.StartsWith("Cpp2ILInjected", StringComparison.Ordinal) ?? false; + static bool IsCpp2ILInjectedType(TypeDefinition type) => type.Namespace?.Value.StartsWith("Cpp2ILInjected", StringComparison.Ordinal) ?? false; } private static void ProcessType(TypeDefinition type, AssemblyRewriteContext assemblyContext, @@ -34,12 +34,11 @@ private static void ProcessType(TypeDefinition type, AssemblyRewriteContext asse if (parentType == null) { - assemblyContext.NewAssembly.MainModule.Types.Add(newType); + assemblyContext.NewAssembly.ManifestModule!.TopLevelTypes.Add(newType); } else { parentType.NestedTypes.Add(newType); - newType.DeclaringType = parentType; } foreach (var typeNestedType in type.NestedTypes) @@ -47,9 +46,9 @@ private static void ProcessType(TypeDefinition type, AssemblyRewriteContext asse assemblyContext.RegisterTypeRewrite(new TypeRewriteContext(assemblyContext, type, newType)); - static string GetNamespace(TypeDefinition type, AssemblyRewriteContext assemblyContext) + static string? GetNamespace(TypeDefinition type, AssemblyRewriteContext assemblyContext) { - if (type.Name is "" || type.DeclaringType is not null) + if (type.Name?.Value is "" || type.DeclaringType is not null) return type.Namespace; else return type.Namespace.UnSystemify(assemblyContext.GlobalContext.Options); @@ -60,7 +59,7 @@ internal static (string? Namespace, string Name) GetConvertedTypeName( RewriteGlobalContext assemblyContextGlobalContext, TypeDefinition type, TypeDefinition? enclosingType) { if (assemblyContextGlobalContext.Options.PassthroughNames) - return (null, type.Name); + return (null, type.Name!); if (type.Name.IsObfuscated(assemblyContextGlobalContext.Options)) { @@ -68,7 +67,7 @@ internal static (string? Namespace, string Name) GetConvertedTypeName( var genericParametersCount = type.GenericParameters.Count; var renameGroup = assemblyContextGlobalContext.RenameGroups[ - ((object)type.DeclaringType ?? type.Namespace, newNameBase, genericParametersCount)]; + ((object?)type.DeclaringType ?? type.Namespace, newNameBase, genericParametersCount)]; var genericSuffix = genericParametersCount == 0 ? "" : "`" + genericParametersCount; var convertedTypeName = newNameBase + (renameGroup.Count == 1 ? "Unique" : renameGroup.IndexOf(type).ToString()) + @@ -81,7 +80,7 @@ internal static (string? Namespace, string Name) GetConvertedTypeName( if (assemblyContextGlobalContext.Options.RenameMap.TryGetValue(fullName + "." + convertedTypeName, out var newName)) { - if (type.Module.Types.Any(t => t.FullName == newName)) + if (type.Module!.TopLevelTypes.Any(t => t.FullName == newName)) { Logger.Instance.LogWarning("[Rename map issue] {NewName} already exists in {ModuleName} (mapped from {MappedNamespace}.{MappedType})", newName, type.Module.Name, fullName, convertedTypeName); @@ -105,7 +104,7 @@ internal static (string? Namespace, string Name) GetConvertedTypeName( if (type.Name.IsInvalidInSource()) return (null, type.Name.FilterInvalidInSourceChars()); - return (null, type.Name); + return (null, type.Name!); } private static TypeAttributes AdjustAttributes(TypeAttributes typeAttributes) diff --git a/Il2CppInterop.Generator/Passes/Pass11ComputeTypeSpecifics.cs b/Il2CppInterop.Generator/Passes/Pass11ComputeTypeSpecifics.cs index 43730192..b50cd2e8 100644 --- a/Il2CppInterop.Generator/Passes/Pass11ComputeTypeSpecifics.cs +++ b/Il2CppInterop.Generator/Passes/Pass11ComputeTypeSpecifics.cs @@ -1,3 +1,4 @@ +using AsmResolver.DotNet.Signatures; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; @@ -28,16 +29,17 @@ private static void ComputeSpecifics(TypeRewriteContext typeContext) if (originalField.IsStatic) continue; - var fieldType = originalField.FieldType; - if (fieldType.IsPrimitive || fieldType.IsPointer) continue; - if (fieldType.FullName == "System.String" || fieldType.FullName == "System.Object" || fieldType.IsArray || - fieldType.IsByReference || fieldType.IsGenericParameter || fieldType.IsGenericInstance) + var fieldType = originalField.Signature!.FieldType; + if (fieldType.IsPrimitive() || fieldType is PointerTypeSignature) + continue; + if (fieldType.FullName == "System.String" || fieldType.FullName == "System.Object" + || fieldType is ArrayBaseTypeSignature or ByReferenceTypeSignature or GenericParameterSignature or GenericInstanceTypeSignature) { typeContext.ComputedTypeSpecifics = TypeRewriteContext.TypeSpecifics.NonBlittableStruct; return; } - var fieldTypeContext = typeContext.AssemblyContext.GlobalContext.GetNewTypeForOriginal(fieldType.Resolve()); + var fieldTypeContext = typeContext.AssemblyContext.GlobalContext.GetNewTypeForOriginal(fieldType.Resolve()!); ComputeSpecifics(fieldTypeContext); if (fieldTypeContext.ComputedTypeSpecifics != TypeRewriteContext.TypeSpecifics.BlittableStruct) { diff --git a/Il2CppInterop.Generator/Passes/Pass12FillTypedefs.cs b/Il2CppInterop.Generator/Passes/Pass12FillTypedefs.cs index 57cd9f7a..7c5b09de 100644 --- a/Il2CppInterop.Generator/Passes/Pass12FillTypedefs.cs +++ b/Il2CppInterop.Generator/Passes/Pass12FillTypedefs.cs @@ -1,7 +1,7 @@ +using AsmResolver.DotNet; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -14,15 +14,15 @@ public static void DoPass(RewriteGlobalContext context) { foreach (var originalParameter in typeContext.OriginalType.GenericParameters) { - var newParameter = new GenericParameter(originalParameter.Name, typeContext.NewType); + var newParameter = new GenericParameter(originalParameter.Name); typeContext.NewType.GenericParameters.Add(newParameter); newParameter.Attributes = originalParameter.Attributes.StripValueTypeConstraint(); } if (typeContext.OriginalType.IsEnum) - typeContext.NewType.BaseType = assemblyContext.Imports.Module.Enum(); + typeContext.NewType.BaseType = assemblyContext.Imports.Module.Enum().ToTypeDefOrRef(); else if (typeContext.ComputedTypeSpecifics == TypeRewriteContext.TypeSpecifics.BlittableStruct) - typeContext.NewType.BaseType = assemblyContext.Imports.Module.ValueType(); + typeContext.NewType.BaseType = assemblyContext.Imports.Module.ValueType().ToTypeDefOrRef(); } // Second pass is explicitly done after first to account for rewriting of generic base types - value-typeness is important there @@ -30,6 +30,6 @@ public static void DoPass(RewriteGlobalContext context) foreach (var typeContext in assemblyContext.Types) if (!typeContext.OriginalType.IsEnum && typeContext.ComputedTypeSpecifics != TypeRewriteContext.TypeSpecifics.BlittableStruct) - typeContext.NewType.BaseType = assemblyContext.RewriteTypeRef(typeContext.OriginalType.BaseType); + typeContext.NewType.BaseType = assemblyContext.RewriteTypeRef(typeContext.OriginalType.BaseType!); } } diff --git a/Il2CppInterop.Generator/Passes/Pass13FillGenericConstraints.cs b/Il2CppInterop.Generator/Passes/Pass13FillGenericConstraints.cs index 0515ed18..806c27a5 100644 --- a/Il2CppInterop.Generator/Passes/Pass13FillGenericConstraints.cs +++ b/Il2CppInterop.Generator/Passes/Pass13FillGenericConstraints.cs @@ -1,5 +1,5 @@ +using AsmResolver.DotNet; using Il2CppInterop.Generator.Contexts; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -8,20 +8,25 @@ public static class Pass13FillGenericConstraints public static void DoPass(RewriteGlobalContext context) { foreach (var assemblyContext in context.Assemblies) + { foreach (var typeContext in assemblyContext.Types) + { for (var i = 0; i < typeContext.OriginalType.GenericParameters.Count; i++) { var originalParameter = typeContext.OriginalType.GenericParameters[i]; var newParameter = typeContext.NewType.GenericParameters[i]; foreach (var originalConstraint in originalParameter.Constraints) { - if (originalConstraint.ConstraintType.FullName == "System.ValueType" || - originalConstraint.ConstraintType.Resolve()?.IsInterface == true) continue; + if (originalConstraint.Constraint?.FullName is "System.ValueType" || + originalConstraint.Constraint?.Resolve()?.IsInterface == true) + continue; newParameter.Constraints.Add( new GenericParameterConstraint( - assemblyContext.RewriteTypeRef(originalConstraint.ConstraintType))); + assemblyContext.RewriteTypeRef(originalConstraint.Constraint!))); } } + } + } } } diff --git a/Il2CppInterop.Generator/Passes/Pass16ScanMethodRefs.cs b/Il2CppInterop.Generator/Passes/Pass16ScanMethodRefs.cs index 96854b7b..9dea948c 100644 --- a/Il2CppInterop.Generator/Passes/Pass16ScanMethodRefs.cs +++ b/Il2CppInterop.Generator/Passes/Pass16ScanMethodRefs.cs @@ -1,15 +1,10 @@ -using System; using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; using System.IO.MemoryMappedFiles; -using System.Linq; using System.Text; using Il2CppInterop.Common.XrefScans; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; -using Il2CppInterop.Generator.XrefScans; namespace Il2CppInterop.Generator.Passes; diff --git a/Il2CppInterop.Generator/Passes/Pass18FinalizeMethodContexts.cs b/Il2CppInterop.Generator/Passes/Pass18FinalizeMethodContexts.cs index 1c7fe60c..319ba1d1 100644 --- a/Il2CppInterop.Generator/Passes/Pass18FinalizeMethodContexts.cs +++ b/Il2CppInterop.Generator/Passes/Pass18FinalizeMethodContexts.cs @@ -1,8 +1,9 @@ +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; using Il2CppInterop.Common; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Utils; using Microsoft.Extensions.Logging; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -18,7 +19,9 @@ public static void DoPass(RewriteGlobalContext context) var pdmTopNZCaller = 0; foreach (var assemblyContext in context.Assemblies) + { foreach (var typeContext in assemblyContext.Types) + { foreach (var methodContext in typeContext.Methods) { methodContext.CtorPhase2(); @@ -30,14 +33,10 @@ public static void DoPass(RewriteGlobalContext context) callerCount = callers.Count; methodContext.NewMethod.CustomAttributes.Add( - new CustomAttribute(assemblyContext.Imports.CallerCountAttributector.Value) - { - ConstructorArguments = - {new CustomAttributeArgument(assemblyContext.Imports.Module.Int(), callerCount)} - }); + new CustomAttribute((ICustomAttributeType)assemblyContext.Imports.CallerCountAttributector.Value, new CustomAttributeSignature(new CustomAttributeArgument(assemblyContext.Imports.Module.Int(), callerCount)))); if (!Pass15GenerateMemberContexts.HasObfuscatedMethods) continue; - if (!methodContext.UnmangledName.Contains("_PDM_")) continue; + if (methodContext.UnmangledName?.Contains("_PDM_") is not true) continue; TotalPotentiallyDeadMethods++; var hasZeroCallers = callerCount == 0; @@ -57,6 +56,8 @@ public static void DoPass(RewriteGlobalContext context) } } } + } + } if (Pass15GenerateMemberContexts.HasObfuscatedMethods) { diff --git a/Il2CppInterop.Generator/Passes/Pass19CopyMethodParameters.cs b/Il2CppInterop.Generator/Passes/Pass19CopyMethodParameters.cs index 200cded8..8f7542b0 100644 --- a/Il2CppInterop.Generator/Passes/Pass19CopyMethodParameters.cs +++ b/Il2CppInterop.Generator/Passes/Pass19CopyMethodParameters.cs @@ -1,6 +1,6 @@ +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -9,7 +9,9 @@ public static class Pass19CopyMethodParameters public static void DoPass(RewriteGlobalContext context) { foreach (var assemblyContext in context.Assemblies) + { foreach (var typeContext in assemblyContext.Types) + { foreach (var methodRewriteContext in typeContext.Methods) { var originalMethod = methodRewriteContext.OriginalMethod; @@ -21,24 +23,27 @@ public static void DoPass(RewriteGlobalContext context) ? $"param_{originalMethodParameter.Sequence}" : originalMethodParameter.Name; - var newParameter = new ParameterDefinition(newName, - originalMethodParameter.Attributes & ~ParameterAttributes.HasFieldMarshal, - assemblyContext.RewriteTypeRef(originalMethodParameter.ParameterType)); + var newParameter = newMethod.AddParameter( + assemblyContext.RewriteTypeRef(originalMethodParameter.ParameterType), + newName, + originalMethodParameter.Definition!.Attributes & ~ParameterAttributes.HasFieldMarshal); if (originalMethodParameter.IsParamsArray()) { - newParameter.Constant = null; - newParameter.IsOptional = true; + newParameter.Definition!.Constant = null; + newParameter.Definition.IsOptional = true; } else - newParameter.Constant = originalMethodParameter.Constant; - - newMethod.Parameters.Add(newParameter); + { + newParameter.Definition!.Constant = originalMethodParameter.Definition.Constant; + } } var paramsMethod = context.CreateParamsMethod(originalMethod, newMethod, assemblyContext.Imports, type => assemblyContext.RewriteTypeRef(type)); if (paramsMethod != null) typeContext.NewType.Methods.Add(paramsMethod); } + } + } } } diff --git a/Il2CppInterop.Generator/Passes/Pass20GenerateStaticConstructors.cs b/Il2CppInterop.Generator/Passes/Pass20GenerateStaticConstructors.cs index 1a81795b..47c93e7f 100644 --- a/Il2CppInterop.Generator/Passes/Pass20GenerateStaticConstructors.cs +++ b/Il2CppInterop.Generator/Passes/Pass20GenerateStaticConstructors.cs @@ -1,11 +1,10 @@ -using System; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; using Il2CppInterop.Common; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; using Microsoft.Extensions.Logging; -using Mono.Cecil; -using Mono.Cecil.Cil; namespace Il2CppInterop.Generator.Passes; @@ -28,171 +27,154 @@ private static void GenerateStaticProxy(AssemblyRewriteContext assemblyContext, var newType = typeContext.NewType; if (newType.IsEnum) return; - var staticCtorMethod = new MethodDefinition(".cctor", - MethodAttributes.Static | MethodAttributes.Private | MethodAttributes.SpecialName | - MethodAttributes.HideBySig | MethodAttributes.RTSpecialName, assemblyContext.Imports.Module.Void()); - newType.Methods.Add(staticCtorMethod); + var staticCtorMethod = newType.GetOrCreateStaticConstructor(); - var ctorBuilder = staticCtorMethod.Body.GetILProcessor(); + var ctorBuilder = staticCtorMethod.CilMethodBody!.Instructions; + ctorBuilder.Clear(); if (newType.IsNested) { - ctorBuilder.Emit(OpCodes.Ldsfld, - assemblyContext.GlobalContext.GetNewTypeForOriginal(oldType.DeclaringType).ClassPointerFieldRef); - ctorBuilder.Emit(OpCodes.Ldstr, oldType.Name); - ctorBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_GetIl2CppNestedType.Value); + ctorBuilder.Add(OpCodes.Ldsfld, + assemblyContext.GlobalContext.GetNewTypeForOriginal(oldType.DeclaringType!).ClassPointerFieldRef); + ctorBuilder.Add(OpCodes.Ldstr, oldType.Name ?? ""); + ctorBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_GetIl2CppNestedType.Value); } else { - ctorBuilder.Emit(OpCodes.Ldstr, oldType.Module.Name); - ctorBuilder.Emit(OpCodes.Ldstr, oldType.Namespace); - ctorBuilder.Emit(OpCodes.Ldstr, oldType.Name); - ctorBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_GetIl2CppClass.Value); + ctorBuilder.Add(OpCodes.Ldstr, oldType.Module?.Name ?? ""); + ctorBuilder.Add(OpCodes.Ldstr, oldType.Namespace ?? ""); + ctorBuilder.Add(OpCodes.Ldstr, oldType.Name ?? ""); + ctorBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_GetIl2CppClass.Value); } - if (oldType.HasGenericParameters) + if (oldType.HasGenericParameters()) { var il2CppTypeTypeRewriteContext = assemblyContext.GlobalContext.GetAssemblyByName("mscorlib") .GetTypeByName("System.Type"); - var il2CppSystemTypeRef = newType.Module.ImportReference(il2CppTypeTypeRewriteContext.NewType); + var il2CppSystemTypeRef = newType.Module!.DefaultImporter.ImportType(il2CppTypeTypeRewriteContext.NewType); var il2CppTypeHandleTypeRewriteContext = assemblyContext.GlobalContext.GetAssemblyByName("mscorlib") .GetTypeByName("System.RuntimeTypeHandle"); - var il2CppSystemTypeHandleRef = newType.Module.ImportReference(il2CppTypeHandleTypeRewriteContext.NewType); + var il2CppSystemTypeHandleRef = newType.Module.DefaultImporter.ImportType(il2CppTypeHandleTypeRewriteContext.NewType); - ctorBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_class_get_type.Value); - ctorBuilder.Emit(OpCodes.Call, - new MethodReference("internal_from_handle", il2CppSystemTypeRef, il2CppSystemTypeRef) - { Parameters = { new ParameterDefinition(assemblyContext.Imports.Module.IntPtr()) } }); + ctorBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_class_get_type.Value); + ctorBuilder.Add(OpCodes.Call, + new MemberReference(il2CppSystemTypeRef, "internal_from_handle", MethodSignature.CreateStatic(il2CppSystemTypeRef.ToTypeSignature(), assemblyContext.Imports.Module.IntPtr()))); - ctorBuilder.EmitLdcI4(oldType.GenericParameters.Count); + ctorBuilder.Add(OpCodes.Ldc_I4, oldType.GenericParameters.Count); - ctorBuilder.Emit(OpCodes.Newarr, il2CppSystemTypeRef); + ctorBuilder.Add(OpCodes.Newarr, il2CppSystemTypeRef); for (var i = 0; i < oldType.GenericParameters.Count; i++) { - ctorBuilder.Emit(OpCodes.Dup); - ctorBuilder.EmitLdcI4(i); + ctorBuilder.Add(OpCodes.Dup); + ctorBuilder.Add(OpCodes.Ldc_I4, i); var param = oldType.GenericParameters[i]; - var storeRef = new GenericInstanceType(assemblyContext.Imports.Il2CppClassPointerStore) - { GenericArguments = { param } }; - var fieldRef = new FieldReference("NativeClassPtr", assemblyContext.Imports.Module.IntPtr(), storeRef); - ctorBuilder.Emit(OpCodes.Ldsfld, fieldRef); + var storeRef = assemblyContext.Imports.Il2CppClassPointerStore + .MakeGenericInstanceType(new GenericParameterSignature(GenericParameterType.Type, param.Number)); + var fieldRef = new MemberReference(storeRef.ToTypeDefOrRef(), "NativeClassPtr", new FieldSignature(assemblyContext.Imports.Module.IntPtr())); + ctorBuilder.Add(OpCodes.Ldsfld, fieldRef); - ctorBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_class_get_type.Value); + ctorBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_class_get_type.Value); - ctorBuilder.Emit(OpCodes.Call, - new MethodReference("internal_from_handle", il2CppSystemTypeRef, il2CppSystemTypeRef) - { Parameters = { new ParameterDefinition(assemblyContext.Imports.Module.IntPtr()) } }); - ctorBuilder.Emit(OpCodes.Stelem_Ref); + ctorBuilder.Add(OpCodes.Call, + new MemberReference(il2CppSystemTypeRef, "internal_from_handle", MethodSignature.CreateStatic(il2CppSystemTypeRef.ToTypeSignature(), assemblyContext.Imports.Module.IntPtr()))); + ctorBuilder.Add(OpCodes.Stelem_Ref); } - var il2CppTypeArray = new GenericInstanceType(assemblyContext.Imports.Il2CppReferenceArray) - { GenericArguments = { il2CppSystemTypeRef } }; - ctorBuilder.Emit(OpCodes.Newobj, - new MethodReference(".ctor", assemblyContext.Imports.Module.Void(), il2CppTypeArray) - { - HasThis = true, - Parameters = - { - new ParameterDefinition( - new ArrayType(assemblyContext.Imports.Il2CppReferenceArray.GenericParameters[0])) - } - }); - ctorBuilder.Emit(OpCodes.Call, - new MethodReference(nameof(Type.MakeGenericType), il2CppSystemTypeRef, il2CppSystemTypeRef) - { HasThis = true, Parameters = { new ParameterDefinition(il2CppTypeArray) } }); - - ctorBuilder.Emit(OpCodes.Call, - new MethodReference(typeof(Type).GetProperty(nameof(Type.TypeHandle))!.GetMethod!.Name, - il2CppSystemTypeHandleRef, il2CppSystemTypeRef) - { HasThis = true }); - ctorBuilder.Emit(OpCodes.Ldfld, - new FieldReference("value", assemblyContext.Imports.Module.IntPtr(), il2CppSystemTypeHandleRef)); - - ctorBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_class_from_type.Value); + var il2CppTypeArray = assemblyContext.Imports.Il2CppReferenceArray.MakeGenericInstanceType(il2CppSystemTypeRef.ToTypeSignature()); + ctorBuilder.Add(OpCodes.Newobj, + new MemberReference(il2CppTypeArray.ToTypeDefOrRef(), ".ctor", MethodSignature.CreateInstance(assemblyContext.Imports.Module.Void(), new GenericParameterSignature(GenericParameterType.Type, 0).MakeSzArrayType()))); + ctorBuilder.Add(OpCodes.Call, + ReferenceCreator.CreateInstanceMethodReference(nameof(Type.MakeGenericType), il2CppSystemTypeRef.ToTypeSignature(), il2CppSystemTypeRef, il2CppTypeArray)); + + ctorBuilder.Add(OpCodes.Call, + ReferenceCreator.CreateInstanceMethodReference(typeof(Type).GetProperty(nameof(Type.TypeHandle))!.GetMethod!.Name, + il2CppSystemTypeHandleRef.ToTypeSignature(), il2CppSystemTypeRef)); + ctorBuilder.Add(OpCodes.Ldfld, + ReferenceCreator.CreateFieldReference("value", assemblyContext.Imports.Module.IntPtr(), il2CppSystemTypeHandleRef)); + + ctorBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_class_from_type.Value); } - ctorBuilder.Emit(OpCodes.Stsfld, typeContext.ClassPointerFieldRef); + ctorBuilder.Add(OpCodes.Stsfld, typeContext.ClassPointerFieldRef); if (oldType.IsBeforeFieldInit) { - ctorBuilder.Emit(OpCodes.Ldsfld, typeContext.ClassPointerFieldRef); - ctorBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_runtime_class_init.Value); + ctorBuilder.Add(OpCodes.Ldsfld, typeContext.ClassPointerFieldRef); + ctorBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_runtime_class_init.Value); } if (oldType.IsEnum) { - ctorBuilder.Emit(OpCodes.Ret); + ctorBuilder.Add(OpCodes.Ret); return; } foreach (var field in typeContext.Fields) { - ctorBuilder.Emit(OpCodes.Ldsfld, typeContext.ClassPointerFieldRef); - ctorBuilder.Emit(OpCodes.Ldstr, field.OriginalField.Name); - ctorBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_GetIl2CppField.Value); - ctorBuilder.Emit(OpCodes.Stsfld, field.PointerField); + ctorBuilder.Add(OpCodes.Ldsfld, typeContext.ClassPointerFieldRef); + ctorBuilder.Add(OpCodes.Ldstr, field.OriginalField.Name!); + ctorBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_GetIl2CppField.Value); + ctorBuilder.Add(OpCodes.Stsfld, field.PointerField); } foreach (var method in typeContext.Methods) { - ctorBuilder.Emit(OpCodes.Ldsfld, typeContext.ClassPointerFieldRef); + ctorBuilder.Add(OpCodes.Ldsfld, typeContext.ClassPointerFieldRef); var token = method.OriginalMethod.ExtractToken(); if (token == 0) { ourTokenlessMethods++; - ctorBuilder.Emit( + ctorBuilder.Add( method.OriginalMethod.GenericParameters.Count > 0 ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); - ctorBuilder.Emit(OpCodes.Ldstr, method.OriginalMethod.Name); + ctorBuilder.Add(OpCodes.Ldstr, method.OriginalMethod.Name!); ctorBuilder.EmitLoadTypeNameString(assemblyContext.Imports, method.OriginalMethod, - method.OriginalMethod.ReturnType, method.NewMethod.ReturnType); - ctorBuilder.Emit(OpCodes.Ldc_I4, method.OriginalMethod.Parameters.Count); - ctorBuilder.Emit(OpCodes.Newarr, assemblyContext.Imports.Module.String()); + method.OriginalMethod.Signature!.ReturnType, method.NewMethod.Signature!.ReturnType); + ctorBuilder.Add(OpCodes.Ldc_I4, method.OriginalMethod.Parameters.Count); + ctorBuilder.Add(OpCodes.Newarr, assemblyContext.Imports.Module.String().ToTypeDefOrRef()); for (var i = 0; i < method.OriginalMethod.Parameters.Count; i++) { - ctorBuilder.Emit(OpCodes.Dup); - ctorBuilder.EmitLdcI4(i); + ctorBuilder.Add(OpCodes.Dup); + ctorBuilder.Add(OpCodes.Ldc_I4, i); ctorBuilder.EmitLoadTypeNameString(assemblyContext.Imports, method.OriginalMethod, method.OriginalMethod.Parameters[i].ParameterType, method.NewMethod.Parameters[i].ParameterType); - ctorBuilder.Emit(OpCodes.Stelem_Ref); + ctorBuilder.Add(OpCodes.Stelem_Ref); } - ctorBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_GetIl2CppMethod.Value); + ctorBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_GetIl2CppMethod.Value); } else { - ctorBuilder.EmitLdcI4((int)token); - ctorBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_GetIl2CppMethodByToken.Value); + ctorBuilder.Add(OpCodes.Ldc_I4, (int)token); + ctorBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_GetIl2CppMethodByToken.Value); } - ctorBuilder.Emit(OpCodes.Stsfld, method.NonGenericMethodInfoPointerField); + ctorBuilder.Add(OpCodes.Stsfld, method.NonGenericMethodInfoPointerField); } - ctorBuilder.Emit(OpCodes.Ret); + ctorBuilder.Add(OpCodes.Ret); } private static void EmitLoadTypeNameString(this ILProcessor ctorBuilder, RuntimeAssemblyReferences imports, - MethodDefinition originalMethod, TypeReference originalTypeReference, TypeReference newTypeReference) + MethodDefinition originalMethod, TypeSignature originalTypeReference, TypeSignature newTypeReference) { - if (originalMethod.HasGenericParameters || originalTypeReference.FullName == "System.Void") + if (originalMethod.HasGenericParameters() || originalTypeReference.FullName == "System.Void") { - ctorBuilder.Emit(OpCodes.Ldstr, originalTypeReference.FullName); + ctorBuilder.Add(OpCodes.Ldstr, originalTypeReference.FullName); } else { - ctorBuilder.Emit(newTypeReference.IsByReference ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); - ctorBuilder.Emit(OpCodes.Call, - imports.Module.ImportReference(new GenericInstanceMethod(imports.IL2CPP_RenderTypeName.Value) - { - GenericArguments = - {newTypeReference.IsByReference ? newTypeReference.GetElementType() : newTypeReference} - })); + ctorBuilder.Add(newTypeReference is ByReferenceTypeSignature ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); + ctorBuilder.Add(OpCodes.Call, + imports.Module.DefaultImporter.ImportMethod( + imports.IL2CPP_RenderTypeName.Value + .MakeGenericInstanceMethod(newTypeReference is ByReferenceTypeSignature ? newTypeReference.GetElementType() : newTypeReference))); } } } diff --git a/Il2CppInterop.Generator/Passes/Pass21GenerateValueTypeFields.cs b/Il2CppInterop.Generator/Passes/Pass21GenerateValueTypeFields.cs index c7e0d6c5..2ad087df 100644 --- a/Il2CppInterop.Generator/Passes/Pass21GenerateValueTypeFields.cs +++ b/Il2CppInterop.Generator/Passes/Pass21GenerateValueTypeFields.cs @@ -1,9 +1,9 @@ -using System; -using System.Linq; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -16,7 +16,7 @@ public static void DoPass(RewriteGlobalContext context) var il2CppTypeTypeRewriteContext = assemblyContext.GlobalContext.GetAssemblyByName("mscorlib") .GetTypeByName("System.Object"); var il2CppSystemTypeRef = - assemblyContext.NewAssembly.MainModule.ImportReference(il2CppTypeTypeRewriteContext.NewType); + assemblyContext.NewAssembly.ManifestModule!.DefaultImporter.ImportType(il2CppTypeTypeRewriteContext.NewType).ToTypeSignature(); foreach (var typeContext in assemblyContext.Types) { @@ -38,15 +38,15 @@ public static void DoPass(RewriteGlobalContext context) if (field.IsStatic) continue; var newField = new FieldDefinition(fieldContext.UnmangledName, field.Attributes.ForcePublic(), - !field.FieldType.IsValueType + !field.Signature!.FieldType.IsValueType ? assemblyContext.Imports.Module.IntPtr() - : assemblyContext.RewriteTypeRef(field.FieldType)); + : assemblyContext.RewriteTypeRef(field.Signature.FieldType)); - newField.Offset = field.ExtractFieldOffset(); + newField.FieldOffset = field.ExtractFieldOffset(); // Special case: bools in Il2Cpp are bytes - if (newField.FieldType.FullName == "System.Boolean") - newField.MarshalInfo = new MarshalInfo(NativeType.U1); + if (newField.Signature!.FieldType.FullName == "System.Boolean") + newField.MarshalDescriptor = new SimpleMarshalDescriptor(NativeType.U1); newType.Fields.Add(newField); } diff --git a/Il2CppInterop.Generator/Passes/Pass22GenerateEnums.cs b/Il2CppInterop.Generator/Passes/Pass22GenerateEnums.cs index fedf3c59..dab60bcc 100644 --- a/Il2CppInterop.Generator/Passes/Pass22GenerateEnums.cs +++ b/Il2CppInterop.Generator/Passes/Pass22GenerateEnums.cs @@ -1,8 +1,9 @@ -using System.Linq; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -20,22 +21,20 @@ public static void DoPass(RewriteGlobalContext context) if (type.Namespace.NameShouldBePrefixed(context.Options)) { - newType.CustomAttributes.Add(new CustomAttribute(assemblyContext.Imports.OriginalNameAttributector.Value) - { - ConstructorArguments = { - new CustomAttributeArgument(assemblyContext.Imports.Module.String(), type.Module.Name), + newType.CustomAttributes.Add(new CustomAttribute( + (ICustomAttributeType)assemblyContext.Imports.OriginalNameAttributector.Value, + new CustomAttributeSignature( + new CustomAttributeArgument(assemblyContext.Imports.Module.String(), type.Module!.Name), new CustomAttributeArgument(assemblyContext.Imports.Module.String(), type.Namespace), - new CustomAttributeArgument(assemblyContext.Imports.Module.String(), type.Name), - } - }); + new CustomAttributeArgument(assemblyContext.Imports.Module.String(), type.Name)))); } - if (type.CustomAttributes.Any(it => it.AttributeType.FullName == "System.FlagsAttribute")) + if (type.CustomAttributes.Any(it => it.Constructor?.DeclaringType?.FullName == "System.FlagsAttribute")) newType.CustomAttributes.Add(new CustomAttribute(assemblyContext.Imports.Module.FlagsAttributeCtor())); foreach (var fieldDefinition in type.Fields) { - var fieldName = fieldDefinition.Name; + var fieldName = fieldDefinition.Name!; if (!context.Options.PassthroughNames && fieldName.IsObfuscated(context.Options)) fieldName = GetUnmangledName(fieldDefinition); @@ -45,7 +44,7 @@ public static void DoPass(RewriteGlobalContext context) fieldName = newName; var newDef = new FieldDefinition(fieldName, fieldDefinition.Attributes | FieldAttributes.HasDefault, - assemblyContext.RewriteTypeRef(fieldDefinition.FieldType)); + assemblyContext.RewriteTypeRef(fieldDefinition.Signature!.FieldType)); newType.Fields.Add(newDef); newDef.Constant = fieldDefinition.Constant; diff --git a/Il2CppInterop.Generator/Passes/Pass23GeneratePointerConstructors.cs b/Il2CppInterop.Generator/Passes/Pass23GeneratePointerConstructors.cs index 568b1b64..d5d468c2 100644 --- a/Il2CppInterop.Generator/Passes/Pass23GeneratePointerConstructors.cs +++ b/Il2CppInterop.Generator/Passes/Pass23GeneratePointerConstructors.cs @@ -1,7 +1,9 @@ +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Generator.Contexts; +using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; -using Mono.Cecil.Cil; namespace Il2CppInterop.Generator.Passes; @@ -16,22 +18,22 @@ public static void DoPass(RewriteGlobalContext context) typeContext.OriginalType.IsEnum) continue; var newType = typeContext.NewType; + var nativeCtor = new MethodDefinition(".ctor", - MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | - MethodAttributes.HideBySig, assemblyContext.Imports.Module.Void()); + MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RuntimeSpecialName | + MethodAttributes.HideBySig, MethodSignature.CreateInstance(assemblyContext.Imports.Module.Void())); - nativeCtor.Parameters.Add(new ParameterDefinition("pointer", ParameterAttributes.None, - assemblyContext.Imports.Module.IntPtr())); + nativeCtor.AddParameter(assemblyContext.Imports.Module.IntPtr(), "pointer"); - var ctorBody = nativeCtor.Body.GetILProcessor(); + nativeCtor.CilMethodBody = new(nativeCtor); + var ctorBody = nativeCtor.CilMethodBody.Instructions; newType.Methods.Add(nativeCtor); - ctorBody.Emit(OpCodes.Ldarg_0); - ctorBody.Emit(OpCodes.Ldarg_1); - ctorBody.Emit(OpCodes.Call, - new MethodReference(".ctor", assemblyContext.Imports.Module.Void(), newType.BaseType) - { Parameters = { new ParameterDefinition(assemblyContext.Imports.Module.IntPtr()) }, HasThis = true }); - ctorBody.Emit(OpCodes.Ret); + ctorBody.Add(OpCodes.Ldarg_0); + ctorBody.Add(OpCodes.Ldarg_1); + ctorBody.Add(OpCodes.Call, + new MemberReference(newType.BaseType, ".ctor", MethodSignature.CreateInstance(assemblyContext.Imports.Module.Void(), assemblyContext.Imports.Module.IntPtr()))); + ctorBody.Add(OpCodes.Ret); } } } diff --git a/Il2CppInterop.Generator/Passes/Pass25GenerateNonBlittableValueTypeDefaultCtors.cs b/Il2CppInterop.Generator/Passes/Pass25GenerateNonBlittableValueTypeDefaultCtors.cs index 30b4aeff..f50cfcdf 100644 --- a/Il2CppInterop.Generator/Passes/Pass25GenerateNonBlittableValueTypeDefaultCtors.cs +++ b/Il2CppInterop.Generator/Passes/Pass25GenerateNonBlittableValueTypeDefaultCtors.cs @@ -1,7 +1,8 @@ +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; -using Mono.Cecil.Cil; namespace Il2CppInterop.Generator.Passes; @@ -16,24 +17,22 @@ public static void DoPass(RewriteGlobalContext context) TypeRewriteContext.TypeSpecifics.NonBlittableStruct) continue; var emptyCtor = new MethodDefinition(".ctor", - MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | - MethodAttributes.HideBySig, assemblyContext.Imports.Module.Void()); + MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RuntimeSpecialName | + MethodAttributes.HideBySig, MethodSignature.CreateInstance(assemblyContext.Imports.Module.Void())); typeContext.NewType.Methods.Add(emptyCtor); + emptyCtor.CilMethodBody = new(emptyCtor); + // NOTE(Kas): This used to stackalloc data of the valuetype's size and box it into an object // but it seems like it caused issues on certain games. If more issues arise - revert this. - var bodyBuilder = emptyCtor.Body.GetILProcessor(); - bodyBuilder.Emit(OpCodes.Ldarg_0); - bodyBuilder.Emit(OpCodes.Ldsfld, typeContext.ClassPointerFieldRef); - bodyBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_object_new.Value); - bodyBuilder.Emit(OpCodes.Call, - new MethodReference(".ctor", assemblyContext.Imports.Module.Void(), typeContext.NewType.BaseType) - { - HasThis = true, - Parameters = { new ParameterDefinition(assemblyContext.Imports.Module.IntPtr()) } - }); - bodyBuilder.Emit(OpCodes.Ret); + var bodyBuilder = emptyCtor.CilMethodBody.Instructions; + bodyBuilder.Add(OpCodes.Ldarg_0); + bodyBuilder.Add(OpCodes.Ldsfld, typeContext.ClassPointerFieldRef); + bodyBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_object_new.Value); + bodyBuilder.Add(OpCodes.Call, + new MemberReference(typeContext.NewType.BaseType, ".ctor", MethodSignature.CreateInstance(assemblyContext.Imports.Module.Void(), assemblyContext.Imports.Module.IntPtr()))); + bodyBuilder.Add(OpCodes.Ret); } } } diff --git a/Il2CppInterop.Generator/Passes/Pass30GenerateGenericMethodStoreConstructors.cs b/Il2CppInterop.Generator/Passes/Pass30GenerateGenericMethodStoreConstructors.cs index e23da101..57a589b7 100644 --- a/Il2CppInterop.Generator/Passes/Pass30GenerateGenericMethodStoreConstructors.cs +++ b/Il2CppInterop.Generator/Passes/Pass30GenerateGenericMethodStoreConstructors.cs @@ -1,10 +1,9 @@ using System.Reflection; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; -using Mono.Cecil.Cil; -using MethodAttributes = Mono.Cecil.MethodAttributes; namespace Il2CppInterop.Generator.Passes; @@ -13,7 +12,9 @@ public static class Pass30GenerateGenericMethodStoreConstructors public static void DoPass(RewriteGlobalContext context) { foreach (var assemblyContext in context.Assemblies) + { foreach (var typeContext in assemblyContext.Types) + { foreach (var methodContext in typeContext.Methods) { var oldMethod = methodContext.OriginalMethod; @@ -21,86 +22,70 @@ public static void DoPass(RewriteGlobalContext context) var storeType = methodContext.GenericInstantiationsStore; if (storeType != null) { - var cctor = new MethodDefinition(".cctor", - MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.SpecialName | - MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, - assemblyContext.Imports.Module.Void()); - storeType.Methods.Add(cctor); + var cctor = storeType.GetOrCreateStaticConstructor(); - var ctorBuilder = cctor.Body.GetILProcessor(); + var ctorBuilder = cctor.CilMethodBody!.Instructions; + ctorBuilder.Clear(); var il2CppTypeTypeRewriteContext = assemblyContext.GlobalContext .GetAssemblyByName("mscorlib").GetTypeByName("System.Type"); var il2CppSystemTypeRef = - assemblyContext.NewAssembly.MainModule.ImportReference(il2CppTypeTypeRewriteContext.NewType); + assemblyContext.NewAssembly.ManifestModule!.DefaultImporter.ImportType(il2CppTypeTypeRewriteContext.NewType); var il2CppMethodInfoTypeRewriteContext = assemblyContext.GlobalContext .GetAssemblyByName("mscorlib").GetTypeByName("System.Reflection.MethodInfo"); var il2CppSystemReflectionMethodInfoRef = - assemblyContext.NewAssembly.MainModule.ImportReference(il2CppMethodInfoTypeRewriteContext.NewType); + assemblyContext.NewAssembly.ManifestModule.DefaultImporter.ImportType(il2CppMethodInfoTypeRewriteContext.NewType); - ctorBuilder.Emit(OpCodes.Ldsfld, methodContext.NonGenericMethodInfoPointerField); - ctorBuilder.Emit(OpCodes.Ldsfld, typeContext.ClassPointerFieldRef); - ctorBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_method_get_object.Value); - ctorBuilder.Emit(OpCodes.Newobj, - new MethodReference(".ctor", assemblyContext.Imports.Module.Void(), - il2CppSystemReflectionMethodInfoRef) - { - HasThis = true, - Parameters = { new ParameterDefinition(assemblyContext.Imports.Module.IntPtr()) } - }); + ctorBuilder.Add(OpCodes.Ldsfld, methodContext.NonGenericMethodInfoPointerField); + ctorBuilder.Add(OpCodes.Ldsfld, typeContext.ClassPointerFieldRef); + ctorBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_method_get_object.Value); + ctorBuilder.Add(OpCodes.Newobj, + new MemberReference(il2CppSystemReflectionMethodInfoRef, ".ctor", + MethodSignature.CreateInstance(assemblyContext.Imports.Module.Void(), assemblyContext.Imports.Module.IntPtr()))); - ctorBuilder.EmitLdcI4(oldMethod.GenericParameters.Count); + ctorBuilder.Add(OpCodes.Ldc_I4, oldMethod.GenericParameters.Count); - ctorBuilder.Emit(OpCodes.Newarr, il2CppSystemTypeRef); + ctorBuilder.Add(OpCodes.Newarr, il2CppSystemTypeRef); for (var i = 0; i < oldMethod.GenericParameters.Count; i++) { - ctorBuilder.Emit(OpCodes.Dup); - ctorBuilder.EmitLdcI4(i); + ctorBuilder.Add(OpCodes.Dup); + ctorBuilder.Add(OpCodes.Ldc_I4, i); var param = storeType.GenericParameters[i]; - var storeRef = new GenericInstanceType(assemblyContext.Imports.Il2CppClassPointerStore) - { GenericArguments = { param } }; - var fieldRef = new FieldReference( + var storeRef = assemblyContext.Imports.Il2CppClassPointerStore.MakeGenericInstanceType(new GenericParameterSignature(GenericParameterType.Type, param.Number)); + var fieldRef = new MemberReference( + storeRef.ToTypeDefOrRef(), "NativeClassPtr", - assemblyContext.Imports.Module.IntPtr(), storeRef); - ctorBuilder.Emit(OpCodes.Ldsfld, fieldRef); + new FieldSignature(assemblyContext.Imports.Module.IntPtr())); + ctorBuilder.Add(OpCodes.Ldsfld, fieldRef); - ctorBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_class_get_type.Value); + ctorBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_class_get_type.Value); - ctorBuilder.Emit(OpCodes.Call, - new MethodReference("internal_from_handle", il2CppSystemTypeRef, - il2CppSystemTypeRef) - { Parameters = { new ParameterDefinition(assemblyContext.Imports.Module.IntPtr()) } }); - ctorBuilder.Emit(OpCodes.Stelem_Ref); + ctorBuilder.Add(OpCodes.Call, + new MemberReference(il2CppSystemTypeRef, "internal_from_handle", + MethodSignature.CreateStatic(il2CppSystemTypeRef.ToTypeSignature(), assemblyContext.Imports.Module.IntPtr()))); + ctorBuilder.Add(OpCodes.Stelem_Ref); } - var il2CppTypeArray = new GenericInstanceType(assemblyContext.Imports.Il2CppReferenceArray) - { GenericArguments = { il2CppSystemTypeRef } }; - ctorBuilder.Emit(OpCodes.Newobj, - new MethodReference(".ctor", assemblyContext.Imports.Module.Void(), il2CppTypeArray) - { - HasThis = true, - Parameters = - { - new ParameterDefinition( - new ArrayType(assemblyContext.Imports.Il2CppReferenceArray.GenericParameters[0])) - } - }); - ctorBuilder.Emit(OpCodes.Call, - new MethodReference(nameof(MethodInfo.MakeGenericMethod), il2CppSystemReflectionMethodInfoRef, - il2CppSystemReflectionMethodInfoRef) - { HasThis = true, Parameters = { new ParameterDefinition(il2CppTypeArray) } }); - ctorBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_Il2CppObjectBaseToPtrNotNull.Value); - - ctorBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_method_get_from_reflection.Value); - ctorBuilder.Emit(OpCodes.Stsfld, - new FieldReference("Pointer", assemblyContext.Imports.Module.IntPtr(), + var il2CppTypeArray = assemblyContext.Imports.Il2CppReferenceArray.MakeGenericInstanceType(il2CppSystemTypeRef.ToTypeSignature()); + ctorBuilder.Add(OpCodes.Newobj, + ReferenceCreator.CreateInstanceMethodReference(".ctor", assemblyContext.Imports.Module.Void(), il2CppTypeArray.ToTypeDefOrRef(), new GenericParameterSignature(GenericParameterType.Type, 0).MakeSzArrayType())); + ctorBuilder.Add(OpCodes.Call, + ReferenceCreator.CreateInstanceMethodReference(nameof(MethodInfo.MakeGenericMethod), il2CppSystemReflectionMethodInfoRef.ToTypeSignature(), + il2CppSystemReflectionMethodInfoRef, il2CppTypeArray)); + ctorBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_Il2CppObjectBaseToPtrNotNull.Value); + + ctorBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_il2cpp_method_get_from_reflection.Value); + ctorBuilder.Add(OpCodes.Stsfld, + ReferenceCreator.CreateFieldReference("Pointer", assemblyContext.Imports.Module.IntPtr(), methodContext.GenericInstantiationsStoreSelfSubstRef)); - ctorBuilder.Emit(OpCodes.Ret); + ctorBuilder.Add(OpCodes.Ret); } } + } + } } } diff --git a/Il2CppInterop.Generator/Passes/Pass40GenerateFieldAccessors.cs b/Il2CppInterop.Generator/Passes/Pass40GenerateFieldAccessors.cs index f736cb99..b100ebc0 100644 --- a/Il2CppInterop.Generator/Passes/Pass40GenerateFieldAccessors.cs +++ b/Il2CppInterop.Generator/Passes/Pass40GenerateFieldAccessors.cs @@ -1,6 +1,8 @@ +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -9,7 +11,9 @@ public static class Pass40GenerateFieldAccessors public static void DoPass(RewriteGlobalContext context) { foreach (var assemblyContext in context.Assemblies) + { foreach (var typeContext in assemblyContext.Types) + { foreach (var fieldContext in typeContext.Fields) { if (typeContext.ComputedTypeSpecifics == TypeRewriteContext.TypeSpecifics.BlittableStruct && @@ -18,12 +22,17 @@ public static void DoPass(RewriteGlobalContext context) var field = fieldContext.OriginalField; var unmangleFieldName = fieldContext.UnmangledName; - var property = new PropertyDefinition(unmangleFieldName, PropertyAttributes.None, - assemblyContext.RewriteTypeRef(fieldContext.OriginalField.FieldType)); + var propertyType = assemblyContext.RewriteTypeRef(fieldContext.OriginalField.Signature!.FieldType); + var signature = field.IsStatic + ? PropertySignature.CreateStatic(propertyType) + : PropertySignature.CreateInstance(propertyType); + var property = new PropertyDefinition(unmangleFieldName, PropertyAttributes.None, signature); typeContext.NewType.Properties.Add(property); FieldAccessorGenerator.MakeGetter(field, fieldContext, property, assemblyContext.Imports); FieldAccessorGenerator.MakeSetter(field, fieldContext, property, assemblyContext.Imports); } + } + } } } diff --git a/Il2CppInterop.Generator/Passes/Pass50GenerateMethods.cs b/Il2CppInterop.Generator/Passes/Pass50GenerateMethods.cs index 8844d2af..d0f04a70 100644 --- a/Il2CppInterop.Generator/Passes/Pass50GenerateMethods.cs +++ b/Il2CppInterop.Generator/Passes/Pass50GenerateMethods.cs @@ -1,9 +1,10 @@ -using System.Collections.Generic; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Code.Cil; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Cil; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; -using Mono.Cecil.Cil; namespace Il2CppInterop.Generator.Passes; @@ -12,30 +13,32 @@ public static class Pass50GenerateMethods public static void DoPass(RewriteGlobalContext context) { foreach (var assemblyContext in context.Assemblies) + { foreach (var typeContext in assemblyContext.Types) + { foreach (var methodRewriteContext in typeContext.Methods) { var originalMethod = methodRewriteContext.OriginalMethod; var newMethod = methodRewriteContext.NewMethod; var imports = assemblyContext.Imports; - var bodyBuilder = newMethod.Body.GetILProcessor(); - var exceptionLocal = new VariableDefinition(imports.Module.IntPtr()); - var argArray = new VariableDefinition(new PointerType(imports.Module.IntPtr())); - var resultVar = new VariableDefinition(imports.Module.IntPtr()); - var valueTypeLocal = new VariableDefinition(newMethod.ReturnType); - newMethod.Body.Variables.Add(exceptionLocal); - newMethod.Body.Variables.Add(argArray); - newMethod.Body.Variables.Add(resultVar); + var bodyBuilder = newMethod.CilMethodBody!.Instructions; + var exceptionLocal = new CilLocalVariable(imports.Module.IntPtr()); + var argArray = new CilLocalVariable(imports.Module.IntPtr().MakePointerType()); + var resultVar = new CilLocalVariable(imports.Module.IntPtr()); + var valueTypeLocal = new CilLocalVariable(newMethod.Signature!.ReturnType); + newMethod.CilMethodBody.LocalVariables.Add(exceptionLocal); + newMethod.CilMethodBody.LocalVariables.Add(argArray); + newMethod.CilMethodBody.LocalVariables.Add(resultVar); if (valueTypeLocal.VariableType.FullName != "System.Void") - newMethod.Body.Variables.Add(valueTypeLocal); + newMethod.CilMethodBody.LocalVariables.Add(valueTypeLocal); // Pre-initialize any present params // TODO: This doesn't account for params T[] (i.e. generic element type) yet; may emit incorrect IL // TODO: Do we really need a loop here? C# allows only one params array. // On the other hand, CreateParamsMethod accommodates multiple ParamArrayAttribute as well - Instruction nextInstruction = null; + CilInstructionLabel? nextInstruction = null; for (var paramIndex = 0; paramIndex < originalMethod.Parameters.Count; paramIndex++) { var newParameter = newMethod.Parameters[paramIndex]; @@ -43,124 +46,123 @@ public static void DoPass(RewriteGlobalContext context) if (!originalParameter.IsParamsArray()) continue; - var originalElementType = ((ArrayType)originalParameter.ParameterType).ElementType; + var originalElementType = ((ArrayBaseTypeSignature)originalParameter.ParameterType).BaseType; if (nextInstruction != null) - bodyBuilder.Append(nextInstruction); - nextInstruction = bodyBuilder.Create(OpCodes.Nop); + nextInstruction.Instruction = bodyBuilder.Add(OpCodes.Nop); + nextInstruction = new(); - bodyBuilder.Emit(OpCodes.Ldarg, newParameter); - bodyBuilder.Emit(OpCodes.Brtrue, nextInstruction); + bodyBuilder.Add(OpCodes.Ldarg, newParameter); + bodyBuilder.Add(OpCodes.Brtrue, nextInstruction); - bodyBuilder.Emit(OpCodes.Ldc_I4_0); - bodyBuilder.Emit(OpCodes.Conv_I8); - bodyBuilder.Emit(OpCodes.Newobj, imports.Module.ImportReference(originalElementType.FullName switch + bodyBuilder.Add(OpCodes.Ldc_I4_0); + bodyBuilder.Add(OpCodes.Conv_I8); + bodyBuilder.Add(OpCodes.Newobj, imports.Module.DefaultImporter.ImportMethod(originalElementType.FullName switch { "System.String" => imports.Il2CppStringArrayctor_size.Value, - _ when originalElementType.IsValueType => imports.Il2CppStructArrayctor_size.Get(((GenericInstanceType)newParameter.ParameterType).GenericArguments[0]), - _ => imports.Il2CppRefrenceArrayctor_size.Get(((GenericInstanceType)newParameter.ParameterType).GenericArguments[0]) + _ when originalElementType.IsValueType => imports.Il2CppStructArrayctor_size.Get(((GenericInstanceTypeSignature)newParameter.ParameterType).TypeArguments[0]), + _ => imports.Il2CppRefrenceArrayctor_size.Get(((GenericInstanceTypeSignature)newParameter.ParameterType).TypeArguments[0]) })); - bodyBuilder.Emit(OpCodes.Starg, newParameter); + bodyBuilder.Add(OpCodes.Starg, newParameter); } if (nextInstruction != null) - bodyBuilder.Append(nextInstruction); + nextInstruction.Instruction = bodyBuilder.Add(OpCodes.Nop); if (typeContext.ComputedTypeSpecifics != TypeRewriteContext.TypeSpecifics.BlittableStruct) { if (originalMethod.IsConstructor) { - bodyBuilder.Emit(OpCodes.Ldarg_0); - bodyBuilder.Emit(OpCodes.Ldsfld, typeContext.ClassPointerFieldRef); - bodyBuilder.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_object_new.Value); - bodyBuilder.Emit(OpCodes.Call, - new MethodReference(".ctor", imports.Module.Void(), typeContext.SelfSubstitutedRef) - { Parameters = { new ParameterDefinition(imports.Module.IntPtr()) }, HasThis = true }); + bodyBuilder.Add(OpCodes.Ldarg_0); + bodyBuilder.Add(OpCodes.Ldsfld, typeContext.ClassPointerFieldRef); + bodyBuilder.Add(OpCodes.Call, imports.IL2CPP_il2cpp_object_new.Value); + bodyBuilder.Add(OpCodes.Call, + ReferenceCreator.CreateInstanceMethodReference(".ctor", imports.Module.Void(), typeContext.SelfSubstitutedRef, imports.Module.IntPtr())); } else if (!originalMethod.IsStatic) { - bodyBuilder.Emit(OpCodes.Ldarg_0); - bodyBuilder.Emit(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtrNotNull.Value); - bodyBuilder.Emit(OpCodes.Pop); + bodyBuilder.Add(OpCodes.Ldarg_0); + bodyBuilder.Add(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtrNotNull.Value); + bodyBuilder.Add(OpCodes.Pop); } } if (originalMethod.Parameters.Count == 0) { - bodyBuilder.Emit(OpCodes.Ldc_I4_0); - bodyBuilder.Emit(OpCodes.Conv_U); + bodyBuilder.Add(OpCodes.Ldc_I4_0); + bodyBuilder.Add(OpCodes.Conv_U); } else { - bodyBuilder.EmitLdcI4(originalMethod.Parameters.Count); - bodyBuilder.Emit(OpCodes.Conv_U); - bodyBuilder.Emit(OpCodes.Sizeof, imports.Module.IntPtr()); - bodyBuilder.Emit(OpCodes.Mul_Ovf_Un); - bodyBuilder.Emit(OpCodes.Localloc); + bodyBuilder.Add(OpCodes.Ldc_I4, originalMethod.Parameters.Count); + bodyBuilder.Add(OpCodes.Conv_U); + bodyBuilder.Add(OpCodes.Sizeof, imports.Module.IntPtr().ToTypeDefOrRef()); + bodyBuilder.Add(OpCodes.Mul_Ovf_Un); + bodyBuilder.Add(OpCodes.Localloc); } - bodyBuilder.Emit(OpCodes.Stloc, argArray); + bodyBuilder.Add(OpCodes.Stloc, argArray); var argOffset = originalMethod.IsStatic ? 0 : 1; - var byRefParams = new List<(int, VariableDefinition)>(); + var byRefParams = new List<(int, CilLocalVariable)>(); for (var i = 0; i < newMethod.Parameters.Count; i++) { - bodyBuilder.Emit(OpCodes.Ldloc, argArray); + bodyBuilder.Add(OpCodes.Ldloc, argArray); if (i > 0) { - bodyBuilder.EmitLdcI4(i); - bodyBuilder.Emit(OpCodes.Conv_U); - bodyBuilder.Emit(OpCodes.Sizeof, imports.Module.IntPtr()); - bodyBuilder.Emit(OpCodes.Mul_Ovf_Un); - bodyBuilder.Emit(OpCodes.Add); + bodyBuilder.Add(OpCodes.Ldc_I4, i); + bodyBuilder.Add(OpCodes.Conv_U); + bodyBuilder.Add(OpCodes.Sizeof, imports.Module.IntPtr().ToTypeDefOrRef()); + bodyBuilder.Add(OpCodes.Mul_Ovf_Un); + bodyBuilder.Add(OpCodes.Add); } var newParam = newMethod.Parameters[i]; // NOTE(Kas): out parameters of value type are passed directly as a pointer to the il2cpp method // since we don't need to perform any additional copies - if (newParam.IsOut && !newParam.ParameterType.GetElementType().IsValueType) + if (newParam.Definition!.IsOut && !newParam.ParameterType.GetElementType().IsValueType) { var elementType = newParam.ParameterType.GetElementType(); // Storage for the output Il2CppObjectBase pointer, it's // unused if there's a generic value type parameter - var outVar = new VariableDefinition(imports.Module.IntPtr()); - bodyBuilder.Body.Variables.Add(outVar); + var outVar = new CilLocalVariable(imports.Module.IntPtr()); + bodyBuilder.Owner.LocalVariables.Add(outVar); - if (elementType.IsGenericParameter) + if (elementType is GenericParameterSignature) { - bodyBuilder.Emit(OpCodes.Ldtoken, elementType); - bodyBuilder.Emit(OpCodes.Call, imports.Module.TypeGetTypeFromHandle()); - bodyBuilder.Emit(OpCodes.Callvirt, imports.Module.TypeGetIsValueType()); + bodyBuilder.Add(OpCodes.Ldtoken, elementType.ToTypeDefOrRef()); + bodyBuilder.Add(OpCodes.Call, imports.Module.TypeGetTypeFromHandle()); + bodyBuilder.Add(OpCodes.Callvirt, imports.Module.TypeGetIsValueType()); - var valueTypeBlock = bodyBuilder.Create(OpCodes.Nop); - var continueBlock = bodyBuilder.Create(OpCodes.Nop); + var valueTypeBlock = new CilInstructionLabel(); + var continueBlock = new CilInstructionLabel(); - bodyBuilder.Emit(OpCodes.Brtrue, valueTypeBlock); + bodyBuilder.Add(OpCodes.Brtrue, valueTypeBlock); // The generic parameter is an Il2CppObjectBase => set the output storage to a nullptr - bodyBuilder.EmitLdcI4(0); - bodyBuilder.Emit(OpCodes.Stloc, outVar); - bodyBuilder.Emit(OpCodes.Ldloca, outVar); - bodyBuilder.Emit(OpCodes.Conv_I); + bodyBuilder.Add(OpCodes.Ldc_I4, 0); + bodyBuilder.Add(OpCodes.Stloc, outVar); + bodyBuilder.Add(OpCodes.Ldloca, outVar); + bodyBuilder.Add(OpCodes.Conv_I); - bodyBuilder.Emit(OpCodes.Br_S, continueBlock); + bodyBuilder.Add(OpCodes.Br_S, continueBlock); // Instruction block that handles generic value types, we only need to return a reference // to the output argument since it is already allocated for us - bodyBuilder.Append(valueTypeBlock); - bodyBuilder.Emit(OpCodes.Ldarg, argOffset + i); + valueTypeBlock.Instruction = bodyBuilder.Add(OpCodes.Nop); + bodyBuilder.AddLoadArgument(argOffset + i); - bodyBuilder.Append(continueBlock); + continueBlock.Instruction = bodyBuilder.Add(OpCodes.Nop); } else { - bodyBuilder.EmitLdcI4(0); - bodyBuilder.Emit(OpCodes.Stloc, outVar); - bodyBuilder.Emit(OpCodes.Ldloca, outVar); - bodyBuilder.Emit(OpCodes.Conv_I); + bodyBuilder.Add(OpCodes.Ldc_I4, 0); + bodyBuilder.Add(OpCodes.Stloc, outVar); + bodyBuilder.Add(OpCodes.Ldloca, outVar); + bodyBuilder.Add(OpCodes.Conv_I); } byRefParams.Add((i, outVar)); } @@ -171,47 +173,47 @@ public static void DoPass(RewriteGlobalContext context) if (refVar != null) byRefParams.Add((i, refVar)); } - bodyBuilder.Emit(OpCodes.Stind_I); + bodyBuilder.Add(OpCodes.Stind_I); } - if (!originalMethod.DeclaringType.IsSealed && !originalMethod.IsFinal && + if (!originalMethod.DeclaringType!.IsSealed && !originalMethod.IsFinal && ((originalMethod.IsVirtual && !originalMethod.DeclaringType.IsValueType) || originalMethod.IsAbstract)) { - bodyBuilder.Emit(OpCodes.Ldarg_0); - bodyBuilder.Emit(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtr.Value); + bodyBuilder.Add(OpCodes.Ldarg_0); + bodyBuilder.Add(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtr.Value); if (methodRewriteContext.GenericInstantiationsStoreSelfSubstRef != null) - bodyBuilder.Emit(OpCodes.Ldsfld, - new FieldReference("Pointer", imports.Module.IntPtr(), + bodyBuilder.Add(OpCodes.Ldsfld, + ReferenceCreator.CreateFieldReference("Pointer", imports.Module.IntPtr(), methodRewriteContext.GenericInstantiationsStoreSelfSubstMethodRef)); else - bodyBuilder.Emit(OpCodes.Ldsfld, methodRewriteContext.NonGenericMethodInfoPointerField); - bodyBuilder.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_object_get_virtual_method.Value); + bodyBuilder.Add(OpCodes.Ldsfld, methodRewriteContext.NonGenericMethodInfoPointerField); + bodyBuilder.Add(OpCodes.Call, imports.IL2CPP_il2cpp_object_get_virtual_method.Value); } else if (methodRewriteContext.GenericInstantiationsStoreSelfSubstRef != null) { - bodyBuilder.Emit(OpCodes.Ldsfld, - new FieldReference("Pointer", imports.Module.IntPtr(), + bodyBuilder.Add(OpCodes.Ldsfld, + ReferenceCreator.CreateFieldReference("Pointer", imports.Module.IntPtr(), methodRewriteContext.GenericInstantiationsStoreSelfSubstMethodRef)); } else { - bodyBuilder.Emit(OpCodes.Ldsfld, methodRewriteContext.NonGenericMethodInfoPointerField); + bodyBuilder.Add(OpCodes.Ldsfld, methodRewriteContext.NonGenericMethodInfoPointerField); } if (originalMethod.IsStatic) - bodyBuilder.Emit(OpCodes.Ldc_I4_0); + bodyBuilder.Add(OpCodes.Ldc_I4_0); else - bodyBuilder.EmitObjectToPointer(originalMethod.DeclaringType, newMethod.DeclaringType, typeContext, 0, + bodyBuilder.EmitObjectToPointer(originalMethod.DeclaringType.ToTypeSignature(), newMethod.DeclaringType!.ToTypeSignature(), typeContext, 0, true, false, true, true, out _); - bodyBuilder.Emit(OpCodes.Ldloc, argArray); - bodyBuilder.Emit(OpCodes.Ldloca, exceptionLocal); - bodyBuilder.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_runtime_invoke.Value); - bodyBuilder.Emit(OpCodes.Stloc, resultVar); + bodyBuilder.Add(OpCodes.Ldloc, argArray); + bodyBuilder.Add(OpCodes.Ldloca, exceptionLocal); + bodyBuilder.Add(OpCodes.Call, imports.IL2CPP_il2cpp_runtime_invoke.Value); + bodyBuilder.Add(OpCodes.Stloc, resultVar); - bodyBuilder.Emit(OpCodes.Ldloc, exceptionLocal); - bodyBuilder.Emit(OpCodes.Call, imports.Il2CppException_RaiseExceptionIfNecessary.Value); + bodyBuilder.Add(OpCodes.Ldloc, exceptionLocal); + bodyBuilder.Add(OpCodes.Call, imports.Il2CppException_RaiseExceptionIfNecessary.Value); foreach (var byRefParam in byRefParams) { @@ -219,25 +221,25 @@ public static void DoPass(RewriteGlobalContext context) var paramVariable = byRefParam.Item2; var methodParam = newMethod.Parameters[paramIndex]; - if (methodParam.IsOut && methodParam.ParameterType.GetElementType().IsGenericParameter) + if (methodParam.Definition!.IsOut && methodParam.ParameterType.GetElementType() is GenericParameterSignature) { - bodyBuilder.Emit(OpCodes.Ldtoken, methodParam.ParameterType.GetElementType()); - bodyBuilder.Emit(OpCodes.Call, imports.Module.TypeGetTypeFromHandle()); - bodyBuilder.Emit(OpCodes.Callvirt, imports.Module.TypeGetIsValueType()); + bodyBuilder.Add(OpCodes.Ldtoken, methodParam.ParameterType.GetElementType().ToTypeDefOrRef()); + bodyBuilder.Add(OpCodes.Call, imports.Module.TypeGetTypeFromHandle()); + bodyBuilder.Add(OpCodes.Callvirt, imports.Module.TypeGetIsValueType()); - var continueBlock = bodyBuilder.Create(OpCodes.Nop); + var continueBlock = new CilInstructionLabel(); - bodyBuilder.Emit(OpCodes.Brtrue, continueBlock); + bodyBuilder.Add(OpCodes.Brtrue, continueBlock); // The generic parameter is an Il2CppObjectBase => update the reference appropriately bodyBuilder.EmitUpdateRef(newMethod.Parameters[paramIndex], paramIndex + argOffset, paramVariable, imports); - bodyBuilder.Emit(OpCodes.Br_S, continueBlock); + bodyBuilder.Add(OpCodes.Br_S, continueBlock); // There is no need to handle generic value types, they are already passed by reference - bodyBuilder.Append(continueBlock); + continueBlock.Instruction = bodyBuilder.Add(OpCodes.Nop); } else { @@ -246,10 +248,12 @@ public static void DoPass(RewriteGlobalContext context) } } - bodyBuilder.EmitPointerToObject(originalMethod.ReturnType, newMethod.ReturnType, typeContext, - bodyBuilder.Create(OpCodes.Ldloc, resultVar), false, true); + bodyBuilder.EmitPointerToObject(originalMethod.Signature!.ReturnType, newMethod.Signature.ReturnType, typeContext, + resultVar, false, true); - bodyBuilder.Emit(OpCodes.Ret); + bodyBuilder.Add(OpCodes.Ret); } + } + } } } diff --git a/Il2CppInterop.Generator/Passes/Pass60AddImplicitConversions.cs b/Il2CppInterop.Generator/Passes/Pass60AddImplicitConversions.cs index 54b2e1df..b0d0438f 100644 --- a/Il2CppInterop.Generator/Passes/Pass60AddImplicitConversions.cs +++ b/Il2CppInterop.Generator/Passes/Pass60AddImplicitConversions.cs @@ -1,8 +1,11 @@ -using System.Linq; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Code.Cil; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Cil; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Generator.Contexts; +using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; -using Mono.Cecil.Cil; namespace Il2CppInterop.Generator.Passes; @@ -16,59 +19,59 @@ public static void DoPass(RewriteGlobalContext context) var typeContext = assemblyContext.GetTypeByName("System.String"); var objectTypeContext = assemblyContext.GetTypeByName("System.Object"); - var methodFromMonoString = new MethodDefinition("op_Implicit", OperatorAttributes, typeContext.NewType); - methodFromMonoString.Parameters.Add(new ParameterDefinition(assemblyContext.Imports.Module.String())); + var methodFromMonoString = new MethodDefinition("op_Implicit", OperatorAttributes, + MethodSignature.CreateStatic(typeContext.NewType.ToTypeSignature(), assemblyContext.Imports.Module.String())); typeContext.NewType.Methods.Add(methodFromMonoString); - var fromBuilder = methodFromMonoString.Body.GetILProcessor(); + methodFromMonoString.CilMethodBody = new CilMethodBody(methodFromMonoString); + var fromBuilder = methodFromMonoString.CilMethodBody.Instructions; - var createIl2CppStringNop = fromBuilder.Create(OpCodes.Nop); + var createIl2CppStringNop = new CilInstructionLabel(); - fromBuilder.Emit(OpCodes.Ldarg_0); - fromBuilder.Emit(OpCodes.Dup); - fromBuilder.Emit(OpCodes.Brtrue_S, createIl2CppStringNop); - fromBuilder.Emit(OpCodes.Ret); + fromBuilder.Add(OpCodes.Ldarg_0); + fromBuilder.Add(OpCodes.Dup); + fromBuilder.Add(OpCodes.Brtrue_S, createIl2CppStringNop); + fromBuilder.Add(OpCodes.Ret); - fromBuilder.Append(createIl2CppStringNop); - fromBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_ManagedStringToIl2Cpp.Value); - fromBuilder.Emit(OpCodes.Newobj, - new MethodReference(".ctor", assemblyContext.Imports.Module.Void(), typeContext.NewType) - { - HasThis = true, - Parameters = { new ParameterDefinition(assemblyContext.Imports.Module.IntPtr()) } - }); - fromBuilder.Emit(OpCodes.Ret); + createIl2CppStringNop.Instruction = fromBuilder.Add(OpCodes.Nop); - var methodToObject = new MethodDefinition("op_Implicit", OperatorAttributes, objectTypeContext.NewType); - methodToObject.Parameters.Add(new ParameterDefinition(assemblyContext.Imports.Module.String())); - objectTypeContext.NewType.Methods.Add(methodToObject); - var toObjectBuilder = methodToObject.Body.GetILProcessor(); - toObjectBuilder.Emit(OpCodes.Ldarg_0); - toObjectBuilder.Emit(OpCodes.Call, methodFromMonoString); - toObjectBuilder.Emit(OpCodes.Ret); + fromBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_ManagedStringToIl2Cpp.Value); + fromBuilder.Add(OpCodes.Newobj, + ReferenceCreator.CreateInstanceMethodReference(".ctor", assemblyContext.Imports.Module.Void(), typeContext.NewType, assemblyContext.Imports.Module.IntPtr())); + fromBuilder.Add(OpCodes.Ret); - var methodToMonoString = new MethodDefinition("op_Implicit", OperatorAttributes, assemblyContext.Imports.Module.String()); - methodToMonoString.Parameters.Add(new ParameterDefinition(typeContext.NewType)); + var methodToObject = new MethodDefinition("op_Implicit", OperatorAttributes, MethodSignature.CreateStatic(objectTypeContext.NewType.ToTypeSignature())); + methodToObject.AddParameter(assemblyContext.Imports.Module.String()); + objectTypeContext.NewType.Methods.Add(methodToObject); + methodToObject.CilMethodBody = new CilMethodBody(methodToObject); + var toObjectBuilder = methodToObject.CilMethodBody.Instructions; + toObjectBuilder.Add(OpCodes.Ldarg_0); + toObjectBuilder.Add(OpCodes.Call, methodFromMonoString); + toObjectBuilder.Add(OpCodes.Ret); + + var methodToMonoString = new MethodDefinition("op_Implicit", OperatorAttributes, MethodSignature.CreateStatic(assemblyContext.Imports.Module.String())); + methodToMonoString.AddParameter(typeContext.NewType.ToTypeSignature()); typeContext.NewType.Methods.Add(methodToMonoString); - var toBuilder = methodToMonoString.Body.GetILProcessor(); + methodToMonoString.CilMethodBody = new CilMethodBody(methodToMonoString); + var toBuilder = methodToMonoString.CilMethodBody.Instructions; - var createStringNop = toBuilder.Create(OpCodes.Nop); + var createStringNop = new CilInstructionLabel(); - toBuilder.Emit(OpCodes.Ldarg_0); - toBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_Il2CppObjectBaseToPtr.Value); - toBuilder.Emit(OpCodes.Dup); - toBuilder.Emit(OpCodes.Brtrue_S, createStringNop); - toBuilder.Emit(OpCodes.Pop); - toBuilder.Emit(OpCodes.Ldnull); - toBuilder.Emit(OpCodes.Ret); + toBuilder.Add(OpCodes.Ldarg_0); + toBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_Il2CppObjectBaseToPtr.Value); + toBuilder.Add(OpCodes.Dup); + toBuilder.Add(OpCodes.Brtrue_S, createStringNop); + toBuilder.Add(OpCodes.Pop); + toBuilder.Add(OpCodes.Ldnull); + toBuilder.Add(OpCodes.Ret); - toBuilder.Append(createStringNop); - toBuilder.Emit(OpCodes.Call, assemblyContext.Imports.IL2CPP_Il2CppStringToManaged.Value); - toBuilder.Emit(OpCodes.Ret); + createStringNop.Instruction = toBuilder.Add(OpCodes.Nop); + toBuilder.Add(OpCodes.Call, assemblyContext.Imports.IL2CPP_Il2CppStringToManaged.Value); + toBuilder.Add(OpCodes.Ret); AddDelegateConversions(context); - var primitiveTypes = new[] - { + TypeSignature[] primitiveTypes = + [ assemblyContext.Imports.Module.SByte(), assemblyContext.Imports.Module.Byte(), @@ -86,30 +89,31 @@ public static void DoPass(RewriteGlobalContext context) assemblyContext.Imports.Module.Char(), assemblyContext.Imports.Module.Bool(), - }; + ]; foreach (var systemType in primitiveTypes) { var il2CppSystemType = assemblyContext.GetTypeByName(systemType.FullName).NewType; - var method = new MethodDefinition("op_Implicit", OperatorAttributes, objectTypeContext.NewType); - method.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.None, systemType)); + var method = new MethodDefinition("op_Implicit", OperatorAttributes, MethodSignature.CreateStatic(objectTypeContext.NewType.ToTypeSignature())); + method.AddParameter(systemType, "value"); - var il = method.Body.GetILProcessor(); + method.CilMethodBody = new CilMethodBody(method); + var il = method.CilMethodBody.Instructions; - var structLocal = new VariableDefinition(il2CppSystemType); - method.Body.Variables.Add(structLocal); + var structLocal = new CilLocalVariable(il2CppSystemType.ToTypeSignature()); + method.CilMethodBody.LocalVariables.Add(structLocal); - il.Emit(OpCodes.Ldloca, structLocal); - il.Emit(OpCodes.Initobj, il2CppSystemType); + il.Add(OpCodes.Ldloca, structLocal); + il.Add(OpCodes.Initobj, il2CppSystemType); - il.Emit(OpCodes.Ldloca, structLocal); - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Stfld, il2CppSystemType.Fields.Single(f => f.Name == "m_value")); + il.Add(OpCodes.Ldloca, structLocal); + il.Add(OpCodes.Ldarg_0); + il.Add(OpCodes.Stfld, il2CppSystemType.Fields.Single(f => f.Name == "m_value")); - il.Emit(OpCodes.Ldloca_S, structLocal); - il.Emit(OpCodes.Call, il2CppSystemType.Methods.Single(m => m.Name == "BoxIl2CppObject")); - il.Emit(OpCodes.Ret); + il.Add(OpCodes.Ldloca_S, structLocal); + il.Add(OpCodes.Call, il2CppSystemType.Methods.Single(m => m.Name == "BoxIl2CppObject")); + il.Add(OpCodes.Ret); objectTypeContext.NewType.Methods.Add(method); } @@ -118,101 +122,94 @@ public static void DoPass(RewriteGlobalContext context) private static void AddDelegateConversions(RewriteGlobalContext context) { foreach (var assemblyContext in context.Assemblies) + { foreach (var typeContext in assemblyContext.Types) { - if (typeContext.OriginalType.BaseType?.FullName != "System.MulticastDelegate") continue; + if (typeContext.OriginalType.BaseType?.FullName != "System.MulticastDelegate") + continue; var invokeMethod = typeContext.NewType.Methods.Single(it => it.Name == "Invoke"); - if (invokeMethod.Parameters.Count > 8) continue; // mscorlib only contains delegates of up to 8 parameters + if (invokeMethod.Parameters.Count > 8) + continue; // mscorlib only contains delegates of up to 8 parameters // Don't generate implicit conversions for pointers and byrefs, as they can't be specified in generics - if (invokeMethod.Parameters.Any(it => it.ParameterType.IsByReference || it.ParameterType.IsPointer)) + if (invokeMethod.Parameters.Any(it => it.ParameterType is PointerTypeSignature or ByReferenceTypeSignature)) continue; - var implicitMethod = new MethodDefinition("op_Implicit", OperatorAttributes, typeContext.SelfSubstitutedRef); + var implicitMethod = new MethodDefinition("op_Implicit", OperatorAttributes, MethodSignature.CreateStatic(typeContext.SelfSubstitutedRef.ToTypeSignature())); typeContext.NewType.Methods.Add(implicitMethod); + implicitMethod.CilMethodBody = new CilMethodBody(implicitMethod); - var hasReturn = invokeMethod.ReturnType.FullName != "System.Void"; + var hasReturn = invokeMethod.Signature!.ReturnType.FullName != "System.Void"; var hasParameters = invokeMethod.Parameters.Count > 0; - TypeReference monoDelegateType; + TypeSignature monoDelegateType; if (!hasReturn && !hasParameters) - monoDelegateType = - typeContext.NewType.Module.Action(); + monoDelegateType = typeContext.NewType.Module!.Action(); else if (!hasReturn) - monoDelegateType = - typeContext.NewType.Module.Action(invokeMethod.Parameters.Count); + monoDelegateType = typeContext.NewType.Module!.Action(invokeMethod.Parameters.Count); else - monoDelegateType = - typeContext.NewType.Module.Func(invokeMethod.Parameters.Count); + monoDelegateType = typeContext.NewType.Module!.Func(invokeMethod.Parameters.Count); - GenericInstanceType genericInstanceType = null; + GenericInstanceTypeSignature? genericInstanceType = null; if (hasParameters) { - genericInstanceType = new GenericInstanceType(monoDelegateType); + genericInstanceType = new GenericInstanceTypeSignature(monoDelegateType.ToTypeDefOrRef(), false); foreach (var t in invokeMethod.Parameters) - genericInstanceType.GenericArguments.Add(t.ParameterType); + genericInstanceType.TypeArguments.Add(t.ParameterType); } if (hasReturn) { - genericInstanceType ??= new GenericInstanceType(monoDelegateType); - genericInstanceType.GenericArguments.Add(invokeMethod.ReturnType); + genericInstanceType ??= new GenericInstanceTypeSignature(monoDelegateType.ToTypeDefOrRef(), false); + genericInstanceType.TypeArguments.Add(invokeMethod.Signature.ReturnType); } - implicitMethod.Parameters.Add(new ParameterDefinition(genericInstanceType != null - ? typeContext.NewType.Module.ImportReference(genericInstanceType) - : monoDelegateType)); + implicitMethod.AddParameter(genericInstanceType != null + ? typeContext.NewType.Module!.DefaultImporter.ImportTypeSignature(genericInstanceType) + : monoDelegateType); - var bodyBuilder = implicitMethod.Body.GetILProcessor(); + var bodyBuilder = implicitMethod.CilMethodBody.Instructions; - bodyBuilder.Emit(OpCodes.Ldarg_0); + bodyBuilder.Add(OpCodes.Ldarg_0); var delegateSupportTypeRef = typeContext.AssemblyContext.Imports.DelegateSupport; - var genericConvertRef = - new MethodReference("ConvertDelegate", assemblyContext.Imports.Module.Void(), delegateSupportTypeRef) - { - HasThis = false, - Parameters = { new ParameterDefinition(assemblyContext.Imports.Module.Delegate()) } - }; - genericConvertRef.GenericParameters.Add(new GenericParameter(genericConvertRef)); - genericConvertRef.ReturnType = genericConvertRef.GenericParameters[0]; - var convertMethodRef = new GenericInstanceMethod(genericConvertRef) - { GenericArguments = { typeContext.SelfSubstitutedRef } }; - bodyBuilder.Emit(OpCodes.Call, typeContext.NewType.Module.ImportReference(convertMethodRef)); - bodyBuilder.Emit(OpCodes.Ret); + var genericConvertSignature = MethodSignature.CreateStatic(new GenericParameterSignature(GenericParameterType.Method, 0), 1, assemblyContext.Imports.Module.Delegate()); + var genericConvertRef = new MemberReference(delegateSupportTypeRef.ToTypeDefOrRef(), "ConvertDelegate", genericConvertSignature); + var convertMethodRef = genericConvertRef.MakeGenericInstanceMethod(typeContext.SelfSubstitutedRef.ToTypeSignature()); + bodyBuilder.Add(OpCodes.Call, typeContext.NewType.Module!.DefaultImporter.ImportMethod(convertMethodRef)); + bodyBuilder.Add(OpCodes.Ret); // public static T operator+(T lhs, T rhs) => Il2CppSystem.Delegate.Combine(lhs, rhs).Cast(); - var addMethod = new MethodDefinition("op_Addition", OperatorAttributes, typeContext.SelfSubstitutedRef); + var addMethod = new MethodDefinition("op_Addition", OperatorAttributes, MethodSignature.CreateStatic(typeContext.SelfSubstitutedRef.ToTypeSignature())); typeContext.NewType.Methods.Add(addMethod); - addMethod.Parameters.Add(new ParameterDefinition(typeContext.SelfSubstitutedRef)); - addMethod.Parameters.Add(new ParameterDefinition(typeContext.SelfSubstitutedRef)); - var addBody = addMethod.Body.GetILProcessor(); - addBody.Emit(OpCodes.Ldarg_0); - addBody.Emit(OpCodes.Ldarg_1); - addBody.Emit(OpCodes.Call, assemblyContext.Imports.Il2CppSystemDelegateCombine.Value); - addBody.Emit(OpCodes.Call, - assemblyContext.Imports.Module.ImportReference( - new GenericInstanceMethod(assemblyContext.Imports.Il2CppObjectBase_Cast.Value) - { GenericArguments = { typeContext.SelfSubstitutedRef } })); - addBody.Emit(OpCodes.Ret); + addMethod.AddParameter(typeContext.SelfSubstitutedRef.ToTypeSignature()); + addMethod.AddParameter(typeContext.SelfSubstitutedRef.ToTypeSignature()); + addMethod.CilMethodBody = new CilMethodBody(addMethod); + var addBody = addMethod.CilMethodBody.Instructions; + addBody.Add(OpCodes.Ldarg_0); + addBody.Add(OpCodes.Ldarg_1); + addBody.Add(OpCodes.Call, assemblyContext.Imports.Il2CppSystemDelegateCombine.Value); + addBody.Add(OpCodes.Call, + assemblyContext.Imports.Module.DefaultImporter.ImportMethod(assemblyContext.Imports.Il2CppObjectBase_Cast.Value.MakeGenericInstanceMethod(typeContext.SelfSubstitutedRef.ToTypeSignature()))); + addBody.Add(OpCodes.Ret); // public static T operator-(T lhs, T rhs) => Il2CppSystem.Delegate.Remove(lhs, rhs)?.Cast(); - var subtractMethod = new MethodDefinition("op_Subtraction", OperatorAttributes, typeContext.SelfSubstitutedRef); + var subtractMethod = new MethodDefinition("op_Subtraction", OperatorAttributes, MethodSignature.CreateStatic(typeContext.SelfSubstitutedRef.ToTypeSignature())); typeContext.NewType.Methods.Add(subtractMethod); - subtractMethod.Parameters.Add(new ParameterDefinition(typeContext.SelfSubstitutedRef)); - subtractMethod.Parameters.Add(new ParameterDefinition(typeContext.SelfSubstitutedRef)); - var subtractBody = subtractMethod.Body.GetILProcessor(); - subtractBody.Emit(OpCodes.Ldarg_0); - subtractBody.Emit(OpCodes.Ldarg_1); - subtractBody.Emit(OpCodes.Call, assemblyContext.Imports.Il2CppSystemDelegateRemove.Value); - subtractBody.Emit(OpCodes.Dup); - var ret = subtractBody.Create(OpCodes.Ret); - subtractBody.Emit(OpCodes.Brfalse_S, ret); - subtractBody.Emit(OpCodes.Call, - assemblyContext.Imports.Module.ImportReference( - new GenericInstanceMethod(assemblyContext.Imports.Il2CppObjectBase_Cast.Value) - { GenericArguments = { typeContext.SelfSubstitutedRef } })); - subtractBody.Append(ret); + subtractMethod.AddParameter(typeContext.SelfSubstitutedRef.ToTypeSignature()); + subtractMethod.AddParameter(typeContext.SelfSubstitutedRef.ToTypeSignature()); + subtractMethod.CilMethodBody = new CilMethodBody(subtractMethod); + var subtractBody = subtractMethod.CilMethodBody.Instructions; + subtractBody.Add(OpCodes.Ldarg_0); + subtractBody.Add(OpCodes.Ldarg_1); + subtractBody.Add(OpCodes.Call, assemblyContext.Imports.Il2CppSystemDelegateRemove.Value); + subtractBody.Add(OpCodes.Dup); + var ret = new CilInstructionLabel(); + subtractBody.Add(OpCodes.Brfalse_S, ret); + subtractBody.Add(OpCodes.Call, + assemblyContext.Imports.Module.DefaultImporter.ImportMethod(assemblyContext.Imports.Il2CppObjectBase_Cast.Value.MakeGenericInstanceMethod(typeContext.SelfSubstitutedRef.ToTypeSignature()))); + ret.Instruction = subtractBody.Add(OpCodes.Ret); } + } } } diff --git a/Il2CppInterop.Generator/Passes/Pass70GenerateProperties.cs b/Il2CppInterop.Generator/Passes/Pass70GenerateProperties.cs index 9a31cdee..5c842be5 100644 --- a/Il2CppInterop.Generator/Passes/Pass70GenerateProperties.cs +++ b/Il2CppInterop.Generator/Passes/Pass70GenerateProperties.cs @@ -1,10 +1,10 @@ -using System.Collections.Generic; -using System.Linq; using System.Reflection; +using AsmResolver; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -20,30 +20,31 @@ public static void DoPass(RewriteGlobalContext context) foreach (var oldProperty in type.Properties) { - if ((oldProperty.GetMethod?.HasOverrides ?? false) || (oldProperty.SetMethod?.HasOverrides ?? false)) continue; + FixPropertyDefinitionParameters(oldProperty); var unmangledPropertyName = UnmanglePropertyName(assemblyContext, oldProperty, typeContext.NewType, propertyCountsByName); - var property = new PropertyDefinition(unmangledPropertyName, oldProperty.Attributes, - assemblyContext.RewriteTypeRef(oldProperty.PropertyType)); - foreach (var oldParameter in oldProperty.Parameters) - property.Parameters.Add(new ParameterDefinition(oldParameter.Name, oldParameter.Attributes, - assemblyContext.RewriteTypeRef(oldParameter.ParameterType))); + var propertyType = assemblyContext.RewriteTypeRef(oldProperty.Signature!.ReturnType); + var signature = oldProperty.Signature.HasThis + ? PropertySignature.CreateInstance(propertyType) + : PropertySignature.CreateStatic(propertyType); + foreach (var oldParameter in oldProperty.Signature.ParameterTypes) + signature.ParameterTypes.Add(assemblyContext.RewriteTypeRef(oldParameter)); - typeContext.NewType.Properties.Add(property); + var property = new PropertyDefinition(unmangledPropertyName, oldProperty.Attributes, signature); - if (oldProperty.GetMethod != null) - property.GetMethod = typeContext.GetMethodByOldMethod(oldProperty.GetMethod).NewMethod; + typeContext.NewType.Properties.Add(property); - if (oldProperty.SetMethod != null) - property.SetMethod = typeContext.GetMethodByOldMethod(oldProperty.SetMethod).NewMethod; + property.SetSemanticMethods( + oldProperty.GetMethod is null ? null : typeContext.GetMethodByOldMethod(oldProperty.GetMethod).NewMethod, + oldProperty.SetMethod is null ? null : typeContext.GetMethodByOldMethod(oldProperty.SetMethod).NewMethod); } - string defaultMemberName = null; + string? defaultMemberName = null; var defaultMemberAttributeAttribute = type.CustomAttributes.FirstOrDefault(it => - it.AttributeType.Name == "AttributeAttribute" && it.Fields.Any(it => - it.Name == "Name" && (string)it.Argument.Value == nameof(DefaultMemberAttribute))); + it.AttributeType()?.Name == "AttributeAttribute" && it.Signature!.NamedArguments.Any(it => + it.MemberName == "Name" && (Utf8String?)it.Argument.Element == nameof(DefaultMemberAttribute))); if (defaultMemberAttributeAttribute != null) { defaultMemberName = "Item"; @@ -51,33 +52,26 @@ public static void DoPass(RewriteGlobalContext context) else { var realDefaultMemberAttribute = - type.CustomAttributes.FirstOrDefault(it => it.AttributeType.Name == nameof(DefaultMemberAttribute)); + type.CustomAttributes.FirstOrDefault(it => it.AttributeType()?.Name == nameof(DefaultMemberAttribute)); if (realDefaultMemberAttribute != null) - defaultMemberName = realDefaultMemberAttribute.ConstructorArguments[0].Value?.ToString() ?? "Item"; + defaultMemberName = realDefaultMemberAttribute.Signature?.FixedArguments[0].Element?.ToString() ?? "Item"; } if (defaultMemberName != null) typeContext.NewType.CustomAttributes.Add(new CustomAttribute( - new MethodReference(".ctor", assemblyContext.Imports.Module.Void(), - assemblyContext.Imports.Module.DefaultMemberAttribute()) - { - HasThis = true, - Parameters = { new ParameterDefinition(assemblyContext.Imports.Module.String()) } - }) - { - ConstructorArguments = - {new CustomAttributeArgument(assemblyContext.Imports.Module.String(), defaultMemberName)} - }); + ReferenceCreator.CreateInstanceMethodReference(".ctor", assemblyContext.Imports.Module.Void(), + assemblyContext.Imports.Module.DefaultMemberAttribute().ToTypeDefOrRef(), assemblyContext.Imports.Module.String()), + new CustomAttributeSignature(new CustomAttributeArgument(assemblyContext.Imports.Module.String(), defaultMemberName)))); } } private static string UnmanglePropertyName(AssemblyRewriteContext assemblyContext, PropertyDefinition prop, - TypeReference declaringType, Dictionary countsByBaseName) + ITypeDefOrRef declaringType, Dictionary countsByBaseName) { if (assemblyContext.GlobalContext.Options.PassthroughNames || - !prop.Name.IsObfuscated(assemblyContext.GlobalContext.Options)) return prop.Name; + !prop.Name.IsObfuscated(assemblyContext.GlobalContext.Options)) return prop.Name!; - var baseName = "prop_" + assemblyContext.RewriteTypeRef(prop.PropertyType).GetUnmangledName(); + var baseName = "prop_" + assemblyContext.RewriteTypeRef(prop.Signature!.ReturnType).GetUnmangledName(prop.DeclaringType); countsByBaseName.TryGetValue(baseName, out var index); countsByBaseName[baseName] = index + 1; @@ -98,4 +92,38 @@ private static string UnmanglePropertyName(AssemblyRewriteContext assemblyContex return unmanglePropertyName; } + + private static void FixPropertyDefinitionParameters(PropertyDefinition property) + { + // See: https://github.com/SamboyCoding/Cpp2IL/issues/249 + + if (property.Signature is null or { ParameterTypes.Count: > 0 }) + return; + + var getMethod = property.GetMethod; + if (getMethod?.Signature is not null) + { + if (getMethod.Signature.ParameterTypes.Count > 0) + { + foreach (var parameter in getMethod.Signature.ParameterTypes) + { + property.Signature.ParameterTypes.Add(parameter); + } + } + + return; + } + + var setMethod = property.SetMethod; + if (setMethod?.Signature is not null) + { + if (setMethod.Signature.ParameterTypes.Count > 1) + { + foreach (var parameter in setMethod.Signature.ParameterTypes.Take(setMethod.Signature.ParameterTypes.Count - 1)) + { + property.Signature.ParameterTypes.Add(parameter); + } + } + } + } } diff --git a/Il2CppInterop.Generator/Passes/Pass79UnstripTypes.cs b/Il2CppInterop.Generator/Passes/Pass79UnstripTypes.cs index 50d68cb8..8e16c9e9 100644 --- a/Il2CppInterop.Generator/Passes/Pass79UnstripTypes.cs +++ b/Il2CppInterop.Generator/Passes/Pass79UnstripTypes.cs @@ -1,9 +1,11 @@ -using System.Linq; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Common; using Il2CppInterop.Generator.Contexts; +using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; using Microsoft.Extensions.Logging; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -15,19 +17,20 @@ public static void DoPass(RewriteGlobalContext context) foreach (var unityAssembly in context.UnityAssemblies.Assemblies) { - var processedAssembly = context.TryGetAssemblyByName(unityAssembly.Name.Name); + var processedAssembly = context.TryGetAssemblyByName(unityAssembly.Name); if (processedAssembly == null) { - var newAssembly = new AssemblyRewriteContext(context, unityAssembly, - AssemblyDefinition.CreateAssembly(unityAssembly.Name, unityAssembly.MainModule.Name, - ModuleKind.Dll)); - context.AddAssemblyContext(unityAssembly.Name.Name, newAssembly); - processedAssembly = newAssembly; + var newAssembly = new AssemblyDefinition(unityAssembly.Name, unityAssembly.Version); + newAssembly.Modules.Add(new ModuleDefinition(unityAssembly.ManifestModule!.Name)); + var newContext = new AssemblyRewriteContext(context, unityAssembly, + newAssembly); + context.AddAssemblyContext(unityAssembly.Name!, newContext); + processedAssembly = newContext; } var imports = processedAssembly.Imports; - foreach (var unityType in unityAssembly.MainModule.Types) + foreach (var unityType in unityAssembly.ManifestModule!.TopLevelTypes) ProcessType(processedAssembly, unityType, null, imports, ref typesUnstripped); } @@ -43,7 +46,7 @@ private static void ProcessType(AssemblyRewriteContext processedAssembly, TypeDe // Don't unstrip delegates, the il2cpp runtime methods are stripped and we cannot recover them if (unityType.BaseType != null && unityType.BaseType.FullName == "System.MulticastDelegate") return; - var newModule = processedAssembly.NewAssembly.MainModule; + var newModule = processedAssembly.NewAssembly.ManifestModule!; var processedType = enclosingNewType == null ? processedAssembly.TryGetTypeByName(unityType.FullName)?.NewType : enclosingNewType.NestedTypes.SingleOrDefault(it => it.Name == unityType.Name); @@ -55,12 +58,11 @@ private static void ProcessType(AssemblyRewriteContext processedAssembly, TypeDe var clonedType = CloneEnum(unityType, imports); if (enclosingNewType == null) { - newModule.Types.Add(clonedType); + newModule.TopLevelTypes.Add(clonedType); } else { enclosingNewType.NestedTypes.Add(clonedType); - clonedType.DeclaringType = enclosingNewType; } processedAssembly.RegisterTypeRewrite(new TypeRewriteContext(processedAssembly, null, clonedType)); @@ -69,18 +71,17 @@ private static void ProcessType(AssemblyRewriteContext processedAssembly, TypeDe } if (processedType == null && !unityType.IsEnum && !HasNonBlittableFields(unityType) && - !unityType.HasGenericParameters) // restore all types even if it would be not entirely correct + !unityType.HasGenericParameters()) // restore all types even if it would be not entirely correct { typesUnstripped++; - var clonedType = new TypeDefinition(unityType.Namespace, unityType.Name, ForcePublic(unityType.Attributes), unityType.BaseType == null ? null : newModule.ImportReference(unityType.BaseType)); + var clonedType = new TypeDefinition(unityType.Namespace, unityType.Name, ForcePublic(unityType.Attributes), unityType.BaseType == null ? null : newModule.DefaultImporter.ImportType(unityType.BaseType)); if (enclosingNewType == null) { - newModule.Types.Add(clonedType); + newModule.TopLevelTypes.Add(clonedType); } else { enclosingNewType.NestedTypes.Add(clonedType); - clonedType.DeclaringType = enclosingNewType; } // Unity assemblies sometimes have struct layouts on classes. @@ -102,14 +103,13 @@ private static void ProcessType(AssemblyRewriteContext processedAssembly, TypeDe private static TypeDefinition CloneEnum(TypeDefinition sourceEnum, RuntimeAssemblyReferences imports) { var newType = new TypeDefinition(sourceEnum.Namespace, sourceEnum.Name, ForcePublic(sourceEnum.Attributes), - imports.Module.Enum()); + imports.Module.Enum().ToTypeDefOrRef()); foreach (var sourceEnumField in sourceEnum.Fields) { - var newField = new FieldDefinition(sourceEnumField.Name, sourceEnumField.Attributes, - sourceEnumField.Name == "value__" - ? imports.Module.ImportCorlibReference(sourceEnumField.FieldType.Namespace, - sourceEnumField.FieldType.Name) - : newType); + TypeSignature fieldType = sourceEnumField.Name == "value__" + ? imports.Module.ImportCorlibReference(sourceEnumField.Signature!.FieldType.FullName) + : newType.ToTypeSignature(); + var newField = new FieldDefinition(sourceEnumField.Name, sourceEnumField.Attributes, new FieldSignature(fieldType)); newField.Constant = sourceEnumField.Constant; newType.Fields.Add(newField); } @@ -121,15 +121,17 @@ private static bool HasNonBlittableFields(TypeDefinition type) { if (!type.IsValueType) return false; + var typeSignature = type.ToTypeSignature(); foreach (var fieldDefinition in type.Fields) { - if (fieldDefinition.IsStatic || fieldDefinition.FieldType == type) continue; + if (fieldDefinition.IsStatic || SignatureComparer.Default.Equals(fieldDefinition.Signature?.FieldType, typeSignature)) + continue; - if (!fieldDefinition.FieldType.IsValueType) + if (!fieldDefinition.Signature!.FieldType.IsValueType) return true; - if (fieldDefinition.FieldType.Namespace.StartsWith("System") && - HasNonBlittableFields(fieldDefinition.FieldType.Resolve())) + if (fieldDefinition.Signature.FieldType.Namespace?.StartsWith("System") ?? false && + HasNonBlittableFields(fieldDefinition.Signature.FieldType.Resolve())) return true; } diff --git a/Il2CppInterop.Generator/Passes/Pass80UnstripFields.cs b/Il2CppInterop.Generator/Passes/Pass80UnstripFields.cs index 4c98207c..4c9dcf1a 100644 --- a/Il2CppInterop.Generator/Passes/Pass80UnstripFields.cs +++ b/Il2CppInterop.Generator/Passes/Pass80UnstripFields.cs @@ -1,7 +1,9 @@ +using AsmResolver.DotNet; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Common; using Il2CppInterop.Generator.Contexts; +using Il2CppInterop.Generator.Extensions; using Microsoft.Extensions.Logging; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -14,11 +16,11 @@ public static void DoPass(RewriteGlobalContext context) foreach (var unityAssembly in context.UnityAssemblies.Assemblies) { - var processedAssembly = context.TryGetAssemblyByName(unityAssembly.Name.Name); + var processedAssembly = context.TryGetAssemblyByName(unityAssembly.Name); if (processedAssembly == null) continue; var imports = processedAssembly.Imports; - foreach (var unityType in unityAssembly.MainModule.Types) + foreach (var unityType in unityAssembly.ManifestModule!.TopLevelTypes) { var processedType = processedAssembly.TryGetTypeByName(unityType.FullName); if (processedType == null) continue; @@ -28,25 +30,25 @@ public static void DoPass(RewriteGlobalContext context) foreach (var unityField in unityType.Fields) { - if (unityField.IsStatic && !unityField.HasConstant) continue; + if (unityField.IsStatic && !unityField.HasConstant()) continue; if (processedType.NewType.IsExplicitLayout && !unityField.IsStatic) continue; var processedField = processedType.TryGetFieldByUnityAssemblyField(unityField); if (processedField != null) continue; var fieldType = - Pass80UnstripMethods.ResolveTypeInNewAssemblies(context, unityField.FieldType, imports); + Pass80UnstripMethods.ResolveTypeInNewAssemblies(context, unityField.Signature!.FieldType, imports); if (fieldType == null) { - Logger.Instance.LogTrace("Field {UnityField} on type {UnityType} has unsupported type {UnityFieldType}, the type will be unusable", unityField.ToString(), unityType.FullName, unityField.FieldType.ToString()); + Logger.Instance.LogTrace("Field {UnityField} on type {UnityType} has unsupported type {UnityFieldType}, the type will be unusable", unityField.ToString(), unityType.FullName, unityField.Signature.FieldType.ToString()); fieldsIgnored++; continue; } - var newField = new FieldDefinition(unityField.Name, + var newField = new FieldDefinition(unityField.Name!, (unityField.Attributes & ~FieldAttributes.FieldAccessMask) | FieldAttributes.Public, fieldType); - if (unityField.HasConstant) newField.Constant = unityField.Constant; + if (unityField.HasConstant()) newField.Constant = unityField.Constant; processedType.NewType.Fields.Add(newField); diff --git a/Il2CppInterop.Generator/Passes/Pass80UnstripMethods.cs b/Il2CppInterop.Generator/Passes/Pass80UnstripMethods.cs index d64773dc..0c56791d 100644 --- a/Il2CppInterop.Generator/Passes/Pass80UnstripMethods.cs +++ b/Il2CppInterop.Generator/Passes/Pass80UnstripMethods.cs @@ -1,9 +1,11 @@ -using System.Linq; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Common; using Il2CppInterop.Generator.Contexts; +using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; using Microsoft.Extensions.Logging; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -16,11 +18,11 @@ public static void DoPass(RewriteGlobalContext context) foreach (var unityAssembly in context.UnityAssemblies.Assemblies) { - var processedAssembly = context.TryGetAssemblyByName(unityAssembly.Name.Name); + var processedAssembly = context.TryGetAssemblyByName(unityAssembly.Name); if (processedAssembly == null) continue; var imports = processedAssembly.Imports; - foreach (var unityType in unityAssembly.MainModule.Types) + foreach (var unityType in unityAssembly.ManifestModule!.TopLevelTypes) { var processedType = processedAssembly.TryGetTypeByName(unityType.FullName); if (processedType == null) continue; @@ -28,24 +30,26 @@ public static void DoPass(RewriteGlobalContext context) foreach (var unityMethod in unityType.Methods) { var isICall = (unityMethod.ImplAttributes & MethodImplAttributes.InternalCall) != 0; - if (unityMethod.Name == ".cctor" || unityMethod.Name == ".ctor") continue; + if (unityMethod.IsConstructor) continue; if (unityMethod.IsAbstract) continue; - if (!unityMethod.HasBody && !isICall) continue; // CoreCLR chokes on no-body methods + if (!unityMethod.HasMethodBody && !isICall) continue; // CoreCLR chokes on no-body methods var processedMethod = processedType.TryGetMethodByUnityAssemblyMethod(unityMethod); if (processedMethod != null) continue; - var returnType = ResolveTypeInNewAssemblies(context, unityMethod.ReturnType, imports); + var returnType = ResolveTypeInNewAssemblies(context, unityMethod.Signature!.ReturnType, imports); if (returnType == null) { - Logger.Instance.LogTrace("Method {UnityMethod} has unsupported return type {UnityMethodReturnType}", unityMethod.ToString(), unityMethod.ReturnType.ToString()); + Logger.Instance.LogTrace("Method {UnityMethod} has unsupported return type {UnityMethodReturnType}", unityMethod.ToString(), unityMethod.Signature.ReturnType.ToString()); methodsIgnored++; continue; } + var newAttributes = (unityMethod.Attributes & ~MethodAttributes.MemberAccessMask) | MethodAttributes.Public; var newMethod = new MethodDefinition(unityMethod.Name, - (unityMethod.Attributes & ~MethodAttributes.MemberAccessMask) | MethodAttributes.Public, - returnType); + newAttributes, + MethodSignatureCreator.CreateMethodSignature(newAttributes, returnType, unityMethod.Signature.GenericParameterCount)); + newMethod.CilMethodBody = new(newMethod); var hadBadParameter = false; foreach (var unityMethodParameter in unityMethod.Parameters) { @@ -58,8 +62,7 @@ public static void DoPass(RewriteGlobalContext context) break; } - newMethod.Parameters.Add(new ParameterDefinition(unityMethodParameter.Name, - unityMethodParameter.Attributes, convertedType)); + newMethod.AddParameter(convertedType, unityMethodParameter.Name, unityMethodParameter.Definition?.Attributes ?? default); } if (hadBadParameter) @@ -70,17 +73,17 @@ public static void DoPass(RewriteGlobalContext context) foreach (var unityMethodGenericParameter in unityMethod.GenericParameters) { - var newParameter = new GenericParameter(unityMethodGenericParameter.Name, newMethod); + var newParameter = new GenericParameter(unityMethodGenericParameter.Name); newParameter.Attributes = unityMethodGenericParameter.Attributes; foreach (var genericParameterConstraint in unityMethodGenericParameter.Constraints) { - if (genericParameterConstraint.ConstraintType.FullName == "System.ValueType") continue; - if (genericParameterConstraint.ConstraintType.Resolve().IsInterface) continue; + if (genericParameterConstraint.Constraint?.FullName == "System.ValueType") continue; + if (genericParameterConstraint.Constraint?.Resolve()?.IsInterface ?? false) continue; - var newType = ResolveTypeInNewAssemblies(context, genericParameterConstraint.ConstraintType, + var newType = ResolveTypeInNewAssemblies(context, genericParameterConstraint.Constraint?.ToTypeSignature(), imports); if (newType != null) - newParameter.Constraints.Add(new GenericParameterConstraint(newType)); + newParameter.Constraints.Add(new GenericParameterConstraint(newType.ToTypeDefOrRef())); } newMethod.GenericParameters.Add(newParameter); @@ -91,7 +94,6 @@ public static void DoPass(RewriteGlobalContext context) var delegateType = UnstripGenerator.CreateDelegateTypeForICallMethod(unityMethod, newMethod, imports); processedType.NewType.NestedTypes.Add(delegateType); - delegateType.DeclaringType = processedType.NewType; processedType.NewType.Methods.Add(newMethod); @@ -106,10 +108,16 @@ public static void DoPass(RewriteGlobalContext context) processedType.NewType.Methods.Add(newMethod); } - if (unityMethod.IsGetter) - GetOrCreateProperty(unityMethod, newMethod).GetMethod = newMethod; - else if (unityMethod.IsSetter) - GetOrCreateProperty(unityMethod, newMethod).SetMethod = newMethod; + if (unityMethod.IsGetMethod) + { + var property = GetOrCreateProperty(unityMethod, newMethod); + property.GetMethod = newMethod; + } + else if (unityMethod.IsSetMethod) + { + var property = GetOrCreateProperty(unityMethod, newMethod); + property.SetMethod = newMethod; + } var paramsMethod = context.CreateParamsMethod(unityMethod, newMethod, imports, type => ResolveTypeInNewAssemblies(context, type, imports)); @@ -127,41 +135,56 @@ public static void DoPass(RewriteGlobalContext context) private static PropertyDefinition GetOrCreateProperty(MethodDefinition unityMethod, MethodDefinition newMethod) { var unityProperty = - unityMethod.DeclaringType.Properties.Single( + unityMethod.DeclaringType!.Properties.Single( it => it.SetMethod == unityMethod || it.GetMethod == unityMethod); - var newProperty = newMethod.DeclaringType.Properties.SingleOrDefault(it => - it.Name == unityProperty.Name && it.Parameters.Count == unityProperty.Parameters.Count && - it.Parameters.SequenceEqual(unityProperty.Parameters, new TypeComparer())); + var newProperty = newMethod.DeclaringType?.Properties.SingleOrDefault(it => + it.Name == unityProperty.Name && it.Signature!.ParameterTypes.Count == unityProperty.Signature!.ParameterTypes.Count && + it.Signature.ParameterTypes.SequenceEqual(unityProperty.Signature.ParameterTypes, SignatureComparer.Default)); if (newProperty == null) { - newProperty = new PropertyDefinition(unityProperty.Name, PropertyAttributes.None, - unityMethod.IsGetter ? newMethod.ReturnType : newMethod.Parameters.Last().ParameterType); - newMethod.DeclaringType.Properties.Add(newProperty); + TypeSignature propertyType; + IEnumerable parameterTypes; + if (unityMethod.IsGetMethod) + { + propertyType = newMethod.Signature!.ReturnType; + parameterTypes = newMethod.Signature.ParameterTypes; + } + else + { + propertyType = newMethod.Signature!.ParameterTypes.Last(); + parameterTypes = newMethod.Signature.ParameterTypes.Take(newMethod.Signature.ParameterTypes.Count - 1); + } + + var propertySignature = unityProperty.Signature!.HasThis + ? PropertySignature.CreateInstance(propertyType, parameterTypes) + : PropertySignature.CreateStatic(propertyType, parameterTypes); + newProperty = new PropertyDefinition(unityProperty.Name, unityProperty.Attributes, propertySignature); + newMethod.DeclaringType!.Properties.Add(newProperty); } return newProperty; } - internal static TypeReference? ResolveTypeInNewAssemblies(RewriteGlobalContext context, TypeReference unityType, + internal static TypeSignature? ResolveTypeInNewAssemblies(RewriteGlobalContext context, TypeSignature? unityType, RuntimeAssemblyReferences imports) { var resolved = ResolveTypeInNewAssembliesRaw(context, unityType, imports); - return resolved != null ? imports.Module.ImportReference(resolved) : null; + return resolved != null ? imports.Module.DefaultImporter.ImportTypeSignature(resolved) : null; } - internal static TypeReference? ResolveTypeInNewAssembliesRaw(RewriteGlobalContext context, TypeReference unityType, + internal static TypeSignature? ResolveTypeInNewAssembliesRaw(RewriteGlobalContext context, TypeSignature? unityType, RuntimeAssemblyReferences imports) { - if (unityType is ByReferenceType) + if (unityType is null or GenericParameterSignature) + return null; + + if (unityType is ByReferenceTypeSignature) { var resolvedElementType = ResolveTypeInNewAssemblies(context, unityType.GetElementType(), imports); - return resolvedElementType == null ? null : new ByReferenceType(resolvedElementType); + return resolvedElementType == null ? null : new ByReferenceTypeSignature(resolvedElementType); } - if (unityType is GenericParameter) - return null; - - if (unityType is ArrayType arrayType) + if (unityType is ArrayBaseTypeSignature arrayType) { if (arrayType.Rank != 1) return null; var resolvedElementType = ResolveTypeInNewAssemblies(context, unityType.GetElementType(), imports); @@ -171,81 +194,63 @@ private static PropertyDefinition GetOrCreateProperty(MethodDefinition unityMeth var genericBase = resolvedElementType.IsValueType ? imports.Il2CppStructArray : imports.Il2CppReferenceArray; - return new GenericInstanceType(genericBase) { GenericArguments = { resolvedElementType } }; + return new GenericInstanceTypeSignature(genericBase.ToTypeDefOrRef(), false, resolvedElementType); } if (unityType.DeclaringType != null) { - var enclosingResolvedType = ResolveTypeInNewAssembliesRaw(context, unityType.DeclaringType, imports); + var enclosingResolvedType = ResolveTypeInNewAssembliesRaw(context, unityType.DeclaringType.ToTypeSignature(), imports); if (enclosingResolvedType == null) return null; - var resolvedNestedType = enclosingResolvedType.Resolve().NestedTypes + var resolvedNestedType = enclosingResolvedType.Resolve()!.NestedTypes .FirstOrDefault(it => it.Name == unityType.Name); - if (resolvedNestedType == null) return null; - return resolvedNestedType; + + return resolvedNestedType?.ToTypeSignature(); } - if (unityType is PointerType) + if (unityType is PointerTypeSignature) { var resolvedElementType = ResolveTypeInNewAssemblies(context, unityType.GetElementType(), imports); - return resolvedElementType == null ? null : new PointerType(resolvedElementType); + return resolvedElementType?.MakePointerType(); } - if (unityType is GenericInstanceType genericInstance) + if (unityType is GenericInstanceTypeSignature genericInstance) { - var baseRef = ResolveTypeInNewAssembliesRaw(context, genericInstance.ElementType, imports); + var baseRef = ResolveTypeInNewAssembliesRaw(context, genericInstance.GenericType.ToTypeSignature(), imports); if (baseRef == null) return null; - var newInstance = new GenericInstanceType(baseRef); - foreach (var unityGenericArgument in genericInstance.GenericArguments) + var newInstance = new GenericInstanceTypeSignature(baseRef.ToTypeDefOrRef(), baseRef.IsValueType); + foreach (var unityGenericArgument in genericInstance.TypeArguments) { var resolvedArgument = ResolveTypeInNewAssemblies(context, unityGenericArgument, imports); if (resolvedArgument == null) return null; - newInstance.GenericArguments.Add(resolvedArgument); + newInstance.TypeArguments.Add(resolvedArgument); } return newInstance; } - var targetAssemblyName = unityType.Scope.Name; + 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.Namespace, unityType.Name); + return imports.Module.ImportCorlibReference(unityType.FullName); if (targetAssemblyName == "UnityEngine") foreach (var assemblyRewriteContext in context.Assemblies) { - if (!assemblyRewriteContext.NewAssembly.Name.Name.StartsWith("UnityEngine")) continue; + if (!assemblyRewriteContext.NewAssembly.Name.StartsWith("UnityEngine")) + continue; var newTypeInAnyUnityAssembly = assemblyRewriteContext.TryGetTypeByName(unityType.FullName)?.NewType; if (newTypeInAnyUnityAssembly != null) - return newTypeInAnyUnityAssembly; + return newTypeInAnyUnityAssembly.ToTypeSignature(); } var targetAssembly = context.TryGetAssemblyByName(targetAssemblyName); - var newType = targetAssembly?.TryGetTypeByName(unityType.FullName)?.NewType; + var newType = targetAssembly?.TryGetTypeByName(unityType.FullName)?.NewType.ToTypeSignature(); return newType; } - - //Stolen from: https://github.com/kremnev8/Il2CppInterop/blob/2c4a31f95f8aa6afe910aca0f8044efb80259d20/Il2CppInterop.Generator/Passes/Pass11ComputeTypeSpecifics.cs#L223 - internal sealed class TypeComparer : IEqualityComparer - { - public bool Equals(ParameterDefinition x, ParameterDefinition y) - { - if (x == null) - return y == null; - if (y == null) - return false; - - return x.ParameterType.FullName.Equals(y.ParameterType.FullName); - } - - public int GetHashCode(ParameterDefinition obj) - { - return obj.ParameterType.FullName.GetHashCode(); - } - } } diff --git a/Il2CppInterop.Generator/Passes/Pass81FillUnstrippedMethodBodies.cs b/Il2CppInterop.Generator/Passes/Pass81FillUnstrippedMethodBodies.cs index eadd4df7..ffcef3a1 100644 --- a/Il2CppInterop.Generator/Passes/Pass81FillUnstrippedMethodBodies.cs +++ b/Il2CppInterop.Generator/Passes/Pass81FillUnstrippedMethodBodies.cs @@ -1,9 +1,8 @@ -using System.Collections.Generic; +using AsmResolver.DotNet; using Il2CppInterop.Common; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Utils; using Microsoft.Extensions.Logging; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; diff --git a/Il2CppInterop.Generator/Passes/Pass89GenerateForwarders.cs b/Il2CppInterop.Generator/Passes/Pass89GenerateForwarders.cs index 3168ce71..70b77aee 100644 --- a/Il2CppInterop.Generator/Passes/Pass89GenerateForwarders.cs +++ b/Il2CppInterop.Generator/Passes/Pass89GenerateForwarders.cs @@ -1,7 +1,9 @@ +using AsmResolver.DotNet; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Common; using Il2CppInterop.Generator.Contexts; +using Il2CppInterop.Generator.Extensions; using Microsoft.Extensions.Logging; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -16,22 +18,21 @@ public static void DoPass(RewriteGlobalContext context) return; } - var targetModule = targetAssembly.NewAssembly.MainModule; + var targetModule = targetAssembly.NewAssembly.ManifestModule; foreach (var assemblyRewriteContext in context.Assemblies) { - if (!assemblyRewriteContext.NewAssembly.Name.Name.StartsWith("UnityEngine.")) continue; - foreach (var mainModuleType in assemblyRewriteContext.NewAssembly.MainModule.Types) + if (!assemblyRewriteContext.NewAssembly.Name.StartsWith("UnityEngine.")) continue; + foreach (var mainModuleType in assemblyRewriteContext.NewAssembly.ManifestModule!.TopLevelTypes) { if (mainModuleType.Name == "") continue; - var importedType = targetModule.ImportReference(mainModuleType); - var exportedType = - new ExportedType(mainModuleType.Namespace, mainModuleType.Name, importedType.Module, - importedType.Scope) - { Attributes = TypeAttributes.Forwarder }; - targetModule.ExportedTypes.Add(exportedType); + var exportedType = new ExportedType(null, mainModuleType.Namespace, mainModuleType.Name) + { + Attributes = TypeAttributes.Forwarder + }; + targetModule!.ExportedTypes.Add(exportedType); AddNestedTypes(mainModuleType, exportedType, targetModule); } @@ -45,11 +46,12 @@ private static void AddNestedTypes(TypeDefinition mainModuleType, ExportedType i { if ((nested.Attributes & TypeAttributes.VisibilityMask) != TypeAttributes.NestedPublic) continue; - var nestedImport = targetModule.ImportReference(nested); - var nestedExport = - new ExportedType(nestedImport.Namespace, nestedImport.Name, nestedImport.Module, nestedImport.Scope) - { Attributes = TypeAttributes.Forwarder }; - nestedExport.DeclaringType = importedType; + var nestedImport = targetModule.DefaultImporter.ImportType(nested); + var nestedExport = new ExportedType(importedType, nestedImport.Namespace, nestedImport.Name) + { + Attributes = TypeAttributes.Forwarder + }; + targetModule.ExportedTypes.Add(nestedExport); AddNestedTypes(nested, nestedExport, targetModule); diff --git a/Il2CppInterop.Generator/Passes/Pass89GenerateMethodXrefCache.cs b/Il2CppInterop.Generator/Passes/Pass89GenerateMethodXrefCache.cs index d54ec593..4ee5a9ab 100644 --- a/Il2CppInterop.Generator/Passes/Pass89GenerateMethodXrefCache.cs +++ b/Il2CppInterop.Generator/Passes/Pass89GenerateMethodXrefCache.cs @@ -1,12 +1,11 @@ -using System.Collections.Generic; -using System.IO; using System.Text; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; using Il2CppInterop.Common.Attributes; using Il2CppInterop.Common.Maps; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -22,7 +21,7 @@ public static void DoPass(RewriteGlobalContext context, GeneratorOptions options foreach (var assemblyRewriteContext in context.Assemblies) { - if (options.AdditionalAssembliesBlacklist.Contains(assemblyRewriteContext.NewAssembly.Name.Name)) + if (options.AdditionalAssembliesBlacklist.Contains(assemblyRewriteContext.NewAssembly.Name!)) continue; var imports = assemblyRewriteContext.Imports; @@ -35,30 +34,39 @@ public static void DoPass(RewriteGlobalContext context, GeneratorOptions options if (existingAttributesPerAddress.TryGetValue(address, out var attribute)) { methodRewriteContext.NewMethod.CustomAttributes.Add( - new CustomAttribute(imports.CachedScanResultsAttributector.Value) - { - Fields = - { + new CustomAttribute((ICustomAttributeType?)imports.CachedScanResultsAttributector.Value, new CustomAttributeSignature([], + [ new CustomAttributeNamedArgument( + CustomAttributeArgumentMemberType.Field, nameof(CachedScanResultsAttribute.RefRangeStart), + imports.Module.Int(), new CustomAttributeArgument(imports.Module.Int(), attribute.RefRangeStart)), new CustomAttributeNamedArgument( + CustomAttributeArgumentMemberType.Field, nameof(CachedScanResultsAttribute.RefRangeEnd), + imports.Module.Int(), new CustomAttributeArgument(imports.Module.Int(), attribute.RefRangeEnd)), new CustomAttributeNamedArgument( + CustomAttributeArgumentMemberType.Field, nameof(CachedScanResultsAttribute.XrefRangeStart), + imports.Module.Int(), new CustomAttributeArgument(imports.Module.Int(), attribute.RefRangeStart)), new CustomAttributeNamedArgument( + CustomAttributeArgumentMemberType.Field, nameof(CachedScanResultsAttribute.XrefRangeEnd), + imports.Module.Int(), new CustomAttributeArgument(imports.Module.Int(), attribute.RefRangeEnd)), new CustomAttributeNamedArgument( + CustomAttributeArgumentMemberType.Field, nameof(CachedScanResultsAttribute.MetadataInitTokenRva), + imports.Module.Long(), new CustomAttributeArgument(imports.Module.Long(), attribute.MetadataInitTokenRva)), new CustomAttributeNamedArgument( + CustomAttributeArgumentMemberType.Field, nameof(CachedScanResultsAttribute.MetadataInitFlagRva), + imports.Module.Long(), new CustomAttributeArgument(imports.Module.Long(), attribute.MetadataInitFlagRva)) - } - }); + ]))); continue; } @@ -85,32 +93,39 @@ public static void DoPass(RewriteGlobalContext context, GeneratorOptions options if (xrefEnd != xrefStart || refStart != refEnd) { methodRewriteContext.NewMethod.CustomAttributes.Add( - new CustomAttribute(imports.CachedScanResultsAttributector.Value) - { - Fields = - { + new CustomAttribute((ICustomAttributeType?)imports.CachedScanResultsAttributector.Value, new CustomAttributeSignature([], + [ new CustomAttributeNamedArgument( + CustomAttributeArgumentMemberType.Field, nameof(CachedScanResultsAttribute.RefRangeStart), + imports.Module.Int(), new CustomAttributeArgument(imports.Module.Int(), refStart)), new CustomAttributeNamedArgument( + CustomAttributeArgumentMemberType.Field, nameof(CachedScanResultsAttribute.RefRangeEnd), + imports.Module.Int(), new CustomAttributeArgument(imports.Module.Int(), refEnd)), new CustomAttributeNamedArgument( + CustomAttributeArgumentMemberType.Field, nameof(CachedScanResultsAttribute.XrefRangeStart), + imports.Module.Int(), new CustomAttributeArgument(imports.Module.Int(), xrefStart)), new CustomAttributeNamedArgument( + CustomAttributeArgumentMemberType.Field, nameof(CachedScanResultsAttribute.XrefRangeEnd), + imports.Module.Int(), new CustomAttributeArgument(imports.Module.Int(), xrefEnd)), new CustomAttributeNamedArgument( + CustomAttributeArgumentMemberType.Field, nameof(CachedScanResultsAttribute.MetadataInitTokenRva), - new CustomAttributeArgument(imports.Module.Long(), - methodRewriteContext.MetadataInitTokenRva)), + imports.Module.Long(), + new CustomAttributeArgument(imports.Module.Long(), methodRewriteContext.MetadataInitTokenRva)), new CustomAttributeNamedArgument( + CustomAttributeArgumentMemberType.Field, nameof(CachedScanResultsAttribute.MetadataInitFlagRva), - new CustomAttributeArgument(imports.Module.Long(), - methodRewriteContext.MetadataInitFlagRva)) - } - }); + imports.Module.Long(), + new CustomAttributeArgument(imports.Module.Long(), methodRewriteContext.MetadataInitFlagRva)) + ]))); existingAttributesPerAddress[address] = new CachedScanResultsAttribute { diff --git a/Il2CppInterop.Generator/Passes/Pass90WriteToDisk.cs b/Il2CppInterop.Generator/Passes/Pass90WriteToDisk.cs index 8886a9c4..b8ad65fa 100644 --- a/Il2CppInterop.Generator/Passes/Pass90WriteToDisk.cs +++ b/Il2CppInterop.Generator/Passes/Pass90WriteToDisk.cs @@ -1,7 +1,10 @@ -using System.Reflection; +using System.Runtime.Versioning; +using AsmResolver; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Builder; +using AsmResolver.DotNet.Signatures; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Utils; -using Mono.Cecil; namespace Il2CppInterop.Generator.Passes; @@ -9,39 +12,60 @@ public static class Pass90WriteToDisk { public static void DoPass(RewriteGlobalContext context, GeneratorOptions options) { - var registerMethod = - typeof(DefaultAssemblyResolver).GetMethod("RegisterAssembly", - BindingFlags.Instance | BindingFlags.NonPublic); + var targetAttributeConstructor = typeof(TargetFrameworkAttribute).GetConstructor([typeof(string)]); + foreach (var asmContext in context.Assemblies) { - var module = asmContext.NewAssembly.MainModule; - if (module.AssemblyResolver is DefaultAssemblyResolver resolver) + var module = asmContext.NewAssembly.ManifestModule!; + + // Rewrite corlib references. + foreach (var reference in module.AssemblyReferences) + { + // System.Private.CoreLib needs rewriting because references can get created during the rewrite process. + // mscorlib and netstandard are included for completeness. + if (reference.Name?.Value is "System.Private.CoreLib" or "mscorlib" or "netstandard") + { + CorlibReferences.RewriteCorlibReference(reference); + continue; + } + } + + // Add TargetFrameworkAttribute to the assembly. + { + var importedConstructor = (ICustomAttributeType)module.DefaultImporter.ImportMethod(targetAttributeConstructor); + + CustomAttribute targetFrameworkAttribute = new(importedConstructor, new()); + + CustomAttributeArgument fixedArgument = new(module.CorLibTypeFactory.String, module.OriginalTargetRuntime.ToString()); + targetFrameworkAttribute.Signature!.FixedArguments.Add(fixedArgument); + + CustomAttributeNamedArgument namedArgument = new( + CustomAttributeArgumentMemberType.Property, + nameof(TargetFrameworkAttribute.FrameworkDisplayName), + module.CorLibTypeFactory.String, + new(module.CorLibTypeFactory.String, CorlibReferences.TargetFrameworkName)); + targetFrameworkAttribute.Signature.NamedArguments.Add(namedArgument); + + asmContext.NewAssembly.CustomAttributes.Add(targetFrameworkAttribute); + } + + // Optimize macros in all methods. + foreach (var type in module.GetAllTypes()) { - foreach (var reference in module.AssemblyReferences) + foreach (var method in type.Methods) { - // TODO: Instead of a hack, set correctly initially via source generator - if (reference.Name == "System.Private.CoreLib") - { - CorlibReferences.RewriteReferenceToMscorlib(reference); - continue; - } - - var match = context.Assemblies.FirstOrDefault(f => f.NewAssembly.FullName == reference.FullName); - if (match != null) - { - registerMethod!.Invoke(resolver, new object[] { match.NewAssembly }); - } + method.CilMethodBody?.Instructions.OptimizeMacros(); } } } var assembliesToProcess = context.Assemblies - .Where(it => !options.AdditionalAssembliesBlacklist.Contains(it.NewAssembly.Name.Name)); + .Where(it => !options.AdditionalAssembliesBlacklist.Contains(it.NewAssembly.Name!)); void Processor(AssemblyRewriteContext assemblyContext) { assemblyContext.NewAssembly.Write( - Path.Combine(options.OutputDir ?? ".", $"{assemblyContext.NewAssembly.Name.Name}.dll")); + Path.Combine(options.OutputDir ?? ".", $"{assemblyContext.NewAssembly.Name}.dll"), new ManagedPEImageBuilder(ThrowErrorListener.Instance)); } if (options.Parallel) diff --git a/Il2CppInterop.Generator/Passes/Pass91GenerateMethodPointerMap.cs b/Il2CppInterop.Generator/Passes/Pass91GenerateMethodPointerMap.cs index 4092678d..7d501591 100644 --- a/Il2CppInterop.Generator/Passes/Pass91GenerateMethodPointerMap.cs +++ b/Il2CppInterop.Generator/Passes/Pass91GenerateMethodPointerMap.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; -using System.IO; using System.Reflection; using System.Text; using Il2CppInterop.Common.Maps; @@ -17,7 +15,7 @@ public static void DoPass(RewriteGlobalContext context, GeneratorOptions options foreach (var assemblyRewriteContext in context.Assemblies) { - if (options.AdditionalAssembliesBlacklist.Contains(assemblyRewriteContext.NewAssembly.Name.Name)) + if (options.AdditionalAssembliesBlacklist.Contains(assemblyRewriteContext.NewAssembly.Name!)) continue; assemblyList.Add(assemblyRewriteContext.NewAssembly.FullName); diff --git a/Il2CppInterop.Generator/Runners/DeobfuscationAnalyzer.cs b/Il2CppInterop.Generator/Runners/DeobfuscationAnalyzer.cs index d164cd77..2c5b465c 100644 --- a/Il2CppInterop.Generator/Runners/DeobfuscationAnalyzer.cs +++ b/Il2CppInterop.Generator/Runners/DeobfuscationAnalyzer.cs @@ -1,6 +1,4 @@ -using System; -using System.Linq; -using Il2CppInterop.Generator.Contexts; +using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.MetadataAccess; using Il2CppInterop.Generator.Passes; using Il2CppInterop.Generator.Utils; @@ -25,7 +23,7 @@ public void Run(GeneratorOptions options) IIl2CppMetadataAccess inputAssemblies; using (new TimingCookie("Reading assemblies")) { - inputAssemblies = new CecilMetadataAccess(options.Source); + inputAssemblies = new AssemblyMetadataAccess(options.Source ?? throw new ArgumentException("Source assemblies must be provided.", nameof(options))); } using (new TimingCookie("Creating assembly contexts")) diff --git a/Il2CppInterop.Generator/Runners/DeobfuscationMapGenerator.cs b/Il2CppInterop.Generator/Runners/DeobfuscationMapGenerator.cs index b60d8cb9..e6a5e28b 100644 --- a/Il2CppInterop.Generator/Runners/DeobfuscationMapGenerator.cs +++ b/Il2CppInterop.Generator/Runners/DeobfuscationMapGenerator.cs @@ -1,9 +1,8 @@ -using System; -using System.Collections.Generic; -using System.IO; using System.IO.Compression; -using System.Linq; using System.Text; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Common; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; @@ -11,7 +10,6 @@ using Il2CppInterop.Generator.Passes; using Il2CppInterop.Generator.Utils; using Microsoft.Extensions.Logging; -using Mono.Cecil; namespace Il2CppInterop.Generator.Runners; @@ -53,7 +51,7 @@ public void Run(GeneratorOptions options) using (new TimingCookie("Reading assemblies")) { inputAssemblies = - new CecilMetadataAccess(Directory.EnumerateFiles(options.DeobfuscationNewAssembliesPath, "*.dll")); + new AssemblyMetadataAccess(Directory.EnumerateFiles(options.DeobfuscationNewAssembliesPath, "*.dll")); } using (new TimingCookie("Creating rewrite assemblies")) @@ -96,7 +94,7 @@ public void Run(GeneratorOptions options) IIl2CppMetadataAccess cleanAssemblies; using (new TimingCookie("Reading clean assemblies")) { - cleanAssemblies = new CecilMetadataAccess(options.Source); + cleanAssemblies = new AssemblyMetadataAccess(options.Source); } using (new TimingCookie("Creating clean rewrite assemblies")) @@ -140,10 +138,10 @@ void DoEnum(TypeRewriteContext obfuscatedType, TypeRewriteContext cleanType) foreach (var assemblyContext in rewriteContext.Assemblies) { if (options.DeobfuscationGenerationAssemblies.Count > 0 && - !options.DeobfuscationGenerationAssemblies.Contains(assemblyContext.NewAssembly.Name.Name)) + !options.DeobfuscationGenerationAssemblies.Contains(assemblyContext.NewAssembly.Name!)) continue; - var cleanAssembly = cleanContext.GetAssemblyByName(assemblyContext.OriginalAssembly.Name.Name); + var cleanAssembly = cleanContext.GetAssemblyByName(assemblyContext.OriginalAssembly.Name!); void DoType(TypeRewriteContext typeContext, TypeRewriteContext? enclosingType) { @@ -196,7 +194,7 @@ private static (TypeRewriteContext?, int) FindBestMatchType(TypeRewriteContext o { if (currentBase == null) break; var currentBaseContext = - obfType.AssemblyContext.GlobalContext.TryGetNewTypeForOriginal(currentBase.Resolve()); + obfType.AssemblyContext.GlobalContext.TryGetNewTypeForOriginal(currentBase.Resolve()!); if (currentBaseContext == null || !currentBaseContext.OriginalNameWasObfuscated) break; inheritanceDepthOfOriginal++; @@ -213,10 +211,10 @@ private static (TypeRewriteContext?, int) FindBestMatchType(TypeRewriteContext o foreach (var candidateCleanType in source) { - if (obfType.OriginalType.HasMethods != candidateCleanType.OriginalType.HasMethods) + if (obfType.OriginalType.HasMethods() != candidateCleanType.OriginalType.HasMethods()) continue; - if (obfType.OriginalType.HasFields != candidateCleanType.OriginalType.HasFields) + if (obfType.OriginalType.HasFields() != candidateCleanType.OriginalType.HasFields()) continue; if (obfType.OriginalType.IsEnum) @@ -232,7 +230,7 @@ private static (TypeRewriteContext?, int) FindBestMatchType(TypeRewriteContext o if (tryBase?.Name == currentBase?.Name && tryBase?.Namespace == currentBase?.Namespace) break; - tryBase = tryBase?.Resolve().BaseType; + tryBase = tryBase?.Resolve()?.BaseType; actualBaseDepth++; } @@ -262,7 +260,7 @@ private static (TypeRewriteContext?, int) FindBestMatchType(TypeRewriteContext o if (obfuscatedField.Name.IsObfuscated(options)) { var bestFieldScore = candidateCleanType.OriginalType.Fields.Max(it => - TypeMatchWeight(obfuscatedField.FieldType, it.FieldType, options)); + TypeMatchWeight(obfuscatedField.Signature!.FieldType, it.Signature!.FieldType, options)); currentPenalty += bestFieldScore * (bestFieldScore < 0 ? 10 : 2); continue; } @@ -273,7 +271,7 @@ private static (TypeRewriteContext?, int) FindBestMatchType(TypeRewriteContext o foreach (var obfuscatedMethod in obfType.OriginalType.Methods) { - if (obfuscatedMethod.Name.Contains(".ctor")) continue; + if (obfuscatedMethod.IsConstructor) continue; if (obfuscatedMethod.Name.IsObfuscated(options)) { @@ -285,7 +283,7 @@ private static (TypeRewriteContext?, int) FindBestMatchType(TypeRewriteContext o } if (candidateCleanType.OriginalType.Methods.Any(it => it.Name == obfuscatedMethod.Name)) - currentPenalty += obfuscatedMethod.Name.Length / 10 * 5 + 1; + currentPenalty += (obfuscatedMethod.Name?.Length ?? 0) / 10 * 5 + 1; } if (currentPenalty == bestPenalty) @@ -305,7 +303,7 @@ private static (TypeRewriteContext?, int) FindBestMatchType(TypeRewriteContext o return (bestMatch, bestPenalty); } - private static int TypeMatchWeight(TypeReference a, TypeReference b, GeneratorOptions options) + private static int TypeMatchWeight(TypeSignature a, TypeSignature b, GeneratorOptions options) { if (a.GetType() != b.GetType()) return -1; @@ -322,36 +320,36 @@ void Accumulate(int i) switch (a) { - case ArrayType arr: - if (!(b is ArrayType brr)) + case ArrayBaseTypeSignature arr: + if (b is not ArrayBaseTypeSignature brr) return -1; - return TypeMatchWeight(arr.ElementType, brr.ElementType, options) * 5; - case ByReferenceType abr: - if (!(b is ByReferenceType bbr)) + return TypeMatchWeight(arr.BaseType, brr.BaseType, options) * 5; + case ByReferenceTypeSignature abr: + if (b is not ByReferenceTypeSignature bbr) return -1; - return TypeMatchWeight(abr.ElementType, bbr.ElementType, options) * 5; - case GenericInstanceType agi: - if (!(b is GenericInstanceType bgi)) + return TypeMatchWeight(abr.BaseType, bbr.BaseType, options) * 5; + case GenericInstanceTypeSignature agi: + if (b is not GenericInstanceTypeSignature bgi) return -1; - if (agi.GenericArguments.Count != bgi.GenericArguments.Count) return -1; - Accumulate(TypeMatchWeight(agi.ElementType, bgi.ElementType, options)); - for (var i = 0; i < agi.GenericArguments.Count; i++) - Accumulate(TypeMatchWeight(agi.GenericArguments[i], bgi.GenericArguments[i], options)); + if (agi.TypeArguments.Count != bgi.TypeArguments.Count) return -1; + Accumulate(TypeMatchWeight(agi.GenericType.ToTypeSignature(), bgi.GenericType.ToTypeSignature(), options)); + for (var i = 0; i < agi.TypeArguments.Count; i++) + Accumulate(TypeMatchWeight(agi.TypeArguments[i], bgi.TypeArguments[i], options)); return runningSum * 5; - case GenericParameter: - if (!(b is GenericParameter)) + case GenericParameterSignature: + if (b is not GenericParameterSignature) return -1; return 5; default: - if (a.IsNested) + if (a.IsNested()) { - if (!b.IsNested) + if (!b.IsNested()) return -1; if (a.Name.IsObfuscated(options)) return 0; - var declMatch = TypeMatchWeight(a.DeclaringType, b.DeclaringType, options); + var declMatch = TypeMatchWeight(a.DeclaringType!.ToTypeSignature(), b.DeclaringType!.ToTypeSignature(), options); if (declMatch == -1 || a.Name != b.Name) return -1; @@ -371,7 +369,7 @@ private static int MethodSignatureMatchWeight(MethodDefinition a, MethodDefiniti (b.Attributes & MethodAttributes.MemberAccessMask)) return -1; - var runningSum = TypeMatchWeight(a.ReturnType, b.ReturnType, options); + var runningSum = TypeMatchWeight(a.Signature!.ReturnType, b.Signature!.ReturnType, options); if (runningSum == -1) return -1; diff --git a/Il2CppInterop.Generator/Runners/IRunner.cs b/Il2CppInterop.Generator/Runners/IRunner.cs index 5b76e1de..ad697781 100644 --- a/Il2CppInterop.Generator/Runners/IRunner.cs +++ b/Il2CppInterop.Generator/Runners/IRunner.cs @@ -1,6 +1,4 @@ -using System; - -namespace Il2CppInterop.Generator.Runners; +namespace Il2CppInterop.Generator.Runners; internal interface IRunner : IDisposable { diff --git a/Il2CppInterop.Generator/Runners/InteropAssemblyGenerator.cs b/Il2CppInterop.Generator/Runners/InteropAssemblyGenerator.cs index f380fb2b..b1c66b7c 100644 --- a/Il2CppInterop.Generator/Runners/InteropAssemblyGenerator.cs +++ b/Il2CppInterop.Generator/Runners/InteropAssemblyGenerator.cs @@ -1,7 +1,4 @@ -using System; -using System.IO; -using System.Linq; -using Il2CppInterop.Common; +using Il2CppInterop.Common; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.MetadataAccess; using Il2CppInterop.Generator.Passes; @@ -43,13 +40,13 @@ public void Run(GeneratorOptions options) using (new TimingCookie("Reading assemblies")) { - gameAssemblies = new CecilMetadataAccess(options.Source); + gameAssemblies = new AssemblyMetadataAccess(options.Source); } if (!string.IsNullOrEmpty(options.UnityBaseLibsDir)) using (new TimingCookie("Reading unity assemblies")) { - unityAssemblies = new CecilMetadataAccess(Directory.EnumerateFiles(options.UnityBaseLibsDir, "*.dll")); + unityAssemblies = new AssemblyMetadataAccess(Directory.EnumerateFiles(options.UnityBaseLibsDir, "*.dll")); } else unityAssemblies = NullMetadataAccess.Instance; diff --git a/Il2CppInterop.Generator/Usings.cs b/Il2CppInterop.Generator/Usings.cs new file mode 100644 index 00000000..5bf58772 --- /dev/null +++ b/Il2CppInterop.Generator/Usings.cs @@ -0,0 +1,3 @@ +global using ILProcessor = AsmResolver.DotNet.Code.Cil.CilInstructionCollection; +global using OpCode = AsmResolver.PE.DotNet.Cil.CilOpCode; +global using OpCodes = AsmResolver.PE.DotNet.Cil.CilOpCodes; diff --git a/Il2CppInterop.Generator/Utils/CorlibReferences.cs b/Il2CppInterop.Generator/Utils/CorlibReferences.cs index 220414d7..cf341c04 100644 --- a/Il2CppInterop.Generator/Utils/CorlibReferences.cs +++ b/Il2CppInterop.Generator/Utils/CorlibReferences.cs @@ -1,256 +1,262 @@ -using System; using System.Reflection; using System.Runtime.CompilerServices; -using Mono.Cecil; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; namespace Il2CppInterop.Generator.Utils; internal static class CorlibReferences { - public static void RewriteReferenceToMscorlib(AssemblyNameReference assemblyNameReference) + /// + /// This is used in the TargetFrameworkAttribute. + /// + public static string TargetFrameworkName => ".NET 6.0"; + public static AssemblyReference TargetCorlib => KnownCorLibs.SystemRuntime_v6_0_0_0; + + public static void RewriteCorlibReference(AssemblyReference assemblyNameReference) + { + CopyValues(assemblyNameReference, TargetCorlib); + } + + private static void CopyValues(AssemblyReference target, AssemblyReference source) { - assemblyNameReference.Name = "mscorlib"; - assemblyNameReference.Version = new Version(4, 0, 0, 0); - assemblyNameReference.PublicKeyToken = new byte[] { 183, 122, 92, 86, 25, 52, 224, 137 }; - assemblyNameReference.Culture = ""; + target.Attributes = source.Attributes; + target.Culture = source.Culture; + target.DisableJitCompileOptimizer = source.DisableJitCompileOptimizer; + target.EnableJitCompileTracking = source.EnableJitCompileTracking; + target.HashValue = source.HashValue?.ToArray(); + target.HasPublicKey = source.HasPublicKey; + target.IsRetargetable = source.IsRetargetable; + target.IsWindowsRuntime = source.IsWindowsRuntime; + target.Name = source.Name; + target.PublicKeyOrToken = source.PublicKeyOrToken?.ToArray(); + target.Version = source.Version; } - public static TypeReference ImportCorlibReference(this ModuleDefinition module, string @namespace, string type) + public static TypeSignature ImportCorlibReference(this ModuleDefinition module, string fullName) { - return module.ImportReference(typeof(string).Assembly.GetType($"{@namespace}.{type}")); + return module.DefaultImporter.ImportTypeSignature(typeof(string).Assembly.GetType(fullName)); } - public static TypeReference Void(this ModuleDefinition module) + public static TypeSignature Void(this ModuleDefinition module) { - return module.ImportReference(typeof(void)); + return module.CorLibTypeFactory.Void; } - public static TypeReference Bool(this ModuleDefinition module) + public static TypeSignature Bool(this ModuleDefinition module) { - return module.ImportReference(typeof(bool)); + return module.CorLibTypeFactory.Boolean; } - public static TypeReference IntPtr(this ModuleDefinition module) + public static TypeSignature IntPtr(this ModuleDefinition module) { - return module.ImportReference(typeof(IntPtr)); + return module.CorLibTypeFactory.IntPtr; } - public static TypeReference String(this ModuleDefinition module) + public static TypeSignature String(this ModuleDefinition module) { - return module.ImportReference(typeof(string)); + return module.CorLibTypeFactory.String; } - public static TypeReference SByte(this ModuleDefinition module) + public static TypeSignature SByte(this ModuleDefinition module) { - return module.ImportReference(typeof(sbyte)); + return module.CorLibTypeFactory.SByte; } - public static TypeReference Byte(this ModuleDefinition module) + public static TypeSignature Byte(this ModuleDefinition module) { - return module.ImportReference(typeof(byte)); + return module.CorLibTypeFactory.Byte; } - public static TypeReference Short(this ModuleDefinition module) + public static TypeSignature Short(this ModuleDefinition module) { - return module.ImportReference(typeof(short)); + return module.CorLibTypeFactory.Int16; } - public static TypeReference Int(this ModuleDefinition module) + public static TypeSignature Int(this ModuleDefinition module) { - return module.ImportReference(typeof(int)); + return module.CorLibTypeFactory.Int32; } - public static TypeReference Long(this ModuleDefinition module) + public static TypeSignature Long(this ModuleDefinition module) { - return module.ImportReference(typeof(long)); + return module.CorLibTypeFactory.Int64; } - public static TypeReference UShort(this ModuleDefinition module) + public static TypeSignature UShort(this ModuleDefinition module) { - return module.ImportReference(typeof(ushort)); + return module.CorLibTypeFactory.UInt16; } - public static TypeReference UInt(this ModuleDefinition module) + public static TypeSignature UInt(this ModuleDefinition module) { - return module.ImportReference(typeof(uint)); + return module.CorLibTypeFactory.UInt32; } - public static TypeReference ULong(this ModuleDefinition module) + public static TypeSignature ULong(this ModuleDefinition module) { - return module.ImportReference(typeof(ulong)); + return module.CorLibTypeFactory.UInt64; } - public static TypeReference Float(this ModuleDefinition module) + public static TypeSignature Float(this ModuleDefinition module) { - return module.ImportReference(typeof(float)); + return module.CorLibTypeFactory.Single; } - public static TypeReference Double(this ModuleDefinition module) + public static TypeSignature Double(this ModuleDefinition module) { - return module.ImportReference(typeof(double)); + return module.CorLibTypeFactory.Double; } - public static TypeReference Char(this ModuleDefinition module) + public static TypeSignature Char(this ModuleDefinition module) { - return module.ImportReference(typeof(char)); + return module.CorLibTypeFactory.Char; } - public static TypeReference Type(this ModuleDefinition module) + public static TypeSignature Type(this ModuleDefinition module) { - return module.ImportReference(typeof(Type)); + return module.DefaultImporter.ImportTypeSignature(typeof(Type)); } - public static TypeReference Object(this ModuleDefinition module) + public static TypeSignature Object(this ModuleDefinition module) { - return module.ImportReference(typeof(object)); + return module.CorLibTypeFactory.Object; } - public static TypeReference Enum(this ModuleDefinition module) + public static TypeSignature Enum(this ModuleDefinition module) { - return module.ImportReference(typeof(Enum)); + return module.DefaultImporter.ImportTypeSignature(typeof(Enum)); } - public static TypeReference ValueType(this ModuleDefinition module) + public static TypeSignature ValueType(this ModuleDefinition module) { - return module.ImportReference(typeof(ValueType)); + return module.DefaultImporter.ImportTypeSignature(typeof(ValueType)); } - public static TypeReference Delegate(this ModuleDefinition module) + public static TypeSignature Delegate(this ModuleDefinition module) { - return module.ImportReference(typeof(Delegate)); + return module.DefaultImporter.ImportTypeSignature(typeof(Delegate)); } - public static TypeReference MulticastDelegate(this ModuleDefinition module) + public static TypeSignature MulticastDelegate(this ModuleDefinition module) { - return module.ImportReference(typeof(MulticastDelegate)); + return module.DefaultImporter.ImportTypeSignature(typeof(MulticastDelegate)); } - public static TypeReference DefaultMemberAttribute(this ModuleDefinition module) + public static TypeSignature DefaultMemberAttribute(this ModuleDefinition module) { - return module.ImportReference(typeof(DefaultMemberAttribute)); + return module.DefaultImporter.ImportTypeSignature(typeof(DefaultMemberAttribute)); } - public static TypeReference NotSupportedException(this ModuleDefinition module) + public static TypeSignature NotSupportedException(this ModuleDefinition module) { - return module.ImportReference(typeof(NotSupportedException)); + return module.DefaultImporter.ImportTypeSignature(typeof(NotSupportedException)); } - public static TypeReference FlagsAttribute(this ModuleDefinition module) + public static TypeSignature FlagsAttribute(this ModuleDefinition module) { - return module.ImportReference(typeof(FlagsAttribute)); + return module.DefaultImporter.ImportTypeSignature(typeof(FlagsAttribute)); } - public static TypeReference ObsoleteAttribute(this ModuleDefinition module) + public static TypeSignature ObsoleteAttribute(this ModuleDefinition module) { - return module.ImportReference(typeof(ObsoleteAttribute)); + return module.DefaultImporter.ImportTypeSignature(typeof(ObsoleteAttribute)); } - public static TypeReference Attribute(this ModuleDefinition module) + public static TypeSignature Attribute(this ModuleDefinition module) { - return module.ImportReference(typeof(Attribute)); + return module.DefaultImporter.ImportTypeSignature(typeof(Attribute)); } - public static TypeReference RuntimeTypeHandle(this ModuleDefinition module) + public static TypeSignature RuntimeTypeHandle(this ModuleDefinition module) { - return module.ImportReference(typeof(RuntimeTypeHandle)); + return module.DefaultImporter.ImportTypeSignature(typeof(RuntimeTypeHandle)); } - public static TypeReference ExtensionAttribute(this ModuleDefinition module) + public static TypeSignature ExtensionAttribute(this ModuleDefinition module) { - return module.ImportReference(typeof(ExtensionAttribute)); + return module.DefaultImporter.ImportTypeSignature(typeof(ExtensionAttribute)); } - public static TypeReference ParamArrayAttribute(this ModuleDefinition module) + public static TypeSignature ParamArrayAttribute(this ModuleDefinition module) { - return module.ImportReference(typeof(ParamArrayAttribute)); + return module.DefaultImporter.ImportTypeSignature(typeof(ParamArrayAttribute)); } - public static TypeReference Action(this ModuleDefinition module, int n = 0) + public static TypeSignature Action(this ModuleDefinition module, int n = 0) { return n switch { - 0 => module.ImportCorlibReference("System", "Action"), - 1 => module.ImportCorlibReference("System", "Action`1"), - _ => module.ImportCorlibReference("System", $"Action`{n}") + 0 => module.ImportCorlibReference("System.Action"), + 1 => module.ImportCorlibReference("System.Action`1"), + _ => module.ImportCorlibReference($"System.Action`{n}") }; } - public static TypeReference Func(this ModuleDefinition module, int n = 0) + public static TypeSignature Func(this ModuleDefinition module, int n = 0) { return n switch { - 0 => module.ImportCorlibReference("System", "Func`1"), - 1 => module.ImportCorlibReference("System", "Func`2"), - _ => module.ImportCorlibReference("System", $"Func`{n + 1}") + 0 => module.ImportCorlibReference("System.Func`1"), + 1 => module.ImportCorlibReference("System.Func`2"), + _ => module.ImportCorlibReference($"System.Func`{n + 1}") }; } - public static MethodReference TypeGetTypeFromHandle(this ModuleDefinition module) + public static MemberReference TypeGetTypeFromHandle(this ModuleDefinition module) { var type = module.Type(); - var mr = new MethodReference("GetTypeFromHandle", type, type) - { - HasThis = false - }; - mr.Parameters.Add(new ParameterDefinition(module.RuntimeTypeHandle())); - return mr; + MethodSignature signature = MethodSignature.CreateStatic(type, module.RuntimeTypeHandle()); + return new MemberReference(type.ToTypeDefOrRef(), nameof(System.Type.GetTypeFromHandle), signature); } - public static MethodReference TypeGetIsValueType(this ModuleDefinition module) + public static MemberReference TypeGetIsValueType(this ModuleDefinition module) { var type = module.Type(); - var mr = new MethodReference("get_IsValueType", module.Bool(), type) - { - HasThis = true - }; - return mr; + return new MemberReference(type.ToTypeDefOrRef(), "get_IsValueType", MethodSignature.CreateInstance(module.Bool())); } - public static MethodReference TypeGetFullName(this ModuleDefinition module) + public static MemberReference TypeGetFullName(this ModuleDefinition module) { var type = module.Type(); - var mr = new MethodReference("get_FullName", module.String(), type) - { - HasThis = true - }; - return mr; + return new MemberReference(type.ToTypeDefOrRef(), "get_FullName", MethodSignature.CreateInstance(module.String())); } - public static MethodReference StringEquals(this ModuleDefinition module) + public static MemberReference StringEquals(this ModuleDefinition module) { - var mr = new MethodReference("Equals", module.Bool(), module.String()) - { - HasThis = false - }; - mr.Parameters.Add(new ParameterDefinition(module.String())); - mr.Parameters.Add(new ParameterDefinition(module.String())); - return mr; + var @string = module.String(); + MethodSignature signature = MethodSignature.CreateStatic(module.Bool(), @string, @string); + return new MemberReference(@string.ToTypeDefOrRef(), nameof(string.Equals), signature); + } + + public static MemberReference ExtensionAttributeCtor(this ModuleDefinition module) + { + return MakeConstructorReference(module, module.ExtensionAttribute().ToTypeDefOrRef()); } - public static MethodReference ExtensionAttributeCtor(this ModuleDefinition module) + public static MemberReference ParamArrayAttributeCtor(this ModuleDefinition module) { - return new MethodReference(".ctor", module.Void(), module.ExtensionAttribute()) { HasThis = true }; + return MakeConstructorReference(module, module.ParamArrayAttribute().ToTypeDefOrRef()); } - public static MethodReference ParamArrayAttributeCtor(this ModuleDefinition module) + public static MemberReference FlagsAttributeCtor(this ModuleDefinition module) { - return new MethodReference(".ctor", module.Void(), module.ParamArrayAttribute()) { HasThis = true }; + return MakeConstructorReference(module, module.FlagsAttribute().ToTypeDefOrRef()); } - public static MethodReference FlagsAttributeCtor(this ModuleDefinition module) + public static MemberReference NotSupportedExceptionCtor(this ModuleDefinition module) { - return new MethodReference(".ctor", module.Void(), module.FlagsAttribute()) { HasThis = true }; + return MakeConstructorReference(module, module.NotSupportedException().ToTypeDefOrRef(), module.String()); } - public static MethodReference NotSupportedExceptionCtor(this ModuleDefinition module) + public static MemberReference ObsoleteAttributeCtor(this ModuleDefinition module) { - return new MethodReference(".ctor", module.Void(), module.NotSupportedException()) - { HasThis = true, Parameters = { new ParameterDefinition(module.String()) } }; + return MakeConstructorReference(module, module.ObsoleteAttribute().ToTypeDefOrRef(), module.String()); } - public static MethodReference ObsoleteAttributeCtor(this ModuleDefinition module) + private static MemberReference MakeConstructorReference(ModuleDefinition module, ITypeDefOrRef type, params TypeSignature[] parameters) { - return new MethodReference(".ctor", module.Void(), module.ObsoleteAttribute()) - { HasThis = true, Parameters = { new ParameterDefinition(module.String()) } }; + MethodSignature signature = MethodSignature.CreateInstance(module.Void(), parameters); + return new MemberReference(type, ".ctor", signature); } } diff --git a/Il2CppInterop.Generator/Utils/FieldAccessorGenerator.cs b/Il2CppInterop.Generator/Utils/FieldAccessorGenerator.cs index 3fbc3308..8200f8b7 100644 --- a/Il2CppInterop.Generator/Utils/FieldAccessorGenerator.cs +++ b/Il2CppInterop.Generator/Utils/FieldAccessorGenerator.cs @@ -1,7 +1,9 @@ +using AsmResolver.DotNet; +using AsmResolver.DotNet.Code.Cil; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; -using Mono.Cecil; -using Mono.Cecil.Cil; namespace Il2CppInterop.Generator.Utils; @@ -10,49 +12,51 @@ internal static class FieldAccessorGenerator public static void MakeGetter(FieldDefinition field, FieldRewriteContext fieldContext, PropertyDefinition property, RuntimeAssemblyReferences imports) { + var attributes = Field2MethodAttrs(field.Attributes) | MethodAttributes.SpecialName | MethodAttributes.HideBySig; var getter = new MethodDefinition("get_" + property.Name, - Field2MethodAttrs(field.Attributes) | MethodAttributes.SpecialName | MethodAttributes.HideBySig, - property.PropertyType); + attributes, + MethodSignatureCreator.CreateMethodSignature(attributes, property.Signature!.ReturnType, 0)); - var getterBody = getter.Body.GetILProcessor(); - property.DeclaringType.Methods.Add(getter); + getter.CilMethodBody = new(getter); + var getterBody = getter.CilMethodBody.Instructions; + property.DeclaringType!.Methods.Add(getter); + CilLocalVariable local0; if (field.IsStatic) { - var local0 = new VariableDefinition(property.PropertyType.IsValueType - ? property.PropertyType + local0 = new CilLocalVariable(property.Signature.ReturnType.IsValueType + ? property.Signature.ReturnType : imports.Module.IntPtr()); - getter.Body.Variables.Add(local0); + getter.CilMethodBody.LocalVariables.Add(local0); var localIsPointer = false; - if (field.FieldType.IsValueType && !property.PropertyType.IsValueType) + if (field.Signature!.FieldType.IsValueType && !property.Signature.ReturnType.IsValueType) { - var pointerStore = new GenericInstanceType(imports.Il2CppClassPointerStore); - pointerStore.GenericArguments.Add(property.PropertyType); - var pointerStoreType = property.DeclaringType.Module.ImportReference(pointerStore); - getterBody.Emit(OpCodes.Ldsfld, - new FieldReference("NativeClassPtr", imports.Module.IntPtr(), pointerStoreType)); - getterBody.Emit(OpCodes.Ldc_I4, 0); - getterBody.Emit(OpCodes.Conv_U); - getterBody.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_class_value_size.Value); - getterBody.Emit(OpCodes.Conv_U); - getterBody.Emit(OpCodes.Localloc); - getterBody.Emit(OpCodes.Stloc, local0); + var pointerStore = imports.Il2CppClassPointerStore.MakeGenericInstanceType(property.Signature.ReturnType).ToTypeDefOrRef(); + var pointerStoreType = property.DeclaringType.Module!.DefaultImporter.ImportType(pointerStore); + getterBody.Add(OpCodes.Ldsfld, + new MemberReference(pointerStoreType, "NativeClassPtr", new FieldSignature(imports.Module.IntPtr()))); + getterBody.Add(OpCodes.Ldc_I4, 0); + getterBody.Add(OpCodes.Conv_U); + getterBody.Add(OpCodes.Call, imports.IL2CPP_il2cpp_class_value_size.Value); + getterBody.Add(OpCodes.Conv_U); + getterBody.Add(OpCodes.Localloc); + getterBody.Add(OpCodes.Stloc, local0); localIsPointer = true; } - getterBody.Emit(OpCodes.Ldsfld, fieldContext.PointerField); + getterBody.Add(OpCodes.Ldsfld, fieldContext.PointerField); if (localIsPointer) - getterBody.Emit(OpCodes.Ldloc, local0); + getterBody.Add(OpCodes.Ldloc, local0); else - getterBody.Emit(OpCodes.Ldloca_S, local0); - getterBody.Emit(OpCodes.Conv_U); - getterBody.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_field_static_get_value.Value); + getterBody.Add(OpCodes.Ldloca_S, local0); + getterBody.Add(OpCodes.Conv_U); + getterBody.Add(OpCodes.Call, imports.IL2CPP_il2cpp_field_static_get_value.Value); - if (property.PropertyType.IsValueType) + if (property.Signature.ReturnType.IsValueType) { - getterBody.Emit(OpCodes.Ldloc, local0); - getterBody.Emit(OpCodes.Ret); + getterBody.Add(OpCodes.Ldloc, local0); + getterBody.Add(OpCodes.Ret); property.GetMethod = getter; return; @@ -60,22 +64,22 @@ public static void MakeGetter(FieldDefinition field, FieldRewriteContext fieldCo } else { - var local0 = new VariableDefinition(imports.Module.IntPtr()); - getter.Body.Variables.Add(local0); + local0 = new CilLocalVariable(imports.Module.IntPtr()); + getter.CilMethodBody.LocalVariables.Add(local0); - getterBody.EmitObjectToPointer(fieldContext.DeclaringType.OriginalType, fieldContext.DeclaringType.NewType, + getterBody.EmitObjectToPointer(fieldContext.DeclaringType.OriginalType.ToTypeSignature(), fieldContext.DeclaringType.NewType.ToTypeSignature(), fieldContext.DeclaringType, 0, false, false, false, false, out _); - getterBody.Emit(OpCodes.Ldsfld, fieldContext.PointerField); - getterBody.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_field_get_offset.Value); - getterBody.Emit(OpCodes.Add); + getterBody.Add(OpCodes.Ldsfld, fieldContext.PointerField); + getterBody.Add(OpCodes.Call, imports.IL2CPP_il2cpp_field_get_offset.Value); + getterBody.Add(OpCodes.Add); - getterBody.Emit(OpCodes.Stloc_0); + getterBody.Add(OpCodes.Stloc_0); } - getterBody.EmitPointerToObject(fieldContext.OriginalField.FieldType, property.PropertyType, - fieldContext.DeclaringType, getterBody.Create(OpCodes.Ldloc_0), !field.IsStatic, false); + getterBody.EmitPointerToObject(fieldContext.OriginalField.Signature!.FieldType, property.Signature.ReturnType, + fieldContext.DeclaringType, local0, !field.IsStatic, false); - getterBody.Emit(OpCodes.Ret); + getterBody.Add(OpCodes.Ret); property.GetMethod = getter; } @@ -83,32 +87,33 @@ public static void MakeGetter(FieldDefinition field, FieldRewriteContext fieldCo public static void MakeSetter(FieldDefinition field, FieldRewriteContext fieldContext, PropertyDefinition property, RuntimeAssemblyReferences imports) { + var attributes = Field2MethodAttrs(field.Attributes) | MethodAttributes.SpecialName | MethodAttributes.HideBySig; var setter = new MethodDefinition("set_" + property.Name, - Field2MethodAttrs(field.Attributes) | MethodAttributes.SpecialName | MethodAttributes.HideBySig, - imports.Module.Void()); - setter.Parameters.Add(new ParameterDefinition(property.PropertyType)); - property.DeclaringType.Methods.Add(setter); - var setterBody = setter.Body.GetILProcessor(); + attributes, + MethodSignatureCreator.CreateMethodSignature(attributes, imports.Module.Void(), 0, property.Signature!.ReturnType)); + property.DeclaringType!.Methods.Add(setter); + setter.CilMethodBody = new(setter); + var setterBody = setter.CilMethodBody.Instructions; if (field.IsStatic) { - setterBody.Emit(OpCodes.Ldsfld, fieldContext.PointerField); - setterBody.EmitObjectToPointer(field.FieldType, property.PropertyType, fieldContext.DeclaringType, 0, false, + setterBody.Add(OpCodes.Ldsfld, fieldContext.PointerField); + setterBody.EmitObjectToPointer(field.Signature!.FieldType, property.Signature.ReturnType, fieldContext.DeclaringType, 0, false, true, true, true, out _); - setterBody.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_field_static_set_value.Value); + setterBody.Add(OpCodes.Call, imports.IL2CPP_il2cpp_field_static_set_value.Value); } else { - setterBody.EmitObjectToPointer(fieldContext.DeclaringType.OriginalType, fieldContext.DeclaringType.NewType, + setterBody.EmitObjectToPointer(fieldContext.DeclaringType.OriginalType.ToTypeSignature(), fieldContext.DeclaringType.NewType.ToTypeSignature(), fieldContext.DeclaringType, 0, false, false, false, false, out _); - setterBody.Emit(OpCodes.Dup); - setterBody.Emit(OpCodes.Ldsfld, fieldContext.PointerField); - setterBody.Emit(OpCodes.Call, imports.IL2CPP_il2cpp_field_get_offset.Value); - setterBody.Emit(OpCodes.Add); - setterBody.EmitObjectStore(field.FieldType, property.PropertyType, fieldContext.DeclaringType, 1); + setterBody.Add(OpCodes.Dup); + setterBody.Add(OpCodes.Ldsfld, fieldContext.PointerField); + setterBody.Add(OpCodes.Call, imports.IL2CPP_il2cpp_field_get_offset.Value); + setterBody.Add(OpCodes.Add); + setterBody.EmitObjectStore(field.Signature!.FieldType, property.Signature.ReturnType, fieldContext.DeclaringType, 1); } - setterBody.Emit(OpCodes.Ret); + setterBody.Add(OpCodes.Ret); property.SetMethod = setter; } diff --git a/Il2CppInterop.Generator/Utils/Memoize.cs b/Il2CppInterop.Generator/Utils/Memoize.cs index 501d3d23..bbab4b7b 100644 --- a/Il2CppInterop.Generator/Utils/Memoize.cs +++ b/Il2CppInterop.Generator/Utils/Memoize.cs @@ -1,9 +1,6 @@ -using System; -using System.Collections.Generic; +namespace Il2CppInterop.Generator.Utils; -namespace Il2CppInterop.Generator.Utils; - -public class Memoize +public class Memoize where TParam : notnull { private readonly Dictionary _cache = new(); private readonly Func _func; diff --git a/Il2CppInterop.Generator/Utils/MethodSignatureCreator.cs b/Il2CppInterop.Generator/Utils/MethodSignatureCreator.cs new file mode 100644 index 00000000..023ca43d --- /dev/null +++ b/Il2CppInterop.Generator/Utils/MethodSignatureCreator.cs @@ -0,0 +1,17 @@ +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; + +namespace Il2CppInterop.Generator.Utils; + +internal static class MethodSignatureCreator +{ + public static MethodSignature CreateMethodSignature(MethodAttributes attributes, TypeSignature returnType, int genericParameterCount, params TypeSignature[] parameterTypes) + { + return CreateMethodSignature((attributes & MethodAttributes.Static) != 0, returnType, genericParameterCount, parameterTypes); + } + + public static MethodSignature CreateMethodSignature(bool isStatic, TypeSignature returnType, int genericParameterCount, params TypeSignature[] parameterTypes) + { + return isStatic ? MethodSignature.CreateStatic(returnType, genericParameterCount, parameterTypes) : MethodSignature.CreateInstance(returnType, genericParameterCount, parameterTypes); + } +} diff --git a/Il2CppInterop.Generator/Utils/ReferenceCreator.cs b/Il2CppInterop.Generator/Utils/ReferenceCreator.cs new file mode 100644 index 00000000..b9272be6 --- /dev/null +++ b/Il2CppInterop.Generator/Utils/ReferenceCreator.cs @@ -0,0 +1,22 @@ +using AsmResolver; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; + +namespace Il2CppInterop.Generator.Utils; +internal static class ReferenceCreator +{ + public static MemberReference CreateFieldReference(Utf8String? name, TypeSignature fieldType, IMemberRefParent? parent) + { + return new MemberReference(parent, name, new FieldSignature(fieldType)); + } + + public static MemberReference CreateInstanceMethodReference(Utf8String? name, TypeSignature returnType, IMemberRefParent? parent, params TypeSignature[] parameterTypes) + { + return new MemberReference(parent, name, MethodSignature.CreateInstance(returnType, parameterTypes)); + } + + public static MemberReference CreateStaticMethodReference(Utf8String? name, TypeSignature returnType, IMemberRefParent? parent, params TypeSignature[] parameterTypes) + { + return new MemberReference(parent, name, MethodSignature.CreateStatic(returnType, parameterTypes)); + } +} diff --git a/Il2CppInterop.Generator/Utils/RuntimeAssemblyReferences.cs b/Il2CppInterop.Generator/Utils/RuntimeAssemblyReferences.cs index 6646699a..112c4602 100644 --- a/Il2CppInterop.Generator/Utils/RuntimeAssemblyReferences.cs +++ b/Il2CppInterop.Generator/Utils/RuntimeAssemblyReferences.cs @@ -1,17 +1,16 @@ // ReSharper disable InconsistentNaming -using System; -using System.Collections.Generic; -using System.Linq; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; using Il2CppInterop.Common.Attributes; using Il2CppInterop.Generator.Contexts; -using Mono.Cecil; +using Il2CppInterop.Generator.Extensions; namespace Il2CppInterop.Generator.Utils; public class RuntimeAssemblyReferences { - private readonly Dictionary allTypes = new(); + private readonly Dictionary allTypes = new(); private readonly RewriteGlobalContext globalCtx; public RuntimeAssemblyReferences(ModuleDefinition module, RewriteGlobalContext globalContext) @@ -23,130 +22,124 @@ public RuntimeAssemblyReferences(ModuleDefinition module, RewriteGlobalContext g } public ModuleDefinition Module { get; } - - public Memoize Il2CppRefrenceArrayctor { get; private set; } - public Lazy Il2CppStringArrayctor { get; private set; } - public Memoize Il2CppStructArrayctor { get; private set; } - public Memoize Il2CppRefrenceArrayctor_size { get; private set; } - public Lazy Il2CppStringArrayctor_size { get; private set; } - public Memoize Il2CppStructArrayctor_size { get; private set; } - public Lazy IL2CPP_Il2CppObjectBaseToPtr { get; private set; } - public Lazy IL2CPP_Il2CppObjectBaseToPtrNotNull { get; private set; } - public Lazy IL2CPP_Il2CppStringToManaged { get; private set; } - public Lazy IL2CPP_ManagedStringToIl2Cpp { get; private set; } - public Lazy Il2CppObjectBase_Cast { get; private set; } - public Lazy Il2CppObjectBase_TryCast { get; private set; } - public Lazy Il2CppObjectPool_Get { get; private set; } - public Lazy IL2CPP_ResolveICall { get; private set; } - public Lazy IL2CPP_il2cpp_gc_wbarrier_set_field { get; private set; } - public Lazy IL2CPP_FieldWriteWbarrierStub { get; private set; } - public Lazy IL2CPP_il2cpp_field_get_offset { get; private set; } - public Lazy IL2CPP_il2cpp_field_static_get_value { get; private set; } - public Lazy IL2CPP_il2cpp_field_static_set_value { get; private set; } - public Lazy IL2CPP_il2cpp_runtime_invoke { get; private set; } - public Lazy IL2CPP_il2cpp_runtime_class_init { get; private set; } - public Lazy IL2CPP_il2cpp_object_unbox { get; private set; } - public Lazy IL2CPP_il2cpp_value_box { get; private set; } - public Lazy IL2CPP_il2cpp_class_value_size { get; private set; } - public Lazy IL2CPP_il2cpp_object_get_class { get; private set; } - public Lazy IL2CPP_il2cpp_class_is_valuetype { get; private set; } - public Lazy Il2CppException_RaiseExceptionIfNecessary { get; private set; } - public Lazy IL2CPP_il2cpp_object_get_virtual_method { get; private set; } - public Lazy IL2CPP_GetIl2CppField { get; private set; } - public Lazy IL2CPP_GetIl2CppNestedType { get; private set; } - public Lazy IL2CPP_GetIl2CppClass { get; private set; } - public Lazy IL2CPP_GetIl2CppMethod { get; private set; } - public Lazy IL2CPP_GetIl2CppMethodByToken { get; private set; } - public Lazy IL2CPP_il2cpp_class_get_type { get; private set; } - public Lazy IL2CPP_il2cpp_class_from_type { get; private set; } - public Lazy IL2CPP_il2cpp_object_new { get; private set; } - public Lazy IL2CPP_il2cpp_method_get_from_reflection { get; private set; } - public Lazy IL2CPP_il2cpp_method_get_object { get; private set; } - public Lazy IL2CPP_PointerToValueGeneric { get; private set; } - public Lazy IL2CPP_RenderTypeName { get; private set; } - public Lazy OriginalNameAttributector { get; private set; } - public Lazy ObfuscatedNameAttributector { get; private set; } - public Lazy CallerCountAttributector { get; private set; } - public Lazy CachedScanResultsAttributector { get; private set; } - public Lazy Il2CppSystemDelegateCombine { get; private set; } - public Lazy Il2CppSystemDelegateRemove { get; private set; } - public Lazy Il2CppSystemRuntimeTypeHandleGetRuntimeTypeHandle { get; private set; } - - public MethodReference WriteFieldWBarrier => globalCtx.HasGcWbarrierFieldWrite +#nullable disable + public Memoize Il2CppRefrenceArrayctor { get; private set; } + public Lazy Il2CppStringArrayctor { get; private set; } + public Memoize Il2CppStructArrayctor { get; private set; } + public Memoize Il2CppRefrenceArrayctor_size { get; private set; } + public Lazy Il2CppStringArrayctor_size { get; private set; } + public Memoize Il2CppStructArrayctor_size { get; private set; } + public Lazy Il2CppArrayBase_get_Length { get; private set; } + public Lazy IL2CPP_Il2CppObjectBaseToPtr { get; private set; } + public Lazy IL2CPP_Il2CppObjectBaseToPtrNotNull { get; private set; } + public Lazy IL2CPP_Il2CppStringToManaged { get; private set; } + public Lazy IL2CPP_ManagedStringToIl2Cpp { get; private set; } + public Lazy Il2CppObjectBase_Cast { get; private set; } + public Lazy Il2CppObjectBase_TryCast { get; private set; } + public Lazy Il2CppObjectPool_Get { get; private set; } + public Lazy IL2CPP_ResolveICall { get; private set; } + public Lazy IL2CPP_il2cpp_gc_wbarrier_set_field { get; private set; } + public Lazy IL2CPP_FieldWriteWbarrierStub { get; private set; } + public Lazy IL2CPP_il2cpp_field_get_offset { get; private set; } + public Lazy IL2CPP_il2cpp_field_static_get_value { get; private set; } + public Lazy IL2CPP_il2cpp_field_static_set_value { get; private set; } + public Lazy IL2CPP_il2cpp_runtime_invoke { get; private set; } + public Lazy IL2CPP_il2cpp_runtime_class_init { get; private set; } + public Lazy IL2CPP_il2cpp_object_unbox { get; private set; } + public Lazy IL2CPP_il2cpp_value_box { get; private set; } + public Lazy IL2CPP_il2cpp_class_value_size { get; private set; } + public Lazy IL2CPP_il2cpp_object_get_class { get; private set; } + public Lazy IL2CPP_il2cpp_class_is_valuetype { get; private set; } + public Lazy Il2CppException_RaiseExceptionIfNecessary { get; private set; } + public Lazy IL2CPP_il2cpp_object_get_virtual_method { get; private set; } + public Lazy IL2CPP_GetIl2CppField { get; private set; } + public Lazy IL2CPP_GetIl2CppNestedType { get; private set; } + public Lazy IL2CPP_GetIl2CppClass { get; private set; } + public Lazy IL2CPP_GetIl2CppMethod { get; private set; } + public Lazy IL2CPP_GetIl2CppMethodByToken { get; private set; } + public Lazy IL2CPP_il2cpp_class_get_type { get; private set; } + public Lazy IL2CPP_il2cpp_class_from_type { get; private set; } + public Lazy IL2CPP_il2cpp_object_new { get; private set; } + public Lazy IL2CPP_il2cpp_method_get_from_reflection { get; private set; } + public Lazy IL2CPP_il2cpp_method_get_object { get; private set; } + public Lazy IL2CPP_PointerToValueGeneric { get; private set; } + public Lazy IL2CPP_RenderTypeName { get; private set; } + public Lazy OriginalNameAttributector { get; private set; } + public Lazy ObfuscatedNameAttributector { get; private set; } + public Lazy CallerCountAttributector { get; private set; } + public Lazy CachedScanResultsAttributector { get; private set; } + public Lazy Il2CppSystemDelegateCombine { get; private set; } + public Lazy Il2CppSystemDelegateRemove { get; private set; } + public Lazy Il2CppSystemRuntimeTypeHandleGetRuntimeTypeHandle { get; private set; } + + public IMethodDescriptor WriteFieldWBarrier => globalCtx.HasGcWbarrierFieldWrite ? IL2CPP_il2cpp_gc_wbarrier_set_field.Value : IL2CPP_FieldWriteWbarrierStub.Value; - public TypeReference Il2CppObjectBase { get; private set; } - public TypeReference Il2CppObjectPool { get; private set; } - public TypeReference Il2CppStringArray { get; private set; } - public TypeReference Il2CppArrayBase { get; private set; } - public TypeReference Il2CppStructArray { get; private set; } - public TypeReference Il2CppReferenceArray { get; private set; } - public TypeReference Il2CppClassPointerStore { get; private set; } - public TypeReference Il2Cpp { get; set; } - public TypeReference RuntimeReflectionHelper { get; private set; } - public TypeReference DelegateSupport { get; private set; } - public TypeReference Il2CppException { get; private set; } - - private TypeReference ResolveType(string typeName) + public TypeSignature Il2CppObjectBase { get; private set; } + public TypeSignature Il2CppObjectPool { get; private set; } + public TypeSignature Il2CppStringArray { get; private set; } + public TypeSignature Il2CppArrayBase { get; private set; } + public TypeSignature Il2CppStructArray { get; private set; } + public TypeSignature Il2CppReferenceArray { get; private set; } + public TypeSignature Il2CppClassPointerStore { get; private set; } + public TypeSignature Il2Cpp { get; set; } + public TypeSignature RuntimeReflectionHelper { get; private set; } + public TypeSignature DelegateSupport { get; private set; } + public TypeSignature Il2CppException { get; private set; } +#nullable enable + private TypeSignature ResolveType(string typeName) { return allTypes[typeName]; } private void InitTypeRefs() { - allTypes["System.Void"] = Module.ImportReference(typeof(void)); - allTypes["System.String[]"] = Module.ImportReference(typeof(string[])); - allTypes["System.IntPtr"] = Module.ImportReference(typeof(IntPtr)); - allTypes["System.String"] = Module.ImportReference(typeof(string)); - allTypes["System.UInt32"] = Module.ImportReference(typeof(uint)); - allTypes["System.Void*"] = Module.ImportReference(typeof(void*)); - allTypes["System.Void**"] = Module.ImportReference(typeof(void**)); - allTypes["System.IntPtr&"] = Module.ImportReference(typeof(IntPtr).MakeByRefType()); - allTypes["System.Int32"] = Module.ImportReference(typeof(int)); - allTypes["System.UInt32&"] = Module.ImportReference(typeof(uint).MakeByRefType()); - allTypes["System.Boolean"] = Module.ImportReference(typeof(bool)); - allTypes["System.Int64"] = Module.ImportReference(typeof(long)); - - var assemblyRef = new AssemblyNameReference("Il2CppInterop.Runtime", new Version(0, 0, 0, 0)); + allTypes["System.Void"] = Module.DefaultImporter.ImportTypeSignature(typeof(void)); + allTypes["System.String[]"] = Module.DefaultImporter.ImportTypeSignature(typeof(string[])); + allTypes["System.IntPtr"] = Module.DefaultImporter.ImportTypeSignature(typeof(IntPtr)); + allTypes["System.String"] = Module.DefaultImporter.ImportTypeSignature(typeof(string)); + allTypes["System.UInt32"] = Module.DefaultImporter.ImportTypeSignature(typeof(uint)); + allTypes["System.Void*"] = Module.DefaultImporter.ImportTypeSignature(typeof(void*)); + allTypes["System.Void**"] = Module.DefaultImporter.ImportTypeSignature(typeof(void**)); + allTypes["System.IntPtr&"] = Module.DefaultImporter.ImportTypeSignature(typeof(IntPtr).MakeByRefType()); + allTypes["System.Int32"] = Module.DefaultImporter.ImportTypeSignature(typeof(int)); + allTypes["System.UInt32&"] = Module.DefaultImporter.ImportTypeSignature(typeof(uint).MakeByRefType()); + allTypes["System.Boolean"] = Module.DefaultImporter.ImportTypeSignature(typeof(bool)); + allTypes["System.Int64"] = Module.DefaultImporter.ImportTypeSignature(typeof(long)); + + var assemblyRef = new AssemblyReference("Il2CppInterop.Runtime", new Version(0, 0, 0, 0)); Module.AssemblyReferences.Add(assemblyRef); Il2CppObjectBase = - new TypeReference("Il2CppInterop.Runtime.InteropTypes", "Il2CppObjectBase", Module, assemblyRef); + new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime.InteropTypes", "Il2CppObjectBase").ToTypeSignature(); + + Il2CppObjectPool = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime.Runtime", "Il2CppObjectPool").ToTypeSignature(); - Il2CppObjectPool = new TypeReference("Il2CppInterop.Runtime.Runtime", "Il2CppObjectPool", Module, assemblyRef); + Il2CppStringArray = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppStringArray").ToTypeSignature(); - Il2CppStringArray = new TypeReference("Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppStringArray", Module, - assemblyRef); + Il2CppArrayBase = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppArrayBase`1").ToTypeSignature(); - Il2CppArrayBase = new TypeReference("Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppArrayBase`1", Module, - assemblyRef); - Il2CppArrayBase.GenericParameters.Add(new GenericParameter("T", Il2CppArrayBase)); + var nonGenericIl2CppArrayBase = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppArrayBase").ToTypeSignature(); - Il2CppStructArray = new TypeReference("Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppStructArray`1", - Module, - assemblyRef); - Il2CppStructArray.GenericParameters.Add(new GenericParameter("T", Il2CppStructArray)); + Il2CppStructArray = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppStructArray`1").ToTypeSignature(); - Il2CppReferenceArray = new TypeReference("Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppReferenceArray`1", - Module, assemblyRef); - Il2CppReferenceArray.GenericParameters.Add(new GenericParameter("T", Il2CppReferenceArray)); + Il2CppReferenceArray = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppReferenceArray`1").ToTypeSignature(); - Il2CppClassPointerStore = new TypeReference("Il2CppInterop.Runtime", "Il2CppClassPointerStore`1", - Module, assemblyRef); - Il2CppClassPointerStore.GenericParameters.Add(new GenericParameter("T", Il2CppClassPointerStore)); + Il2CppClassPointerStore = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime", "Il2CppClassPointerStore`1").ToTypeSignature(); - Il2Cpp = new TypeReference("Il2CppInterop.Runtime", "IL2CPP", Module, assemblyRef); + Il2Cpp = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime", "IL2CPP").ToTypeSignature(); RuntimeReflectionHelper = - new TypeReference("Il2CppInterop.Runtime", "RuntimeReflectionHelper", Module, assemblyRef); + new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime", "RuntimeReflectionHelper").ToTypeSignature(); - DelegateSupport = new TypeReference("Il2CppInterop.Runtime", "DelegateSupport", Module, assemblyRef); + DelegateSupport = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime", "DelegateSupport").ToTypeSignature(); - Il2CppException = new TypeReference("Il2CppInterop.Runtime", "Il2CppException", Module, assemblyRef); + Il2CppException = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime", "Il2CppException").ToTypeSignature(); allTypes["Il2CppInterop.Runtime.InteropTypes.Il2CppObjectBase"] = Il2CppObjectBase; allTypes["Il2CppInterop.Runtime.Runtime.Il2CppObjectPool"] = Il2CppObjectPool; + allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppArrayBase"] = nonGenericIl2CppArrayBase; allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStringArray"] = Il2CppStringArray; allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppReferenceArray"] = Il2CppReferenceArray; allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStructArray"] = Il2CppStructArray; @@ -159,465 +152,342 @@ private void InitMethodRefs() Il2CppRefrenceArrayctor = new((param) => { var owner = ResolveType("Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppReferenceArray"); - var gp = owner.GenericParameters[0]; - var giOwner = new GenericInstanceType(owner); - giOwner.GenericArguments.Add(param); - var mr = new MethodReference(".ctor", ResolveType("System.Void"), - giOwner) - { HasThis = true }; - var paramType = new ArrayType(gp); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, paramType)); - return mr; + var gp = new GenericParameterSignature(GenericParameterType.Type, 0); + var giOwner = owner.MakeGenericInstanceType(param).ToTypeDefOrRef(); + return ReferenceCreator.CreateInstanceMethodReference(".ctor", ResolveType("System.Void"), + giOwner, gp.MakeSzArrayType()); }); - Il2CppStringArrayctor = new Lazy(() => + Il2CppStringArrayctor = new Lazy(() => { - var mr = new MethodReference(".ctor", ResolveType("System.Void"), - ResolveType("Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStringArray")); - mr.HasThis = true; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.String[]"))); - return mr; + return ReferenceCreator.CreateInstanceMethodReference(".ctor", ResolveType("System.Void"), + ResolveType("Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStringArray").ToTypeDefOrRef(), ResolveType("System.String[]")); }); Il2CppStructArrayctor = new((param) => { var owner = ResolveType("Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStructArray"); - var gp = owner.GenericParameters[0]; - var giOwner = new GenericInstanceType(owner); - giOwner.GenericArguments.Add(param); - var mr = new MethodReference(".ctor", ResolveType("System.Void"), - giOwner); - mr.HasThis = true; - var paramType = new ArrayType(gp); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, paramType)); + var gp = new GenericParameterSignature(GenericParameterType.Type, 0); + var giOwner = new GenericInstanceTypeSignature(owner.ToTypeDefOrRef(), false); + giOwner.TypeArguments.Add(param); + var mr = ReferenceCreator.CreateInstanceMethodReference(".ctor", ResolveType("System.Void"), + giOwner.ToTypeDefOrRef()); + var paramType = gp.MakeSzArrayType(); + ((MethodSignature)mr.Signature!).ParameterTypes.Add(paramType); return mr; }); Il2CppRefrenceArrayctor_size = new((param) => { var owner = ResolveType("Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppReferenceArray"); - var giOwner = new GenericInstanceType(owner); - giOwner.GenericArguments.Add(param); - var mr = new MethodReference(".ctor", ResolveType("System.Void"), - giOwner) - { HasThis = true }; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.Int64"))); + var giOwner = new GenericInstanceTypeSignature(owner.ToTypeDefOrRef(), false); + giOwner.TypeArguments.Add(param); + var mr = ReferenceCreator.CreateInstanceMethodReference(".ctor", ResolveType("System.Void"), + giOwner.ToTypeDefOrRef(), ResolveType("System.Int64")); return mr; }); - Il2CppStringArrayctor_size = new Lazy(() => + Il2CppStringArrayctor_size = new Lazy(() => { - var mr = new MethodReference(".ctor", ResolveType("System.Void"), - ResolveType("Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStringArray")); - mr.HasThis = true; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.Int64"))); + var mr = ReferenceCreator.CreateInstanceMethodReference(".ctor", ResolveType("System.Void"), + ResolveType("Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStringArray").ToTypeDefOrRef(), ResolveType("System.Int64")); return mr; }); Il2CppStructArrayctor_size = new((param) => { var owner = ResolveType("Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStructArray"); - var giOwner = new GenericInstanceType(owner); - giOwner.GenericArguments.Add(param); - var mr = new MethodReference(".ctor", ResolveType("System.Void"), - giOwner); - mr.HasThis = true; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.Int64"))); + var giOwner = owner.MakeGenericInstanceType(param).ToTypeDefOrRef(); + var mr = ReferenceCreator.CreateInstanceMethodReference(".ctor", ResolveType("System.Void"), + giOwner, ResolveType("System.Int64")); return mr; }); - IL2CPP_Il2CppObjectBaseToPtr = new Lazy(() => + Il2CppArrayBase_get_Length = new Lazy(() => { - var mr = new MethodReference("Il2CppObjectBaseToPtr", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, - ResolveType("Il2CppInterop.Runtime.InteropTypes.Il2CppObjectBase"))); + var owner = ResolveType("Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppArrayBase"); + var mr = ReferenceCreator.CreateInstanceMethodReference("get_Length", ResolveType("System.Int32"), + owner.ToTypeDefOrRef()); return mr; }); - IL2CPP_Il2CppObjectBaseToPtrNotNull = new Lazy(() => + IL2CPP_Il2CppObjectBaseToPtr = new Lazy(() => { - var mr = new MethodReference("Il2CppObjectBaseToPtrNotNull", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, - ResolveType("Il2CppInterop.Runtime.InteropTypes.Il2CppObjectBase"))); + var mr = ReferenceCreator.CreateStaticMethodReference("Il2CppObjectBaseToPtr", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("Il2CppInterop.Runtime.InteropTypes.Il2CppObjectBase")); return mr; }); - IL2CPP_Il2CppStringToManaged = new Lazy(() => + IL2CPP_Il2CppObjectBaseToPtrNotNull = new Lazy(() => { - var mr = new MethodReference("Il2CppStringToManaged", ResolveType("System.String"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var mr = ReferenceCreator.CreateStaticMethodReference("Il2CppObjectBaseToPtrNotNull", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), + ResolveType("Il2CppInterop.Runtime.InteropTypes.Il2CppObjectBase")); return mr; }); - IL2CPP_ManagedStringToIl2Cpp = new Lazy(() => + IL2CPP_Il2CppStringToManaged = new Lazy(() => { - var mr = new MethodReference("ManagedStringToIl2Cpp", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.String"))); + var mr = ReferenceCreator.CreateStaticMethodReference("Il2CppStringToManaged", ResolveType("System.String"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr")); return mr; }); - Il2CppObjectBase_Cast = new Lazy(() => + IL2CPP_ManagedStringToIl2Cpp = new Lazy(() => { - var mr = new MethodReference("Cast", Module.Void(), - ResolveType("Il2CppInterop.Runtime.InteropTypes.Il2CppObjectBase")); - var gp0 = new GenericParameter("T", mr); - mr.GenericParameters.Add(gp0); - mr.ReturnType = gp0; - mr.HasThis = true; + var mr = ReferenceCreator.CreateStaticMethodReference("ManagedStringToIl2Cpp", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.String")); return mr; }); - Il2CppObjectBase_TryCast = new Lazy(() => + Il2CppObjectBase_Cast = new Lazy(() => { - var mr = new MethodReference("TryCast", Module.Void(), - ResolveType("Il2CppInterop.Runtime.InteropTypes.Il2CppObjectBase")); - var gp0 = new GenericParameter("T", mr); - mr.GenericParameters.Add(gp0); - mr.ReturnType = gp0; - mr.HasThis = true; + var gp0 = new GenericParameterSignature(GenericParameterType.Method, 0); + var signature = MethodSignature.CreateInstance(gp0, 1); + var mr = new MemberReference(ResolveType("Il2CppInterop.Runtime.InteropTypes.Il2CppObjectBase").ToTypeDefOrRef(), "Cast", signature); return mr; }); - Il2CppObjectPool_Get = new Lazy(() => + Il2CppObjectBase_TryCast = new Lazy(() => { - var mr = new MethodReference("Get", Module.Void(), - ResolveType("Il2CppInterop.Runtime.Runtime.Il2CppObjectPool")); - var gp0 = new GenericParameter("T", mr); - mr.GenericParameters.Add(gp0); - mr.ReturnType = gp0; - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("ptr", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var gp0 = new GenericParameterSignature(GenericParameterType.Method, 0); + var signature = MethodSignature.CreateInstance(gp0, 1); + var mr = new MemberReference(ResolveType("Il2CppInterop.Runtime.InteropTypes.Il2CppObjectBase").ToTypeDefOrRef(), "TryCast", signature); return mr; }); - IL2CPP_ResolveICall = new Lazy(() => + Il2CppObjectPool_Get = new Lazy(() => { - var mr = new MethodReference("ResolveICall", Module.Void(), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - var gp0 = new GenericParameter("T", mr); - mr.GenericParameters.Add(gp0); - mr.ReturnType = gp0; - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.String"))); + var gp0 = new GenericParameterSignature(GenericParameterType.Method, 0); + var signature = MethodSignature.CreateStatic(gp0, 1, ResolveType("System.IntPtr")); + var mr = new MemberReference(ResolveType("Il2CppInterop.Runtime.Runtime.Il2CppObjectPool").ToTypeDefOrRef(), "Get", signature); return mr; }); - IL2CPP_il2cpp_gc_wbarrier_set_field = new Lazy(() => + IL2CPP_ResolveICall = new Lazy(() => { - var mr = new MethodReference("il2cpp_gc_wbarrier_set_field", ResolveType("System.Void"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var gp0 = new GenericParameterSignature(GenericParameterType.Method, 0); + var signature = MethodSignature.CreateStatic(gp0, 1, ResolveType("System.String")); + var mr = new MemberReference(ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), "ResolveICall", signature); return mr; }); - IL2CPP_FieldWriteWbarrierStub = new Lazy(() => + IL2CPP_il2cpp_gc_wbarrier_set_field = new Lazy(() => { - var mr = new MethodReference("FieldWriteWbarrierStub", ResolveType("System.Void"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_gc_wbarrier_set_field", ResolveType("System.Void"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr"), ResolveType("System.IntPtr"), ResolveType("System.IntPtr")); return mr; }); - IL2CPP_il2cpp_field_get_offset = new Lazy(() => + IL2CPP_FieldWriteWbarrierStub = new Lazy(() => { - var mr = new MethodReference("il2cpp_field_get_offset", ResolveType("System.UInt32"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var mr = ReferenceCreator.CreateStaticMethodReference("FieldWriteWbarrierStub", ResolveType("System.Void"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr"), ResolveType("System.IntPtr"), ResolveType("System.IntPtr")); return mr; }); - IL2CPP_il2cpp_field_static_get_value = new Lazy(() => + IL2CPP_il2cpp_field_get_offset = new Lazy(() => { - var mr = new MethodReference("il2cpp_field_static_get_value", ResolveType("System.Void"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.Void*"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_field_get_offset", ResolveType("System.UInt32"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr")); return mr; }); - IL2CPP_il2cpp_field_static_set_value = new Lazy(() => + IL2CPP_il2cpp_field_static_get_value = new Lazy(() => { - var mr = new MethodReference("il2cpp_field_static_set_value", ResolveType("System.Void"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.Void*"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_field_static_get_value", ResolveType("System.Void"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr"), ResolveType("System.Void*")); return mr; }); - IL2CPP_il2cpp_runtime_invoke = new Lazy(() => + IL2CPP_il2cpp_field_static_set_value = new Lazy(() => { - var mr = new MethodReference("il2cpp_runtime_invoke", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.Void**"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr&"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_field_static_set_value", ResolveType("System.Void"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr"), ResolveType("System.Void*")); return mr; }); - IL2CPP_il2cpp_runtime_class_init = new Lazy(() => + IL2CPP_il2cpp_runtime_invoke = new Lazy(() => { - var mr = new MethodReference("il2cpp_runtime_class_init", ResolveType("System.Void"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_runtime_invoke", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr"), ResolveType("System.IntPtr"), ResolveType("System.Void**"), ResolveType("System.IntPtr&")); return mr; }); - IL2CPP_il2cpp_object_unbox = new Lazy(() => + IL2CPP_il2cpp_runtime_class_init = new Lazy(() => { - var mr = new MethodReference("il2cpp_object_unbox", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_runtime_class_init", ResolveType("System.Void"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr")); return mr; }); - IL2CPP_il2cpp_value_box = new Lazy(() => + IL2CPP_il2cpp_object_unbox = new Lazy(() => { - var mr = new MethodReference("il2cpp_value_box", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_object_unbox", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr")); return mr; }); - IL2CPP_il2cpp_class_value_size = new Lazy(() => + IL2CPP_il2cpp_value_box = new Lazy(() => { - var mr = new MethodReference("il2cpp_class_value_size", ResolveType("System.Int32"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.UInt32&"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_value_box", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr"), ResolveType("System.IntPtr")); return mr; }); - IL2CPP_il2cpp_object_get_class = new Lazy(() => + IL2CPP_il2cpp_class_value_size = new Lazy(() => { - var mr = new MethodReference("il2cpp_object_get_class", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_class_value_size", ResolveType("System.Int32"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr"), ResolveType("System.UInt32&")); return mr; }); - IL2CPP_il2cpp_class_is_valuetype = new Lazy(() => + IL2CPP_il2cpp_object_get_class = new Lazy(() => { - var mr = new MethodReference("il2cpp_class_is_valuetype", ResolveType("System.Boolean"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_object_get_class", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr")); return mr; }); - Il2CppException_RaiseExceptionIfNecessary = new Lazy(() => + IL2CPP_il2cpp_class_is_valuetype = new Lazy(() => { - var mr = new MethodReference("RaiseExceptionIfNecessary", ResolveType("System.Void"), - ResolveType("Il2CppInterop.Runtime.Il2CppException")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_class_is_valuetype", ResolveType("System.Boolean"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr")); return mr; }); - IL2CPP_il2cpp_object_get_virtual_method = new Lazy(() => + Il2CppException_RaiseExceptionIfNecessary = new Lazy(() => { - var mr = new MethodReference("il2cpp_object_get_virtual_method", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var mr = ReferenceCreator.CreateStaticMethodReference("RaiseExceptionIfNecessary", ResolveType("System.Void"), + ResolveType("Il2CppInterop.Runtime.Il2CppException").ToTypeDefOrRef(), ResolveType("System.IntPtr")); return mr; }); - IL2CPP_GetIl2CppField = new Lazy(() => + IL2CPP_il2cpp_object_get_virtual_method = new Lazy(() => { - var mr = new MethodReference("GetIl2CppField", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.String"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_object_get_virtual_method", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr"), ResolveType("System.IntPtr")); return mr; }); - IL2CPP_GetIl2CppNestedType = new Lazy(() => + IL2CPP_GetIl2CppField = new Lazy(() => { - var mr = new MethodReference("GetIl2CppNestedType", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.String"))); + var mr = ReferenceCreator.CreateStaticMethodReference("GetIl2CppField", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr"), ResolveType("System.String")); return mr; }); - IL2CPP_GetIl2CppClass = new Lazy(() => + IL2CPP_GetIl2CppNestedType = new Lazy(() => { - var mr = new MethodReference("GetIl2CppClass", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.String"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.String"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.String"))); + var mr = ReferenceCreator.CreateStaticMethodReference("GetIl2CppNestedType", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr"), ResolveType("System.String")); return mr; }); - IL2CPP_GetIl2CppMethod = new Lazy(() => + IL2CPP_GetIl2CppClass = new Lazy(() => { - var mr = new MethodReference("GetIl2CppMethod", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.Boolean"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.String"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.String"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.String[]"))); + var mr = ReferenceCreator.CreateStaticMethodReference("GetIl2CppClass", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.String"), ResolveType("System.String"), ResolveType("System.String")); return mr; }); - IL2CPP_GetIl2CppMethodByToken = new Lazy(() => + IL2CPP_GetIl2CppMethod = new Lazy(() => { - var mr = new MethodReference("GetIl2CppMethodByToken", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.Int32"))); + var mr = ReferenceCreator.CreateStaticMethodReference("GetIl2CppMethod", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), + ResolveType("System.IntPtr"), ResolveType("System.Boolean"), ResolveType("System.String"), ResolveType("System.String"), ResolveType("System.String[]")); return mr; }); - IL2CPP_il2cpp_class_get_type = new Lazy(() => + IL2CPP_GetIl2CppMethodByToken = new Lazy(() => { - var mr = new MethodReference("il2cpp_class_get_type", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var mr = ReferenceCreator.CreateStaticMethodReference("GetIl2CppMethodByToken", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr"), ResolveType("System.Int32")); return mr; }); - IL2CPP_il2cpp_class_from_type = new Lazy(() => + IL2CPP_il2cpp_class_get_type = new Lazy(() => { - var mr = new MethodReference("il2cpp_class_from_type", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_class_get_type", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr")); return mr; }); - IL2CPP_il2cpp_object_new = new Lazy(() => + IL2CPP_il2cpp_class_from_type = new Lazy(() => { - var mr = new MethodReference("il2cpp_object_new", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_class_from_type", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr")); return mr; }); - IL2CPP_il2cpp_method_get_from_reflection = new Lazy(() => + IL2CPP_il2cpp_object_new = new Lazy(() => { - var mr = new MethodReference("il2cpp_method_get_from_reflection", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_object_new", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr")); return mr; }); - IL2CPP_il2cpp_method_get_object = new Lazy(() => + IL2CPP_il2cpp_method_get_from_reflection = new Lazy(() => { - var mr = new MethodReference("il2cpp_method_get_object", ResolveType("System.IntPtr"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_method_get_from_reflection", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr")); return mr; }); - IL2CPP_PointerToValueGeneric = new Lazy(() => + IL2CPP_il2cpp_method_get_object = new Lazy(() => { - var mr = new MethodReference("PointerToValueGeneric", Module.Void(), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - var gp0 = new GenericParameter("T", mr); - mr.GenericParameters.Add(gp0); - mr.ReturnType = gp0; - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.IntPtr"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.Boolean"))); - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.Boolean"))); + var mr = ReferenceCreator.CreateStaticMethodReference("il2cpp_method_get_object", ResolveType("System.IntPtr"), + ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), ResolveType("System.IntPtr"), ResolveType("System.IntPtr")); return mr; }); - IL2CPP_RenderTypeName = new Lazy(() => + IL2CPP_PointerToValueGeneric = new Lazy(() => { - var mr = new MethodReference("RenderTypeName", ResolveType("System.String"), - ResolveType("Il2CppInterop.Runtime.IL2CPP")); - var gp0 = new GenericParameter("T", mr); - mr.GenericParameters.Add(gp0); - mr.HasThis = false; - mr.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, ResolveType("System.Boolean"))); + var gp0 = new GenericParameterSignature(GenericParameterType.Method, 0); + var signature = MethodSignature.CreateStatic(gp0, 1, ResolveType("System.IntPtr"), ResolveType("System.Boolean"), ResolveType("System.Boolean")); + var mr = new MemberReference(ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), "PointerToValueGeneric", signature); return mr; }); - OriginalNameAttributector = new Lazy(() => new MethodReference(".ctor", - Module.Void(), - Module.ImportReference(typeof(OriginalNameAttribute))) + IL2CPP_RenderTypeName = new Lazy(() => { - HasThis = true, - Parameters = { - new ParameterDefinition(Module.String()), - new ParameterDefinition(Module.String()), - new ParameterDefinition(Module.String()) - } + var gp0 = new GenericParameterSignature(GenericParameterType.Method, 0); + var signature = MethodSignature.CreateStatic(ResolveType("System.String"), 1, ResolveType("System.Boolean")); + var mr = new MemberReference(ResolveType("Il2CppInterop.Runtime.IL2CPP").ToTypeDefOrRef(), "RenderTypeName", signature); + return mr; }); - ObfuscatedNameAttributector = new Lazy(() => new MethodReference(".ctor", + OriginalNameAttributector = new Lazy(() => ReferenceCreator.CreateInstanceMethodReference(".ctor", + Module.Void(), + Module.DefaultImporter.ImportType(typeof(OriginalNameAttribute)), Module.String(), Module.String(), Module.String())); + + ObfuscatedNameAttributector = new Lazy(() => ReferenceCreator.CreateInstanceMethodReference(".ctor", Module.Void(), - Module.ImportReference(typeof(ObfuscatedNameAttribute))) - { HasThis = true, Parameters = { new ParameterDefinition(Module.String()) } }); - - CallerCountAttributector = new Lazy(() => - new MethodReference(".ctor", Module.Void(), Module.ImportReference(typeof(CallerCountAttribute))) - { HasThis = true, Parameters = { new ParameterDefinition(Module.Int()) } }); - - CachedScanResultsAttributector = new Lazy(() => - new MethodReference(".ctor", Module.Void(), - Module.ImportReference(typeof(CachedScanResultsAttribute))) - { - HasThis = true - }); - - Il2CppSystemDelegateCombine = new Lazy(() => - Module.ImportReference(globalCtx.GetAssemblyByName("mscorlib").NewAssembly.MainModule + Module.DefaultImporter.ImportType(typeof(ObfuscatedNameAttribute)), Module.String())); + + CallerCountAttributector = new Lazy(() => + ReferenceCreator.CreateInstanceMethodReference(".ctor", Module.Void(), Module.DefaultImporter.ImportType(typeof(CallerCountAttribute)), Module.Int())); + + CachedScanResultsAttributector = new Lazy(() => + ReferenceCreator.CreateInstanceMethodReference(".ctor", Module.Void(), + Module.DefaultImporter.ImportType(typeof(CachedScanResultsAttribute)))); + + Il2CppSystemDelegateCombine = new Lazy(() => + Module.DefaultImporter.ImportMethod(globalCtx.GetAssemblyByName("mscorlib").NewAssembly.ManifestModule! .GetType("Il2CppSystem.Delegate").Methods.Single(m => m.Name == "Combine" && m.Parameters.Count == 2))); - Il2CppSystemDelegateRemove = new Lazy(() => - Module.ImportReference(globalCtx.GetAssemblyByName("mscorlib").NewAssembly.MainModule + Il2CppSystemDelegateRemove = new Lazy(() => + Module.DefaultImporter.ImportMethod(globalCtx.GetAssemblyByName("mscorlib").NewAssembly.ManifestModule! .GetType("Il2CppSystem.Delegate").Methods.Single(m => m.Name == "Remove"))); - Il2CppSystemRuntimeTypeHandleGetRuntimeTypeHandle = new Lazy(() => + Il2CppSystemRuntimeTypeHandleGetRuntimeTypeHandle = new Lazy(() => { var declaringTypeRef = RuntimeReflectionHelper; - var returnTypeRef = Module.ImportReference(globalCtx.GetAssemblyByName("mscorlib").NewAssembly.MainModule + var returnTypeRef = Module.DefaultImporter.ImportType(globalCtx.GetAssemblyByName("mscorlib").NewAssembly.ManifestModule! .GetType("Il2CppSystem.RuntimeTypeHandle")); - var methodReference = new MethodReference("GetRuntimeTypeHandle", returnTypeRef, declaringTypeRef) - { HasThis = false }; - methodReference.GenericParameters.Add(new GenericParameter("T", methodReference)); - return Module.ImportReference(methodReference); + var signature = MethodSignature.CreateStatic(returnTypeRef.ToTypeSignature(), 1); + var methodReference = new MemberReference(declaringTypeRef.ToTypeDefOrRef(), "GetRuntimeTypeHandle", signature); + return Module.DefaultImporter.ImportMethod(methodReference); }); } } diff --git a/Il2CppInterop.Generator/Utils/TimingCookie.cs b/Il2CppInterop.Generator/Utils/TimingCookie.cs index 75da4735..9eed28bc 100644 --- a/Il2CppInterop.Generator/Utils/TimingCookie.cs +++ b/Il2CppInterop.Generator/Utils/TimingCookie.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using Il2CppInterop.Common; using Microsoft.Extensions.Logging; diff --git a/Il2CppInterop.Generator/Utils/UniquificationContext.cs b/Il2CppInterop.Generator/Utils/UniquificationContext.cs index 8df0cb6c..662654ef 100644 --- a/Il2CppInterop.Generator/Utils/UniquificationContext.cs +++ b/Il2CppInterop.Generator/Utils/UniquificationContext.cs @@ -1,6 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; using Il2CppInterop.Generator.Extensions; namespace Il2CppInterop.Generator.Utils; diff --git a/Il2CppInterop.Generator/Utils/UnstripGenerator.cs b/Il2CppInterop.Generator/Utils/UnstripGenerator.cs index dabd4801..8db431e1 100644 --- a/Il2CppInterop.Generator/Utils/UnstripGenerator.cs +++ b/Il2CppInterop.Generator/Utils/UnstripGenerator.cs @@ -1,11 +1,12 @@ -using System.Linq; using System.Text; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Code.Cil; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Common; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; using Microsoft.Extensions.Logging; -using Mono.Cecil; -using Mono.Cecil.Cil; namespace Il2CppInterop.Generator.Utils; @@ -15,34 +16,32 @@ public static TypeDefinition CreateDelegateTypeForICallMethod(MethodDefinition u MethodDefinition convertedMethod, RuntimeAssemblyReferences imports) { var delegateType = new TypeDefinition("", unityMethod.Name + "Delegate", - TypeAttributes.Sealed | TypeAttributes.NestedPrivate, imports.Module.MulticastDelegate()); + TypeAttributes.Sealed | TypeAttributes.NestedPrivate, imports.Module.MulticastDelegate().ToTypeDefOrRef()); var constructor = new MethodDefinition(".ctor", - MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | - MethodAttributes.Public, imports.Module.Void()); - constructor.Parameters.Add(new ParameterDefinition(imports.Module.Object())); - constructor.Parameters.Add(new ParameterDefinition(imports.Module.IntPtr())); + MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RuntimeSpecialName | + MethodAttributes.Public, MethodSignature.CreateInstance(imports.Module.Void(), imports.Module.Object(), imports.Module.IntPtr())); constructor.ImplAttributes = MethodImplAttributes.CodeTypeMask; delegateType.Methods.Add(constructor); var invokeMethod = new MethodDefinition("Invoke", MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Public, - imports.Module.Void()); // todo + MethodSignature.CreateInstance(imports.Module.Void())); // todo invokeMethod.ImplAttributes = MethodImplAttributes.CodeTypeMask; delegateType.Methods.Add(invokeMethod); - invokeMethod.ReturnType = convertedMethod.ReturnType.IsValueType - ? convertedMethod.ReturnType + invokeMethod.Signature!.ReturnType = convertedMethod.Signature!.ReturnType.IsValueType + ? convertedMethod.Signature.ReturnType : imports.Module.IntPtr(); - if (convertedMethod.HasThis) - invokeMethod.Parameters.Add(new ParameterDefinition("@this", ParameterAttributes.None, - imports.Module.IntPtr())); + if (!convertedMethod.IsStatic) + invokeMethod.AddParameter(imports.Module.IntPtr(), "@this"); foreach (var convertedParameter in convertedMethod.Parameters) - invokeMethod.Parameters.Add(new ParameterDefinition(convertedParameter.Name, - convertedParameter.Attributes & ~ParameterAttributes.Optional, + invokeMethod.AddParameter( convertedParameter.ParameterType.IsValueType ? convertedParameter.ParameterType - : imports.Module.IntPtr())); + : imports.Module.IntPtr(), + convertedParameter.Name, + convertedParameter.Definition!.Attributes & ~ParameterAttributes.Optional); return delegateType; } @@ -50,24 +49,24 @@ public static TypeDefinition CreateDelegateTypeForICallMethod(MethodDefinition u public static void GenerateInvokerMethodBody(MethodDefinition newMethod, FieldDefinition delegateField, TypeDefinition delegateType, TypeRewriteContext enclosingType, RuntimeAssemblyReferences imports) { - var body = newMethod.Body.GetILProcessor(); + var body = newMethod.CilMethodBody!.Instructions; - body.Emit(OpCodes.Ldsfld, delegateField); - if (newMethod.HasThis) + body.Add(OpCodes.Ldsfld, delegateField); + if (!newMethod.IsStatic) { - body.Emit(OpCodes.Ldarg_0); - body.Emit(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtrNotNull.Value); + body.Add(OpCodes.Ldarg_0); + body.Add(OpCodes.Call, imports.IL2CPP_Il2CppObjectBaseToPtrNotNull.Value); } - var argOffset = newMethod.HasThis ? 1 : 0; + var argOffset = newMethod.IsStatic ? 0 : 1; for (var i = 0; i < newMethod.Parameters.Count; i++) { var param = newMethod.Parameters[i]; var paramType = param.ParameterType; - if (paramType.IsValueType || (paramType.IsByReference && paramType.GetElementType().IsValueType)) + if (paramType.IsValueType || (paramType is ByReferenceTypeSignature && paramType.GetElementType().IsValueType)) { - body.Emit(OpCodes.Ldarg, i + argOffset); + body.AddLoadArgument(i + argOffset); } else { @@ -81,49 +80,39 @@ public static void GenerateInvokerMethodBody(MethodDefinition newMethod, FieldDe } } - body.Emit(OpCodes.Call, delegateType.Methods.Single(it => it.Name == "Invoke")); - if (!newMethod.ReturnType.IsValueType) + body.Add(OpCodes.Call, delegateType.Methods.Single(it => it.Name == "Invoke")); + if (!newMethod.Signature!.ReturnType.IsValueType) { - var pointerVar = new VariableDefinition(imports.Module.IntPtr()); - newMethod.Body.Variables.Add(pointerVar); - body.Emit(OpCodes.Stloc, pointerVar); - var loadInstr = body.Create(OpCodes.Ldloc, pointerVar); - body.EmitPointerToObject(newMethod.ReturnType, newMethod.ReturnType, enclosingType, loadInstr, false, + var pointerVar = new CilLocalVariable(imports.Module.IntPtr()); + newMethod.CilMethodBody.LocalVariables.Add(pointerVar); + body.Add(OpCodes.Stloc, pointerVar); + body.EmitPointerToObject(newMethod.Signature.ReturnType, newMethod.Signature.ReturnType, enclosingType, pointerVar, false, false); } - body.Emit(OpCodes.Ret); + body.Add(OpCodes.Ret); } public static FieldDefinition GenerateStaticCtorSuffix(TypeDefinition enclosingType, TypeDefinition delegateType, MethodDefinition unityMethod, RuntimeAssemblyReferences imports) { var delegateField = new FieldDefinition(delegateType.Name + "Field", - FieldAttributes.Static | FieldAttributes.Private | FieldAttributes.InitOnly, delegateType); + FieldAttributes.Static | FieldAttributes.Private | FieldAttributes.InitOnly, new FieldSignature(delegateType.ToTypeSignature())); enclosingType.Fields.Add(delegateField); - var staticCtor = enclosingType.Methods.SingleOrDefault(it => it.Name == ".cctor"); - if (staticCtor == null) - { - staticCtor = new MethodDefinition(".cctor", - MethodAttributes.Static | MethodAttributes.Private | MethodAttributes.SpecialName | - MethodAttributes.HideBySig | MethodAttributes.RTSpecialName, imports.Module.Void()); - staticCtor.Body.GetILProcessor().Emit(OpCodes.Ret); - enclosingType.Methods.Add(staticCtor); - } + var staticCtor = enclosingType.GetOrCreateStaticConstructor(); - var bodyProcessor = staticCtor.Body.GetILProcessor(); + var bodyProcessor = staticCtor.CilMethodBody!.Instructions; - bodyProcessor.Remove(staticCtor.Body.Instructions.Last()); // remove ret + bodyProcessor.Remove(staticCtor.CilMethodBody.Instructions.Last()); // remove ret - bodyProcessor.Emit(OpCodes.Ldstr, GetICallSignature(unityMethod)); + bodyProcessor.Add(OpCodes.Ldstr, GetICallSignature(unityMethod)); - var methodRef = new GenericInstanceMethod(imports.IL2CPP_ResolveICall.Value); - methodRef.GenericArguments.Add(delegateType); - bodyProcessor.Emit(OpCodes.Call, enclosingType.Module.ImportReference(methodRef)); - bodyProcessor.Emit(OpCodes.Stsfld, delegateField); + var methodRef = imports.IL2CPP_ResolveICall.Value.MakeGenericInstanceMethod(delegateType.ToTypeSignature()); + bodyProcessor.Add(OpCodes.Call, enclosingType.Module!.DefaultImporter.ImportMethod(methodRef)); + bodyProcessor.Add(OpCodes.Stsfld, delegateField); - bodyProcessor.Emit(OpCodes.Ret); // restore ret + bodyProcessor.Add(OpCodes.Ret); // restore ret return delegateField; } @@ -131,7 +120,7 @@ public static FieldDefinition GenerateStaticCtorSuffix(TypeDefinition enclosingT private static string GetICallSignature(MethodDefinition unityMethod) { var builder = new StringBuilder(); - builder.Append(unityMethod.DeclaringType.FullName); + builder.Append(unityMethod.DeclaringType!.FullName); builder.Append("::"); builder.Append(unityMethod.Name); diff --git a/Il2CppInterop.Generator/Utils/UnstripTranslator.cs b/Il2CppInterop.Generator/Utils/UnstripTranslator.cs index 06df34a0..826250fb 100644 --- a/Il2CppInterop.Generator/Utils/UnstripTranslator.cs +++ b/Il2CppInterop.Generator/Utils/UnstripTranslator.cs @@ -1,8 +1,12 @@ -using System.Linq; +using AsmResolver; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Code.Cil; +using AsmResolver.DotNet.Collections; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Cil; using Il2CppInterop.Generator.Contexts; +using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Passes; -using Mono.Cecil; -using Mono.Cecil.Cil; namespace Il2CppInterop.Generator.Utils; @@ -11,186 +15,334 @@ public static class UnstripTranslator public static bool TranslateMethod(MethodDefinition original, MethodDefinition target, TypeRewriteContext typeRewriteContext, RuntimeAssemblyReferences imports) { - if (!original.HasBody) return true; + if (original.CilMethodBody is null) + return true; + + target.CilMethodBody = new(target); var globalContext = typeRewriteContext.AssemblyContext.GlobalContext; - foreach (var variableDefinition in original.Body.Variables) + Dictionary localVariableMap = new(); + foreach (var variableDefinition in original.CilMethodBody.LocalVariables) { var variableType = Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, variableDefinition.VariableType, imports); - if (variableType == null) return false; - target.Body.Variables.Add(new VariableDefinition(variableType)); + if (variableType == null) + return false; + var newVariableDefinition = new CilLocalVariable(variableType); + target.CilMethodBody.LocalVariables.Add(newVariableDefinition); + localVariableMap.Add(variableDefinition, newVariableDefinition); } - var targetBuilder = target.Body.GetILProcessor(); - foreach (var bodyInstruction in original.Body.Instructions) - if (bodyInstruction.OpCode.OperandType == OperandType.InlineField) + List> labelMap = new(); + Dictionary instructionMap = new(); + + var targetBuilder = target.CilMethodBody.Instructions; + foreach (var bodyInstruction in original.CilMethodBody.Instructions) + { + if (bodyInstruction.Operand is null) + { + CilInstruction newInstruction; + switch (bodyInstruction.OpCode.Code) + { + case CilCode.Ldlen: + //This is Il2CppArrayBase.Length + newInstruction = targetBuilder.Add(OpCodes.Callvirt, + imports.Module.DefaultImporter.ImportMethod(imports.Il2CppArrayBase_get_Length.Value)); + break; + + case CilCode.Ldelema: + //This is Il2CppArrayBase.Pointer + index * sizeof(T) but the T is not known because the operand is null. + return false; + + case CilCode.Ldelem: + //This is Il2CppArrayBase.set_Item but the T is not known because the operand is null. + return false; + + case CilCode.Stelem: + //This is Il2CppArrayBase.set_Item but the T is not known because the operand is null. + return false; + + case CilCode.Ldelem_Ref: + //This is Il2CppReferenceArray.get_Item but the T is not known because the operand is null. + return false; + + case CilCode.Stelem_Ref: + //This is Il2CppReferenceArray.set_Item but the T is not known because the operand is null. + return false; + + case >= CilCode.Ldelem_I1 and <= CilCode.Ldelem_R8: + //This is Il2CppStructArray.get_Item + return false; + + case >= CilCode.Stelem_I and <= CilCode.Stelem_R8: + //This is Il2CppStructArray.set_Item + return false; + + case >= CilCode.Ldind_I1 and <= CilCode.Ldind_Ref: + //This is for by ref parameters + goto default; + + case >= CilCode.Stind_Ref and <= CilCode.Stind_R8: + //This is for by ref parameters + goto default; + + default: + //Noop, ldnull, ldarg_0, mul, add, etc. + newInstruction = targetBuilder.Add(bodyInstruction.OpCode); + break; + } + + instructionMap.Add(bodyInstruction, newInstruction); + } + else if (bodyInstruction.OpCode.OperandType == CilOperandType.InlineField) { - var fieldArg = (FieldReference)bodyInstruction.Operand; + var fieldArg = (IFieldDescriptor)bodyInstruction.Operand; var fieldDeclarer = - Pass80UnstripMethods.ResolveTypeInNewAssembliesRaw(globalContext, fieldArg.DeclaringType, imports); - if (fieldDeclarer == null) return false; - var newField = fieldDeclarer.Resolve().Fields.SingleOrDefault(it => it.Name == fieldArg.Name); + Pass80UnstripMethods.ResolveTypeInNewAssembliesRaw(globalContext, fieldArg.DeclaringType!.ToTypeSignature(), imports); + if (fieldDeclarer == null) + return false; + var newField = fieldDeclarer.Resolve()?.Fields.SingleOrDefault(it => it.Name == fieldArg.Name); if (newField != null) { - targetBuilder.Emit(bodyInstruction.OpCode, imports.Module.ImportReference(newField)); + var newInstruction = targetBuilder.Add(bodyInstruction.OpCode, imports.Module.DefaultImporter.ImportField(newField)); + instructionMap.Add(bodyInstruction, newInstruction); } else { if (bodyInstruction.OpCode == OpCodes.Ldfld || bodyInstruction.OpCode == OpCodes.Ldsfld) { - var getterMethod = fieldDeclarer.Resolve().Properties + var getterMethod = fieldDeclarer.Resolve()?.Properties .SingleOrDefault(it => it.Name == fieldArg.Name)?.GetMethod; - if (getterMethod == null) return false; + if (getterMethod == null) + return false; - targetBuilder.Emit(OpCodes.Call, imports.Module.ImportReference(getterMethod)); + var newInstruction = targetBuilder.Add(OpCodes.Call, imports.Module.DefaultImporter.ImportMethod(getterMethod)); + instructionMap.Add(bodyInstruction, newInstruction); } else if (bodyInstruction.OpCode == OpCodes.Stfld || bodyInstruction.OpCode == OpCodes.Stsfld) { - var setterMethod = fieldDeclarer.Resolve().Properties + var setterMethod = fieldDeclarer.Resolve()?.Properties .SingleOrDefault(it => it.Name == fieldArg.Name)?.SetMethod; - if (setterMethod == null) return false; + if (setterMethod == null) + return false; - targetBuilder.Emit(OpCodes.Call, imports.Module.ImportReference(setterMethod)); + var newInstruction = targetBuilder.Add(OpCodes.Call, imports.Module.DefaultImporter.ImportMethod(setterMethod)); + instructionMap.Add(bodyInstruction, newInstruction); } else { + //Ldflda, Ldsflda return false; } } } - else if (bodyInstruction.OpCode.OperandType == OperandType.InlineMethod) + else if (bodyInstruction.OpCode.OperandType == CilOperandType.InlineMethod) { - var methodArg = (MethodReference)bodyInstruction.Operand; + var methodArg = (IMethodDescriptor)bodyInstruction.Operand; var methodDeclarer = - Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, methodArg.DeclaringType, imports); - if (methodDeclarer == null) return false; // todo: generic methods + Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, methodArg.DeclaringType?.ToTypeSignature(), imports); + if (methodDeclarer == null) + return false; // todo: generic methods var newReturnType = - Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, methodArg.ReturnType, imports); - if (newReturnType == null) return false; + Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, methodArg.Signature?.ReturnType, imports); + if (newReturnType == null) + return false; - var newMethod = new MethodReference(methodArg.Name, newReturnType, methodDeclarer); - newMethod.HasThis = methodArg.HasThis; - foreach (var methodArgParameter in methodArg.Parameters) + var newMethodSignature = methodArg.Signature!.HasThis + ? MethodSignature.CreateInstance(newReturnType, methodArg.Signature.GenericParameterCount) + : MethodSignature.CreateStatic(newReturnType, methodArg.Signature.GenericParameterCount); + foreach (var methodArgParameter in methodArg.Signature.ParameterTypes) { var newParamType = Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, - methodArgParameter.ParameterType, imports); - if (newParamType == null) return false; + methodArgParameter, imports); + if (newParamType == null) + return false; - var newParam = new ParameterDefinition(methodArgParameter.Name, methodArgParameter.Attributes, - newParamType); - newMethod.Parameters.Add(newParam); + newMethodSignature.ParameterTypes.Add(newParamType); } - targetBuilder.Emit(bodyInstruction.OpCode, imports.Module.ImportReference(newMethod)); + var newMethod = 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 == OperandType.InlineType) + else if (bodyInstruction.OpCode.OperandType == CilOperandType.InlineType) { - var targetType = (TypeReference)bodyInstruction.Operand; - if (targetType is GenericParameter genericParam) + var targetType = ((ITypeDefOrRef)bodyInstruction.Operand).ToTypeSignature(); + if (targetType is GenericParameterSignature genericParam) { - if (genericParam.Owner is TypeReference paramOwner) + if (genericParam.ParameterType is GenericParameterType.Type) { var newTypeOwner = - Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, paramOwner, imports); - if (newTypeOwner == null) return false; - targetType = newTypeOwner.GenericParameters.Single(it => it.Name == targetType.Name); + Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, original.DeclaringType?.ToTypeSignature(), imports)?.Resolve(); + if (newTypeOwner == null) + return false; + targetType = newTypeOwner.GenericParameters.Single(it => it.Name == targetType.Name).ToTypeSignature(); } else { - targetType = target.GenericParameters.Single(it => it.Name == targetType.Name); + targetType = target.GenericParameters.Single(it => it.Name == targetType.Name).ToTypeSignature(); } } else { targetType = Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, targetType, imports); - if (targetType == null) return false; + if (targetType == null) + return false; } if (bodyInstruction.OpCode == OpCodes.Castclass && !targetType.IsValueType) { - targetBuilder.Emit(OpCodes.Call, - imports.Module.ImportReference(new GenericInstanceMethod(imports.Il2CppObjectBase_Cast.Value) - { GenericArguments = { targetType } })); + var newInstruction = targetBuilder.Add(OpCodes.Call, + imports.Module.DefaultImporter.ImportMethod(imports.Il2CppObjectBase_Cast.Value.MakeGenericInstanceMethod(targetType))); + instructionMap.Add(bodyInstruction, newInstruction); } else if (bodyInstruction.OpCode == OpCodes.Isinst && !targetType.IsValueType) { - targetBuilder.Emit(OpCodes.Call, - imports.Module.ImportReference(new GenericInstanceMethod(imports.Il2CppObjectBase_TryCast.Value) - { GenericArguments = { targetType } })); + var newInstruction = targetBuilder.Add(OpCodes.Call, + imports.Module.DefaultImporter.ImportMethod(imports.Il2CppObjectBase_TryCast.Value.MakeGenericInstanceMethod(targetType))); + instructionMap.Add(bodyInstruction, newInstruction); } else if (bodyInstruction.OpCode == OpCodes.Newarr && !targetType.IsValueType) { - targetBuilder.Emit(OpCodes.Conv_I8); - - var il2cppTypeArray = new GenericInstanceType(imports.Il2CppReferenceArray) - { GenericArguments = { targetType } }; - targetBuilder.Emit(OpCodes.Newobj, imports.Module.ImportReference( - new MethodReference(".ctor", imports.Module.Void(), il2cppTypeArray) - { - HasThis = true, - Parameters = { new ParameterDefinition(imports.Module.Long()) } - })); + var newInstruction = targetBuilder.Add(OpCodes.Conv_I8); + + ITypeDefOrRef il2cppTypeArray; + if (targetType.IsValueType) + { + return false; + } + else if (targetType.FullName == "System.String") + { + il2cppTypeArray = imports.Il2CppStringArray.ToTypeDefOrRef(); + } + else + { + il2cppTypeArray = imports.Il2CppReferenceArray.MakeGenericInstanceType(targetType).ToTypeDefOrRef(); + } + targetBuilder.Add(OpCodes.Newobj, imports.Module.DefaultImporter.ImportMethod( + ReferenceCreator.CreateInstanceMethodReference(".ctor", imports.Module.Void(), il2cppTypeArray, imports.Module.Long()))); + instructionMap.Add(bodyInstruction, newInstruction); } else { - targetBuilder.Emit(bodyInstruction.OpCode, targetType); + var newInstruction = targetBuilder.Add(bodyInstruction.OpCode, targetType.ToTypeDefOrRef()); + instructionMap.Add(bodyInstruction, newInstruction); } } - else if (bodyInstruction.OpCode.OperandType == OperandType.InlineSig) + else if (bodyInstruction.OpCode.OperandType == CilOperandType.InlineSig) { // todo: rewrite sig if this ever happens in unity types return false; } - else if (bodyInstruction.OpCode.OperandType == OperandType.InlineTok) + else if (bodyInstruction.OpCode.OperandType == CilOperandType.InlineTok) { - var targetTok = bodyInstruction.Operand as TypeReference; + var targetTok = (bodyInstruction.Operand as ITypeDefOrRef)?.ToTypeSignature(); if (targetTok == null) return false; - if (targetTok is GenericParameter genericParam) + if (targetTok is GenericParameterSignature genericParam) { - if (genericParam.Owner is TypeReference paramOwner) + if (genericParam.ParameterType is GenericParameterType.Type) { var newTypeOwner = - Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, paramOwner, imports); - if (newTypeOwner == null) return false; - targetTok = newTypeOwner.GenericParameters.Single(it => it.Name == targetTok.Name); + Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, original.DeclaringType?.ToTypeSignature(), imports)?.Resolve(); + if (newTypeOwner == null) + return false; + var name = original.DeclaringType!.GenericParameters[genericParam.Index].Name; + targetTok = newTypeOwner.GenericParameters.Single(it => it.Name == name).ToTypeSignature(); } else { - targetTok = target.GenericParameters.Single(it => it.Name == targetTok.Name); + var name = original.GenericParameters[genericParam.Index].Name; + targetTok = target.GenericParameters.Single(it => it.Name == name).ToTypeSignature(); } } else { targetTok = Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, targetTok, imports); - if (targetTok == null) return false; + if (targetTok == null) + return false; } - targetBuilder.Emit(OpCodes.Call, - imports.Module.ImportReference( - new GenericInstanceMethod(imports.Il2CppSystemRuntimeTypeHandleGetRuntimeTypeHandle.Value) - { GenericArguments = { targetTok } })); + var newInstruction = targetBuilder.Add(OpCodes.Call, + imports.Module.DefaultImporter.ImportMethod(imports.Il2CppSystemRuntimeTypeHandleGetRuntimeTypeHandle.Value.MakeGenericInstanceMethod(targetTok))); + instructionMap.Add(bodyInstruction, newInstruction); + } + else if (bodyInstruction.OpCode.OperandType is CilOperandType.InlineSwitch && bodyInstruction.Operand is IReadOnlyList labels) + { + List newLabels = new(labels.Count); + for (var i = 0; i < labels.Count; i++) + { + if (labels[i] is CilInstructionLabel oldLabel) + { + var newLabel = new CilInstructionLabel(); + labelMap.Add(new(oldLabel, newLabel)); + newLabels.Add(newLabel); + } + else + { + return false; + } + } + var newInstruction = targetBuilder.Add(bodyInstruction.OpCode, newLabels); + instructionMap.Add(bodyInstruction, newInstruction); + } + else if (bodyInstruction.Operand is string or Utf8String + || bodyInstruction.Operand.GetType().IsPrimitive) + { + var newInstruction = new CilInstruction(bodyInstruction.OpCode, bodyInstruction.Operand); + targetBuilder.Add(newInstruction); + instructionMap.Add(bodyInstruction, newInstruction); + } + else if (bodyInstruction.Operand is Parameter parameter) + { + var newInstruction = targetBuilder.Add(bodyInstruction.OpCode, target.Parameters.GetBySignatureIndex(parameter.MethodSignatureIndex)); + instructionMap.Add(bodyInstruction, newInstruction); + } + else if (bodyInstruction.Operand is CilLocalVariable localVariable) + { + var newInstruction = targetBuilder.Add(bodyInstruction.OpCode, localVariableMap[localVariable]); + instructionMap.Add(bodyInstruction, newInstruction); + } + else if (bodyInstruction.Operand is CilInstructionLabel label) + { + var newLabel = new CilInstructionLabel(); + labelMap.Add(new(label, newLabel)); + var newInstruction = targetBuilder.Add(bodyInstruction.OpCode, newLabel); + instructionMap.Add(bodyInstruction, newInstruction); } else { - targetBuilder.Append(bodyInstruction); + return false; } + } + + foreach ((var oldLabel, var newLabel) in labelMap) + { + newLabel.Instruction = instructionMap[oldLabel.Instruction!]; + } return true; } public static void ReplaceBodyWithException(MethodDefinition newMethod, RuntimeAssemblyReferences imports) { - newMethod.Body.Variables.Clear(); - newMethod.Body.Instructions.Clear(); - var processor = newMethod.Body.GetILProcessor(); - - processor.Emit(OpCodes.Ldstr, "Method unstripping failed"); - processor.Emit(OpCodes.Newobj, imports.Module.NotSupportedExceptionCtor()); - processor.Emit(OpCodes.Throw); - processor.Emit(OpCodes.Ret); + newMethod.CilMethodBody!.LocalVariables.Clear(); + newMethod.CilMethodBody.Instructions.Clear(); + var processor = newMethod.CilMethodBody.Instructions; + + processor.Add(OpCodes.Ldstr, "Method unstripping failed"); + processor.Add(OpCodes.Newobj, imports.Module.NotSupportedExceptionCtor()); + processor.Add(OpCodes.Throw); + processor.Add(OpCodes.Ret); + } + + //Required for deconstruction on net472 + private static void Deconstruct(this KeyValuePair pair, out CilInstructionLabel key, out CilInstructionLabel value) + { + key = pair.Key; + value = pair.Value; } } diff --git a/Il2CppInterop.Generator/Utils/XrefScanMetadataGenerationUtil.cs b/Il2CppInterop.Generator/Utils/XrefScanMetadataGenerationUtil.cs index d63d0592..bb0355dc 100644 --- a/Il2CppInterop.Generator/Utils/XrefScanMetadataGenerationUtil.cs +++ b/Il2CppInterop.Generator/Utils/XrefScanMetadataGenerationUtil.cs @@ -1,5 +1,3 @@ -using System; -using System.Linq; using Il2CppInterop.Common.XrefScans; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; @@ -24,7 +22,7 @@ private static void FindMetadataInitForMethod(RewriteGlobalContext context, long { var assembly = context.Assemblies.FirstOrDefault(it => - it.OriginalAssembly.Name.Name == metadataInitCandidate.Assembly); + it.OriginalAssembly.Name == metadataInitCandidate.Assembly); var unityObjectCctor = assembly?.TryGetTypeByName(metadataInitCandidate.Type)?.OriginalType.Methods .FirstOrDefault(it => it.Name == metadataInitCandidate.Method); diff --git a/Il2CppInterop.Generator/XrefScans/XrefScanImpl.cs b/Il2CppInterop.Generator/XrefScans/XrefScanImpl.cs index 7faf3569..fbcb3aba 100644 --- a/Il2CppInterop.Generator/XrefScans/XrefScanImpl.cs +++ b/Il2CppInterop.Generator/XrefScans/XrefScanImpl.cs @@ -1,5 +1,4 @@ -using System; -using Il2CppInterop.Common.XrefScans; +using Il2CppInterop.Common.XrefScans; namespace Il2CppInterop.Generator.XrefScans; diff --git a/Il2CppInterop.Runtime/Il2CppInterop.Runtime.csproj b/Il2CppInterop.Runtime/Il2CppInterop.Runtime.csproj index 0815e6b0..6fda3574 100644 --- a/Il2CppInterop.Runtime/Il2CppInterop.Runtime.csproj +++ b/Il2CppInterop.Runtime/Il2CppInterop.Runtime.csproj @@ -28,18 +28,18 @@ - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Il2CppInterop.StructGenerator/CodeGen/CodeGenClass.cs b/Il2CppInterop.StructGenerator/CodeGen/CodeGenClass.cs index ad004fcd..18b95bd7 100644 --- a/Il2CppInterop.StructGenerator/CodeGen/CodeGenClass.cs +++ b/Il2CppInterop.StructGenerator/CodeGen/CodeGenClass.cs @@ -82,4 +82,14 @@ public override string Build() return true; } + + public override bool Equals(object obj) + { + return obj is CodeGenClass @class && this == @class; + } + + public override int GetHashCode() + { + return HashCode.Combine(Fields.Count, NestedElements.Count); + } } diff --git a/Il2CppInterop.StructGenerator/CodeGen/CodeGenEnum.cs b/Il2CppInterop.StructGenerator/CodeGen/CodeGenEnum.cs index af0443ac..f0bdb56c 100644 --- a/Il2CppInterop.StructGenerator/CodeGen/CodeGenEnum.cs +++ b/Il2CppInterop.StructGenerator/CodeGen/CodeGenEnum.cs @@ -32,6 +32,16 @@ public string BuildFrom(CodeGenEnum origin) if (lhs.Name != rhs.Name) return false; return lhs.Value == rhs.Value; } + + public override bool Equals(object obj) + { + return obj is CodeGenEnumElement element && this == element; + } + + public override int GetHashCode() + { + return HashCode.Combine(Name, Value); + } } internal enum EnumUnderlyingType @@ -94,4 +104,14 @@ public override string Build() return false; return true; } + + public override bool Equals(object obj) + { + return obj is CodeGenEnum @enum && this == @enum; + } + + public override int GetHashCode() + { + return HashCode.Combine(Name, UnderlyingType, Elements.Count); + } } diff --git a/Il2CppInterop.StructGenerator/CodeGen/CodeGenField.cs b/Il2CppInterop.StructGenerator/CodeGen/CodeGenField.cs index 74c04002..f656abbe 100644 --- a/Il2CppInterop.StructGenerator/CodeGen/CodeGenField.cs +++ b/Il2CppInterop.StructGenerator/CodeGen/CodeGenField.cs @@ -35,4 +35,14 @@ public override string Build() if (lhs.Name != rhs.Name) return false; return lhs.DefaultValue == rhs.DefaultValue; } + + public override bool Equals(object obj) + { + return obj is CodeGenField field && this == field; + } + + public override int GetHashCode() + { + return HashCode.Combine(Type, Name, DefaultValue); + } } diff --git a/Il2CppInterop.StructGenerator/Il2CppInterop.StructGenerator.csproj b/Il2CppInterop.StructGenerator/Il2CppInterop.StructGenerator.csproj index 10e1a8ea..0fa1a0cc 100644 --- a/Il2CppInterop.StructGenerator/Il2CppInterop.StructGenerator.csproj +++ b/Il2CppInterop.StructGenerator/Il2CppInterop.StructGenerator.csproj @@ -8,16 +8,16 @@ - - - + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - diff --git a/Il2CppInterop.StructGenerator/Utilities/UnityVersion.cs b/Il2CppInterop.StructGenerator/Utilities/UnityVersion.cs index 371f897d..797d6fd1 100644 --- a/Il2CppInterop.StructGenerator/Utilities/UnityVersion.cs +++ b/Il2CppInterop.StructGenerator/Utilities/UnityVersion.cs @@ -86,4 +86,11 @@ public override string ToString() } private readonly ulong myMBlob; + + public override readonly bool Equals(object obj) + { + return obj is UnityVersion version && this == version; + } + + public override readonly int GetHashCode() => myMBlob.GetHashCode(); }