/** * Insert an instruction at start of this list. * * @param ih instruction to insert */ private void insert(InstructionHandle ih) { if (isEmpty()) { start = end = ih; ih.next = ih.prev = null; } else { start.prev = ih; ih.next = start; ih.prev = null; start = ih; } length++; }
/** * Append an instruction to the end of this list. * * @param ih instruction to append */ private void append(InstructionHandle ih) { if (isEmpty()) { start = end = ih; ih.next = ih.prev = null; } else { end.next = ih; ih.prev = end; ih.next = null; end = ih; } length++; // Update length }
/** * Take all instructions (handles) from "start" to "end" and append them after the new location * "target". Of course, "end" must be after "start" and target must not be located withing this * range. If you want to move something to the start of the list use null as value for target.<br> * Any instruction targeters pointing to handles within the block, keep their targets. * * @param start of moved block * @param end of moved block * @param target of moved block */ public void move(InstructionHandle start, InstructionHandle end, InstructionHandle target) { // Step 1: Check constraints if ((start == null) || (end == null)) { throw new ClassGenException("Invalid null handle: From " + start + " to " + end); } if ((target == start) || (target == end)) { throw new ClassGenException( "Invalid range: From " + start + " to " + end + " contains target " + target); } for (InstructionHandle ih = start; ih != end.next; ih = ih.next) { if (ih == null) { throw new ClassGenException("Invalid range: From " + start + " to " + end); } else if (ih == target) { throw new ClassGenException( "Invalid range: From " + start + " to " + end + " contains target " + target); } } // Step 2: Temporarily remove the given instructions from the list InstructionHandle prev = start.prev, next = end.next; if (prev != null) { prev.next = next; } else { this.start = next; } if (next != null) { next.prev = prev; } else { this.end = prev; } start.prev = end.next = null; // Step 3: append after target if (target == null) { // append to start of list if (this.start != null) { this.start.prev = end; } end.next = this.start; this.start = start; } else { next = target.next; target.next = start; start.prev = target; end.next = next; if (next != null) { next.prev = end; } else { this.end = end; } } }
/** * Remove from instruction `prev' to instruction `next' both contained in this list. Throws * TargetLostException when one of the removed instruction handles is still being targeted. * * @param prev where to start deleting (predecessor, exclusive) * @param next where to end deleting (successor, exclusive) */ private void remove(InstructionHandle prev, InstructionHandle next) throws TargetLostException { InstructionHandle first, last; // First and last deleted instruction if ((prev == null) && (next == null)) { first = start; last = end; start = end = null; } else { if (prev == null) { // At start of list first = start; start = next; } else { first = prev.next; prev.next = next; } if (next == null) { // At end of list last = end; end = prev; } else { last = next.prev; next.prev = prev; } } first.prev = null; // Completely separated from rest of list last.next = null; List<InstructionHandle> target_vec = new ArrayList<InstructionHandle>(); for (InstructionHandle ih = first; ih != null; ih = ih.next) { ih.getInstruction().dispose(); // e.g. BranchInstructions release their targets } StringBuilder buf = new StringBuilder("{ "); for (InstructionHandle ih = first; ih != null; ih = next) { next = ih.next; length--; if (ih.hasTargeters()) { // Still got targeters? target_vec.add(ih); buf.append(ih.toString(true) + " "); ih.next = ih.prev = null; } else { ih.dispose(); } } buf.append("}"); if (!target_vec.isEmpty()) { InstructionHandle[] targeted = new InstructionHandle[target_vec.size()]; target_vec.toArray(targeted); throw new TargetLostException(targeted, buf.toString()); } }
/** * Insert another list before Instruction handle ih contained in this list. Consumes argument * list, i.e., it becomes empty. * * @param ih where to append the instruction list * @param il Instruction list to insert * @return instruction handle of the first inserted instruction */ public InstructionHandle insert(InstructionHandle ih, InstructionList il) { if (il == null) { throw new ClassGenException("Inserting null InstructionList"); } if (il.isEmpty()) { return ih; } InstructionHandle prev = ih.prev, ret = il.start; ih.prev = il.end; il.end.next = ih; il.start.prev = prev; if (prev != null) { prev.next = il.start; } else { start = il.start; // Update start ... } length += il.length; // Update length il.clear(); return ret; }
/** * Append another list after instruction (handle) ih contained in this list. Consumes argument * list, i.e., it becomes empty. * * @param ih where to append the instruction list * @param il Instruction list to append to this one * @return instruction handle pointing to the <B>first</B> appended instruction */ public InstructionHandle append(InstructionHandle ih, InstructionList il) { if (il == null) { throw new ClassGenException("Appending null InstructionList"); } if (il.isEmpty()) { return ih; } InstructionHandle next = ih.next, ret = il.start; ih.next = il.start; il.start.prev = ih; il.end.next = next; if (next != null) { next.prev = il.end; } else { end = il.end; // Update end ... } length += il.length; // Update length il.clear(); return ret; }