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     }