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}