aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/javassist/compiler/CodeGen.java
diff options
context:
space:
mode:
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2003-04-23 17:08:37 +0000
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2003-04-23 17:08:37 +0000
commitcdeddfd6fc34a06734f9fa525cf5c7437a6c8fb6 (patch)
tree0471a4d9b985b11969ecd6f521f660e3d468f1d1 /src/main/javassist/compiler/CodeGen.java
parentfb431982111b03608b888953f7ed8ba7e98f421c (diff)
downloadjavassist-cdeddfd6fc34a06734f9fa525cf5c7437a6c8fb6.tar.gz
javassist-cdeddfd6fc34a06734f9fa525cf5c7437a6c8fb6.zip
Changed the copyright notices and removed tab characters.
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@9 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main/javassist/compiler/CodeGen.java')
-rw-r--r--src/main/javassist/compiler/CodeGen.java2315
1 files changed, 1152 insertions, 1163 deletions
diff --git a/src/main/javassist/compiler/CodeGen.java b/src/main/javassist/compiler/CodeGen.java
index 9a5f6771..d061e320 100644
--- a/src/main/javassist/compiler/CodeGen.java
+++ b/src/main/javassist/compiler/CodeGen.java
@@ -1,28 +1,17 @@
/*
- * This file is part of the Javassist toolkit.
+ * Javassist, a Java-bytecode translator toolkit.
+ * Copyright (C) 1999-2003 Shigeru Chiba. All Rights Reserved.
*
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * either http://www.mozilla.org/MPL/.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
*
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Original Code is Javassist.
- *
- * The Initial Developer of the Original Code is Shigeru Chiba. Portions
- * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba.
- * All Rights Reserved.
- *
- * Contributor(s):
- *
- * The development of this software is supported in part by the PRESTO
- * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*/
-
package javassist.compiler;
import java.util.ArrayList;
@@ -54,34 +43,34 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
/* The following fields are used by atXXX() methods
* for returning the type of the compiled expression.
*/
- protected int exprType; // VOID, NULL, CLASS, BOOLEAN, INT, ...
+ protected int exprType; // VOID, NULL, CLASS, BOOLEAN, INT, ...
protected int arrayDim;
- protected String className; // JVM-internal representation
+ protected String className; // JVM-internal representation
public CodeGen(Bytecode b) {
- bytecode = b;
- tempVar = -1;
- inStaticMethod = false;
- breakList = null;
- continueList = null;
+ bytecode = b;
+ tempVar = -1;
+ inStaticMethod = false;
+ breakList = null;
+ continueList = null;
}
protected static void fatal() throws CompileError {
- throw new CompileError("fatal");
+ throw new CompileError("fatal");
}
public static boolean is2word(int type, int dim) {
- return dim == 0 && (type == DOUBLE || type == LONG);
+ return dim == 0 && (type == DOUBLE || type == LONG);
}
public int getMaxLocals() { return bytecode.getMaxLocals(); }
public void setMaxLocals(int n) {
- bytecode.setMaxLocals(n);
+ bytecode.setMaxLocals(n);
}
protected void incMaxLocals(int size) {
- bytecode.incMaxLocals(size);
+ bytecode.incMaxLocals(size);
}
/**
@@ -89,23 +78,23 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
* stored in.
*/
protected int getTempVar() {
- if (tempVar < 0) {
- tempVar = getMaxLocals();
- incMaxLocals(2);
- }
+ if (tempVar < 0) {
+ tempVar = getMaxLocals();
+ incMaxLocals(2);
+ }
- return tempVar;
+ return tempVar;
}
protected int getLocalVar(Declarator d) {
- int v = d.getLocalVar();
- if (v < 0) {
- v = getMaxLocals(); // delayed variable allocation.
- d.setLocalVar(v);
- incMaxLocals(1);
- }
+ int v = d.getLocalVar();
+ if (v < 0) {
+ v = getMaxLocals(); // delayed variable allocation.
+ d.setLocalVar(v);
+ incMaxLocals(1);
+ }
- return v;
+ return v;
}
/**
@@ -124,76 +113,76 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
* For example, this converts Object into java/lang/Object.
*/
protected abstract String resolveClassName(ASTList name)
- throws CompileError;
+ throws CompileError;
/* Expands a simple class name to java.lang.*.
* For example, this converts Object into java/lang/Object.
*/
protected abstract String resolveClassName(String jvmClassName)
- throws CompileError;
+ throws CompileError;
/**
- * @param name the JVM-internal representation.
- * name is not exapnded to java.lang.*.
+ * @param name the JVM-internal representation.
+ * name is not exapnded to java.lang.*.
*/
protected static String toJvmArrayName(String name, int dim) {
- if (name == null)
- return null;
+ if (name == null)
+ return null;
- if (dim == 0)
- return name;
- else {
- StringBuffer sbuf = new StringBuffer();
- int d = dim;
- while (d-- > 0)
- sbuf.append('[');
+ if (dim == 0)
+ return name;
+ else {
+ StringBuffer sbuf = new StringBuffer();
+ int d = dim;
+ while (d-- > 0)
+ sbuf.append('[');
- sbuf.append('L');
- sbuf.append(name);
- sbuf.append(';');
+ sbuf.append('L');
+ sbuf.append(name);
+ sbuf.append(';');
- return sbuf.toString();
- }
+ return sbuf.toString();
+ }
}
protected static String toJvmTypeName(int type, int dim) {
- char c = 'I';
- switch(type) {
- case BOOLEAN :
- c = 'Z';
- break;
- case BYTE :
- c = 'B';
- break;
- case CHAR :
- c = 'C';
- break;
- case SHORT :
- c = 'S';
- break;
- case INT :
- c = 'I';
- break;
- case LONG :
- c = 'J';
- break;
- case FLOAT :
- c = 'F';
- break;
- case DOUBLE :
- c = 'D';
- break;
- case VOID :
- c = 'V';
- break;
- }
-
- StringBuffer sbuf = new StringBuffer();
- while (dim-- > 0)
- sbuf.append('[');
-
- sbuf.append(c);
- return sbuf.toString();
+ char c = 'I';
+ switch(type) {
+ case BOOLEAN :
+ c = 'Z';
+ break;
+ case BYTE :
+ c = 'B';
+ break;
+ case CHAR :
+ c = 'C';
+ break;
+ case SHORT :
+ c = 'S';
+ break;
+ case INT :
+ c = 'I';
+ break;
+ case LONG :
+ c = 'J';
+ break;
+ case FLOAT :
+ c = 'F';
+ break;
+ case DOUBLE :
+ c = 'D';
+ break;
+ case VOID :
+ c = 'V';
+ break;
+ }
+
+ StringBuffer sbuf = new StringBuffer();
+ while (dim-- > 0)
+ sbuf.append('[');
+
+ sbuf.append(c);
+ return sbuf.toString();
}
@@ -204,353 +193,353 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
public void atSymbol(Symbol n) throws CompileError { fatal(); }
public void atFieldDecl(FieldDecl field) throws CompileError {
- field.getInit().accept(this);
+ field.getInit().accept(this);
}
public void atMethodDecl(MethodDecl method) throws CompileError {
- ASTList mods = method.getModifiers();
- setMaxLocals(1);
- while (mods != null) {
- Keyword k = (Keyword)mods.head();
- mods = mods.tail();
- if (k.get() == STATIC) {
- setMaxLocals(0);
- inStaticMethod = true;
- }
- }
-
- ASTList params = method.getParams();
- while (params != null) {
- atDeclarator((Declarator)params.head());
- params = params.tail();
- }
-
- Stmnt s = method.getBody();
- atMethodBody(s, method.isConstructor(),
- method.getReturn().getType() == VOID);
+ ASTList mods = method.getModifiers();
+ setMaxLocals(1);
+ while (mods != null) {
+ Keyword k = (Keyword)mods.head();
+ mods = mods.tail();
+ if (k.get() == STATIC) {
+ setMaxLocals(0);
+ inStaticMethod = true;
+ }
+ }
+
+ ASTList params = method.getParams();
+ while (params != null) {
+ atDeclarator((Declarator)params.head());
+ params = params.tail();
+ }
+
+ Stmnt s = method.getBody();
+ atMethodBody(s, method.isConstructor(),
+ method.getReturn().getType() == VOID);
}
public void atMethodBody(Stmnt s, boolean isCons, boolean isVoid)
- throws CompileError
+ throws CompileError
{
- if (s == null)
- return;
+ if (s == null)
+ return;
- if (isCons && needsSuperCall(s))
- insertDefaultSuperCall();
+ if (isCons && needsSuperCall(s))
+ insertDefaultSuperCall();
- s.accept(this);
- if (isVoid
- && (bytecode.read(bytecode.currentPc() - 1) & 0xff)
- != Opcode.RETURN) {
- bytecode.addOpcode(Opcode.RETURN);
- }
+ s.accept(this);
+ if (isVoid
+ && (bytecode.read(bytecode.currentPc() - 1) & 0xff)
+ != Opcode.RETURN) {
+ bytecode.addOpcode(Opcode.RETURN);
+ }
}
private boolean needsSuperCall(Stmnt body) {
- if (body.getOperator() == BLOCK) {
- Stmnt first = (Stmnt)body.head();
- if (first != null && first.getOperator() == EXPR) {
- ASTree expr = first.head();
- if (expr != null && expr instanceof Expr
- && ((Expr)expr).getOperator() == CALL) {
- ASTree target = ((Expr)expr).head();
- if (target instanceof Keyword) {
- int token = ((Keyword)target).get();
- return token != THIS && token != SUPER;
- }
- }
- }
- }
-
- return true;
+ if (body.getOperator() == BLOCK) {
+ Stmnt first = (Stmnt)body.head();
+ if (first != null && first.getOperator() == EXPR) {
+ ASTree expr = first.head();
+ if (expr != null && expr instanceof Expr
+ && ((Expr)expr).getOperator() == CALL) {
+ ASTree target = ((Expr)expr).head();
+ if (target instanceof Keyword) {
+ int token = ((Keyword)target).get();
+ return token != THIS && token != SUPER;
+ }
+ }
+ }
+ }
+
+ return true;
}
protected abstract void insertDefaultSuperCall() throws CompileError;
public void atStmnt(Stmnt st) throws CompileError {
- if (st == null)
- return; // empty
-
- int op = st.getOperator();
- if (op == EXPR) {
- ASTree expr = st.getLeft();
- if (expr instanceof AssignExpr)
- atAssignExpr((AssignExpr)expr, false);
- else if (isPlusPlusExpr(expr)) {
- Expr e = (Expr)expr;
- atPlusPlus(e.getOperator(), e.oprand1(), e, false);
- }
- else {
- expr.accept(this);
- if (is2word(exprType, arrayDim))
- bytecode.addOpcode(POP2);
- else if (exprType != VOID)
- bytecode.addOpcode(POP);
- }
- }
- else if (op == DECL || op == BLOCK) {
- ASTList list = st;
- while (list != null) {
- ASTree h = list.head();
- list = list.tail();
- if (h != null)
- h.accept(this);
- }
- }
- else if (op == IF)
- atIfStmnt(st);
- else if (op == WHILE || op == DO)
- atWhileStmnt(st, op == WHILE);
- else if (op == FOR)
- atForStmnt(st);
- else if (op == BREAK || op == CONTINUE)
- atBreakStmnt(st, op == BREAK);
- else if (op == TokenId.RETURN)
- atReturnStmnt(st);
- else if (op == THROW)
- atThrowStmnt(st);
- else if (op == TRY)
- atTryStmnt(st);
- else // LABEL, SWITCH label stament might be null?.
- throw new CompileError(
- "sorry, not supported statement: TokenId " + op);
+ if (st == null)
+ return; // empty
+
+ int op = st.getOperator();
+ if (op == EXPR) {
+ ASTree expr = st.getLeft();
+ if (expr instanceof AssignExpr)
+ atAssignExpr((AssignExpr)expr, false);
+ else if (isPlusPlusExpr(expr)) {
+ Expr e = (Expr)expr;
+ atPlusPlus(e.getOperator(), e.oprand1(), e, false);
+ }
+ else {
+ expr.accept(this);
+ if (is2word(exprType, arrayDim))
+ bytecode.addOpcode(POP2);
+ else if (exprType != VOID)
+ bytecode.addOpcode(POP);
+ }
+ }
+ else if (op == DECL || op == BLOCK) {
+ ASTList list = st;
+ while (list != null) {
+ ASTree h = list.head();
+ list = list.tail();
+ if (h != null)
+ h.accept(this);
+ }
+ }
+ else if (op == IF)
+ atIfStmnt(st);
+ else if (op == WHILE || op == DO)
+ atWhileStmnt(st, op == WHILE);
+ else if (op == FOR)
+ atForStmnt(st);
+ else if (op == BREAK || op == CONTINUE)
+ atBreakStmnt(st, op == BREAK);
+ else if (op == TokenId.RETURN)
+ atReturnStmnt(st);
+ else if (op == THROW)
+ atThrowStmnt(st);
+ else if (op == TRY)
+ atTryStmnt(st);
+ else // LABEL, SWITCH label stament might be null?.
+ throw new CompileError(
+ "sorry, not supported statement: TokenId " + op);
}
private void atIfStmnt(Stmnt st) throws CompileError {
- ASTree expr = st.head();
- Stmnt thenp = (Stmnt)st.tail().head();
- Stmnt elsep = (Stmnt)st.tail().tail().head();
- booleanExpr(false, expr);
- int pc = bytecode.currentPc();
- int pc2 = 0;
- bytecode.addIndex(0); // correct later
+ ASTree expr = st.head();
+ Stmnt thenp = (Stmnt)st.tail().head();
+ Stmnt elsep = (Stmnt)st.tail().tail().head();
+ booleanExpr(false, expr);
+ int pc = bytecode.currentPc();
+ int pc2 = 0;
+ bytecode.addIndex(0); // correct later
- if (thenp != null)
- thenp.accept(this);
+ if (thenp != null)
+ thenp.accept(this);
- if (elsep != null) {
- bytecode.addOpcode(Opcode.GOTO);
- pc2 = bytecode.currentPc();
- bytecode.addIndex(0);
- }
+ if (elsep != null) {
+ bytecode.addOpcode(Opcode.GOTO);
+ pc2 = bytecode.currentPc();
+ bytecode.addIndex(0);
+ }
- bytecode.write16bit(pc, bytecode.currentPc() - pc + 1);
+ bytecode.write16bit(pc, bytecode.currentPc() - pc + 1);
- if (elsep != null) {
- elsep.accept(this);
- bytecode.write16bit(pc2, bytecode.currentPc() - pc2 + 1);
- }
+ if (elsep != null) {
+ elsep.accept(this);
+ bytecode.write16bit(pc2, bytecode.currentPc() - pc2 + 1);
+ }
}
private void atWhileStmnt(Stmnt st, boolean notDo) throws CompileError {
- ArrayList prevBreakList = breakList;
- ArrayList prevContList = continueList;
- breakList = new ArrayList();
- continueList = new ArrayList();
+ ArrayList prevBreakList = breakList;
+ ArrayList prevContList = continueList;
+ breakList = new ArrayList();
+ continueList = new ArrayList();
- ASTree expr = st.head();
- Stmnt body = (Stmnt)st.tail();
+ ASTree expr = st.head();
+ Stmnt body = (Stmnt)st.tail();
- int pc = 0;
- if (notDo) {
- bytecode.addOpcode(Opcode.GOTO);
- pc = bytecode.currentPc();
- bytecode.addIndex(0);
- }
+ int pc = 0;
+ if (notDo) {
+ bytecode.addOpcode(Opcode.GOTO);
+ pc = bytecode.currentPc();
+ bytecode.addIndex(0);
+ }
- int pc2 = bytecode.currentPc();
- if (body != null)
- body.accept(this);
+ int pc2 = bytecode.currentPc();
+ if (body != null)
+ body.accept(this);
- int pc3 = bytecode.currentPc();
- if (notDo)
- bytecode.write16bit(pc, pc3 - pc + 1);
+ int pc3 = bytecode.currentPc();
+ if (notDo)
+ bytecode.write16bit(pc, pc3 - pc + 1);
- booleanExpr(true, expr);
- bytecode.addIndex(pc2 - bytecode.currentPc() + 1);
+ booleanExpr(true, expr);
+ bytecode.addIndex(pc2 - bytecode.currentPc() + 1);
- patchGoto(breakList, bytecode.currentPc());
- patchGoto(continueList, pc3);
- continueList = prevContList;
- breakList = prevBreakList;
+ patchGoto(breakList, bytecode.currentPc());
+ patchGoto(continueList, pc3);
+ continueList = prevContList;
+ breakList = prevBreakList;
}
private void patchGoto(ArrayList list, int targetPc) {
- int n = list.size();
- for (int i = 0; i < n; ++i) {
- int pc = ((Integer)list.get(i)).intValue();
- bytecode.write16bit(pc, targetPc - pc + 1);
- }
+ int n = list.size();
+ for (int i = 0; i < n; ++i) {
+ int pc = ((Integer)list.get(i)).intValue();
+ bytecode.write16bit(pc, targetPc - pc + 1);
+ }
}
private void atForStmnt(Stmnt st) throws CompileError {
- ArrayList prevBreakList = breakList;
- ArrayList prevContList = continueList;
- breakList = new ArrayList();
- continueList = new ArrayList();
+ ArrayList prevBreakList = breakList;
+ ArrayList prevContList = continueList;
+ breakList = new ArrayList();
+ continueList = new ArrayList();
- Stmnt init = (Stmnt)st.head();
- ASTList p = st.tail();
- ASTree expr = p.head();
- p = p.tail();
- Stmnt update = (Stmnt)p.head();
- Stmnt body = (Stmnt)p.tail();
+ Stmnt init = (Stmnt)st.head();
+ ASTList p = st.tail();
+ ASTree expr = p.head();
+ p = p.tail();
+ Stmnt update = (Stmnt)p.head();
+ Stmnt body = (Stmnt)p.tail();
- if (init != null)
- init.accept(this);
+ if (init != null)
+ init.accept(this);
- int pc = bytecode.currentPc();
- int pc2 = 0;
- if (expr != null) {
- booleanExpr(false, expr);
- pc2 = bytecode.currentPc();
- bytecode.addIndex(0);
- }
+ int pc = bytecode.currentPc();
+ int pc2 = 0;
+ if (expr != null) {
+ booleanExpr(false, expr);
+ pc2 = bytecode.currentPc();
+ bytecode.addIndex(0);
+ }
- if (body != null)
- body.accept(this);
+ if (body != null)
+ body.accept(this);
- int pc3 = bytecode.currentPc();
- if (update != null)
- update.accept(this);
+ int pc3 = bytecode.currentPc();
+ if (update != null)
+ update.accept(this);
- bytecode.addOpcode(Opcode.GOTO);
- bytecode.addIndex(pc - bytecode.currentPc() + 1);
+ bytecode.addOpcode(Opcode.GOTO);
+ bytecode.addIndex(pc - bytecode.currentPc() + 1);
- int pc4 = bytecode.currentPc();
- if (expr != null)
- bytecode.write16bit(pc2, pc4 - pc2 + 1);
+ int pc4 = bytecode.currentPc();
+ if (expr != null)
+ bytecode.write16bit(pc2, pc4 - pc2 + 1);
- patchGoto(breakList, pc4);
- patchGoto(continueList, pc3);
- continueList = prevContList;
- breakList = prevBreakList;
+ patchGoto(breakList, pc4);
+ patchGoto(continueList, pc3);
+ continueList = prevContList;
+ breakList = prevBreakList;
}
private void atBreakStmnt(Stmnt st, boolean notCont)
- throws CompileError
+ throws CompileError
{
- if (st.head() != null)
- throw new CompileError(
- "sorry, not support labeled break or continue");
+ if (st.head() != null)
+ throw new CompileError(
+ "sorry, not support labeled break or continue");
- bytecode.addOpcode(Opcode.GOTO);
- Integer pc = new Integer(bytecode.currentPc());
- bytecode.addIndex(0);
- if (notCont)
- breakList.add(pc);
- else
- continueList.add(pc);
+ bytecode.addOpcode(Opcode.GOTO);
+ Integer pc = new Integer(bytecode.currentPc());
+ bytecode.addIndex(0);
+ if (notCont)
+ breakList.add(pc);
+ else
+ continueList.add(pc);
}
protected void atReturnStmnt(Stmnt st) throws CompileError {
- atReturnStmnt2(st.getLeft());
+ atReturnStmnt2(st.getLeft());
}
protected final void atReturnStmnt2(ASTree result) throws CompileError {
- int op;
- if (result == null)
- op = Opcode.RETURN;
- else {
- result.accept(this);
- if (arrayDim > 0)
- op = ARETURN;
- else {
- int type = exprType;
- if (type == DOUBLE)
- op = DRETURN;
- else if (type == FLOAT)
- op = FRETURN;
- else if (type == LONG)
- op = LRETURN;
- else if (isRefType(type))
- op = ARETURN;
- else
- op = IRETURN;
- }
- }
-
- bytecode.addOpcode(op);
+ int op;
+ if (result == null)
+ op = Opcode.RETURN;
+ else {
+ result.accept(this);
+ if (arrayDim > 0)
+ op = ARETURN;
+ else {
+ int type = exprType;
+ if (type == DOUBLE)
+ op = DRETURN;
+ else if (type == FLOAT)
+ op = FRETURN;
+ else if (type == LONG)
+ op = LRETURN;
+ else if (isRefType(type))
+ op = ARETURN;
+ else
+ op = IRETURN;
+ }
+ }
+
+ bytecode.addOpcode(op);
}
private void atThrowStmnt(Stmnt st) throws CompileError {
- ASTree e = st.getLeft();
- e.accept(this);
- if (exprType != CLASS || arrayDim > 0)
- throw new CompileError("bad throw statement");
+ ASTree e = st.getLeft();
+ e.accept(this);
+ if (exprType != CLASS || arrayDim > 0)
+ throw new CompileError("bad throw statement");
- bytecode.addOpcode(ATHROW);
+ bytecode.addOpcode(ATHROW);
}
protected abstract void atTryStmnt(Stmnt st) throws CompileError;
private static boolean isPlusPlusExpr(ASTree expr) {
- if (expr instanceof Expr) {
- int op = ((Expr)expr).getOperator();
- return op == PLUSPLUS || op == MINUSMINUS;
- }
+ if (expr instanceof Expr) {
+ int op = ((Expr)expr).getOperator();
+ return op == PLUSPLUS || op == MINUSMINUS;
+ }
- return false;
+ return false;
}
public void atDeclarator(Declarator d) throws CompileError {
- d.setLocalVar(getMaxLocals());
- d.setClassName(resolveClassName(d.getClassName()));
+ d.setLocalVar(getMaxLocals());
+ d.setClassName(resolveClassName(d.getClassName()));
- int size;
- if (is2word(d.getType(), d.getArrayDim()))
- size = 2;
- else
- size = 1;
+ int size;
+ if (is2word(d.getType(), d.getArrayDim()))
+ size = 2;
+ else
+ size = 1;
- incMaxLocals(size);
+ incMaxLocals(size);
- /* NOTE: Array initializers has not been supported.
- */
- ASTree init = d.getInitializer();
- if (init != null)
- atVariableAssign(null, '=', null, d, init, false);
+ /* NOTE: Array initializers has not been supported.
+ */
+ ASTree init = d.getInitializer();
+ if (init != null)
+ atVariableAssign(null, '=', null, d, init, false);
}
public abstract void atNewExpr(NewExpr n) throws CompileError;
public void atAssignExpr(AssignExpr expr) throws CompileError {
- atAssignExpr(expr, true);
+ atAssignExpr(expr, true);
}
protected void atAssignExpr(AssignExpr expr, boolean doDup)
- throws CompileError
+ throws CompileError
{
- // =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, >>>=
- int op = expr.getOperator();
- ASTree left = expr.oprand1();
- ASTree right = expr.oprand2();
- if (left instanceof Variable)
- atVariableAssign(expr, op, (Variable)left,
- ((Variable)left).getDeclarator(),
- right, doDup);
- else {
- if (left instanceof Expr) {
- Expr e = (Expr)left;
- if (e.getOperator() == ARRAY) {
- atArrayAssign(expr, op, (Expr)left, right, doDup);
- return;
- }
- }
-
- atFieldAssign(expr, op, left, right, doDup);
- }
+ // =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, >>>=
+ int op = expr.getOperator();
+ ASTree left = expr.oprand1();
+ ASTree right = expr.oprand2();
+ if (left instanceof Variable)
+ atVariableAssign(expr, op, (Variable)left,
+ ((Variable)left).getDeclarator(),
+ right, doDup);
+ else {
+ if (left instanceof Expr) {
+ Expr e = (Expr)left;
+ if (e.getOperator() == ARRAY) {
+ atArrayAssign(expr, op, (Expr)left, right, doDup);
+ return;
+ }
+ }
+
+ atFieldAssign(expr, op, left, right, doDup);
+ }
}
protected static void badAssign(Expr expr) throws CompileError {
- String msg;
- if (expr == null)
- msg = "incompatible type for assignment";
- else
- msg = "incompatible type for " + expr.getName();
+ String msg;
+ if (expr == null)
+ msg = "incompatible type for assignment";
+ else
+ msg = "incompatible type for " + expr.getName();
- throw new CompileError(msg);
+ throw new CompileError(msg);
}
/* op is either =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, or >>>=.
@@ -558,187 +547,187 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
* expr and var can be null.
*/
private void atVariableAssign(Expr expr, int op, Variable var,
- Declarator d, ASTree right,
- boolean doDup) throws CompileError
+ Declarator d, ASTree right,
+ boolean doDup) throws CompileError
{
- int varType = d.getType();
- int varArray = d.getArrayDim();
- String varClass = d.getClassName();
- int varNo = getLocalVar(d);
-
- if (op != '=')
- atVariable(var);
-
- atAssignCore(expr, op, right, varType, varArray, varClass);
-
- if (doDup)
- if (is2word(varType, varArray))
- bytecode.addOpcode(DUP2);
- else
- bytecode.addOpcode(DUP);
-
- if (varArray > 0)
- bytecode.addAstore(varNo);
- else if (varType == DOUBLE)
- bytecode.addDstore(varNo);
- else if (varType == FLOAT)
- bytecode.addFstore(varNo);
- else if (varType == LONG)
- bytecode.addLstore(varNo);
- else if (isRefType(varType))
- bytecode.addAstore(varNo);
- else
- bytecode.addIstore(varNo);
-
- exprType = varType;
- arrayDim = varArray;
- className = varClass;
+ int varType = d.getType();
+ int varArray = d.getArrayDim();
+ String varClass = d.getClassName();
+ int varNo = getLocalVar(d);
+
+ if (op != '=')
+ atVariable(var);
+
+ atAssignCore(expr, op, right, varType, varArray, varClass);
+
+ if (doDup)
+ if (is2word(varType, varArray))
+ bytecode.addOpcode(DUP2);
+ else
+ bytecode.addOpcode(DUP);
+
+ if (varArray > 0)
+ bytecode.addAstore(varNo);
+ else if (varType == DOUBLE)
+ bytecode.addDstore(varNo);
+ else if (varType == FLOAT)
+ bytecode.addFstore(varNo);
+ else if (varType == LONG)
+ bytecode.addLstore(varNo);
+ else if (isRefType(varType))
+ bytecode.addAstore(varNo);
+ else
+ bytecode.addIstore(varNo);
+
+ exprType = varType;
+ arrayDim = varArray;
+ className = varClass;
}
private void atArrayAssign(Expr expr, int op, Expr array,
- ASTree right, boolean doDup) throws CompileError
+ ASTree right, boolean doDup) throws CompileError
{
- arrayAccess(array.oprand1(), array.oprand2());
+ arrayAccess(array.oprand1(), array.oprand2());
- if (op != '=') {
- bytecode.addOpcode(DUP2);
- bytecode.addOpcode(getArrayReadOp(exprType, arrayDim));
- }
+ if (op != '=') {
+ bytecode.addOpcode(DUP2);
+ bytecode.addOpcode(getArrayReadOp(exprType, arrayDim));
+ }
- int aType = exprType;
- int aDim = arrayDim;
- String cname = className;
+ int aType = exprType;
+ int aDim = arrayDim;
+ String cname = className;
- atAssignCore(expr, op, right, aType, aDim, cname);
+ atAssignCore(expr, op, right, aType, aDim, cname);
- if (doDup)
- if (is2word(aType, aDim))
- bytecode.addOpcode(DUP2_X2);
- else
- bytecode.addOpcode(DUP_X2);
+ if (doDup)
+ if (is2word(aType, aDim))
+ bytecode.addOpcode(DUP2_X2);
+ else
+ bytecode.addOpcode(DUP_X2);
- bytecode.addOpcode(getArrayWriteOp(aType, aDim));
- exprType = aType;
- arrayDim = aDim;
- className = cname;
+ bytecode.addOpcode(getArrayWriteOp(aType, aDim));
+ exprType = aType;
+ arrayDim = aDim;
+ className = cname;
}
protected abstract void atFieldAssign(Expr expr, int op, ASTree left,
- ASTree right, boolean doDup) throws CompileError;
+ ASTree right, boolean doDup) throws CompileError;
protected void atAssignCore(Expr expr, int op, ASTree right,
- int type, int dim, String cname)
- throws CompileError
+ int type, int dim, String cname)
+ throws CompileError
{
- right.accept(this);
- if (invalidDim(exprType, arrayDim, className, type, dim, cname, false)
- || (op != '=' && dim > 0))
- badAssign(expr);
+ right.accept(this);
+ if (invalidDim(exprType, arrayDim, className, type, dim, cname, false)
+ || (op != '=' && dim > 0))
+ badAssign(expr);
- if (op == PLUS_E && dim == 0 && type == CLASS)
- atStringConcatExpr(expr, type, dim, cname);
- else if (op != '=') {
- int token = assignOps[op - MOD_E];
- int k = lookupBinOp(token);
- if (k < 0)
- fatal();
+ if (op == PLUS_E && dim == 0 && type == CLASS)
+ atStringConcatExpr(expr, type, dim, cname);
+ else if (op != '=') {
+ int token = assignOps[op - MOD_E];
+ int k = lookupBinOp(token);
+ if (k < 0)
+ fatal();
- atArithBinExpr(expr, token, k, type);
- }
+ atArithBinExpr(expr, token, k, type);
+ }
- if (op != '=' || (dim == 0 && !isRefType(type)))
- atNumCastExpr(exprType, type);
+ if (op != '=' || (dim == 0 && !isRefType(type)))
+ atNumCastExpr(exprType, type);
- // type check should be done here.
+ // type check should be done here.
}
private boolean invalidDim(int srcType, int srcDim, String srcClass,
- int destType, int destDim, String destClass,
- boolean isCast)
+ int destType, int destDim, String destClass,
+ boolean isCast)
{
- if (srcDim != destDim)
- if (srcType == NULL)
- return false;
- else if (destDim == 0 && destType == CLASS
- && jvmJavaLangObject.equals(destClass))
- return false;
- else if (isCast && srcDim == 0 && srcType == CLASS
- && jvmJavaLangObject.equals(srcClass))
- return false;
- else
- return true;
+ if (srcDim != destDim)
+ if (srcType == NULL)
+ return false;
+ else if (destDim == 0 && destType == CLASS
+ && jvmJavaLangObject.equals(destClass))
+ return false;
+ else if (isCast && srcDim == 0 && srcType == CLASS
+ && jvmJavaLangObject.equals(srcClass))
+ return false;
+ else
+ return true;
- return false;
+ return false;
}
public void atCondExpr(CondExpr expr) throws CompileError {
- booleanExpr(false, expr.condExpr());
- int pc = bytecode.currentPc();
- bytecode.addIndex(0); // correct later
- expr.thenExpr().accept(this);
- bytecode.addOpcode(Opcode.GOTO);
- int pc2 = bytecode.currentPc();
- bytecode.addIndex(0);
- bytecode.write16bit(pc, bytecode.currentPc() - pc + 1);
- expr.elseExpr().accept(this);
- bytecode.write16bit(pc2, bytecode.currentPc() - pc2 + 1);
+ booleanExpr(false, expr.condExpr());
+ int pc = bytecode.currentPc();
+ bytecode.addIndex(0); // correct later
+ expr.thenExpr().accept(this);
+ bytecode.addOpcode(Opcode.GOTO);
+ int pc2 = bytecode.currentPc();
+ bytecode.addIndex(0);
+ bytecode.write16bit(pc, bytecode.currentPc() - pc + 1);
+ expr.elseExpr().accept(this);
+ bytecode.write16bit(pc2, bytecode.currentPc() - pc2 + 1);
}
private final int[] binOp = {
- '+', DADD, FADD, LADD, IADD,
- '-', DSUB, FSUB, LSUB, ISUB,
- '*', DMUL, FMUL, LMUL, IMUL,
- '/', DDIV, FDIV, LDIV, IDIV,
- '%', DREM, FREM, LREM, IREM,
- '|', NOP, NOP, LOR, IOR,
- '^', NOP, NOP, LXOR, IXOR,
- '&', NOP, NOP, LAND, IAND,
- LSHIFT, NOP, NOP, LSHL, ISHL,
- RSHIFT, NOP, NOP, LSHR, ISHR,
- ARSHIFT, NOP, NOP, LUSHR, IUSHR };
+ '+', DADD, FADD, LADD, IADD,
+ '-', DSUB, FSUB, LSUB, ISUB,
+ '*', DMUL, FMUL, LMUL, IMUL,
+ '/', DDIV, FDIV, LDIV, IDIV,
+ '%', DREM, FREM, LREM, IREM,
+ '|', NOP, NOP, LOR, IOR,
+ '^', NOP, NOP, LXOR, IXOR,
+ '&', NOP, NOP, LAND, IAND,
+ LSHIFT, NOP, NOP, LSHL, ISHL,
+ RSHIFT, NOP, NOP, LSHR, ISHR,
+ ARSHIFT, NOP, NOP, LUSHR, IUSHR };
private int lookupBinOp(int token) {
- int[] code = binOp;
- int s = code.length;
- for (int k = 0; k < s; k = k + 5)
- if (code[k] == token)
- return k;
+ int[] code = binOp;
+ int s = code.length;
+ for (int k = 0; k < s; k = k + 5)
+ if (code[k] == token)
+ return k;
- return -1;
+ return -1;
}
public void atBinExpr(BinExpr expr) throws CompileError {
- int token = expr.getOperator();
-
- /* arithmetic operators: +, -, *, /, %, |, ^, &, <<, >>, >>>
- */
- int k = lookupBinOp(token);
- if (k >= 0) {
- expr.oprand1().accept(this);
- int type1 = exprType;
- int dim1 = arrayDim;
- String cname1 = className;
- expr.oprand2().accept(this);
- if (dim1 != arrayDim)
- throw new CompileError("incompatible array types");
-
- if (token == '+' && dim1 == 0
- && (type1 == CLASS || exprType == CLASS))
- atStringConcatExpr(expr, type1, dim1, cname1);
- else
- atArithBinExpr(expr, token, k, type1);
-
- return;
- }
-
- /* equation: &&, ||, ==, !=, <=, >=, <, >
- */
- booleanExpr(true, expr);
- bytecode.addIndex(7);
- bytecode.addIconst(0); // false
- bytecode.addOpcode(Opcode.GOTO);
- bytecode.addIndex(4);
- bytecode.addIconst(1); // true
+ int token = expr.getOperator();
+
+ /* arithmetic operators: +, -, *, /, %, |, ^, &, <<, >>, >>>
+ */
+ int k = lookupBinOp(token);
+ if (k >= 0) {
+ expr.oprand1().accept(this);
+ int type1 = exprType;
+ int dim1 = arrayDim;
+ String cname1 = className;
+ expr.oprand2().accept(this);
+ if (dim1 != arrayDim)
+ throw new CompileError("incompatible array types");
+
+ if (token == '+' && dim1 == 0
+ && (type1 == CLASS || exprType == CLASS))
+ atStringConcatExpr(expr, type1, dim1, cname1);
+ else
+ atArithBinExpr(expr, token, k, type1);
+
+ return;
+ }
+
+ /* equation: &&, ||, ==, !=, <=, >=, <, >
+ */
+ booleanExpr(true, expr);
+ bytecode.addIndex(7);
+ bytecode.addIconst(0); // false
+ bytecode.addOpcode(Opcode.GOTO);
+ bytecode.addIndex(4);
+ bytecode.addIconst(1); // true
}
/* arrayDim values of the two oprands must be equal.
@@ -746,94 +735,94 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
* throws an exception.
*/
private void atArithBinExpr(Expr expr, int token,
- int index, int type1) throws CompileError
+ int index, int type1) throws CompileError
{
- if (arrayDim != 0)
- badTypes(expr);
-
- int type2 = exprType;
- if (token == LSHIFT || token == RSHIFT || token == ARSHIFT)
- if (type2 == INT || type2 == SHORT
- || type2 == CHAR || type2 == BYTE)
- exprType = type1;
- else
- badTypes(expr);
- else
- convertOprandTypes(type1, type2, expr);
-
- int p = typePrecedence(exprType);
- if (p >= 0) {
- int op = binOp[index + p + 1];
- if (op != NOP) {
- if (p == P_INT)
- exprType = INT; // type1 may be BYTE, ...
-
- bytecode.addOpcode(op);
- return;
- }
- }
-
- badTypes(expr);
+ if (arrayDim != 0)
+ badTypes(expr);
+
+ int type2 = exprType;
+ if (token == LSHIFT || token == RSHIFT || token == ARSHIFT)
+ if (type2 == INT || type2 == SHORT
+ || type2 == CHAR || type2 == BYTE)
+ exprType = type1;
+ else
+ badTypes(expr);
+ else
+ convertOprandTypes(type1, type2, expr);
+
+ int p = typePrecedence(exprType);
+ if (p >= 0) {
+ int op = binOp[index + p + 1];
+ if (op != NOP) {
+ if (p == P_INT)
+ exprType = INT; // type1 may be BYTE, ...
+
+ bytecode.addOpcode(op);
+ return;
+ }
+ }
+
+ badTypes(expr);
}
private void atStringConcatExpr(Expr expr, int type1, int dim1,
- String cname1) throws CompileError
+ String cname1) throws CompileError
{
- int type2 = exprType;
- int dim2 = arrayDim;
- boolean type2Is2 = is2word(type2, dim2);
- boolean type2IsString
- = (type2 == CLASS && jvmJavaLangString.equals(className));
+ int type2 = exprType;
+ int dim2 = arrayDim;
+ boolean type2Is2 = is2word(type2, dim2);
+ boolean type2IsString
+ = (type2 == CLASS && jvmJavaLangString.equals(className));
- if (type2Is2)
- convToString(type2, dim2);
+ if (type2Is2)
+ convToString(type2, dim2);
- if (is2word(type1, dim1)) {
- bytecode.addOpcode(DUP_X2);
- bytecode.addOpcode(POP);
- }
- else
- bytecode.addOpcode(SWAP);
+ if (is2word(type1, dim1)) {
+ bytecode.addOpcode(DUP_X2);
+ bytecode.addOpcode(POP);
+ }
+ else
+ bytecode.addOpcode(SWAP);
- convToString(type1, dim1);
- bytecode.addOpcode(SWAP);
+ convToString(type1, dim1);
+ bytecode.addOpcode(SWAP);
- if (!type2Is2 && !type2IsString)
- convToString(type2, dim2);
+ if (!type2Is2 && !type2IsString)
+ convToString(type2, dim2);
- bytecode.addInvokevirtual(javaLangString, "concat",
- "(Ljava/lang/String;)Ljava/lang/String;");
- exprType = CLASS;
- arrayDim = 0;
- className = jvmJavaLangString;
+ bytecode.addInvokevirtual(javaLangString, "concat",
+ "(Ljava/lang/String;)Ljava/lang/String;");
+ exprType = CLASS;
+ arrayDim = 0;
+ className = jvmJavaLangString;
}
private void convToString(int type, int dim) throws CompileError {
- final String method = "valueOf";
-
- if (isRefType(type) || dim > 0)
- bytecode.addInvokestatic(javaLangString, method,
- "(Ljava/lang/Object;)Ljava/lang/String;");
- else if (type == DOUBLE)
- bytecode.addInvokestatic(javaLangString, method,
- "(D)Ljava/lang/String;");
- else if (type == FLOAT)
- bytecode.addInvokestatic(javaLangString, method,
- "(F)Ljava/lang/String;");
- else if (type == LONG)
- bytecode.addInvokestatic(javaLangString, method,
- "(J)Ljava/lang/String;");
- else if (type == BOOLEAN)
- bytecode.addInvokestatic(javaLangString, method,
- "(Z)Ljava/lang/String;");
- else if (type == CHAR)
- bytecode.addInvokestatic(javaLangString, method,
- "(C)Ljava/lang/String;");
- else if (type == VOID)
- throw new CompileError("void type expression");
- else /* INT, BYTE, SHORT */
- bytecode.addInvokestatic(javaLangString, method,
- "(I)Ljava/lang/String;");
+ final String method = "valueOf";
+
+ if (isRefType(type) || dim > 0)
+ bytecode.addInvokestatic(javaLangString, method,
+ "(Ljava/lang/Object;)Ljava/lang/String;");
+ else if (type == DOUBLE)
+ bytecode.addInvokestatic(javaLangString, method,
+ "(D)Ljava/lang/String;");
+ else if (type == FLOAT)
+ bytecode.addInvokestatic(javaLangString, method,
+ "(F)Ljava/lang/String;");
+ else if (type == LONG)
+ bytecode.addInvokestatic(javaLangString, method,
+ "(J)Ljava/lang/String;");
+ else if (type == BOOLEAN)
+ bytecode.addInvokestatic(javaLangString, method,
+ "(Z)Ljava/lang/String;");
+ else if (type == CHAR)
+ bytecode.addInvokestatic(javaLangString, method,
+ "(C)Ljava/lang/String;");
+ else if (type == VOID)
+ throw new CompileError("void type expression");
+ else /* INT, BYTE, SHORT */
+ bytecode.addInvokestatic(javaLangString, method,
+ "(I)Ljava/lang/String;");
}
/* Produces the opcode to branch if the condition is true.
@@ -843,80 +832,80 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
* false.
*/
private void booleanExpr(boolean branchIf, ASTree expr)
- throws CompileError
+ throws CompileError
{
- boolean isAndAnd;
- int op = getCompOperator(expr);
- if (op == EQ) { // ==, !=, ...
- BinExpr bexpr = (BinExpr)expr;
- int type1 = compileOprands(bexpr);
- compareExpr(branchIf, bexpr.getOperator(), type1, bexpr);
- }
- else if (op == '!')
- booleanExpr(!branchIf, ((Expr)expr).oprand1());
- else if ((isAndAnd = (op == ANDAND)) || op == OROR) {
- BinExpr bexpr = (BinExpr)expr;
- booleanExpr(!isAndAnd, bexpr.oprand1());
- int pc = bytecode.currentPc();
- bytecode.addIndex(0); // correct later
-
- booleanExpr(isAndAnd, bexpr.oprand2());
- bytecode.write16bit(pc, bytecode.currentPc() - pc + 3);
- if (branchIf != isAndAnd) {
- bytecode.addIndex(6); // skip GOTO instruction
- bytecode.addOpcode(Opcode.GOTO);
- }
- }
- else { // others
- expr.accept(this);
- bytecode.addOpcode(branchIf ? IFNE : IFEQ);
- }
-
- exprType = BOOLEAN;
- arrayDim = 0;
+ boolean isAndAnd;
+ int op = getCompOperator(expr);
+ if (op == EQ) { // ==, !=, ...
+ BinExpr bexpr = (BinExpr)expr;
+ int type1 = compileOprands(bexpr);
+ compareExpr(branchIf, bexpr.getOperator(), type1, bexpr);
+ }
+ else if (op == '!')
+ booleanExpr(!branchIf, ((Expr)expr).oprand1());
+ else if ((isAndAnd = (op == ANDAND)) || op == OROR) {
+ BinExpr bexpr = (BinExpr)expr;
+ booleanExpr(!isAndAnd, bexpr.oprand1());
+ int pc = bytecode.currentPc();
+ bytecode.addIndex(0); // correct later
+
+ booleanExpr(isAndAnd, bexpr.oprand2());
+ bytecode.write16bit(pc, bytecode.currentPc() - pc + 3);
+ if (branchIf != isAndAnd) {
+ bytecode.addIndex(6); // skip GOTO instruction
+ bytecode.addOpcode(Opcode.GOTO);
+ }
+ }
+ else { // others
+ expr.accept(this);
+ bytecode.addOpcode(branchIf ? IFNE : IFEQ);
+ }
+
+ exprType = BOOLEAN;
+ arrayDim = 0;
}
private static int getCompOperator(ASTree expr) throws CompileError {
- if (expr instanceof Expr) {
- Expr bexpr = (Expr)expr;
- int token = bexpr.getOperator();
- if (token == '!')
- return '!';
- else if ((bexpr instanceof BinExpr)
- && token != OROR && token != ANDAND
- && token != '&' && token != '|')
- return EQ; // ==, !=, ...
- else
- return token;
- }
-
- return ' '; // others
+ if (expr instanceof Expr) {
+ Expr bexpr = (Expr)expr;
+ int token = bexpr.getOperator();
+ if (token == '!')
+ return '!';
+ else if ((bexpr instanceof BinExpr)
+ && token != OROR && token != ANDAND
+ && token != '&' && token != '|')
+ return EQ; // ==, !=, ...
+ else
+ return token;
+ }
+
+ return ' '; // others
}
private int compileOprands(BinExpr expr) throws CompileError {
- expr.oprand1().accept(this);
- int type1 = exprType;
- int dim1 = arrayDim;
- expr.oprand2().accept(this);
- if (dim1 != arrayDim)
- throw new CompileError("incompatible array types");
+ expr.oprand1().accept(this);
+ int type1 = exprType;
+ int dim1 = arrayDim;
+ expr.oprand2().accept(this);
+ if (dim1 != arrayDim)
+ throw new CompileError("incompatible array types");
- return type1;
+ return type1;
}
private final int ifOp[] = { EQ, IF_ICMPEQ, IF_ICMPNE,
- NEQ, IF_ICMPNE, IF_ICMPEQ,
- LE, IF_ICMPLE, IF_ICMPGT,
- GE, IF_ICMPGE, IF_ICMPLT,
- '<', IF_ICMPLT, IF_ICMPGE,
- '>', IF_ICMPGT, IF_ICMPLE };
+ NEQ, IF_ICMPNE, IF_ICMPEQ,
+ LE, IF_ICMPLE, IF_ICMPGT,
+ GE, IF_ICMPGE, IF_ICMPLT,
+ '<', IF_ICMPLT, IF_ICMPGE,
+ '>', IF_ICMPGT, IF_ICMPLE };
private final int ifOp2[] = { EQ, IFEQ, IFNE,
- NEQ, IFNE, IFEQ,
- LE, IFLE, IFGT,
- GE, IFGE, IFLT,
- '<', IFLT, IFGE,
- '>', IFGT, IFLE };
+ NEQ, IFNE, IFEQ,
+ LE, IFLE, IFGT,
+ GE, IFGE, IFLT,
+ '<', IFLT, IFGE,
+ '>', IFGT, IFLE };
/* Produces the opcode to branch if the condition is true.
* The oprands are not produced.
@@ -924,60 +913,60 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
* Parameter expr - compare expression ==, !=, <=, >=, <, >
*/
private void compareExpr(boolean branchIf,
- int token, int type1, BinExpr expr)
- throws CompileError
+ int token, int type1, BinExpr expr)
+ throws CompileError
{
- if (arrayDim == 0)
- convertOprandTypes(type1, exprType, expr);
-
- int p = typePrecedence(exprType);
- if (p == P_OTHER || arrayDim > 0)
- if (token == EQ)
- bytecode.addOpcode(branchIf ? IF_ACMPEQ : IF_ACMPNE);
- else if (token == NEQ)
- bytecode.addOpcode(branchIf ? IF_ACMPNE : IF_ACMPEQ);
- else
- badTypes(expr);
- else
- if (p == P_INT) {
- int op[] = ifOp;
- for (int i = 0; i < op.length; i += 3)
- if (op[i] == token) {
- bytecode.addOpcode(op[i + (branchIf ? 1 : 2)]);
- return;
- }
-
- badTypes(expr);
- }
- else {
- if (p == P_DOUBLE)
- if (token == '<' || token == LE)
- bytecode.addOpcode(DCMPG);
- else
- bytecode.addOpcode(DCMPL);
- else if (p == P_FLOAT)
- if (token == '<' || token == LE)
- bytecode.addOpcode(FCMPG);
- else
- bytecode.addOpcode(FCMPL);
- else if (p == P_LONG)
- bytecode.addOpcode(LCMP); // 1: >, 0: =, -1: <
- else
- fatal();
-
- int[] op = ifOp2;
- for (int i = 0; i < op.length; i += 3)
- if (op[i] == token) {
- bytecode.addOpcode(op[i + (branchIf ? 1 : 2)]);
- return;
- }
-
- badTypes(expr);
- }
+ if (arrayDim == 0)
+ convertOprandTypes(type1, exprType, expr);
+
+ int p = typePrecedence(exprType);
+ if (p == P_OTHER || arrayDim > 0)
+ if (token == EQ)
+ bytecode.addOpcode(branchIf ? IF_ACMPEQ : IF_ACMPNE);
+ else if (token == NEQ)
+ bytecode.addOpcode(branchIf ? IF_ACMPNE : IF_ACMPEQ);
+ else
+ badTypes(expr);
+ else
+ if (p == P_INT) {
+ int op[] = ifOp;
+ for (int i = 0; i < op.length; i += 3)
+ if (op[i] == token) {
+ bytecode.addOpcode(op[i + (branchIf ? 1 : 2)]);
+ return;
+ }
+
+ badTypes(expr);
+ }
+ else {
+ if (p == P_DOUBLE)
+ if (token == '<' || token == LE)
+ bytecode.addOpcode(DCMPG);
+ else
+ bytecode.addOpcode(DCMPL);
+ else if (p == P_FLOAT)
+ if (token == '<' || token == LE)
+ bytecode.addOpcode(FCMPG);
+ else
+ bytecode.addOpcode(FCMPL);
+ else if (p == P_LONG)
+ bytecode.addOpcode(LCMP); // 1: >, 0: =, -1: <
+ else
+ fatal();
+
+ int[] op = ifOp2;
+ for (int i = 0; i < op.length; i += 3)
+ if (op[i] == token) {
+ bytecode.addOpcode(op[i + (branchIf ? 1 : 2)]);
+ return;
+ }
+
+ badTypes(expr);
+ }
}
protected static void badTypes(Expr expr) throws CompileError {
- throw new CompileError("invalid types for " + expr.getName());
+ throw new CompileError("invalid types for " + expr.getName());
}
private static final int P_DOUBLE = 0;
@@ -987,244 +976,244 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
private static final int P_OTHER = -1;
protected static boolean isRefType(int type) {
- return type == CLASS || type == NULL;
+ return type == CLASS || type == NULL;
}
private static int typePrecedence(int type) {
- if (type == DOUBLE)
- return P_DOUBLE;
- else if (type == FLOAT)
- return P_FLOAT;
- else if (type == LONG)
- return P_LONG;
- else if (isRefType(type))
- return P_OTHER;
- else if (type == VOID)
- return P_OTHER; // this is wrong, but ...
- else
- return P_INT; // BOOLEAN, BYTE, CHAR, SHORT, INT
+ if (type == DOUBLE)
+ return P_DOUBLE;
+ else if (type == FLOAT)
+ return P_FLOAT;
+ else if (type == LONG)
+ return P_LONG;
+ else if (isRefType(type))
+ return P_OTHER;
+ else if (type == VOID)
+ return P_OTHER; // this is wrong, but ...
+ else
+ return P_INT; // BOOLEAN, BYTE, CHAR, SHORT, INT
}
private static final int[] castOp = {
- /* D F L I */
- /* double */ NOP, D2F, D2L, D2I,
- /* float */ F2D, NOP, F2L, F2I,
- /* long */ L2D, L2F, NOP, L2I,
- /* other */ I2D, I2F, I2L, NOP };
+ /* D F L I */
+ /* double */ NOP, D2F, D2L, D2I,
+ /* float */ F2D, NOP, F2L, F2I,
+ /* long */ L2D, L2F, NOP, L2I,
+ /* other */ I2D, I2F, I2L, NOP };
/* do implicit type conversion.
* arrayDim values of the two oprands must be zero.
*/
private void convertOprandTypes(int type1, int type2, Expr expr)
- throws CompileError
+ throws CompileError
{
- boolean rightStrong;
- int type1_p = typePrecedence(type1);
- int type2_p = typePrecedence(type2);
-
- if (type2_p < 0 && type1_p < 0) // not primitive types
- return;
-
- if (type2_p < 0 || type1_p < 0) // either is not a primitive type
- badTypes(expr);
-
- int op, result_type;
- if (type1_p <= type2_p) {
- rightStrong = false;
- exprType = type1;
- op = castOp[type2_p * 4 + type1_p];
- result_type = type1_p;
- }
- else {
- rightStrong = true;
- op = castOp[type1_p * 4 + type2_p];
- result_type = type2_p;
- }
-
- if (rightStrong) {
- if (result_type == P_DOUBLE || result_type == P_LONG) {
- if (type1_p == P_DOUBLE || type1_p == P_LONG)
- bytecode.addOpcode(DUP2_X2);
- else
- bytecode.addOpcode(DUP2_X1);
-
- bytecode.addOpcode(POP2);
- bytecode.addOpcode(op);
- bytecode.addOpcode(DUP2_X2);
- bytecode.addOpcode(POP2);
- }
- else if (result_type == P_FLOAT) {
- bytecode.addOpcode(SWAP);
- bytecode.addOpcode(op);
- bytecode.addOpcode(SWAP);
- }
- else
- fatal();
- }
- else if (op != NOP)
- bytecode.addOpcode(op);
+ boolean rightStrong;
+ int type1_p = typePrecedence(type1);
+ int type2_p = typePrecedence(type2);
+
+ if (type2_p < 0 && type1_p < 0) // not primitive types
+ return;
+
+ if (type2_p < 0 || type1_p < 0) // either is not a primitive type
+ badTypes(expr);
+
+ int op, result_type;
+ if (type1_p <= type2_p) {
+ rightStrong = false;
+ exprType = type1;
+ op = castOp[type2_p * 4 + type1_p];
+ result_type = type1_p;
+ }
+ else {
+ rightStrong = true;
+ op = castOp[type1_p * 4 + type2_p];
+ result_type = type2_p;
+ }
+
+ if (rightStrong) {
+ if (result_type == P_DOUBLE || result_type == P_LONG) {
+ if (type1_p == P_DOUBLE || type1_p == P_LONG)
+ bytecode.addOpcode(DUP2_X2);
+ else
+ bytecode.addOpcode(DUP2_X1);
+
+ bytecode.addOpcode(POP2);
+ bytecode.addOpcode(op);
+ bytecode.addOpcode(DUP2_X2);
+ bytecode.addOpcode(POP2);
+ }
+ else if (result_type == P_FLOAT) {
+ bytecode.addOpcode(SWAP);
+ bytecode.addOpcode(op);
+ bytecode.addOpcode(SWAP);
+ }
+ else
+ fatal();
+ }
+ else if (op != NOP)
+ bytecode.addOpcode(op);
}
public void atCastExpr(CastExpr expr) throws CompileError {
- String cname = resolveClassName(expr.getClassName());
- String toClass = checkCastExpr(expr, cname);
- int srcType = exprType;
- exprType = expr.getType();
- arrayDim = expr.getArrayDim();
- className = cname;
- if (toClass == null)
- atNumCastExpr(srcType, exprType); // built-in type
- else
- bytecode.addCheckcast(toClass);
+ String cname = resolveClassName(expr.getClassName());
+ String toClass = checkCastExpr(expr, cname);
+ int srcType = exprType;
+ exprType = expr.getType();
+ arrayDim = expr.getArrayDim();
+ className = cname;
+ if (toClass == null)
+ atNumCastExpr(srcType, exprType); // built-in type
+ else
+ bytecode.addCheckcast(toClass);
}
public void atInstanceOfExpr(InstanceOfExpr expr) throws CompileError {
- String cname = resolveClassName(expr.getClassName());
- String toClass = checkCastExpr(expr, cname);
- bytecode.addInstanceof(toClass);
- exprType = BOOLEAN;
- arrayDim = 0;
+ String cname = resolveClassName(expr.getClassName());
+ String toClass = checkCastExpr(expr, cname);
+ bytecode.addInstanceof(toClass);
+ exprType = BOOLEAN;
+ arrayDim = 0;
}
private String checkCastExpr(CastExpr expr, String name)
- throws CompileError
+ throws CompileError
{
- final String msg = "invalid cast";
- ASTree oprand = expr.getOprand();
- int dim = expr.getArrayDim();
- int type = expr.getType();
- oprand.accept(this);
- int srcType = exprType;
- if (invalidDim(srcType, arrayDim, className, type, dim, name, true)
- || srcType == VOID || type == VOID)
- throw new CompileError(msg);
-
- if (type == CLASS) {
- if (!isRefType(srcType))
- throw new CompileError(msg);
-
- return toJvmArrayName(name, dim);
- }
- else
- if (dim > 0)
- return toJvmTypeName(type, dim);
- else
- return null; // built-in type
+ final String msg = "invalid cast";
+ ASTree oprand = expr.getOprand();
+ int dim = expr.getArrayDim();
+ int type = expr.getType();
+ oprand.accept(this);
+ int srcType = exprType;
+ if (invalidDim(srcType, arrayDim, className, type, dim, name, true)
+ || srcType == VOID || type == VOID)
+ throw new CompileError(msg);
+
+ if (type == CLASS) {
+ if (!isRefType(srcType))
+ throw new CompileError(msg);
+
+ return toJvmArrayName(name, dim);
+ }
+ else
+ if (dim > 0)
+ return toJvmTypeName(type, dim);
+ else
+ return null; // built-in type
}
void atNumCastExpr(int srcType, int destType)
- throws CompileError
+ throws CompileError
{
- if (srcType == destType)
- return;
-
- int op, op2;
- int stype = typePrecedence(srcType);
- int dtype = typePrecedence(destType);
- if (0 <= stype && stype < 3)
- op = castOp[stype * 4 + dtype];
- else
- op = NOP;
-
- if (destType == DOUBLE)
- op2 = I2D;
- else if (destType == FLOAT)
- op2 = I2F;
- else if (destType == LONG)
- op2 = I2L;
- else if (destType == SHORT)
- op2 = I2S;
- else if (destType == CHAR)
- op2 = I2C;
- else if (destType == BYTE)
- op2 = I2B;
- else
- op2 = NOP;
-
- if (op != NOP)
- bytecode.addOpcode(op);
-
- if (op == NOP || op == L2I || op == F2I || op == D2I)
- if (op2 != NOP)
- bytecode.addOpcode(op2);
+ if (srcType == destType)
+ return;
+
+ int op, op2;
+ int stype = typePrecedence(srcType);
+ int dtype = typePrecedence(destType);
+ if (0 <= stype && stype < 3)
+ op = castOp[stype * 4 + dtype];
+ else
+ op = NOP;
+
+ if (destType == DOUBLE)
+ op2 = I2D;
+ else if (destType == FLOAT)
+ op2 = I2F;
+ else if (destType == LONG)
+ op2 = I2L;
+ else if (destType == SHORT)
+ op2 = I2S;
+ else if (destType == CHAR)
+ op2 = I2C;
+ else if (destType == BYTE)
+ op2 = I2B;
+ else
+ op2 = NOP;
+
+ if (op != NOP)
+ bytecode.addOpcode(op);
+
+ if (op == NOP || op == L2I || op == F2I || op == D2I)
+ if (op2 != NOP)
+ bytecode.addOpcode(op2);
}
public void atExpr(Expr expr) throws CompileError {
- // method call, array access, member access,
- // (unary) +, (unary) -, ++, --, !, ~
-
- int token = expr.getOperator();
- ASTree oprand = expr.oprand1();
- if (token == CALL) // method call
- atMethodCall(expr);
- else if (token == '.')
- if (((Symbol)expr.oprand2()).get().equals("length"))
- atArrayLength(expr);
- else
- atFieldRead(expr);
- else if (token == MEMBER) { // field read
- if (!atClassObject(expr)) // .class
- atFieldRead(expr);
- }
- else if (token == ARRAY)
- atArrayRead(oprand, expr.oprand2());
- else if (token == PLUSPLUS || token == MINUSMINUS)
- atPlusPlus(token, oprand, expr, true);
- else if (token == '!') {
- booleanExpr(false, expr);
- bytecode.addIndex(7);
- bytecode.addIconst(1);
- bytecode.addOpcode(Opcode.GOTO);
- bytecode.addIndex(4);
- bytecode.addIconst(0);
- }
- else {
- expr.oprand1().accept(this);
- int type = typePrecedence(exprType);
- if (arrayDim > 0)
- badType(expr);
-
- if (token == '-') {
- if (type == P_DOUBLE)
- bytecode.addOpcode(DNEG);
- else if (type == P_FLOAT)
- bytecode.addOpcode(FNEG);
- else if (type == P_LONG)
- bytecode.addOpcode(LNEG);
- else if (type == P_INT) {
- bytecode.addOpcode(INEG);
- exprType = INT; // type may be BYTE, ...
- }
- else
- badType(expr);
- }
- else if (token == '~') {
- if (type == P_INT) {
- bytecode.addIconst(-1);
- bytecode.addOpcode(IXOR);
- exprType = INT; // type may be BYTE. ...
- }
- else if (type == P_LONG) {
- bytecode.addLconst(-1);
- bytecode.addOpcode(LXOR);
- }
- else
- badType(expr);
-
- }
- else if (token == '+') {
- if (type == P_OTHER)
- badType(expr);
-
- // do nothing. ignore.
- }
- else
- fatal();
- }
+ // method call, array access, member access,
+ // (unary) +, (unary) -, ++, --, !, ~
+
+ int token = expr.getOperator();
+ ASTree oprand = expr.oprand1();
+ if (token == CALL) // method call
+ atMethodCall(expr);
+ else if (token == '.')
+ if (((Symbol)expr.oprand2()).get().equals("length"))
+ atArrayLength(expr);
+ else
+ atFieldRead(expr);
+ else if (token == MEMBER) { // field read
+ if (!atClassObject(expr)) // .class
+ atFieldRead(expr);
+ }
+ else if (token == ARRAY)
+ atArrayRead(oprand, expr.oprand2());
+ else if (token == PLUSPLUS || token == MINUSMINUS)
+ atPlusPlus(token, oprand, expr, true);
+ else if (token == '!') {
+ booleanExpr(false, expr);
+ bytecode.addIndex(7);
+ bytecode.addIconst(1);
+ bytecode.addOpcode(Opcode.GOTO);
+ bytecode.addIndex(4);
+ bytecode.addIconst(0);
+ }
+ else {
+ expr.oprand1().accept(this);
+ int type = typePrecedence(exprType);
+ if (arrayDim > 0)
+ badType(expr);
+
+ if (token == '-') {
+ if (type == P_DOUBLE)
+ bytecode.addOpcode(DNEG);
+ else if (type == P_FLOAT)
+ bytecode.addOpcode(FNEG);
+ else if (type == P_LONG)
+ bytecode.addOpcode(LNEG);
+ else if (type == P_INT) {
+ bytecode.addOpcode(INEG);
+ exprType = INT; // type may be BYTE, ...
+ }
+ else
+ badType(expr);
+ }
+ else if (token == '~') {
+ if (type == P_INT) {
+ bytecode.addIconst(-1);
+ bytecode.addOpcode(IXOR);
+ exprType = INT; // type may be BYTE. ...
+ }
+ else if (type == P_LONG) {
+ bytecode.addLconst(-1);
+ bytecode.addOpcode(LXOR);
+ }
+ else
+ badType(expr);
+
+ }
+ else if (token == '+') {
+ if (type == P_OTHER)
+ badType(expr);
+
+ // do nothing. ignore.
+ }
+ else
+ fatal();
+ }
}
protected static void badType(Expr expr) throws CompileError {
- throw new CompileError("invalid type for " + expr.getName());
+ throw new CompileError("invalid type for " + expr.getName());
}
protected abstract void atMethodCall(Expr expr) throws CompileError;
@@ -1232,328 +1221,328 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
protected abstract void atFieldRead(ASTree expr) throws CompileError;
public boolean atClassObject(Expr expr) throws CompileError {
- if (!((Symbol)expr.oprand2()).get().equals("class"))
- return false;
+ if (!((Symbol)expr.oprand2()).get().equals("class"))
+ return false;
- if (resolveClassName((ASTList)expr.oprand1()) == null)
- return false;
+ if (resolveClassName((ASTList)expr.oprand1()) == null)
+ return false;
- throw new CompileError(".class is not supported");
+ throw new CompileError(".class is not supported");
}
public void atArrayLength(Expr expr) throws CompileError {
- expr.oprand1().accept(this);
- if (arrayDim == 0)
- throw new CompileError(".length applied to a non array");
+ expr.oprand1().accept(this);
+ if (arrayDim == 0)
+ throw new CompileError(".length applied to a non array");
- bytecode.addOpcode(ARRAYLENGTH);
- exprType = INT;
- arrayDim = 0;
+ bytecode.addOpcode(ARRAYLENGTH);
+ exprType = INT;
+ arrayDim = 0;
}
public void atArrayRead(ASTree array, ASTree index)
- throws CompileError
+ throws CompileError
{
- int op;
- arrayAccess(array, index);
- bytecode.addOpcode(getArrayReadOp(exprType, arrayDim));
+ int op;
+ arrayAccess(array, index);
+ bytecode.addOpcode(getArrayReadOp(exprType, arrayDim));
}
protected void arrayAccess(ASTree array, ASTree index)
- throws CompileError
+ throws CompileError
{
- array.accept(this);
- int type = exprType;
- int dim = arrayDim;
- if (dim == 0)
- throw new CompileError("bad array access");
+ array.accept(this);
+ int type = exprType;
+ int dim = arrayDim;
+ if (dim == 0)
+ throw new CompileError("bad array access");
- String cname = className;
+ String cname = className;
- index.accept(this);
- if (typePrecedence(exprType) != P_INT || arrayDim > 0)
- throw new CompileError("bad array index");
+ index.accept(this);
+ if (typePrecedence(exprType) != P_INT || arrayDim > 0)
+ throw new CompileError("bad array index");
- exprType = type;
- arrayDim = dim - 1;
- className = cname;
+ exprType = type;
+ arrayDim = dim - 1;
+ className = cname;
}
protected static int getArrayReadOp(int type, int dim) {
- int op;
- if (dim > 0)
- return AALOAD;
-
- switch (type) {
- case DOUBLE :
- return DALOAD;
- case FLOAT :
- return FALOAD;
- case LONG :
- return LALOAD;
- case INT :
- return IALOAD;
- case SHORT :
- return SALOAD;
- case CHAR :
- return CALOAD;
- case BYTE :
- case BOOLEAN :
- return BALOAD;
- default :
- return AALOAD;
- }
+ int op;
+ if (dim > 0)
+ return AALOAD;
+
+ switch (type) {
+ case DOUBLE :
+ return DALOAD;
+ case FLOAT :
+ return FALOAD;
+ case LONG :
+ return LALOAD;
+ case INT :
+ return IALOAD;
+ case SHORT :
+ return SALOAD;
+ case CHAR :
+ return CALOAD;
+ case BYTE :
+ case BOOLEAN :
+ return BALOAD;
+ default :
+ return AALOAD;
+ }
}
protected static int getArrayWriteOp(int type, int dim) {
- int op;
- if (dim > 0)
- return AASTORE;
-
- switch (type) {
- case DOUBLE :
- return DASTORE;
- case FLOAT :
- return FASTORE;
- case LONG :
- return LASTORE;
- case INT :
- return IASTORE;
- case CHAR :
- return CASTORE;
- case BYTE :
- case BOOLEAN :
- return BASTORE;
- default :
- return AASTORE;
- }
+ int op;
+ if (dim > 0)
+ return AASTORE;
+
+ switch (type) {
+ case DOUBLE :
+ return DASTORE;
+ case FLOAT :
+ return FASTORE;
+ case LONG :
+ return LASTORE;
+ case INT :
+ return IASTORE;
+ case CHAR :
+ return CASTORE;
+ case BYTE :
+ case BOOLEAN :
+ return BASTORE;
+ default :
+ return AASTORE;
+ }
}
private void atPlusPlus(int token, ASTree oprand, Expr expr,
- boolean doDup) throws CompileError
+ 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);
-
- bytecode.addOpcode(IINC);
- bytecode.add(var);
- bytecode.add(token == PLUSPLUS ? 1 : -1);
-
- 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);
- }
+ 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);
+
+ bytecode.addOpcode(IINC);
+ bytecode.add(var);
+ bytecode.add(token == PLUSPLUS ? 1 : -1);
+
+ 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);
+ }
}
public void atArrayPlusPlus(int token, boolean isPost,
- Expr expr, boolean doDup) throws CompileError
+ Expr expr, boolean doDup) throws CompileError
{
- arrayAccess(expr.oprand1(), expr.oprand2());
- int t = exprType;
- int dim = arrayDim;
- if (dim > 0)
- badType(expr);
+ arrayAccess(expr.oprand1(), expr.oprand2());
+ int t = exprType;
+ int dim = arrayDim;
+ if (dim > 0)
+ badType(expr);
- bytecode.addOpcode(DUP2);
- bytecode.addOpcode(getArrayReadOp(t, arrayDim));
- int dup_code = is2word(t, dim) ? DUP2_X2 : DUP_X2;
- atPlusPlusCore(dup_code, doDup, token, isPost, expr);
- bytecode.addOpcode(getArrayWriteOp(t, dim));
+ bytecode.addOpcode(DUP2);
+ bytecode.addOpcode(getArrayReadOp(t, arrayDim));
+ int dup_code = is2word(t, dim) ? DUP2_X2 : DUP_X2;
+ atPlusPlusCore(dup_code, doDup, token, isPost, expr);
+ bytecode.addOpcode(getArrayWriteOp(t, dim));
}
protected void atPlusPlusCore(int dup_code, boolean doDup,
- int token, boolean isPost,
- Expr expr) throws CompileError
+ int token, boolean isPost,
+ Expr expr) throws CompileError
{
- int t = exprType;
-
- if (doDup && isPost)
- bytecode.addOpcode(dup_code);
-
- if (t == INT || t == BYTE || t == CHAR || t == SHORT) {
- bytecode.addIconst(1);
- bytecode.addOpcode(token == PLUSPLUS ? IADD : ISUB);
- exprType = INT;
- }
- else if (t == LONG) {
- bytecode.addLconst((long)1);
- bytecode.addOpcode(token == PLUSPLUS ? LADD : LSUB);
- }
- else if (t == FLOAT) {
- bytecode.addFconst(1.0f);
- bytecode.addOpcode(token == PLUSPLUS ? FADD : FSUB);
- }
- else if (t == DOUBLE) {
- bytecode.addDconst(1.0);
- bytecode.addOpcode(token == PLUSPLUS ? DADD : DSUB);
- }
- else
- badType(expr);
-
- if (doDup && !isPost)
- bytecode.addOpcode(dup_code);
+ int t = exprType;
+
+ if (doDup && isPost)
+ bytecode.addOpcode(dup_code);
+
+ if (t == INT || t == BYTE || t == CHAR || t == SHORT) {
+ bytecode.addIconst(1);
+ bytecode.addOpcode(token == PLUSPLUS ? IADD : ISUB);
+ exprType = INT;
+ }
+ else if (t == LONG) {
+ bytecode.addLconst((long)1);
+ bytecode.addOpcode(token == PLUSPLUS ? LADD : LSUB);
+ }
+ else if (t == FLOAT) {
+ bytecode.addFconst(1.0f);
+ bytecode.addOpcode(token == PLUSPLUS ? FADD : FSUB);
+ }
+ else if (t == DOUBLE) {
+ bytecode.addDconst(1.0);
+ bytecode.addOpcode(token == PLUSPLUS ? DADD : DSUB);
+ }
+ else
+ badType(expr);
+
+ if (doDup && !isPost)
+ bytecode.addOpcode(dup_code);
}
protected abstract void atFieldPlusPlus(int token, boolean isPost,
- ASTree oprand, Expr expr, boolean doDup) throws CompileError;
+ ASTree oprand, Expr expr, boolean doDup) throws CompileError;
public abstract void atMember(Member n) throws CompileError;
public void atVariable(Variable v) throws CompileError {
- Declarator d = v.getDeclarator();
- exprType = d.getType();
- arrayDim = d.getArrayDim();
- className = d.getClassName();
- int var = getLocalVar(d);
-
- if (arrayDim > 0)
- bytecode.addAload(var);
- else
- switch (exprType) {
- case CLASS :
- bytecode.addAload(var);
- break;
- case LONG :
- bytecode.addLload(var);
- break;
- case FLOAT :
- bytecode.addFload(var);
- break;
- case DOUBLE :
- bytecode.addDload(var);
- break;
- default : // BOOLEAN, BYTE, CHAR, SHORT, INT
- bytecode.addIload(var);
- break;
- }
+ Declarator d = v.getDeclarator();
+ exprType = d.getType();
+ arrayDim = d.getArrayDim();
+ className = d.getClassName();
+ int var = getLocalVar(d);
+
+ if (arrayDim > 0)
+ bytecode.addAload(var);
+ else
+ switch (exprType) {
+ case CLASS :
+ bytecode.addAload(var);
+ break;
+ case LONG :
+ bytecode.addLload(var);
+ break;
+ case FLOAT :
+ bytecode.addFload(var);
+ break;
+ case DOUBLE :
+ bytecode.addDload(var);
+ break;
+ default : // BOOLEAN, BYTE, CHAR, SHORT, INT
+ bytecode.addIload(var);
+ break;
+ }
}
public void atKeyword(Keyword k) throws CompileError {
- arrayDim = 0;
- int token = k.get();
- switch (token) {
- case TRUE :
- bytecode.addIconst(1);
- exprType = BOOLEAN;
- break;
- case FALSE :
- bytecode.addIconst(0);
- exprType = BOOLEAN;
- break;
- case NULL :
- bytecode.addOpcode(ACONST_NULL);
- exprType = NULL;
- break;
- case THIS :
- case SUPER :
- if (inStaticMethod)
- throw new CompileError("not-available: "
- + (token == THIS ? "this" : "super"));
-
- bytecode.addAload(0);
- exprType = CLASS;
- if (token == THIS)
- className = getThisName();
- else
- className = getSuperName();
- break;
- default :
- fatal();
- }
+ arrayDim = 0;
+ int token = k.get();
+ switch (token) {
+ case TRUE :
+ bytecode.addIconst(1);
+ exprType = BOOLEAN;
+ break;
+ case FALSE :
+ bytecode.addIconst(0);
+ exprType = BOOLEAN;
+ break;
+ case NULL :
+ bytecode.addOpcode(ACONST_NULL);
+ exprType = NULL;
+ break;
+ case THIS :
+ case SUPER :
+ if (inStaticMethod)
+ throw new CompileError("not-available: "
+ + (token == THIS ? "this" : "super"));
+
+ bytecode.addAload(0);
+ exprType = CLASS;
+ if (token == THIS)
+ className = getThisName();
+ else
+ className = getSuperName();
+ break;
+ default :
+ fatal();
+ }
}
public void atStringL(StringL s) throws CompileError {
- exprType = CLASS;
- arrayDim = 0;
- className = "java/lang/String";
- bytecode.addLdc(s.get());
+ exprType = CLASS;
+ arrayDim = 0;
+ className = "java/lang/String";
+ bytecode.addLdc(s.get());
}
public void atIntConst(IntConst i) throws CompileError {
- arrayDim = 0;
- long value = i.get();
- int type = i.getType();
- if (type == IntConstant || type == CharConstant) {
- exprType = (type == IntConstant ? INT : CHAR);
- bytecode.addIconst((int)value);
- }
- else {
- exprType = LONG;
- bytecode.addLconst(value);
- }
+ arrayDim = 0;
+ long value = i.get();
+ int type = i.getType();
+ if (type == IntConstant || type == CharConstant) {
+ exprType = (type == IntConstant ? INT : CHAR);
+ bytecode.addIconst((int)value);
+ }
+ else {
+ exprType = LONG;
+ bytecode.addLconst(value);
+ }
}
public void atDoubleConst(DoubleConst d) throws CompileError {
- arrayDim = 0;
- if (d.getType() == DoubleConstant) {
- exprType = DOUBLE;
- bytecode.addDconst(d.get());
- }
- else {
- exprType = FLOAT;
- bytecode.addFconst((float)d.get());
- }
+ arrayDim = 0;
+ if (d.getType() == DoubleConstant) {
+ exprType = DOUBLE;
+ bytecode.addDconst(d.get());
+ }
+ else {
+ exprType = FLOAT;
+ bytecode.addFconst((float)d.get());
+ }
}
}