001/***
002 * ASM: a very small and fast Java bytecode manipulation framework
003 * Copyright (c) 2000-2011 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 */
030package io.ebean.enhance.asm.tree.analysis;
031
032import io.ebean.enhance.asm.Type;
033import io.ebean.enhance.asm.tree.AbstractInsnNode;
034
035import java.util.List;
036
037/**
038 * A semantic bytecode interpreter. More precisely, this interpreter only
039 * manages the computation of values from other values: it does not manage the
040 * transfer of values to or from the stack, and to or from the local variables.
041 * This separation allows a generic bytecode {@link Analyzer} to work with
042 * various semantic interpreters, without needing to duplicate the code to
043 * simulate the transfer of values.
044 * 
045 * @param <V>
046 *            type of the Value used for the analysis.
047 * 
048 * @author Eric Bruneton
049 */
050public abstract class Interpreter<V extends Value> {
051
052    protected final int api;
053
054    protected Interpreter(final int api) {
055        this.api = api;
056    }
057
058    /**
059     * Creates a new value that represents the given type.
060     * 
061     * Called for method parameters (including <code>this</code>), exception
062     * handler variable and with <code>null</code> type for variables reserved
063     * by long and double types.
064     * 
065     * @param type
066     *            a primitive or reference type, or <tt>null</tt> to represent
067     *            an uninitialized value.
068     * @return a value that represents the given type. The size of the returned
069     *         value must be equal to the size of the given type.
070     */
071    public abstract V newValue(Type type);
072
073    /**
074     * Interprets a bytecode instruction without arguments. This method is
075     * called for the following opcodes:
076     * 
077     * ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4,
078     * ICONST_5, LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0,
079     * DCONST_1, BIPUSH, SIPUSH, LDC, JSR, GETSTATIC, NEW
080     * 
081     * @param insn
082     *            the bytecode instruction to be interpreted.
083     * @return the result of the interpretation of the given instruction.
084     * @throws AnalyzerException
085     *             if an error occured during the interpretation.
086     */
087    public abstract V newOperation(AbstractInsnNode insn)
088            throws AnalyzerException;
089
090    /**
091     * Interprets a bytecode instruction that moves a value on the stack or to
092     * or from local variables. This method is called for the following opcodes:
093     * 
094     * ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE,
095     * ASTORE, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP
096     * 
097     * @param insn
098     *            the bytecode instruction to be interpreted.
099     * @param value
100     *            the value that must be moved by the instruction.
101     * @return the result of the interpretation of the given instruction. The
102     *         returned value must be <tt>equal</tt> to the given value.
103     * @throws AnalyzerException
104     *             if an error occured during the interpretation.
105     */
106    public abstract V copyOperation(AbstractInsnNode insn, V value)
107            throws AnalyzerException;
108
109    /**
110     * Interprets a bytecode instruction with a single argument. This method is
111     * called for the following opcodes:
112     * 
113     * INEG, LNEG, FNEG, DNEG, IINC, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L,
114     * F2D, D2I, D2L, D2F, I2B, I2C, I2S, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE,
115     * TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN,
116     * PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW, CHECKCAST,
117     * INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL
118     * 
119     * @param insn
120     *            the bytecode instruction to be interpreted.
121     * @param value
122     *            the argument of the instruction to be interpreted.
123     * @return the result of the interpretation of the given instruction.
124     * @throws AnalyzerException
125     *             if an error occured during the interpretation.
126     */
127    public abstract V unaryOperation(AbstractInsnNode insn, V value)
128            throws AnalyzerException;
129
130    /**
131     * Interprets a bytecode instruction with two arguments. This method is
132     * called for the following opcodes:
133     * 
134     * IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD,
135     * LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV,
136     * LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, ISHL, LSHL, ISHR, LSHR, IUSHR,
137     * LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG, DCMPL,
138     * DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
139     * IF_ACMPEQ, IF_ACMPNE, PUTFIELD
140     * 
141     * @param insn
142     *            the bytecode instruction to be interpreted.
143     * @param value1
144     *            the first argument of the instruction to be interpreted.
145     * @param value2
146     *            the second argument of the instruction to be interpreted.
147     * @return the result of the interpretation of the given instruction.
148     * @throws AnalyzerException
149     *             if an error occured during the interpretation.
150     */
151    public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2)
152            throws AnalyzerException;
153
154    /**
155     * Interprets a bytecode instruction with three arguments. This method is
156     * called for the following opcodes:
157     * 
158     * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE
159     * 
160     * @param insn
161     *            the bytecode instruction to be interpreted.
162     * @param value1
163     *            the first argument of the instruction to be interpreted.
164     * @param value2
165     *            the second argument of the instruction to be interpreted.
166     * @param value3
167     *            the third argument of the instruction to be interpreted.
168     * @return the result of the interpretation of the given instruction.
169     * @throws AnalyzerException
170     *             if an error occured during the interpretation.
171     */
172    public abstract V ternaryOperation(AbstractInsnNode insn, V value1,
173                                       V value2, V value3) throws AnalyzerException;
174
175    /**
176     * Interprets a bytecode instruction with a variable number of arguments.
177     * This method is called for the following opcodes:
178     * 
179     * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE,
180     * MULTIANEWARRAY and INVOKEDYNAMIC
181     * 
182     * @param insn
183     *            the bytecode instruction to be interpreted.
184     * @param values
185     *            the arguments of the instruction to be interpreted.
186     * @return the result of the interpretation of the given instruction.
187     * @throws AnalyzerException
188     *             if an error occured during the interpretation.
189     */
190    public abstract V naryOperation(AbstractInsnNode insn,
191            List<? extends V> values) throws AnalyzerException;
192
193    /**
194     * Interprets a bytecode return instruction. This method is called for the
195     * following opcodes:
196     * 
197     * IRETURN, LRETURN, FRETURN, DRETURN, ARETURN
198     * 
199     * @param insn
200     *            the bytecode instruction to be interpreted.
201     * @param value
202     *            the argument of the instruction to be interpreted.
203     * @param expected
204     *            the expected return type of the analyzed method.
205     * @throws AnalyzerException
206     *             if an error occured during the interpretation.
207     */
208    public abstract void returnOperation(AbstractInsnNode insn, V value,
209                                         V expected) throws AnalyzerException;
210
211    /**
212     * Merges two values. The merge operation must return a value that
213     * represents both values (for instance, if the two values are two types,
214     * the merged value must be a common super type of the two types. If the two
215     * values are integer intervals, the merged value must be an interval that
216     * contains the previous ones. Likewise for other types of values).
217     * 
218     * @param v
219     *            a value.
220     * @param w
221     *            another value.
222     * @return the merged value. If the merged value is equal to <tt>v</tt>,
223     *         this method <i>must</i> return <tt>v</tt>.
224     */
225    public abstract V merge(V v, V w);
226}