00001 package de.fub.bytecode.generic;
00002
00003 import de.fub.bytecode.Constants;
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 public class InstructionFactory implements InstructionConstants {
00015 protected ClassGen cg;
00016 protected ConstantPoolGen cp;
00017
00018
00019
00020 public InstructionFactory(ClassGen cg) {
00021 this.cg = cg;
00022 cp = cg.getConstantPool();
00023 }
00024
00025
00026
00027 public static ArrayInstruction createArrayLoad(Type type) {
00028 switch(type.getType()) {
00029 case Constants.T_BOOLEAN:
00030 case Constants.T_BYTE: return BALOAD;
00031 case Constants.T_CHAR: return CALOAD;
00032 case Constants.T_SHORT: return SALOAD;
00033 case Constants.T_INT: return IALOAD;
00034 case Constants.T_FLOAT: return FALOAD;
00035 case Constants.T_DOUBLE: return DALOAD;
00036 case Constants.T_LONG: return LALOAD;
00037 case Constants.T_ARRAY:
00038 case Constants.T_OBJECT: return AALOAD;
00039 default: throw new RuntimeException("Invalid type " + type);
00040 }
00041 }
00042
00043
00044
00045 public static ArrayInstruction createArrayStore(Type type) {
00046 switch(type.getType()) {
00047 case Constants.T_BOOLEAN:
00048 case Constants.T_BYTE: return BASTORE;
00049 case Constants.T_CHAR: return CASTORE;
00050 case Constants.T_SHORT: return SASTORE;
00051 case Constants.T_INT: return IASTORE;
00052 case Constants.T_FLOAT: return FASTORE;
00053 case Constants.T_DOUBLE: return DASTORE;
00054 case Constants.T_LONG: return LASTORE;
00055 case Constants.T_ARRAY:
00056 case Constants.T_OBJECT: return AASTORE;
00057 default: throw new RuntimeException("Invalid type " + type);
00058 }
00059 }
00060 private static final ArithmeticInstruction createBinaryDoubleOp(char op) {
00061 switch(op) {
00062 case '-' : return DSUB;
00063 case '+' : return DADD;
00064 case '*' : return DMUL;
00065 case '/' : return DDIV;
00066 default: throw new RuntimeException("Invalid operand " + op);
00067 }
00068 }
00069 private static final ArithmeticInstruction createBinaryFloatOp(char op) {
00070 switch(op) {
00071 case '-' : return FSUB;
00072 case '+' : return FADD;
00073 case '*' : return FMUL;
00074 case '/' : return FDIV;
00075 default: throw new RuntimeException("Invalid operand " + op);
00076 }
00077 }
00078 private static final ArithmeticInstruction createBinaryIntOp(char first, String op) {
00079 switch(first) {
00080 case '-' : return ISUB;
00081 case '+' : return IADD;
00082 case '%' : return IREM;
00083 case '*' : return IMUL;
00084 case '/' : return IDIV;
00085 case '&' : return IAND;
00086 case '|' : return IOR;
00087 case '^' : return IXOR;
00088 case '<' : return ISHL;
00089 case '>' : return op.equals(">>>")? (ArithmeticInstruction)IUSHR :
00090 (ArithmeticInstruction)ISHR;
00091 default: throw new RuntimeException("Invalid operand " + op);
00092 }
00093 }
00094 private static final ArithmeticInstruction createBinaryLongOp(char first, String op) {
00095 switch(first) {
00096 case '-' : return LSUB;
00097 case '+' : return LADD;
00098 case '%' : return LREM;
00099 case '*' : return LMUL;
00100 case '/' : return LDIV;
00101 case '&' : return LAND;
00102 case '|' : return LOR;
00103 case '^' : return LXOR;
00104 case '<' : return LSHL;
00105 case '>' : return op.equals(">>>")? (ArithmeticInstruction)LUSHR :
00106 (ArithmeticInstruction)LSHR;
00107 default: throw new RuntimeException("Invalid operand " + op);
00108 }
00109 }
00110
00111
00112
00113
00114
00115 public static ArithmeticInstruction createBinaryOperation(String op, Type type) {
00116 char first = op.toCharArray()[0];
00117
00118 switch(type.getType()) {
00119 case Constants.T_BYTE:
00120 case Constants.T_SHORT:
00121 case Constants.T_INT:
00122 case Constants.T_CHAR: return createBinaryIntOp(first, op);
00123 case Constants.T_LONG: return createBinaryLongOp(first, op);
00124 case Constants.T_FLOAT: return createBinaryFloatOp(first);
00125 case Constants.T_DOUBLE: return createBinaryDoubleOp(first);
00126 default: throw new RuntimeException("Invalid type " + type);
00127 }
00128 }
00129
00130
00131
00132 public Instruction createCast(Type src_type, Type dest_type) {
00133 if((src_type instanceof BasicType) && (dest_type instanceof BasicType)) {
00134 byte dest = dest_type.getType();
00135 byte src = src_type.getType();
00136
00137 if(dest == Constants.T_LONG && (src == Constants.T_CHAR || src == Constants.T_BYTE ||
00138 src == Constants.T_SHORT))
00139 src = Constants.T_INT;
00140
00141 String[] short_names = { "C", "F", "D", "B", "S", "I", "L" };
00142
00143 String name = "de.fub.bytecode.generic." + short_names[src - Constants.T_CHAR] +
00144 "2" + short_names[dest - Constants.T_CHAR];
00145
00146 Instruction i = null;
00147 try {
00148 i = (Instruction)java.lang.Class.forName(name).newInstance();
00149 } catch(Exception e) {
00150 throw new RuntimeException("Could not find instruction: " + name);
00151 }
00152
00153 return i;
00154 } else if((src_type instanceof ReferenceType) && (dest_type instanceof ReferenceType)) {
00155 if(dest_type instanceof ArrayType)
00156 return new CHECKCAST(cp.addArrayClass((ArrayType)dest_type));
00157 else
00158 return new CHECKCAST(cp.addClass(((ObjectType)dest_type).getClassName()));
00159 }
00160 else
00161 throw new RuntimeException("Can not cast " + src_type + " to " + dest_type);
00162 }
00163 public CHECKCAST createCheckCast(ReferenceType t) {
00164 if(t instanceof ArrayType)
00165 return new CHECKCAST(cp.addArrayClass((ArrayType)t));
00166 else
00167 return new CHECKCAST(cp.addClass((ObjectType)t));
00168 }
00169
00170
00171
00172 public static StackInstruction createDup(int size) {
00173 return (size == 2)? (StackInstruction)DUP2 :
00174 (StackInstruction)DUP;
00175 }
00176
00177
00178
00179 public static StackInstruction createDup_1(int size) {
00180 return (size == 2)? (StackInstruction)DUP2_X1 :
00181 (StackInstruction)DUP_X1;
00182 }
00183
00184
00185
00186 public static StackInstruction createDup_2(int size) {
00187 return (size == 2)? (StackInstruction)DUP2_X2 :
00188 (StackInstruction)DUP_X2;
00189 }
00190 public GETFIELD createGetField(String class_name, String name, Type t) {
00191 return new GETFIELD(cp.addFieldref(class_name, name, t.getSignature()));
00192 }
00193 public GETSTATIC createGetStatic(String class_name, String name, Type t) {
00194 return new GETSTATIC(cp.addFieldref(class_name, name, t.getSignature()));
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 public InvokeInstruction createInvoke(String class_name, String name, Type ret_type,
00206 Type[] arg_types, short kind) {
00207 int index;
00208 int nargs = 0;
00209 String signature = Type.getMethodSignature(ret_type, arg_types);
00210
00211 for(int i=0; i < arg_types.length; i++)
00212 nargs += arg_types[i].getSize();
00213
00214 if(kind == Constants.INVOKEINTERFACE)
00215 index = cp.addInterfaceMethodref(class_name, name, signature);
00216 else
00217 index = cp.addMethodref(class_name, name, signature);
00218
00219 switch(kind) {
00220 case Constants.INVOKESPECIAL: return new INVOKESPECIAL(index);
00221 case Constants.INVOKEVIRTUAL: return new INVOKEVIRTUAL(index);
00222 case Constants.INVOKESTATIC: return new INVOKESTATIC(index);
00223 case Constants.INVOKEINTERFACE: return new INVOKEINTERFACE(index, nargs + 1);
00224 default:
00225 throw new RuntimeException("Oops: Unknown invoke kind:" + kind);
00226 }
00227 }
00228
00229
00230
00231 public static LocalVariableInstruction createLoad(Type type, int index) {
00232 switch(type.getType()) {
00233 case Constants.T_BOOLEAN:
00234 case Constants.T_CHAR:
00235 case Constants.T_BYTE:
00236 case Constants.T_SHORT:
00237 case Constants.T_INT: return new ILOAD(index);
00238 case Constants.T_FLOAT: return new FLOAD(index);
00239 case Constants.T_DOUBLE: return new DLOAD(index);
00240 case Constants.T_LONG: return new LLOAD(index);
00241 case Constants.T_ARRAY:
00242 case Constants.T_OBJECT: return new ALOAD(index);
00243 default: throw new RuntimeException("Invalid type " + type);
00244 }
00245 }
00246 public NEW createNew(ObjectType t) {
00247 return new NEW(cp.addClass(t));
00248 }
00249 public NEW createNew(String s) {
00250 return createNew(new ObjectType(s));
00251 }
00252
00253
00254 public AllocationInstruction createNewArray(Type t, short dim) {
00255 if(dim == 1) {
00256 if(t instanceof ObjectType)
00257 return new ANEWARRAY(cp.addClass((ObjectType)t));
00258 else if(t instanceof ArrayType)
00259 return new ANEWARRAY(cp.addArrayClass((ArrayType)t));
00260 else
00261 return new NEWARRAY(((BasicType)t).getType());
00262 } else {
00263 ArrayType at;
00264
00265 if(t instanceof ArrayType)
00266 at = (ArrayType)t;
00267 else
00268 at = new ArrayType(t, dim);
00269
00270 return new MULTIANEWARRAY(cp.addArrayClass(at), dim);
00271 }
00272 }
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 public static Instruction createNull(Type type) {
00299 switch(type.getType()) {
00300 case Constants.T_ARRAY:
00301 case Constants.T_OBJECT: return ACONST_NULL;
00302 case Constants.T_INT:
00303 case Constants.T_SHORT:
00304 case Constants.T_BOOLEAN:
00305 case Constants.T_CHAR:
00306 case Constants.T_BYTE: return ICONST_0;
00307 case Constants.T_FLOAT: return FCONST_0;
00308 case Constants.T_DOUBLE: return DCONST_0;
00309 case Constants.T_LONG: return LCONST_0;
00310 case Constants.T_VOID: return NOP;
00311
00312 default:
00313 throw new RuntimeException("Invalid type: " + type);
00314 }
00315 }
00316
00317
00318
00319 public static StackInstruction createPop(int size) {
00320 return (size == 2)? (StackInstruction)POP2 :
00321 (StackInstruction)POP;
00322 }
00323 public PUTFIELD createPutField(String class_name, String name, Type t) {
00324 return new PUTFIELD(cp.addFieldref(class_name, name, t.getSignature()));
00325 }
00326 public PUTSTATIC createPutStatic(String class_name, String name, Type t) {
00327 return new PUTSTATIC(cp.addFieldref(class_name, name, t.getSignature()));
00328 }
00329
00330
00331 public static ReturnInstruction createReturn(Type type) {
00332 switch(type.getType()) {
00333 case Constants.T_ARRAY:
00334 case Constants.T_OBJECT: return ARETURN;
00335 case Constants.T_INT:
00336 case Constants.T_SHORT:
00337 case Constants.T_BOOLEAN:
00338 case Constants.T_CHAR:
00339 case Constants.T_BYTE: return IRETURN;
00340 case Constants.T_FLOAT: return FRETURN;
00341 case Constants.T_DOUBLE: return DRETURN;
00342 case Constants.T_LONG: return LRETURN;
00343 case Constants.T_VOID: return RETURN;
00344
00345 default:
00346 throw new RuntimeException("Invalid type: " + type);
00347 }
00348 }
00349
00350
00351
00352 public static LocalVariableInstruction createStore(Type type, int index) {
00353 switch(type.getType()) {
00354 case Constants.T_BOOLEAN:
00355 case Constants.T_CHAR:
00356 case Constants.T_BYTE:
00357 case Constants.T_SHORT:
00358 case Constants.T_INT: return new ISTORE(index);
00359 case Constants.T_FLOAT: return new FSTORE(index);
00360 case Constants.T_DOUBLE: return new DSTORE(index);
00361 case Constants.T_LONG: return new LSTORE(index);
00362 case Constants.T_ARRAY:
00363 case Constants.T_OBJECT: return new ASTORE(index);
00364 default: throw new RuntimeException("Invalid type " + type);
00365 }
00366 }
00367
00368
00369 public static Instruction createThis() {
00370 return new ALOAD(0);
00371 }
00372 }