FileDocCategorySizeDatePackage
InstructionFactory.javaAPI DocJava SE 6 API22340Tue Jun 10 00:22:20 BST 2008com.sun.org.apache.bcel.internal.generic

InstructionFactory

public class InstructionFactory extends Object implements InstructionConstants, Serializable
Instances of this class may be used, e.g., to generate typed versions of instructions. Its main purpose is to be used as the byte code generating backend of a compiler. You can subclass it to add your own create methods.
version
$Id: InstructionFactory.java,v 1.1.2.1 2005/07/31 23:45:04 jeffsuttor Exp $
author
M. Dahm
see
Constants

Fields Summary
protected ClassGen
cg
protected ConstantPoolGen
cp
private static MethodObject[]
append_mos
Constructors Summary
public InstructionFactory(ClassGen cg, ConstantPoolGen cp)

    this.cg = cg;
    this.cp = cp;
  
public InstructionFactory(ClassGen cg)
Initialize with ClassGen object

    this(cg, cg.getConstantPool());
  
public InstructionFactory(ConstantPoolGen cp)
Initialize just with ConstantPoolGen object

    this(null, cp);
  
Methods Summary
public com.sun.org.apache.bcel.internal.generic.InstructioncreateAppend(com.sun.org.apache.bcel.internal.generic.Type type)

    byte t = type.getType();

    if(isString(type))
      return createInvoke(append_mos[0], Constants.INVOKEVIRTUAL);

    switch(t) {
    case Constants.T_BOOLEAN:
    case Constants.T_CHAR: 
    case Constants.T_FLOAT:
    case Constants.T_DOUBLE:
    case Constants.T_BYTE:
    case Constants.T_SHORT:
    case Constants.T_INT:
    case Constants.T_LONG
      :   return createInvoke(append_mos[t], Constants.INVOKEVIRTUAL);
    case Constants.T_ARRAY:
    case Constants.T_OBJECT:
      return createInvoke(append_mos[1], Constants.INVOKEVIRTUAL);
    default:
      throw new RuntimeException("Oops: No append for this type? " + type);
    }
  
public static com.sun.org.apache.bcel.internal.generic.ArrayInstructioncreateArrayLoad(com.sun.org.apache.bcel.internal.generic.Type type)

param
type type of elements of array, i.e., array.getElementType()

    switch(type.getType()) {
    case Constants.T_BOOLEAN:
    case Constants.T_BYTE:   return BALOAD;
    case Constants.T_CHAR:   return CALOAD;
    case Constants.T_SHORT:  return SALOAD;
    case Constants.T_INT:    return IALOAD;
    case Constants.T_FLOAT:  return FALOAD;
    case Constants.T_DOUBLE: return DALOAD;
    case Constants.T_LONG:   return LALOAD;
    case Constants.T_ARRAY:
    case Constants.T_OBJECT: return AALOAD;
    default:       throw new RuntimeException("Invalid type " + type);
    }
  
public static com.sun.org.apache.bcel.internal.generic.ArrayInstructioncreateArrayStore(com.sun.org.apache.bcel.internal.generic.Type type)

param
type type of elements of array, i.e., array.getElementType()

    switch(type.getType()) {
    case Constants.T_BOOLEAN:
    case Constants.T_BYTE:   return BASTORE;
    case Constants.T_CHAR:   return CASTORE;
    case Constants.T_SHORT:  return SASTORE;
    case Constants.T_INT:    return IASTORE;
    case Constants.T_FLOAT:  return FASTORE;
    case Constants.T_DOUBLE: return DASTORE;
    case Constants.T_LONG:   return LASTORE;
    case Constants.T_ARRAY:
    case Constants.T_OBJECT: return AASTORE;
    default:       throw new RuntimeException("Invalid type " + type);
    }
  
private static final com.sun.org.apache.bcel.internal.generic.ArithmeticInstructioncreateBinaryDoubleOp(char op)

    switch(op) {
    case '-" : return DSUB;
    case '+" : return DADD;
    case '*" : return DMUL;
    case '/" : return DDIV;
    default: throw new RuntimeException("Invalid operand " + op);
    }
  
private static final com.sun.org.apache.bcel.internal.generic.ArithmeticInstructioncreateBinaryFloatOp(char op)

    switch(op) {
    case '-" : return FSUB;
    case '+" : return FADD;
    case '*" : return FMUL;
    case '/" : return FDIV;
    default: throw new RuntimeException("Invalid operand " + op);
    }
  
private static final com.sun.org.apache.bcel.internal.generic.ArithmeticInstructioncreateBinaryIntOp(char first, java.lang.String op)

    switch(first) {
    case '-" : return ISUB;
    case '+" : return IADD;
    case '%" : return IREM;
    case '*" : return IMUL;
    case '/" : return IDIV;
    case '&" : return IAND;
    case '|" : return IOR;
    case '^" : return IXOR;
    case '<" : return ISHL;
    case '>" : return op.equals(">>>")? (ArithmeticInstruction)IUSHR :
      (ArithmeticInstruction)ISHR;
    default: throw new RuntimeException("Invalid operand " + op);
    }
  
private static final com.sun.org.apache.bcel.internal.generic.ArithmeticInstructioncreateBinaryLongOp(char first, java.lang.String op)

    switch(first) {
    case '-" : return LSUB;
    case '+" : return LADD;
    case '%" : return LREM;
    case '*" : return LMUL;
    case '/" : return LDIV;
    case '&" : return LAND;
    case '|" : return LOR;
    case '^" : return LXOR;
    case '<" : return LSHL;
    case '>" : return op.equals(">>>")? (ArithmeticInstruction)LUSHR :
      (ArithmeticInstruction)LSHR;
    default: throw new RuntimeException("Invalid operand " + op);
    }
  
public static com.sun.org.apache.bcel.internal.generic.ArithmeticInstructioncreateBinaryOperation(java.lang.String op, com.sun.org.apache.bcel.internal.generic.Type type)
Create binary operation for simple basic types, such as int and float.

param
op operation, such as "+", "*", "<<", etc.

    char first = op.toCharArray()[0];

    switch(type.getType()) {
    case Constants.T_BYTE:
    case Constants.T_SHORT:
    case Constants.T_INT:
    case Constants.T_CHAR:    return createBinaryIntOp(first, op);
    case Constants.T_LONG:    return createBinaryLongOp(first, op);
    case Constants.T_FLOAT:   return createBinaryFloatOp(first);
    case Constants.T_DOUBLE:  return createBinaryDoubleOp(first);
    default:        throw new RuntimeException("Invalid type " + type);
    }
  
public static com.sun.org.apache.bcel.internal.generic.BranchInstructioncreateBranchInstruction(short opcode, com.sun.org.apache.bcel.internal.generic.InstructionHandle target)
Create branch instruction by given opcode, except LOOKUPSWITCH and TABLESWITCH. For those you should use the SWITCH compound instruction.

    switch(opcode) {
    case Constants.IFEQ:      return new IFEQ(target);
    case Constants.IFNE:      return new IFNE(target);
    case Constants.IFLT:      return new IFLT(target);
    case Constants.IFGE:      return new IFGE(target);
    case Constants.IFGT:      return new IFGT(target);
    case Constants.IFLE:      return new IFLE(target);
    case Constants.IF_ICMPEQ: return new IF_ICMPEQ(target);
    case Constants.IF_ICMPNE: return new IF_ICMPNE(target);
    case Constants.IF_ICMPLT: return new IF_ICMPLT(target);
    case Constants.IF_ICMPGE: return new IF_ICMPGE(target);
    case Constants.IF_ICMPGT: return new IF_ICMPGT(target);
    case Constants.IF_ICMPLE: return new IF_ICMPLE(target);
    case Constants.IF_ACMPEQ: return new IF_ACMPEQ(target);
    case Constants.IF_ACMPNE: return new IF_ACMPNE(target);
    case Constants.GOTO:      return new GOTO(target);
    case Constants.JSR:       return new JSR(target);
    case Constants.IFNULL:    return new IFNULL(target);
    case Constants.IFNONNULL: return new IFNONNULL(target);
    case Constants.GOTO_W:    return new GOTO_W(target);
    case Constants.JSR_W:     return new JSR_W(target);
    default:
	throw new RuntimeException("Invalid opcode: " + opcode);
    }
  
public com.sun.org.apache.bcel.internal.generic.InstructioncreateCast(com.sun.org.apache.bcel.internal.generic.Type src_type, com.sun.org.apache.bcel.internal.generic.Type dest_type)
Create conversion operation for two stack operands, this may be an I2C, instruction, e.g., if the operands are basic types and CHECKCAST if they are reference types.

    if((src_type instanceof BasicType) && (dest_type instanceof BasicType)) {
      byte dest = dest_type.getType();
      byte src  = src_type.getType();

      if(dest == Constants.T_LONG && (src == Constants.T_CHAR || src == Constants.T_BYTE ||
				      src == Constants.T_SHORT))
	src = Constants.T_INT;

      String[] short_names = { "C", "F", "D", "B", "S", "I", "L" };

      String name = "com.sun.org.apache.bcel.internal.generic." + short_names[src - Constants.T_CHAR] +
	"2" + short_names[dest - Constants.T_CHAR];
      
      Instruction i = null;
      try {
	i = (Instruction)java.lang.Class.forName(name).newInstance();
      } catch(Exception e) {
	throw new RuntimeException("Could not find instruction: " + name);
      }

      return i;
    } else if((src_type instanceof ReferenceType) && (dest_type instanceof ReferenceType)) {
      if(dest_type instanceof ArrayType)
	return new CHECKCAST(cp.addArrayClass((ArrayType)dest_type));
      else
	return new CHECKCAST(cp.addClass(((ObjectType)dest_type).getClassName()));
    }
    else
      throw new RuntimeException("Can not cast " + src_type + " to " + dest_type);
  
public com.sun.org.apache.bcel.internal.generic.CHECKCASTcreateCheckCast(com.sun.org.apache.bcel.internal.generic.ReferenceType t)

    if(t instanceof ArrayType)
      return new CHECKCAST(cp.addArrayClass((ArrayType)t));
    else
      return new CHECKCAST(cp.addClass((ObjectType)t));
  
public com.sun.org.apache.bcel.internal.generic.InstructioncreateConstant(java.lang.Object value)
Uses PUSH to push a constant value onto the stack.

param
value must be of type Number, Boolean, Character or String

    PUSH push;

    if(value instanceof Number)
      push = new PUSH(cp, (Number)value);
    else if(value instanceof String)
      push = new PUSH(cp, (String)value);
    else if(value instanceof Boolean)
      push = new PUSH(cp, (Boolean)value);
    else if(value instanceof Character)
      push = new PUSH(cp, (Character)value);
    else
      throw new ClassGenException("Illegal type: " + value.getClass());

    return push.getInstruction();
  
public static com.sun.org.apache.bcel.internal.generic.StackInstructioncreateDup(int size)

param
size size of operand, either 1 (int, e.g.) or 2 (double)

    return (size == 2)? (StackInstruction)DUP2 :
      (StackInstruction)DUP;
  
public static com.sun.org.apache.bcel.internal.generic.StackInstructioncreateDup_1(int size)

param
size size of operand, either 1 (int, e.g.) or 2 (double)

    return (size == 2)? (StackInstruction)DUP2_X1 :
      (StackInstruction)DUP_X1;
  
public static com.sun.org.apache.bcel.internal.generic.StackInstructioncreateDup_2(int size)

param
size size of operand, either 1 (int, e.g.) or 2 (double)

    return (size == 2)? (StackInstruction)DUP2_X2 :
      (StackInstruction)DUP_X2;
  
public com.sun.org.apache.bcel.internal.generic.FieldInstructioncreateFieldAccess(java.lang.String class_name, java.lang.String name, com.sun.org.apache.bcel.internal.generic.Type type, short kind)
Create a field instruction.

param
class_name name of the accessed class
param
name name of the referenced field
param
type type of field
param
kind how to access, i.e., GETFIELD, PUTFIELD, GETSTATIC, PUTSTATIC
see
Constants

    int    index;
    String signature  = type.getSignature();

    index = cp.addFieldref(class_name, name, signature);

    switch(kind) {
    case Constants.GETFIELD:  return new GETFIELD(index);
    case Constants.PUTFIELD:  return new PUTFIELD(index);
    case Constants.GETSTATIC: return new GETSTATIC(index);
    case Constants.PUTSTATIC: return new PUTSTATIC(index);

    default:
      throw new RuntimeException("Oops: Unknown getfield kind:" + kind);
    }
  
public com.sun.org.apache.bcel.internal.generic.GETFIELDcreateGetField(java.lang.String class_name, java.lang.String name, com.sun.org.apache.bcel.internal.generic.Type t)

    return new GETFIELD(cp.addFieldref(class_name, name, t.getSignature()));
  
public com.sun.org.apache.bcel.internal.generic.GETSTATICcreateGetStatic(java.lang.String class_name, java.lang.String name, com.sun.org.apache.bcel.internal.generic.Type t)

    return new GETSTATIC(cp.addFieldref(class_name, name, t.getSignature()));
  
public com.sun.org.apache.bcel.internal.generic.INSTANCEOFcreateInstanceOf(com.sun.org.apache.bcel.internal.generic.ReferenceType t)

    if(t instanceof ArrayType)
      return new INSTANCEOF(cp.addArrayClass((ArrayType)t));
    else
      return new INSTANCEOF(cp.addClass((ObjectType)t));
  
public com.sun.org.apache.bcel.internal.generic.InvokeInstructioncreateInvoke(java.lang.String class_name, java.lang.String name, com.sun.org.apache.bcel.internal.generic.Type ret_type, com.sun.org.apache.bcel.internal.generic.Type[] arg_types, short kind)
Create an invoke instruction.

param
class_name name of the called class
param
name name of the called method
param
ret_type return type of method
param
arg_types argument types of method
param
kind how to invoke, i.e., INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL, or INVOKESPECIAL
see
Constants

    int    index;
    int    nargs      = 0;
    String signature  = Type.getMethodSignature(ret_type, arg_types);

    for(int i=0; i < arg_types.length; i++) // Count size of arguments
      nargs += arg_types[i].getSize();

    if(kind == Constants.INVOKEINTERFACE)
      index = cp.addInterfaceMethodref(class_name, name, signature);
    else
      index = cp.addMethodref(class_name, name, signature);

    switch(kind) {
    case Constants.INVOKESPECIAL:   return new INVOKESPECIAL(index);
    case Constants.INVOKEVIRTUAL:   return new INVOKEVIRTUAL(index);
    case Constants.INVOKESTATIC:    return new INVOKESTATIC(index);
    case Constants.INVOKEINTERFACE: return new INVOKEINTERFACE(index, nargs + 1);
    default:
      throw new RuntimeException("Oops: Unknown invoke kind:" + kind);
    }
  
private com.sun.org.apache.bcel.internal.generic.InvokeInstructioncreateInvoke(com.sun.org.apache.bcel.internal.generic.InstructionFactory$MethodObject m, short kind)

    return createInvoke(m.class_name, m.name, m.result_type, m.arg_types, kind);
  
public static com.sun.org.apache.bcel.internal.generic.LocalVariableInstructioncreateLoad(com.sun.org.apache.bcel.internal.generic.Type type, int index)

param
index index of local variable

    switch(type.getType()) {
    case Constants.T_BOOLEAN:
    case Constants.T_CHAR:
    case Constants.T_BYTE:
    case Constants.T_SHORT:
    case Constants.T_INT:    return new ILOAD(index);
    case Constants.T_FLOAT:  return new FLOAD(index);
    case Constants.T_DOUBLE: return new DLOAD(index);
    case Constants.T_LONG:   return new LLOAD(index);
    case Constants.T_ARRAY:
    case Constants.T_OBJECT: return new ALOAD(index);
    default:       throw new RuntimeException("Invalid type " + type);
    }
  
public com.sun.org.apache.bcel.internal.generic.NEWcreateNew(com.sun.org.apache.bcel.internal.generic.ObjectType t)

    return new NEW(cp.addClass(t));
  
public com.sun.org.apache.bcel.internal.generic.NEWcreateNew(java.lang.String s)

    return createNew(new ObjectType(s));
  
public com.sun.org.apache.bcel.internal.generic.InstructioncreateNewArray(com.sun.org.apache.bcel.internal.generic.Type t, short dim)
Create new array of given size and type.

return
an instruction that creates the corresponding array at runtime, i.e. is an AllocationInstruction

    if(dim == 1) {
      if(t instanceof ObjectType)
	return new ANEWARRAY(cp.addClass((ObjectType)t));
      else if(t instanceof ArrayType)
	return new ANEWARRAY(cp.addArrayClass((ArrayType)t));
      else
	return new NEWARRAY(((BasicType)t).getType());
    } else {
      ArrayType at;

      if(t instanceof ArrayType)
	at = (ArrayType)t;
      else
	at = new ArrayType(t, dim);

      return new MULTIANEWARRAY(cp.addArrayClass(at), dim);
    }
  
public static com.sun.org.apache.bcel.internal.generic.InstructioncreateNull(com.sun.org.apache.bcel.internal.generic.Type type)
Create "null" value for reference types, 0 for basic types like int

    switch(type.getType()) {
    case Constants.T_ARRAY:
    case Constants.T_OBJECT:  return ACONST_NULL;
    case Constants.T_INT:
    case Constants.T_SHORT:
    case Constants.T_BOOLEAN:
    case Constants.T_CHAR: 
    case Constants.T_BYTE:    return ICONST_0;
    case Constants.T_FLOAT:   return FCONST_0;
    case Constants.T_DOUBLE:  return DCONST_0;
    case Constants.T_LONG:    return LCONST_0;
    case Constants.T_VOID:    return NOP;

    default:
      throw new RuntimeException("Invalid type: " + type);
    }
  
public static com.sun.org.apache.bcel.internal.generic.StackInstructioncreatePop(int size)

param
size size of operand, either 1 (int, e.g.) or 2 (double)

    return (size == 2)? (StackInstruction)POP2 :
      (StackInstruction)POP;
  
public com.sun.org.apache.bcel.internal.generic.InstructionListcreatePrintln(java.lang.String s)
Create a call to the most popular System.out.println() method.

param
s the string to print

    InstructionList il      = new InstructionList();
    int             out     = cp.addFieldref("java.lang.System", "out",
					     "Ljava/io/PrintStream;");
    int             println = cp.addMethodref("java.io.PrintStream", "println",
					      "(Ljava/lang/String;)V");

    il.append(new GETSTATIC(out));
    il.append(new PUSH(cp, s));
    il.append(new INVOKEVIRTUAL(println));

    return il;
  
public com.sun.org.apache.bcel.internal.generic.PUTFIELDcreatePutField(java.lang.String class_name, java.lang.String name, com.sun.org.apache.bcel.internal.generic.Type t)

    return new PUTFIELD(cp.addFieldref(class_name, name, t.getSignature()));
  
public com.sun.org.apache.bcel.internal.generic.PUTSTATICcreatePutStatic(java.lang.String class_name, java.lang.String name, com.sun.org.apache.bcel.internal.generic.Type t)

    return new PUTSTATIC(cp.addFieldref(class_name, name, t.getSignature()));
  
public static com.sun.org.apache.bcel.internal.generic.ReturnInstructioncreateReturn(com.sun.org.apache.bcel.internal.generic.Type type)
Create typed return

    switch(type.getType()) {
    case Constants.T_ARRAY:
    case Constants.T_OBJECT:  return ARETURN;
    case Constants.T_INT:
    case Constants.T_SHORT:
    case Constants.T_BOOLEAN:
    case Constants.T_CHAR: 
    case Constants.T_BYTE:    return IRETURN;
    case Constants.T_FLOAT:   return FRETURN;
    case Constants.T_DOUBLE:  return DRETURN;
    case Constants.T_LONG:    return LRETURN;
    case Constants.T_VOID:    return RETURN;

    default:
      throw new RuntimeException("Invalid type: " + type);
    }
  
public static com.sun.org.apache.bcel.internal.generic.LocalVariableInstructioncreateStore(com.sun.org.apache.bcel.internal.generic.Type type, int index)

param
index index of local variable

    switch(type.getType()) {
    case Constants.T_BOOLEAN:
    case Constants.T_CHAR:
    case Constants.T_BYTE:
    case Constants.T_SHORT:
    case Constants.T_INT:    return new ISTORE(index);
    case Constants.T_FLOAT:  return new FSTORE(index);
    case Constants.T_DOUBLE: return new DSTORE(index);
    case Constants.T_LONG:   return new LSTORE(index);
    case Constants.T_ARRAY:
    case Constants.T_OBJECT: return new ASTORE(index);
    default:       throw new RuntimeException("Invalid type " + type);
    }
  
public static com.sun.org.apache.bcel.internal.generic.InstructioncreateThis()
Create reference to `this'

    return new ALOAD(0);
  
public com.sun.org.apache.bcel.internal.generic.ClassGengetClassGen()

 return cg; 
public com.sun.org.apache.bcel.internal.generic.ConstantPoolGengetConstantPool()

 return cp; 
private static final booleanisString(com.sun.org.apache.bcel.internal.generic.Type type)


        
    return ((type instanceof ObjectType) && 
            ((ObjectType)type).getClassName().equals("java.lang.String"));
  
public voidsetClassGen(com.sun.org.apache.bcel.internal.generic.ClassGen c)

 cg = c; 
public voidsetConstantPool(com.sun.org.apache.bcel.internal.generic.ConstantPoolGen c)

 cp = c;