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