Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

InstructionFactory.java

00001 package de.fub.bytecode.generic;
00002 
00003 import de.fub.bytecode.Constants;
00004 
00005 /** 
00006  * Instances of this class may be used, e.g., to generate typed
00007  * versions of instructions.  Its main purpose is to be used as the
00008  * byte code generating backend of a compiler. You can subclass it to
00009  * add your own create methods.
00010  *
00011  * @version $Id: InstructionFactory.java,v 1.1.1.1 2002/01/24 03:44:05 pserver Exp $
00012  * @author <A HREF="http://www.inf.fu-berlin.de/~dahm">M. Dahm</A>
00013  */
00014 public class InstructionFactory implements InstructionConstants {
00015   protected ClassGen        cg;
00016   protected ConstantPoolGen cp;
00017 
00018   /** Need a ClassGen object to obtain a constant pool, e.g.
00019    */
00020   public InstructionFactory(ClassGen cg) {
00021     this.cg = cg;
00022     cp = cg.getConstantPool();
00023   }  
00024   /**
00025    * @param type type of elements of array, i.e. array.getElementType()
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    * @param type type of elements of array, i.e. array.getElementType()
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    * Create binary operation for simple basic types, such as int and float.
00112    *
00113    * @param op operation, such as "+", "*", "<<", etc.
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   /** Create conversion operation for two stack operands, this may be an I2C, instruction, e.g.,
00130    * if the operands are basic types and CHECKCAST if they are reference types.
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    * @param size size of operand, either 1 (int, e.g.) or 2 (double)
00171    */
00172   public static StackInstruction createDup(int size) {
00173     return (size == 2)? (StackInstruction)DUP2 :
00174       (StackInstruction)DUP;
00175   }  
00176   /**
00177    * @param size size of operand, either 1 (int, e.g.) or 2 (double)
00178    */
00179   public static StackInstruction createDup_1(int size) {
00180     return (size == 2)? (StackInstruction)DUP2_X1 :
00181       (StackInstruction)DUP_X1;
00182   }  
00183   /**
00184    * @param size size of operand, either 1 (int, e.g.) or 2 (double)
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   /** Create an invoke instruction.
00197    *
00198    * @param class_name name of the called class
00199    * @param name name of the called method
00200    * @param ret_type return type of method
00201    * @param arg_types argument types of method
00202    * @param kind how to invoke, i.e. INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL,
00203    * or INVOKESPECIAL
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++) // Count size of arguments
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    * @param index index of local variable
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   /** Create new array of given size and type.
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   /*public AllocationInstruction createNewArray(ArrayType t, short dim) {
00274 if(dim == 1)
00275 return createNewArray(t.getElementType());
00276 else
00277 return new MULTIANEWARRAY(cp.addArrayClass(t), dim);
00278 }
00279   public AllocationInstruction createNewArray(Type t, short dim) {
00280     return createNewArray(new ArrayType(t, dim));
00281   }
00282   public AllocationInstruction createNewArray(ArrayType t) {
00283     int dim = t.getDimensions();
00284 
00285     if(dim == 1) {
00286       Type type = t.getBasicType();
00287 
00288       if(type instanceof ObjectType)
00289     return new ANEWARRAY(cp.addClass((ObjectType)type));
00290       else
00291     return new NEWARRAY(((BasicType)type).getType());
00292     } else
00293       return new MULTIANEWARRAY(cp.addArrayClass(t), (short)dim);
00294       }*/
00295  
00296   /** Create "null" value for reference types, 0 for basic types like int
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    * @param size size of operand, either 1 (int, e.g.) or 2 (double)
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   /** Create typed return
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    * @param index index of local variable
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   /** Create reference to `this'
00368    */
00369   public static Instruction createThis() {
00370     return new ALOAD(0);
00371   }  
00372 }

Generated at Thu Feb 7 06:47:39 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001