private void atSwitchStmnt(Stmnt st) throws CompileError { compileExpr(st.head()); ArrayList prevBreakList = breakList; breakList = new ArrayList(); int opcodePc = bytecode.currentPc(); bytecode.addOpcode(LOOKUPSWITCH); int npads = 3 - (opcodePc & 3); while (npads-- > 0) bytecode.add(0); Stmnt body = (Stmnt) st.tail(); int npairs = 0; for (ASTList list = body; list != null; list = list.tail()) if (((Stmnt) list.head()).getOperator() == CASE) ++npairs; // opcodePc2 is the position at which the default jump offset is. int opcodePc2 = bytecode.currentPc(); bytecode.addGap(4); bytecode.add32bit(npairs); bytecode.addGap(npairs * 8); long[] pairs = new long[npairs]; int ipairs = 0; int defaultPc = -1; for (ASTList list = body; list != null; list = list.tail()) { Stmnt label = (Stmnt) list.head(); int op = label.getOperator(); if (op == DEFAULT) defaultPc = bytecode.currentPc(); else if (op != CASE) fatal(); else { pairs[ipairs++] = ((long) computeLabel(label.head()) << 32) + ((long) (bytecode.currentPc() - opcodePc) & 0xffffffff); } hasReturned = false; ((Stmnt) label.tail()).accept(this); } Arrays.sort(pairs); int pc = opcodePc2 + 8; for (int i = 0; i < npairs; ++i) { bytecode.write32bit(pc, (int) (pairs[i] >>> 32)); bytecode.write32bit(pc + 4, (int) pairs[i]); pc += 8; } if (defaultPc < 0 || breakList.size() > 0) hasReturned = false; int endPc = bytecode.currentPc(); if (defaultPc < 0) defaultPc = endPc; bytecode.write32bit(opcodePc2, defaultPc - opcodePc); patchGoto(breakList, endPc); breakList = prevBreakList; }
private void atPlusPlus(int token, ASTree oprand, Expr expr, boolean doDup) throws CompileError { boolean isPost = oprand == null; // ++i or i++? if (isPost) oprand = expr.oprand2(); if (oprand instanceof Variable) { Declarator d = ((Variable) oprand).getDeclarator(); int t = exprType = d.getType(); arrayDim = d.getArrayDim(); int var = getLocalVar(d); if (arrayDim > 0) badType(expr); if (t == DOUBLE) { bytecode.addDload(var); if (doDup && isPost) bytecode.addOpcode(DUP2); bytecode.addDconst(1.0); bytecode.addOpcode(token == PLUSPLUS ? DADD : DSUB); if (doDup && !isPost) bytecode.addOpcode(DUP2); bytecode.addDstore(var); } else if (t == LONG) { bytecode.addLload(var); if (doDup && isPost) bytecode.addOpcode(DUP2); bytecode.addLconst((long) 1); bytecode.addOpcode(token == PLUSPLUS ? LADD : LSUB); if (doDup && !isPost) bytecode.addOpcode(DUP2); bytecode.addLstore(var); } else if (t == FLOAT) { bytecode.addFload(var); if (doDup && isPost) bytecode.addOpcode(DUP); bytecode.addFconst(1.0f); bytecode.addOpcode(token == PLUSPLUS ? FADD : FSUB); if (doDup && !isPost) bytecode.addOpcode(DUP); bytecode.addFstore(var); } else if (t == BYTE || t == CHAR || t == SHORT || t == INT) { if (doDup && isPost) bytecode.addIload(var); int delta = token == PLUSPLUS ? 1 : -1; if (var > 0xff) { bytecode.addOpcode(WIDE); bytecode.addOpcode(IINC); bytecode.addIndex(var); bytecode.addIndex(delta); } else { bytecode.addOpcode(IINC); bytecode.add(var); bytecode.add(delta); } if (doDup && !isPost) bytecode.addIload(var); } else badType(expr); } else { if (oprand instanceof Expr) { Expr e = (Expr) oprand; if (e.getOperator() == ARRAY) { atArrayPlusPlus(token, isPost, e, doDup); return; } } atFieldPlusPlus(token, isPost, oprand, expr, doDup); } }