1 16 17 package org.cojen.classfile; 18 19 import java.util.Arrays ; 20 import java.util.HashMap ; 21 import java.util.Map ; 22 import java.util.Set ; 23 import java.io.PrintWriter ; 24 25 33 public class CodeAssemblerPrinter extends AbstractCodeAssembler implements CodeAssembler { 34 private final LocalVariable[] mParams; 35 private final boolean mIsStatic; 36 private final PrintWriter mWriter; 37 private final String mLinePrefix; 38 private final String mLineSuffix; 39 private final String mBulder; 40 41 private boolean mNeedSeparatorLine; 42 43 private int mLocalCounter; 44 private int mLabelCounter; 45 46 private int mTypeDescCounter; 47 private Map mTypeDescNames; 49 50 private int mTypeDescArrayCounter; 51 private Map mTypeDescArrayNames; 53 54 public CodeAssemblerPrinter(TypeDesc[] paramTypes, boolean isStatic, 55 PrintWriter writer) 56 { 57 this(paramTypes, isStatic, writer, null, null, null); 58 } 59 60 66 public CodeAssemblerPrinter(TypeDesc[] paramTypes, boolean isStatic, 67 PrintWriter writer, 68 String linePrefix, String lineSuffix, 69 String builder) 70 { 71 mIsStatic = isStatic; 72 mWriter = writer; 73 mLinePrefix = linePrefix; 74 mLineSuffix = lineSuffix; 75 if (builder == null || builder.length() == 0) { 76 builder = ""; 77 } else if (!builder.endsWith(".")) { 78 builder += '.'; 79 } 80 mBulder = builder; 81 mTypeDescNames = new HashMap (); 82 mTypeDescArrayNames = new HashMap (); 83 84 mParams = new LocalVariable[paramTypes.length]; 85 86 int varNum = (isStatic) ? 0 : 1; 87 for (int i = 0; i<paramTypes.length; i++) { 88 String varName = "var_" + (++mLocalCounter); 89 println("LocalVariable " + varName + " = " + 90 mBulder + "getParameter(" + i + ')'); 91 LocalVariable localVar = new NamedLocal(varName, paramTypes[i], varNum); 92 varNum += (localVar.isDoubleWord() ? 2 : 1); 93 mParams[i] = localVar; 94 } 95 } 96 97 public int getParameterCount() { 98 return mParams.length; 99 } 100 101 public LocalVariable getParameter(int index) { 102 return mParams[index]; 103 } 104 105 public LocalVariable createLocalVariable(String name, 106 TypeDesc type) { 107 String varName = "var_" + (++mLocalCounter); 108 if (name != null) { 109 name = '"' + name + '"'; 110 } 111 println("LocalVariable " + varName + " = " + 112 mBulder + "createLocalVariable(" + name + 113 ", " + getTypeDescName(type) + ')'); 114 return new NamedLocal(varName, type, -1); 115 } 116 117 public Label createLabel() { 118 String name = "label_" + (++mLabelCounter); 119 println("Label " + name + " = " + mBulder + "createLabel()"); 120 return new NamedLabel(name); 121 } 122 123 public void exceptionHandler(Location startLocation, 124 Location endLocation, 125 String catchClassName) { 126 println(mBulder + "exceptionHandler(" + 127 getLabelName(startLocation) + ", " + 128 getLabelName(endLocation) + ", " + 129 (catchClassName == null ? "null" : ('"' + catchClassName + '"')) + 130 ')'); 131 } 132 133 public void mapLineNumber(int lineNumber) { 134 separatorLine(); 135 println(mBulder + "mapLineNumber(" + lineNumber + ')'); 136 } 137 138 public void loadNull() { 139 println(mBulder + "loadNull()"); 140 } 141 142 public void loadConstant(String value) { 143 if (value == null) { 144 loadNull(); 145 } else { 146 println(mBulder + "loadConstant(\"" + escape(value) + "\")"); 147 } 148 } 149 150 public void loadConstant(TypeDesc type) { 151 if (type == null) { 152 loadNull(); 153 } else { 154 println(mBulder + "loadConstant(" + getTypeDescName(type) + ')'); 155 } 156 157 } 158 159 public void loadConstant(boolean value) { 160 println(mBulder + "loadConstant(" + value + ')'); 161 } 162 163 public void loadConstant(int value) { 164 println(mBulder + "loadConstant(" + value + ')'); 165 } 166 167 public void loadConstant(long value) { 168 println(mBulder + "loadConstant(" + value + "L)"); 169 } 170 171 public void loadConstant(float value) { 172 String str; 173 if (value != value) { 174 str = "0.0f/0.0f"; 175 } else if (value == Float.NEGATIVE_INFINITY) { 176 str = "-1.0f/0.0f"; 177 } else if (value == Float.POSITIVE_INFINITY) { 178 str = "1.0f/0.0f"; 179 } else { 180 str = String.valueOf(value) + 'f'; 181 } 182 println(mBulder + "loadConstant(" + str + ")"); 183 } 184 185 public void loadConstant(double value) { 186 String str; 187 if (value != value) { 188 str = "0.0d/0.0d"; 189 } else if (value == Double.NEGATIVE_INFINITY) { 190 str = "-1.0d/0.0d"; 191 } else if (value == Double.POSITIVE_INFINITY) { 192 str = "1.0d/0.0d"; 193 } else { 194 str = String.valueOf(value) + 'd'; 195 } 196 println(mBulder + "loadConstant(" + str + ")"); 197 } 198 199 public void loadLocal(LocalVariable local) { 200 println(mBulder + "loadLocal(" + local.getName() + ')'); 201 } 202 203 public void loadThis() { 204 println(mBulder + "loadThis()"); 205 } 206 207 public void storeLocal(LocalVariable local) { 208 println(mBulder + "storeLocal(" + local.getName() + ')'); 209 } 210 211 public void loadFromArray(TypeDesc type) { 212 println(mBulder + "loadFromArray(" + getTypeDescName(type) + ')'); 213 } 214 215 public void storeToArray(TypeDesc type) { 216 println(mBulder + "storeToArray(" + getTypeDescName(type) + ')'); 217 } 218 219 public void loadField(String fieldName, 220 TypeDesc type) { 221 println(mBulder + "loadField(\"" + fieldName + "\", " + 222 getTypeDescName(type) + ')'); 223 } 224 225 public void loadField(String className, 226 String fieldName, 227 TypeDesc type) { 228 println(mBulder + "loadField(\"" + className + "\", \"" + fieldName + "\", " + 229 getTypeDescName(type) + ')'); 230 } 231 232 public void loadField(TypeDesc classDesc, 233 String fieldName, 234 TypeDesc type) { 235 println(mBulder + "loadField(\"" + getTypeDescName(classDesc) + "\", \"" 236 + fieldName + "\", " + 237 getTypeDescName(type) + ')'); 238 } 239 240 public void loadStaticField(String fieldName, 241 TypeDesc type) { 242 println(mBulder + "loadStaticField(\"" + fieldName + "\", " + 243 getTypeDescName(type) + ')'); 244 } 245 246 public void loadStaticField(String className, 247 String fieldName, 248 TypeDesc type) { 249 println(mBulder + "loadStaticField(\"" + className + "\", \"" + 250 fieldName + "\", " + 251 getTypeDescName(type) + ')'); 252 } 253 254 public void loadStaticField(TypeDesc classDesc, 255 String fieldName, 256 TypeDesc type) { 257 println(mBulder + "loadStaticField(\"" + getTypeDescName(classDesc) + "\", \"" + 258 fieldName + "\", " + 259 getTypeDescName(type) + ')'); 260 } 261 262 public void storeField(String fieldName, 263 TypeDesc type) { 264 println(mBulder + "storeField(\"" + fieldName + "\", " + 265 getTypeDescName(type) + ')'); 266 } 267 268 public void storeField(String className, 269 String fieldName, 270 TypeDesc type) { 271 println(mBulder + "storeField(\"" + className + "\", \"" + fieldName + "\", " + 272 getTypeDescName(type) + ')'); 273 } 274 275 public void storeField(TypeDesc classDesc, 276 String fieldName, 277 TypeDesc type) { 278 println(mBulder + "storeField(\"" + getTypeDescName(classDesc) + "\", \"" + 279 fieldName + "\", " + 280 getTypeDescName(type) + ')'); 281 } 282 283 public void storeStaticField(String fieldName, 284 TypeDesc type) { 285 println(mBulder + "storeStaticField(\"" + fieldName + "\", " + 286 getTypeDescName(type) + ')'); 287 } 288 289 public void storeStaticField(String className, 290 String fieldName, 291 TypeDesc type) { 292 println(mBulder + "storeStaticField(\"" + className + "\", \"" + 293 fieldName + "\", " + 294 getTypeDescName(type) + ')'); 295 } 296 297 public void storeStaticField(TypeDesc classDesc, 298 String fieldName, 299 TypeDesc type) { 300 println(mBulder + "storeStaticField(\"" + getTypeDescName(classDesc) + "\", \"" + 301 fieldName + "\", " + 302 getTypeDescName(type) + ')'); 303 } 304 305 public void returnVoid() { 306 println(mBulder + "returnVoid()"); 307 } 308 309 public void returnValue(TypeDesc type) { 310 println(mBulder + "returnValue(" + getTypeDescName(type) + ')'); 311 } 312 313 public void convert(TypeDesc fromType, TypeDesc toType) { 314 println(mBulder + "convert(" + 315 getTypeDescName(fromType) + ", " + 316 getTypeDescName(toType) + ')'); 317 } 318 319 public void convert(TypeDesc fromType, TypeDesc toType, int fpConvertMode) { 320 switch (fpConvertMode) { 321 default: 322 convert(fromType, toType); 323 break; 324 case CONVERT_FP_BITS: 325 println(mBulder + "convert(" + 326 getTypeDescName(fromType) + ", " + 327 getTypeDescName(toType) + ", " + 328 mBulder + ".CONVERT_FP_BITS" + ')'); 329 break; 330 case CONVERT_FP_RAW_BITS: 331 println(mBulder + "convert(" + 332 getTypeDescName(fromType) + ", " + 333 getTypeDescName(toType) + ", " + 334 mBulder + ".CONVERT_FP_RAW_BITS" + ')'); 335 break; 336 } 337 } 338 339 public void invokeVirtual(String methodName, 340 TypeDesc ret, 341 TypeDesc[] params) { 342 println(mBulder + "invokeVirtual(\"" + methodName + "\", " + 343 getTypeDescName(ret) + ", " + 344 getTypeDescArrayName(params) + ')'); 345 } 346 347 public void invokeVirtual(String className, 348 String methodName, 349 TypeDesc ret, 350 TypeDesc[] params) { 351 println(mBulder + "invokeVirtual(\"" + className + "\", \"" + 352 methodName + "\", " + 353 getTypeDescName(ret) + ", " + 354 getTypeDescArrayName(params) + ')'); 355 } 356 357 public void invokeVirtual(TypeDesc classDesc, 358 String methodName, 359 TypeDesc ret, 360 TypeDesc[] params) { 361 println(mBulder + "invokeVirtual(\"" + getTypeDescName(classDesc) + "\", \"" + 362 methodName + "\", " + 363 getTypeDescName(ret) + ", " + 364 getTypeDescArrayName(params) + ')'); 365 } 366 367 public void invokeStatic(String methodName, 368 TypeDesc ret, 369 TypeDesc[] params) { 370 println(mBulder + "invokeStatic(\"" + methodName + "\", " + 371 getTypeDescName(ret) + ", " + 372 getTypeDescArrayName(params) + ')'); 373 } 374 375 public void invokeStatic(String className, 376 String methodName, 377 TypeDesc ret, 378 TypeDesc[] params) { 379 println(mBulder + "invokeStatic(\"" + className + "\", \"" + 380 methodName + "\", " + 381 getTypeDescName(ret) + ", " + 382 getTypeDescArrayName(params) + ')'); 383 } 384 385 public void invokeStatic(TypeDesc classDesc, 386 String methodName, 387 TypeDesc ret, 388 TypeDesc[] params) { 389 println(mBulder + "invokeStatic(\"" + getTypeDescName(classDesc) + "\", \"" + 390 methodName + "\", " + 391 getTypeDescName(ret) + ", " + 392 getTypeDescArrayName(params) + ')'); 393 } 394 395 public void invokeInterface(String className, 396 String methodName, 397 TypeDesc ret, 398 TypeDesc[] params) { 399 println(mBulder + "invokeInterface(\"" + className + "\", \"" + 400 methodName + "\", " + 401 getTypeDescName(ret) + ", " + 402 getTypeDescArrayName(params) + ')'); 403 } 404 405 public void invokeInterface(TypeDesc classDesc, 406 String methodName, 407 TypeDesc ret, 408 TypeDesc[] params) { 409 println(mBulder + "invokeInterface(\"" + getTypeDescName(classDesc) + "\", \"" + 410 methodName + "\", " + 411 getTypeDescName(ret) + ", " + 412 getTypeDescArrayName(params) + ')'); 413 } 414 415 public void invokePrivate(String methodName, 416 TypeDesc ret, 417 TypeDesc[] params) { 418 println(mBulder + "invokePrivate(\"" + methodName + "\", " + 419 getTypeDescName(ret) + ", " + 420 getTypeDescArrayName(params) + ')'); 421 } 422 423 public void invokeSuper(String superClassName, 424 String methodName, 425 TypeDesc ret, 426 TypeDesc[] params) { 427 println(mBulder + "invokeSuper(\"" + superClassName + "\", \"" + 428 methodName + "\", " + 429 getTypeDescName(ret) + ", " + 430 getTypeDescArrayName(params) + ')'); 431 } 432 433 public void invokeSuper(TypeDesc superClassDesc, 434 String methodName, 435 TypeDesc ret, 436 TypeDesc[] params) { 437 println(mBulder + "invokeSuper(\"" + getTypeDescName(superClassDesc) + "\", \"" + 438 methodName + "\", " + 439 getTypeDescName(ret) + ", " + 440 getTypeDescArrayName(params) + ')'); 441 } 442 443 public void invokeConstructor(TypeDesc[] params) { 444 println(mBulder + "invokeConstructor(" + 445 getTypeDescArrayName(params) + ')'); 446 } 447 448 public void invokeConstructor(String className, TypeDesc[] params) { 449 println(mBulder + "invokeConstructor(\"" + className + "\", " + 450 getTypeDescArrayName(params) + ')'); 451 } 452 453 public void invokeConstructor(TypeDesc classDesc, TypeDesc[] params) { 454 println(mBulder + "invokeConstructor(\"" + getTypeDescName(classDesc) + "\", " + 455 getTypeDescArrayName(params) + ')'); 456 } 457 458 public void invokeSuperConstructor(TypeDesc[] params) { 459 println(mBulder + "invokeSuperConstructor(" + 460 getTypeDescArrayName(params) + ')'); 461 } 462 463 public void newObject(TypeDesc type) { 464 println(mBulder + "newObject(" + getTypeDescName(type) + ')'); 465 } 466 467 public void newObject(TypeDesc type, int dimensions) { 468 if (dimensions == 0 && !type.isArray()) { 469 newObject(type); 470 } else { 471 println(mBulder + "newObject(" + getTypeDescName(type) + ", " + 472 dimensions + ')'); 473 } 474 } 475 476 public void dup() { 477 println(mBulder + "dup()"); 478 } 479 480 public void dupX1() { 481 println(mBulder + "dupX1()"); 482 } 483 484 public void dupX2() { 485 println(mBulder + "dupX2()"); 486 } 487 488 public void dup2() { 489 println(mBulder + "dup2()"); 490 } 491 492 public void dup2X1() { 493 println(mBulder + "dup2X1()"); 494 } 495 496 public void dup2X2() { 497 println(mBulder + "dup2X2()"); 498 } 499 500 public void pop() { 501 println(mBulder + "pop()"); 502 } 503 504 public void pop2() { 505 println(mBulder + "pop2()"); 506 } 507 508 public void swap() { 509 println(mBulder + "swap()"); 510 } 511 512 public void swap2() { 513 println(mBulder + "swap2()"); 514 } 515 516 public void branch(Location location) { 517 println(mBulder + "branch(" + getLabelName(location) + ')'); 518 } 519 520 public void ifNullBranch(Location location, boolean choice) { 521 println(mBulder + "ifNullBranch(" + 522 getLabelName(location) + ", " + choice + ')'); 523 } 524 525 public void ifEqualBranch(Location location, boolean choice) { 526 println(mBulder + "ifEqualBranch(" + 527 getLabelName(location) + ", " + choice + ')'); 528 } 529 530 public void ifZeroComparisonBranch(Location location, String choice) { 531 println(mBulder + "ifZeroComparisonBranch(" + 532 getLabelName(location) + ", \"" + choice + "\")"); 533 } 534 535 public void ifComparisonBranch(Location location, String choice) { 536 println(mBulder + "ifComparisonBranch(" + 537 getLabelName(location) + ", \"" + choice + "\")"); 538 } 539 540 public void switchBranch(int[] cases, 541 Location[] locations, Location defaultLocation) { 542 543 StringBuffer buf = new StringBuffer (cases.length * 15); 544 545 buf.append(mBulder + "switchBranch("); 546 547 buf.append("new int[] {"); 548 for (int i=0; i<cases.length; i++) { 549 if (i > 0) { 550 buf.append(", "); 551 } 552 buf.append(cases[i]); 553 } 554 buf.append("}"); 555 556 buf.append(", "); 557 558 buf.append("new Location[] {"); 559 for (int i=0; i<locations.length; i++) { 560 if (i > 0) { 561 buf.append(", "); 562 } 563 buf.append(getLabelName(locations[i])); 564 } 565 buf.append("}"); 566 567 buf.append(", "); 568 buf.append(getLabelName(defaultLocation)); 569 buf.append(')'); 570 571 println(buf.toString()); 572 } 573 574 public void jsr(Location location) { 575 println(mBulder + "jsr(" + getLabelName(location) + ')'); 576 } 577 578 public void ret(LocalVariable local) { 579 println(mBulder + "ret(" + local.getName() + ')'); 580 } 581 582 public void math(byte opcode) { 583 println 584 (mBulder + "math(Opcode." + Opcode.getMnemonic(opcode).toUpperCase() + ')'); 585 } 586 587 public void arrayLength() { 588 println(mBulder + "arrayLength()"); 589 } 590 591 public void throwObject() { 592 println(mBulder + "throwObject()"); 593 } 594 595 public void checkCast(TypeDesc type) { 596 println(mBulder + "checkCast(" + getTypeDescName(type) + ')'); 597 } 598 599 public void instanceOf(TypeDesc type) { 600 println(mBulder + "instanceOf(" + getTypeDescName(type) + ')'); 601 } 602 603 public void integerIncrement(LocalVariable local, int amount) { 604 println(mBulder + "integerIncrement(" + local.getName() + ", " + amount + ')'); 605 } 606 607 public void monitorEnter() { 608 println(mBulder + "monitorEnter()"); 609 } 610 611 public void monitorExit() { 612 println(mBulder + "monitorExit()"); 613 } 614 615 public void nop() { 616 println(mBulder + "nop()"); 617 } 618 619 public void breakpoint() { 620 println(mBulder + "breakpoint()"); 621 } 622 623 private void separatorLine() { 624 if (mNeedSeparatorLine) { 625 mWriter.println(); 626 mNeedSeparatorLine = false; 627 } 628 } 629 630 private void println(String str) { 631 mNeedSeparatorLine = true; 632 if (mLinePrefix != null) { 633 mWriter.print(mLinePrefix); 634 } 635 if (mLineSuffix == null) { 636 mWriter.println(str); 637 } else { 638 mWriter.print(str); 639 mWriter.println(mLineSuffix); 640 } 641 } 642 643 private String getLabelName(Location location) { 644 if (location instanceof NamedLabel) { 645 return ((NamedLabel)location).mName; 646 } else { 647 return ((NamedLabel)createLabel()).mName; 648 } 649 } 650 651 private String getTypeDescName(TypeDesc type) { 652 if (type == null) { 653 return "null"; 654 } 655 656 String name = (String )mTypeDescNames.get(type); 657 658 if (name == null) { 659 if (type.isPrimitive()) { 660 name = "TypeDesc.".concat(type.getRootName().toUpperCase()); 661 mTypeDescNames.put(type, name); 662 return name; 663 } else if (type == TypeDesc.OBJECT) { 664 mTypeDescNames.put(type, name = "TypeDesc.OBJECT"); 665 return name; 666 } else if (type == TypeDesc.STRING) { 667 mTypeDescNames.put(type, name = "TypeDesc.STRING"); 668 return name; 669 } 670 671 name = "type_" + (++mTypeDescCounter); 672 mTypeDescNames.put(type, name); 673 674 StringBuffer buf = new StringBuffer ("TypeDesc "); 675 buf.append(name); 676 buf.append(" = "); 677 678 TypeDesc componentType = type.getComponentType(); 679 if (componentType != null) { 680 buf.append(getTypeDescName(componentType)); 681 buf.append(".toArrayType("); 682 } else { 683 buf.append("TypeDesc.forClass("); 684 buf.append('"'); 685 buf.append(type.getRootName()); 686 buf.append('"'); 687 } 688 689 buf.append(')'); 690 println(buf.toString()); 691 } 692 693 return name; 694 } 695 696 private String getTypeDescArrayName(TypeDesc[] types) { 697 if (types == null) { 698 return "null"; 699 } 700 701 Object key = Arrays.asList(types); 702 String name = (String )mTypeDescArrayNames.get(key); 703 704 if (name == null) { 705 name = "params_" + (++mTypeDescArrayCounter); 706 mTypeDescArrayNames.put(key, name); 707 708 StringBuffer buf = new StringBuffer ("TypeDesc[] "); 709 buf.append(name); 710 buf.append(" = new TypeDesc[] {"); 711 712 for (int i=0; i<types.length; i++) { 713 if (i > 0) { 714 buf.append(", "); 715 } 716 buf.append(getTypeDescName(types[i])); 717 } 718 719 buf.append('}'); 720 println(buf.toString()); 721 } 722 723 return name; 724 } 725 726 static String escape(String value) { 727 return escape(value, false); 728 } 729 730 static String escape(String value, boolean forChar) { 731 int length = value.length(); 732 int i = 0; 733 for (; i < length; i++) { 734 char c = value.charAt(i); 735 if (c < 32 || c > 126 || c == '"' || c == '\\' || (forChar && c == '\'')) { 736 break; 737 } 738 } 739 740 if (i >= length) { 741 return value; 742 } 743 744 StringBuffer buf = new StringBuffer (length + 16); 745 for (i=0; i<length; i++) { 746 char c = value.charAt(i); 747 if (c >= 32 && c <= 126 && c != '"' && c != '\\' && (!forChar || c != '\'')) { 748 buf.append(c); 749 continue; 750 } 751 752 switch (c) { 753 case '\0': 754 buf.append("\\0"); 755 break; 756 case '"': 757 buf.append("\\\""); 758 break; 759 case '\'': 760 buf.append("\\'"); 761 break; 762 case '\\': 763 buf.append("\\\\"); 764 break; 765 case '\b': 766 buf.append("\\b"); 767 break; 768 case '\f': 769 buf.append("\\f"); 770 break; 771 case '\n': 772 buf.append("\\n"); 773 break; 774 case '\r': 775 buf.append("\\r"); 776 break; 777 case '\t': 778 buf.append("\\t"); 779 break; 780 default: 781 String u = Integer.toHexString(c).toLowerCase(); 782 buf.append("\\u"); 783 for (int len = u.length(); len < 4; len++) { 784 buf.append('0'); 785 } 786 buf.append(u); 787 break; 788 } 789 } 790 791 return buf.toString(); 792 } 793 794 private class NamedLocal implements LocalVariable { 795 private final String mName; 796 private final TypeDesc mType; 797 private final int mNumber; 798 799 public NamedLocal(String name, TypeDesc type, int number) { 800 mName = name; 801 mType = type; 802 mNumber = number; 803 } 804 805 public String getName() { 806 return mName; 807 } 808 809 public void setName(String name) { 810 println(mName + ".setName(" + name + ')'); 811 } 812 813 public TypeDesc getType() { 814 return mType; 815 } 816 817 public boolean isDoubleWord() { 818 return mType.isDoubleWord(); 819 } 820 821 public int getNumber() { 822 return mNumber; 823 } 824 825 public Location getStartLocation() { 826 return null; 827 } 828 829 public Location getEndLocation() { 830 return null; 831 } 832 833 public Set getLocationRangeSet() { 834 return null; 835 } 836 } 837 838 private class NamedLabel implements Label { 839 public final String mName; 840 841 public NamedLabel(String name) { 842 mName = name; 843 } 844 845 public Label setLocation() { 846 println(mName + ".setLocation()"); 847 return this; 848 } 849 850 public int getLocation() { 851 return -1; 852 } 853 854 public int compareTo(Object obj) { 855 return 0; 856 } 857 } 858 } 859 | Popular Tags |