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