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