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 
  85     public BasicInterpreter() {
  86         super(ASM4);
  87     }
  88 
  89     protected BasicInterpreter(final int api) {
  90         super(api);
  91     }
  92 
  93     @Override
  94     public BasicValue newValue(final Type type) {
  95         if (type == null) {
  96             return BasicValue.UNINITIALIZED_VALUE;
  97         }
  98         switch (type.getSort()) {
  99             case Type.VOID:
 100                 return null;
 101             case Type.BOOLEAN:
 102             case Type.CHAR:
 103             case Type.BYTE:
 104             case Type.SHORT:
 105             case Type.INT:
 106                 return BasicValue.INT_VALUE;
 107             case Type.FLOAT:
 108                 return BasicValue.FLOAT_VALUE;
 109             case Type.LONG:
 110                 return BasicValue.LONG_VALUE;
 111             case Type.DOUBLE:
 112                 return BasicValue.DOUBLE_VALUE;
 113             case Type.ARRAY:
 114             case Type.OBJECT:
 115                 return BasicValue.REFERENCE_VALUE;
 116             default:
 117                 throw new Error("Internal error");
 118         }
 119     }
 120 
 121     @Override
 122     public BasicValue newOperation(final AbstractInsnNode insn)
 123             throws AnalyzerException
 124     {
 125         switch (insn.getOpcode()) {
 126             case ACONST_NULL:
 127                 return newValue(Type.getObjectType("null"));
 128             case ICONST_M1:
 129             case ICONST_0:
 130             case ICONST_1:
 131             case ICONST_2:
 132             case ICONST_3:
 133             case ICONST_4:
 134             case ICONST_5:
 135                 return BasicValue.INT_VALUE;
 136             case LCONST_0:
 137             case LCONST_1:
 138                 return BasicValue.LONG_VALUE;
 139             case FCONST_0:
 140             case FCONST_1:
 141             case FCONST_2:
 142                 return BasicValue.FLOAT_VALUE;
 143             case DCONST_0:
 144             case DCONST_1:
 145                 return BasicValue.DOUBLE_VALUE;
 146             case BIPUSH:
 147             case SIPUSH:
 148                 return BasicValue.INT_VALUE;
 149             case LDC:
 150                 Object cst = ((LdcInsnNode) insn).cst;
 151                 if (cst instanceof Integer) {
 152                     return BasicValue.INT_VALUE;
 153                 } else if (cst instanceof Float) {
 154                     return BasicValue.FLOAT_VALUE;
 155                 } else if (cst instanceof Long) {
 156                     return BasicValue.LONG_VALUE;
 157                 } else if (cst instanceof Double) {
 158                     return BasicValue.DOUBLE_VALUE;
 159                 } else if (cst instanceof String) {
 160                     return newValue(Type.getObjectType("java/lang/String"));
 161                 } else if (cst instanceof Type) {
 162                     int sort = ((Type) cst).getSort();
 163                     if (sort == Type.OBJECT || sort == Type.ARRAY) {
 164                         return newValue(Type.getObjectType("java/lang/Class"));
 165                     } else if (sort == Type.METHOD) {
 166                         return newValue(Type.getObjectType("java/lang/invoke/MethodType"));
 167                     } else {
 168                         throw new IllegalArgumentException("Illegal LDC constant " + cst);
 169                     }
 170                 } else if (cst instanceof Handle) {
 171                     return newValue(Type.getObjectType("java/lang/invoke/MethodHandle"));
 172                 } else {
 173                     throw new IllegalArgumentException("Illegal LDC constant " + cst);
 174                 }
 175             case JSR:
 176                 return BasicValue.RETURNADDRESS_VALUE;
 177             case GETSTATIC:
 178                 return newValue(Type.getType(((FieldInsnNode) insn).desc));
 179             case NEW:
 180                 return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
 181             default:
 182                 throw new Error("Internal error.");
 183         }
 184     }
 185 
 186     @Override
 187     public BasicValue copyOperation(final AbstractInsnNode insn, final BasicValue value)
 188             throws AnalyzerException
 189     {
 190         return value;
 191     }
 192 
 193     @Override
 194     public BasicValue unaryOperation(final AbstractInsnNode insn, final BasicValue value)
 195             throws AnalyzerException
 196     {
 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(
 284         final AbstractInsnNode insn,
 285         final BasicValue value1,
 286         final BasicValue value2) throws AnalyzerException
 287     {
 288         switch (insn.getOpcode()) {
 289             case IALOAD:
 290             case BALOAD:
 291             case CALOAD:
 292             case SALOAD:
 293             case IADD:
 294             case ISUB:
 295             case IMUL:
 296             case IDIV:
 297             case IREM:
 298             case ISHL:
 299             case ISHR:
 300             case IUSHR:
 301             case IAND:
 302             case IOR:
 303             case IXOR:
 304                 return BasicValue.INT_VALUE;
 305             case FALOAD:
 306             case FADD:
 307             case FSUB:
 308             case FMUL:
 309             case FDIV:
 310             case FREM:
 311                 return BasicValue.FLOAT_VALUE;
 312             case LALOAD:
 313             case LADD:
 314             case LSUB:
 315             case LMUL:
 316             case LDIV:
 317             case LREM:
 318             case LSHL:
 319             case LSHR:
 320             case LUSHR:
 321             case LAND:
 322             case LOR:
 323             case LXOR:
 324                 return BasicValue.LONG_VALUE;
 325             case DALOAD:
 326             case DADD:
 327             case DSUB:
 328             case DMUL:
 329             case DDIV:
 330             case DREM:
 331                 return BasicValue.DOUBLE_VALUE;
 332             case AALOAD:
 333                 return BasicValue.REFERENCE_VALUE;
 334             case LCMP:
 335             case FCMPL:
 336             case FCMPG:
 337             case DCMPL:
 338             case DCMPG:
 339                 return BasicValue.INT_VALUE;
 340             case IF_ICMPEQ:
 341             case IF_ICMPNE:
 342             case IF_ICMPLT:
 343             case IF_ICMPGE:
 344             case IF_ICMPGT:
 345             case IF_ICMPLE:
 346             case IF_ACMPEQ:
 347             case IF_ACMPNE:
 348             case PUTFIELD:
 349                 return null;
 350             default:
 351                 throw new Error("Internal error.");
 352         }
 353     }
 354 
 355     @Override
 356     public BasicValue ternaryOperation(
 357         final AbstractInsnNode insn,
 358         final BasicValue value1,
 359         final BasicValue value2,
 360         final BasicValue value3) throws AnalyzerException
 361     {
 362         return null;
 363     }
 364 
 365     @Override
 366     public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values)
 367             throws AnalyzerException
 368     {
 369         int opcode = insn.getOpcode();
 370         if (opcode == MULTIANEWARRAY) {
 371             return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
 372         } else if (opcode == INVOKEDYNAMIC){
 373             return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc));
 374         } else {
 375             return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
 376         }
 377     }
 378 
 379     @Override
 380     public void returnOperation(
 381         final AbstractInsnNode insn,
 382         final BasicValue value,
 383         final BasicValue expected) throws AnalyzerException
 384     {
 385     }
 386 
 387     @Override
 388     public BasicValue merge(final BasicValue v, final BasicValue w) {
 389         if (!v.equals(w)) {
 390             return BasicValue.UNINITIALIZED_VALUE;
 391         }
 392         return v;
 393     }
 394 }