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  */
  59 package jdk.internal.org.objectweb.asm.tree.analysis;
  60 
  61 import java.util.List;
  62 
  63 import jdk.internal.org.objectweb.asm.Handle;
  64 import jdk.internal.org.objectweb.asm.Opcodes;
  65 import jdk.internal.org.objectweb.asm.Type;
  66 import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
  67 import jdk.internal.org.objectweb.asm.tree.FieldInsnNode;
  68 import jdk.internal.org.objectweb.asm.tree.IntInsnNode;
  69 import jdk.internal.org.objectweb.asm.tree.InvokeDynamicInsnNode;
  70 import jdk.internal.org.objectweb.asm.tree.LdcInsnNode;
  71 import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
  72 import jdk.internal.org.objectweb.asm.tree.MultiANewArrayInsnNode;
  73 import 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  */
  81 public 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 }