/** * Insert an instruction before instruction (handle) ih contained in this list. * * @param ih where to insert to the instruction list * @param i Instruction to insert * @return instruction handle of the first inserted instruction */ public BranchHandle insert(InstructionHandle ih, BranchInstruction i) { BranchHandle bh = BranchHandle.getBranchHandle(i); InstructionList il = new InstructionList(); il.append(bh); insert(ih, il); return bh; }
/** * Append another list to this one. Consumes argument list, i.e., it becomes empty. * * @param il list to append to end of this list * @return instruction handle of the <B>first</B> appended instruction */ public InstructionHandle append(InstructionList il) { if (il == null) { throw new ClassGenException("Appending null InstructionList"); } if (il.isEmpty()) { return null; } if (isEmpty()) { start = il.start; end = il.end; length = il.length; il.clear(); return start; } else { return append(end, il); // was end.instruction } }
/** @return complete, i.e., deep copy of this list */ public InstructionList copy() { Map<InstructionHandle, InstructionHandle> map = new HashMap<InstructionHandle, InstructionHandle>(); InstructionList il = new InstructionList(); /* Pass 1: Make copies of all instructions, append them to the new list * and associate old instruction references with the new ones, i.e., * a 1:1 mapping. */ for (InstructionHandle ih = start; ih != null; ih = ih.next) { Instruction i = ih.instruction; Instruction c = i.copy(); // Use clone for shallow copy if (c instanceof BranchInstruction) { map.put(ih, il.append((BranchInstruction) c)); } else { map.put(ih, il.append(c)); } } /* Pass 2: Update branch targets. */ InstructionHandle ih = start; InstructionHandle ch = il.start; while (ih != null) { Instruction i = ih.instruction; Instruction c = ch.instruction; if (i instanceof BranchInstruction) { BranchInstruction bi = (BranchInstruction) i; BranchInstruction bc = (BranchInstruction) c; InstructionHandle itarget = bi.getTarget(); // old target // New target is in hash map bc.setTarget(map.get(itarget)); if (bi instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH InstructionHandle[] itargets = ((Select) bi).getTargets(); InstructionHandle[] ctargets = ((Select) bc).getTargets(); for (int j = 0; j < itargets.length; j++) { // Update all targets ctargets[j] = map.get(itargets[j]); } } } ih = ih.next; ch = ch.next; } return il; }
/** * 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; }