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