Mercurial > hg > blitz_condensed
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/go/trove/classfile/CodeAssemblerPrinter.java Sat Mar 21 11:00:06 2009 +0000 @@ -0,0 +1,774 @@ +/* ==================================================================== + * Trove - Copyright (c) 1997-2000 Walt Disney Internet Group + * ==================================================================== + * The Tea Software License, Version 1.1 + * + * Copyright (c) 2000 Walt Disney Internet Group. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Walt Disney Internet Group (http://opensource.go.com/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Tea", "TeaServlet", "Kettle", "Trove" and "BeanDoc" must + * not be used to endorse or promote products derived from this + * software without prior written permission. For written + * permission, please contact opensource@dig.com. + * + * 5. Products derived from this software may not be called "Tea", + * "TeaServlet", "Kettle" or "Trove", nor may "Tea", "TeaServlet", + * "Kettle", "Trove" or "BeanDoc" appear in their name, without prior + * written permission of the Walt Disney Internet Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE WALT DISNEY INTERNET GROUP OR ITS + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * For more information about Tea, please see http://opensource.go.com/. + */ + +package com.go.trove.classfile; + +import java.util.*; +import java.io.PrintWriter; + +/****************************************************************************** + * CodeAssembler implementation that prints out instructions using a Java-like + * syntax that matches the methods of CodeAssembler. When used in conjunction + * with a {@link CodeDisassembler}, this class makes it easier to understand + * how to use a CodeAssembler. + * + * @author Brian S O'Neill + * @version + * <!--$$Revision: 1.1 $-->, <!--$$JustDate:--> 00/11/27 <!-- $--> + */ +public class CodeAssemblerPrinter implements CodeAssembler { + private TypeDescriptor[] mParamTypes; + private boolean mIsStatic; + private PrintWriter mWriter; + private String mLinePrefix; + private String mLineSuffix; + + private int mLocalCounter; + private int mLabelCounter; + + private int mTypeDescriptorCounter; + // Maps TypeDescriptor objects to String variable names. + private Map mTypeDescriptorNames; + + private int mTypeDescriptorArrayCounter; + // Maps TypeDescriptor arrays to String variable names. + private Map mTypeDescriptorArrayNames; + + public CodeAssemblerPrinter(TypeDescriptor[] paramTypes, boolean isStatic, + PrintWriter writer) + { + this(paramTypes, isStatic, writer, null, null); + } + + public CodeAssemblerPrinter(TypeDescriptor[] paramTypes, boolean isStatic, + PrintWriter writer, + String linePrefix, String lineSuffix) + { + mParamTypes = paramTypes; + mIsStatic = isStatic; + mWriter = writer; + mLinePrefix = linePrefix; + mLineSuffix = lineSuffix; + mTypeDescriptorNames = new HashMap(); + mTypeDescriptorArrayNames = new HashMap(); + } + + public LocalVariable[] getParameters() { + LocalVariable[] vars = new LocalVariable[mParamTypes.length]; + + int varNum = (mIsStatic) ? 0 : 1; + for (int i = 0; i<mParamTypes.length; i++) { + String varName = "var_" + (++mLocalCounter); + println("LocalVariable " + varName + + " = getParameters()[" + i + ']'); + LocalVariable localVar = + new NamedLocal(varName, mParamTypes[i], varNum); + varNum += (localVar.isDoubleWord() ? 2 : 1); + vars[i] = localVar; + } + + return vars; + } + + public LocalVariable createLocalVariable(String name, + TypeDescriptor type) { + String varName = "var_" + (++mLocalCounter); + if (name != null) { + name = '"' + name + '"'; + } + println("LocalVariable " + varName + + " = createLocalVariable(" + name + + ", " + getTypeDescriptorName(type) + ')'); + return new NamedLocal(varName, type, -1); + } + + public Label createLabel() { + String name = "label_" + (++mLabelCounter); + println("Label " + name + " = createLabel()"); + return new NamedLabel(name); + } + + public void exceptionHandler(Location startLocation, + Location endLocation, + String catchClassName) { + println("exceptionHandler(" + + getLabelName(startLocation) + ", " + + getLabelName(endLocation) + ", " + + catchClassName + ')'); + } + + public void mapLineNumber(int lineNumber) { + println("mapLineNumber(" + lineNumber + ')'); + } + + public void loadConstant(String value) { + if (value == null) { + println("loadConstant(null)"); + } + else { + println("loadConstant(\"" + escape(value) + "\")"); + } + } + + public void loadConstant(boolean value) { + println("loadConstant(" + value + ')'); + } + + public void loadConstant(int value) { + println("loadConstant(" + value + ')'); + } + + public void loadConstant(long value) { + println("loadConstant(" + value + "L)"); + } + + public void loadConstant(float value) { + println("loadConstant(" + value + "f)"); + } + + public void loadConstant(double value) { + println("loadConstant(" + value + "d)"); + } + + public void loadLocal(LocalVariable local) { + println("loadLocal(" + local.getName() + ')'); + } + + public void loadThis() { + println("loadThis()"); + } + + public void storeLocal(LocalVariable local) { + println("storeLocal(" + local.getName() + ')'); + } + + public void loadFromArray(Class type) { + println("loadFromArray(" + generateClassLiteral(type) + ')'); + } + + public void storeToArray(Class type) { + println("storeToArray(" + generateClassLiteral(type) + ')'); + } + + public void loadField(String fieldName, + TypeDescriptor type) { + println("loadField(\"" + fieldName + "\", " + + getTypeDescriptorName(type) + ')'); + } + + public void loadField(String className, + String fieldName, + TypeDescriptor type) { + println("loadField(\"" + className + "\", \"" + fieldName + "\", " + + getTypeDescriptorName(type) + ')'); + } + + public void loadStaticField(String fieldName, + TypeDescriptor type) { + println("loadStaticField(\"" + fieldName + "\", " + + getTypeDescriptorName(type) + ')'); + } + + public void loadStaticField(String className, + String fieldName, + TypeDescriptor type) { + println("loadStaticField(\"" + className + "\", \"" + + fieldName + "\", " + + getTypeDescriptorName(type) + ')'); + } + + public void storeField(String fieldName, + TypeDescriptor type) { + println("storeField(\"" + fieldName + "\", " + + getTypeDescriptorName(type) + ')'); + } + + public void storeField(String className, + String fieldName, + TypeDescriptor type) { + println("storeField(\"" + className + "\", \"" + fieldName + "\", " + + getTypeDescriptorName(type) + ')'); + } + + public void storeStaticField(String fieldName, + TypeDescriptor type) { + println("storeStaticField(\"" + fieldName + "\", " + + getTypeDescriptorName(type) + ')'); + } + + public void storeStaticField(String className, + String fieldName, + TypeDescriptor type) { + println("storeStaticField(\"" + className + "\", \"" + + fieldName + "\", " + + getTypeDescriptorName(type) + ')'); + } + + public void returnVoid() { + println("returnVoid()"); + } + + public void returnValue(Class type) { + println("returnValue(" + generateClassLiteral(type) + ')'); + } + + public void convert(Class fromType, Class toType) { + println("convert(" + + generateClassLiteral(fromType) + ", " + + generateClassLiteral(toType) + ')'); + } + + public void invokeVirtual(String methodName, + TypeDescriptor ret, + TypeDescriptor[] params) { + println("invokeVirtual(\"" + methodName + "\", " + + getTypeDescriptorName(ret) + ", " + + getTypeDescriptorArrayName(params) + ')'); + } + + public void invokeVirtual(String className, + String methodName, + TypeDescriptor ret, + TypeDescriptor[] params) { + println("invokeVirtual(\"" + className + "\", \"" + + methodName + "\", " + + getTypeDescriptorName(ret) + ", " + + getTypeDescriptorArrayName(params) + ')'); + } + + public void invokeStatic(String methodName, + TypeDescriptor ret, + TypeDescriptor[] params) { + println("invokeStatic(\"" + methodName + "\", " + + getTypeDescriptorName(ret) + ", " + + getTypeDescriptorArrayName(params) + ')'); + } + + public void invokeStatic(String className, + String methodName, + TypeDescriptor ret, + TypeDescriptor[] params) { + println("invokeStatic(\"" + className + ", " + + methodName + ", " + + getTypeDescriptorName(ret) + ", " + + getTypeDescriptorArrayName(params) + ')'); + } + + public void invokeInterface(String className, + String methodName, + TypeDescriptor ret, + TypeDescriptor[] params) { + println("invokeInterface(\"" + className + "\", \"" + + methodName + "\", " + + getTypeDescriptorName(ret) + ", " + + getTypeDescriptorArrayName(params) + ')'); + } + + public void invokePrivate(String methodName, + TypeDescriptor ret, + TypeDescriptor[] params) { + println("invokePrivate(\"" + methodName + "\", " + + getTypeDescriptorName(ret) + ", " + + getTypeDescriptorArrayName(params) + ')'); + } + + public void invokeSuper(String superClassName, + String methodName, + TypeDescriptor ret, + TypeDescriptor[] params) { + println("invokeSuper(\"" + superClassName + "\", \"" + + methodName + "\", " + + getTypeDescriptorName(ret) + ", " + + getTypeDescriptorArrayName(params) + ')'); + } + + public void invokeConstructor(TypeDescriptor[] params) { + println("invokeConstructor(" + + getTypeDescriptorArrayName(params) + ')'); + } + + public void invokeConstructor(String className, TypeDescriptor[] params) { + println("invokeConstructor(\"" + className + "\", " + + getTypeDescriptorArrayName(params) + ')'); + } + + public void invokeSuperConstructor(TypeDescriptor[] params) { + println("invokeSuperConstructor(" + + getTypeDescriptorArrayName(params) + ')'); + } + + public void newObject(TypeDescriptor type) { + println("newObject(" + getTypeDescriptorName(type) + ')'); + } + + public void dup() { + println("dup()"); + } + + public void dupX1() { + println("dupX1()"); + } + + public void dupX2() { + println("dupX2()"); + } + + public void dup2() { + println("dup2()"); + } + + public void dup2X1() { + println("dup2X1()"); + } + + public void dup2X2() { + println("dup2X2()"); + } + + public void pop() { + println("pop()"); + } + + public void pop2() { + println("pop2()"); + } + + public void swap() { + println("swap()"); + } + + public void swap2() { + println("swap2()"); + } + + public void branch(Location location) { + println("branch(" + getLabelName(location) + ')'); + } + + public void ifNullBranch(Location location, boolean choice) { + println("ifNullBranch(" + + getLabelName(location) + ", " + choice + ')'); + } + + public void ifEqualBranch(Location location, boolean choice) { + println("ifEqualBranch(" + + getLabelName(location) + ", " + choice + ')'); + } + + public void ifZeroComparisonBranch(Location location, String choice) { + println("ifZeroComparisonBranch(" + + getLabelName(location) + ", \"" + choice + "\")"); + } + + public void ifComparisonBranch(Location location, String choice) { + println("ifComparisonBranch(" + + getLabelName(location) + ", \"" + choice + "\")"); + } + + public void switchBranch(int[] cases, + Location[] locations, Location defaultLocation) { + + StringBuffer buf = new StringBuffer(cases.length * 15); + + buf.append("switchBranch("); + + buf.append("new int[] {"); + for (int i=0; i<cases.length; i++) { + if (i > 0) { + buf.append(", "); + } + buf.append(cases[i]); + } + buf.append("}"); + + buf.append(", "); + + buf.append("new Location[] {"); + for (int i=0; i<locations.length; i++) { + if (i > 0) { + buf.append(", "); + } + buf.append(getLabelName(locations[i])); + } + buf.append("}"); + + buf.append(", "); + buf.append(getLabelName(defaultLocation)); + buf.append(')'); + + println(buf.toString()); + } + + public void jsr(Location location) { + println("jsr(" + getLabelName(location) + ')'); + } + + public void ret(LocalVariable local) { + println("ret(" + local.getName() + ')'); + } + + public void math(byte opcode) { + println + ("math(Opcode." + Opcode.getMnemonic(opcode).toUpperCase() + ')'); + } + + public void arrayLength() { + println("arrayLength()"); + } + + public void throwObject() { + println("throwObject()"); + } + + public void checkCast(TypeDescriptor type) { + println("checkCast(" + getTypeDescriptorName(type) + ')'); + } + + public void instanceOf(TypeDescriptor type) { + println("instanceOf(" + getTypeDescriptorName(type) + ')'); + } + + public void integerIncrement(LocalVariable local, int amount) { + println("integerIncrement(" + local.getName() + ", " + amount + ')'); + } + + public void monitorEnter() { + println("monitorEnter()"); + } + + public void monitorExit() { + println("monitorExit()"); + } + + public void nop() { + println("nop()"); + } + + public void breakpoint() { + println("breakpoint()"); + } + + private void println(String str) { + if (mLinePrefix != null) { + mWriter.print(mLinePrefix); + } + if (mLineSuffix == null) { + mWriter.println(str); + } + else { + mWriter.print(str); + mWriter.println(mLineSuffix); + } + } + + private String generateClassLiteral(Class type) { + StringBuffer buf = new StringBuffer(); + + int dim = 0; + while (type.isArray()) { + dim++; + type = type.getComponentType(); + } + + if (!type.isPrimitive()) { + buf.append(type.getName()); + } + else { + if (type == int.class) { + buf.append("int"); + } + else if (type == char.class) { + buf.append("char"); + } + else if (type == boolean.class) { + buf.append("boolean"); + } + else if (type == double.class) { + buf.append("double"); + } + else if (type == float.class) { + buf.append("float"); + } + else if (type == long.class) { + buf.append("long"); + } + else if (type == byte.class) { + buf.append("byte"); + } + else if (type == short.class) { + buf.append("short"); + } + else { + buf.append("void"); + } + } + + while (dim-- > 0) { + buf.append('['); + buf.append(']'); + } + + buf.append(".class"); + + return buf.toString(); + } + + private String getLabelName(Location location) { + if (location instanceof NamedLabel) { + return ((NamedLabel)location).mName; + } + else { + return ((NamedLabel)createLabel()).mName; + } + } + + private String getTypeDescriptorName(TypeDescriptor type) { + if (type == null) { + return "null"; + } + + String name = (String)mTypeDescriptorNames.get(type); + + if (name == null) { + name = "type_" + (++mTypeDescriptorCounter); + mTypeDescriptorNames.put(type, name); + + StringBuffer buf = new StringBuffer("TypeDescriptor "); + buf.append(name); + buf.append(" = new TypeDescriptor("); + + TypeDescriptor componentType = type.getComponentType(); + if (componentType != null) { + buf.append(getTypeDescriptorName(componentType)); + buf.append(", "); + buf.append(type.getSpecifiedDimensions()); + } + else { + Class clazz = type.getClassArg(); + if (clazz != null) { + buf.append(generateClassLiteral(clazz)); + } + else { + buf.append('"'); + buf.append(type.getClassName()); + buf.append('"'); + } + } + + buf.append(')'); + + println(buf.toString()); + } + + return name; + } + + private String getTypeDescriptorArrayName(TypeDescriptor[] types) { + if (types == null) { + return "null"; + } + + Object key = Arrays.asList(types); + String name = (String)mTypeDescriptorArrayNames.get(key); + + if (name == null) { + name = "params_" + (++mTypeDescriptorArrayCounter); + mTypeDescriptorArrayNames.put(key, name); + + StringBuffer buf = new StringBuffer("TypeDescriptor[] "); + buf.append(name); + buf.append(" = new TypeDescriptor[] {"); + + for (int i=0; i<types.length; i++) { + if (i > 0) { + buf.append(", "); + } + buf.append(getTypeDescriptorName(types[i])); + } + + buf.append('}'); + + println(buf.toString()); + } + + return name; + } + + private String escape(String value) { + int length = value.length(); + int i = 0; + for (; i < length; i++) { + char c = value.charAt(i); + if (c < 32 || c > 126 || c == '"' || c == '\\') { + break; + } + } + + if (i >= length) { + return value; + } + + StringBuffer buf = new StringBuffer(length + 16); + for (i=0; i<length; i++) { + char c = value.charAt(i); + if (c >= 32 && c <= 126 && c != '"' && c != '\\') { + buf.append(c); + continue; + } + + switch (c) { + case '\0': + buf.append("\\0"); + break; + case '"': + buf.append("\\\""); + break; + case '\\': + buf.append("\\\\"); + break; + case '\b': + buf.append("\\b"); + break; + case '\f': + buf.append("\\f"); + break; + case '\n': + buf.append("\\n"); + break; + case '\r': + buf.append("\\r"); + break; + case '\t': + buf.append("\\t"); + break; + default: + String u = Integer.toHexString(c).toLowerCase(); + buf.append("\\u"); + for (int len = u.length(); len < 4; len++) { + buf.append('0'); + } + buf.append(u); + break; + } + } + + return buf.toString(); + } + + private class NamedLocal implements LocalVariable { + private String mName; + private TypeDescriptor mType; + private boolean mIsDoubleWord; + private int mNumber; + + public NamedLocal(String name, TypeDescriptor type, int number) { + mName = name; + mType = type; + Class clazz = type.getClassArg(); + mIsDoubleWord = clazz == long.class || clazz == double.class; + mNumber = number; + } + + public String getName() { + return mName; + } + + public void setName(String name) { + println(mName + ".setName(" + name + ')'); + } + + public TypeDescriptor getType() { + return mType; + } + + public boolean isDoubleWord() { + return mIsDoubleWord; + } + + public int getNumber() { + return mNumber; + } + + public Location getStartLocation() { + return null; + } + + public Location getEndLocation() { + return null; + } + + public SortedSet getLocationRangeSet() { + return null; + } + } + + private class NamedLabel implements Label { + public final String mName; + + public NamedLabel(String name) { + mName = name; + } + + public Label setLocation() { + println(mName + ".setLocation()"); + return this; + } + + public int getLocation() { + return -1; + } + + public int compareTo(Object obj) { + return 0; + } + } +}