1 package serp.bytecode; 2 3 import java.util.*; 4 5 import serp.bytecode.lowlevel.*; 6 import serp.util.*; 7 8 /*** 9 * Any typed instruction. 10 * 11 * @author Abe White 12 */ 13 public abstract class TypedInstruction extends Instruction { 14 private static final Set _opcodeTypes = new HashSet(); 15 static { 16 _opcodeTypes.add(int.class.getName()); 17 _opcodeTypes.add(long.class.getName()); 18 _opcodeTypes.add(float.class.getName()); 19 _opcodeTypes.add(double.class.getName()); 20 _opcodeTypes.add(Object.class.getName()); 21 _opcodeTypes.add(byte.class.getName()); 22 _opcodeTypes.add(char.class.getName()); 23 _opcodeTypes.add(short.class.getName()); 24 _opcodeTypes.add(boolean.class.getName()); 25 _opcodeTypes.add(void.class.getName()); 26 } 27 28 TypedInstruction(Code owner) { 29 super(owner); 30 } 31 32 TypedInstruction(Code owner, int opcode) { 33 super(owner, opcode); 34 } 35 36 /*** 37 * Return the type for the given name. Takes into account 38 * the given mappings and the demote flag. 39 * 40 * @param mappings mappings of one type to another; for example, 41 * array instruction treat booleans as ints, so 42 * to reflect that there should be an index x of the 43 * array such that mappings[x][0] = boolean.class and 44 * mappings[x][1] = int.class; may be null if no special mappings are needed 45 * @param demote if true, all object types will be demoted to Object.class 46 */ 47 String mapType(String type, Class[][] mappings, boolean demote) { 48 if (type == null) 49 return null; 50 51 type = getProject().getNameCache().getExternalForm(type, false); 52 if (!_opcodeTypes.contains(type) && demote) 53 type = Object.class.getName(); 54 55 if (mappings != null) 56 for (int i = 0; i < mappings.length; i++) 57 if (mappings[i][0].getName().equals(type)) 58 type = mappings[i][1].getName(); 59 return type; 60 } 61 62 /*** 63 * Return the type name for this instruction. 64 * If the type has not been set, this method will return null. 65 */ 66 public abstract String getTypeName(); 67 68 /*** 69 * Return the type for this instruction. 70 * If the type has not been set, this method will return null. 71 */ 72 public Class getType() { 73 String type = getTypeName(); 74 if (type == null) 75 return null; 76 return Strings.toClass(type, getClassLoader()); 77 } 78 79 /*** 80 * Return the type for this instruction. 81 * If the type has not been set, this method will return null. 82 */ 83 public BCClass getTypeBC() { 84 String type = getTypeName(); 85 if (type == null) 86 return null; 87 return getProject().loadClass(type, getClassLoader()); 88 } 89 90 /*** 91 * Set the type of this instruction. Types that have no direct 92 * support will be converted accordingly. 93 * 94 * @return this instruction, for method chaining 95 */ 96 public abstract TypedInstruction setType(String type); 97 98 /*** 99 * Set the type of this instruction. Types that have no direct 100 * support will be converted accordingly. 101 * 102 * @return this instruction, for method chaining 103 */ 104 public TypedInstruction setType(Class type) { 105 if (type == null) 106 return setType((String) null); 107 return setType(type.getName()); 108 } 109 110 /*** 111 * Set the type of this instruction. Types that have no direct 112 * support will be converted accordingly. 113 * 114 * @return this instruction, for method chaining 115 */ 116 public TypedInstruction setType(BCClass type) { 117 if (type == null) 118 return setType((String) null); 119 return setType(type.getName()); 120 } 121 }