View Javadoc

1   // Operand.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_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   * @author  John Whaley <jwhaley@alum.mit.edu>
20   * @version $Id: Operand.java 1931 2004-09-22 22:17:47Z joewhaley $
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          //public int hashCode() { return System.identityHashCode(value); }
88          //public boolean equals(Object that) { return equals((AConstOperand)that); }
89          //public boolean equals(AConstOperand that) { return this.value == that.value; }
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         //public int hashCode() { return System.identityHashCode(value); }
117         //public boolean equals(Object that) { return equals((AConstOperand)that); }
118         //public boolean equals(AConstOperand that) { return this.value == that.value; }
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         //public int hashCode() { return value; }
147         //public boolean equals(Object that) { return equals((IConstOperand)that); }
148         //public boolean equals(IConstOperand that) { return this.value == that.value; }
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         //public int hashCode() { return Float.floatToRawIntBits(value); }
167         //public boolean equals(Object that) { return equals((FConstOperand)that); }
168         //public boolean equals(FConstOperand that) { return this.value == that.value; }
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         //public int hashCode() { return (int)(value>>32) ^ (int)value; }
187         //public boolean equals(Object that) { return equals((LConstOperand)that); }
188         //public boolean equals(DConstOperand that) { return this.value == that.value; }
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         //public int hashCode() { long v = Double.doubleToRawLongBits(value); return (int)(v>>32) ^ (int)v; }
207         //public boolean equals(Object that) { return equals((DConstOperand)that); }
208         //public boolean equals(DConstOperand that) { return this.value == that.value; }
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         //public int hashCode() { return 67; }
226         //public boolean equals(Object that) { return that instanceof UnnecessaryGuardOperand; }
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         //public int hashCode() { return condition; }
238         //public boolean equals(Object that) { return this.equals((ConditionOperand)that); }
239         //public boolean equals(ConditionOperand that) { return this.condition == that.condition; }
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 }