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      }