in ILRepack/RepackImporter.cs [441:585]
private void CloneTo(MethodBody body, MethodDefinition parent)
{
MethodBody nb = new MethodBody(parent);
parent.Body = nb;
nb.MaxStackSize = body.MaxStackSize;
nb.InitLocals = body.InitLocals;
nb.LocalVarToken = body.LocalVarToken;
foreach (VariableDefinition var in body.Variables)
nb.Variables.Add(new VariableDefinition(
Import(var.VariableType, parent)));
nb.Instructions.Capacity = Math.Max(nb.Instructions.Capacity, body.Instructions.Count);
_repackContext.LineIndexer.PreMethodBodyRepack(body, parent);
foreach (Instruction instr in body.Instructions)
{
Instruction ni;
if (instr.OpCode.Code == Code.Calli)
{
var callSite = (CallSite)instr.Operand;
CallSite ncs = new CallSite(Import(callSite.ReturnType, parent))
{
HasThis = callSite.HasThis,
ExplicitThis = callSite.ExplicitThis,
CallingConvention = callSite.CallingConvention
};
foreach (ParameterDefinition param in callSite.Parameters)
CloneTo(param, parent, ncs.Parameters);
ni = Instruction.Create(instr.OpCode, ncs);
}
else switch (instr.OpCode.OperandType)
{
case OperandType.InlineArg:
case OperandType.ShortInlineArg:
if (instr.Operand == body.ThisParameter)
{
ni = Instruction.Create(instr.OpCode, nb.ThisParameter);
}
else
{
int param = body.Method.Parameters.IndexOf((ParameterDefinition)instr.Operand);
ni = Instruction.Create(instr.OpCode, parent.Parameters[param]);
}
break;
case OperandType.InlineVar:
case OperandType.ShortInlineVar:
int var = body.Variables.IndexOf((VariableDefinition)instr.Operand);
ni = Instruction.Create(instr.OpCode, nb.Variables[var]);
break;
case OperandType.InlineField:
ni = Instruction.Create(instr.OpCode, Import((FieldReference)instr.Operand, parent));
break;
case OperandType.InlineMethod:
ni = Instruction.Create(instr.OpCode, Import((MethodReference)instr.Operand, parent));
FixAspNetOffset(nb.Instructions, (MethodReference)instr.Operand, parent);
break;
case OperandType.InlineType:
ni = Instruction.Create(instr.OpCode, Import((TypeReference)instr.Operand, parent));
break;
case OperandType.InlineTok:
if (instr.Operand is TypeReference)
ni = Instruction.Create(instr.OpCode, Import((TypeReference)instr.Operand, parent));
else if (instr.Operand is FieldReference)
ni = Instruction.Create(instr.OpCode, Import((FieldReference)instr.Operand, parent));
else if (instr.Operand is MethodReference)
ni = Instruction.Create(instr.OpCode, Import((MethodReference)instr.Operand, parent));
else
throw new InvalidOperationException();
break;
case OperandType.ShortInlineBrTarget:
case OperandType.InlineBrTarget:
ni = Instruction.Create(instr.OpCode, (Instruction)instr.Operand);
break;
case OperandType.InlineSwitch:
ni = Instruction.Create(instr.OpCode, (Instruction[])instr.Operand);
break;
case OperandType.InlineR:
ni = Instruction.Create(instr.OpCode, (double)instr.Operand);
break;
case OperandType.ShortInlineR:
ni = Instruction.Create(instr.OpCode, (float)instr.Operand);
break;
case OperandType.InlineNone:
ni = Instruction.Create(instr.OpCode);
break;
case OperandType.InlineString:
ni = Instruction.Create(instr.OpCode, (string)instr.Operand);
break;
case OperandType.ShortInlineI:
if (instr.OpCode == OpCodes.Ldc_I4_S)
ni = Instruction.Create(instr.OpCode, (sbyte)instr.Operand);
else
ni = Instruction.Create(instr.OpCode, (byte)instr.Operand);
break;
case OperandType.InlineI8:
ni = Instruction.Create(instr.OpCode, (long)instr.Operand);
break;
case OperandType.InlineI:
ni = Instruction.Create(instr.OpCode, (int)instr.Operand);
break;
default:
throw new InvalidOperationException();
}
nb.Instructions.Add(ni);
}
for (int i = 0; i < body.Instructions.Count; i++)
{
Instruction instr = nb.Instructions[i];
switch (instr.OpCode.OperandType)
{
case OperandType.ShortInlineBrTarget:
case OperandType.InlineBrTarget:
instr.Operand = GetInstruction(body, nb, (Instruction)body.Instructions[i].Operand);
break;
case OperandType.InlineSwitch:
instr.Operand = ((Instruction[])body.Instructions[i].Operand).Select(op => GetInstruction(body, nb, op)).ToArray();
break;
default:
break;
}
}
foreach (ExceptionHandler eh in body.ExceptionHandlers)
{
ExceptionHandler neh = new ExceptionHandler(eh.HandlerType);
neh.TryStart = GetInstruction(body, nb, eh.TryStart);
neh.TryEnd = GetInstruction(body, nb, eh.TryEnd);
neh.HandlerStart = GetInstruction(body, nb, eh.HandlerStart);
neh.HandlerEnd = GetInstruction(body, nb, eh.HandlerEnd);
switch (eh.HandlerType)
{
case ExceptionHandlerType.Catch:
neh.CatchType = Import(eh.CatchType, parent);
break;
case ExceptionHandlerType.Filter:
neh.FilterStart = GetInstruction(body, nb, eh.FilterStart);
break;
}
nb.ExceptionHandlers.Add(neh);
}
}