1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 package com.sun.org.apache.bcel.internal.generic;
  21 
  22 import com.sun.org.apache.bcel.internal.Const;
  23 
  24 /**
  25  * Instances of this class may be used, e.g., to generate typed versions of
  26  * instructions. Its main purpose is to be used as the byte code generating
  27  * backend of a compiler. You can subclass it to add your own create methods.
  28  * <p>
  29  * Note: The static createXXX methods return singleton instances from the
  30  * {@link InstructionConst} class.
  31  *
  32  * @version $Id: InstructionFactory.java 1749603 2016-06-21 20:50:19Z ggregory $
  33  * @see Const
  34  * @see InstructionConst
  35  * @LastModified: Nov 2017
  36  */
  37 public class InstructionFactory {
  38 
  39     // N.N. These must agree with the order of Constants.T_CHAR through T_LONG
  40     private static final String[] short_names = {
  41         "C", "F", "D", "B", "S", "I", "L"
  42     };
  43 
  44     private ClassGen cg;
  45     private ConstantPoolGen cp;
  46 
  47     public InstructionFactory(final ClassGen cg, final ConstantPoolGen cp) {
  48         this.cg = cg;
  49         this.cp = cp;
  50     }
  51 
  52     /**
  53      * Initialize with ClassGen object
  54      */
  55     public InstructionFactory(final ClassGen cg) {
  56         this(cg, cg.getConstantPool());
  57     }
  58 
  59     /**
  60      * Initialize just with ConstantPoolGen object
  61      */
  62     public InstructionFactory(final ConstantPoolGen cp) {
  63         this(null, cp);
  64     }
  65 
  66     /**
  67      * Create an invoke instruction. (Except for invokedynamic.)
  68      *
  69      * @param class_name name of the called class
  70      * @param name name of the called method
  71      * @param ret_type return type of method
  72      * @param arg_types argument types of method
  73      * @param kind how to invoke, i.e., INVOKEINTERFACE, INVOKESTATIC,
  74      * INVOKEVIRTUAL, or INVOKESPECIAL
  75      * @see Const
  76      */
  77     public InvokeInstruction createInvoke(final String class_name, final String name, final Type ret_type,
  78             final Type[] arg_types, final short kind) {
  79         int index;
  80         int nargs = 0;
  81         final String signature = Type.getMethodSignature(ret_type, arg_types);
  82         for (final Type arg_type : arg_types) {
  83             nargs += arg_type.getSize();
  84         }
  85         if (kind == Const.INVOKEINTERFACE) {
  86             index = cp.addInterfaceMethodref(class_name, name, signature);
  87         } else {
  88             index = cp.addMethodref(class_name, name, signature);
  89         }
  90         switch (kind) {
  91             case Const.INVOKESPECIAL:
  92                 return new INVOKESPECIAL(index);
  93             case Const.INVOKEVIRTUAL:
  94                 return new INVOKEVIRTUAL(index);
  95             case Const.INVOKESTATIC:
  96                 return new INVOKESTATIC(index);
  97             case Const.INVOKEINTERFACE:
  98                 return new INVOKEINTERFACE(index, nargs + 1);
  99             case Const.INVOKEDYNAMIC:
 100                 return new INVOKEDYNAMIC(index);
 101             default:
 102                 throw new RuntimeException("Oops: Unknown invoke kind: " + kind);
 103         }
 104     }
 105 
 106     /**
 107      * Create an invokedynamic instruction.
 108      *
 109      * @param bootstrap_index index into the bootstrap_methods array
 110      * @param name name of the called method
 111      * @param ret_type return type of method
 112      * @param arg_types argument types of method
 113      * @see Constants
 114      */
 115     /*
 116      * createInvokeDynamic only needed if instrumention code wants to generate
 117      * a new invokedynamic instruction.  I don't think we need.  (markro)
 118      *
 119      public InvokeInstruction createInvokeDynamic( int bootstrap_index, String name, Type ret_type,
 120      Type[] arg_types) {
 121      int index;
 122      int nargs = 0;
 123      String signature = Type.getMethodSignature(ret_type, arg_types);
 124      for (int i = 0; i < arg_types.length; i++) {
 125      nargs += arg_types[i].getSize();
 126      }
 127      // UNDONE - needs to be added to ConstantPoolGen
 128      //index = cp.addInvokeDynamic(bootstrap_index, name, signature);
 129      index = 0;
 130      return new INVOKEDYNAMIC(index);
 131      }
 132      */
 133     /**
 134      * Create a call to the most popular System.out.println() method.
 135      *
 136      * @param s the string to print
 137      */
 138     public InstructionList createPrintln(final String s) {
 139         final InstructionList il = new InstructionList();
 140         final int out = cp.addFieldref("java.lang.System", "out", "Ljava/io/PrintStream;");
 141         final int println = cp.addMethodref("java.io.PrintStream", "println", "(Ljava/lang/String;)V");
 142         il.append(new GETSTATIC(out));
 143         il.append(new PUSH(cp, s));
 144         il.append(new INVOKEVIRTUAL(println));
 145         return il;
 146     }
 147 
 148     /**
 149      * Uses PUSH to push a constant value onto the stack.
 150      *
 151      * @param value must be of type Number, Boolean, Character or String
 152      */
 153     public Instruction createConstant(final Object value) {
 154         PUSH push;
 155         if (value instanceof Number) {
 156             push = new PUSH(cp, (Number) value);
 157         } else if (value instanceof String) {
 158             push = new PUSH(cp, (String) value);
 159         } else if (value instanceof Boolean) {
 160             push = new PUSH(cp, (Boolean) value);
 161         } else if (value instanceof Character) {
 162             push = new PUSH(cp, (Character) value);
 163         } else {
 164             throw new ClassGenException("Illegal type: " + value.getClass());
 165         }
 166         return push.getInstruction();
 167     }
 168 
 169     private static class MethodObject {
 170 
 171         final Type[] arg_types;
 172         final Type result_type;
 173         final String class_name;
 174         final String name;
 175 
 176         MethodObject(final String c, final String n, final Type r, final Type[] a) {
 177             class_name = c;
 178             name = n;
 179             result_type = r;
 180             arg_types = a;
 181         }
 182     }
 183 
 184     private InvokeInstruction createInvoke(final MethodObject m, final short kind) {
 185         return createInvoke(m.class_name, m.name, m.result_type, m.arg_types, kind);
 186     }
 187 
 188     private static final MethodObject[] append_mos = {
 189         new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[]{
 190             Type.STRING
 191         }),
 192         new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[]{
 193             Type.OBJECT
 194         }),
 195         null,
 196         null, // indices 2, 3
 197         new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[]{
 198             Type.BOOLEAN
 199         }),
 200         new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[]{
 201             Type.CHAR
 202         }),
 203         new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[]{
 204             Type.FLOAT
 205         }),
 206         new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[]{
 207             Type.DOUBLE
 208         }),
 209         new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[]{
 210             Type.INT
 211         }),
 212         new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(byte)
 213         new Type[]{
 214             Type.INT
 215         }),
 216         new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(short)
 217         new Type[]{
 218             Type.INT
 219         }),
 220         new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[]{
 221             Type.LONG
 222         })
 223     };
 224 
 225     private static boolean isString(final Type type) {
 226         return (type instanceof ObjectType)
 227                 && ((ObjectType) type).getClassName().equals("java.lang.String");
 228     }
 229 
 230     public Instruction createAppend(final Type type) {
 231         final byte t = type.getType();
 232         if (isString(type)) {
 233             return createInvoke(append_mos[0], Const.INVOKEVIRTUAL);
 234         }
 235         switch (t) {
 236             case Const.T_BOOLEAN:
 237             case Const.T_CHAR:
 238             case Const.T_FLOAT:
 239             case Const.T_DOUBLE:
 240             case Const.T_BYTE:
 241             case Const.T_SHORT:
 242             case Const.T_INT:
 243             case Const.T_LONG:
 244                 return createInvoke(append_mos[t], Const.INVOKEVIRTUAL);
 245             case Const.T_ARRAY:
 246             case Const.T_OBJECT:
 247                 return createInvoke(append_mos[1], Const.INVOKEVIRTUAL);
 248             default:
 249                 throw new RuntimeException("Oops: No append for this type? " + type);
 250         }
 251     }
 252 
 253     /**
 254      * Create a field instruction.
 255      *
 256      * @param class_name name of the accessed class
 257      * @param name name of the referenced field
 258      * @param type type of field
 259      * @param kind how to access, i.e., GETFIELD, PUTFIELD, GETSTATIC, PUTSTATIC
 260      * @see Const
 261      */
 262     public FieldInstruction createFieldAccess(final String class_name, final String name, final Type type, final short kind) {
 263         int index;
 264         final String signature = type.getSignature();
 265         index = cp.addFieldref(class_name, name, signature);
 266         switch (kind) {
 267             case Const.GETFIELD:
 268                 return new GETFIELD(index);
 269             case Const.PUTFIELD:
 270                 return new PUTFIELD(index);
 271             case Const.GETSTATIC:
 272                 return new GETSTATIC(index);
 273             case Const.PUTSTATIC:
 274                 return new PUTSTATIC(index);
 275             default:
 276                 throw new RuntimeException("Oops: Unknown getfield kind:" + kind);
 277         }
 278     }
 279 
 280     /**
 281      * Create reference to `this'
 282      */
 283     public static Instruction createThis() {
 284         return new ALOAD(0);
 285     }
 286 
 287     /**
 288      * Create typed return
 289      */
 290     public static ReturnInstruction createReturn(final Type type) {
 291         switch (type.getType()) {
 292             case Const.T_ARRAY:
 293             case Const.T_OBJECT:
 294                 return InstructionConst.ARETURN;
 295             case Const.T_INT:
 296             case Const.T_SHORT:
 297             case Const.T_BOOLEAN:
 298             case Const.T_CHAR:
 299             case Const.T_BYTE:
 300                 return InstructionConst.IRETURN;
 301             case Const.T_FLOAT:
 302                 return InstructionConst.FRETURN;
 303             case Const.T_DOUBLE:
 304                 return InstructionConst.DRETURN;
 305             case Const.T_LONG:
 306                 return InstructionConst.LRETURN;
 307             case Const.T_VOID:
 308                 return InstructionConst.RETURN;
 309             default:
 310                 throw new RuntimeException("Invalid type: " + type);
 311         }
 312     }
 313 
 314     private static ArithmeticInstruction createBinaryIntOp(final char first, final String op) {
 315         switch (first) {
 316             case '-':
 317                 return InstructionConst.ISUB;
 318             case '+':
 319                 return InstructionConst.IADD;
 320             case '%':
 321                 return InstructionConst.IREM;
 322             case '*':
 323                 return InstructionConst.IMUL;
 324             case '/':
 325                 return InstructionConst.IDIV;
 326             case '&':
 327                 return InstructionConst.IAND;
 328             case '|':
 329                 return InstructionConst.IOR;
 330             case '^':
 331                 return InstructionConst.IXOR;
 332             case '<':
 333                 return InstructionConst.ISHL;
 334             case '>':
 335                 return op.equals(">>>") ? InstructionConst.IUSHR : InstructionConst.ISHR;
 336             default:
 337                 throw new RuntimeException("Invalid operand " + op);
 338         }
 339     }
 340 
 341     private static ArithmeticInstruction createBinaryLongOp(final char first, final String op) {
 342         switch (first) {
 343             case '-':
 344                 return InstructionConst.LSUB;
 345             case '+':
 346                 return InstructionConst.LADD;
 347             case '%':
 348                 return InstructionConst.LREM;
 349             case '*':
 350                 return InstructionConst.LMUL;
 351             case '/':
 352                 return InstructionConst.LDIV;
 353             case '&':
 354                 return InstructionConst.LAND;
 355             case '|':
 356                 return InstructionConst.LOR;
 357             case '^':
 358                 return InstructionConst.LXOR;
 359             case '<':
 360                 return InstructionConst.LSHL;
 361             case '>':
 362                 return op.equals(">>>") ? InstructionConst.LUSHR : InstructionConst.LSHR;
 363             default:
 364                 throw new RuntimeException("Invalid operand " + op);
 365         }
 366     }
 367 
 368     private static ArithmeticInstruction createBinaryFloatOp(final char op) {
 369         switch (op) {
 370             case '-':
 371                 return InstructionConst.FSUB;
 372             case '+':
 373                 return InstructionConst.FADD;
 374             case '*':
 375                 return InstructionConst.FMUL;
 376             case '/':
 377                 return InstructionConst.FDIV;
 378             case '%':
 379                 return InstructionConst.FREM;
 380             default:
 381                 throw new RuntimeException("Invalid operand " + op);
 382         }
 383     }
 384 
 385     private static ArithmeticInstruction createBinaryDoubleOp(final char op) {
 386         switch (op) {
 387             case '-':
 388                 return InstructionConst.DSUB;
 389             case '+':
 390                 return InstructionConst.DADD;
 391             case '*':
 392                 return InstructionConst.DMUL;
 393             case '/':
 394                 return InstructionConst.DDIV;
 395             case '%':
 396                 return InstructionConst.DREM;
 397             default:
 398                 throw new RuntimeException("Invalid operand " + op);
 399         }
 400     }
 401 
 402     /**
 403      * Create binary operation for simple basic types, such as int and float.
 404      *
 405      * @param op operation, such as "+", "*", "&lt;&lt;", etc.
 406      */
 407     public static ArithmeticInstruction createBinaryOperation(final String op, final Type type) {
 408         final char first = op.charAt(0);
 409         switch (type.getType()) {
 410             case Const.T_BYTE:
 411             case Const.T_SHORT:
 412             case Const.T_INT:
 413             case Const.T_CHAR:
 414                 return createBinaryIntOp(first, op);
 415             case Const.T_LONG:
 416                 return createBinaryLongOp(first, op);
 417             case Const.T_FLOAT:
 418                 return createBinaryFloatOp(first);
 419             case Const.T_DOUBLE:
 420                 return createBinaryDoubleOp(first);
 421             default:
 422                 throw new RuntimeException("Invalid type " + type);
 423         }
 424     }
 425 
 426     /**
 427      * @param size size of operand, either 1 (int, e.g.) or 2 (double)
 428      */
 429     public static StackInstruction createPop(final int size) {
 430         return (size == 2) ? InstructionConst.POP2 : InstructionConst.POP;
 431     }
 432 
 433     /**
 434      * @param size size of operand, either 1 (int, e.g.) or 2 (double)
 435      */
 436     public static StackInstruction createDup(final int size) {
 437         return (size == 2) ? InstructionConst.DUP2 : InstructionConst.DUP;
 438     }
 439 
 440     /**
 441      * @param size size of operand, either 1 (int, e.g.) or 2 (double)
 442      */
 443     public static StackInstruction createDup_2(final int size) {
 444         return (size == 2) ? InstructionConst.DUP2_X2 : InstructionConst.DUP_X2;
 445     }
 446 
 447     /**
 448      * @param size size of operand, either 1 (int, e.g.) or 2 (double)
 449      */
 450     public static StackInstruction createDup_1(final int size) {
 451         return (size == 2) ? InstructionConst.DUP2_X1 : InstructionConst.DUP_X1;
 452     }
 453 
 454     /**
 455      * @param index index of local variable
 456      */
 457     public static LocalVariableInstruction createStore(final Type type, final int index) {
 458         switch (type.getType()) {
 459             case Const.T_BOOLEAN:
 460             case Const.T_CHAR:
 461             case Const.T_BYTE:
 462             case Const.T_SHORT:
 463             case Const.T_INT:
 464                 return new ISTORE(index);
 465             case Const.T_FLOAT:
 466                 return new FSTORE(index);
 467             case Const.T_DOUBLE:
 468                 return new DSTORE(index);
 469             case Const.T_LONG:
 470                 return new LSTORE(index);
 471             case Const.T_ARRAY:
 472             case Const.T_OBJECT:
 473                 return new ASTORE(index);
 474             default:
 475                 throw new RuntimeException("Invalid type " + type);
 476         }
 477     }
 478 
 479     /**
 480      * @param index index of local variable
 481      */
 482     public static LocalVariableInstruction createLoad(final Type type, final int index) {
 483         switch (type.getType()) {
 484             case Const.T_BOOLEAN:
 485             case Const.T_CHAR:
 486             case Const.T_BYTE:
 487             case Const.T_SHORT:
 488             case Const.T_INT:
 489                 return new ILOAD(index);
 490             case Const.T_FLOAT:
 491                 return new FLOAD(index);
 492             case Const.T_DOUBLE:
 493                 return new DLOAD(index);
 494             case Const.T_LONG:
 495                 return new LLOAD(index);
 496             case Const.T_ARRAY:
 497             case Const.T_OBJECT:
 498                 return new ALOAD(index);
 499             default:
 500                 throw new RuntimeException("Invalid type " + type);
 501         }
 502     }
 503 
 504     /**
 505      * @param type type of elements of array, i.e., array.getElementType()
 506      */
 507     public static ArrayInstruction createArrayLoad(final Type type) {
 508         switch (type.getType()) {
 509             case Const.T_BOOLEAN:
 510             case Const.T_BYTE:
 511                 return InstructionConst.BALOAD;
 512             case Const.T_CHAR:
 513                 return InstructionConst.CALOAD;
 514             case Const.T_SHORT:
 515                 return InstructionConst.SALOAD;
 516             case Const.T_INT:
 517                 return InstructionConst.IALOAD;
 518             case Const.T_FLOAT:
 519                 return InstructionConst.FALOAD;
 520             case Const.T_DOUBLE:
 521                 return InstructionConst.DALOAD;
 522             case Const.T_LONG:
 523                 return InstructionConst.LALOAD;
 524             case Const.T_ARRAY:
 525             case Const.T_OBJECT:
 526                 return InstructionConst.AALOAD;
 527             default:
 528                 throw new RuntimeException("Invalid type " + type);
 529         }
 530     }
 531 
 532     /**
 533      * @param type type of elements of array, i.e., array.getElementType()
 534      */
 535     public static ArrayInstruction createArrayStore(final Type type) {
 536         switch (type.getType()) {
 537             case Const.T_BOOLEAN:
 538             case Const.T_BYTE:
 539                 return InstructionConst.BASTORE;
 540             case Const.T_CHAR:
 541                 return InstructionConst.CASTORE;
 542             case Const.T_SHORT:
 543                 return InstructionConst.SASTORE;
 544             case Const.T_INT:
 545                 return InstructionConst.IASTORE;
 546             case Const.T_FLOAT:
 547                 return InstructionConst.FASTORE;
 548             case Const.T_DOUBLE:
 549                 return InstructionConst.DASTORE;
 550             case Const.T_LONG:
 551                 return InstructionConst.LASTORE;
 552             case Const.T_ARRAY:
 553             case Const.T_OBJECT:
 554                 return InstructionConst.AASTORE;
 555             default:
 556                 throw new RuntimeException("Invalid type " + type);
 557         }
 558     }
 559 
 560     /**
 561      * Create conversion operation for two stack operands, this may be an I2C,
 562      * instruction, e.g., if the operands are basic types and CHECKCAST if they
 563      * are reference types.
 564      */
 565     public Instruction createCast(final Type src_type, final Type dest_type) {
 566         if ((src_type instanceof BasicType) && (dest_type instanceof BasicType)) {
 567             final byte dest = dest_type.getType();
 568             byte src = src_type.getType();
 569             if (dest == Const.T_LONG
 570                     && (src == Const.T_CHAR || src == Const.T_BYTE || src == Const.T_SHORT)) {
 571                 src = Const.T_INT;
 572             }
 573             final String name = "com.sun.org.apache.bcel.internal.generic." + short_names[src - Const.T_CHAR] + "2"
 574                     + short_names[dest - Const.T_CHAR];
 575             Instruction i = null;
 576             try {
 577                 i = (Instruction) java.lang.Class.forName(name).getDeclaredConstructor().newInstance();
 578             } catch (final Exception e) {
 579                 throw new RuntimeException("Could not find instruction: " + name, e);
 580             }
 581             return i;
 582         } else if ((src_type instanceof ReferenceType) && (dest_type instanceof ReferenceType)) {
 583             if (dest_type instanceof ArrayType) {
 584                 return new CHECKCAST(cp.addArrayClass((ArrayType) dest_type));
 585             }
 586             return new CHECKCAST(cp.addClass(((ObjectType) dest_type).getClassName()));
 587         } else {
 588             throw new RuntimeException("Can not cast " + src_type + " to " + dest_type);
 589         }
 590     }
 591 
 592     public GETFIELD createGetField(final String class_name, final String name, final Type t) {
 593         return new GETFIELD(cp.addFieldref(class_name, name, t.getSignature()));
 594     }
 595 
 596     public GETSTATIC createGetStatic(final String class_name, final String name, final Type t) {
 597         return new GETSTATIC(cp.addFieldref(class_name, name, t.getSignature()));
 598     }
 599 
 600     public PUTFIELD createPutField(final String class_name, final String name, final Type t) {
 601         return new PUTFIELD(cp.addFieldref(class_name, name, t.getSignature()));
 602     }
 603 
 604     public PUTSTATIC createPutStatic(final String class_name, final String name, final Type t) {
 605         return new PUTSTATIC(cp.addFieldref(class_name, name, t.getSignature()));
 606     }
 607 
 608     public CHECKCAST createCheckCast(final ReferenceType t) {
 609         if (t instanceof ArrayType) {
 610             return new CHECKCAST(cp.addArrayClass((ArrayType) t));
 611         }
 612         return new CHECKCAST(cp.addClass((ObjectType) t));
 613     }
 614 
 615     public INSTANCEOF createInstanceOf(final ReferenceType t) {
 616         if (t instanceof ArrayType) {
 617             return new INSTANCEOF(cp.addArrayClass((ArrayType) t));
 618         }
 619         return new INSTANCEOF(cp.addClass((ObjectType) t));
 620     }
 621 
 622     public NEW createNew(final ObjectType t) {
 623         return new NEW(cp.addClass(t));
 624     }
 625 
 626     public NEW createNew(final String s) {
 627         return createNew(ObjectType.getInstance(s));
 628     }
 629 
 630     /**
 631      * Create new array of given size and type.
 632      *
 633      * @return an instruction that creates the corresponding array at runtime,
 634      * i.e. is an AllocationInstruction
 635      */
 636     public Instruction createNewArray(final Type t, final short dim) {
 637         if (dim == 1) {
 638             if (t instanceof ObjectType) {
 639                 return new ANEWARRAY(cp.addClass((ObjectType) t));
 640             } else if (t instanceof ArrayType) {
 641                 return new ANEWARRAY(cp.addArrayClass((ArrayType) t));
 642             } else {
 643                 return new NEWARRAY(t.getType());
 644             }
 645         }
 646         ArrayType at;
 647         if (t instanceof ArrayType) {
 648             at = (ArrayType) t;
 649         } else {
 650             at = new ArrayType(t, dim);
 651         }
 652         return new MULTIANEWARRAY(cp.addArrayClass(at), dim);
 653     }
 654 
 655     /**
 656      * Create "null" value for reference types, 0 for basic types like int
 657      */
 658     public static Instruction createNull(final Type type) {
 659         switch (type.getType()) {
 660             case Const.T_ARRAY:
 661             case Const.T_OBJECT:
 662                 return InstructionConst.ACONST_NULL;
 663             case Const.T_INT:
 664             case Const.T_SHORT:
 665             case Const.T_BOOLEAN:
 666             case Const.T_CHAR:
 667             case Const.T_BYTE:
 668                 return InstructionConst.ICONST_0;
 669             case Const.T_FLOAT:
 670                 return InstructionConst.FCONST_0;
 671             case Const.T_DOUBLE:
 672                 return InstructionConst.DCONST_0;
 673             case Const.T_LONG:
 674                 return InstructionConst.LCONST_0;
 675             case Const.T_VOID:
 676                 return InstructionConst.NOP;
 677             default:
 678                 throw new RuntimeException("Invalid type: " + type);
 679         }
 680     }
 681 
 682     /**
 683      * Create branch instruction by given opcode, except LOOKUPSWITCH and
 684      * TABLESWITCH. For those you should use the SWITCH compound instruction.
 685      */
 686     public static BranchInstruction createBranchInstruction(final short opcode, final InstructionHandle target) {
 687         switch (opcode) {
 688             case Const.IFEQ:
 689                 return new IFEQ(target);
 690             case Const.IFNE:
 691                 return new IFNE(target);
 692             case Const.IFLT:
 693                 return new IFLT(target);
 694             case Const.IFGE:
 695                 return new IFGE(target);
 696             case Const.IFGT:
 697                 return new IFGT(target);
 698             case Const.IFLE:
 699                 return new IFLE(target);
 700             case Const.IF_ICMPEQ:
 701                 return new IF_ICMPEQ(target);
 702             case Const.IF_ICMPNE:
 703                 return new IF_ICMPNE(target);
 704             case Const.IF_ICMPLT:
 705                 return new IF_ICMPLT(target);
 706             case Const.IF_ICMPGE:
 707                 return new IF_ICMPGE(target);
 708             case Const.IF_ICMPGT:
 709                 return new IF_ICMPGT(target);
 710             case Const.IF_ICMPLE:
 711                 return new IF_ICMPLE(target);
 712             case Const.IF_ACMPEQ:
 713                 return new IF_ACMPEQ(target);
 714             case Const.IF_ACMPNE:
 715                 return new IF_ACMPNE(target);
 716             case Const.GOTO:
 717                 return new GOTO(target);
 718             case Const.JSR:
 719                 return new JSR(target);
 720             case Const.IFNULL:
 721                 return new IFNULL(target);
 722             case Const.IFNONNULL:
 723                 return new IFNONNULL(target);
 724             case Const.GOTO_W:
 725                 return new GOTO_W(target);
 726             case Const.JSR_W:
 727                 return new JSR_W(target);
 728             default:
 729                 throw new RuntimeException("Invalid opcode: " + opcode);
 730         }
 731     }
 732 
 733     public void setClassGen(final ClassGen c) {
 734         cg = c;
 735     }
 736 
 737     public ClassGen getClassGen() {
 738         return cg;
 739     }
 740 
 741     public void setConstantPool(final ConstantPoolGen c) {
 742         cp = c;
 743     }
 744 
 745     public ConstantPoolGen getConstantPool() {
 746         return cp;
 747     }
 748 }