1 19 20 25 26 27 package soot.jimple; 28 import soot.options.*; 29 import soot.*; 30 import soot.jimple.internal.*; 31 import soot.toolkits.graph.*; 32 import soot.toolkits.scalar.*; 33 import soot.util.*; 34 import java.util.*; 35 import java.io.*; 36 import soot.grimp.*; 37 38 39 public class JasminClass extends AbstractJasminClass 40 { 41 void emit(String s, int stackChange) 42 { 43 modifyStackHeight(stackChange); 44 okayEmit(s); 45 } 46 47 void modifyStackHeight(int stackChange) 48 { 49 if(currentStackHeight > maxStackHeight) 50 maxStackHeight = currentStackHeight; 51 52 currentStackHeight += stackChange; 53 54 if(currentStackHeight < 0) 55 throw new RuntimeException ("Stack height is negative!"); 56 57 if(currentStackHeight > maxStackHeight) 58 maxStackHeight = currentStackHeight; 59 } 60 61 public JasminClass(SootClass sootClass) 62 { 63 super(sootClass); 64 } 65 66 protected void assignColorsToLocals(Body body) 67 { 68 super.assignColorsToLocals(body); 69 70 FastColorer.assignColorsToLocals(body, localToGroup, 72 localToColor, groupToColorCount); 73 74 if(Options.v().time()) 75 Timers.v().packTimer.end(); 76 77 } 78 79 80 protected void emitMethodBody(SootMethod method) { 82 if(Options.v().time()) 83 Timers.v().buildJasminTimer.end(); 84 85 86 Body activeBody = method.getActiveBody(); 87 88 if(!(activeBody instanceof StmtBody)) 89 throw new RuntimeException ("method: " + method.getName() + " has an invalid active body!"); 90 91 StmtBody body = (StmtBody) activeBody; 92 93 body.validate(); 94 95 if(body == null) 96 97 if(Options.v().time()) 98 Timers.v().buildJasminTimer.start(); 99 100 Chain units = body.getUnits(); 101 102 ExceptionalUnitGraph stmtGraph = null; 103 LocalDefs ld = null; 104 LocalUses lu = null; 105 106 107 109 if(Options.v().verbose()) 110 G.v().out.println("[" + body.getMethod().getName() + 111 "] Performing peephole optimizations..."); 112 113 boolean disablePeephole = true; 115 116 if (!disablePeephole) 117 { 118 stmtGraph = new ExceptionalUnitGraph(body); 119 ld = new SmartLocalDefs(stmtGraph, new SimpleLiveLocals(stmtGraph)); 120 lu = new SimpleLocalUses(stmtGraph, ld); 121 } 122 123 int stackLimitIndex = -1; 124 125 subroutineToReturnAddressSlot = new HashMap(10, 0.7f); 126 127 { 129 Iterator boxIt = body.getUnitBoxes(true).iterator(); 130 131 unitToLabel = new HashMap(units.size() * 2 + 1, 0.7f); 132 labelCount = 0; 133 134 while(boxIt.hasNext()) 135 { 136 { 138 StmtBox box = (StmtBox) boxIt.next(); 139 140 if(!unitToLabel.containsKey(box.getUnit())) 141 unitToLabel.put(box.getUnit(), "label" + labelCount++); 142 } 143 } 144 } 145 146 { 148 Iterator trapIt = body.getTraps().iterator(); 149 150 while(trapIt.hasNext()) 151 { 152 Trap trap = (Trap) trapIt.next(); 153 154 if(trap.getBeginUnit() != trap.getEndUnit()) 155 emit(".catch " + slashify(trap.getException().getName()) + " from " + 156 unitToLabel.get(trap.getBeginUnit()) + " to " + unitToLabel.get(trap.getEndUnit()) + 157 " using " + unitToLabel.get(trap.getHandlerUnit())); 158 } 159 } 160 161 { 163 int localCount = 0; 164 int[] paramSlots = new int[method.getParameterCount()]; 165 int thisSlot = 0; 166 Set assignedLocals = new HashSet(); 167 Map groupColorPairToSlot = new HashMap(body.getLocalCount() * 2 + 1, 0.7f); 168 169 localToSlot = new HashMap(body.getLocalCount() * 2 + 1, 0.7f); 170 171 assignColorsToLocals(body); 172 173 { 175 List paramTypes = method.getParameterTypes(); 176 177 if(!method.isStatic()) 178 { 179 thisSlot = 0; 180 localCount++; 181 } 182 183 for(int i = 0; i < paramTypes.size(); i++) 184 { 185 paramSlots[i] = localCount; 186 localCount += sizeOfType((Type) paramTypes.get(i)); 187 } 188 } 189 190 { 192 Iterator stmtIt = units.iterator(); 193 194 while(stmtIt.hasNext()) 195 { 196 Stmt s = (Stmt) stmtIt.next(); 197 198 if(s instanceof IdentityStmt && ((IdentityStmt) s).getLeftOp() instanceof Local) 199 { 200 Local l = (Local) ((IdentityStmt) s).getLeftOp(); 201 IdentityRef identity = (IdentityRef) ((IdentityStmt) s).getRightOp(); 202 203 int slot = 0; 204 205 if(identity instanceof ThisRef) 206 { 207 if(method.isStatic()) 208 throw new RuntimeException ("Attempting to use 'this' in static method"); 209 210 slot = thisSlot; 211 } 212 else if(identity instanceof ParameterRef) 213 slot = paramSlots[((ParameterRef) identity).getIndex()]; 214 else { 215 continue; 217 } 218 219 { 222 223 GroupIntPair pair = new GroupIntPair(localToGroup.get(l), 224 ((Integer ) localToColor.get(l)).intValue()); 225 226 groupColorPairToSlot.put(pair, new Integer (slot)); 227 } 228 229 localToSlot.put(l, new Integer (slot)); 230 assignedLocals.add(l); 231 232 } 233 } 234 } 235 236 { 238 Iterator localIt = body.getLocals().iterator(); 239 240 while(localIt.hasNext()) 241 { 242 Local local = (Local) localIt.next(); 243 244 if(!assignedLocals.contains(local)) 245 { 246 GroupIntPair pair = new GroupIntPair(localToGroup.get(local), 247 ((Integer ) localToColor.get(local)).intValue()); 248 249 int slot; 250 251 if(groupColorPairToSlot.containsKey(pair)) 252 { 253 256 slot = ((Integer ) groupColorPairToSlot.get(pair)).intValue(); 257 } 258 else { 259 slot = localCount; 260 localCount += sizeOfType(local.getType()); 261 262 groupColorPairToSlot.put(pair, new Integer (slot)); 263 } 264 265 localToSlot.put(local, new Integer (slot)); 266 assignedLocals.add(local); 267 } 268 } 269 270 if (!Modifier.isNative(method.getModifiers()) 271 && !Modifier.isAbstract(method.getModifiers())) 272 { 273 emit(" .limit stack ?"); 274 stackLimitIndex = code.size() - 1; 275 276 emit(" .limit locals " + localCount); 277 } 278 } 279 } 280 281 { 283 Iterator codeIt = units.iterator(); 284 285 isEmittingMethodCode = true; 286 maxStackHeight = 0; 287 isNextGotoAJsr = false; 288 289 while(codeIt.hasNext()) 290 { 291 Stmt s = (Stmt) codeIt.next(); 292 293 if(unitToLabel.containsKey(s)) 294 emit(unitToLabel.get(s) + ":"); 295 296 if(subroutineToReturnAddressSlot.containsKey(s)) 297 { 298 AssignStmt assignStmt = (AssignStmt) s; 299 300 modifyStackHeight(1); 302 int slot = ((Integer ) localToSlot.get(assignStmt.getLeftOp())).intValue(); 303 304 if(slot >= 0 && slot <= 3) 305 emit("astore_" + slot, -1); 306 else 307 emit("astore " + slot, -1); 308 309 311 } 312 313 316 boolean contFlag = false; 317 do 319 { 320 if (disablePeephole) 321 break; 322 323 if (!(s instanceof AssignStmt)) 324 break; 325 326 AssignStmt stmt = (AssignStmt)s; 327 328 if (!codeIt.hasNext()) 330 break; 331 332 Stmt ns = (Stmt)(stmtGraph.getSuccsOf(stmt).get(0)); 333 if (!(ns instanceof AssignStmt)) 334 break; 335 AssignStmt nextStmt = (AssignStmt)ns; 336 337 List l = stmtGraph.getSuccsOf(nextStmt); 338 if (l.size() != 1) 339 break; 340 341 Stmt nextNextStmt = (Stmt)(l.get(0)); 342 343 Value lvalue = stmt.getLeftOp(); 344 final Value rvalue = stmt.getRightOp(); 345 346 if (!(lvalue instanceof Local)) 347 break; 348 349 355 358 if (!(lvalue instanceof Local) 359 || !nextStmt.getLeftOp().equivTo(rvalue) 360 || !(nextStmt.getRightOp() instanceof AddExpr)) 361 break; 362 363 { 365 Iterator boxIt = nextNextStmt.getUseBoxes().iterator(); 366 367 boolean foundExactlyOnce = false; 368 369 while(boxIt.hasNext()) 370 { 371 ValueBox box = (ValueBox) boxIt.next(); 372 373 if(box.getValue() == lvalue) 374 { 375 if(!foundExactlyOnce) 376 foundExactlyOnce = true; 377 else 378 { 379 foundExactlyOnce = false; 380 break; 381 } 382 } 383 } 384 385 if(!foundExactlyOnce) 386 break; 387 } 388 389 { 394 Iterator boxIt = nextNextStmt.getDefBoxes().iterator(); 395 396 boolean found = false; 397 398 while(boxIt.hasNext()) 399 { 400 ValueBox box = (ValueBox) boxIt.next(); 401 402 if(box.getValue().equivTo(rvalue)) 403 { 404 found = true; 405 } 406 } 407 408 if(found) 409 break; 410 } 411 412 AddExpr addexp = (AddExpr)nextStmt.getRightOp(); 413 if (!addexp.getOp1().equivTo(lvalue) && !addexp.getOp1().equivTo(rvalue)) 414 break; 415 416 Value added = addexp.getOp2(); 417 418 if (!(added instanceof IntConstant) 419 || ((IntConstant)(added)).value != 1) 420 break; 421 422 423 424 425 426 if (addexp.getOp1().equivTo(lvalue)) 427 { 428 if (lu.getUsesOf(stmt).size() != 2 || 429 ld.getDefsOfAt((Local)lvalue, nextStmt).size() != 1 || 430 ld.getDefsOfAt((Local)lvalue, nextNextStmt).size() !=1) 431 break; 432 plusPlusState = 0; 433 } 434 else 435 { 436 if (lu.getUsesOf(stmt).size() != 1 || 437 ld.getDefsOfAt((Local)lvalue, nextNextStmt).size() !=1) 438 break; 439 plusPlusState = 10; 440 } 441 442 443 444 448 449 450 if (lvalue.getType() != IntType.v()) 451 break; 452 453 454 455 456 457 458 459 currentStackHeight = 0; 460 461 462 plusPlusValue = rvalue; 463 plusPlusHolder = (Local)lvalue; 464 plusPlusIncrementer = nextStmt; 465 466 467 emitStmt(nextNextStmt); 468 469 470 if (plusPlusHolder != null) 471 { emitStmt(stmt); emitStmt(nextStmt); } 472 473 if(currentStackHeight != 0) 474 throw new RuntimeException ("Stack has height " + currentStackHeight + " after execution of stmt: " + s); 475 contFlag = true; 476 codeIt.next(); codeIt.next(); 477 } 478 while(false); 479 if (contFlag) 480 continue; 481 482 484 { 486 currentStackHeight = 0; 487 emitStmt(s); 488 489 if(currentStackHeight != 0) 490 throw new RuntimeException ("Stack has height " + currentStackHeight + " after execution of stmt: " + s); 491 } 492 } 493 494 isEmittingMethodCode = false; 495 496 if (!Modifier.isNative(method.getModifiers()) 497 && !Modifier.isAbstract(method.getModifiers())) 498 code.set(stackLimitIndex, " .limit stack " + maxStackHeight); 499 } 500 } 501 502 503 void emitAssignStmt(AssignStmt stmt) 504 { 505 final Value lvalue = stmt.getLeftOp(); 506 final Value rvalue = stmt.getRightOp(); 507 508 if(lvalue instanceof Local && (rvalue instanceof AddExpr || rvalue instanceof SubExpr)) 510 { 511 Local l = (Local) lvalue; 512 BinopExpr expr = (BinopExpr) rvalue; 513 Value op1 = expr.getOp1(); 514 Value op2 = expr.getOp2(); 515 516 if (lvalue == plusPlusHolder) 518 { 519 emitValue(lvalue); 520 plusPlusHolder = null; 521 plusPlusState = 0; 522 } 523 525 if(l.getType().equals(IntType.v())) 526 { 527 boolean isValidCase = false; 528 int x = 0; 529 530 if(op1 == l && op2 instanceof IntConstant) 531 { 532 x = ((IntConstant) op2).value; 533 isValidCase = true; 534 } 535 else if(expr instanceof AddExpr && 536 op2 == l && op1 instanceof IntConstant) 537 { 538 540 x = ((IntConstant) op1).value; 541 isValidCase = true; 542 } 543 544 if(isValidCase && x >= Short.MIN_VALUE && x <= Short.MAX_VALUE) 545 { 546 emit("iinc " + ((Integer ) localToSlot.get(l)).intValue() + " " + 547 ((expr instanceof AddExpr) ? x : -x), 0); 548 return; 549 } 550 } 551 } 552 553 lvalue.apply(new AbstractJimpleValueSwitch() 554 { 555 public void caseArrayRef(ArrayRef v) 556 { 557 emitValue(v.getBase()); 558 emitValue(v.getIndex()); 559 emitValue(rvalue); 560 561 v.getType().apply(new TypeSwitch() 562 { 563 public void caseArrayType(ArrayType t) 564 { 565 emit("aastore", -3); 566 } 567 568 public void caseDoubleType(DoubleType t) 569 { 570 emit("dastore", -4); 571 } 572 573 public void caseFloatType(FloatType t) 574 { 575 emit("fastore", -3); 576 } 577 578 public void caseIntType(IntType t) 579 { 580 emit("iastore", -3); 581 } 582 583 public void caseLongType(LongType t) 584 { 585 emit("lastore", -4); 586 } 587 588 public void caseRefType(RefType t) 589 { 590 emit("aastore", -3); 591 } 592 593 public void caseByteType(ByteType t) 594 { 595 emit("bastore", -3); 596 } 597 598 public void caseBooleanType(BooleanType t) 599 { 600 emit("bastore", -3); 601 } 602 603 public void caseCharType(CharType t) 604 { 605 emit("castore", -3); 606 } 607 608 public void caseShortType(ShortType t) 609 { 610 emit("sastore", -3); 611 } 612 613 public void defaultCase(Type t) 614 { 615 throw new RuntimeException ("Invalid type: " + t); 616 } 617 }); 618 } 619 620 public void defaultCase(Value v) 621 { 622 throw new RuntimeException ("Can't store in value " + v); 623 } 624 625 public void caseInstanceFieldRef(InstanceFieldRef v) 626 { 627 emitValue(v.getBase()); 628 emitValue(rvalue); 629 630 emit("putfield " + slashify(v.getFieldRef().declaringClass().getName()) + "/" + 631 v.getFieldRef().name() + " " + jasminDescriptorOf(v.getFieldRef().type()), 632 -1 + -sizeOfType(v.getFieldRef().type())); 633 } 634 635 public void caseLocal(final Local v) 636 { 637 final int slot = ((Integer ) localToSlot.get(v)).intValue(); 638 639 v.getType().apply(new TypeSwitch() 640 { 641 private void handleIntegerType(IntegerType t) 642 { 643 emitValue(rvalue); 644 645 if(slot >= 0 && slot <= 3) 646 emit("istore_" + slot, -1); 647 else 648 emit("istore " + slot, -1); 649 } 650 651 public void caseBooleanType(BooleanType t) 652 { 653 handleIntegerType(t); 654 } 655 656 public void caseByteType(ByteType t) 657 { 658 handleIntegerType(t); 659 } 660 661 public void caseShortType(ShortType t) 662 { 663 handleIntegerType(t); 664 } 665 666 public void caseCharType(CharType t) 667 { 668 handleIntegerType(t); 669 } 670 671 public void caseIntType(IntType t) 672 { 673 handleIntegerType(t); 674 } 675 676 public void caseArrayType(ArrayType t) 677 { 678 emitValue(rvalue); 679 680 if(slot >= 0 && slot <= 3) 681 emit("astore_" + slot, -1); 682 else 683 emit("astore " + slot, -1); 684 } 685 686 public void caseDoubleType(DoubleType t) 687 { 688 emitValue(rvalue); 689 690 if(slot >= 0 && slot <= 3) 691 emit("dstore_" + slot, -2); 692 else 693 emit("dstore " + slot, -2); 694 } 695 696 public void caseFloatType(FloatType t) 697 { 698 emitValue(rvalue); 699 700 if(slot >= 0 && slot <= 3) 701 emit("fstore_" + slot, -1); 702 else 703 emit("fstore " + slot, -1); 704 } 705 706 public void caseLongType(LongType t) 707 { 708 emitValue(rvalue); 709 710 if(slot >= 0 && slot <= 3) 711 emit("lstore_" + slot, -2); 712 else 713 emit("lstore " + slot, -2); 714 } 715 716 public void caseRefType(RefType t) 717 { 718 emitValue(rvalue); 719 720 if(slot >= 0 && slot <= 3) 721 emit("astore_" + slot, -1); 722 else 723 emit("astore " + slot, -1); 724 } 725 726 public void caseStmtAddressType(StmtAddressType t) 727 { 728 isNextGotoAJsr = true; 729 returnAddressSlot = slot; 730 731 738 739 } 740 741 public void caseNullType(NullType t) 742 { 743 emitValue(rvalue); 744 745 if(slot >= 0 && slot <= 3) 746 emit("astore_" + slot, -1); 747 else 748 emit("astore " + slot, -1); 749 } 750 751 public void defaultCase(Type t) 752 { 753 throw new RuntimeException ("Invalid local type: " + t); 754 } 755 }); 756 } 757 758 public void caseStaticFieldRef(StaticFieldRef v) 759 { 760 SootFieldRef field = v.getFieldRef(); 761 762 emitValue(rvalue); 763 emit("putstatic " + slashify(field.declaringClass().getName()) + "/" + 764 field.name() + " " + jasminDescriptorOf(field.type()), 765 -sizeOfType(v.getFieldRef().type())); 766 } 767 }); 768 } 769 770 void emitIfStmt(IfStmt stmt) 771 { 772 Value cond = stmt.getCondition(); 773 774 final Value op1 = ((BinopExpr) cond).getOp1(); 775 final Value op2 = ((BinopExpr) cond).getOp2(); 776 final String label = (String ) unitToLabel.get(stmt.getTarget()); 777 778 if(op2 instanceof NullConstant || op1 instanceof NullConstant) 780 { 781 if(op2 instanceof NullConstant) 782 emitValue(op1); 783 else 784 emitValue(op2); 785 786 if(cond instanceof EqExpr) 787 emit("ifnull " + label, -1); 788 else if(cond instanceof NeExpr) 789 emit("ifnonnull "+ label, -1); 790 else 791 throw new RuntimeException ("invalid condition"); 792 793 return; 794 } 795 796 if(op2 instanceof IntConstant && ((IntConstant) op2).value == 0) 798 { 799 emitValue(op1); 800 801 cond.apply(new AbstractJimpleValueSwitch() 802 { 803 public void caseEqExpr(EqExpr expr) 804 { 805 emit("ifeq " + label, -1); 806 } 807 808 public void caseNeExpr(NeExpr expr) 809 { 810 emit("ifne " + label, -1); 811 } 812 813 public void caseLtExpr(LtExpr expr) 814 { 815 emit("iflt " + label, -1); 816 } 817 818 public void caseLeExpr(LeExpr expr) 819 { 820 emit("ifle " + label, -1); 821 } 822 823 public void caseGtExpr(GtExpr expr) 824 { 825 emit("ifgt " + label, -1); 826 } 827 828 public void caseGeExpr(GeExpr expr) 829 { 830 emit("ifge " + label, -1); 831 } 832 833 public void defaultCase(Value v) 834 { 835 throw new RuntimeException ("invalid condition " + v); 836 } 837 }); 838 839 return; 840 } 841 842 if(op1 instanceof IntConstant && ((IntConstant) op1).value == 0) 844 { 845 emitValue(op2); 846 847 cond.apply(new AbstractJimpleValueSwitch() 848 { 849 public void caseEqExpr(EqExpr expr) 850 { 851 emit("ifeq " + label, -1); 852 } 853 854 public void caseNeExpr(NeExpr expr) 855 { 856 emit("ifne " + label, -1); 857 } 858 859 public void caseLtExpr(LtExpr expr) 860 { 861 emit("ifgt " + label, -1); 862 } 863 864 public void caseLeExpr(LeExpr expr) 865 { 866 emit("ifge " + label, -1); 867 } 868 869 public void caseGtExpr(GtExpr expr) 870 { 871 emit("iflt " + label, -1); 872 } 873 874 public void caseGeExpr(GeExpr expr) 875 { 876 emit("ifle " + label, -1); 877 } 878 879 public void defaultCase(Value v) 880 { 881 throw new RuntimeException ("invalid condition " + v); 882 } 883 }); 884 885 return; 886 } 887 888 emitValue(op1); 889 emitValue(op2); 890 891 cond.apply(new AbstractJimpleValueSwitch() 892 { 893 public void caseEqExpr(EqExpr expr) 894 { 895 op1.getType().apply(new TypeSwitch() 896 { 897 public void caseIntType(IntType t) 898 { 899 emit("if_icmpeq " + label, -2); 900 } 901 902 public void caseBooleanType(BooleanType t) 903 { 904 emit("if_icmpeq " + label, -2); 905 } 906 907 public void caseShortType(ShortType t) 908 { 909 emit("if_icmpeq " + label, -2); 910 } 911 912 public void caseCharType(CharType t) 913 { 914 emit("if_icmpeq " + label, -2); 915 } 916 917 public void caseByteType(ByteType t) 918 { 919 emit("if_icmpeq " + label, -2); 920 } 921 922 public void caseDoubleType(DoubleType t) 923 { 924 emit("dcmpg", -3); 925 emit("ifeq " + label, -1); 926 } 927 928 public void caseLongType(LongType t) 929 { 930 emit("lcmp", -3); 931 emit("ifeq " + label, -1); 932 } 933 934 public void caseFloatType(FloatType t) 935 { 936 emit("fcmpg", -1); 937 emit("ifeq " + label, -1); 938 } 939 940 public void caseArrayType(ArrayType t) 941 { 942 emit("if_acmpeq " + label, -2); 943 } 944 945 public void caseRefType(RefType t) 946 { 947 emit("if_acmpeq " + label, -2); 948 } 949 950 public void caseNullType(NullType t) 951 { 952 emit("if_acmpeq " + label, -2); 953 } 954 955 public void defaultCase(Type t) 956 { 957 throw new RuntimeException ("invalid type"); 958 } 959 }); 960 } 961 962 public void caseNeExpr(NeExpr expr) 963 { 964 op1.getType().apply(new TypeSwitch() 965 { 966 public void caseIntType(IntType t) 967 { 968 emit("if_icmpne " + label, -2); 969 } 970 971 public void caseBooleanType(BooleanType t) 972 { 973 emit("if_icmpne " + label, -2); 974 } 975 976 public void caseShortType(ShortType t) 977 { 978 emit("if_icmpne " + label, -2); 979 } 980 981 public void caseCharType(CharType t) 982 { 983 emit("if_icmpne " + label, -2); 984 } 985 986 public void caseByteType(ByteType t) 987 { 988 emit("if_icmpne " + label, -2); 989 } 990 991 public void caseDoubleType(DoubleType t) 992 { 993 emit("dcmpg", -3); 994 emit("ifne " + label, -1); 995 } 996 997 public void caseLongType(LongType t) 998 { 999 emit("lcmp", -3); 1000 emit("ifne " + label, -1); 1001 } 1002 1003 public void caseFloatType(FloatType t) 1004 { 1005 emit("fcmpg", -1); 1006 emit("ifne " + label, -1); 1007 } 1008 1009 public void caseArrayType(ArrayType t) 1010 { 1011 emit("if_acmpne " + label, -2); 1012 } 1013 1014 public void caseRefType(RefType t) 1015 { 1016 emit("if_acmpne " + label, -2); 1017 } 1018 1019 public void caseNullType(NullType t) 1020 { 1021 emit("if_acmpne " + label, -2); 1022 } 1023 1024 public void defaultCase(Type t) 1025 { 1026 throw new RuntimeException ("invalid type for NeExpr: " + t); 1027 } 1028 }); 1029 } 1030 1031 public void caseLtExpr(LtExpr expr) 1032 { 1033 op1.getType().apply(new TypeSwitch() 1034 { 1035 public void caseIntType(IntType t) 1036 { 1037 emit("if_icmplt " + label, -2); 1038 } 1039 1040 public void caseBooleanType(BooleanType t) 1041 { 1042 emit("if_icmplt " + label, -2); 1043 } 1044 1045 public void caseShortType(ShortType t) 1046 { 1047 emit("if_icmplt " + label, -2); 1048 } 1049 1050 public void caseCharType(CharType t) 1051 { 1052 emit("if_icmplt " + label, -2); 1053 } 1054 1055 public void caseByteType(ByteType t) 1056 { 1057 emit("if_icmplt " + label, -2); 1058 } 1059 1060 1061 public void caseDoubleType(DoubleType t) 1062 { 1063 emit("dcmpg", -3); 1064 emit("iflt " + label, -1); 1065 } 1066 1067 public void caseLongType(LongType t) 1068 { 1069 emit("lcmp", -3); 1070 emit("iflt " + label, -1); 1071 } 1072 1073 public void caseFloatType(FloatType t) 1074 { 1075 emit("fcmpg", -1); 1076 emit("iflt " + label, -1); 1077 } 1078 1079 public void defaultCase(Type t) 1080 { 1081 throw new RuntimeException ("invalid type"); 1082 } 1083 }); 1084 } 1085 1086 public void caseLeExpr(LeExpr expr) 1087 { 1088 op1.getType().apply(new TypeSwitch() 1089 { 1090 public void caseIntType(IntType t) 1091 { 1092 emit("if_icmple " + label, -2); 1093 } 1094 1095 public void caseBooleanType(BooleanType t) 1096 { 1097 emit("if_icmple " + label, -2); 1098 } 1099 1100 public void caseShortType(ShortType t) 1101 { 1102 emit("if_icmple " + label, -2); 1103 } 1104 1105 public void caseCharType(CharType t) 1106 { 1107 emit("if_icmple " + label, -2); 1108 } 1109 1110 public void caseByteType(ByteType t) 1111 { 1112 emit("if_icmple " + label, -2); 1113 } 1114 1115 public void caseDoubleType(DoubleType t) 1116 { 1117 emit("dcmpg", -3); 1118 emit("ifle " + label, -1); 1119 } 1120 1121 public void caseLongType(LongType t) 1122 { 1123 emit("lcmp", -3); 1124 emit("ifle " + label, -1); 1125 } 1126 1127 public void caseFloatType(FloatType t) 1128 { 1129 emit("fcmpg", -1); 1130 emit("ifle " + label, -1); 1131 } 1132 1133 public void defaultCase(Type t) 1134 { 1135 throw new RuntimeException ("invalid type"); 1136 } 1137 }); 1138 } 1139 1140 public void caseGtExpr(GtExpr expr) 1141 { 1142 op1.getType().apply(new TypeSwitch() 1143 { 1144 public void caseIntType(IntType t) 1145 { 1146 emit("if_icmpgt " + label, -2); 1147 } 1148 1149 public void caseBooleanType(BooleanType t) 1150 { 1151 emit("if_icmpgt " + label, -2); 1152 } 1153 1154 public void caseShortType(ShortType t) 1155 { 1156 emit("if_icmpgt " + label, -2); 1157 } 1158 1159 public void caseCharType(CharType t) 1160 { 1161 emit("if_icmpgt " + label, -2); 1162 } 1163 1164 public void caseByteType(ByteType t) 1165 { 1166 emit("if_icmpgt " + label, -2); 1167 } 1168 1169 public void caseDoubleType(DoubleType t) 1170 { 1171 emit("dcmpg", -3); 1172 emit("ifgt " + label, -1); 1173 } 1174 1175 public void caseLongType(LongType t) 1176 { 1177 emit("lcmp", -3); 1178 emit("ifgt " + label, -1); 1179 } 1180 1181 public void caseFloatType(FloatType t) 1182 { 1183 emit("fcmpg", -1); 1184 emit("ifgt " + label, -1); 1185 } 1186 1187 public void defaultCase(Type t) 1188 { 1189 throw new RuntimeException ("invalid type"); 1190 } 1191 }); 1192 } 1193 1194 public void caseGeExpr(GeExpr expr) 1195 { 1196 op1.getType().apply(new TypeSwitch() 1197 { 1198 public void caseIntType(IntType t) 1199 { 1200 emit("if_icmpge " + label, -2); 1201 } 1202 1203 public void caseBooleanType(BooleanType t) 1204 { 1205 emit("if_icmpge " + label, -2); 1206 } 1207 1208 public void caseShortType(ShortType t) 1209 { 1210 emit("if_icmpge " + label, -2); 1211 } 1212 1213 public void caseCharType(CharType t) 1214 { 1215 emit("if_icmpge " + label, -2); 1216 } 1217 1218 public void caseByteType(ByteType t) 1219 { 1220 emit("if_icmpge " + label, -2); 1221 } 1222 1223 public void caseDoubleType(DoubleType t) 1224 { 1225 emit("dcmpg", -3); 1226 emit("ifge " + label, -1); 1227 } 1228 1229 public void caseLongType(LongType t) 1230 { 1231 emit("lcmp", -3); 1232 emit("ifge " + label, -1); 1233 } 1234 1235 public void caseFloatType(FloatType t) 1236 { 1237 emit("fcmpg", -1); 1238 emit("ifge " + label, -1); 1239 } 1240 1241 public void defaultCase(Type t) 1242 { 1243 throw new RuntimeException ("invalid type"); 1244 } 1245 }); 1246 } 1247 1248 public void defaultCase(Value v) 1249 { 1250 throw new RuntimeException ("invalid condition " + v); 1251 } 1252 }); 1253 } 1254 1255 void emitStmt(Stmt stmt) 1256 { 1257 stmt.apply(new AbstractStmtSwitch() 1258 { 1259 public void caseAssignStmt(AssignStmt s) 1260 { 1261 emitAssignStmt(s); 1262 } 1263 1264 public void caseIdentityStmt(IdentityStmt s) 1265 { 1266 if(s.getRightOp() instanceof CaughtExceptionRef && 1267 s.getLeftOp() instanceof Local) 1268 { 1269 int slot = ((Integer ) localToSlot.get(s.getLeftOp())).intValue(); 1270 1271 modifyStackHeight(1); 1274 if(slot >= 0 && slot <= 3) 1275 emit("astore_" + slot, -1); 1276 else 1277 emit("astore " + slot, -1); 1278 } 1279 } 1280 1281 public void caseBreakpointStmt(BreakpointStmt s) 1282 { 1283 emit("breakpoint", 0); 1284 } 1285 1286 public void caseInvokeStmt(InvokeStmt s) 1287 { 1288 emitValue(s.getInvokeExpr()); 1289 1290 Type returnType = ((InvokeExpr) s.getInvokeExpr()).getMethodRef().returnType(); 1291 1292 if(!returnType.equals(VoidType.v())) 1293 { 1294 1296 if(sizeOfType(returnType) == 1) 1297 emit("pop", -1); 1298 else 1299 emit("pop2", -2); 1300 } 1301 } 1302 1303 public void defaultCase(Stmt s) 1304 { 1305 throw new RuntimeException ("invalid stmt: " + s); 1306 } 1307 1308 public void caseEnterMonitorStmt(EnterMonitorStmt s) 1309 { 1310 emitValue(s.getOp()); 1311 emit("monitorenter", -1); 1312 } 1313 1314 public void caseExitMonitorStmt(ExitMonitorStmt s) 1315 { 1316 emitValue(s.getOp()); 1317 emit("monitorexit", -1); 1318 } 1319 1320 public void caseGotoStmt(GotoStmt s) 1321 { 1322 if(isNextGotoAJsr) 1323 { 1324 emit("jsr " + unitToLabel.get(s.getTarget())); 1325 isNextGotoAJsr = false; 1326 1327 subroutineToReturnAddressSlot.put(s.getTarget(), new Integer (returnAddressSlot)); 1328 } 1329 else 1330 emit("goto " + unitToLabel.get(s.getTarget())); 1331 } 1332 1333 1334 public void caseIfStmt(IfStmt s) 1335 { 1336 emitIfStmt(s); 1337 } 1338 1339 public void caseLookupSwitchStmt(LookupSwitchStmt s) 1340 { 1341 emitValue(s.getKey()); 1342 emit("lookupswitch", -1); 1343 1344 List lookupValues = s.getLookupValues(); 1345 List targets = s.getTargets(); 1346 1347 for(int i = 0; i < lookupValues.size(); i++) 1348 emit(" " + lookupValues.get(i) + " : " + unitToLabel.get(targets.get(i))); 1349 1350 emit(" default : " + unitToLabel.get(s.getDefaultTarget())); 1351 } 1352 1353 public void caseNopStmt(NopStmt s) 1354 { 1355 emit("nop", 0); 1356 } 1357 1358 public void caseRetStmt(RetStmt s) 1359 { 1360 emit("ret " + localToSlot.get(s.getStmtAddress()), 0); 1361 } 1362 1363 public void caseReturnStmt(ReturnStmt s) 1364 { 1365 emitValue(s.getOp()); 1366 1367 Value returnValue = s.getOp(); 1368 1369 returnValue.getType().apply(new TypeSwitch() 1370 { 1371 public void defaultCase(Type t) 1372 { 1373 throw new RuntimeException ("invalid return type " + t.toString()); 1374 } 1375 1376 public void caseDoubleType(DoubleType t) 1377 { 1378 emit("dreturn", -2); 1379 } 1380 1381 public void caseFloatType(FloatType t) 1382 { 1383 emit("freturn", -1); 1384 } 1385 1386 public void caseIntType(IntType t) 1387 { 1388 emit("ireturn", -1); 1389 } 1390 1391 public void caseByteType(ByteType t) 1392 { 1393 emit("ireturn", -1); 1394 } 1395 1396 public void caseShortType(ShortType t) 1397 { 1398 emit("ireturn", -1); 1399 } 1400 1401 public void caseCharType(CharType t) 1402 { 1403 emit("ireturn", -1); 1404 } 1405 1406 public void caseBooleanType(BooleanType t) 1407 { 1408 emit("ireturn", -1); 1409 } 1410 1411 public void caseLongType(LongType t) 1412 { 1413 emit("lreturn", -2); 1414 } 1415 1416 public void caseArrayType(ArrayType t) 1417 { 1418 emit("areturn", -1); 1419 } 1420 1421 public void caseRefType(RefType t) 1422 { 1423 emit("areturn", -1); 1424 } 1425 1426 public void caseNullType(NullType t) 1427 { 1428 emit("areturn", -1); 1429 } 1430 1431 }); 1432 } 1433 1434 public void caseReturnVoidStmt(ReturnVoidStmt s) 1435 { 1436 emit("return", 0); 1437 } 1438 1439 public void caseTableSwitchStmt(TableSwitchStmt s) 1440 { 1441 emitValue(s.getKey()); 1442 emit("tableswitch " + s.getLowIndex() + " ; high = " + s.getHighIndex(), -1); 1443 1444 List targets = s.getTargets(); 1445 1446 for(int i = 0; i < targets.size(); i++) 1447 emit(" " + unitToLabel.get(targets.get(i))); 1448 1449 emit("default : " + unitToLabel.get(s.getDefaultTarget())); 1450 } 1451 1452 public void caseThrowStmt(ThrowStmt s) 1453 { 1454 emitValue(s.getOp()); 1455 emit("athrow", -1); 1456 } 1457 }); 1458 } 1459 1460 1461 1462 1463 Value plusPlusValue; 1464 Local plusPlusHolder; 1465 int plusPlusState; 1466 int plusPlusPlace; 1467 int plusPlusHeight; 1468 Stmt plusPlusIncrementer; 1469 1470 1471 void emitLocal(Local v) 1472 { 1473 final int slot = ((Integer ) localToSlot.get(v)).intValue(); 1474 final Local vAlias = v; 1475 1476 v.getType().apply(new TypeSwitch() 1477 { 1478 public void caseArrayType(ArrayType t) 1479 { 1480 if(slot >= 0 && slot <= 3) 1481 emit("aload_" + slot, 1); 1482 else 1483 emit("aload " + slot, 1); 1484 } 1485 1486 public void defaultCase(Type t) 1487 { 1488 throw new RuntimeException ("invalid local type to load" + t); 1489 } 1490 1491 public void caseDoubleType(DoubleType t) 1492 { 1493 if(slot >= 0 && slot <= 3) 1494 emit("dload_" + slot, 2); 1495 else 1496 emit("dload " + slot, 2); 1497 } 1498 1499 public void caseFloatType(FloatType t) 1500 { 1501 if(slot >= 0 && slot <= 3) 1502 emit("fload_" + slot, 1); 1503 else 1504 emit("fload " + slot, 1); 1505 } 1506 1507 public void caseBooleanType(BooleanType t) 1509 { 1510 handleIntegerType(t); 1511 } 1512 1513 public void caseByteType(ByteType t) 1514 { 1515 handleIntegerType(t); 1516 } 1517 1518 public void caseShortType(ShortType t) 1519 { 1520 handleIntegerType(t); 1521 } 1522 1523 public void caseCharType(CharType t) 1524 { 1525 handleIntegerType(t); 1526 } 1527 1528 public void caseIntType(IntType t) 1529 { 1530 handleIntegerType(t); 1531 } 1532 1533 public void handleIntegerType(IntegerType t) 1535 { 1536 if (vAlias.equals(plusPlusHolder)) 1537 { 1538 switch(plusPlusState) 1539 { 1540 case 0: 1541 { 1542 1545 1549 1551 plusPlusState = 1; 1552 1553 emitStmt(plusPlusIncrementer); 1554 int diff = plusPlusHeight - currentStackHeight + 1; 1555 if (diff > 0) 1556 code.set(plusPlusPlace, " dup_x"+diff); 1557 plusPlusHolder = null; 1558 1559 return; 1561 } 1562 case 1: 1563 plusPlusHeight = currentStackHeight; 1564 plusPlusHolder = null; 1565 1566 emitValue(plusPlusValue); 1567 1568 plusPlusPlace = code.size(); 1569 emit("dup", 1); 1570 1571 return; 1572 case 10: 1573 { 1574 plusPlusState = 11; 1576 1577 1581 plusPlusHolder = (Local)plusPlusValue; 1582 emitStmt(plusPlusIncrementer); 1583 int diff = plusPlusHeight - currentStackHeight + 1; 1584 if (diff > 0 && plusPlusState == 11) 1585 code.set(plusPlusPlace, " dup_x"+diff); 1586 plusPlusHolder = null; 1587 1588 return; 1590 } 1591 case 11: 1592 plusPlusHeight = currentStackHeight; 1593 plusPlusHolder = null; 1594 1595 emitValue(plusPlusValue); 1596 if (plusPlusState != 11) 1597 emit("dup", 1); 1598 1599 plusPlusPlace = code.size(); 1600 1601 return; 1602 } 1603 } 1604 if(slot >= 0 && slot <= 3) 1605 emit("iload_" + slot, 1); 1606 else 1607 emit("iload " + slot, 1); 1608 } 1609 1611 public void caseLongType(LongType t) 1612 { 1613 if(slot >= 0 && slot <= 3) 1614 emit("lload_" + slot, 2); 1615 else 1616 emit("lload " + slot, 2); 1617 } 1618 1619 public void caseRefType(RefType t) 1620 { 1621 if(slot >= 0 && slot <= 3) 1622 emit("aload_" + slot, 1); 1623 else 1624 emit("aload " + slot, 1); 1625 } 1626 1627 public void caseNullType(NullType t) 1628 { 1629 if(slot >= 0 && slot <= 3) 1630 emit("aload_" + slot, 1); 1631 else 1632 emit("aload " + slot, 1); 1633 } 1634 }); 1635 } 1636 1637 void emitValue(Value value) 1638 { 1639 value.apply(new AbstractGrimpValueSwitch() 1640 { 1641 public void caseAddExpr(AddExpr v) 1642 { 1643 emitValue(v.getOp1()); 1644 emitValue(v.getOp2()); 1645 1646 v.getType().apply(new TypeSwitch() 1647 { 1648 private void handleIntCase() 1649 { 1650 emit("iadd", -1); 1651 } 1652 1653 public void caseIntType(IntType t) { handleIntCase(); } 1654 public void caseBooleanType(BooleanType t) { handleIntCase(); } 1655 public void caseShortType(ShortType t) { handleIntCase(); } 1656 public void caseCharType(CharType t) { handleIntCase(); } 1657 public void caseByteType(ByteType t) { handleIntCase(); } 1658 1659 public void caseLongType(LongType t) 1660 { 1661 emit("ladd", -2); 1662 } 1663 1664 public void caseDoubleType(DoubleType t) 1665 { 1666 emit("dadd", -2); 1667 } 1668 1669 public void caseFloatType(FloatType t) 1670 { 1671 emit("fadd", -1); 1672 } 1673 1674 public void defaultCase(Type t) 1675 { 1676 throw new RuntimeException ("Invalid argument type for add"); 1677 } 1678 }); 1679 1680 } 1681 1682 public void caseAndExpr(AndExpr v) 1683 { 1684 emitValue(v.getOp1()); 1685 emitValue(v.getOp2()); 1686 1687 v.getType().apply(new TypeSwitch() 1688 { 1689 private void handleIntCase() 1690 { 1691 emit("iand", -1); 1692 } 1693 1694 public void caseIntType(IntType t) { handleIntCase(); } 1695 public void caseBooleanType(BooleanType t) { handleIntCase(); } 1696 public void caseShortType(ShortType t) { handleIntCase(); } 1697 public void caseCharType(CharType t) { handleIntCase(); } 1698 public void caseByteType(ByteType t) { handleIntCase(); } 1699 1700 public void caseLongType(LongType t) 1701 { 1702 emit("land", -2); 1703 } 1704 1705 public void defaultCase(Type t) 1706 { 1707 throw new RuntimeException ("Invalid argument type for and"); 1708 } 1709 }); 1710 } 1711 1712 public void caseArrayRef(ArrayRef v) 1713 { 1714 emitValue(v.getBase()); 1715 emitValue(v.getIndex()); 1716 1717 v.getType().apply(new TypeSwitch() 1718 { 1719 public void caseArrayType(ArrayType ty) 1720 { 1721 emit("aaload", -1); 1722 } 1723 1724 public void caseBooleanType(BooleanType ty) 1725 { 1726 emit("baload", -1); 1727 } 1728 1729 public void caseByteType(ByteType ty) 1730 { 1731 emit("baload", -1); 1732 } 1733 1734 public void caseCharType(CharType ty) 1735 { 1736 emit("caload", -1); 1737 } 1738 1739 public void defaultCase(Type ty) 1740 { 1741 throw new RuntimeException ("invalid base type"); 1742 } 1743 1744 public void caseDoubleType(DoubleType ty) 1745 { 1746 emit("daload", 0); 1747 } 1748 1749 public void caseFloatType(FloatType ty) 1750 { 1751 emit("faload", -1); 1752 } 1753 1754 public void caseIntType(IntType ty) 1755 { 1756 emit("iaload", -1); 1757 } 1758 1759 public void caseLongType(LongType ty) 1760 { 1761 emit("laload", 0); 1762 } 1763 1764 public void caseNullType(NullType ty) 1765 { 1766 emit("aaload", -1); 1767 } 1768 public void caseRefType(RefType ty) 1769 { 1770 emit("aaload", -1); 1771 } 1772 1773 public void caseShortType(ShortType ty) 1774 { 1775 emit("saload", -1); 1776 } 1777 }); 1778 } 1779 1780 public void caseCastExpr(final CastExpr v) 1781 { 1782 final Type toType = v.getCastType(); 1783 final Type fromType = v.getOp().getType(); 1784 1785 emitValue(v.getOp()); 1786 1787 if(toType instanceof RefType) 1788 emit("checkcast " + slashify(toType.toString()), 0); 1789 else if(toType instanceof ArrayType) 1790 emit("checkcast " + jasminDescriptorOf(toType), 0); 1791 else { 1792 fromType.apply(new TypeSwitch() 1793 { 1794 public void defaultCase(Type ty) 1795 { 1796 throw new RuntimeException ("invalid fromType " + fromType); 1797 } 1798 1799 public void caseDoubleType(DoubleType ty) 1800 { 1801 if(toType.equals(IntType.v())) 1802 emit("d2i", -1); 1803 else if(toType.equals(LongType.v())) 1804 emit("d2l", 0); 1805 else if(toType.equals(FloatType.v())) 1806 emit("d2f", -1); 1807 else 1808 throw new RuntimeException ("invalid toType from double: " + toType); 1809 } 1810 1811 public void caseFloatType(FloatType ty) 1812 { 1813 if(toType.equals(IntType.v())) 1814 emit("f2i", 0); 1815 else if(toType.equals(LongType.v())) 1816 emit("f2l", 1); 1817 else if(toType.equals(DoubleType.v())) 1818 emit("f2d", 1); 1819 else 1820 throw new RuntimeException ("invalid toType from float: " + toType); 1821 } 1822 1823 public void caseIntType(IntType ty) 1824 { 1825 emitIntToTypeCast(); 1826 } 1827 1828 public void caseBooleanType(BooleanType ty) 1829 { 1830 emitIntToTypeCast(); 1831 } 1832 1833 public void caseByteType(ByteType ty) 1834 { 1835 emitIntToTypeCast(); 1836 } 1837 1838 public void caseCharType(CharType ty) 1839 { 1840 emitIntToTypeCast(); 1841 } 1842 1843 public void caseShortType(ShortType ty) 1844 { 1845 emitIntToTypeCast(); 1846 } 1847 1848 private void emitIntToTypeCast() 1849 { 1850 if(toType.equals(ByteType.v())) 1851 emit("i2b", 0); 1852 else if(toType.equals(CharType.v())) 1853 emit("i2c", 0); 1854 else if(toType.equals(ShortType.v())) 1855 emit("i2s", 0); 1856 else if(toType.equals(FloatType.v())) 1857 emit("i2f", 0); 1858 else if(toType.equals(LongType.v())) 1859 emit("i2l", 1); 1860 else if(toType.equals(DoubleType.v())) 1861 emit("i2d", 1); 1862 else if(toType.equals(IntType.v())) 1863 ; else if(toType.equals(BooleanType.v())) 1865 ; 1866 else 1867 throw new RuntimeException ("invalid toType from int: " + toType + 1868 " " + v.toString()); 1869 } 1870 1871 public void caseLongType(LongType ty) 1872 { 1873 if(toType.equals(IntType.v())) 1874 emit("l2i", -1); 1875 else if(toType.equals(FloatType.v())) 1876 emit("l2f", -1); 1877 else if(toType.equals(DoubleType.v())) 1878 emit("l2d", 0); 1879 else if(toType.equals(ByteType.v())) 1880 { emit("l2i", -1); emitIntToTypeCast(); } 1881 else if(toType.equals(ShortType.v())) 1882 { emit("l2i", -1); emitIntToTypeCast(); } 1883 else if(toType.equals(CharType.v())) 1884 { emit("l2i", -1); emitIntToTypeCast(); } 1885 else if(toType.equals(BooleanType.v())) 1886 { emit("l2i", -1); emitIntToTypeCast(); } 1887 else 1888 throw new RuntimeException ("invalid toType from long: " + toType); 1889 } 1890 }); 1891 } 1892 } 1893 1894 public void caseCmpExpr(CmpExpr v) 1895 { 1896 emitValue(v.getOp1()); 1897 emitValue(v.getOp2()); 1898 emit("lcmp", -3); 1899 } 1900 1901 public void caseCmpgExpr(CmpgExpr v) 1902 { 1903 emitValue(v.getOp1()); 1904 emitValue(v.getOp2()); 1905 1906 if(v.getOp1().getType().equals(FloatType.v())) 1907 emit("fcmpg", -1); 1908 else 1909 emit("dcmpg", -3); 1910 } 1911 1912 public void caseCmplExpr(CmplExpr v) 1913 { 1914 emitValue(v.getOp1()); 1915 emitValue(v.getOp2()); 1916 1917 if(v.getOp1().getType().equals(FloatType.v())) 1918 emit("fcmpl", -1); 1919 else 1920 emit("dcmpl", -3); 1921 } 1922 1923 public void defaultCase(Value v) 1924 { 1925 throw new RuntimeException ("Can't load value: " + v); 1926 } 1927 1928 public void caseDivExpr(DivExpr v) 1929 { 1930 emitValue(v.getOp1()); 1931 emitValue(v.getOp2()); 1932 1933 v.getType().apply(new TypeSwitch() 1934 { 1935 private void handleIntCase() 1936 { 1937 emit("idiv", -1); 1938 } 1939 1940 public void caseIntType(IntType t) { handleIntCase(); } 1941 public void caseBooleanType(BooleanType t) { handleIntCase(); } 1942 public void caseShortType(ShortType t) { handleIntCase(); } 1943 public void caseCharType(CharType t) { handleIntCase(); } 1944 public void caseByteType(ByteType t) { handleIntCase(); } 1945 1946 public void caseLongType(LongType t) 1947 { 1948 emit("ldiv", -2); 1949 } 1950 1951 public void caseDoubleType(DoubleType t) 1952 { 1953 emit("ddiv", -2); 1954 } 1955 1956 public void caseFloatType(FloatType t) 1957 { 1958 emit("fdiv", -1); 1959 } 1960 1961 public void defaultCase(Type t) 1962 { 1963 throw new RuntimeException ("Invalid argument type for div"); 1964 } 1965 }); 1966 1967 } 1968 1969 public void caseDoubleConstant(DoubleConstant v) 1970 { 1971 if((v.value == 0) && ((1.0/v.value) > 0.0)) 1972 emit("dconst_0", 2); 1973 else if(v.value == 1) 1974 emit("dconst_1", 2); 1975 else { 1976 String s = v.toString(); 1977 1978 if(s.equals("#Infinity")) 1979 s="+DoubleInfinity"; 1980 1981 if(s.equals("#-Infinity")) 1982 s="-DoubleInfinity"; 1983 1984 if(s.equals("#NaN")) 1985 s="+DoubleNaN"; 1986 1987 emit("ldc2_w " + s, 2); 1988 } 1989 } 1990 1991 public void caseFloatConstant(FloatConstant v) 1992 { 1993 if((v.value == 0) && ((1.0f/v.value) > 0.0f)) 1994 emit("fconst_0", 1); 1995 else if(v.value == 1) 1996 emit("fconst_1", 1); 1997 else if(v.value == 2) 1998 emit("fconst_2", 1); 1999 else { 2000 String s = v.toString(); 2001 2002 if(s.equals("#InfinityF")) 2003 s="+FloatInfinity"; 2004 if(s.equals("#-InfinityF")) 2005 s="-FloatInfinity"; 2006 2007 if(s.equals("#NaNF")) 2008 s="+FloatNaN"; 2009 2010 emit("ldc " + s, 1); 2011 } 2012 } 2013 2014 2015 public void caseInstanceFieldRef(InstanceFieldRef v) 2016 { 2017 emitValue(v.getBase()); 2018 2019 emit("getfield " + slashify(v.getFieldRef().declaringClass().getName()) + "/" + 2020 v.getFieldRef().name() + " " + jasminDescriptorOf(v.getFieldRef().type()), 2021 -1 + sizeOfType(v.getFieldRef().type())); 2022 } 2023 2024 public void caseInstanceOfExpr(InstanceOfExpr v) 2025 { 2026 final Type checkType; 2027 2028 emitValue(v.getOp()); 2029 2030 checkType = v.getCheckType(); 2031 2032 if(checkType instanceof RefType) 2033 emit("instanceof " + slashify(checkType.toString()), 0); 2034 else if(checkType instanceof ArrayType) 2035 emit("instanceof " + jasminDescriptorOf(checkType), 0); 2036 } 2037 2038 public void caseIntConstant(IntConstant v) 2039 { 2040 if(v.value == -1) 2041 emit("iconst_m1", 1); 2042 else if(v.value >= 0 && v.value <= 5) 2043 emit("iconst_" + v.value, 1); 2044 else if(v.value >= Byte.MIN_VALUE && v.value <= Byte.MAX_VALUE) 2045 emit("bipush " + v.value, 1); 2046 else if(v.value >= Short.MIN_VALUE && v.value <= Short.MAX_VALUE) 2047 emit("sipush " + v.value, 1); 2048 else 2049 emit("ldc " + v.toString(), 1); 2050 } 2051 2052 public void caseInterfaceInvokeExpr(InterfaceInvokeExpr v) 2053 { 2054 SootMethodRef m = v.getMethodRef(); 2055 2056 emitValue(v.getBase()); 2057 2058 for(int i = 0; i < m.parameterTypes().size(); i++) 2059 emitValue(v.getArg(i)); 2060 2061 emit("invokeinterface " + slashify(m.declaringClass().getName()) + "/" + 2062 m.name() + jasminDescriptorOf(m) + " " + (argCountOf(m) + 1), 2063 -(argCountOf(m) + 1) + sizeOfType(m.returnType())); 2064 } 2065 2066 public void caseLengthExpr(LengthExpr v) 2067 { 2068 emitValue(v.getOp()); 2069 emit("arraylength", 0); 2070 } 2071 2072 public void caseLocal(Local v) 2073 { 2074 emitLocal(v); 2075 } 2076 2077 public void caseLongConstant(LongConstant v) 2078 { 2079 if(v.value == 0) 2080 emit("lconst_0", 2); 2081 else if(v.value == 1) 2082 emit("lconst_1", 2); 2083 else 2084 emit("ldc2_w " + v.toString(), 2); 2085 } 2086 2087 2088 public void caseMulExpr(MulExpr v) 2089 { 2090 emitValue(v.getOp1()); 2091 emitValue(v.getOp2()); 2092 2093 v.getType().apply(new TypeSwitch() 2094 { 2095 private void handleIntCase() 2096 { 2097 emit("imul", -1); 2098 } 2099 2100 public void caseIntType(IntType t) { handleIntCase(); } 2101 public void caseBooleanType(BooleanType t) { handleIntCase(); } 2102 public void caseShortType(ShortType t) { handleIntCase(); } 2103 public void caseCharType(CharType t) { handleIntCase(); } 2104 public void caseByteType(ByteType t) { handleIntCase(); } 2105 2106 public void caseLongType(LongType t) 2107 { 2108 emit("lmul", -2); 2109 } 2110 2111 public void caseDoubleType(DoubleType t) 2112 { 2113 emit("dmul", -2); 2114 } 2115 2116 public void caseFloatType(FloatType t) 2117 { 2118 emit("fmul", -1); 2119 } 2120 2121 public void defaultCase(Type t) 2122 { 2123 throw new RuntimeException ("Invalid argument type for mul"); 2124 } 2125 }); 2126 } 2127 2128 public void caseLtExpr(LtExpr v) 2129 { 2130 emitValue(v.getOp1()); 2131 emitValue(v.getOp2()); 2132 2133 v.getOp1().getType().apply(new TypeSwitch() 2134 { 2135 public void caseDoubleType(DoubleType t) 2136 { 2137 emit("dcmpg", -3); 2138 emitBooleanBranch("iflt"); 2139 } 2140 2141 public void caseFloatType(FloatType t) 2142 { 2143 emit("fcmpg", -1); 2144 emitBooleanBranch("iflt"); 2145 } 2146 2147 private void handleIntCase() 2148 { 2149 emit("if_icmplt", -2); 2150 } 2151 2152 2153 public void caseIntType(IntType t) { handleIntCase(); } 2154 public void caseBooleanType(BooleanType t) { handleIntCase(); } 2155 public void caseShortType(ShortType t) { handleIntCase(); } 2156 public void caseCharType(CharType t) { handleIntCase(); } 2157 public void caseByteType(ByteType t) { handleIntCase(); } 2158 2159 public void caseLongType(LongType t) 2160 { 2161 emit("lcmp", -3); 2162 emitBooleanBranch("iflt"); 2163 } 2164 2165 public void defaultCase(Type t) 2166 { 2167 throw new RuntimeException ("invalid type"); 2168 } 2169 }); 2170 } 2171 2172 public void caseLeExpr(LeExpr v) 2173 { 2174 emitValue(v.getOp1()); 2175 emitValue(v.getOp2()); 2176 2177 v.getOp1().getType().apply(new TypeSwitch() 2178 { 2179 public void caseDoubleType(DoubleType t) 2180 { 2181 emit("dcmpg", -3); 2182 emitBooleanBranch("ifle"); 2183 } 2184 2185 public void caseFloatType(FloatType t) 2186 { 2187 emit("fcmpg", -1); 2188 emitBooleanBranch("ifle"); 2189 } 2190 2191 private void handleIntCase() 2192 { 2193 emit("if_icmple", -2); 2194 } 2195 2196 public void caseIntType(IntType t) { handleIntCase(); } 2197 public void caseBooleanType(BooleanType t) { handleIntCase(); } 2198 public void caseShortType(ShortType t) { handleIntCase(); } 2199 public void caseCharType(CharType t) { handleIntCase(); } 2200 public void caseByteType(ByteType t) { handleIntCase(); } 2201 2202 public void caseLongType(LongType t) 2203 { 2204 emit("lcmp", -3); 2205 emitBooleanBranch("ifle"); 2206 } 2207 2208 public void defaultCase(Type t) 2209 { 2210 throw new RuntimeException ("invalid type"); 2211 } 2212 }); 2213 } 2214 2215 public void caseGtExpr(GtExpr v) 2216 { 2217 emitValue(v.getOp1()); 2218 emitValue(v.getOp2()); 2219 2220 v.getOp1().getType().apply(new TypeSwitch() 2221 { 2222 public void caseDoubleType(DoubleType t) 2223 { 2224 emit("dcmpg", -3); 2225 emitBooleanBranch("ifgt"); 2226 } 2227 2228 public void caseFloatType(FloatType t) 2229 { 2230 emit("fcmpg", -1); 2231 emitBooleanBranch("ifgt"); 2232 } 2233 2234 private void handleIntCase() 2235 { 2236 emit("if_icmpgt", -2); 2237 } 2238 2239 public void caseIntType(IntType t) { handleIntCase(); } 2240 public void caseBooleanType(BooleanType t) { handleIntCase(); } 2241 public void caseShortType(ShortType t) { handleIntCase(); } 2242 public void caseCharType(CharType t) { handleIntCase(); } 2243 public void caseByteType(ByteType t) { handleIntCase(); } 2244 2245 public void caseLongType(LongType t) 2246 { 2247 emit("lcmp", -3); 2248 emitBooleanBranch("ifgt"); 2249 } 2250 2251 public void defaultCase(Type t) 2252 { 2253 throw new RuntimeException ("invalid type"); 2254 } 2255 }); 2256 } 2257 2258 public void caseGeExpr(GeExpr v) 2259 { 2260 emitValue(v.getOp1()); 2261 emitValue(v.getOp2()); 2262 2263 v.getOp1().getType().apply(new TypeSwitch() 2264 { 2265 public void caseDoubleType(DoubleType t) 2266 { 2267 emit("dcmpg", -3); 2268 emitBooleanBranch("ifge"); 2269 } 2270 2271 public void caseFloatType(FloatType t) 2272 { 2273 emit("fcmpg", -1); 2274 emitBooleanBranch("ifge"); 2275 } 2276 2277 private void handleIntCase() 2278 { 2279 emit("if_icmpge", -2); 2280 } 2281 2282 public void caseIntType(IntType t) { handleIntCase(); } 2283 public void caseBooleanType(BooleanType t) { handleIntCase(); } 2284 public void caseShortType(ShortType t) { handleIntCase(); } 2285 public void caseCharType(CharType t) { handleIntCase(); } 2286 public void caseByteType(ByteType t) { handleIntCase(); } 2287 2288 public void caseLongType(LongType t) 2289 { 2290 emit("lcmp", -3); 2291 emitBooleanBranch("ifge"); 2292 } 2293 2294 public void defaultCase(Type t) 2295 { 2296 throw new RuntimeException ("invalid type"); 2297 } 2298 }); 2299 } 2300 2301 public void caseNeExpr(NeExpr v) 2302 { 2303 emitValue(v.getOp1()); 2304 emitValue(v.getOp2()); 2305 2306 v.getOp1().getType().apply(new TypeSwitch() 2307 { 2308 public void caseDoubleType(DoubleType t) 2309 { 2310 emit("dcmpg", -3); 2311 emit("iconst_0", 1); 2312 emitBooleanBranch("if_icmpne"); 2313 } 2314 2315 public void caseFloatType(FloatType t) 2316 { 2317 emit("fcmpg", -1); 2318 emit("iconst_0", 1); 2319 emitBooleanBranch("if_icmpne"); 2320 } 2321 2322 private void handleIntCase() 2323 { 2324 emit("if_icmpne", -2); 2325 } 2326 2327 public void caseIntType(IntType t) { handleIntCase(); } 2328 public void caseBooleanType(BooleanType t) { handleIntCase(); } 2329 public void caseShortType(ShortType t) { handleIntCase(); } 2330 public void caseCharType(CharType t) { handleIntCase(); } 2331 public void caseByteType(ByteType t) { handleIntCase(); } 2332 2333 public void caseLongType(LongType t) 2334 { 2335 emit("lcmp", -3); 2336 emit("iconst_0", 1); 2337 emitBooleanBranch("if_icmpne"); 2338 } 2339 2340 public void caseArrayType(ArrayType t) 2341 { 2342 emitBooleanBranch("if_acmpne"); 2343 } 2344 2345 public void caseRefType(RefType t) 2346 { 2347 emitBooleanBranch("if_acmpne"); 2348 } 2349 2350 public void defaultCase(Type t) 2351 { 2352 throw new RuntimeException ("invalid type"); 2353 } 2354 }); 2355 } 2356 2357 public void caseEqExpr(EqExpr v) 2358 { 2359 emitValue(v.getOp1()); 2360 emitValue(v.getOp2()); 2361 2362 v.getOp1().getType().apply(new TypeSwitch() 2363 { 2364 public void caseDoubleType(DoubleType t) 2365 { 2366 emit("dcmpg", -3); 2367 emit("iconst_0", 1); 2368 emitBooleanBranch("if_icmpeq"); 2369 } 2370 2371 public void caseFloatType(FloatType t) 2372 { 2373 emit("fcmpg", -3); 2374 emit("iconst_0", 1); 2375 emitBooleanBranch("if_icmpeq"); 2376 } 2377 2378 private void handleIntCase() 2379 { 2380 emit("if_icmpeq", -2); 2381 } 2382 2383 public void caseIntType(IntType t) { handleIntCase(); } 2384 public void caseBooleanType(BooleanType t) { handleIntCase(); } 2385 public void caseShortType(ShortType t) { handleIntCase(); } 2386 public void caseCharType(CharType t) { handleIntCase(); } 2387 public void caseByteType(ByteType t) { handleIntCase(); } 2388 2389 public void caseLongType(LongType t) 2390 { 2391 emit("lcmp", -3); 2392 emit("iconst_0", 1); 2393 emitBooleanBranch("if_icmpeq"); 2394 } 2395 2396 public void caseArrayType(ArrayType t) 2397 { 2398 emitBooleanBranch("if_acmpeq"); 2399 } 2400 2401 public void casbeRefType(RefType t) 2402 { 2403 emitBooleanBranch("if_acmpeq"); 2404 } 2405 2406 public void defaultCase(Type t) 2407 { 2408 throw new RuntimeException ("invalid type"); 2409 } 2410 }); 2411 } 2412 2413 public void caseNegExpr(final NegExpr v) 2414 { 2415 emitValue(v.getOp()); 2416 2417 v.getType().apply(new TypeSwitch() 2418 { 2419 private void handleIntCase() 2420 { 2421 emit("ineg", 0); 2422 } 2423 2424 public void caseIntType(IntType t) { handleIntCase(); } 2425 public void caseBooleanType(BooleanType t) { handleIntCase(); } 2426 public void caseShortType(ShortType t) { handleIntCase(); } 2427 public void caseCharType(CharType t) { handleIntCase(); } 2428 public void caseByteType(ByteType t) { handleIntCase(); } 2429 2430 public void caseLongType(LongType t) 2431 { 2432 emit("lneg", 0); 2433 } 2434 2435 public void caseDoubleType(DoubleType t) 2436 { 2437 emit("dneg", 0); 2438 } 2439 2440 public void caseFloatType(FloatType t) 2441 { 2442 emit("fneg", 0); 2443 } 2444 2445 public void defaultCase(Type t) 2446 { 2447 throw new RuntimeException ("Invalid argument type for neg: " + t + ": " + v); 2448 } 2449 }); 2450 2451 } 2452 2453 public void caseNewArrayExpr(NewArrayExpr v) 2454 { 2455 Value size = v.getSize(); 2456 2457 emitValue(size); 2458 2459 if(v.getBaseType() instanceof RefType) 2460 emit("anewarray " + slashify(v.getBaseType().toString()), 0); 2461 else if(v.getBaseType() instanceof ArrayType) 2462 emit("anewarray " + jasminDescriptorOf(v.getBaseType()), 0); 2463 else 2464 emit("newarray " + v.getBaseType().toString(), 0); 2465 } 2466 2467 public void caseNewMultiArrayExpr(NewMultiArrayExpr v) 2468 { 2469 List sizes = v.getSizes(); 2470 2471 for(int i = 0; i < sizes.size(); i++) 2472 emitValue((Value) sizes.get(i)); 2473 2474 emit("multianewarray " + jasminDescriptorOf(v.getBaseType()) + " " + sizes.size(), -sizes.size() + 1); 2475 } 2476 2477 public void caseNewExpr(NewExpr v) 2478 { 2479 emit("new " + slashify(v.getBaseType().toString()), 1); 2480 } 2481 2482 public void caseNewInvokeExpr(NewInvokeExpr v) 2483 { 2484 emit("new " + slashify(v.getBaseType().toString()), 1); 2485 emit("dup", 1); 2486 2487 SootMethodRef m = v.getMethodRef(); 2488 2489 2492 for(int i = 0; i < m.parameterTypes().size(); i++) 2493 emitValue(v.getArg(i)); 2494 2495 emit("invokespecial " + slashify(m.declaringClass().getName()) + "/" + 2496 m.name() + jasminDescriptorOf(m), 2497 -(argCountOf(m) + 1) + sizeOfType(m.returnType())); 2498 } 2499 2500 public void caseNullConstant(NullConstant v) 2501 { 2502 emit("aconst_null", 1); 2503 } 2504 2505 public void caseOrExpr(OrExpr v) 2506 { 2507 emitValue(v.getOp1()); 2508 emitValue(v.getOp2()); 2509 2510 v.getType().apply(new TypeSwitch() 2511 { 2512 private void handleIntCase() 2513 { 2514 emit("ior", -1); 2515 } 2516 2517 public void caseIntType(IntType t) { handleIntCase(); } 2518 public void caseBooleanType(BooleanType t) { handleIntCase(); } 2519 public void caseShortType(ShortType t) { handleIntCase(); } 2520 public void caseCharType(CharType t) { handleIntCase(); } 2521 public void caseByteType(ByteType t) { handleIntCase(); } 2522 2523 public void caseLongType(LongType t) 2524 { 2525 emit("lor", -2); 2526 } 2527 2528 public void defaultCase(Type t) 2529 { 2530 throw new RuntimeException ("Invalid argument type for or"); 2531 } 2532 }); 2533 } 2534 2535 public void caseRemExpr(RemExpr v) 2536 { 2537 emitValue(v.getOp1()); 2538 emitValue(v.getOp2()); 2539 2540 v.getType().apply(new TypeSwitch() 2541 { 2542 private void handleIntCase() 2543 { 2544 emit("irem", -1); 2545 } 2546 2547 public void caseIntType(IntType t) { handleIntCase(); } 2548 public void caseBooleanType(BooleanType t) { handleIntCase(); } 2549 public void caseShortType(ShortType t) { handleIntCase(); } 2550 public void caseCharType(CharType t) { handleIntCase(); } 2551 public void caseByteType(ByteType t) { handleIntCase(); } 2552 2553 public void caseLongType(LongType t) 2554 { 2555 emit("lrem", -2); 2556 } 2557 2558 public void caseDoubleType(DoubleType t) 2559 { 2560 emit("drem", -2); 2561 } 2562 2563 public void caseFloatType(FloatType t) 2564 { 2565 emit("frem", -1); 2566 } 2567 2568 public void defaultCase(Type t) 2569 { 2570 throw new RuntimeException ("Invalid argument type for rem"); 2571 } 2572 }); 2573 } 2574 2575 public void caseShlExpr(ShlExpr v) 2576 { 2577 emitValue(v.getOp1()); 2578 emitValue(v.getOp2()); 2579 2580 v.getType().apply(new TypeSwitch() 2581 { 2582 private void handleIntCase() 2583 { 2584 emit("ishl", -1); 2585 } 2586 2587 public void caseIntType(IntType t) { handleIntCase(); } 2588 public void caseBooleanType(BooleanType t) { handleIntCase(); } 2589 public void caseShortType(ShortType t) { handleIntCase(); } 2590 public void caseCharType(CharType t) { handleIntCase(); } 2591 public void caseByteType(ByteType t) { handleIntCase(); } 2592 2593 public void caseLongType(LongType t) 2594 { 2595 emit("lshl", -1); 2596 } 2597 2598 public void defaultCase(Type t) 2599 { 2600 throw new RuntimeException ("Invalid argument type for shl"); 2601 } 2602 }); 2603 } 2604 2605 public void caseShrExpr(ShrExpr v) 2606 { 2607 emitValue(v.getOp1()); 2608 emitValue(v.getOp2()); 2609 2610 v.getType().apply(new TypeSwitch() 2611 { 2612 private void handleIntCase() 2613 { 2614 emit("ishr", -1); 2615 } 2616 2617 public void caseIntType(IntType t) { handleIntCase(); } 2618 public void caseBooleanType(BooleanType t) { handleIntCase(); } 2619 public void caseShortType(ShortType t) { handleIntCase(); } 2620 public void caseCharType(CharType t) { handleIntCase(); } 2621 public void caseByteType(ByteType t) { handleIntCase(); } 2622 2623 public void caseLongType(LongType t) 2624 { 2625 emit("lshr", -1); 2626 } 2627 2628 public void defaultCase(Type t) 2629 { 2630 throw new RuntimeException ("Invalid argument type for shr"); 2631 } 2632 }); 2633 } 2634 2635 public void caseSpecialInvokeExpr(SpecialInvokeExpr v) 2636 { 2637 SootMethodRef m = v.getMethodRef(); 2638 2639 emitValue(v.getBase()); 2640 2641 for(int i = 0; i < m.parameterTypes().size(); i++) 2642 emitValue(v.getArg(i)); 2643 2644 emit("invokespecial " + slashify(m.declaringClass().getName()) + "/" + 2645 m.name() + jasminDescriptorOf(m), 2646 -(argCountOf(m) + 1) + sizeOfType(m.returnType())); 2647 } 2648 2649 public void caseStaticInvokeExpr(StaticInvokeExpr v) 2650 { 2651 SootMethodRef m = v.getMethodRef(); 2652 2653 for(int i = 0; i < m.parameterTypes().size(); i++) 2654 emitValue(v.getArg(i)); 2655 2656 emit("invokestatic " + slashify(m.declaringClass().getName()) + "/" + 2657 m.name() + jasminDescriptorOf(m), 2658 -(argCountOf(m)) + sizeOfType(m.returnType())); 2659 } 2660 2661 public void caseStaticFieldRef(StaticFieldRef v) 2662 { 2663 emit("getstatic " + slashify(v.getFieldRef().declaringClass().getName()) + "/" + 2664 v.getFieldRef().name() + " " + jasminDescriptorOf(v.getFieldRef().type()), 2665 sizeOfType(v.getFieldRef().type())); 2666 } 2667 2668 public void caseStringConstant(StringConstant v) 2669 { 2670 emit("ldc " + v.toString(), 1); 2671 } 2672 2673 public void caseClassConstant(ClassConstant v) 2674 { 2675 emit("ldc_w " + v.getValue(), 1); 2676 } 2677 2678 public void caseSubExpr(SubExpr v) 2679 { 2680 emitValue(v.getOp1()); 2681 emitValue(v.getOp2()); 2682 2683 v.getType().apply(new TypeSwitch() 2684 { 2685 private void handleIntCase() 2686 { 2687 emit("isub", -1); 2688 } 2689 2690 public void caseIntType(IntType t) { handleIntCase(); } 2691 public void caseBooleanType(BooleanType t) { handleIntCase(); } 2692 public void caseShortType(ShortType t) { handleIntCase(); } 2693 public void caseCharType(CharType t) { handleIntCase(); } 2694 public void caseByteType(ByteType t) { handleIntCase(); } 2695 2696 public void caseLongType(LongType t) 2697 { 2698 emit("lsub", -2); 2699 } 2700 2701 public void caseDoubleType(DoubleType t) 2702 { 2703 emit("dsub", -2); 2704 } 2705 2706 public void caseFloatType(FloatType t) 2707 { 2708 emit("fsub", -1); 2709 } 2710 2711 public void defaultCase(Type t) 2712 { 2713 throw new RuntimeException ("Invalid argument type for sub"); 2714 } 2715 }); 2716 2717 } 2718 2719 public void caseUshrExpr(UshrExpr v) 2720 { 2721 emitValue(v.getOp1()); 2722 emitValue(v.getOp2()); 2723 2724 v.getType().apply(new TypeSwitch() 2725 { 2726 private void handleIntCase() 2727 { 2728 emit("iushr", -1); 2729 } 2730 2731 public void caseIntType(IntType t) { handleIntCase(); } 2732 public void caseBooleanType(BooleanType t) { handleIntCase(); } 2733 public void caseShortType(ShortType t) { handleIntCase(); } 2734 public void caseCharType(CharType t) { handleIntCase(); } 2735 public void caseByteType(ByteType t) { handleIntCase(); } 2736 2737 public void caseLongType(LongType t) 2738 { 2739 emit("lushr", -1); 2740 } 2741 2742 public void defaultCase(Type t) 2743 { 2744 throw new RuntimeException ("Invalid argument type for ushr"); 2745 } 2746 }); 2747 } 2748 2749 public void caseVirtualInvokeExpr(VirtualInvokeExpr v) 2750 { 2751 SootMethodRef m = v.getMethodRef(); 2752 2753 emitValue(v.getBase()); 2754 2755 for(int i = 0; i < m.parameterTypes().size(); i++) 2756 emitValue(v.getArg(i)); 2757 2758 emit("invokevirtual " + slashify(m.declaringClass().getName()) + "/" + 2759 m.name() + jasminDescriptorOf(m), 2760 -(argCountOf(m) + 1) + sizeOfType(m.returnType())); 2761 } 2762 2763 public void caseXorExpr(XorExpr v) 2764 { 2765 emitValue(v.getOp1()); 2766 emitValue(v.getOp2()); 2767 2768 v.getType().apply(new TypeSwitch() 2769 { 2770 private void handleIntCase() 2771 { 2772 emit ("ixor", -1); 2773 } 2774 2775 public void caseIntType(IntType t) { handleIntCase(); } 2776 public void caseBooleanType(BooleanType t) { handleIntCase(); } 2777 public void caseShortType(ShortType t) { handleIntCase(); } 2778 public void caseCharType(CharType t) { handleIntCase(); } 2779 public void caseByteType(ByteType t) { handleIntCase(); } 2780 2781 public void caseLongType(LongType t) 2782 { 2783 emit("lxor", -2); 2784 } 2785 2786 public void defaultCase(Type t) 2787 { 2788 throw new RuntimeException ("Invalid argument type for xor"); 2789 } 2790 }); 2791 } 2792 }); 2793 } 2794 2795 public void emitBooleanBranch(String s) 2796 { 2797 int count; 2798 2799 if(s.indexOf("icmp") != -1 || s.indexOf("acmp") != -1) 2800 count = -2; 2801 else 2802 count = -1; 2803 2804 emit(s + " label" + labelCount, count); 2805 emit("iconst_0", 1); 2806 emit("goto label" + labelCount+1, 0); 2807 emit("label" + labelCount++ + ":"); 2808 emit("iconst_1", 1); 2809 emit("label" + labelCount++ + ":"); 2810 } 2811 2812} 2813 | Popular Tags |