internal bool InlineSubroutine()
{
bool hasJsrs = false;
// start with a pre-amble to load a dummy return address on the stack and to branch to the subroutine
{
// TODO consider exception handling around these instructions
ClassFile.Method.Instruction instr = new ClassFile.Method.Instruction();
instr.PatchOpCode(NormalizedByteCode.__aconst_null);
instr.SetPC(inliner.m.Instructions[subroutineIndex].PC);
Emit(instr);
EmitGoto(subroutineIndex);
}
bool fallThru = false;
for (int instructionIndex = 0; instructionIndex < inliner.m.Instructions.Length; instructionIndex++)
{
if ((inliner.flags[instructionIndex] & InstructionFlags.Reachable) != 0
&& inliner.ma.IsSubroutineActive(instructionIndex, subroutineIndex))
{
fallThru = false;
branchMap[instructionIndex] = inliner.codeLength;
switch (inliner.m.Instructions[instructionIndex].NormalizedOpCode)
{
case NormalizedByteCode.__tableswitch:
case NormalizedByteCode.__lookupswitch:
case NormalizedByteCode.__ireturn:
case NormalizedByteCode.__lreturn:
case NormalizedByteCode.__freturn:
case NormalizedByteCode.__dreturn:
case NormalizedByteCode.__areturn:
case NormalizedByteCode.__return:
case NormalizedByteCode.__athrow:
case NormalizedByteCode.__goto:
Emit(inliner.m.Instructions[instructionIndex]);
break;
case NormalizedByteCode.__jsr:
hasJsrs = true;
goto default;
case NormalizedByteCode.__ret:
{
int subid = inliner.ma.GetLocalTypeWrapper(instructionIndex, inliner.m.Instructions[instructionIndex].TargetIndex).SubroutineIndex;
if (subid == subroutineIndex)
{
EmitGoto(returnIndex);
}
else
{
Emit(inliner.m.Instructions[instructionIndex]);
}
break;
}
default:
fallThru = true;
Emit(inliner.m.Instructions[instructionIndex]);
break;
}
}
else if (fallThru)
{
EmitGoto(instructionIndex);
}
}
endIndex = inliner.codeLength;
DoFixups();
return hasJsrs;
}