1 cananian 1.2.2.2 // InCti.java, created Sun Sep 13 22:49:20 1998 by cananian 2 cananian 1.2 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.2 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1 package harpoon.IR.Bytecode; 5 cananian 1.1 6 cananian 1.1 import harpoon.Util.Util; 7 cananian 1.1 8 cananian 1.1 /** 9 cananian 1.1 * <code>InCti</code> is used for control-transfer instructions. 10 cananian 1.1 * It will have exactly one predecessor, and multiple successors. 11 cananian 1.1 * For conditional branches, the first successor 12 cananian 1.1 * (<code>next()[0]</code>) will be the 'fall-through' instruction 13 cananian 1.1 * (corresponding to branch-not-taken). For unconditional branches, 14 cananian 1.1 * the first successor will be the target, if there is one. 15 cananian 1.1 * Instructions like <code>ireturn</code> have no successors. 16 cananian 1.1 * 17 cananian 1.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 18 cananian 1.3 * @version $Id: InCti.java,v 1.3 2002/02/25 21:04:17 cananian Exp $ 19 cananian 1.1 * @see Instr 20 cananian 1.1 */ 21 cananian 1.1 public class InCti extends Instr { 22 cananian 1.2.2.1 final byte opcode; 23 cananian 1.1 int arity; 24 cananian 1.1 25 cananian 1.1 /** Create an <code>InCti</code> from a chunk of bytecode starting 26 cananian 1.1 * at offest <code>pc</code>. */ 27 cananian 1.1 public InCti(String sourcefile, int linenumber, byte[] code, int pc) { 28 cananian 1.1 super(sourcefile, linenumber); 29 cananian 1.1 this.opcode=code[pc]; 30 cananian 1.1 this.arity = Op.branchTargets(code, pc).length; 31 cananian 1.1 if (!Op.isUnconditionalBranch(code[pc])) this.arity++; 32 cananian 1.1 if (Op.isJSR(code[pc])) this.arity++; 33 cananian 1.1 } 34 cananian 1.1 35 cananian 1.1 // Provide run-time checks on arity. 36 cananian 1.1 /** @see Instr#addPrev */ 37 cananian 1.1 void addPrev(Instr prev) { 38 cananian 1.1 if (this.prev.size()>=1) 39 cananian 1.1 throw new Error("CTI should have only one predecessor."); 40 cananian 1.1 super.addPrev(prev); 41 cananian 1.1 } 42 cananian 1.1 /** @see Instr#addNext */ 43 cananian 1.1 void addNext(Instr next) { 44 cananian 1.1 if (this.next.size()>=arity) 45 cananian 1.1 throw new Error("Exceeding arity of CTI."); 46 cananian 1.1 super.addNext(next); 47 cananian 1.1 } 48 cananian 1.1 49 cananian 1.1 /** Return the java bytecode opcode of this instruction. */ 50 cananian 1.1 public byte getOpcode() { return opcode; } 51 cananian 1.1 52 cananian 1.1 /** Return human-readable instruction string. */ 53 cananian 1.1 public String toString() { 54 cananian 1.1 StringBuffer sb = new StringBuffer(Op.toString(opcode)); 55 cananian 1.1 Instr[] targets = next(); 56 cananian 1.1 // skip targets[0] if this is a conditional branch or JSR. 57 cananian 1.1 int start = (Op.isUnconditionalBranch(opcode)&&!Op.isJSR(opcode))?0:1; 58 cananian 1.1 if (targets.length > start) 59 cananian 1.1 sb.append(' '); 60 cananian 1.1 for (int i=start; i<targets.length; i++) { 61 cananian 1.1 sb.append('#'); sb.append(targets[i].getID()); 62 cananian 1.1 if (i<targets.length-1) 63 cananian 1.1 sb.append(", "); 64 cananian 1.1 } 65 cananian 1.1 return sb.toString(); 66 cananian 1.1 } 67 cananian 1.1 }