View Javadoc

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