|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.tools.java; |
|
|
|
import java.util.Hashtable; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public |
|
class Type implements Constants { |
|
|
|
|
|
*/ |
|
private static final Hashtable typeHash = new Hashtable(231); |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
protected int typeCode; |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
protected String typeSig; |
|
|
|
|
|
|
|
*/ |
|
public static final Type noArgs[] = new Type[0]; |
|
public static final Type tError = new Type(TC_ERROR, "?"); |
|
public static final Type tPackage = new Type(TC_ERROR, "."); |
|
public static final Type tNull = new Type(TC_NULL, "*"); |
|
public static final Type tVoid = new Type(TC_VOID, SIG_VOID); |
|
public static final Type tBoolean = new Type(TC_BOOLEAN, SIG_BOOLEAN); |
|
public static final Type tByte = new Type(TC_BYTE, SIG_BYTE); |
|
public static final Type tChar = new Type(TC_CHAR, SIG_CHAR); |
|
public static final Type tShort = new Type(TC_SHORT, SIG_SHORT); |
|
public static final Type tInt = new Type(TC_INT, SIG_INT); |
|
public static final Type tFloat = new Type(TC_FLOAT, SIG_FLOAT); |
|
public static final Type tLong = new Type(TC_LONG, SIG_LONG); |
|
public static final Type tDouble = new Type(TC_DOUBLE, SIG_DOUBLE); |
|
public static final Type tObject = Type.tClass(idJavaLangObject); |
|
public static final Type tClassDesc = Type.tClass(idJavaLangClass); |
|
public static final Type tString = Type.tClass(idJavaLangString); |
|
public static final Type tCloneable = Type.tClass(idJavaLangCloneable); |
|
public static final Type tSerializable = Type.tClass(idJavaIoSerializable); |
|
|
|
|
|
|
|
*/ |
|
protected Type(int typeCode, String typeSig) { |
|
this.typeCode = typeCode; |
|
this.typeSig = typeSig; |
|
typeHash.put(typeSig, this); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public final String getTypeSignature() { |
|
return typeSig; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public final int getTypeCode() { |
|
return typeCode; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final int getTypeMask() { |
|
return 1 << typeCode; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public final boolean isType(int tc) { |
|
return typeCode == tc; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean isVoidArray() { |
|
|
|
if (!isType(TC_ARRAY)) { |
|
return false; |
|
} |
|
|
|
Type type = this; |
|
while (type.isType(TC_ARRAY)) |
|
type = type.getElementType(); |
|
|
|
return type.isType(TC_VOID); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public final boolean inMask(int tm) { |
|
return ((1 << typeCode) & tm) != 0; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static synchronized Type tArray(Type elem) { |
|
String sig = new String(SIG_ARRAY + elem.getTypeSignature()); |
|
Type t = (Type)typeHash.get(sig); |
|
if (t == null) { |
|
t = new ArrayType(sig, elem); |
|
} |
|
return t; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public Type getElementType() { |
|
throw new CompilerError("getElementType"); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public int getArrayDimension() { |
|
return 0; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static synchronized Type tClass(Identifier className) { |
|
if (className.isInner()) { |
|
Type t = tClass(mangleInnerType(className)); |
|
if (t.getClassName() != className) |
|
// Somebody got here first with a mangled name. |
|
|
|
changeClassName(t.getClassName(), className); |
|
return t; |
|
} |
|
|
|
if (className.typeObject != null) { |
|
return className.typeObject; |
|
} |
|
String sig = |
|
new String(SIG_CLASS + |
|
className.toString().replace('.', SIGC_PACKAGE) + |
|
SIG_ENDCLASS); |
|
Type t = (Type)typeHash.get(sig); |
|
if (t == null) { |
|
t = new ClassType(sig, className); |
|
} |
|
|
|
className.typeObject = t; |
|
return t; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public Identifier getClassName() { |
|
throw new CompilerError("getClassName:" + this); |
|
} |
|
|
|
/** |
|
* Given an inner identifier, return the non-inner, mangled |
|
* representation used to manage signatures. |
|
* |
|
* Note: It is changed to 'public' for Jcov file generation. |
|
* (see Assembler.java) |
|
*/ |
|
|
|
public static Identifier mangleInnerType(Identifier className) { |
|
|
|
if (!className.isInner()) return className; |
|
Identifier mname = Identifier.lookup( |
|
className.getFlatName().toString(). |
|
replace('.', SIGC_INNERCLASS) ); |
|
if (mname.isInner()) throw new CompilerError("mangle "+mname); |
|
return Identifier.lookup(className.getQualifier(), mname); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
static void changeClassName(Identifier oldName, Identifier newName) { |
|
// Note: If we are upgrading "pkg.Foo$Bar" to "pkg.Foo. Bar", |
|
// we assume someone else will come along and deal with any types |
|
|
|
((ClassType)Type.tClass(oldName)).className = newName; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static synchronized Type tMethod(Type ret) { |
|
return tMethod(ret, noArgs); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static synchronized Type tMethod(Type returnType, Type argTypes[]) { |
|
StringBuffer buf = new StringBuffer(); |
|
buf.append(SIG_METHOD); |
|
for (int i = 0 ; i < argTypes.length ; i++) { |
|
buf.append(argTypes[i].getTypeSignature()); |
|
} |
|
buf.append(SIG_ENDMETHOD); |
|
buf.append(returnType.getTypeSignature()); |
|
|
|
String sig = buf.toString(); |
|
Type t = (Type)typeHash.get(sig); |
|
if (t == null) { |
|
t = new MethodType(sig, returnType, argTypes); |
|
} |
|
return t; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public Type getReturnType() { |
|
throw new CompilerError("getReturnType"); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public Type getArgumentTypes()[] { |
|
throw new CompilerError("getArgumentTypes"); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static synchronized Type tType(String sig) { |
|
Type t = (Type)typeHash.get(sig); |
|
if (t != null) { |
|
return t; |
|
} |
|
|
|
switch (sig.charAt(0)) { |
|
case SIGC_ARRAY: |
|
return Type.tArray(tType(sig.substring(1))); |
|
|
|
case SIGC_CLASS: |
|
return Type.tClass(Identifier.lookup(sig.substring(1, sig.length() - 1).replace(SIGC_PACKAGE, '.'))); |
|
|
|
case SIGC_METHOD: { |
|
Type argv[] = new Type[8]; |
|
int argc = 0; |
|
int i, j; |
|
|
|
for (i = 1 ; sig.charAt(i) != SIGC_ENDMETHOD ; i = j) { |
|
for (j = i ; sig.charAt(j) == SIGC_ARRAY ; j++); |
|
if (sig.charAt(j++) == SIGC_CLASS) { |
|
while (sig.charAt(j++) != SIGC_ENDCLASS); |
|
} |
|
if (argc == argv.length) { |
|
Type newargv[] = new Type[argc * 2]; |
|
System.arraycopy(argv, 0, newargv, 0, argc); |
|
argv = newargv; |
|
} |
|
argv[argc++] = tType(sig.substring(i, j)); |
|
} |
|
|
|
Type argtypes[] = new Type[argc]; |
|
System.arraycopy(argv, 0, argtypes, 0, argc); |
|
return Type.tMethod(tType(sig.substring(i + 1)), argtypes); |
|
} |
|
} |
|
|
|
throw new CompilerError("invalid TypeSignature:" + sig); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean equalArguments(Type t) { |
|
return false; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int stackSize() { |
|
switch (typeCode) { |
|
case TC_ERROR: |
|
case TC_VOID: |
|
return 0; |
|
case TC_BOOLEAN: |
|
case TC_BYTE: |
|
case TC_SHORT: |
|
case TC_CHAR: |
|
case TC_INT: |
|
case TC_FLOAT: |
|
case TC_ARRAY: |
|
case TC_CLASS: |
|
return 1; |
|
case TC_LONG: |
|
case TC_DOUBLE: |
|
return 2; |
|
} |
|
throw new CompilerError("stackSize " + toString()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int getTypeCodeOffset() { |
|
switch (typeCode) { |
|
case TC_BOOLEAN: |
|
case TC_BYTE: |
|
case TC_SHORT: |
|
case TC_CHAR: |
|
case TC_INT: |
|
return 0; |
|
case TC_LONG: |
|
return 1; |
|
case TC_FLOAT: |
|
return 2; |
|
case TC_DOUBLE: |
|
return 3; |
|
case TC_NULL: |
|
case TC_ARRAY: |
|
case TC_CLASS: |
|
return 4; |
|
} |
|
throw new CompilerError("invalid typecode: " + typeCode); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public String typeString(String id, boolean abbrev, boolean ret) { |
|
String s = null; |
|
|
|
switch (typeCode) { |
|
case TC_NULL: s = "null"; break; |
|
case TC_VOID: s = "void"; break; |
|
case TC_BOOLEAN: s = "boolean"; break; |
|
case TC_BYTE: s = "byte"; break; |
|
case TC_CHAR: s = "char"; break; |
|
case TC_SHORT: s = "short"; break; |
|
case TC_INT: s = "int"; break; |
|
case TC_LONG: s = "long"; break; |
|
case TC_FLOAT: s = "float"; break; |
|
case TC_DOUBLE: s = "double"; break; |
|
case TC_ERROR: s = "<error>"; |
|
if (this==tPackage) s = "<package>"; |
|
break; |
|
default: s = "unknown"; |
|
} |
|
|
|
return (id.length() > 0) ? s + " " + id : s; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public String typeString(String id) { |
|
return typeString(id, false, true); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public String toString() { |
|
return typeString("", false, true); |
|
} |
|
} |