View Javadoc

1   // Quad.java, created Fri Jan 11 16:42:38 2002 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package joeq.Compiler.Quad;
5   
6   import joeq.Class.jq_Class;
7   import joeq.Compiler.Quad.Operand.RegisterOperand;
8   import joeq.Compiler.Quad.Operator.Return;
9   import joeq.Interpreter.QuadInterpreter;
10  import joeq.Util.Templates.List;
11  import joeq.Util.Templates.UnmodifiableList;
12  import jwutil.strings.Strings;
13  
14  /***
15   * @author  John Whaley <jwhaley@alum.mit.edu>
16   * @version $Id: Quad.java 2261 2005-05-05 19:40:03Z joewhaley $
17   */
18  public class Quad {
19  
20      /*** The operator.  Operator objects are shared across all quads. */
21      private Operator operator;
22      /*** The four operands.  Operands are quad-specific. */
23      private Operand operand1, operand2, operand3, operand4;
24      /*** Id number for this quad.  THIS NUMBER HOLDS NO MEANING WHATSOEVER.  It is just used for printing. */
25      private int id_number;
26      
27      /*** Creates new Quad */
28      Quad(int id, Operator operator) {
29          this.id_number = id; this.operator = operator;
30      }
31      Quad(int id, Operator operator, Operand operand1) {
32          this.id_number = id; this.operator = operator; this.operand1 = operand1;
33          if (operand1 != null) operand1.attachToQuad(this);
34      }
35      Quad(int id, Operator operator, Operand operand1, Operand operand2) {
36          this.id_number = id; this.operator = operator; this.operand1 = operand1; this.operand2 = operand2;
37          if (operand1 != null) operand1.attachToQuad(this);
38          if (operand2 != null) operand2.attachToQuad(this);
39      }
40      Quad(int id, Operator operator, Operand operand1, Operand operand2, Operand operand3) {
41          this.id_number = id; this.operator = operator; this.operand1 = operand1; this.operand2 = operand2; this.operand3 = operand3;
42          if (operand1 != null) operand1.attachToQuad(this);
43          if (operand2 != null) operand2.attachToQuad(this);
44          if (operand3 != null) operand3.attachToQuad(this);
45      }
46      Quad(int id, Operator operator, Operand operand1, Operand operand2, Operand operand3, Operand operand4) {
47          this.id_number = id; this.operator = operator; this.operand1 = operand1; this.operand2 = operand2; this.operand3 = operand3; this.operand4 = operand4;
48          if (operand1 != null) operand1.attachToQuad(this);
49          if (operand2 != null) operand2.attachToQuad(this);
50          if (operand3 != null) operand3.attachToQuad(this);
51          if (operand4 != null) operand4.attachToQuad(this); // maybe null guard
52      }
53      /*** These are not intended to be used outside of the joeq.Compiler.Quad package.
54       * Instead, use the static accessor methods for each operator, e.g. Move.getDest(quad).
55       */
56      Operand getOp1() { return operand1; }
57      Operand getOp2() { return operand2; }
58      Operand getOp3() { return operand3; }
59      Operand getOp4() { return operand4; }
60      public void setOp1(Operand op) { operand1 = op; }
61      public void setOp2(Operand op) { operand2 = op; }
62      public void setOp3(Operand op) { operand3 = op; }
63      public void setOp4(Operand op) { operand4 = op; }
64  
65      public Quad copy(int id_number) {
66          Operand op1 = (operand1!=null)?operand1.copy():null;
67          Operand op2 = (operand2!=null)?operand2.copy():null;
68          Operand op3 = (operand3!=null)?operand3.copy():null;
69          Operand op4 = (operand4!=null)?operand4.copy():null;
70          return new Quad(id_number, operator, op1, op2, op3, op4);
71      }
72      
73      public UnmodifiableList.Operand getAllOperands() {
74          int k = 0;
75          if (operand1 != null) k += 1;
76          if (operand2 != null) k += 2;
77          if (operand3 != null) k += 4;
78          if (operand4 != null) k += 8;
79          switch (k) {
80              case 0 :
81                  return UnmodifiableList.Operand.EMPTY;
82              case 1 :
83                  return new UnmodifiableList.Operand(operand1);
84              case 2 :
85                  return new UnmodifiableList.Operand(operand2);
86              case 3 :
87                  return new UnmodifiableList.Operand(operand1, operand2);
88              case 4 :
89                  return new UnmodifiableList.Operand(operand3);
90              case 5 :
91                  return new UnmodifiableList.Operand(operand1, operand3);
92              case 6 :
93                  return new UnmodifiableList.Operand(operand2, operand3);
94              case 7 :
95                  return new UnmodifiableList.Operand(operand1, operand2, operand3);
96              case 8 :
97                  return new UnmodifiableList.Operand(operand4);
98              case 9 :
99                  return new UnmodifiableList.Operand(operand1, operand4);
100             case 10 :
101                 return new UnmodifiableList.Operand(operand2, operand4);
102             case 11 :
103                 return new UnmodifiableList.Operand(operand1, operand2, operand4);
104             case 12 :
105                 return new UnmodifiableList.Operand(operand3, operand4);
106             case 13 :
107                 return new UnmodifiableList.Operand(operand1, operand3, operand4);
108             case 14 :
109                 return new UnmodifiableList.Operand(operand2, operand3, operand4);
110             case 15 :
111             default:
112                 return new UnmodifiableList.Operand(operand1, operand2, operand3, operand4);
113         }
114     }
115     
116     /*** Return the operator for this quad. */
117     public Operator getOperator() { return operator; }
118     
119     /*** Accepts a quad visitor to this quad.  For the visitor pattern. */
120     public void accept(QuadVisitor qv) { this.operator.accept(this, qv); }
121 
122     /*** Returns the id number of this quad.  THIS NUMBER HOLDS NO MEANING WHATSOEVER.  It is just used for printing. */
123     public int getID() { return id_number; }
124     
125     /*** Returns a list of the types of exceptions that this quad can throw.
126      * Note that types in this list are not exact, therefore subtypes of the
127      * returned types may also be thrown. */
128     public List.jq_Class getThrownExceptions() {
129         if (operator == Return.THROW_A.INSTANCE) {
130             Operand op = Return.getSrc(this);
131             if (op instanceof RegisterOperand) {
132                 // use the operand type.
133                 return new UnmodifiableList.jq_Class((jq_Class)((RegisterOperand)op).getType());
134             }
135         }
136         return joeq.Compiler.CompilationState.DEFAULT.getThrownExceptions(this);
137     }
138 
139     /*** Returns a list of the registers defined by this quad. */
140     public List.RegisterOperand getDefinedRegisters() { return this.operator.getDefinedRegisters(this); }
141     /*** Returns a list of the registers used by this quad. */
142     public List.RegisterOperand getUsedRegisters() { return this.operator.getUsedRegisters(this); }
143     
144     /*** Interprets this quad, modifying the given interpreter state. */
145     public void interpret(QuadInterpreter s) { this.operator.interpret(this, s); }
146 
147     /*** Returns a string representation of this quad. */
148     public String toString() {
149         StringBuffer s = new StringBuffer();
150         s.append(Strings.left(Integer.toString(id_number), 4));
151         s.append(Strings.left(operator.toString(), 24));
152         if (operand1 == null) {
153             if (operand2 == null) return s.toString();
154             s.append("    \t");
155         } else {
156             s.append(operand1.toString());
157             if (operand2 == null) return s.toString();
158             s.append(",\t");
159         }
160         s.append(operand2.toString());
161         if (operand3 == null) return s.toString();
162         s.append(",\t");
163         s.append(operand3.toString());
164         if (operand4 == null) return s.toString();
165         s.append(",\t");
166         s.append(operand4.toString());
167         return s.toString();
168     }
169     
170     /*** Returns a short string representation of this quad, without any operands. */
171     public String toString_short() {
172         StringBuffer s = new StringBuffer();
173         s.append(Strings.left(Integer.toString(id_number), 4));
174         s.append(operator.toString());
175         return s.toString();
176     }
177     
178     public static final boolean DETERMINISTIC = true;
179     
180     /* (non-Javadoc)
181      * @see java.lang.Object#hashCode()
182      */
183     public int hashCode() {
184         if (DETERMINISTIC) return getID();
185         else return System.identityHashCode(this);
186     }
187     
188     /* (non-Javadoc)
189      * @see java.lang.Object#equals(java.lang.Object)
190      */
191     public boolean equals(Object that) {
192         return this == that;
193     }
194     
195 }