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; }
private void EmitGoto(int targetIndex) { ClassFile.Method.Instruction instr = new ClassFile.Method.Instruction(); instr.PatchOpCode(NormalizedByteCode.__goto, targetIndex); instr.SetPC(-1); Emit(instr); }