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