diff --git a/Il2CppInterop.Generator/Extensions/AsmResolverExtensions.cs b/Il2CppInterop.Generator/Extensions/AsmResolverExtensions.cs index 7788790f..e6a1c2b4 100644 --- a/Il2CppInterop.Generator/Extensions/AsmResolverExtensions.cs +++ b/Il2CppInterop.Generator/Extensions/AsmResolverExtensions.cs @@ -53,6 +53,10 @@ private static Parameter GetArgument(this ILProcessor instructions, int argument public static bool IsNested(this TypeSignature type) => type.DeclaringType is not null; + public static bool IsPointerLike(this TypeSignature type) => type is PointerTypeSignature or ByReferenceTypeSignature; + + public static bool IsValueTypeLike(this TypeSignature type) => type.IsValueType || type.IsPointerLike(); + public static bool IsSystemEnum(this GenericParameterConstraint constraint) => constraint.Constraint?.FullName is "System.Enum"; public static bool IsSystemValueType(this GenericParameterConstraint constraint) => constraint.Constraint?.FullName is "System.ValueType"; diff --git a/Il2CppInterop.Generator/Extensions/ILGeneratorEx.cs b/Il2CppInterop.Generator/Extensions/ILGeneratorEx.cs index 75d4002f..5c1ee845 100644 --- a/Il2CppInterop.Generator/Extensions/ILGeneratorEx.cs +++ b/Il2CppInterop.Generator/Extensions/ILGeneratorEx.cs @@ -31,6 +31,13 @@ public static void EmitObjectStore(this ILProcessor body, TypeSignature original body.Add(OpCodes.Call, imports.IL2CPP_ManagedStringToIl2Cpp.Value); body.Add(OpCodes.Call, imports.WriteFieldWBarrier); } + else if (originalType.IsPointerLike()) + { + Debug.Assert(newType.IsPointerLike()); + body.AddLoadArgument(argumentIndex); + body.Add(OpCodes.Stobj, newType.ToTypeDefOrRef()); + body.Add(OpCodes.Pop); + } else if (originalType.IsValueType) { var typeSpecifics = enclosingType.AssemblyContext.GlobalContext.JudgeSpecificsByOriginalType(originalType); @@ -182,6 +189,11 @@ public static void EmitObjectToPointer(this ILProcessor body, TypeSignature orig body.Add(OpCodes.Conv_I); } } + else if (originalType.IsPointerLike()) + { + Debug.Assert(newType.IsPointerLike()); + body.AddLoadArgument(argumentIndex); + } else if (originalType.IsValueType) { if (newType.IsValueType) @@ -285,6 +297,11 @@ public static void EmitPointerToObject(this ILProcessor body, TypeSignature orig { // do nothing } + else if (originalReturnType.IsPointerLike()) + { + Debug.Assert(convertedReturnType.IsPointerLike()); + body.Add(OpCodes.Ldloc, pointerVariable); + } else if (originalReturnType.IsValueType) { if (convertedReturnType.IsValueType) diff --git a/Il2CppInterop.Generator/Utils/FieldAccessorGenerator.cs b/Il2CppInterop.Generator/Utils/FieldAccessorGenerator.cs index 8200f8b7..3eeb0bd2 100644 --- a/Il2CppInterop.Generator/Utils/FieldAccessorGenerator.cs +++ b/Il2CppInterop.Generator/Utils/FieldAccessorGenerator.cs @@ -79,6 +79,9 @@ public static void MakeGetter(FieldDefinition field, FieldRewriteContext fieldCo getterBody.EmitPointerToObject(fieldContext.OriginalField.Signature!.FieldType, property.Signature.ReturnType, fieldContext.DeclaringType, local0, !field.IsStatic, false); + if (property.Signature.ReturnType.IsPointerLike()) + getterBody.Add(OpCodes.Ldind_I); + getterBody.Add(OpCodes.Ret); property.GetMethod = getter; diff --git a/Il2CppInterop.Generator/Utils/UnstripGenerator.cs b/Il2CppInterop.Generator/Utils/UnstripGenerator.cs index 8db431e1..1f9901fe 100644 --- a/Il2CppInterop.Generator/Utils/UnstripGenerator.cs +++ b/Il2CppInterop.Generator/Utils/UnstripGenerator.cs @@ -81,7 +81,7 @@ public static void GenerateInvokerMethodBody(MethodDefinition newMethod, FieldDe } body.Add(OpCodes.Call, delegateType.Methods.Single(it => it.Name == "Invoke")); - if (!newMethod.Signature!.ReturnType.IsValueType) + if (!newMethod.Signature!.ReturnType.IsValueTypeLike()) { var pointerVar = new CilLocalVariable(imports.Module.IntPtr()); newMethod.CilMethodBody.LocalVariables.Add(pointerVar);