1 package com.sun.org.apache.bcel.internal.generic; 2 3 56 import com.sun.org.apache.bcel.internal.Constants; 57 58 68 public class InstructionFactory implements InstructionConstants { 69 protected ClassGen cg; 70 protected ConstantPoolGen cp; 71 72 public InstructionFactory(ClassGen cg, ConstantPoolGen cp) { 73 this.cg = cg; 74 this.cp = cp; 75 } 76 77 79 public InstructionFactory(ClassGen cg) { 80 this(cg, cg.getConstantPool()); 81 } 82 83 85 public InstructionFactory(ConstantPoolGen cp) { 86 this(null, cp); 87 } 88 89 99 public InvokeInstruction createInvoke(String class_name, String name, Type ret_type, 100 Type[] arg_types, short kind) { 101 int index; 102 int nargs = 0; 103 String signature = Type.getMethodSignature(ret_type, arg_types); 104 105 for(int i=0; i < arg_types.length; i++) nargs += arg_types[i].getSize(); 107 108 if(kind == Constants.INVOKEINTERFACE) 109 index = cp.addInterfaceMethodref(class_name, name, signature); 110 else 111 index = cp.addMethodref(class_name, name, signature); 112 113 switch(kind) { 114 case Constants.INVOKESPECIAL: return new INVOKESPECIAL(index); 115 case Constants.INVOKEVIRTUAL: return new INVOKEVIRTUAL(index); 116 case Constants.INVOKESTATIC: return new INVOKESTATIC(index); 117 case Constants.INVOKEINTERFACE: return new INVOKEINTERFACE(index, nargs + 1); 118 default: 119 throw new RuntimeException ("Oops: Unknown invoke kind:" + kind); 120 } 121 } 122 123 127 public InstructionList createPrintln(String s) { 128 InstructionList il = new InstructionList(); 129 int out = cp.addFieldref("java.lang.System", "out", 130 "Ljava/io/PrintStream;"); 131 int println = cp.addMethodref("java.io.PrintStream", "println", 132 "(Ljava/lang/String;)V"); 133 134 il.append(new GETSTATIC(out)); 135 il.append(new PUSH(cp, s)); 136 il.append(new INVOKEVIRTUAL(println)); 137 138 return il; 139 } 140 141 private static class MethodObject { 142 Type[] arg_types; 143 Type result_type; 144 String [] arg_names; 145 String class_name; 146 String name; 147 int access; 148 149 MethodObject(String c, String n, Type r, Type[] a, int acc) { 150 class_name = c; 151 name = n; 152 result_type = r; 153 arg_types = a; 154 access = acc; 155 } 156 } 157 158 private InvokeInstruction createInvoke(MethodObject m, short kind) { 159 return createInvoke(m.class_name, m.name, m.result_type, m.arg_types, kind); 160 } 161 162 private static MethodObject[] append_mos = { 163 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, 164 new Type[] { Type.STRING }, Constants.ACC_PUBLIC), 165 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, 166 new Type[] { Type.OBJECT }, Constants.ACC_PUBLIC), 167 null, null, new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, 169 new Type[] { Type.BOOLEAN }, Constants.ACC_PUBLIC), 170 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, 171 new Type[] { Type.CHAR }, Constants.ACC_PUBLIC), 172 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, 173 new Type[] { Type.FLOAT }, Constants.ACC_PUBLIC), 174 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, 175 new Type[] { Type.DOUBLE }, Constants.ACC_PUBLIC), 176 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, 177 new Type[] { Type.INT }, Constants.ACC_PUBLIC), 178 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { Type.INT }, Constants.ACC_PUBLIC), 180 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { Type.INT }, Constants.ACC_PUBLIC), 182 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, 183 new Type[] { Type.LONG }, Constants.ACC_PUBLIC) 184 }; 185 186 private static final boolean isString(Type type) { 187 return ((type instanceof ObjectType) && 188 ((ObjectType)type).getClassName().equals("java.lang.String")); 189 } 190 191 public Instruction createAppend(Type type) { 192 byte t = type.getType(); 193 194 if(isString(type)) 195 return createInvoke(append_mos[0], Constants.INVOKEVIRTUAL); 196 197 switch(t) { 198 case Constants.T_BOOLEAN: 199 case Constants.T_CHAR: 200 case Constants.T_FLOAT: 201 case Constants.T_DOUBLE: 202 case Constants.T_BYTE: 203 case Constants.T_SHORT: 204 case Constants.T_INT: 205 case Constants.T_LONG 206 : return createInvoke(append_mos[t], Constants.INVOKEVIRTUAL); 207 case Constants.T_ARRAY: 208 case Constants.T_OBJECT: 209 return createInvoke(append_mos[1], Constants.INVOKEVIRTUAL); 210 default: 211 throw new RuntimeException ("Oops: No append for this type? " + type); 212 } 213 } 214 215 223 public FieldInstruction createFieldAccess(String class_name, String name, Type type, short kind) { 224 int index; 225 String signature = type.getSignature(); 226 227 index = cp.addFieldref(class_name, name, signature); 228 229 switch(kind) { 230 case Constants.GETFIELD: return new GETFIELD(index); 231 case Constants.PUTFIELD: return new PUTFIELD(index); 232 case Constants.GETSTATIC: return new GETSTATIC(index); 233 case Constants.PUTSTATIC: return new PUTSTATIC(index); 234 235 default: 236 throw new RuntimeException ("Oops: Unknown getfield kind:" + kind); 237 } 238 } 239 240 242 public static Instruction createThis() { 243 return new ALOAD(0); 244 } 245 246 248 public static ReturnInstruction createReturn(Type type) { 249 switch(type.getType()) { 250 case Constants.T_ARRAY: 251 case Constants.T_OBJECT: return ARETURN; 252 case Constants.T_INT: 253 case Constants.T_SHORT: 254 case Constants.T_BOOLEAN: 255 case Constants.T_CHAR: 256 case Constants.T_BYTE: return IRETURN; 257 case Constants.T_FLOAT: return FRETURN; 258 case Constants.T_DOUBLE: return DRETURN; 259 case Constants.T_LONG: return LRETURN; 260 case Constants.T_VOID: return RETURN; 261 262 default: 263 throw new RuntimeException ("Invalid type: " + type); 264 } 265 } 266 267 private static final ArithmeticInstruction createBinaryIntOp(char first, String op) { 268 switch(first) { 269 case '-' : return ISUB; 270 case '+' : return IADD; 271 case '%' : return IREM; 272 case '*' : return IMUL; 273 case '/' : return IDIV; 274 case '&' : return IAND; 275 case '|' : return IOR; 276 case '^' : return IXOR; 277 case '<' : return ISHL; 278 case '>' : return op.equals(">>>")? (ArithmeticInstruction)IUSHR : 279 (ArithmeticInstruction)ISHR; 280 default: throw new RuntimeException ("Invalid operand " + op); 281 } 282 } 283 284 private static final ArithmeticInstruction createBinaryLongOp(char first, String op) { 285 switch(first) { 286 case '-' : return LSUB; 287 case '+' : return LADD; 288 case '%' : return LREM; 289 case '*' : return LMUL; 290 case '/' : return LDIV; 291 case '&' : return LAND; 292 case '|' : return LOR; 293 case '^' : return LXOR; 294 case '<' : return LSHL; 295 case '>' : return op.equals(">>>")? (ArithmeticInstruction)LUSHR : 296 (ArithmeticInstruction)LSHR; 297 default: throw new RuntimeException ("Invalid operand " + op); 298 } 299 } 300 301 private static final ArithmeticInstruction createBinaryFloatOp(char op) { 302 switch(op) { 303 case '-' : return FSUB; 304 case '+' : return FADD; 305 case '*' : return FMUL; 306 case '/' : return FDIV; 307 default: throw new RuntimeException ("Invalid operand " + op); 308 } 309 } 310 311 private static final ArithmeticInstruction createBinaryDoubleOp(char op) { 312 switch(op) { 313 case '-' : return DSUB; 314 case '+' : return DADD; 315 case '*' : return DMUL; 316 case '/' : return DDIV; 317 default: throw new RuntimeException ("Invalid operand " + op); 318 } 319 } 320 321 326 public static ArithmeticInstruction createBinaryOperation(String op, Type type) { 327 char first = op.toCharArray()[0]; 328 329 switch(type.getType()) { 330 case Constants.T_BYTE: 331 case Constants.T_SHORT: 332 case Constants.T_INT: 333 case Constants.T_CHAR: return createBinaryIntOp(first, op); 334 case Constants.T_LONG: return createBinaryLongOp(first, op); 335 case Constants.T_FLOAT: return createBinaryFloatOp(first); 336 case Constants.T_DOUBLE: return createBinaryDoubleOp(first); 337 default: throw new RuntimeException ("Invalid type " + type); 338 } 339 } 340 341 344 public static StackInstruction createPop(int size) { 345 return (size == 2)? (StackInstruction)POP2 : 346 (StackInstruction)POP; 347 } 348 349 352 public static StackInstruction createDup(int size) { 353 return (size == 2)? (StackInstruction)DUP2 : 354 (StackInstruction)DUP; 355 } 356 357 360 public static StackInstruction createDup_2(int size) { 361 return (size == 2)? (StackInstruction)DUP2_X2 : 362 (StackInstruction)DUP_X2; 363 } 364 365 368 public static StackInstruction createDup_1(int size) { 369 return (size == 2)? (StackInstruction)DUP2_X1 : 370 (StackInstruction)DUP_X1; 371 } 372 373 376 public static LocalVariableInstruction createStore(Type type, int index) { 377 switch(type.getType()) { 378 case Constants.T_BOOLEAN: 379 case Constants.T_CHAR: 380 case Constants.T_BYTE: 381 case Constants.T_SHORT: 382 case Constants.T_INT: return new ISTORE(index); 383 case Constants.T_FLOAT: return new FSTORE(index); 384 case Constants.T_DOUBLE: return new DSTORE(index); 385 case Constants.T_LONG: return new LSTORE(index); 386 case Constants.T_ARRAY: 387 case Constants.T_OBJECT: return new ASTORE(index); 388 default: throw new RuntimeException ("Invalid type " + type); 389 } 390 } 391 392 395 public static LocalVariableInstruction createLoad(Type type, int index) { 396 switch(type.getType()) { 397 case Constants.T_BOOLEAN: 398 case Constants.T_CHAR: 399 case Constants.T_BYTE: 400 case Constants.T_SHORT: 401 case Constants.T_INT: return new ILOAD(index); 402 case Constants.T_FLOAT: return new FLOAD(index); 403 case Constants.T_DOUBLE: return new DLOAD(index); 404 case Constants.T_LONG: return new LLOAD(index); 405 case Constants.T_ARRAY: 406 case Constants.T_OBJECT: return new ALOAD(index); 407 default: throw new RuntimeException ("Invalid type " + type); 408 } 409 } 410 411 414 public static ArrayInstruction createArrayLoad(Type type) { 415 switch(type.getType()) { 416 case Constants.T_BOOLEAN: 417 case Constants.T_BYTE: return BALOAD; 418 case Constants.T_CHAR: return CALOAD; 419 case Constants.T_SHORT: return SALOAD; 420 case Constants.T_INT: return IALOAD; 421 case Constants.T_FLOAT: return FALOAD; 422 case Constants.T_DOUBLE: return DALOAD; 423 case Constants.T_LONG: return LALOAD; 424 case Constants.T_ARRAY: 425 case Constants.T_OBJECT: return AALOAD; 426 default: throw new RuntimeException ("Invalid type " + type); 427 } 428 } 429 430 433 public static ArrayInstruction createArrayStore(Type type) { 434 switch(type.getType()) { 435 case Constants.T_BOOLEAN: 436 case Constants.T_BYTE: return BASTORE; 437 case Constants.T_CHAR: return CASTORE; 438 case Constants.T_SHORT: return SASTORE; 439 case Constants.T_INT: return IASTORE; 440 case Constants.T_FLOAT: return FASTORE; 441 case Constants.T_DOUBLE: return DASTORE; 442 case Constants.T_LONG: return LASTORE; 443 case Constants.T_ARRAY: 444 case Constants.T_OBJECT: return AASTORE; 445 default: throw new RuntimeException ("Invalid type " + type); 446 } 447 } 448 449 450 453 public Instruction createCast(Type src_type, Type dest_type) { 454 if((src_type instanceof BasicType) && (dest_type instanceof BasicType)) { 455 byte dest = dest_type.getType(); 456 byte src = src_type.getType(); 457 458 if(dest == Constants.T_LONG && (src == Constants.T_CHAR || src == Constants.T_BYTE || 459 src == Constants.T_SHORT)) 460 src = Constants.T_INT; 461 462 String [] short_names = { "C", "F", "D", "B", "S", "I", "L" }; 463 464 String name = "com.sun.org.apache.bcel.internal.generic." + short_names[src - Constants.T_CHAR] + 465 "2" + short_names[dest - Constants.T_CHAR]; 466 467 Instruction i = null; 468 try { 469 i = (Instruction)java.lang.Class.forName(name).newInstance(); 470 } catch(Exception e) { 471 throw new RuntimeException ("Could not find instruction: " + name); 472 } 473 474 return i; 475 } else if((src_type instanceof ReferenceType) && (dest_type instanceof ReferenceType)) { 476 if(dest_type instanceof ArrayType) 477 return new CHECKCAST(cp.addArrayClass((ArrayType)dest_type)); 478 else 479 return new CHECKCAST(cp.addClass(((ObjectType)dest_type).getClassName())); 480 } 481 else 482 throw new RuntimeException ("Can not cast " + src_type + " to " + dest_type); 483 } 484 485 public GETFIELD createGetField(String class_name, String name, Type t) { 486 return new GETFIELD(cp.addFieldref(class_name, name, t.getSignature())); 487 } 488 489 public GETSTATIC createGetStatic(String class_name, String name, Type t) { 490 return new GETSTATIC(cp.addFieldref(class_name, name, t.getSignature())); 491 } 492 493 public PUTFIELD createPutField(String class_name, String name, Type t) { 494 return new PUTFIELD(cp.addFieldref(class_name, name, t.getSignature())); 495 } 496 497 public PUTSTATIC createPutStatic(String class_name, String name, Type t) { 498 return new PUTSTATIC(cp.addFieldref(class_name, name, t.getSignature())); 499 } 500 501 public CHECKCAST createCheckCast(ReferenceType t) { 502 if(t instanceof ArrayType) 503 return new CHECKCAST(cp.addArrayClass((ArrayType)t)); 504 else 505 return new CHECKCAST(cp.addClass((ObjectType)t)); 506 } 507 508 public NEW createNew(ObjectType t) { 509 return new NEW(cp.addClass(t)); 510 } 511 512 public NEW createNew(String s) { 513 return createNew(new ObjectType(s)); 514 } 515 516 518 public AllocationInstruction createNewArray(Type t, short dim) { 519 if(dim == 1) { 520 if(t instanceof ObjectType) 521 return new ANEWARRAY(cp.addClass((ObjectType)t)); 522 else if(t instanceof ArrayType) 523 return new ANEWARRAY(cp.addArrayClass((ArrayType)t)); 524 else 525 return new NEWARRAY(((BasicType)t).getType()); 526 } else { 527 ArrayType at; 528 529 if(t instanceof ArrayType) 530 at = (ArrayType)t; 531 else 532 at = new ArrayType(t, dim); 533 534 return new MULTIANEWARRAY(cp.addArrayClass(at), dim); 535 } 536 } 537 538 540 public static Instruction createNull(Type type) { 541 switch(type.getType()) { 542 case Constants.T_ARRAY: 543 case Constants.T_OBJECT: return ACONST_NULL; 544 case Constants.T_INT: 545 case Constants.T_SHORT: 546 case Constants.T_BOOLEAN: 547 case Constants.T_CHAR: 548 case Constants.T_BYTE: return ICONST_0; 549 case Constants.T_FLOAT: return FCONST_0; 550 case Constants.T_DOUBLE: return DCONST_0; 551 case Constants.T_LONG: return LCONST_0; 552 case Constants.T_VOID: return NOP; 553 554 default: 555 throw new RuntimeException ("Invalid type: " + type); 556 } 557 } 558 559 562 public static BranchInstruction createBranchInstruction(short opcode, InstructionHandle target) { 563 switch(opcode) { 564 case Constants.IFEQ: return new IFEQ(target); 565 case Constants.IFNE: return new IFNE(target); 566 case Constants.IFLT: return new IFLT(target); 567 case Constants.IFGE: return new IFGE(target); 568 case Constants.IFGT: return new IFGT(target); 569 case Constants.IFLE: return new IFLE(target); 570 case Constants.IF_ICMPEQ: return new IF_ICMPEQ(target); 571 case Constants.IF_ICMPNE: return new IF_ICMPNE(target); 572 case Constants.IF_ICMPLT: return new IF_ICMPLT(target); 573 case Constants.IF_ICMPGE: return new IF_ICMPGE(target); 574 case Constants.IF_ICMPGT: return new IF_ICMPGT(target); 575 case Constants.IF_ICMPLE: return new IF_ICMPLE(target); 576 case Constants.IF_ACMPEQ: return new IF_ACMPEQ(target); 577 case Constants.IF_ACMPNE: return new IF_ACMPNE(target); 578 case Constants.GOTO: return new GOTO(target); 579 case Constants.JSR: return new JSR(target); 580 case Constants.IFNULL: return new IFNULL(target); 581 case Constants.IFNONNULL: return new IFNONNULL(target); 582 case Constants.GOTO_W: return new GOTO_W(target); 583 case Constants.JSR_W: return new JSR_W(target); 584 default: 585 throw new RuntimeException ("Invalid opcode: " + opcode); 586 } 587 } 588 589 public void setClassGen(ClassGen c) { cg = c; } 590 public ClassGen getClassGen() { return cg; } 591 public void setConstantPool(ConstantPoolGen c) { cp = c; } 592 public ConstantPoolGen getConstantPool() { return cp; } 593 } 594 | Popular Tags |