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