1 cananian 1.3.2.10 // Instr.java, created Sun Sep 13 22:49:21 1998 by cananian 2 cananian 1.3 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.3 // 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.3.2.4 import harpoon.ClassFile.HCodeElement; 7 duncan 1.3.2.12 import harpoon.IR.Properties.CFGEdge; 8 duncan 1.3.2.12 import harpoon.IR.Properties.CFGraphable; 9 cananian 1.3.2.1 import harpoon.Util.ArrayFactory; 10 cananian 1.1 11 cananian 1.3.2.5 import java.util.ArrayList; 12 sportbilly 1.3.2.7 import java.util.Arrays; 13 sportbilly 1.3.2.7 import java.util.Collection; 14 cananian 1.3.2.5 import java.util.List; 15 cananian 1.1 /** 16 cananian 1.1 * <code>Bytecode.Instr</code> is the base type for the specific 17 cananian 1.1 * bytecode instruction classes. It provides standard methods 18 cananian 1.1 * for accessing the opcode of a specific instruction and for 19 cananian 1.1 * determining which instructions may preceed or follow it. 20 cananian 1.1 * <p>As with all <code>HCodeElement</code>s, <code>Instr</code>s are 21 cananian 1.1 * traceable to an original source file and line number, and have 22 cananian 1.1 * a unique numeric identifier. 23 cananian 1.1 * 24 cananian 1.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 25 cananian 1.9 * @version $Id: Instr.java,v 1.9 2004/02/07 21:28:51 cananian Exp $ 26 cananian 1.1 * @see InGen 27 cananian 1.1 * @see InCti 28 cananian 1.1 * @see InMerge 29 cananian 1.1 * @see InSwitch 30 cananian 1.1 * @see Code 31 cananian 1.1 */ 32 cananian 1.2 public abstract class Instr 33 cananian 1.6 implements HCodeElement, harpoon.IR.Properties.CFGraphable<Instr,InstrEdge>, 34 cananian 1.6 Comparable<Instr> { 35 cananian 1.4.2.1 final String sourcefile; 36 cananian 1.4.2.1 final int linenumber; 37 cananian 1.4.2.1 final int id; 38 cananian 1.1 /** Constructor. */ 39 cananian 1.1 protected Instr(String sourcefile, int linenumber) { 40 cananian 1.1 this.sourcefile = sourcefile; 41 cananian 1.1 this.linenumber = linenumber; 42 cananian 1.3.2.5 /* it would be nice if this were unique for a particular Instr in a 43 cananian 1.3.2.5 * method, instead of depending on the translation order of different 44 cananian 1.3.2.5 * methods, but we'll settle for the total ordering Comparable implies. 45 cananian 1.3.2.5 */ 46 cananian 1.1 synchronized(lock) { 47 cananian 1.1 this.id = next_id++; 48 cananian 1.1 } 49 cananian 1.1 } 50 cananian 1.1 static int next_id = 0; 51 cananian 1.1 static final Object lock = new Object(); 52 cananian 1.1 53 cananian 1.1 /** Returns the original source file name that this bytecode instruction 54 cananian 1.1 * is derived from. */ 55 cananian 1.1 public String getSourceFile() { return sourcefile; } 56 cananian 1.1 /** Returns the line in the original source file that this bytecode 57 cananian 1.1 * instruction can be traced to. */ 58 cananian 1.1 public int getLineNumber() { return linenumber; } 59 cananian 1.1 /** Returns a unique numeric identifier for this element. */ 60 cananian 1.1 public int getID() { return id; } 61 cananian 1.1 /** Returns the java bytecode of this instruction. */ 62 cananian 1.1 public abstract byte getOpcode(); 63 cananian 1.3.2.5 /** Natural ordering on <code>Instr</code>s. */ 64 cananian 1.6 public int compareTo(Instr o) { 65 cananian 1.3.2.5 /* ordering is by id. */ 66 cananian 1.6 return o.id - this.id; 67 cananian 1.3.2.5 } 68 cananian 1.3.2.5 public boolean equals(Object o) { // exploit global uniqueness of id. 69 cananian 1.3.2.8 if (this==o) return true; 70 cananian 1.3.2.8 if (o==null) return false; 71 cananian 1.3.2.8 try { return ((Instr) o).id == this.id; } 72 cananian 1.3.2.8 catch (ClassCastException e) { return false; } 73 cananian 1.3.2.5 } 74 cananian 1.3.2.5 public int hashCode() { return id; } // exploit global uniqueness of id. 75 cananian 1.3.2.1 76 cananian 1.3.2.1 /** Array Factory: makes <code>Instr[]</code>s. */ 77 cananian 1.6 public static final ArrayFactory<Instr> arrayFactory = 78 cananian 1.6 new ArrayFactory<Instr>() { 79 cananian 1.6 public Instr[] newArray(int len) { return new Instr[len]; } 80 cananian 1.3.2.1 }; 81 cananian 1.1 82 cananian 1.1 /** Return a list of all the <code>Instr</code>s that can precede 83 cananian 1.1 * this one. */ 84 cananian 1.1 public Instr[] prev() { 85 cananian 1.6 return prev.toArray(new Instr[prev.size()]); 86 cananian 1.1 } 87 cananian 1.1 /** Return a list of all the possible <code>Instr</code>s that may 88 cananian 1.1 * succeed this one. */ 89 cananian 1.1 public Instr[] next() { 90 cananian 1.6 return next.toArray(new Instr[next.size()]); 91 cananian 1.1 } 92 cananian 1.3.2.2 /** Return the specified successor of this <code>Instr</code>. */ 93 cananian 1.6 public Instr next(int i) { return next.get(i); } 94 cananian 1.3.2.2 /** Return the specified predecessor of this <code>Instr</code>. */ 95 cananian 1.6 public Instr prev(int i) { return prev.get(i); } 96 cananian 1.1 97 cananian 1.1 /** Add a predecessor to this <code>Instr</code>. */ 98 cananian 1.3.2.5 void addPrev(Instr prev) { this.prev.add(prev); } 99 cananian 1.1 /** Add a successor to this <code>Instr</code>. */ 100 cananian 1.3.2.5 void addNext(Instr next) { this.next.add(next); } 101 cananian 1.1 /** Remove a predecessor from this <code>Instr</code>. */ 102 cananian 1.3.2.5 void removePrev(Instr prev) { this.prev.remove(prev); } 103 cananian 1.1 /** Remove a successor from this <code>Instr</code>. */ 104 cananian 1.3.2.5 void removeNext(Instr next) { this.next.remove(next); } 105 cananian 1.1 106 cananian 1.1 /** Internal predecessor list. */ 107 cananian 1.6 final List<Instr> prev = new ArrayList<Instr>(2); 108 cananian 1.1 /** Internal successor list. */ 109 cananian 1.6 final List<Instr> next = new ArrayList<Instr>(2); 110 cananian 1.2 111 cananian 1.3.2.11 // CFGraphable interface: 112 cananian 1.6 public InstrEdge newEdge(Instr from, Instr to) { 113 cananian 1.6 return new InstrEdge(from, to); 114 cananian 1.2 } 115 cananian 1.6 public InstrEdge[] succ() { 116 cananian 1.6 InstrEdge[] r = new InstrEdge[next.size()]; 117 cananian 1.2 for (int i=0; i<r.length; i++) 118 cananian 1.6 r[i] = newEdge(this, next.get(i)); 119 cananian 1.2 return r; 120 cananian 1.2 } 121 cananian 1.6 public InstrEdge[] pred() { 122 cananian 1.6 InstrEdge[] r = new InstrEdge[prev.size()]; 123 cananian 1.2 for (int i=0; i<r.length; i++) 124 cananian 1.6 r[i] = newEdge(prev.get(i), this); 125 cananian 1.2 return r; 126 cananian 1.2 } 127 cananian 1.6 public InstrEdge[] edges() { 128 cananian 1.6 InstrEdge[] n = succ(); 129 cananian 1.6 InstrEdge[] p = pred(); 130 cananian 1.6 InstrEdge[] r = new InstrEdge[n.length + p.length]; 131 cananian 1.2 System.arraycopy(n, 0, r, 0, n.length); 132 cananian 1.2 System.arraycopy(p, 0, r, n.length, p.length); 133 cananian 1.2 return r; 134 cananian 1.2 } 135 cananian 1.9 public List<InstrEdge> edgeC() { return Arrays.asList(edges()); } 136 cananian 1.9 public List<InstrEdge> predC() { return Arrays.asList(pred()); } 137 cananian 1.9 public List<InstrEdge> succC() { return Arrays.asList(succ()); } 138 cananian 1.8 public boolean isSucc(Instr i) { return next.contains(i); } 139 cananian 1.8 public boolean isPred(Instr i) { return prev.contains(i); } 140 cananian 1.6 } 141 cananian 1.6 class InstrEdge extends CFGEdge<Instr,InstrEdge> { 142 cananian 1.6 final Instr from, to; 143 cananian 1.6 InstrEdge(Instr from, Instr to) { this.from = from; this.to = to; } 144 cananian 1.7 public Instr from() { return from; } 145 cananian 1.7 public Instr to() { return to; } 146 cananian 1.6 public boolean equals(Object o) { 147 cananian 1.6 CFGEdge hce; 148 cananian 1.6 if (this==o) return true; 149 cananian 1.6 if (o==null) return false; 150 cananian 1.6 try { hce=(CFGEdge)o; } catch (ClassCastException e) {return false; } 151 cananian 1.6 return hce.from() == from && hce.to() == to; 152 cananian 1.6 } 153 cananian 1.6 public int hashCode() { return from.hashCode() ^ to.hashCode(); } 154 cananian 1.1 }