📄 instructionfactory.java
字号:
package de.fub.bytecode.generic;import de.fub.bytecode.Constants;/** * 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.7 2001/08/24 08:35:33 dahm Exp $ * @author <A HREF="http://www.berlin.de/~markus.dahm/">M. Dahm</A> * @see Constants */public class InstructionFactory implements InstructionConstants { protected ClassGen cg; protected ConstantPoolGen cp; public InstructionFactory(ClassGen cg, ConstantPoolGen cp) { this.cg = cg; this.cp = cp; } /** Initialize with ClassGen object */ public InstructionFactory(ClassGen cg) { this(cg, cg.getConstantPool()); } /** Initialize just with ConstantPoolGen object */ public InstructionFactory(ConstantPoolGen cp) { this(null, cp); } /** 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 */ public InvokeInstruction createInvoke(String class_name, String name, Type ret_type, Type[] arg_types, short kind) { 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); } } /** Create a call to the most popular System.out.println() method. * * @param s the string to print */ public InstructionList createPrintln(String s) { 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; } private static class MethodObject { Type[] arg_types; Type result_type; String[] arg_names; String class_name; String name; int access; MethodObject(String c, String n, Type r, Type[] a, int acc) { class_name = c; name = n; result_type = r; arg_types = a; access = acc; } } private InvokeInstruction createInvoke(MethodObject m, short kind) { return createInvoke(m.class_name, m.name, m.result_type, m.arg_types, kind); } private static MethodObject[] append_mos = { new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { Type.STRING }, Constants.ACC_PUBLIC), new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { Type.OBJECT }, Constants.ACC_PUBLIC), null, null, // indices 2, 3 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { Type.BOOLEAN }, Constants.ACC_PUBLIC), new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { Type.CHAR }, Constants.ACC_PUBLIC), new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { Type.FLOAT }, Constants.ACC_PUBLIC), new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { Type.DOUBLE }, Constants.ACC_PUBLIC), new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { Type.INT }, Constants.ACC_PUBLIC), new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(byte) new Type[] { Type.INT }, Constants.ACC_PUBLIC), new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(short) new Type[] { Type.INT }, Constants.ACC_PUBLIC), new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { Type.LONG }, Constants.ACC_PUBLIC) }; private static final boolean isString(Type type) { return ((type instanceof ObjectType) && ((ObjectType)type).getClassName().equals("java.lang.String")); } public Instruction createAppend(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); } } /** 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 */ public FieldInstruction createFieldAccess(String class_name, String name, Type type, short kind) { 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); } } /** Create reference to `this' */ public static Instruction createThis() { return new ALOAD(0); } /** Create typed return */ public static ReturnInstruction createReturn(Type type) { 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); } } private static final ArithmeticInstruction createBinaryIntOp(char first, 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 ArithmeticInstruction createBinaryLongOp(char first, 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); } } private static final ArithmeticInstruction createBinaryFloatOp(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 ArithmeticInstruction createBinaryDoubleOp(char op) { switch(op) { case '-' : return DSUB; case '+' : return DADD; case '*' : return DMUL; case '/' : return DDIV; default: throw new RuntimeException("Invalid operand " + op); } } /** * Create binary operation for simple basic types, such as int and float. * * @param op operation, such as "+", "*", "<<", etc.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -