1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.  Oracle designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Oracle in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25/*
26 * This file is available under and governed by the GNU General Public
27 * License version 2 only, as published by the Free Software Foundation.
28 * However, the following notice accompanied the original version of this
29 * file:
30 *
31 * ASM: a very small and fast Java bytecode manipulation framework
32 * Copyright (c) 2000-2011 INRIA, France Telecom
33 * All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 *    notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 *    notice, this list of conditions and the following disclaimer in the
42 *    documentation and/or other materials provided with the distribution.
43 * 3. Neither the name of the copyright holders nor the names of its
44 *    contributors may be used to endorse or promote products derived from
45 *    this software without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
57 * THE POSSIBILITY OF SUCH DAMAGE.
58 */
59package jdk.internal.org.objectweb.asm.tree.analysis;
60
61import java.util.List;
62
63import jdk.internal.org.objectweb.asm.Handle;
64import jdk.internal.org.objectweb.asm.Opcodes;
65import jdk.internal.org.objectweb.asm.Type;
66import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
67import jdk.internal.org.objectweb.asm.tree.FieldInsnNode;
68import jdk.internal.org.objectweb.asm.tree.IntInsnNode;
69import jdk.internal.org.objectweb.asm.tree.InvokeDynamicInsnNode;
70import jdk.internal.org.objectweb.asm.tree.LdcInsnNode;
71import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
72import jdk.internal.org.objectweb.asm.tree.MultiANewArrayInsnNode;
73import jdk.internal.org.objectweb.asm.tree.TypeInsnNode;
74
75/**
76 * An {@link Interpreter} for {@link BasicValue} values.
77 *
78 * @author Eric Bruneton
79 * @author Bing Ran
80 */
81public class BasicInterpreter extends Interpreter<BasicValue> implements
82        Opcodes {
83
84    public BasicInterpreter() {
85        super(ASM5);
86    }
87
88    protected BasicInterpreter(final int api) {
89        super(api);
90    }
91
92    @Override
93    public BasicValue newValue(final Type type) {
94        if (type == null) {
95            return BasicValue.UNINITIALIZED_VALUE;
96        }
97        switch (type.getSort()) {
98        case Type.VOID:
99            return null;
100        case Type.BOOLEAN:
101        case Type.CHAR:
102        case Type.BYTE:
103        case Type.SHORT:
104        case Type.INT:
105            return BasicValue.INT_VALUE;
106        case Type.FLOAT:
107            return BasicValue.FLOAT_VALUE;
108        case Type.LONG:
109            return BasicValue.LONG_VALUE;
110        case Type.DOUBLE:
111            return BasicValue.DOUBLE_VALUE;
112        case Type.ARRAY:
113        case Type.OBJECT:
114            return BasicValue.REFERENCE_VALUE;
115        default:
116            throw new Error("Internal error");
117        }
118    }
119
120    @Override
121    public BasicValue newOperation(final AbstractInsnNode insn)
122            throws AnalyzerException {
123        switch (insn.getOpcode()) {
124        case ACONST_NULL:
125            return newValue(Type.getObjectType("null"));
126        case ICONST_M1:
127        case ICONST_0:
128        case ICONST_1:
129        case ICONST_2:
130        case ICONST_3:
131        case ICONST_4:
132        case ICONST_5:
133            return BasicValue.INT_VALUE;
134        case LCONST_0:
135        case LCONST_1:
136            return BasicValue.LONG_VALUE;
137        case FCONST_0:
138        case FCONST_1:
139        case FCONST_2:
140            return BasicValue.FLOAT_VALUE;
141        case DCONST_0:
142        case DCONST_1:
143            return BasicValue.DOUBLE_VALUE;
144        case BIPUSH:
145        case SIPUSH:
146            return BasicValue.INT_VALUE;
147        case LDC:
148            Object cst = ((LdcInsnNode) insn).cst;
149            if (cst instanceof Integer) {
150                return BasicValue.INT_VALUE;
151            } else if (cst instanceof Float) {
152                return BasicValue.FLOAT_VALUE;
153            } else if (cst instanceof Long) {
154                return BasicValue.LONG_VALUE;
155            } else if (cst instanceof Double) {
156                return BasicValue.DOUBLE_VALUE;
157            } else if (cst instanceof String) {
158                return newValue(Type.getObjectType("java/lang/String"));
159            } else if (cst instanceof Type) {
160                int sort = ((Type) cst).getSort();
161                if (sort == Type.OBJECT || sort == Type.ARRAY) {
162                    return newValue(Type.getObjectType("java/lang/Class"));
163                } else if (sort == Type.METHOD) {
164                    return newValue(Type
165                            .getObjectType("java/lang/invoke/MethodType"));
166                } else {
167                    throw new IllegalArgumentException("Illegal LDC constant "
168                            + cst);
169                }
170            } else if (cst instanceof Handle) {
171                return newValue(Type
172                        .getObjectType("java/lang/invoke/MethodHandle"));
173            } else {
174                throw new IllegalArgumentException("Illegal LDC constant "
175                        + cst);
176            }
177        case JSR:
178            return BasicValue.RETURNADDRESS_VALUE;
179        case GETSTATIC:
180            return newValue(Type.getType(((FieldInsnNode) insn).desc));
181        case NEW:
182            return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
183        default:
184            throw new Error("Internal error.");
185        }
186    }
187
188    @Override
189    public BasicValue copyOperation(final AbstractInsnNode insn,
190            final BasicValue value) throws AnalyzerException {
191        return value;
192    }
193
194    @Override
195    public BasicValue unaryOperation(final AbstractInsnNode insn,
196            final BasicValue value) throws AnalyzerException {
197        switch (insn.getOpcode()) {
198        case INEG:
199        case IINC:
200        case L2I:
201        case F2I:
202        case D2I:
203        case I2B:
204        case I2C:
205        case I2S:
206            return BasicValue.INT_VALUE;
207        case FNEG:
208        case I2F:
209        case L2F:
210        case D2F:
211            return BasicValue.FLOAT_VALUE;
212        case LNEG:
213        case I2L:
214        case F2L:
215        case D2L:
216            return BasicValue.LONG_VALUE;
217        case DNEG:
218        case I2D:
219        case L2D:
220        case F2D:
221            return BasicValue.DOUBLE_VALUE;
222        case IFEQ:
223        case IFNE:
224        case IFLT:
225        case IFGE:
226        case IFGT:
227        case IFLE:
228        case TABLESWITCH:
229        case LOOKUPSWITCH:
230        case IRETURN:
231        case LRETURN:
232        case FRETURN:
233        case DRETURN:
234        case ARETURN:
235        case PUTSTATIC:
236            return null;
237        case GETFIELD:
238            return newValue(Type.getType(((FieldInsnNode) insn).desc));
239        case NEWARRAY:
240            switch (((IntInsnNode) insn).operand) {
241            case T_BOOLEAN:
242                return newValue(Type.getType("[Z"));
243            case T_CHAR:
244                return newValue(Type.getType("[C"));
245            case T_BYTE:
246                return newValue(Type.getType("[B"));
247            case T_SHORT:
248                return newValue(Type.getType("[S"));
249            case T_INT:
250                return newValue(Type.getType("[I"));
251            case T_FLOAT:
252                return newValue(Type.getType("[F"));
253            case T_DOUBLE:
254                return newValue(Type.getType("[D"));
255            case T_LONG:
256                return newValue(Type.getType("[J"));
257            default:
258                throw new AnalyzerException(insn, "Invalid array type");
259            }
260        case ANEWARRAY:
261            String desc = ((TypeInsnNode) insn).desc;
262            return newValue(Type.getType("[" + Type.getObjectType(desc)));
263        case ARRAYLENGTH:
264            return BasicValue.INT_VALUE;
265        case ATHROW:
266            return null;
267        case CHECKCAST:
268            desc = ((TypeInsnNode) insn).desc;
269            return newValue(Type.getObjectType(desc));
270        case INSTANCEOF:
271            return BasicValue.INT_VALUE;
272        case MONITORENTER:
273        case MONITOREXIT:
274        case IFNULL:
275        case IFNONNULL:
276            return null;
277        default:
278            throw new Error("Internal error.");
279        }
280    }
281
282    @Override
283    public BasicValue binaryOperation(final AbstractInsnNode insn,
284            final BasicValue value1, final BasicValue value2)
285            throws AnalyzerException {
286        switch (insn.getOpcode()) {
287        case IALOAD:
288        case BALOAD:
289        case CALOAD:
290        case SALOAD:
291        case IADD:
292        case ISUB:
293        case IMUL:
294        case IDIV:
295        case IREM:
296        case ISHL:
297        case ISHR:
298        case IUSHR:
299        case IAND:
300        case IOR:
301        case IXOR:
302            return BasicValue.INT_VALUE;
303        case FALOAD:
304        case FADD:
305        case FSUB:
306        case FMUL:
307        case FDIV:
308        case FREM:
309            return BasicValue.FLOAT_VALUE;
310        case LALOAD:
311        case LADD:
312        case LSUB:
313        case LMUL:
314        case LDIV:
315        case LREM:
316        case LSHL:
317        case LSHR:
318        case LUSHR:
319        case LAND:
320        case LOR:
321        case LXOR:
322            return BasicValue.LONG_VALUE;
323        case DALOAD:
324        case DADD:
325        case DSUB:
326        case DMUL:
327        case DDIV:
328        case DREM:
329            return BasicValue.DOUBLE_VALUE;
330        case AALOAD:
331            return BasicValue.REFERENCE_VALUE;
332        case LCMP:
333        case FCMPL:
334        case FCMPG:
335        case DCMPL:
336        case DCMPG:
337            return BasicValue.INT_VALUE;
338        case IF_ICMPEQ:
339        case IF_ICMPNE:
340        case IF_ICMPLT:
341        case IF_ICMPGE:
342        case IF_ICMPGT:
343        case IF_ICMPLE:
344        case IF_ACMPEQ:
345        case IF_ACMPNE:
346        case PUTFIELD:
347            return null;
348        default:
349            throw new Error("Internal error.");
350        }
351    }
352
353    @Override
354    public BasicValue ternaryOperation(final AbstractInsnNode insn,
355            final BasicValue value1, final BasicValue value2,
356            final BasicValue value3) throws AnalyzerException {
357        return null;
358    }
359
360    @Override
361    public BasicValue naryOperation(final AbstractInsnNode insn,
362            final List<? extends BasicValue> values) throws AnalyzerException {
363        int opcode = insn.getOpcode();
364        if (opcode == MULTIANEWARRAY) {
365            return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
366        } else if (opcode == INVOKEDYNAMIC) {
367            return newValue(Type
368                    .getReturnType(((InvokeDynamicInsnNode) insn).desc));
369        } else {
370            return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
371        }
372    }
373
374    @Override
375    public void returnOperation(final AbstractInsnNode insn,
376            final BasicValue value, final BasicValue expected)
377            throws AnalyzerException {
378    }
379
380    @Override
381    public BasicValue merge(final BasicValue v, final BasicValue w) {
382        if (!v.equals(w)) {
383            return BasicValue.UNINITIALIZED_VALUE;
384        }
385        return v;
386    }
387}
388