View Javadoc
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   * @see Const
32   * @see InstructionConst
33   */
34  public class InstructionFactory implements InstructionConstants {
35  
36      // N.N. These must agree with the order of Constants.T_CHAR through T_LONG
37      private static final String[] short_names = {
38              "C", "F", "D", "B", "S", "I", "L"
39      };
40  
41      /**
42       * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
43       */
44      @Deprecated
45      protected ClassGen cg;
46  
47      /**
48       * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
49       */
50      @Deprecated
51      protected ConstantPoolGen cp;
52  
53  
54      public InstructionFactory(final ClassGen cg, final ConstantPoolGen cp) {
55          this.cg = cg;
56          this.cp = cp;
57      }
58  
59  
60      /** Initialize with ClassGen object
61       */
62      public InstructionFactory(final ClassGen cg) {
63          this(cg, cg.getConstantPool());
64      }
65  
66  
67      /** Initialize just with ConstantPoolGen object
68       */
69      public InstructionFactory(final ConstantPoolGen cp) {
70          this(null, cp);
71      }
72  
73  
74      /** Create an invoke instruction. (Except for invokedynamic.)
75       *
76       * @param class_name name of the called class
77       * @param name name of the called method
78       * @param ret_type return type of method
79       * @param arg_types argument types of method
80       * @param kind how to invoke, i.e., INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL,
81       * or INVOKESPECIAL
82       * @see Const
83       */
84      public InvokeInstruction createInvoke( final String class_name, final String name, final Type ret_type,
85              final Type[] arg_types, final short kind ) {
86          return createInvoke(class_name, name, ret_type, arg_types, kind, kind == Const.INVOKEINTERFACE);
87      }
88  
89      /** Create an invoke instruction. (Except for invokedynamic.)
90       *
91       * @param class_name name of the called class
92       * @param name name of the called method
93       * @param ret_type return type of method
94       * @param arg_types argument types of method
95       * @param kind how to invoke: INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL, or INVOKESPECIAL
96       * @param use_interface force use of InterfaceMethodref
97       * @return A new InvokeInstruction.
98       * @since 6.5.0
99       */
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 InstructionListonList.html#InstructionList">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 Typec/Type.html#Type">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 Typehtml#Type">Type src_type, final Type dest_type ) {
608         if ((src_type instanceof BasicType/generic/BasicType.html#BasicType">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 ReferenceTypeeric/ReferenceType.html#ReferenceType">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 }