1
2
3
4 package joeq.Compiler.Quad;
5
6 import joeq.Class.jq_Field;
7 import joeq.Class.jq_Method;
8 import joeq.Class.jq_Reference;
9 import joeq.Class.jq_Type;
10 import joeq.Class.jq_Reference.jq_NullType;
11 import joeq.Compiler.BytecodeAnalysis.BytecodeVisitor;
12 import joeq.Compiler.Quad.RegisterFactory.Register;
13 import joeq.Memory.Address;
14 import joeq.Memory.HeapAddress;
15 import joeq.Runtime.Reflection;
16 import jwutil.util.Assert;
17
18
19
20
21
22 public interface Operand {
23
24 Quad getQuad();
25 void attachToQuad(Quad q);
26 Operand copy();
27 boolean isSimilar(Operand that);
28
29 abstract class Util {
30 public static boolean isNullConstant(Operand op) {
31 return op instanceof AConstOperand && ((AConstOperand)op).getValue() == null;
32 }
33 public static boolean isConstant(Operand op) {
34 return op instanceof AConstOperand ||
35 op instanceof PConstOperand ||
36 op instanceof IConstOperand ||
37 op instanceof FConstOperand ||
38 op instanceof LConstOperand ||
39 op instanceof DConstOperand;
40 }
41 }
42
43 class RegisterOperand implements Operand {
44 private Quad instruction;
45 private Register register; private jq_Type type; private int flags;
46 public static final int PRECISE_TYPE = 0x1;
47 public Object scratchObject;
48 public RegisterOperand(Register reg, jq_Type type) {
49 this(reg, type, 0);
50 }
51 public RegisterOperand(Register reg, jq_Type type, int flags) {
52 this.register = reg; this.type = type; this.flags = flags;
53 }
54 public Register getRegister() { return register; }
55 public void setRegister(Register r) { this.register = r; }
56 public jq_Type getType() { return type; }
57 public void setType(jq_Type t) { this.type = t; }
58 public int getFlags() { return flags; }
59 public void setFlags(int f) { flags = f; }
60 public void meetFlags(int f) { flags &= f; }
61 public boolean isExactType() { return (flags & PRECISE_TYPE) != 0; }
62 public void clearExactType() { flags &= ~PRECISE_TYPE; }
63 public boolean hasMoreConservativeFlags(RegisterOperand that) { return that.getFlags() == (getFlags() | that.getFlags()); }
64 public Operand copy() { return new RegisterOperand(this.register, this.type, this.flags); }
65 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
66 public Quad getQuad() { return instruction; }
67 public boolean isSimilar(Operand that) { return that instanceof RegisterOperand && ((RegisterOperand)that).getRegister() == this.getRegister(); }
68 public String toString() { return register+" "+((type==null)?"<g>":type.shortName()); }
69 }
70
71 interface ConstOperand extends Operand {
72 Object getWrapped();
73 }
74
75 interface Const4Operand extends ConstOperand {
76 int getBits();
77 }
78
79 interface Const8Operand extends ConstOperand {
80 long getBits();
81 }
82
83 class AConstOperand implements Const4Operand {
84 private Quad instruction;
85 private Object value;
86 public AConstOperand(Object v) { this.value = v; }
87
88
89
90 public Object getValue() { return value; }
91 public void setValue(Object o) { this.value = o; }
92 public String toString() {
93 if (value instanceof String) return "AConst: \""+value+"\"";
94 return "AConst: "+value;
95 }
96 public jq_Reference getType() {
97 if (value == null) return jq_NullType.NULL_TYPE;
98 return Reflection.getTypeOf(this.value);
99 }
100 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
101 public Quad getQuad() { return instruction; }
102 public Operand copy() { return new AConstOperand(value); }
103 public boolean isSimilar(Operand that) { return that instanceof AConstOperand && ((AConstOperand)that).getValue() == this.getValue(); }
104 public int getBits() {
105 return HeapAddress.addressOf(value).to32BitValue();
106 }
107 public Object getWrapped() {
108 return value;
109 }
110 }
111
112 class PConstOperand implements Const4Operand {
113 private Quad instruction;
114 private Address value;
115 public PConstOperand(Address v) { this.value = v; }
116
117
118
119 public Address getValue() { return value; }
120 public void setValue(Address o) { this.value = o; }
121 public String toString() {
122 return "PConst: "+(value==null?"<null>":value.stringRep());
123 }
124 public jq_Reference getType() {
125 return Address._class;
126 }
127 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
128 public Quad getQuad() { return instruction; }
129 public Operand copy() { return new PConstOperand(value); }
130 public boolean isSimilar(Operand o) {
131 if (!(o instanceof PConstOperand)) return false;
132 PConstOperand that = (PConstOperand)o;
133 return (this.getValue() == null && (that.getValue() == null || that.getValue().isNull())) ||
134 this.getValue().difference(that.getValue()) == 0;
135 }
136 public int getBits() { return value==null?0:value.to32BitValue(); }
137 public Object getWrapped() {
138 return new Integer(getBits());
139 }
140 }
141
142 class IConstOperand implements Const4Operand {
143 private Quad instruction;
144 private int value;
145 public IConstOperand(int v) { this.value = v; }
146
147
148
149 public int getValue() { return value; }
150 public void setValue(int o) { this.value = o; }
151 public String toString() { return "IConst: "+value; }
152 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
153 public Quad getQuad() { return instruction; }
154 public Operand copy() { return new IConstOperand(value); }
155 public boolean isSimilar(Operand that) { return that instanceof IConstOperand && ((IConstOperand)that).getValue() == this.getValue(); }
156 public int getBits() { return value; }
157 public Object getWrapped() {
158 return new Integer(value);
159 }
160 }
161
162 class FConstOperand implements Const4Operand {
163 private Quad instruction;
164 private float value;
165 public FConstOperand(float v) { this.value = v; }
166
167
168
169 public float getValue() { return value; }
170 public void setValue(float o) { this.value = o; }
171 public String toString() { return "FConst: "+value; }
172 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
173 public Quad getQuad() { return instruction; }
174 public Operand copy() { return new FConstOperand(value); }
175 public boolean isSimilar(Operand that) { return that instanceof FConstOperand && ((FConstOperand)that).getValue() == this.getValue(); }
176 public int getBits() { return Float.floatToRawIntBits(value); }
177 public Object getWrapped() {
178 return new Float(value);
179 }
180 }
181
182 class LConstOperand implements Const8Operand {
183 private Quad instruction;
184 private long value;
185 public LConstOperand(long v) { this.value = v; }
186
187
188
189 public long getValue() { return value; }
190 public void setValue(long o) { this.value = o; }
191 public String toString() { return "LConst: "+value; }
192 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
193 public Quad getQuad() { return instruction; }
194 public Operand copy() { return new LConstOperand(value); }
195 public boolean isSimilar(Operand that) { return that instanceof LConstOperand && ((LConstOperand)that).getValue() == this.getValue(); }
196 public long getBits() { return value; }
197 public Object getWrapped() {
198 return new Long(value);
199 }
200 }
201
202 class DConstOperand implements Const8Operand {
203 private Quad instruction;
204 private double value;
205 public DConstOperand(double v) { this.value = v; }
206
207
208
209 public double getValue() { return value; }
210 public void setValue(double o) { this.value = o; }
211 public String toString() { return "DConst: "+value; }
212 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
213 public Quad getQuad() { return instruction; }
214 public Operand copy() { return new DConstOperand(value); }
215 public boolean isSimilar(Operand that) { return that instanceof DConstOperand && ((DConstOperand)that).getValue() == this.getValue(); }
216 public long getBits() { return Double.doubleToRawLongBits(value); }
217 public Object getWrapped() {
218 return new Double(value);
219 }
220 }
221
222 class UnnecessaryGuardOperand implements Operand {
223 private Quad instruction;
224 public UnnecessaryGuardOperand() {}
225
226
227 public String toString() { return "<no guard>"; }
228 public Operand copy() { return new UnnecessaryGuardOperand(); }
229 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
230 public Quad getQuad() { return instruction; }
231 public boolean isSimilar(Operand that) { return that instanceof UnnecessaryGuardOperand; }
232 }
233
234 class ConditionOperand implements Operand {
235 private Quad instruction; byte condition;
236 public ConditionOperand(byte c) { condition = c; }
237
238
239
240 public byte getCondition() { return condition; }
241 public void setCondition(byte o) { this.condition = o; }
242 public String toString() { return BytecodeVisitor.cmpopnames[condition]; }
243 public Operand copy() { return new ConditionOperand(condition); }
244 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
245 public Quad getQuad() { return instruction; }
246 public boolean isSimilar(Operand that) { return that instanceof ConditionOperand && ((ConditionOperand)that).getCondition() == this.getCondition(); }
247 }
248
249 class FieldOperand implements Operand {
250 private Quad instruction; jq_Field field;
251 public FieldOperand(jq_Field f) { field = f; }
252 public jq_Field getField() { return field; }
253 public void setField(jq_Field f) { this.field = f; }
254 public void resolve() { this.field = (jq_Field) this.field.resolve(); }
255 public String toString() { return "."+field.getName(); }
256 public Operand copy() { return new FieldOperand(field); }
257 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
258 public Quad getQuad() { return instruction; }
259 public boolean isSimilar(Operand that) { return that instanceof FieldOperand && ((FieldOperand)that).getField() == this.getField(); }
260 }
261
262 class TypeOperand implements Operand {
263 private Quad instruction; jq_Type type;
264 TypeOperand(jq_Type f) { type = f; }
265 public jq_Type getType() { return type; }
266 public void setType(jq_Type f) { this.type = f; }
267 public String toString() { return type.toString(); }
268 public Operand copy() { return new TypeOperand(type); }
269 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
270 public Quad getQuad() { return instruction; }
271 public boolean isSimilar(Operand that) { return that instanceof TypeOperand && ((TypeOperand)that).getType() == this.getType(); }
272 }
273
274 class TargetOperand implements Operand {
275 private Quad instruction; BasicBlock target;
276 public TargetOperand(BasicBlock t) { target = t; }
277 public BasicBlock getTarget() { return target; }
278 public void setTarget(BasicBlock f) { this.target = f; }
279 public String toString() { return target.toString(); }
280 public Operand copy() { return new TargetOperand(target); }
281 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
282 public Quad getQuad() { return instruction; }
283 public boolean isSimilar(Operand that) { return that instanceof TargetOperand && ((TargetOperand)that).getTarget() == this.getTarget(); }
284 }
285
286 class MethodOperand implements Operand {
287 private Quad instruction; jq_Method target;
288 public MethodOperand(jq_Method t) { target = t; }
289 public jq_Method getMethod() { return target; }
290 public void setMethod(jq_Method f) { this.target = f; }
291 public void resolve() { this.target = (jq_Method) this.target.resolve(); }
292 public String toString() { return target.toString(); }
293 public Operand copy() { return new MethodOperand(target); }
294 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
295 public Quad getQuad() { return instruction; }
296 public boolean isSimilar(Operand that) { return that instanceof MethodOperand && ((MethodOperand)that).getMethod() == this.getMethod(); }
297 }
298
299 class IntValueTableOperand implements Operand {
300 private Quad instruction; int[] table;
301 public IntValueTableOperand(int[] t) { table = t; }
302 public void set(int i, int b) { table[i] = b; }
303 public int get(int i) { return table[i]; }
304 public int size() { return table.length; }
305 public String toString() {
306 StringBuffer sb = new StringBuffer("{ ");
307 if (table.length > 0) {
308 sb.append(table[0]);
309 for (int i=1; i<table.length; ++i) {
310 sb.append(", ");
311 sb.append(table[i]);
312 }
313 }
314 sb.append(" }");
315 return sb.toString();
316 }
317 public Operand copy() {
318 int[] t2 = new int[this.table.length];
319 System.arraycopy(this.table, 0, t2, 0, t2.length);
320 return new IntValueTableOperand(t2);
321 }
322 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
323 public Quad getQuad() { return instruction; }
324 public boolean isSimilar(Operand that) { return false; }
325 }
326
327 class BasicBlockTableOperand implements Operand {
328 private Quad instruction; BasicBlock[] table;
329 public BasicBlockTableOperand(BasicBlock[] t) { table = t; }
330 public void set(int i, BasicBlock b) { table[i] = b; }
331 public BasicBlock get(int i) { return table[i]; }
332 public int size() { return table.length; }
333 public String toString() {
334 StringBuffer sb = new StringBuffer("{ ");
335 if (table.length > 0) {
336 sb.append(table[0]);
337 for (int i=1; i<table.length; ++i) {
338 sb.append(", ");
339 sb.append(table[i]);
340 }
341 }
342 sb.append(" }");
343 return sb.toString();
344 }
345 public Operand copy() {
346 BasicBlock[] t2 = new BasicBlock[this.table.length];
347 System.arraycopy(this.table, 0, t2, 0, t2.length);
348 return new BasicBlockTableOperand(t2);
349 }
350 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
351 public Quad getQuad() { return instruction; }
352 public boolean isSimilar(Operand that) { return false; }
353 }
354
355 class ParamListOperand implements Operand {
356 private Quad instruction; RegisterOperand[] params;
357 public ParamListOperand(RegisterOperand[] t) { params = t; }
358 public void set(int i, RegisterOperand b) {
359 params[i] = b;
360 if (b != null) b.attachToQuad(instruction);
361 }
362 public RegisterOperand get(int i) { return params[i]; }
363 public int length() { return params.length; }
364 public int words() {
365 int total = 0;
366 for (int i=0; i<params.length; ++i) {
367 ++total;
368 if (params[i].getType().getReferenceSize() == 8)
369 ++total;
370 }
371 return total;
372 }
373 public String toString() {
374 StringBuffer sb = new StringBuffer("(");
375 if (params.length > 0) {
376 sb.append(params[0]);
377 for (int i=1; i<params.length; ++i) {
378 sb.append(", ");
379 sb.append(params[i]);
380 }
381 }
382 sb.append(")");
383 return sb.toString();
384 }
385 public Operand copy() {
386 RegisterOperand[] t2 = new RegisterOperand[this.params.length];
387 for (int i=0; i<t2.length; ++i) {
388 t2[i] = (RegisterOperand)this.params[i].copy();
389 }
390 return new ParamListOperand(t2);
391 }
392 public void attachToQuad(Quad q) { Assert._assert(instruction == null); instruction = q; }
393 public Quad getQuad() { return instruction; }
394 public boolean isSimilar(Operand that) { return false; }
395 }
396
397 }