Skip to content
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
17 changes: 15 additions & 2 deletions Cpp2IL.Core/Analysis/LocalVariables.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down
5 changes: 4 additions & 1 deletion Cpp2IL.Core/IlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,10 @@ private static List<CilInstruction> 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
Expand Down Expand Up @@ -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;
}
}
Expand Down
42 changes: 28 additions & 14 deletions Cpp2IL.Core/InstructionSets/NewArmV8InstructionSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ public override Memory<byte> GetRawBytesForMethod(MethodAnalysisContext context,

public override List<object> GetParameterOperandsFromMethod(MethodAnalysisContext context)
{
return [];
// Is this correct (?)
return GetArgumentOperandsForCall(context);
}

public override List<Instruction> GetIsilFromMethod(MethodAnalysisContext context)
Expand Down Expand Up @@ -97,10 +98,21 @@ private void ConvertInstructionStatement(Arm64Instruction instruction, List<Inst
{
var address = instruction.Address;

void Add(ulong address, OpCode opCode, params object[] operands)
Instruction Add(ulong address, OpCode opCode, params object[] operands)
{
addresses.Add(address);
instructions.Add(new Instruction(instructions.Count, opCode, operands));
var newInstruction = new Instruction(instructions.Count, opCode, operands);
instructions.Add(newInstruction);
return newInstruction;
}

void AddCall(MethodAnalysisContext context, object? returnRegister2, ulong address, ulong target)
{
var call = returnRegister2 == null ?
Add(address, OpCode.CallVoid, target) :
Add(address, OpCode.Call, target, returnRegister2);

call.Operands.AddRange(GetArgumentOperandsForCall(context, target));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AddRange is required here since previously the ArgumentOperands would be System.Object[] instead of correctly being provided as params.

This is because of C# extracting arrays if it's the only argument to params, but if there are more, it gets appended as a System.Object[] instead of appending each item in the array.

}

switch (instruction.Mnemonic)
Expand Down Expand Up @@ -238,7 +250,7 @@ void Add(ulong address, OpCode opCode, params object[] operands)
Add(address, OpCode.Move, dest2, mem2);
break;
case Arm64Mnemonic.BL:
Add(address, OpCode.Call, instruction.BranchTarget, GetArgumentOperandsForCall(context, instruction.BranchTarget).ToArray());
AddCall(context, GetReturnRegisterForContext(context), address, instruction.BranchTarget);
break;
case Arm64Mnemonic.RET:
var returnRegister = GetReturnRegisterForContext(context);
Expand All @@ -253,9 +265,9 @@ void Add(ulong address, OpCode opCode, params object[] operands)
if (target < context.UnderlyingPointer || target > 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
Expand Down Expand Up @@ -527,15 +539,8 @@ private object ConvertOperand(Arm64Instruction instruction, int operand)
return new Register(null, nameof(Arm64Register.X0));
}

private List<object> GetArgumentOperandsForCall(MethodAnalysisContext contextBeingAnalyzed, ulong callAddr)
private List<object> 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;

Expand Down Expand Up @@ -572,4 +577,13 @@ private List<object> GetArgumentOperandsForCall(MethodAnalysisContext contextBei

return ret;
}

private List<object> GetArgumentOperandsForCall(MethodAnalysisContext contextBeingAnalyzed, ulong callAddr)
{
if (!contextBeingAnalyzed.AppContext.MethodsByAddress.TryGetValue(callAddr, out var methodsAtAddress))
//TODO
return [];

return GetArgumentOperandsForCall(methodsAtAddress.First());
}
}
Loading