Source code

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