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