001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 */ 018package org.apache.bcel.generic; 019 020import org.apache.bcel.Const; 021 022/** 023 * Instances of this class may be used, e.g., to generate typed 024 * versions of instructions. Its main purpose is to be used as the 025 * byte code generating backend of a compiler. You can subclass it to 026 * add your own create methods. 027 * <p> 028 * Note: The static createXXX methods return singleton instances 029 * from the {@link InstructionConst} class. 030 * 031 * @see Const 032 * @see InstructionConst 033 */ 034public class InstructionFactory implements InstructionConstants { 035 036 // N.N. These must agree with the order of Constants.T_CHAR through T_LONG 037 private static final String[] short_names = { 038 "C", "F", "D", "B", "S", "I", "L" 039 }; 040 041 /** 042 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 043 */ 044 @Deprecated 045 protected ClassGen cg; 046 047 /** 048 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 049 */ 050 @Deprecated 051 protected ConstantPoolGen cp; 052 053 054 public InstructionFactory(final ClassGen cg, final ConstantPoolGen cp) { 055 this.cg = cg; 056 this.cp = cp; 057 } 058 059 060 /** Initialize with ClassGen object 061 */ 062 public InstructionFactory(final ClassGen cg) { 063 this(cg, cg.getConstantPool()); 064 } 065 066 067 /** Initialize just with ConstantPoolGen object 068 */ 069 public InstructionFactory(final ConstantPoolGen cp) { 070 this(null, cp); 071 } 072 073 074 /** Create an invoke instruction. (Except for invokedynamic.) 075 * 076 * @param class_name name of the called class 077 * @param name name of the called method 078 * @param ret_type return type of method 079 * @param arg_types argument types of method 080 * @param kind how to invoke, i.e., INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL, 081 * or INVOKESPECIAL 082 * @see Const 083 */ 084 public InvokeInstruction createInvoke( final String class_name, final String name, final Type ret_type, 085 final Type[] arg_types, final short kind ) { 086 return createInvoke(class_name, name, ret_type, arg_types, kind, kind == Const.INVOKEINTERFACE); 087 } 088 089 /** Create an invoke instruction. (Except for invokedynamic.) 090 * 091 * @param class_name name of the called class 092 * @param name name of the called method 093 * @param ret_type return type of method 094 * @param arg_types argument types of method 095 * @param kind how to invoke: INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL, or INVOKESPECIAL 096 * @param use_interface force use of InterfaceMethodref 097 * @return A new InvokeInstruction. 098 * @since 6.5.0 099 */ 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 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 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 "+", "*", "<<", 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 Type src_type, final Type dest_type ) { 608 if ((src_type instanceof 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 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}