1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000-2005 INRIA, France Telecom
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  *    contributors may be used to endorse or promote products derived from
16  *    this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 package org.objectweb.asm.tree.analysis;
31 
32 import java.util.List;
33 
34 import org.objectweb.asm.Opcodes;
35 import org.objectweb.asm.Type;
36 import org.objectweb.asm.tree.AbstractInsnNode;
37 import org.objectweb.asm.tree.FieldInsnNode;
38 import org.objectweb.asm.tree.IntInsnNode;
39 import org.objectweb.asm.tree.LdcInsnNode;
40 import org.objectweb.asm.tree.MethodInsnNode;
41 import org.objectweb.asm.tree.MultiANewArrayInsnNode;
42 import org.objectweb.asm.tree.TypeInsnNode;
43 
44 /**
45  * An {@link Interpreter} for {@link BasicValue} values.
46  *
47  * @author Eric Bruneton
48  * @author Bing Ran
49  */
50 public class BasicInterpreter implements Opcodes, Interpreter {
51 
newValue(final Type type)52     public Value newValue(final Type type) {
53         if (type == null) {
54             return BasicValue.UNINITIALIZED_VALUE;
55         }
56         switch (type.getSort()) {
57             case Type.VOID:
58                 return null;
59             case Type.BOOLEAN:
60             case Type.CHAR:
61             case Type.BYTE:
62             case Type.SHORT:
63             case Type.INT:
64                 return BasicValue.INT_VALUE;
65             case Type.FLOAT:
66                 return BasicValue.FLOAT_VALUE;
67             case Type.LONG:
68                 return BasicValue.LONG_VALUE;
69             case Type.DOUBLE:
70                 return BasicValue.DOUBLE_VALUE;
71             case Type.ARRAY:
72             case Type.OBJECT:
73                 return BasicValue.REFERENCE_VALUE;
74             default:
75                 throw new RuntimeException("Internal error.");
76         }
77     }
78 
newOperation(final AbstractInsnNode insn)79     public Value newOperation(final AbstractInsnNode insn) {
80         switch (insn.getOpcode()) {
81             case ACONST_NULL:
82                 return newValue(Type.getType("Lnull;"));
83             case ICONST_M1:
84             case ICONST_0:
85             case ICONST_1:
86             case ICONST_2:
87             case ICONST_3:
88             case ICONST_4:
89             case ICONST_5:
90                 return BasicValue.INT_VALUE;
91             case LCONST_0:
92             case LCONST_1:
93                 return BasicValue.LONG_VALUE;
94             case FCONST_0:
95             case FCONST_1:
96             case FCONST_2:
97                 return BasicValue.FLOAT_VALUE;
98             case DCONST_0:
99             case DCONST_1:
100                 return BasicValue.DOUBLE_VALUE;
101             case BIPUSH:
102             case SIPUSH:
103                 return BasicValue.INT_VALUE;
104             case LDC:
105                 Object cst = ((LdcInsnNode) insn).cst;
106                 if (cst instanceof Integer) {
107                     return BasicValue.INT_VALUE;
108                 } else if (cst instanceof Float) {
109                     return BasicValue.FLOAT_VALUE;
110                 } else if (cst instanceof Long) {
111                     return BasicValue.LONG_VALUE;
112                 } else if (cst instanceof Double) {
113                     return BasicValue.DOUBLE_VALUE;
114                 } else if (cst instanceof Type) {
115                     return newValue(Type.getType("Ljava/lang/Class;"));
116                 } else {
117                     return newValue(Type.getType(cst.getClass()));
118                 }
119             case JSR:
120                 return BasicValue.RETURNADDRESS_VALUE;
121             case GETSTATIC:
122                 return newValue(Type.getType(((FieldInsnNode) insn).desc));
123             case NEW:
124                 return newValue(Type.getType("L" + ((TypeInsnNode) insn).desc
125                         + ";"));
126             default:
127                 throw new RuntimeException("Internal error.");
128         }
129     }
130 
copyOperation(final AbstractInsnNode insn, final Value value)131     public Value copyOperation(final AbstractInsnNode insn, final Value value)
132             throws AnalyzerException
133     {
134         return value;
135     }
136 
unaryOperation(final AbstractInsnNode insn, final Value value)137     public Value unaryOperation(final AbstractInsnNode insn, final Value value)
138             throws AnalyzerException
139     {
140         switch (insn.getOpcode()) {
141             case INEG:
142             case IINC:
143             case L2I:
144             case F2I:
145             case D2I:
146             case I2B:
147             case I2C:
148             case I2S:
149                 return BasicValue.INT_VALUE;
150             case FNEG:
151             case I2F:
152             case L2F:
153             case D2F:
154                 return BasicValue.FLOAT_VALUE;
155             case LNEG:
156             case I2L:
157             case F2L:
158             case D2L:
159                 return BasicValue.LONG_VALUE;
160             case DNEG:
161             case I2D:
162             case L2D:
163             case F2D:
164                 return BasicValue.DOUBLE_VALUE;
165             case IFEQ:
166             case IFNE:
167             case IFLT:
168             case IFGE:
169             case IFGT:
170             case IFLE:
171             case TABLESWITCH:
172             case LOOKUPSWITCH:
173             case IRETURN:
174             case LRETURN:
175             case FRETURN:
176             case DRETURN:
177             case ARETURN:
178             case PUTSTATIC:
179                 return null;
180             case GETFIELD:
181                 return newValue(Type.getType(((FieldInsnNode) insn).desc));
182             case NEWARRAY:
183                 switch (((IntInsnNode) insn).operand) {
184                     case T_BOOLEAN:
185                         return newValue(Type.getType("[Z"));
186                     case T_CHAR:
187                         return newValue(Type.getType("[C"));
188                     case T_BYTE:
189                         return newValue(Type.getType("[B"));
190                     case T_SHORT:
191                         return newValue(Type.getType("[S"));
192                     case T_INT:
193                         return newValue(Type.getType("[I"));
194                     case T_FLOAT:
195                         return newValue(Type.getType("[F"));
196                     case T_DOUBLE:
197                         return newValue(Type.getType("[D"));
198                     case T_LONG:
199                         return newValue(Type.getType("[J"));
200                     default:
201                         throw new AnalyzerException("Invalid array type");
202                 }
203             case ANEWARRAY:
204                 String desc = ((TypeInsnNode) insn).desc;
205                 if (desc.charAt(0) == '[') {
206                     return newValue(Type.getType("[" + desc));
207                 } else {
208                     return newValue(Type.getType("[L" + desc + ";"));
209                 }
210             case ARRAYLENGTH:
211                 return BasicValue.INT_VALUE;
212             case ATHROW:
213                 return null;
214             case CHECKCAST:
215                 desc = ((TypeInsnNode) insn).desc;
216                 if (desc.charAt(0) == '[') {
217                     return newValue(Type.getType(desc));
218                 } else {
219                     return newValue(Type.getType("L" + desc + ";"));
220                 }
221             case INSTANCEOF:
222                 return BasicValue.INT_VALUE;
223             case MONITORENTER:
224             case MONITOREXIT:
225             case IFNULL:
226             case IFNONNULL:
227                 return null;
228             default:
229                 throw new RuntimeException("Internal error.");
230         }
231     }
232 
binaryOperation( final AbstractInsnNode insn, final Value value1, final Value value2)233     public Value binaryOperation(
234         final AbstractInsnNode insn,
235         final Value value1,
236         final Value value2) throws AnalyzerException
237     {
238         switch (insn.getOpcode()) {
239             case IALOAD:
240             case BALOAD:
241             case CALOAD:
242             case SALOAD:
243             case IADD:
244             case ISUB:
245             case IMUL:
246             case IDIV:
247             case IREM:
248             case ISHL:
249             case ISHR:
250             case IUSHR:
251             case IAND:
252             case IOR:
253             case IXOR:
254                 return BasicValue.INT_VALUE;
255             case FALOAD:
256             case FADD:
257             case FSUB:
258             case FMUL:
259             case FDIV:
260             case FREM:
261                 return BasicValue.FLOAT_VALUE;
262             case LALOAD:
263             case LADD:
264             case LSUB:
265             case LMUL:
266             case LDIV:
267             case LREM:
268             case LSHL:
269             case LSHR:
270             case LUSHR:
271             case LAND:
272             case LOR:
273             case LXOR:
274                 return BasicValue.LONG_VALUE;
275             case DALOAD:
276             case DADD:
277             case DSUB:
278             case DMUL:
279             case DDIV:
280             case DREM:
281                 return BasicValue.DOUBLE_VALUE;
282             case AALOAD:
283                 Type t = ((BasicValue) value1).getType();
284                 if (t != null && t.getSort() == Type.ARRAY) {
285                     return newValue(t.getElementType());
286                 } else {
287                     return BasicValue.REFERENCE_VALUE;
288                 }
289             case LCMP:
290             case FCMPL:
291             case FCMPG:
292             case DCMPL:
293             case DCMPG:
294                 return BasicValue.INT_VALUE;
295             case IF_ICMPEQ:
296             case IF_ICMPNE:
297             case IF_ICMPLT:
298             case IF_ICMPGE:
299             case IF_ICMPGT:
300             case IF_ICMPLE:
301             case IF_ACMPEQ:
302             case IF_ACMPNE:
303             case PUTFIELD:
304                 return null;
305             default:
306                 throw new RuntimeException("Internal error.");
307         }
308     }
309 
ternaryOperation( final AbstractInsnNode insn, final Value value1, final Value value2, final Value value3)310     public Value ternaryOperation(
311         final AbstractInsnNode insn,
312         final Value value1,
313         final Value value2,
314         final Value value3) throws AnalyzerException
315     {
316         return null;
317     }
318 
naryOperation(final AbstractInsnNode insn, final List values)319     public Value naryOperation(final AbstractInsnNode insn, final List values)
320             throws AnalyzerException
321     {
322         if (insn.getOpcode() == MULTIANEWARRAY) {
323             return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
324         } else {
325             return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
326         }
327     }
328 
merge(final Value v, final Value w)329     public Value merge(final Value v, final Value w) {
330         if (!v.equals(w)) {
331             return BasicValue.UNINITIALIZED_VALUE;
332         }
333         return v;
334     }
335 }
336