001: /***
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (c) 2000-2005 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: switch (insn.getOpcode()) {
080: case ACONST_NULL:
081: return newValue(Type.getType("Lnull;"));
082: case ICONST_M1:
083: case ICONST_0:
084: case ICONST_1:
085: case ICONST_2:
086: case ICONST_3:
087: case ICONST_4:
088: case ICONST_5:
089: return BasicValue.INT_VALUE;
090: case LCONST_0:
091: case LCONST_1:
092: return BasicValue.LONG_VALUE;
093: case FCONST_0:
094: case FCONST_1:
095: case FCONST_2:
096: return BasicValue.FLOAT_VALUE;
097: case DCONST_0:
098: case DCONST_1:
099: return BasicValue.DOUBLE_VALUE;
100: case BIPUSH:
101: case SIPUSH:
102: return BasicValue.INT_VALUE;
103: case LDC:
104: Object cst = ((LdcInsnNode) insn).cst;
105: if (cst instanceof Integer) {
106: return BasicValue.INT_VALUE;
107: } else if (cst instanceof Float) {
108: return BasicValue.FLOAT_VALUE;
109: } else if (cst instanceof Long) {
110: return BasicValue.LONG_VALUE;
111: } else if (cst instanceof Double) {
112: return BasicValue.DOUBLE_VALUE;
113: } else if (cst instanceof Type) {
114: return newValue(Type.getType("Ljava/lang/Class;"));
115: } else {
116: return newValue(Type.getType(cst.getClass()));
117: }
118: case JSR:
119: return BasicValue.RETURNADDRESS_VALUE;
120: case GETSTATIC:
121: return newValue(Type.getType(((FieldInsnNode) insn).desc));
122: case NEW:
123: return newValue(Type.getType("L"
124: + ((TypeInsnNode) insn).desc + ";"));
125: default:
126: throw new Error("Internal error.");
127: }
128: }
129:
130: public Value copyOperation(final AbstractInsnNode insn,
131: final Value value) throws AnalyzerException {
132: return value;
133: }
134:
135: public Value unaryOperation(final AbstractInsnNode insn,
136: final Value value) throws AnalyzerException {
137: switch (insn.getOpcode()) {
138: case INEG:
139: case IINC:
140: case L2I:
141: case F2I:
142: case D2I:
143: case I2B:
144: case I2C:
145: case I2S:
146: return BasicValue.INT_VALUE;
147: case FNEG:
148: case I2F:
149: case L2F:
150: case D2F:
151: return BasicValue.FLOAT_VALUE;
152: case LNEG:
153: case I2L:
154: case F2L:
155: case D2L:
156: return BasicValue.LONG_VALUE;
157: case DNEG:
158: case I2D:
159: case L2D:
160: case F2D:
161: return BasicValue.DOUBLE_VALUE;
162: case IFEQ:
163: case IFNE:
164: case IFLT:
165: case IFGE:
166: case IFGT:
167: case IFLE:
168: case TABLESWITCH:
169: case LOOKUPSWITCH:
170: case IRETURN:
171: case LRETURN:
172: case FRETURN:
173: case DRETURN:
174: case ARETURN:
175: case PUTSTATIC:
176: return null;
177: case GETFIELD:
178: return newValue(Type.getType(((FieldInsnNode) insn).desc));
179: case NEWARRAY:
180: switch (((IntInsnNode) insn).operand) {
181: case T_BOOLEAN:
182: return newValue(Type.getType("[Z"));
183: case T_CHAR:
184: return newValue(Type.getType("[C"));
185: case T_BYTE:
186: return newValue(Type.getType("[B"));
187: case T_SHORT:
188: return newValue(Type.getType("[S"));
189: case T_INT:
190: return newValue(Type.getType("[I"));
191: case T_FLOAT:
192: return newValue(Type.getType("[F"));
193: case T_DOUBLE:
194: return newValue(Type.getType("[D"));
195: case T_LONG:
196: return newValue(Type.getType("[J"));
197: default:
198: throw new AnalyzerException("Invalid array type");
199: }
200: case ANEWARRAY:
201: String desc = ((TypeInsnNode) insn).desc;
202: if (desc.charAt(0) == '[') {
203: return newValue(Type.getType("[" + desc));
204: } else {
205: return newValue(Type.getType("[L" + desc + ";"));
206: }
207: case ARRAYLENGTH:
208: return BasicValue.INT_VALUE;
209: case ATHROW:
210: return null;
211: case CHECKCAST:
212: desc = ((TypeInsnNode) insn).desc;
213: if (desc.charAt(0) == '[') {
214: return newValue(Type.getType(desc));
215: } else {
216: return newValue(Type.getType("L" + desc + ";"));
217: }
218: case INSTANCEOF:
219: return BasicValue.INT_VALUE;
220: case MONITORENTER:
221: case MONITOREXIT:
222: case IFNULL:
223: case IFNONNULL:
224: return null;
225: default:
226: throw new Error("Internal error.");
227: }
228: }
229:
230: public Value binaryOperation(final AbstractInsnNode insn,
231: final Value value1, final Value value2)
232: throws AnalyzerException {
233: switch (insn.getOpcode()) {
234: case IALOAD:
235: case BALOAD:
236: case CALOAD:
237: case SALOAD:
238: case IADD:
239: case ISUB:
240: case IMUL:
241: case IDIV:
242: case IREM:
243: case ISHL:
244: case ISHR:
245: case IUSHR:
246: case IAND:
247: case IOR:
248: case IXOR:
249: return BasicValue.INT_VALUE;
250: case FALOAD:
251: case FADD:
252: case FSUB:
253: case FMUL:
254: case FDIV:
255: case FREM:
256: return BasicValue.FLOAT_VALUE;
257: case LALOAD:
258: case LADD:
259: case LSUB:
260: case LMUL:
261: case LDIV:
262: case LREM:
263: case LSHL:
264: case LSHR:
265: case LUSHR:
266: case LAND:
267: case LOR:
268: case LXOR:
269: return BasicValue.LONG_VALUE;
270: case DALOAD:
271: case DADD:
272: case DSUB:
273: case DMUL:
274: case DDIV:
275: case DREM:
276: return BasicValue.DOUBLE_VALUE;
277: case AALOAD:
278: return BasicValue.REFERENCE_VALUE;
279: case LCMP:
280: case FCMPL:
281: case FCMPG:
282: case DCMPL:
283: case DCMPG:
284: return BasicValue.INT_VALUE;
285: case IF_ICMPEQ:
286: case IF_ICMPNE:
287: case IF_ICMPLT:
288: case IF_ICMPGE:
289: case IF_ICMPGT:
290: case IF_ICMPLE:
291: case IF_ACMPEQ:
292: case IF_ACMPNE:
293: case PUTFIELD:
294: return null;
295: default:
296: throw new Error("Internal error.");
297: }
298: }
299:
300: public Value ternaryOperation(final AbstractInsnNode insn,
301: final Value value1, final Value value2, final Value value3)
302: throws AnalyzerException {
303: return null;
304: }
305:
306: public Value naryOperation(final AbstractInsnNode insn,
307: final List values) throws AnalyzerException {
308: if (insn.getOpcode() == MULTIANEWARRAY) {
309: return newValue(Type
310: .getType(((MultiANewArrayInsnNode) insn).desc));
311: } else {
312: return newValue(Type
313: .getReturnType(((MethodInsnNode) insn).desc));
314: }
315: }
316:
317: public Value merge(final Value v, final Value w) {
318: if (!v.equals(w)) {
319: return BasicValue.UNINITIALIZED_VALUE;
320: }
321: return v;
322: }
323: }
|