Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Ldelem and Stelem Unstripping #184

Merged
merged 4 commits into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Il2CppInterop.Generator/Utils/RuntimeAssemblyReferences.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public RuntimeAssemblyReferences(ModuleDefinition module, RewriteGlobalContext g
public Lazy<IMethodDefOrRef> Il2CppStringArrayctor_size { get; private set; }
public Memoize<TypeSignature, IMethodDefOrRef> Il2CppStructArrayctor_size { get; private set; }
public Lazy<IMethodDefOrRef> Il2CppArrayBase_get_Length { get; private set; }
public Memoize<TypeSignature, IMethodDefOrRef> Il2CppArrayBase_get_Item { get; private set; }
public Memoize<TypeSignature, IMethodDefOrRef> Il2CppArrayBase_set_Item { get; private set; }
public Lazy<IMethodDefOrRef> IL2CPP_Il2CppObjectBaseToPtr { get; private set; }
public Lazy<IMethodDefOrRef> IL2CPP_Il2CppObjectBaseToPtrNotNull { get; private set; }
public Lazy<IMethodDefOrRef> IL2CPP_Il2CppStringToManaged { get; private set; }
Expand Down Expand Up @@ -122,6 +124,8 @@ private void InitTypeRefs()

var nonGenericIl2CppArrayBase = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppArrayBase").ToTypeSignature();

var genericIl2CppArrayBase = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppArrayBase`1").ToTypeSignature();

Il2CppStructArray = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppStructArray`1").ToTypeSignature();

Il2CppReferenceArray = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppReferenceArray`1").ToTypeSignature();
Expand All @@ -140,6 +144,7 @@ private void InitTypeRefs()
allTypes["Il2CppInterop.Runtime.InteropTypes.Il2CppObjectBase"] = Il2CppObjectBase;
allTypes["Il2CppInterop.Runtime.Runtime.Il2CppObjectPool"] = Il2CppObjectPool;
allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppArrayBase"] = nonGenericIl2CppArrayBase;
allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppArrayBase<T>"] = genericIl2CppArrayBase;
allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStringArray"] = Il2CppStringArray;
allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppReferenceArray<T>"] = Il2CppReferenceArray;
allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStructArray<T>"] = Il2CppStructArray;
Expand Down Expand Up @@ -211,6 +216,24 @@ private void InitMethodRefs()
return mr;
});

Il2CppArrayBase_get_Item = new((param) =>
{
var owner = ResolveType("Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppArrayBase<T>");
var giOwner = owner.MakeGenericInstanceType(param).ToTypeDefOrRef();
var mr = ReferenceCreator.CreateInstanceMethodReference("get_Item", new GenericParameterSignature(Module, GenericParameterType.Type, 0),
giOwner, ResolveType("System.Int32"));
return mr;
});

Il2CppArrayBase_set_Item = new((param) =>
{
var owner = ResolveType("Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppArrayBase<T>");
var giOwner = owner.MakeGenericInstanceType(param).ToTypeDefOrRef();
var mr = ReferenceCreator.CreateInstanceMethodReference("set_Item", Module.Void(),
giOwner, ResolveType("System.Int32"), new GenericParameterSignature(Module, GenericParameterType.Type, 0));
return mr;
});

IL2CPP_Il2CppObjectBaseToPtr = new Lazy<IMethodDefOrRef>(() =>
{
var mr = ReferenceCreator.CreateStaticMethodReference("Il2CppObjectBaseToPtr", ResolveType("System.IntPtr"),
Expand Down
80 changes: 66 additions & 14 deletions Il2CppInterop.Generator/Utils/UnstripTranslator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,34 +57,69 @@ public static bool TranslateMethod(MethodDefinition original, MethodDefinition t
imports.Module.DefaultImporter.ImportMethod(imports.Il2CppArrayBase_get_Length.Value));
break;

case CilCode.Ldelema:
//This is Il2CppArrayBase<T>.Pointer + index * sizeof(T) but the T is not known because the operand is null.
case CilCode.Ldelem_Ref:
//This is Il2CppReferenceArray<T>.get_Item but the T is not known because the operand is null.
return false;

case CilCode.Ldelem:
//This is Il2CppArrayBase<T>.set_Item but the T is not known because the operand is null.
case CilCode.Stelem_Ref:
//This is Il2CppReferenceArray<T>.set_Item but the T is not known because the operand is null.
return false;

case CilCode.Stelem:
//This is Il2CppArrayBase<T>.set_Item but the T is not known because the operand is null.
case CilCode.Ldelem_I1:
case CilCode.Ldelem_I2:
case CilCode.Ldelem_I4:
case CilCode.Ldelem_U4:
//This is Il2CppArrayBase<T>.get_Item but the T could be either the cooresponding primitive or an enum.
return false;

case CilCode.Ldelem_Ref:
//This is Il2CppReferenceArray<T>.get_Item but the T is not known because the operand is null.
case CilCode.Ldelem_U1:
//This is Il2CppArrayBase<T>.get_Item but the T could be either byte, bool, or an enum.
return false;

case CilCode.Stelem_Ref:
//This is Il2CppReferenceArray<T>.set_Item but the T is not known because the operand is null.
case CilCode.Ldelem_U2:
//This is Il2CppArrayBase<T>.get_Item but the T could be either ushort, char, or an enum.
return false;

case CilCode.Ldelem_I8:
//This is Il2CppArrayBase<T>.get_Item but the T could be either signed, unsigned, or an enum.
return false;

case >= CilCode.Ldelem_I1 and <= CilCode.Ldelem_R8:
//This is Il2CppStructArray<T>.get_Item
case CilCode.Ldelem_I:
//This is Il2CppArrayBase<T>.get_Item but the T could be either signed, unsigned, or a pointer.
return false;

case >= CilCode.Stelem_I and <= CilCode.Stelem_R8:
case CilCode.Ldelem_R4:
{
var getMethod = imports.Il2CppArrayBase_get_Item.Get(imports.Module.CorLibTypeFactory.Single);
newInstruction = targetBuilder.Add(OpCodes.Callvirt, imports.Module.DefaultImporter.ImportMethod(getMethod));
}
break;

case CilCode.Ldelem_R8:
{
var getMethod = imports.Il2CppArrayBase_get_Item.Get(imports.Module.CorLibTypeFactory.Double);
newInstruction = targetBuilder.Add(OpCodes.Callvirt, imports.Module.DefaultImporter.ImportMethod(getMethod));
}
break;

case >= CilCode.Stelem_I and <= CilCode.Stelem_I8:
//This is Il2CppStructArray<T>.set_Item
return false;

case CilCode.Stelem_R4:
{
var setMethod = imports.Il2CppArrayBase_set_Item.Get(imports.Module.CorLibTypeFactory.Single);
newInstruction = targetBuilder.Add(OpCodes.Callvirt, imports.Module.DefaultImporter.ImportMethod(setMethod));
}
break;

case CilCode.Stelem_R8:
{
var setMethod = imports.Il2CppArrayBase_set_Item.Get(imports.Module.CorLibTypeFactory.Double);
newInstruction = targetBuilder.Add(OpCodes.Callvirt, imports.Module.DefaultImporter.ImportMethod(setMethod));
}
break;

case >= CilCode.Ldind_I1 and <= CilCode.Ldind_Ref:
//This is for by ref parameters
goto default;
Expand Down Expand Up @@ -239,7 +274,7 @@ public static bool TranslateMethod(MethodDefinition original, MethodDefinition t
imports.Module.DefaultImporter.ImportMethod(imports.Il2CppObjectBase_TryCast.Value.MakeGenericInstanceMethod(targetType)));
instructionMap.Add(bodyInstruction, newInstruction);
}
else if (bodyInstruction.OpCode == OpCodes.Newarr && !targetType.IsValueType)
else if (bodyInstruction.OpCode == OpCodes.Newarr)
{
var newInstruction = targetBuilder.Add(OpCodes.Conv_I8);

Expand All @@ -260,6 +295,23 @@ public static bool TranslateMethod(MethodDefinition original, MethodDefinition t
ReferenceCreator.CreateInstanceMethodReference(".ctor", imports.Module.Void(), il2cppTypeArray, imports.Module.Long())));
instructionMap.Add(bodyInstruction, newInstruction);
}
else if (bodyInstruction.OpCode == OpCodes.Ldelema)
{
// Not implemented
return false;
}
else if (bodyInstruction.OpCode == OpCodes.Ldelem)
{
var getMethod = imports.Il2CppArrayBase_get_Item.Get(targetType);
var newInstruction = targetBuilder.Add(OpCodes.Callvirt, imports.Module.DefaultImporter.ImportMethod(getMethod));
instructionMap.Add(bodyInstruction, newInstruction);
}
else if (bodyInstruction.OpCode == OpCodes.Stelem)
{
var setMethod = imports.Il2CppArrayBase_set_Item.Get(targetType);
var newInstruction = targetBuilder.Add(OpCodes.Callvirt, imports.Module.DefaultImporter.ImportMethod(setMethod));
instructionMap.Add(bodyInstruction, newInstruction);
}
else
{
var newInstruction = targetBuilder.Add(bodyInstruction.OpCode, targetType.ToTypeDefOrRef());
Expand Down
Loading