Skip to content

Commit

Permalink
Merge pull request #203 from nike4613/dont-chage-opcodes
Browse files Browse the repository at this point in the history
Relink variable definitions when cloning DMD bodies
nike4613 authored Dec 12, 2024
2 parents 80b16bf + ac6c21c commit c52e274
Showing 2 changed files with 35 additions and 12 deletions.
19 changes: 19 additions & 0 deletions src/MonoMod.UnitTest/DynamicMethodDefinitionTest.cs
Original file line number Diff line number Diff line change
@@ -266,5 +266,24 @@ public void DMDGenerateDoesNotModifyDMD()
Assert.Equal(OpCodes.Br_S, genClone.Definition.Body.Instructions[0].OpCode);
}

[Fact]
public void ClonedDMDRelinksVariableDefinitions()
{
using var origDmd = new DynamicMethodDefinition("Test DMD", null, []);
var il = origDmd.GetILProcessor();
var varDef = new VariableDefinition(il.Import(typeof(string)));
il.Body.Variables.Add(varDef);
il.Emit(OpCodes.Ldstr, "hello");
il.Emit(OpCodes.Stloc, varDef);
il.Emit(OpCodes.Ldloc, varDef);
il.Emit(OpCodes.Ret);

using var genClone = new DynamicMethodDefinition(origDmd);

Assert.NotEqual(varDef, genClone.Definition.Body.Variables[0]);
var newVarDef = genClone.Definition.Body.Variables[0];
Assert.Equal(newVarDef, genClone.Definition.Body.Instructions[1].Operand);
Assert.Equal(newVarDef, genClone.Definition.Body.Instructions[2].Operand);
}
}
}
28 changes: 16 additions & 12 deletions src/MonoMod.Utils/Extensions.Relinker.cs
Original file line number Diff line number Diff line change
@@ -102,18 +102,6 @@ public static partial class Extensions
return c;
}));

foreach (var c in bc.Instructions)
{
if (c.Operand is Instruction target)
{
c.Operand = bc.Instructions[bo.Instructions.IndexOf(target)];
}
else if (c.Operand is Instruction[] targets)
{
c.Operand = targets.Select(i => bc.Instructions[bo.Instructions.IndexOf(i)]).ToArray();
}
}

bc.ExceptionHandlers.AddRange(bo.ExceptionHandlers.Select(o =>
{
var c = new ExceptionHandler(o.HandlerType);
@@ -173,6 +161,22 @@ Instruction ResolveInstrOff(int off)
return c;
}));

foreach (var c in bc.Instructions)
{
if (c.Operand is Instruction target)
{
c.Operand = bc.Instructions[bo.Instructions.IndexOf(target)];
}
else if (c.Operand is Instruction[] targets)
{
c.Operand = targets.Select(i => bc.Instructions[bo.Instructions.IndexOf(i)]).ToArray();
}
else if (c.Operand is VariableDefinition vardef)
{
c.Operand = bc.Variables[vardef.Index];
}
}

return bc;
}

0 comments on commit c52e274

Please sign in to comment.