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: InstructionFactory.html 992795 2016-07-14 11:53:52Z britter $
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}