Patcher correctly translates catch clauses
This commit is contained in:
@@ -12,19 +12,9 @@ namespace Torch.Managers.PatchManager.MSIL
|
||||
/// </summary>
|
||||
public enum MsilTryCatchOperationType
|
||||
{
|
||||
// TryCatchBlockIL:
|
||||
// var exBlock = ILGenerator.BeginExceptionBlock();
|
||||
// try{
|
||||
// ILGenerator.BeginCatchBlock(typeof(Exception));
|
||||
// } catch(Exception e) {
|
||||
// ILGenerator.BeginCatchBlock(null);
|
||||
// } catch {
|
||||
// ILGenerator.BeginFinallyBlock();
|
||||
// }finally {
|
||||
// ILGenerator.EndExceptionBlock();
|
||||
// }
|
||||
BeginExceptionBlock,
|
||||
BeginCatchBlock,
|
||||
BeginClauseBlock,
|
||||
BeginFaultBlock,
|
||||
BeginFinallyBlock,
|
||||
EndExceptionBlock
|
||||
}
|
||||
@@ -46,9 +36,11 @@ namespace Torch.Managers.PatchManager.MSIL
|
||||
public MsilTryCatchOperation(MsilTryCatchOperationType op, Type caughtType = null)
|
||||
{
|
||||
Type = op;
|
||||
if (caughtType != null && op != MsilTryCatchOperationType.BeginCatchBlock)
|
||||
if (caughtType != null && op != MsilTryCatchOperationType.BeginClauseBlock)
|
||||
throw new ArgumentException($"Can't use caught type with operation type {op}", nameof(caughtType));
|
||||
CatchType = caughtType;
|
||||
}
|
||||
|
||||
public override string ToString() => $"{Type} -> {CatchType}";
|
||||
}
|
||||
}
|
||||
|
@@ -43,10 +43,8 @@ namespace Torch.Managers.PatchManager.Transpile
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma warning disable 649
|
||||
[ReflectedMethod(Name = "BakeByteArray")]
|
||||
private static Func<ILGenerator, byte[]> _ilGeneratorBakeByteArray;
|
||||
[ReflectedMethod(Name = "BakeByteArray")] private static Func<ILGenerator, byte[]> _ilGeneratorBakeByteArray;
|
||||
#pragma warning restore 649
|
||||
|
||||
public MethodContext(DynamicMethod method)
|
||||
@@ -72,11 +70,11 @@ namespace Torch.Managers.PatchManager.Transpile
|
||||
using (var reader = new BinaryReader(memory))
|
||||
while (memory.Length > memory.Position)
|
||||
{
|
||||
var opcodeOffset = (int)memory.Position;
|
||||
var instructionValue = (short)memory.ReadByte();
|
||||
var opcodeOffset = (int) memory.Position;
|
||||
var instructionValue = (short) memory.ReadByte();
|
||||
if (Prefixes.Contains(instructionValue))
|
||||
{
|
||||
instructionValue = (short)((instructionValue << 8) | memory.ReadByte());
|
||||
instructionValue = (short) ((instructionValue << 8) | memory.ReadByte());
|
||||
}
|
||||
if (!OpCodeLookup.TryGetValue(instructionValue, out OpCode opcode))
|
||||
{
|
||||
@@ -86,7 +84,8 @@ namespace Torch.Managers.PatchManager.Transpile
|
||||
continue;
|
||||
}
|
||||
if (opcode.Size != memory.Position - opcodeOffset)
|
||||
throw new Exception($"Opcode said it was {opcode.Size} but we read {memory.Position - opcodeOffset}");
|
||||
throw new Exception(
|
||||
$"Opcode said it was {opcode.Size} but we read {memory.Position - opcodeOffset}");
|
||||
var instruction = new MsilInstruction(opcode)
|
||||
{
|
||||
Offset = opcodeOffset
|
||||
@@ -105,16 +104,24 @@ namespace Torch.Managers.PatchManager.Transpile
|
||||
var beginInstruction = FindInstruction(clause.TryOffset);
|
||||
var catchInstruction = FindInstruction(clause.HandlerOffset);
|
||||
var finalInstruction = FindInstruction(clause.HandlerOffset + clause.HandlerLength);
|
||||
beginInstruction.TryCatchOperation = new MsilTryCatchOperation(MsilTryCatchOperationType.BeginExceptionBlock);
|
||||
if ((clause.Flags & ExceptionHandlingClauseOptions.Clause) != 0)
|
||||
catchInstruction.TryCatchOperation = new MsilTryCatchOperation(MsilTryCatchOperationType.BeginCatchBlock, clause.CatchType);
|
||||
beginInstruction.TryCatchOperation =
|
||||
new MsilTryCatchOperation(MsilTryCatchOperationType.BeginExceptionBlock);
|
||||
if ((clause.Flags & ExceptionHandlingClauseOptions.Fault) != 0)
|
||||
catchInstruction.TryCatchOperation =
|
||||
new MsilTryCatchOperation(MsilTryCatchOperationType.BeginFaultBlock);
|
||||
else if ((clause.Flags & ExceptionHandlingClauseOptions.Finally) != 0)
|
||||
catchInstruction.TryCatchOperation = new MsilTryCatchOperation(MsilTryCatchOperationType.BeginFinallyBlock);
|
||||
finalInstruction.TryCatchOperation = new MsilTryCatchOperation(MsilTryCatchOperationType.EndExceptionBlock);
|
||||
catchInstruction.TryCatchOperation =
|
||||
new MsilTryCatchOperation(MsilTryCatchOperationType.BeginFinallyBlock);
|
||||
else
|
||||
catchInstruction.TryCatchOperation =
|
||||
new MsilTryCatchOperation(MsilTryCatchOperationType.BeginClauseBlock, clause.CatchType);
|
||||
|
||||
finalInstruction.TryCatchOperation =
|
||||
new MsilTryCatchOperation(MsilTryCatchOperationType.EndExceptionBlock);
|
||||
}
|
||||
}
|
||||
|
||||
private MsilInstruction FindInstruction(int offset)
|
||||
public MsilInstruction FindInstruction(int offset)
|
||||
{
|
||||
int min = 0, max = _instructions.Count;
|
||||
while (min != max)
|
||||
@@ -153,14 +160,14 @@ namespace Torch.Managers.PatchManager.Transpile
|
||||
Prefixes = new HashSet<short>();
|
||||
foreach (FieldInfo field in typeof(OpCodes).GetFields(BindingFlags.Static | BindingFlags.Public))
|
||||
{
|
||||
var opcode = (OpCode)field.GetValue(null);
|
||||
var opcode = (OpCode) field.GetValue(null);
|
||||
if (opcode.OpCodeType != OpCodeType.Nternal)
|
||||
OpCodeLookup.Add(opcode.Value, opcode);
|
||||
if ((ushort)opcode.Value > 0xFF)
|
||||
if ((ushort) opcode.Value > 0xFF)
|
||||
{
|
||||
Prefixes.Add((short)((ushort)opcode.Value >> 8));
|
||||
Prefixes.Add((short) ((ushort) opcode.Value >> 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -60,9 +60,12 @@ namespace Torch.Managers.PatchManager.Transpile
|
||||
case MsilTryCatchOperationType.BeginExceptionBlock:
|
||||
target.BeginExceptionBlock();
|
||||
break;
|
||||
case MsilTryCatchOperationType.BeginCatchBlock:
|
||||
case MsilTryCatchOperationType.BeginClauseBlock:
|
||||
target.BeginCatchBlock(il.TryCatchOperation.CatchType);
|
||||
break;
|
||||
case MsilTryCatchOperationType.BeginFaultBlock:
|
||||
target.BeginFaultBlock();
|
||||
break;
|
||||
case MsilTryCatchOperationType.BeginFinallyBlock:
|
||||
target.BeginFinallyBlock();
|
||||
break;
|
||||
@@ -80,11 +83,12 @@ namespace Torch.Managers.PatchManager.Transpile
|
||||
|
||||
// Leave opcodes emitted by these:
|
||||
if (il.OpCode == OpCodes.Endfilter && ilNext?.TryCatchOperation?.Type ==
|
||||
MsilTryCatchOperationType.BeginCatchBlock)
|
||||
MsilTryCatchOperationType.BeginClauseBlock)
|
||||
continue;
|
||||
if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S) &&
|
||||
(ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.EndExceptionBlock ||
|
||||
ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.BeginCatchBlock ||
|
||||
ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.BeginClauseBlock ||
|
||||
ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.BeginFaultBlock ||
|
||||
ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.BeginFinallyBlock))
|
||||
continue;
|
||||
if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S || il.OpCode == OpCodes.Endfinally) &&
|
||||
@@ -175,7 +179,7 @@ namespace Torch.Managers.PatchManager.Transpile
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (k.OpCode == OpCodes.Br || k.OpCode == OpCodes.Br_S)
|
||||
if (k.OpCode == OpCodes.Br || k.OpCode == OpCodes.Br_S || k.OpCode == OpCodes.Leave || k.OpCode == OpCodes.Leave_S)
|
||||
unreachable = true;
|
||||
}
|
||||
foreach (var k in data)
|
||||
|
Reference in New Issue
Block a user