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