📄 insgen.java
字号:
// InsGen.java -- generation of C code for bytecode instructionspackage toba.translator;import toba.classfile.*;import java.io.*;class InsGen extends Opcode {// igen(d, m, ins) -- generate code for one instructionstatic void igen(PrintWriter d, Method m, Instr ins){ int n; FieldRef r; ClassRef c; String s, t1, t2; // We don't generate code for unreachable instructions, // since their stack state is indeterminate if (!ins.isReached) return; Opcode o = ins.opcode; switch (o.kind) { case NOP: // nop, pop, pop2, breakpoint // nothing break; case CONST: // bipush, aconst_null, fconst_<n>, ... d.println(assign(ins) + (ins.val + o.var) + ";"); break; case LDC: // ldc, ldc_2, ldc2_w d.println(assign(ins) + Repr.con(m, ins.con) + ";"); break; case LOAD: // iload, aload_<n>, fload, ... d.println(assign(ins) + o.name.substring(0, 1) + "v" + (ins.val + o.var) + ";"); break; case STORE: // istore, fstore_<n>, astore, ... s = stacktop(ins); d.println("\t" + s.substring(0, 1) + "v" + (ins.val + o.var) + " = " + s + ";"); break; case IINC: // iinc d.println("\tiv" + ins.val + " += " + ins.more[0] + ";"); break; case GETS: // getstatic case PUTS: // putstatic r = (FieldRef)ins.con.value; s = Names.hashclass(r.cl.name); if (!ancestor(m.cl, s)) // if not in this class or a superclass d.println("\tinit_" + s + "();"); if (o.kind == GETS) d.println(assign(ins) + "cl_" + s + ".V." + Names.hashvar(r.name) + ";"); else // (o.kind == PUTS) d.println("\tcl_" + s + ".V." + Names.hashvar(r.name) + " = " + stacktop(ins) + ";"); break; case GETF: // getfield checkref(d, ins, -1); r = (FieldRef)ins.con.value; d.println(assign(ins) + "((struct in_" + Names.hashclass(r.cl.name) + "*)" + stacktop(ins) + ")->" + Names.hashvar(r.name) + ";"); break; case PUTF: // putfield checkref(d, ins, -2); r = (FieldRef)ins.con.value; d.println("\t((struct in_" + Names.hashclass(r.cl.name) + "*)" + stack2nd(ins) + ")->" + Names.hashvar(r.name) + " = " + stacktop(ins) + ";"); break; case NEW: // new c = (ClassRef)ins.con.value; d.println(assign(ins) + "new(&cl_" + Names.hashclass((String)c.name) + ".C);"); break; case ACAST: // checkcas c = (ClassRef)ins.con.value; d.println("\tif ((" + stacktop(ins) + " != 0) && !" + ckinstance(ins, (String)c.name) + ")\n\t\tthrowClassCastException(" + stacktop(ins) +");"); break; case INSTC: // instanceof c = (ClassRef)ins.con.value; d.println(assign(ins) + "(" + stacktop(ins) + " != 0) && " + ckinstance(ins, c.name) + ";"); break; case NEWA: // newarray switch (ins.val) { case T_BOOLEAN: s = "boolean"; break; case T_CHAR: s = "char"; break; case T_FLOAT: s = "float"; break; case T_DOUBLE: s = "double"; break; case T_BYTE: s = "byte"; break; case T_SHORT: s = "short"; break; case T_INT: s = "int"; break; case T_LONG: s = "long"; break; default: throw new VerifyError ("newarray(" + ins.val + ") at pc=" + ins.pc); } d.println(assign(ins) + "anewarray(&cl_" + s + "," + stacktop(ins) + ");"); break; case ANEWA: // anewarray c = (ClassRef)ins.con.value; // result class s = c.name; for (n = 0; s.charAt(n) == '['; n++) ; // n = class dimensions if (n == 0) { d.println(assign(ins) + "anewarray(&cl_" + Names.hashclass(s) + ".C," + stacktop(ins) + ");"); } else { d.println(assign(ins) + "vmnewarray(&" + Names.classref(s.substring(n)) + "," + (n + 1) + ",1," + stacktop(ins) + ");"); } break; case MNEWA: // multianewarray c = (ClassRef)ins.con.value; // result class s = c.name; for (n = 0; s.charAt(n) == '['; n++) ; // n = class dimensions int nargs = ins.more[0]; // number of args d.print(assign(ins) + "vmnewarray(&" + Names.classref(s.substring(n)) + "," + n + "," + nargs); for (int i = 0; i < nargs; i++) d.print(",i" + (ins.after.length() + i)); d.println(");"); break; case ALEN: // arraylength checkref(d, ins, -1); d.println(assign(ins) + "((struct aarray*)" + stacktop(ins) + ")->length;"); break; case ARRAYLOAD: // iaload, faload, aaload,... checkref(d, ins, -2); s = o.name.substring(0,1); // i,f,a,... d.println("\tif ((unsigned)" + stacktop(ins) + " >= ((struct " + s + "array*)" + stack2nd(ins) + ")->length)\n\t\tthrowArrayIndexOutOfBoundsException(" + stack2nd(ins) + "," + stacktop(ins) + ");"); d.println(assign(ins) + "((struct " + s + "array*)" + stack2nd(ins) + ")->data[" + stacktop(ins) + "];"); break; case ARRAYSTORE: // iastore, fastore, aastore,... checkref(d, ins, -3); s = o.name.substring(0,1); // i,f,a,... d.println("\tif ((unsigned)" + stack2nd(ins) + " >= ((struct " + s + "array*)" + stackvar(ins,-3) + ")->length)\n\t\tthrowArrayIndexOutOfBoundsException(" + stackvar(ins,-3) + "," + stack2nd(ins) + ");"); if ((o.flags & INST) != 0) { // aastore must check type d.println("\tif (" + stacktop(ins) + " && !instanceof(" + stacktop(ins) + ",((struct aarray*)" + stackAt(ins, -3) + ")->class->elemclass,0))"); d.println("\t\tthrowArrayStoreException(0);"); } d.println("\t((struct " + s + "array*)" + stackvar(ins,-3) + ")->data[" + stack2nd(ins) + "] = " + stacktop(ins) + ";"); break; case DUP: // dup d.println(assign(ins) + stacktop(ins) + ";"); break; case DUPX1: // dup_x1 // for dup_x1 to be legal, stacktop and stack2nd must be narrow vars d.println("\t" + stackvar(ins.succ,-1) +" = "+ stacktop(ins) +";"); d.println("\t" + stackvar(ins.succ,-2) +" = "+ stack2nd(ins) +";"); d.println("\t"+stackvar(ins.succ,-3)+" = "+stacktop(ins.succ)+";"); break; case DUPX2: // dup_x2 // stacktop must be narrow, but stack2nd may be wide d.println("\t" + stackAt(ins.succ,-1) +" = "+ stackAt(ins,-1) +";"); d.println("\t" + stackAt(ins.succ,-2) +" = "+ stackAt(ins,-2) +";"); if (ins.before.charAt(ins.before.length() - 3) != 'x') { // stack2nd was narrow d.println("\t" + stackAt(ins.succ,-3) + " = " + stackAt(ins,-3) + ";"); } d.println("\t"+stackAt(ins.succ,-4)+" = "+ stackAt(ins.succ,-1)+";"); break; case DUP2: // dup2 // stacktop can be wide or narrow; dup 2 words either way d.println(assign(ins) + stacktop(ins) + ";"); if (ins.before.charAt(ins.before.length() - 2) != 'x') { // stacktop was narrow variable; duping two separate values d.println("\t"+stack2nd(ins.succ)+" = "+ stack2nd(ins)+";"); } break; case D2X1: // dup2x1 // stacktop can be wide or narrow; stackAt(ins,-3) is narrow d.println(assign(ins) + stacktop(ins) + ";"); d.println("\t"+stackAt(ins.succ,-3)+" = "+stackAt(ins,-3)+";"); if (ins.before.charAt(ins.before.length() - 2) != 'x') { // stacktop contains a narrow variable d.println("\t" + stackAt(ins.succ,-2) + " = " + stackAt(ins,-2) + ";"); d.println("\t" + stackAt(ins.succ,-5) + " = " + stackAt(ins.succ,-2) + ";"); } d.println("\t"+stackAt(ins.succ,-4)+" = "+stackAt(ins.succ,-1)+";"); break; case D2X2: // dup2x2 d.println("\t"+stackAt(ins.succ,-1)+" = "+stackAt(ins,-1)+";"); if (ins.before.charAt(ins.before.length() - 2) != 'x') d.println("\t"+stackAt(ins.succ,-2)+" = "+stackAt(ins,-2)+";"); d.println("\t"+stackAt(ins.succ,-3)+" = "+stackAt(ins,-3)+";"); if (ins.before.charAt(ins.before.length() - 4) != 'x') d.println("\t"+stackAt(ins.succ,-4)+" = "+stackAt(ins,-4)+";"); d.println("\t"+stackAt(ins.succ,-5)+" = "+stackAt(ins.succ,-1)+";"); if (ins.before.charAt(ins.before.length() - 2) != 'x') d.println("\t"+stackAt(ins.succ,-6)+" = "+stackAt(ins.succ,-2)+ ";"); break; case SWAP: // swap n = ins.before.length(); t1 = ins.before.substring(n - 1); t2 = ins.before.substring(n - 2, n - 1); d.println("\t" + t1 + "0 = " + t1 + n + ";"); d.println("\t" + t2 + n + " = " + t2 + (n-1) + ";"); d.println("\t" + t1 + (n-1) + " = " + t1 + "0;"); break; case UNOP: // ineg, f2d, int2short, ... d.println(assign(ins) + o.opr + stacktop(ins) + ";"); break; case FTOI: // float-to-int conversion (incl d, l) d.println(assign(ins) + o.opr + "(" + stacktop(ins) + ");"); break; case DIVOP: // {i,l}{div,rem}, but not {f,d} d.println("\tif (!" + stacktop(ins) + ") throwDivisionByZeroException();"); // no break case BINOP: // iadd, fsub, dmul, ... d.println(assign(ins) + stack2nd(ins) +o.opr+ stacktop(ins) + ";"); break; case FREM: // frem, drem d.println(assign(ins) + "remdr(" + stack2nd(ins) + "," + stacktop(ins) + ");"); break; case SHIFT: // ishl, iushr, lshr, ... s = ""; // assume no cast if (o.push.length() == 2) { n = 0x3F; // mask 6 bits for long shifts if ((o.flags & UNS) != 0) s = "(ULong)"; } else { n = 0x1F; // mask 5 bits for int shifts if ((o.flags & UNS) != 0) s = "(UInt)"; } d.println(assign(ins) + s + stack2nd(ins) + o.opr + "(" + stacktop(ins) + " & " + n + ");"); break; case CMP: // lcmp, fcmpl, dcmpg, ... // these are carefully crafted to make NaN cases come out right if (o.var < 0) // if want -1 for NaN d.println(assign(ins) + "(" + stack2nd(ins) + " > " + stacktop(ins) + ") ? 1 : ((" + stack2nd(ins) + " == " + stacktop(ins) + ") ? 0 : -1);"); else d.println(assign(ins) + "(" + stack2nd(ins) + " < " + stacktop(ins) + ") ? -1 : ((" + stack2nd(ins) + " == " + stacktop(ins) + ") ? 0 : 1);"); break; case IFZRO: // ifeq, ifnull, ifgt, ... d.print("\tif (" + stacktop(ins) + o.opr + "0)\n\t\t"); gengoto(d, m, ins, ins.val); break; case IFCMP: // if_icmplt, if_acmpne, ... d.print("\tif (" + stack2nd(ins) +o.opr +stacktop(ins) + ")\n\t\t"); gengoto(d, m, ins, ins.val); break; case TBLSW: // tableswitch n = ins.more[1] - 3; // correction factor d.println("\tswitch (" + stacktop(ins) + ") {"); for (int i = 3; i < ins.more.length; i++) { d.print("\t\tcase " + (i + n) + ": \t"); gengoto(d, m, ins, ins.more[i]); } d.print("\t\tdefault:\t");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -