/* this routine eliminates the specified segment of code from the program */ /* and updates all branches pointing to areas beyond it. The new length */ /* is returned. it also disposes of any additional storage used by the */ /* instructions being deleted */ private static void DropCodeSegment(List <OpcodeRec> Prog, List <int> LineNumberArray, int Start, int Extent) { /* sanity check */ Debug.Assert(NoBranchToInterior(Prog, Start, Extent)); // branches to interior not permitted /* patch up branches */ int Scan; for (Scan = 0; Scan < Prog.Count; Scan += PcodeRec.GetInstructionLength(Prog[Scan].Opcode)) { /* looking for branch instructions */ if ((Prog[Scan].Opcode == Pcodes.epBranchUnconditional) || (Prog[Scan].Opcode == Pcodes.epBranchIfZero) || (Prog[Scan].Opcode == Pcodes.epBranchIfNotZero)) { /* found a branch instruction. does it need to be patched? */ if (Prog[Scan + 1].ImmediateInteger > Start) { /* branch is beyond segment being dropped, so decrement it's address */ /* by the length of the segment */ OpcodeRec opcode = Prog[Scan + 1]; opcode.ImmediateInteger -= Extent; Prog[Scan + 1] = opcode; } } } Debug.Assert(Scan == Prog.Count); // internal instruction alignment error /* delete the code segment */ Prog.RemoveRange(Start, Extent); LineNumberArray.RemoveRange(Start, Extent); }
/* this routine looks for indivisible dup/pop operations (with no interior */ /* branches) and eliminates them. *Flag is set if some change was made, and the */ /* new length of Prog[] is returned. */ private static void EliminateDupPop(List <OpcodeRec> Prog, List <int> LineNumberArray, out bool Flag) { Flag = false; int Scan = 0; while (Scan < Prog.Count) { /* look to see if this part can be dropped. if it can, we don't increment */ /* Scan so that we can look at the part that will be moved into where this */ /* is as well. otherwise, we do increment */ if ((Prog[Scan].Opcode == Pcodes.epDuplicate) && (Prog[Scan + 1].Opcode == Pcodes.epStackPop) && NoBranchToInterior(Prog, Scan, 2)) { /* found one! */ DropCodeSegment(Prog, LineNumberArray, Scan, 2); Flag = true; } else { /* increment only if not found */ Scan += PcodeRec.GetInstructionLength(Prog[Scan].Opcode); } } Debug.Assert(Scan == Prog.Count); // internal instruction alignment error }
/* this routine scans the entire code block to see if any branches are made */ /* to any but the first instruction specified in the run of instructions. */ /* Start points to the first instruction, Extent specifies the number of WORDS */ /* (not instructions). Branches MAY point to Prog[Start], however. */ private static bool NoBranchToInterior(List <OpcodeRec> Prog, int Start, int Extent) { int i; for (i = 0; i < Prog.Count; i += PcodeRec.GetInstructionLength(Prog[i].Opcode)) { if ((Prog[i].Opcode == Pcodes.epBranchUnconditional) || (Prog[i].Opcode == Pcodes.epBranchIfZero) || (Prog[i].Opcode == Pcodes.epBranchIfNotZero)) { /* branch operation detected, test index */ if ((Prog[i + 1].ImmediateInteger > Start) && (Prog[i + 1].ImmediateInteger < Start + Extent)) { /* branch to interior found, so return false. */ return(false); } } } Debug.Assert(i == Prog.Count); // internal instruction alignment error return(true); }