001: /***
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (c) 2000-2007 INRIA, France Telecom
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: * 2. Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: * 3. Neither the name of the copyright holders nor the names of its
015: * contributors may be used to endorse or promote products derived from
016: * this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028: * THE POSSIBILITY OF SUCH DAMAGE.
029: */package org.objectweb.asm.tree.analysis;
030:
031: import java.util.List;
032:
033: import org.objectweb.asm.Opcodes;
034: import org.objectweb.asm.Type;
035: import org.objectweb.asm.tree.AbstractInsnNode;
036: import org.objectweb.asm.tree.FieldInsnNode;
037: import org.objectweb.asm.tree.IntInsnNode;
038: import org.objectweb.asm.tree.LdcInsnNode;
039: import org.objectweb.asm.tree.MethodInsnNode;
040: import org.objectweb.asm.tree.MultiANewArrayInsnNode;
041: import org.objectweb.asm.tree.TypeInsnNode;
042:
043: /**
044: * An {@link Interpreter} for {@link BasicValue} values.
045: *
046: * @author Eric Bruneton
047: * @author Bing Ran
048: */
049: public class BasicInterpreter implements Opcodes, Interpreter {
050:
051: public Value newValue(final Type type) {
052: if (type == null) {
053: return BasicValue.UNINITIALIZED_VALUE;
054: }
055: switch (type.getSort()) {
056: case Type.VOID:
057: return null;
058: case Type.BOOLEAN:
059: case Type.CHAR:
060: case Type.BYTE:
061: case Type.SHORT:
062: case Type.INT:
063: return BasicValue.INT_VALUE;
064: case Type.FLOAT:
065: return BasicValue.FLOAT_VALUE;
066: case Type.LONG:
067: return BasicValue.LONG_VALUE;
068: case Type.DOUBLE:
069: return BasicValue.DOUBLE_VALUE;
070: case Type.ARRAY:
071: case Type.OBJECT:
072: return BasicValue.REFERENCE_VALUE;
073: default:
074: throw new Error("Internal error");
075: }
076: }
077:
078: public Value newOperation(final AbstractInsnNode insn)
079: throws AnalyzerException {
080: switch (insn.getOpcode()) {
081: case ACONST_NULL:
082: return newValue(Type.getObjectType("null"));
083: case ICONST_M1:
084: case ICONST_0:
085: case ICONST_1:
086: case ICONST_2:
087: case ICONST_3:
088: case ICONST_4:
089: case ICONST_5:
090: return BasicValue.INT_VALUE;
091: case LCONST_0:
092: case LCONST_1:
093: return BasicValue.LONG_VALUE;
094: case FCONST_0:
095: case FCONST_1:
096: case FCONST_2:
097: return BasicValue.FLOAT_VALUE;
098: case DCONST_0:
099: 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.getObjectType("java/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
125: .getObjectType(((TypeInsnNode) insn).desc));
126: default:
127: throw new Error("Internal error.");
128: }
129: }
130:
131: public Value copyOperation(final AbstractInsnNode insn,
132: final Value value) throws AnalyzerException {
133: return value;
134: }
135:
136: public Value unaryOperation(final AbstractInsnNode insn,
137: final Value value) throws AnalyzerException {
138: switch (insn.getOpcode()) {
139: case INEG:
140: case IINC:
141: case L2I:
142: case F2I:
143: case D2I:
144: case I2B:
145: case I2C:
146: case I2S:
147: return BasicValue.INT_VALUE;
148: case FNEG:
149: case I2F:
150: case L2F:
151: case D2F:
152: return BasicValue.FLOAT_VALUE;
153: case LNEG:
154: case I2L:
155: case F2L:
156: case D2L:
157: return BasicValue.LONG_VALUE;
158: case DNEG:
159: case I2D:
160: case L2D:
161: case F2D:
162: return BasicValue.DOUBLE_VALUE;
163: case IFEQ:
164: case IFNE:
165: case IFLT:
166: case IFGE:
167: case IFGT:
168: case IFLE:
169: case TABLESWITCH:
170: case LOOKUPSWITCH:
171: case IRETURN:
172: case LRETURN:
173: case FRETURN:
174: case DRETURN:
175: case ARETURN:
176: case PUTSTATIC:
177: return null;
178: case GETFIELD:
179: return newValue(Type.getType(((FieldInsnNode) insn).desc));
180: case NEWARRAY:
181: switch (((IntInsnNode) insn).operand) {
182: case T_BOOLEAN:
183: return newValue(Type.getType("[Z"));
184: case T_CHAR:
185: return newValue(Type.getType("[C"));
186: case T_BYTE:
187: return newValue(Type.getType("[B"));
188: case T_SHORT:
189: return newValue(Type.getType("[S"));
190: case T_INT:
191: return newValue(Type.getType("[I"));
192: case T_FLOAT:
193: return newValue(Type.getType("[F"));
194: case T_DOUBLE:
195: return newValue(Type.getType("[D"));
196: case T_LONG:
197: return newValue(Type.getType("[J"));
198: default:
199: throw new AnalyzerException("Invalid array type");
200: }
201: case ANEWARRAY:
202: String desc = ((TypeInsnNode) insn).desc;
203: return newValue(Type
204: .getType("[" + Type.getObjectType(desc)));
205: case ARRAYLENGTH:
206: return BasicValue.INT_VALUE;
207: case ATHROW:
208: return null;
209: case CHECKCAST:
210: desc = ((TypeInsnNode) insn).desc;
211: return newValue(Type.getObjectType(desc));
212: case INSTANCEOF:
213: return BasicValue.INT_VALUE;
214: case MONITORENTER:
215: case MONITOREXIT:
216: case IFNULL:
217: case IFNONNULL:
218: return null;
219: default:
220: throw new Error("Internal error.");
221: }
222: }
223:
224: public Value binaryOperation(final AbstractInsnNode insn,
225: final Value value1, final Value value2)
226: throws AnalyzerException {
227: switch (insn.getOpcode()) {
228: case IALOAD:
229: case BALOAD:
230: case CALOAD:
231: case SALOAD:
232: case IADD:
233: case ISUB:
234: case IMUL:
235: case IDIV:
236: case IREM:
237: case ISHL:
238: case ISHR:
239: case IUSHR:
240: case IAND:
241: case IOR:
242: case IXOR:
243: return BasicValue.INT_VALUE;
244: case FALOAD:
245: case FADD:
246: case FSUB:
247: case FMUL:
248: case FDIV:
249: case FREM:
250: return BasicValue.FLOAT_VALUE;
251: case LALOAD:
252: case LADD:
253: case LSUB:
254: case LMUL:
255: case LDIV:
256: case LREM:
257: case LSHL:
258: case LSHR:
259: case LUSHR:
260: case LAND:
261: case LOR:
262: case LXOR:
263: return BasicValue.LONG_VALUE;
264: case DALOAD:
265: case DADD:
266: case DSUB:
267: case DMUL:
268: case DDIV:
269: case DREM:
270: return BasicValue.DOUBLE_VALUE;
271: case AALOAD:
272: return BasicValue.REFERENCE_VALUE;
273: case LCMP:
274: case FCMPL:
275: case FCMPG:
276: case DCMPL:
277: case DCMPG:
278: return BasicValue.INT_VALUE;
279: case IF_ICMPEQ:
280: case IF_ICMPNE:
281: case IF_ICMPLT:
282: case IF_ICMPGE:
283: case IF_ICMPGT:
284: case IF_ICMPLE:
285: case IF_ACMPEQ:
286: case IF_ACMPNE:
287: case PUTFIELD:
288: return null;
289: default:
290: throw new Error("Internal error.");
291: }
292: }
293:
294: public Value ternaryOperation(final AbstractInsnNode insn,
295: final Value value1, final Value value2, final Value value3)
296: throws AnalyzerException {
297: return null;
298: }
299:
300: public Value naryOperation(final AbstractInsnNode insn,
301: final List values) throws AnalyzerException {
302: if (insn.getOpcode() == MULTIANEWARRAY) {
303: return newValue(Type
304: .getType(((MultiANewArrayInsnNode) insn).desc));
305: } else {
306: return newValue(Type
307: .getReturnType(((MethodInsnNode) insn).desc));
308: }
309: }
310:
311: public Value merge(final Value v, final Value w) {
312: if (!v.equals(w)) {
313: return BasicValue.UNINITIALIZED_VALUE;
314: }
315: return v;
316: }
317: }
|