comparison src/com/go/trove/classfile/CodeAssemblerPrinter.java @ 0:3dc0c5604566

Initial checkin of blitz 2.0 fcs - no installer yet.
author Dan Creswell <dan.creswell@gmail.com>
date Sat, 21 Mar 2009 11:00:06 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:3dc0c5604566
1 /* ====================================================================
2 * Trove - Copyright (c) 1997-2000 Walt Disney Internet Group
3 * ====================================================================
4 * The Tea Software License, Version 1.1
5 *
6 * Copyright (c) 2000 Walt Disney Internet Group. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. The end-user documentation included with the redistribution,
21 * if any, must include the following acknowledgment:
22 * "This product includes software developed by the
23 * Walt Disney Internet Group (http://opensource.go.com/)."
24 * Alternately, this acknowledgment may appear in the software itself,
25 * if and wherever such third-party acknowledgments normally appear.
26 *
27 * 4. The names "Tea", "TeaServlet", "Kettle", "Trove" and "BeanDoc" must
28 * not be used to endorse or promote products derived from this
29 * software without prior written permission. For written
30 * permission, please contact opensource@dig.com.
31 *
32 * 5. Products derived from this software may not be called "Tea",
33 * "TeaServlet", "Kettle" or "Trove", nor may "Tea", "TeaServlet",
34 * "Kettle", "Trove" or "BeanDoc" appear in their name, without prior
35 * written permission of the Walt Disney Internet Group.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE WALT DISNEY INTERNET GROUP OR ITS
41 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
43 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
44 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48 * ====================================================================
49 *
50 * For more information about Tea, please see http://opensource.go.com/.
51 */
52
53 package com.go.trove.classfile;
54
55 import java.util.*;
56 import java.io.PrintWriter;
57
58 /******************************************************************************
59 * CodeAssembler implementation that prints out instructions using a Java-like
60 * syntax that matches the methods of CodeAssembler. When used in conjunction
61 * with a {@link CodeDisassembler}, this class makes it easier to understand
62 * how to use a CodeAssembler.
63 *
64 * @author Brian S O'Neill
65 * @version
66 * <!--$$Revision: 1.1 $-->, <!--$$JustDate:--> 00/11/27 <!-- $-->
67 */
68 public class CodeAssemblerPrinter implements CodeAssembler {
69 private TypeDescriptor[] mParamTypes;
70 private boolean mIsStatic;
71 private PrintWriter mWriter;
72 private String mLinePrefix;
73 private String mLineSuffix;
74
75 private int mLocalCounter;
76 private int mLabelCounter;
77
78 private int mTypeDescriptorCounter;
79 // Maps TypeDescriptor objects to String variable names.
80 private Map mTypeDescriptorNames;
81
82 private int mTypeDescriptorArrayCounter;
83 // Maps TypeDescriptor arrays to String variable names.
84 private Map mTypeDescriptorArrayNames;
85
86 public CodeAssemblerPrinter(TypeDescriptor[] paramTypes, boolean isStatic,
87 PrintWriter writer)
88 {
89 this(paramTypes, isStatic, writer, null, null);
90 }
91
92 public CodeAssemblerPrinter(TypeDescriptor[] paramTypes, boolean isStatic,
93 PrintWriter writer,
94 String linePrefix, String lineSuffix)
95 {
96 mParamTypes = paramTypes;
97 mIsStatic = isStatic;
98 mWriter = writer;
99 mLinePrefix = linePrefix;
100 mLineSuffix = lineSuffix;
101 mTypeDescriptorNames = new HashMap();
102 mTypeDescriptorArrayNames = new HashMap();
103 }
104
105 public LocalVariable[] getParameters() {
106 LocalVariable[] vars = new LocalVariable[mParamTypes.length];
107
108 int varNum = (mIsStatic) ? 0 : 1;
109 for (int i = 0; i<mParamTypes.length; i++) {
110 String varName = "var_" + (++mLocalCounter);
111 println("LocalVariable " + varName +
112 " = getParameters()[" + i + ']');
113 LocalVariable localVar =
114 new NamedLocal(varName, mParamTypes[i], varNum);
115 varNum += (localVar.isDoubleWord() ? 2 : 1);
116 vars[i] = localVar;
117 }
118
119 return vars;
120 }
121
122 public LocalVariable createLocalVariable(String name,
123 TypeDescriptor type) {
124 String varName = "var_" + (++mLocalCounter);
125 if (name != null) {
126 name = '"' + name + '"';
127 }
128 println("LocalVariable " + varName +
129 " = createLocalVariable(" + name +
130 ", " + getTypeDescriptorName(type) + ')');
131 return new NamedLocal(varName, type, -1);
132 }
133
134 public Label createLabel() {
135 String name = "label_" + (++mLabelCounter);
136 println("Label " + name + " = createLabel()");
137 return new NamedLabel(name);
138 }
139
140 public void exceptionHandler(Location startLocation,
141 Location endLocation,
142 String catchClassName) {
143 println("exceptionHandler(" +
144 getLabelName(startLocation) + ", " +
145 getLabelName(endLocation) + ", " +
146 catchClassName + ')');
147 }
148
149 public void mapLineNumber(int lineNumber) {
150 println("mapLineNumber(" + lineNumber + ')');
151 }
152
153 public void loadConstant(String value) {
154 if (value == null) {
155 println("loadConstant(null)");
156 }
157 else {
158 println("loadConstant(\"" + escape(value) + "\")");
159 }
160 }
161
162 public void loadConstant(boolean value) {
163 println("loadConstant(" + value + ')');
164 }
165
166 public void loadConstant(int value) {
167 println("loadConstant(" + value + ')');
168 }
169
170 public void loadConstant(long value) {
171 println("loadConstant(" + value + "L)");
172 }
173
174 public void loadConstant(float value) {
175 println("loadConstant(" + value + "f)");
176 }
177
178 public void loadConstant(double value) {
179 println("loadConstant(" + value + "d)");
180 }
181
182 public void loadLocal(LocalVariable local) {
183 println("loadLocal(" + local.getName() + ')');
184 }
185
186 public void loadThis() {
187 println("loadThis()");
188 }
189
190 public void storeLocal(LocalVariable local) {
191 println("storeLocal(" + local.getName() + ')');
192 }
193
194 public void loadFromArray(Class type) {
195 println("loadFromArray(" + generateClassLiteral(type) + ')');
196 }
197
198 public void storeToArray(Class type) {
199 println("storeToArray(" + generateClassLiteral(type) + ')');
200 }
201
202 public void loadField(String fieldName,
203 TypeDescriptor type) {
204 println("loadField(\"" + fieldName + "\", " +
205 getTypeDescriptorName(type) + ')');
206 }
207
208 public void loadField(String className,
209 String fieldName,
210 TypeDescriptor type) {
211 println("loadField(\"" + className + "\", \"" + fieldName + "\", " +
212 getTypeDescriptorName(type) + ')');
213 }
214
215 public void loadStaticField(String fieldName,
216 TypeDescriptor type) {
217 println("loadStaticField(\"" + fieldName + "\", " +
218 getTypeDescriptorName(type) + ')');
219 }
220
221 public void loadStaticField(String className,
222 String fieldName,
223 TypeDescriptor type) {
224 println("loadStaticField(\"" + className + "\", \"" +
225 fieldName + "\", " +
226 getTypeDescriptorName(type) + ')');
227 }
228
229 public void storeField(String fieldName,
230 TypeDescriptor type) {
231 println("storeField(\"" + fieldName + "\", " +
232 getTypeDescriptorName(type) + ')');
233 }
234
235 public void storeField(String className,
236 String fieldName,
237 TypeDescriptor type) {
238 println("storeField(\"" + className + "\", \"" + fieldName + "\", " +
239 getTypeDescriptorName(type) + ')');
240 }
241
242 public void storeStaticField(String fieldName,
243 TypeDescriptor type) {
244 println("storeStaticField(\"" + fieldName + "\", " +
245 getTypeDescriptorName(type) + ')');
246 }
247
248 public void storeStaticField(String className,
249 String fieldName,
250 TypeDescriptor type) {
251 println("storeStaticField(\"" + className + "\", \"" +
252 fieldName + "\", " +
253 getTypeDescriptorName(type) + ')');
254 }
255
256 public void returnVoid() {
257 println("returnVoid()");
258 }
259
260 public void returnValue(Class type) {
261 println("returnValue(" + generateClassLiteral(type) + ')');
262 }
263
264 public void convert(Class fromType, Class toType) {
265 println("convert(" +
266 generateClassLiteral(fromType) + ", " +
267 generateClassLiteral(toType) + ')');
268 }
269
270 public void invokeVirtual(String methodName,
271 TypeDescriptor ret,
272 TypeDescriptor[] params) {
273 println("invokeVirtual(\"" + methodName + "\", " +
274 getTypeDescriptorName(ret) + ", " +
275 getTypeDescriptorArrayName(params) + ')');
276 }
277
278 public void invokeVirtual(String className,
279 String methodName,
280 TypeDescriptor ret,
281 TypeDescriptor[] params) {
282 println("invokeVirtual(\"" + className + "\", \"" +
283 methodName + "\", " +
284 getTypeDescriptorName(ret) + ", " +
285 getTypeDescriptorArrayName(params) + ')');
286 }
287
288 public void invokeStatic(String methodName,
289 TypeDescriptor ret,
290 TypeDescriptor[] params) {
291 println("invokeStatic(\"" + methodName + "\", " +
292 getTypeDescriptorName(ret) + ", " +
293 getTypeDescriptorArrayName(params) + ')');
294 }
295
296 public void invokeStatic(String className,
297 String methodName,
298 TypeDescriptor ret,
299 TypeDescriptor[] params) {
300 println("invokeStatic(\"" + className + ", " +
301 methodName + ", " +
302 getTypeDescriptorName(ret) + ", " +
303 getTypeDescriptorArrayName(params) + ')');
304 }
305
306 public void invokeInterface(String className,
307 String methodName,
308 TypeDescriptor ret,
309 TypeDescriptor[] params) {
310 println("invokeInterface(\"" + className + "\", \"" +
311 methodName + "\", " +
312 getTypeDescriptorName(ret) + ", " +
313 getTypeDescriptorArrayName(params) + ')');
314 }
315
316 public void invokePrivate(String methodName,
317 TypeDescriptor ret,
318 TypeDescriptor[] params) {
319 println("invokePrivate(\"" + methodName + "\", " +
320 getTypeDescriptorName(ret) + ", " +
321 getTypeDescriptorArrayName(params) + ')');
322 }
323
324 public void invokeSuper(String superClassName,
325 String methodName,
326 TypeDescriptor ret,
327 TypeDescriptor[] params) {
328 println("invokeSuper(\"" + superClassName + "\", \"" +
329 methodName + "\", " +
330 getTypeDescriptorName(ret) + ", " +
331 getTypeDescriptorArrayName(params) + ')');
332 }
333
334 public void invokeConstructor(TypeDescriptor[] params) {
335 println("invokeConstructor(" +
336 getTypeDescriptorArrayName(params) + ')');
337 }
338
339 public void invokeConstructor(String className, TypeDescriptor[] params) {
340 println("invokeConstructor(\"" + className + "\", " +
341 getTypeDescriptorArrayName(params) + ')');
342 }
343
344 public void invokeSuperConstructor(TypeDescriptor[] params) {
345 println("invokeSuperConstructor(" +
346 getTypeDescriptorArrayName(params) + ')');
347 }
348
349 public void newObject(TypeDescriptor type) {
350 println("newObject(" + getTypeDescriptorName(type) + ')');
351 }
352
353 public void dup() {
354 println("dup()");
355 }
356
357 public void dupX1() {
358 println("dupX1()");
359 }
360
361 public void dupX2() {
362 println("dupX2()");
363 }
364
365 public void dup2() {
366 println("dup2()");
367 }
368
369 public void dup2X1() {
370 println("dup2X1()");
371 }
372
373 public void dup2X2() {
374 println("dup2X2()");
375 }
376
377 public void pop() {
378 println("pop()");
379 }
380
381 public void pop2() {
382 println("pop2()");
383 }
384
385 public void swap() {
386 println("swap()");
387 }
388
389 public void swap2() {
390 println("swap2()");
391 }
392
393 public void branch(Location location) {
394 println("branch(" + getLabelName(location) + ')');
395 }
396
397 public void ifNullBranch(Location location, boolean choice) {
398 println("ifNullBranch(" +
399 getLabelName(location) + ", " + choice + ')');
400 }
401
402 public void ifEqualBranch(Location location, boolean choice) {
403 println("ifEqualBranch(" +
404 getLabelName(location) + ", " + choice + ')');
405 }
406
407 public void ifZeroComparisonBranch(Location location, String choice) {
408 println("ifZeroComparisonBranch(" +
409 getLabelName(location) + ", \"" + choice + "\")");
410 }
411
412 public void ifComparisonBranch(Location location, String choice) {
413 println("ifComparisonBranch(" +
414 getLabelName(location) + ", \"" + choice + "\")");
415 }
416
417 public void switchBranch(int[] cases,
418 Location[] locations, Location defaultLocation) {
419
420 StringBuffer buf = new StringBuffer(cases.length * 15);
421
422 buf.append("switchBranch(");
423
424 buf.append("new int[] {");
425 for (int i=0; i<cases.length; i++) {
426 if (i > 0) {
427 buf.append(", ");
428 }
429 buf.append(cases[i]);
430 }
431 buf.append("}");
432
433 buf.append(", ");
434
435 buf.append("new Location[] {");
436 for (int i=0; i<locations.length; i++) {
437 if (i > 0) {
438 buf.append(", ");
439 }
440 buf.append(getLabelName(locations[i]));
441 }
442 buf.append("}");
443
444 buf.append(", ");
445 buf.append(getLabelName(defaultLocation));
446 buf.append(')');
447
448 println(buf.toString());
449 }
450
451 public void jsr(Location location) {
452 println("jsr(" + getLabelName(location) + ')');
453 }
454
455 public void ret(LocalVariable local) {
456 println("ret(" + local.getName() + ')');
457 }
458
459 public void math(byte opcode) {
460 println
461 ("math(Opcode." + Opcode.getMnemonic(opcode).toUpperCase() + ')');
462 }
463
464 public void arrayLength() {
465 println("arrayLength()");
466 }
467
468 public void throwObject() {
469 println("throwObject()");
470 }
471
472 public void checkCast(TypeDescriptor type) {
473 println("checkCast(" + getTypeDescriptorName(type) + ')');
474 }
475
476 public void instanceOf(TypeDescriptor type) {
477 println("instanceOf(" + getTypeDescriptorName(type) + ')');
478 }
479
480 public void integerIncrement(LocalVariable local, int amount) {
481 println("integerIncrement(" + local.getName() + ", " + amount + ')');
482 }
483
484 public void monitorEnter() {
485 println("monitorEnter()");
486 }
487
488 public void monitorExit() {
489 println("monitorExit()");
490 }
491
492 public void nop() {
493 println("nop()");
494 }
495
496 public void breakpoint() {
497 println("breakpoint()");
498 }
499
500 private void println(String str) {
501 if (mLinePrefix != null) {
502 mWriter.print(mLinePrefix);
503 }
504 if (mLineSuffix == null) {
505 mWriter.println(str);
506 }
507 else {
508 mWriter.print(str);
509 mWriter.println(mLineSuffix);
510 }
511 }
512
513 private String generateClassLiteral(Class type) {
514 StringBuffer buf = new StringBuffer();
515
516 int dim = 0;
517 while (type.isArray()) {
518 dim++;
519 type = type.getComponentType();
520 }
521
522 if (!type.isPrimitive()) {
523 buf.append(type.getName());
524 }
525 else {
526 if (type == int.class) {
527 buf.append("int");
528 }
529 else if (type == char.class) {
530 buf.append("char");
531 }
532 else if (type == boolean.class) {
533 buf.append("boolean");
534 }
535 else if (type == double.class) {
536 buf.append("double");
537 }
538 else if (type == float.class) {
539 buf.append("float");
540 }
541 else if (type == long.class) {
542 buf.append("long");
543 }
544 else if (type == byte.class) {
545 buf.append("byte");
546 }
547 else if (type == short.class) {
548 buf.append("short");
549 }
550 else {
551 buf.append("void");
552 }
553 }
554
555 while (dim-- > 0) {
556 buf.append('[');
557 buf.append(']');
558 }
559
560 buf.append(".class");
561
562 return buf.toString();
563 }
564
565 private String getLabelName(Location location) {
566 if (location instanceof NamedLabel) {
567 return ((NamedLabel)location).mName;
568 }
569 else {
570 return ((NamedLabel)createLabel()).mName;
571 }
572 }
573
574 private String getTypeDescriptorName(TypeDescriptor type) {
575 if (type == null) {
576 return "null";
577 }
578
579 String name = (String)mTypeDescriptorNames.get(type);
580
581 if (name == null) {
582 name = "type_" + (++mTypeDescriptorCounter);
583 mTypeDescriptorNames.put(type, name);
584
585 StringBuffer buf = new StringBuffer("TypeDescriptor ");
586 buf.append(name);
587 buf.append(" = new TypeDescriptor(");
588
589 TypeDescriptor componentType = type.getComponentType();
590 if (componentType != null) {
591 buf.append(getTypeDescriptorName(componentType));
592 buf.append(", ");
593 buf.append(type.getSpecifiedDimensions());
594 }
595 else {
596 Class clazz = type.getClassArg();
597 if (clazz != null) {
598 buf.append(generateClassLiteral(clazz));
599 }
600 else {
601 buf.append('"');
602 buf.append(type.getClassName());
603 buf.append('"');
604 }
605 }
606
607 buf.append(')');
608
609 println(buf.toString());
610 }
611
612 return name;
613 }
614
615 private String getTypeDescriptorArrayName(TypeDescriptor[] types) {
616 if (types == null) {
617 return "null";
618 }
619
620 Object key = Arrays.asList(types);
621 String name = (String)mTypeDescriptorArrayNames.get(key);
622
623 if (name == null) {
624 name = "params_" + (++mTypeDescriptorArrayCounter);
625 mTypeDescriptorArrayNames.put(key, name);
626
627 StringBuffer buf = new StringBuffer("TypeDescriptor[] ");
628 buf.append(name);
629 buf.append(" = new TypeDescriptor[] {");
630
631 for (int i=0; i<types.length; i++) {
632 if (i > 0) {
633 buf.append(", ");
634 }
635 buf.append(getTypeDescriptorName(types[i]));
636 }
637
638 buf.append('}');
639
640 println(buf.toString());
641 }
642
643 return name;
644 }
645
646 private String escape(String value) {
647 int length = value.length();
648 int i = 0;
649 for (; i < length; i++) {
650 char c = value.charAt(i);
651 if (c < 32 || c > 126 || c == '"' || c == '\\') {
652 break;
653 }
654 }
655
656 if (i >= length) {
657 return value;
658 }
659
660 StringBuffer buf = new StringBuffer(length + 16);
661 for (i=0; i<length; i++) {
662 char c = value.charAt(i);
663 if (c >= 32 && c <= 126 && c != '"' && c != '\\') {
664 buf.append(c);
665 continue;
666 }
667
668 switch (c) {
669 case '\0':
670 buf.append("\\0");
671 break;
672 case '"':
673 buf.append("\\\"");
674 break;
675 case '\\':
676 buf.append("\\\\");
677 break;
678 case '\b':
679 buf.append("\\b");
680 break;
681 case '\f':
682 buf.append("\\f");
683 break;
684 case '\n':
685 buf.append("\\n");
686 break;
687 case '\r':
688 buf.append("\\r");
689 break;
690 case '\t':
691 buf.append("\\t");
692 break;
693 default:
694 String u = Integer.toHexString(c).toLowerCase();
695 buf.append("\\u");
696 for (int len = u.length(); len < 4; len++) {
697 buf.append('0');
698 }
699 buf.append(u);
700 break;
701 }
702 }
703
704 return buf.toString();
705 }
706
707 private class NamedLocal implements LocalVariable {
708 private String mName;
709 private TypeDescriptor mType;
710 private boolean mIsDoubleWord;
711 private int mNumber;
712
713 public NamedLocal(String name, TypeDescriptor type, int number) {
714 mName = name;
715 mType = type;
716 Class clazz = type.getClassArg();
717 mIsDoubleWord = clazz == long.class || clazz == double.class;
718 mNumber = number;
719 }
720
721 public String getName() {
722 return mName;
723 }
724
725 public void setName(String name) {
726 println(mName + ".setName(" + name + ')');
727 }
728
729 public TypeDescriptor getType() {
730 return mType;
731 }
732
733 public boolean isDoubleWord() {
734 return mIsDoubleWord;
735 }
736
737 public int getNumber() {
738 return mNumber;
739 }
740
741 public Location getStartLocation() {
742 return null;
743 }
744
745 public Location getEndLocation() {
746 return null;
747 }
748
749 public SortedSet getLocationRangeSet() {
750 return null;
751 }
752 }
753
754 private class NamedLabel implements Label {
755 public final String mName;
756
757 public NamedLabel(String name) {
758 mName = name;
759 }
760
761 public Label setLocation() {
762 println(mName + ".setLocation()");
763 return this;
764 }
765
766 public int getLocation() {
767 return -1;
768 }
769
770 public int compareTo(Object obj) {
771 return 0;
772 }
773 }
774 }