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