|
|
|
@ -28,87 +28,106 @@ import jode.GlobalOptions; |
|
|
|
|
* ints whose value is in byte resp. short range. They may be |
|
|
|
|
* converted to B resp. S, but sometimes need an explicit cast. |
|
|
|
|
* |
|
|
|
|
* @author Jochen Hoenicke */ |
|
|
|
|
* @author Jochen Hoenicke |
|
|
|
|
*/ |
|
|
|
|
public class IntegerType extends Type { |
|
|
|
|
|
|
|
|
|
public static final int IT_I = 0x01; |
|
|
|
|
public static final int IT_C = 0x02; |
|
|
|
|
public static final int IT_S = 0x04; |
|
|
|
|
public static final int IT_B = 0x08; |
|
|
|
|
public static final int IT_Z = 0x10; |
|
|
|
|
/* Order does matter: |
|
|
|
|
* First type that is possible (and hinted) will be taken. |
|
|
|
|
*/ |
|
|
|
|
public static final int IT_Z = 0x01; |
|
|
|
|
public static final int IT_I = 0x02; |
|
|
|
|
public static final int IT_C = 0x04; |
|
|
|
|
public static final int IT_S = 0x08; |
|
|
|
|
public static final int IT_B = 0x10; |
|
|
|
|
public static final int IT_cS = 0x20; |
|
|
|
|
public static final int IT_cB = 0x40; |
|
|
|
|
private static final int NUM_TYPES = 7; |
|
|
|
|
|
|
|
|
|
private static final int[] subTypes = { |
|
|
|
|
/*Z*/ IT_Z, |
|
|
|
|
/*I*/ IT_I|IT_C|IT_S|IT_B/*|IT_cS|IT_cB*/, /*C*/ IT_C, |
|
|
|
|
/*S*/ IT_S|IT_B/*|IT_cS|IT_cB*/, /*B*/ IT_B/*|IT_cB*/, |
|
|
|
|
/*Z*/ IT_Z, |
|
|
|
|
/*cS*/IT_cS|IT_cB, /*cB*/IT_cB |
|
|
|
|
}; |
|
|
|
|
private static final int[] superTypes = { |
|
|
|
|
/*Z*/ IT_Z, |
|
|
|
|
/*I*/ IT_I, /*C*/ IT_I|IT_C, |
|
|
|
|
/*S*/ IT_I|IT_S, /*B*/ IT_I|IT_S|IT_B, |
|
|
|
|
/*Z*/ IT_Z, |
|
|
|
|
/*cS*/IT_I|IT_C|IT_S|IT_cS, /*cB*/IT_I|IT_C|IT_S|IT_B|IT_cS|IT_cB |
|
|
|
|
}; |
|
|
|
|
private static final Type[] simpleTypes = { |
|
|
|
|
new IntegerType(IT_Z), |
|
|
|
|
new IntegerType(IT_I), new IntegerType(IT_C), |
|
|
|
|
new IntegerType(IT_S), new IntegerType(IT_B), |
|
|
|
|
new IntegerType(IT_Z), |
|
|
|
|
new IntegerType(IT_cS), new IntegerType(IT_cB) |
|
|
|
|
}; |
|
|
|
|
private static final String[] typeNames = { |
|
|
|
|
"I","C","S","B","Z","cS","cB" |
|
|
|
|
"Z","I","C","S","B","s","b" |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int possTypes; |
|
|
|
|
int strongHint = 0; |
|
|
|
|
int weakHint = 0; |
|
|
|
|
int hintTypes; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Create a new type with the given type. |
|
|
|
|
*/ |
|
|
|
|
public IntegerType(int types) { |
|
|
|
|
this(types, types); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public IntegerType(int types, int hints) { |
|
|
|
|
super(TC_INTEGER); |
|
|
|
|
possTypes = types; |
|
|
|
|
hintTypes = hints; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public Type getHint() { |
|
|
|
|
int hint = ((possTypes & IT_Z) != 0 ? IT_Z |
|
|
|
|
: strongHint != 0 ? strongHint |
|
|
|
|
: weakHint != 0 ? weakHint |
|
|
|
|
: possTypes); |
|
|
|
|
int hint = possTypes & hintTypes; |
|
|
|
|
if (hint == 0) |
|
|
|
|
hint = possTypes; |
|
|
|
|
int i = 0; |
|
|
|
|
while ((hint & 1) == 0) { |
|
|
|
|
hint >>= 1; |
|
|
|
|
i++; |
|
|
|
|
} |
|
|
|
|
return simpleTypes[i]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public Type getCanonic() { |
|
|
|
|
int types = possTypes; |
|
|
|
|
int i = 0; |
|
|
|
|
for (int it = 0x1; (it & hint) == 0; it <<= 1) |
|
|
|
|
while ((types >>= 1) != 0) { |
|
|
|
|
i++; |
|
|
|
|
} |
|
|
|
|
return simpleTypes[i]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private int getSubTypes() { |
|
|
|
|
private static int getSubTypes(int types) { |
|
|
|
|
int result = 0; |
|
|
|
|
for (int i=0; i < NUM_TYPES; i++) { |
|
|
|
|
if (((1<<i) & possTypes) != 0) |
|
|
|
|
if (((1<<i) & types) != 0) |
|
|
|
|
result |= subTypes[i]; |
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
private int getSuperTypes() { |
|
|
|
|
private static int getSuperTypes(int types) { |
|
|
|
|
int result = 0; |
|
|
|
|
for (int i=0; i < NUM_TYPES; i++) { |
|
|
|
|
if (((1<<i) & possTypes) != 0) |
|
|
|
|
if (((1<<i) & types) != 0) |
|
|
|
|
result |= superTypes[i]; |
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public Type getSubType() { |
|
|
|
|
return new IntegerType(getSubTypes()); |
|
|
|
|
return new IntegerType(getSubTypes(possTypes), |
|
|
|
|
getSubTypes(hintTypes)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public Type getSuperType() { |
|
|
|
|
return new IntegerType(getSuperTypes()); |
|
|
|
|
/* Don't upgrade hints */ |
|
|
|
|
return new IntegerType(getSuperTypes(possTypes), hintTypes); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -181,28 +200,34 @@ public class IntegerType extends Type { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public String toString() { |
|
|
|
|
switch (possTypes) { |
|
|
|
|
case IT_Z: |
|
|
|
|
return "boolean"; |
|
|
|
|
case IT_C: |
|
|
|
|
return "char"; |
|
|
|
|
case IT_B: |
|
|
|
|
return "byte"; |
|
|
|
|
case IT_S: |
|
|
|
|
return "short"; |
|
|
|
|
case IT_I: |
|
|
|
|
return "int"; |
|
|
|
|
default: |
|
|
|
|
StringBuffer sb = new StringBuffer("{"); |
|
|
|
|
String comma = ""; |
|
|
|
|
for (int i=0; i< NUM_TYPES; i++) |
|
|
|
|
if (((1<<i) & possTypes) != 0) { |
|
|
|
|
sb.append(comma).append(typeNames[i]); |
|
|
|
|
comma = ","; |
|
|
|
|
} |
|
|
|
|
sb.append("}"); |
|
|
|
|
return sb.toString(); |
|
|
|
|
} |
|
|
|
|
if (possTypes == hintTypes) { |
|
|
|
|
switch (possTypes) { |
|
|
|
|
case IT_Z: |
|
|
|
|
return "boolean"; |
|
|
|
|
case IT_C: |
|
|
|
|
return "char"; |
|
|
|
|
case IT_B: |
|
|
|
|
return "byte"; |
|
|
|
|
case IT_S: |
|
|
|
|
return "short"; |
|
|
|
|
case IT_I: |
|
|
|
|
return "int"; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
StringBuffer sb = new StringBuffer("{"); |
|
|
|
|
for (int i=0; i< NUM_TYPES; i++) { |
|
|
|
|
if (((1<<i) & possTypes) != 0) |
|
|
|
|
sb.append(typeNames[i]); |
|
|
|
|
} |
|
|
|
|
if (possTypes != hintTypes) { |
|
|
|
|
sb.append(":"); |
|
|
|
|
for (int i=0; i< NUM_TYPES; i++) { |
|
|
|
|
if (((1<<i) & hintTypes) != 0) |
|
|
|
|
sb.append(typeNames[i]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
sb.append("}"); |
|
|
|
|
return sb.toString(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -217,21 +242,26 @@ public class IntegerType extends Type { |
|
|
|
|
return this; |
|
|
|
|
|
|
|
|
|
int mergeTypes; |
|
|
|
|
int mergeHints = 0; |
|
|
|
|
if (type.typecode != TC_INTEGER) |
|
|
|
|
mergeTypes = 0; |
|
|
|
|
else { |
|
|
|
|
IntegerType other = (IntegerType) type; |
|
|
|
|
mergeTypes = possTypes & other.possTypes; |
|
|
|
|
/* HINTING XXX */ |
|
|
|
|
if (mergeTypes == possTypes) |
|
|
|
|
mergeHints = hintTypes & other.hintTypes; |
|
|
|
|
|
|
|
|
|
if (mergeTypes == possTypes |
|
|
|
|
&& mergeHints == hintTypes) |
|
|
|
|
return this; |
|
|
|
|
if (mergeTypes == other.possTypes) |
|
|
|
|
if (mergeTypes == other.possTypes |
|
|
|
|
&& mergeHints == other.hintTypes) |
|
|
|
|
return other; |
|
|
|
|
} |
|
|
|
|
Type result = mergeTypes == 0 ? tError : new IntegerType(mergeTypes); |
|
|
|
|
Type result = mergeTypes == 0 |
|
|
|
|
? tError : new IntegerType(mergeTypes, mergeHints); |
|
|
|
|
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_TYPES) != 0) { |
|
|
|
|
GlobalOptions.err.println("intersecting "+ this +" and "+ type + |
|
|
|
|
" to " + result); |
|
|
|
|
" to " + result); |
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
@ -239,8 +269,11 @@ public class IntegerType extends Type { |
|
|
|
|
public boolean equals(Object o) { |
|
|
|
|
if (o == this) |
|
|
|
|
return true; |
|
|
|
|
if (o instanceof IntegerType) |
|
|
|
|
return ((IntegerType)o).possTypes == possTypes; |
|
|
|
|
if (o instanceof IntegerType) { |
|
|
|
|
IntegerType other = (IntegerType)o; |
|
|
|
|
return other.possTypes == possTypes |
|
|
|
|
&& other.hintTypes == hintTypes; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|