1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  */
18 package org.apache.bcel.generic;
19 
20 import org.apache.bcel.Const;
21 
22 /**
23  * Instances of this class may be used, e.g., to generate typed
24  * versions of instructions. Its main purpose is to be used as the
25  * byte code generating backend of a compiler. You can subclass it to
26  * add your own create methods.
27  * <p>
28  * Note: The static createXXX methods return singleton instances
29  * from the {@link InstructionConst} class.
30  *
31  * @version $Id$
32  * @see Const
33  * @see InstructionConst
34  */
35 public class InstructionFactory implements InstructionConstants {
36 
37     // N.N. These must agree with the order of Constants.T_CHAR through T_LONG
38     private static final String[] short_names = {
39             "C", "F", "D", "B", "S", "I", "L"
40     };
41 
42     /**
43      * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
44      */
45     @Deprecated
46     protected ClassGen cg;
47 
48     /**
49      * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
50      */
51     @Deprecated
52     protected ConstantPoolGen cp;
53 
54 
InstructionFactory(final ClassGen cg, final ConstantPoolGen cp)55     public InstructionFactory(final ClassGen cg, final ConstantPoolGen cp) {
56         this.cg = cg;
57         this.cp = cp;
58     }
59 
60 
61     /** Initialize with ClassGen object
62      */
InstructionFactory(final ClassGen cg)63     public InstructionFactory(final ClassGen cg) {
64         this(cg, cg.getConstantPool());
65     }
66 
67 
68     /** Initialize just with ConstantPoolGen object
69      */
InstructionFactory(final ConstantPoolGen cp)70     public InstructionFactory(final ConstantPoolGen cp) {
71         this(null, cp);
72     }
73 
74 
75     /** Create an invoke instruction. (Except for invokedynamic.)
76      *
77      * @param class_name name of the called class
78      * @param name name of the called method
79      * @param ret_type return type of method
80      * @param arg_types argument types of method
81      * @param kind how to invoke, i.e., INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL,
82      * or INVOKESPECIAL
83      * @see Const
84      */
createInvoke( final String class_name, final String name, final Type ret_type, final Type[] arg_types, final short kind )85     public InvokeInstruction createInvoke( final String class_name, final String name, final Type ret_type,
86             final Type[] arg_types, final short kind ) {
87         int index;
88         int nargs = 0;
89         final String signature = Type.getMethodSignature(ret_type, arg_types);
90         for (final Type arg_type : arg_types) {
91             nargs += arg_type.getSize();
92         }
93         if (kind == Const.INVOKEINTERFACE) {
94             index = cp.addInterfaceMethodref(class_name, name, signature);
95         } else {
96             index = cp.addMethodref(class_name, name, signature);
97         }
98         switch (kind) {
99             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      */
createPrintln( final String s )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      */
createConstant( final Object value )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 
MethodObject(final String c, final String n, final Type r, final Type[] a)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 
createInvoke( final MethodObject m, final short kind )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 
isString( final Type type )234     private static boolean isString( final Type type ) {
235         return (type instanceof ObjectType) &&
236               ((ObjectType) type).getClassName().equals("java.lang.String");
237     }
238 
239 
createAppend( final Type type )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      */
createFieldAccess( final String class_name, final String name, final Type type, final short kind )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      */
createThis()293     public static Instruction createThis() {
294         return new ALOAD(0);
295     }
296 
297 
298     /** Create typed return
299      */
createReturn( final Type type )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 
createBinaryIntOp( final char first, final String op )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 
createBinaryLongOp( final char first, final String op )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 
createBinaryFloatOp( final char op )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 
createBinaryDoubleOp( final char op )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      */
createBinaryOperation( final String op, final Type type )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      */
createPop( final int size )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      */
createDup( final int size )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      */
createDup_2( final int size )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      */
createDup_1( final int size )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      */
createStore( final Type type, final int index )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      */
createLoad( final Type type, final int index )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      */
createArrayLoad( final Type type )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      */
createArrayStore( final Type type )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      */
createCast( final Type src_type, final Type dest_type )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 
createGetField( final String class_name, final String name, final Type t )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 
createGetStatic( final String class_name, final String name, final Type t )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 
createPutField( final String class_name, final String name, final Type t )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 
createPutStatic( final String class_name, final String name, final Type t )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 
createCheckCast( final ReferenceType t )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 
createInstanceOf( final ReferenceType t )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 
createNew( final ObjectType t )651     public NEW createNew( final ObjectType t ) {
652         return new NEW(cp.addClass(t));
653     }
654 
655 
createNew( final String s )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      */
createNewArray( final Type t, final short dim )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      */
createNull( final Type type )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      */
createBranchInstruction( final short opcode, final InstructionHandle target )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 
setClassGen( final ClassGen c )762     public void setClassGen( final ClassGen c ) {
763         cg = c;
764     }
765 
766 
getClassGen()767     public ClassGen getClassGen() {
768         return cg;
769     }
770 
771 
setConstantPool( final ConstantPoolGen c )772     public void setConstantPool( final ConstantPoolGen c ) {
773         cp = c;
774     }
775 
776 
getConstantPool()777     public ConstantPoolGen getConstantPool() {
778         return cp;
779     }
780 }
781