KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hansel > HanselInterpreter


1 package org.hansel;
2
3 import java.util.Iterator JavaDoc;
4 import java.util.List JavaDoc;
5
6 import org.hansel.stack.BinaryOperatorEntry;
7 import org.hansel.stack.HanselValue;
8 import org.hansel.stack.PrefixOpEntry;
9 import org.objectweb.asm.Opcodes;
10 import org.objectweb.asm.Type;
11 import org.objectweb.asm.tree.AbstractInsnNode;
12 import org.objectweb.asm.tree.FieldInsnNode;
13 import org.objectweb.asm.tree.IntInsnNode;
14 import org.objectweb.asm.tree.LdcInsnNode;
15 import org.objectweb.asm.tree.LocalVariableNode;
16 import org.objectweb.asm.tree.MethodInsnNode;
17 import org.objectweb.asm.tree.MultiANewArrayInsnNode;
18 import org.objectweb.asm.tree.TypeInsnNode;
19 import org.objectweb.asm.tree.VarInsnNode;
20 import org.objectweb.asm.tree.analysis.SourceInterpreter;
21 import org.objectweb.asm.tree.analysis.Value;
22
23 public final class HanselInterpreter extends SourceInterpreter {
24     private static final int PRECEDENCE_CAST = 1;
25     private static final int PRECEDENCE_UNARY_MINUS = 1;
26     private static final int PRECEDENCE_MUL = 2;
27     private static final int PRECEDENCE_ADD = 3;
28     private static final int PRECEDENCE_SHIFT = 4;
29     private static final int PRECEDENCE_INSTANCEOF = 5;
30     private static final int PRECEDENCE_COMPARE = 5;
31     private static final int PRECEDENCE_AND = 7;
32     private static final int PRECEDENCE_XOR = 8;
33     private static final int PRECEDENCE_OR = 9;
34     //private InsnList instructions;
35
private List JavaDoc localVariables;
36
37     /** Creates a new instance of HanselInterpreter */
38     public HanselInterpreter(/*InsnList instructions, */List JavaDoc localVariables) {
39         //this.instructions = instructions;
40
this.localVariables = localVariables;
41         //System.out.println("LocalVars: " + localVariables);
42
}
43
44     public Value binaryOperation(AbstractInsnNode insn, Value value1, Value value2) {
45        switch (insn.getOpcode()) {
46            case Opcodes.PUTFIELD:
47            case Opcodes.IF_ICMPEQ:
48            case Opcodes.IF_ICMPNE:
49            case Opcodes.IF_ICMPLT:
50            case Opcodes.IF_ICMPGE:
51            case Opcodes.IF_ICMPGT:
52            case Opcodes.IF_ICMPLE:
53            case Opcodes.IF_ACMPEQ:
54            case Opcodes.IF_ACMPNE:
55                return null;
56            case Opcodes.LALOAD:
57            case Opcodes.DALOAD:
58                return new HanselValue(value1 + "[" + value2 + "]", false, 2);
59
60            case Opcodes.IALOAD:
61            case Opcodes.FALOAD:
62            case Opcodes.AALOAD:
63            case Opcodes.CALOAD:
64            case Opcodes.SALOAD:
65                return new HanselValue(value1 + "[" + value2 + "]", false, 1);
66            case Opcodes.BALOAD:
67                return new HanselValue(value1 + "[" + value2 + "]", true, 1);
68            case Opcodes.IADD:
69            case Opcodes.LADD:
70            case Opcodes.FADD:
71            case Opcodes.DADD:
72                return new BinaryOperatorEntry("+", PRECEDENCE_ADD, value1, value2);
73            case Opcodes.ISUB:
74            case Opcodes.LSUB:
75            case Opcodes.FSUB:
76            case Opcodes.DSUB:
77                return new BinaryOperatorEntry("-", PRECEDENCE_ADD, value1, value2);
78            case Opcodes.IMUL:
79            case Opcodes.LMUL:
80            case Opcodes.FMUL:
81            case Opcodes.DMUL:
82                return new BinaryOperatorEntry("*", PRECEDENCE_MUL, value1, value2);
83            case Opcodes.IDIV:
84            case Opcodes.LDIV:
85            case Opcodes.FDIV:
86            case Opcodes.DDIV:
87                return new BinaryOperatorEntry("/", PRECEDENCE_MUL, value1, value2);
88            case Opcodes.IREM:
89            case Opcodes.LREM:
90            case Opcodes.FREM:
91            case Opcodes.DREM:
92                return new BinaryOperatorEntry("%", PRECEDENCE_MUL, value1, value2);
93            case Opcodes.ISHL:
94            case Opcodes.LSHL:
95                return new BinaryOperatorEntry("<<", PRECEDENCE_SHIFT, value1, value2);
96            case Opcodes.ISHR:
97            case Opcodes.LSHR:
98            case Opcodes.IUSHR:
99            case Opcodes.LUSHR:
100                return new BinaryOperatorEntry(">>", PRECEDENCE_SHIFT, value1, value2);
101            case Opcodes.IAND:
102            case Opcodes.LAND:
103                return new BinaryOperatorEntry("&", PRECEDENCE_AND, value1, value2);
104            case Opcodes.IOR:
105            case Opcodes.LOR:
106                return new BinaryOperatorEntry("|", PRECEDENCE_OR, value1, value2);
107            case Opcodes.IXOR:
108            case Opcodes.LXOR:
109                return new BinaryOperatorEntry("^", PRECEDENCE_XOR, value1, value2);
110            case Opcodes.LCMP:
111            case Opcodes.FCMPL:
112            case Opcodes.FCMPG:
113            case Opcodes.DCMPL:
114            case Opcodes.DCMPG:
115                return new BinaryOperatorEntry("<", PRECEDENCE_COMPARE, value1, value2, 1);
116
117            default:
118                throw failure(insn);
119         }
120     }
121     
122     private HanselValue findLocalVar(int index, AbstractInsnNode insn) {
123         Iterator JavaDoc it = localVariables.iterator();
124         //int insnIndex = instructions.indexOf(insn);
125

126         while (it.hasNext()) {
127             LocalVariableNode lvn = (LocalVariableNode) it.next();
128            
129             // TODO: FixMe....
130
if ((lvn.index == index) /*&&
131                 (insnIndex > instructions.indexOf(lvn.start)) &&
132                 (insnIndex < instructions.indexOf(lvn.end))*/
) {
133                 //System.err.println("Returning local var for: " + index + " " + lvn.desc + " " + getSize(lvn.desc));
134
return new HanselValue(lvn.name, isBool(lvn.desc), getSize(lvn.desc));
135             }
136         }
137
138         return new HanselValue("Unknown local: " + index, false, 1);
139     }
140
141  
142     
143     private int getSize(String JavaDoc desc) {
144         return Type.getType(desc).getSize();
145     }
146
147     private boolean isBool(String JavaDoc desc) {
148         return isBool(Type.getType(desc));
149     }
150
151     private boolean isBool(Type type) {
152         return type.equals(Type.BOOLEAN_TYPE);
153     }
154
155     public Value copyOperation(AbstractInsnNode insn, Value value) {
156         if (insn instanceof VarInsnNode) {
157             return findLocalVar(((VarInsnNode) insn).var, insn);
158         }
159
160         switch (insn.getOpcode()) {
161             case Opcodes.DUP:
162             case Opcodes.DUP_X1:
163             case Opcodes.DUP_X2:
164             case Opcodes.DUP2:
165             case Opcodes.DUP2_X1:
166             case Opcodes.DUP2_X2:
167             case Opcodes.SWAP:
168                 return value;
169
170             case Opcodes.ISTORE:
171             case Opcodes.LSTORE:
172             case Opcodes.FSTORE:
173             case Opcodes.DSTORE:
174             case Opcodes.ASTORE:
175                 return HanselValue.DONT_CARE;
176             default: throw failure(insn);
177         }
178     }
179
180
181     public Value merge(Value v, Value w) {
182         return v;
183     }
184
185     private HanselValue multiANewArray(MultiANewArrayInsnNode node, List JavaDoc values) {
186         String JavaDoc result = node.desc;
187
188         for (int i=0;i<values.size(); i++) {
189             result += "[" + values.get(i) + "]";
190         }
191
192         return new HanselValue(result, false, 1);
193     }
194     
195     private HanselValue invokeMethod(MethodInsnNode node, List JavaDoc values) {
196         String JavaDoc result = "";
197         int start = 0;
198         
199         if (node.getOpcode() != Opcodes.INVOKESTATIC) {
200             start = 1;
201             result = values.get(0) + ".";
202         }
203
204         result += node.name + "(";
205         for (int i=start; i<values.size(); i++) {
206             result += values.get(i);
207             if (i != values.size() - 1) {
208                 result += ", ";
209             }
210         }
211
212         return new HanselValue(result + ")", isBool(Type.getReturnType(node.desc)),
213                                Type.getReturnType(node.desc).getSize());
214     }
215
216
217     public Value naryOperation(AbstractInsnNode insn, List JavaDoc values) {
218    
219         switch (insn.getOpcode()) {
220             case Opcodes.INVOKESPECIAL:
221             case Opcodes.INVOKEVIRTUAL:
222             case Opcodes.INVOKEINTERFACE:
223             case Opcodes.INVOKESTATIC:
224                 return invokeMethod((MethodInsnNode) insn, values);
225             case Opcodes.MULTIANEWARRAY:
226                 return multiANewArray((MultiANewArrayInsnNode) insn, values);
227
228                 
229             default:
230                 throw failure(insn);
231         }
232     }
233     
234     private IllegalStateException JavaDoc failure(AbstractInsnNode insn) {
235         Thread.dumpStack();
236         return new IllegalStateException JavaDoc("Unknown instruction: " + insn.getOpcode() + " " + insn + " (Class: " + insn.getClass() + ")");
237     }
238
239     public Value newOperation(AbstractInsnNode insn) {
240        switch (insn.getOpcode()) {
241            case Opcodes.ACONST_NULL:
242             return HanselValue.NULL;
243            case Opcodes.LCONST_0: return HanselValue.ZERO_2;
244            case Opcodes.LCONST_1: return HanselValue.ONE_2;
245            case Opcodes.FCONST_0: return HanselValue.ZERO_1;
246            case Opcodes.FCONST_1: return HanselValue.ONE_1;
247            case Opcodes.FCONST_2: return new HanselValue("2", false, 1);
248            case Opcodes.DCONST_0: return HanselValue.ZERO_2;
249            case Opcodes.DCONST_1: return HanselValue.ONE_1;
250            case Opcodes.ICONST_M1: return new HanselValue("-1", false,1);
251            case Opcodes.ICONST_0: return HanselValue.ZERO_1;
252            case Opcodes.ICONST_1: return HanselValue.ONE_1;
253            case Opcodes.ICONST_2: return new HanselValue("2", false, 1);
254            case Opcodes.ICONST_3: return new HanselValue("3", false, 1);
255            case Opcodes.ICONST_4: return new HanselValue("4", false, 1);
256            case Opcodes.ICONST_5: return new HanselValue("5", false, 1);
257            case Opcodes.BIPUSH:
258            case Opcodes.SIPUSH:
259                return new HanselValue(String.valueOf(((IntInsnNode) insn).operand), false, 1);
260            case Opcodes.LDC:
261                return formatLDC(((LdcInsnNode) insn).cst);
262            case Opcodes.GETSTATIC:
263                return new HanselValue(((FieldInsnNode) insn).name, isBool(((FieldInsnNode) insn).desc),
264                                       getSize((((FieldInsnNode) insn).desc)));
265            case Opcodes.JSR:
266                return HanselValue.DONT_CARE;
267            case Opcodes.NEW:
268                 return new HanselValue("new " + ((TypeInsnNode) insn).desc + "()", false, 1);
269            default:
270                throw failure(insn);
271         }
272     }
273     
274     private HanselValue formatLDC(Object JavaDoc cst) {
275         if (cst instanceof Type) {
276             Type t = (Type) cst;
277             if (t.getSort() == Type.OBJECT) {
278                 String JavaDoc result = t.getClassName();
279                 if (result.indexOf('.') > -1) {
280                     return new HanselValue(result.substring(result.lastIndexOf('.') + 1) + ".class",
281                                            false, 1);
282                 }
283             }
284         }
285
286         if ((cst instanceof Double JavaDoc) || (cst instanceof Long JavaDoc)) {
287             return new HanselValue(cst.toString(), false, 2);
288         } else if (cst instanceof String JavaDoc) {
289             return new HanselValue("\"" + cst.toString() + "\"", false, 1);
290         } else {
291             return new HanselValue(cst.toString(), false, 1);
292         }
293     }
294
295     public Value newValue(Type type) {
296         return HanselValue.DONT_CARE;
297     }
298     
299     public Value ternaryOperation(AbstractInsnNode insn, Value value1, Value value2, Value value3) {
300         switch (insn.getOpcode()) {
301             case Opcodes.AASTORE:
302             case Opcodes.IASTORE:
303             case Opcodes.LASTORE:
304             case Opcodes.FASTORE:
305             case Opcodes.DASTORE:
306             case Opcodes.BASTORE:
307             case Opcodes.CASTORE:
308             case Opcodes.SASTORE:
309                 return HanselValue.DONT_CARE;
310             default: throw failure(insn);
311         }
312     }
313     
314     public Value unaryOperation(AbstractInsnNode insn, Value value) {
315         switch (insn.getOpcode()) {
316             case Opcodes.ATHROW:
317             case Opcodes.MONITORENTER:
318             case Opcodes.MONITOREXIT:
319             case Opcodes.IFNULL:
320             case Opcodes.IFNONNULL:
321             case Opcodes.IFEQ:
322             case Opcodes.IFNE:
323             case Opcodes.IFLT:
324             case Opcodes.IFGE:
325             case Opcodes.IFGT:
326             case Opcodes.IFLE:
327             case Opcodes.TABLESWITCH:
328             case Opcodes.LOOKUPSWITCH:
329             case Opcodes.IRETURN:
330             case Opcodes.LRETURN:
331             case Opcodes.FRETURN:
332             case Opcodes.DRETURN:
333             case Opcodes.ARETURN:
334             case Opcodes.PUTSTATIC:
335                 // Value is not needed.
336
return null;
337             case Opcodes.IINC:
338                 return HanselValue.DONT_CARE;
339             case Opcodes.INEG:
340             case Opcodes.LNEG:
341             case Opcodes.FNEG:
342             case Opcodes.DNEG:
343                 return new PrefixOpEntry("-", PRECEDENCE_UNARY_MINUS, (HanselValue) value);
344             case Opcodes.I2L:
345             case Opcodes.F2L:
346             case Opcodes.D2L:
347                 return new PrefixOpEntry("(long)", PRECEDENCE_CAST, (HanselValue) value, 2);
348             case Opcodes.I2F:
349             case Opcodes.L2F:
350             case Opcodes.D2F:
351                 return new PrefixOpEntry("(float)", PRECEDENCE_CAST, (HanselValue) value, 1);
352             case Opcodes.I2D:
353             case Opcodes.L2D:
354             case Opcodes.F2D:
355                 return new PrefixOpEntry("(double)", PRECEDENCE_CAST, (HanselValue) value, 2);
356             case Opcodes.L2I:
357             case Opcodes.F2I:
358             case Opcodes.D2I:
359                 return new PrefixOpEntry("(int)", PRECEDENCE_CAST, (HanselValue) value, 1);
360             case Opcodes.I2B:
361                 return new PrefixOpEntry("(boolean)", PRECEDENCE_CAST, (HanselValue) value, 1);
362             case Opcodes.I2C:
363                 return new PrefixOpEntry("(char)", PRECEDENCE_CAST, (HanselValue) value, 1);
364             case Opcodes.I2S:
365                 return new PrefixOpEntry("(short)", PRECEDENCE_CAST, (HanselValue) value, 1);
366             case Opcodes.INSTANCEOF:
367                 return new BinaryOperatorEntry("instanceof", PRECEDENCE_INSTANCEOF,
368                                                (HanselValue) value,
369                                                new HanselValue(((TypeInsnNode) insn).desc, false, 1), 1);
370             case Opcodes.NEWARRAY:
371                 return new HanselValue("new " + getType(((IntInsnNode) insn).operand) + "[" + value + "]", false, 1);
372              case Opcodes.ANEWARRAY:
373                 return new HanselValue("new " + ((TypeInsnNode) insn).desc + "[" + value + "]", false, 1);
374             case Opcodes.ARRAYLENGTH:
375                 return new HanselValue(value + ".length", false, 1);
376             case Opcodes.CHECKCAST:
377                 return new PrefixOpEntry("("+ ((TypeInsnNode) insn).desc + ")",
378                                          PRECEDENCE_CAST, (HanselValue) value,
379                                          1);
380             case Opcodes.GETFIELD:
381                 return new HanselValue("this." + ((FieldInsnNode) insn).name, isBool(((FieldInsnNode) insn).desc),
382                                        getSize(((FieldInsnNode) insn).desc));
383
384             default:
385                 throw failure(insn);
386         }
387     }
388
389     /**
390      * Returns name of primitiv type for operand of newarray.
391      */

392     private String JavaDoc getType(int operand) {
393         switch (operand) {
394             case 4: return "boolean";
395             case 5: return "char";
396             case 6: return "float";
397             case 7: return "double";
398             case 8: return "byte";
399             case 9: return "short";
400             case 10: return "int";
401             case 11: return "long";
402             default: throw new IllegalArgumentException JavaDoc("Unknown type of newarray: " + operand);
403         }
404     }
405
406 }
407
Popular Tags