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