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