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