From 3a04232e93bec7ef9f27dcb6d09afd7e46104290 Mon Sep 17 00:00:00 2001 From: Lillie <75392499+iLillie@users.noreply.github.com> Date: Mon, 8 Jun 2026 22:34:42 +0200 Subject: [PATCH 1/3] fix: Call WriteLine for Unknown operand and Non static method called without 'this' param error --- Cpp2IL.Core/IlGenerator.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Cpp2IL.Core/IlGenerator.cs b/Cpp2IL.Core/IlGenerator.cs index 7f244446..c68b114d 100644 --- a/Cpp2IL.Core/IlGenerator.cs +++ b/Cpp2IL.Core/IlGenerator.cs @@ -212,7 +212,10 @@ private static List GenerateInstructions(Instruction instruction if ((instruction.Operands.Count - 1) >= thisParamIndex) LoadOperand(instruction.Operands[thisParamIndex], method, locals, writeLine, stringCtor); else + { instructions.Add(CilOpCodes.Ldstr, $"Non static method called without 'this' param ({instruction})"); + instructions.Add(CilOpCodes.Call, importer.ImportMethod(writeLine)); + } } // Load normal params @@ -439,7 +442,7 @@ private static void LoadOperand(object operand, MethodDefinition method, break; default: instructions.Add(CilOpCodes.Ldstr, "Unknown operand: " + operand.ToString()); - instructions.Add(CilOpCodes.Newobj, importer.ImportMethod(stringCtor)); + instructions.Add(CilOpCodes.Call, importer.ImportMethod(writeLine)); break; } } From f427f8c65f862510a90183220d651c5411ca8f33 Mon Sep 17 00:00:00 2001 From: Lillie <75392499+iLillie@users.noreply.github.com> Date: Mon, 8 Jun 2026 22:37:12 +0200 Subject: [PATCH 2/3] fix(NewArmV8InstructionSet): properly add call instructions and return ParameterOperands --- .../InstructionSets/NewArmV8InstructionSet.cs | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/Cpp2IL.Core/InstructionSets/NewArmV8InstructionSet.cs b/Cpp2IL.Core/InstructionSets/NewArmV8InstructionSet.cs index 60eb8890..6f5bc2ef 100644 --- a/Cpp2IL.Core/InstructionSets/NewArmV8InstructionSet.cs +++ b/Cpp2IL.Core/InstructionSets/NewArmV8InstructionSet.cs @@ -48,7 +48,8 @@ public override Memory GetRawBytesForMethod(MethodAnalysisContext context, public override List GetParameterOperandsFromMethod(MethodAnalysisContext context) { - return []; + // Is this correct (?) + return GetArgumentOperandsForCall(context); } public override List GetIsilFromMethod(MethodAnalysisContext context) @@ -97,10 +98,21 @@ private void ConvertInstructionStatement(Arm64Instruction instruction, List context.UnderlyingPointer + (ulong)context.RawBytes.Length) { //Unconditional branch to outside the method, treat as call (tail-call, specifically) followed by return - - Add(address, OpCode.Call, instruction.BranchTarget, GetArgumentOperandsForCall(context, instruction.BranchTarget).ToArray()); var returnRegister2 = GetReturnRegisterForContext(context); + AddCall(context, returnRegister2, address, target); + if (returnRegister2 == null) Add(address, OpCode.Return); else @@ -527,15 +539,8 @@ private object ConvertOperand(Arm64Instruction instruction, int operand) return new Register(null, nameof(Arm64Register.X0)); } - private List GetArgumentOperandsForCall(MethodAnalysisContext contextBeingAnalyzed, ulong callAddr) + private List GetArgumentOperandsForCall(MethodAnalysisContext contextBeingCalled) { - if (!contextBeingAnalyzed.AppContext.MethodsByAddress.TryGetValue(callAddr, out var methodsAtAddress)) - //TODO - return []; - - //For the sake of arguments, all we care about is the first method at the address, because they'll only be shared if they have the same signature. - var contextBeingCalled = methodsAtAddress.First(); - var vectorCount = 0; var nonVectorCount = 0; @@ -572,4 +577,13 @@ private List GetArgumentOperandsForCall(MethodAnalysisContext contextBei return ret; } + + private List GetArgumentOperandsForCall(MethodAnalysisContext contextBeingAnalyzed, ulong callAddr) + { + if (!contextBeingAnalyzed.AppContext.MethodsByAddress.TryGetValue(callAddr, out var methodsAtAddress)) + //TODO + return []; + + return GetArgumentOperandsForCall(methodsAtAddress.First()); + } } From abc0754565945f23daf4b8c045e380af83c212c9 Mon Sep 17 00:00:00 2001 From: Lillie <75392499+iLillie@users.noreply.github.com> Date: Mon, 8 Jun 2026 22:38:14 +0200 Subject: [PATCH 3/3] fix(LocalVariables): Add check for ParameterOperands and better document thisParam --- Cpp2IL.Core/Analysis/LocalVariables.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Cpp2IL.Core/Analysis/LocalVariables.cs b/Cpp2IL.Core/Analysis/LocalVariables.cs index 00cccc85..615b7ce3 100644 --- a/Cpp2IL.Core/Analysis/LocalVariables.cs +++ b/Cpp2IL.Core/Analysis/LocalVariables.cs @@ -80,7 +80,7 @@ public static void CreateAll(MethodAnalysisContext method) var operandOffset = method.IsStatic ? 0 : 1; // 'this' // 'this' param - if (!method.IsStatic && method.Locals.Count > 0) + if (!method.IsStatic && method.Locals.Count > 0 && method.ParameterOperands.Count > 0) { var thisOperand = (Register)method.ParameterOperands[0]; var thisLocal = method.Locals.FirstOrDefault(l => l.Register.Number == thisOperand.Number && l.Register.Version == -1); @@ -352,9 +352,22 @@ private static bool PropagateFromCallParameters(MethodAnalysisContext method) calledMethod.Name is ".ctor" or ".cctor" ? calledMethod.DeclaringType : calledMethod.ReturnType); } + + // Call operands + // 0. Target + // 1. ReturnValue + // 2. thisParam + // ... parameters + + // CallVoid operands + // 0. Target + // 1. thisParam + // ... parameters + var thisParamIndex = instruction.OpCode == OpCode.CallVoid ? 1 : 2; + // 'this' param if (!calledMethod.IsStatic - && instruction.Operands[instruction.OpCode == OpCode.CallVoid ? 1 : 2] is LocalVariable thisParam) + && instruction.Operands[thisParamIndex] is LocalVariable thisParam) { changed |= SetTypeIfUnknown(thisParam, calledMethod.DeclaringType); }