Skip to content

Instantly share code, notes, and snippets.

@pardeike
Last active July 16, 2020 11:39
Show Gist options
  • Save pardeike/52a518c452d4b7b9db63fef698454a4a to your computer and use it in GitHub Desktop.
Save pardeike/52a518c452d4b7b9db63fef698454a4a to your computer and use it in GitHub Desktop.
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator il, MethodBase original)
{
// create new local variables
var local = il.DeclareLocal(typeof(TheType));
// create new labels for jumping
var label = il.DefineLabel();
// inspect original methods properties
var args = original.GetParameters();
// alternative 1 - looping and emitting
//
yield return ...; // add new codes before
foreach (CodeInstruction instruction in instructions)
{
// skip instructions
if (...)
continue;
// add new instructions
if (...)
yield return new CodeInstruction(...);
// edit instructions
if (...)
{
instruction.opcode = OpCodes.Brtrue;
instruction.operand = label;
// or
instruction.labels.Add(label); // add label
// or
instruction.blocks.Add(new ExceptionBlock(ExceptionBlockType.BeginCatchBlock)); // add try/catch boundaries
}
yield return instruction;
}
yield return ...; // add new codes after
// alternative 2 - convert to list
//
var list = instructions.ToList();
// search in list (to find existing local variable for example)
var index = list.FindIndex(instr => instr.opcode == OpCodes.Ldloc);
var someLocal = list[index].operand; // LocalBuilder object representing variable
// reuse someLocal here
// move existing labels
int idx = ...;
var someLabels = list[idx].labels;
list[idx].labels.Clear();
list.Insert(idx, new CodeInstruction(OpCodes.Nop) { labels = someLabels });
list[idx].labels.AddRange(someLabels);
return list.AsEnumerable();
// alternative 3 - abort and dont modify
//
if (...)
return null;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment