1
2
3
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);
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
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
181
182
183 public int hashCode() {
184 if (DETERMINISTIC) return getID();
185 else return System.identityHashCode(this);
186 }
187
188
189
190
191 public boolean equals(Object that) {
192 return this == that;
193 }
194
195 }