|
|
@@ -542,7 +542,23 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { |
|
|
|
} |
|
|
|
|
|
|
|
private void atSwitchStmnt(Stmnt st) throws CompileError { |
|
|
|
boolean isString = false; |
|
|
|
if (typeChecker != null) { |
|
|
|
doTypeCheck(st.head()); |
|
|
|
isString = typeChecker.exprType == TypeChecker.CLASS |
|
|
|
&& typeChecker.arrayDim == 0 |
|
|
|
&& TypeChecker.jvmJavaLangString.equals(typeChecker.className); |
|
|
|
} |
|
|
|
|
|
|
|
compileExpr(st.head()); |
|
|
|
int tmpVar = -1; |
|
|
|
if (isString) { |
|
|
|
tmpVar = getMaxLocals(); |
|
|
|
incMaxLocals(1); |
|
|
|
bytecode.addAstore(tmpVar); |
|
|
|
bytecode.addAload(tmpVar); |
|
|
|
bytecode.addInvokevirtual(TypeChecker.jvmJavaLangString, "hashCode", "()I"); |
|
|
|
} |
|
|
|
|
|
|
|
List<Integer> prevBreakList = breakList; |
|
|
|
breakList = new ArrayList<Integer>(); |
|
|
@@ -565,6 +581,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { |
|
|
|
bytecode.addGap(npairs * 8); |
|
|
|
|
|
|
|
long[] pairs = new long[npairs]; |
|
|
|
ArrayList<Integer> gotoDefaults = new ArrayList<Integer>(); |
|
|
|
int ipairs = 0; |
|
|
|
int defaultPc = -1; |
|
|
|
for (ASTList list = body; list != null; list = list.tail()) { |
|
|
@@ -575,9 +592,18 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { |
|
|
|
else if (op != CASE) |
|
|
|
fatal(); |
|
|
|
else { |
|
|
|
int curPos = bytecode.currentPc(); |
|
|
|
long caseLabel; |
|
|
|
if (isString) { |
|
|
|
// computeStringLabel() also adds bytecode as its side-effects. |
|
|
|
caseLabel = (long)computeStringLabel(label.head(), tmpVar, gotoDefaults); |
|
|
|
} |
|
|
|
else |
|
|
|
caseLabel = (long)computeLabel(label.head()); |
|
|
|
|
|
|
|
pairs[ipairs++] |
|
|
|
= ((long)computeLabel(label.head()) << 32) + |
|
|
|
((long)(bytecode.currentPc() - opcodePc) & 0xffffffff); |
|
|
|
= (caseLabel << 32) + |
|
|
|
((long)(curPos - opcodePc) & 0xffffffff); |
|
|
|
} |
|
|
|
|
|
|
|
hasReturned = false; |
|
|
@@ -600,6 +626,8 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { |
|
|
|
defaultPc = endPc; |
|
|
|
|
|
|
|
bytecode.write32bit(opcodePc2, defaultPc - opcodePc); |
|
|
|
for (int addr: gotoDefaults) |
|
|
|
bytecode.write16bit(addr, defaultPc - addr + 1); |
|
|
|
|
|
|
|
patchGoto(breakList, endPc); |
|
|
|
breakList = prevBreakList; |
|
|
@@ -613,6 +641,26 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { |
|
|
|
throw new CompileError("bad case label"); |
|
|
|
} |
|
|
|
|
|
|
|
private int computeStringLabel(ASTree expr, int tmpVar, List<Integer> gotoDefaults) |
|
|
|
throws CompileError |
|
|
|
{ |
|
|
|
doTypeCheck(expr); |
|
|
|
expr = TypeChecker.stripPlusExpr(expr); |
|
|
|
if (expr instanceof StringL) { |
|
|
|
String label = ((StringL)expr).get(); |
|
|
|
bytecode.addAload(tmpVar); |
|
|
|
bytecode.addLdc(label); |
|
|
|
bytecode.addInvokevirtual(TypeChecker.jvmJavaLangString, "equals", |
|
|
|
"(Ljava/lang/Object;)Z"); |
|
|
|
bytecode.addOpcode(IFEQ); |
|
|
|
Integer pc = Integer.valueOf(bytecode.currentPc()); |
|
|
|
bytecode.addIndex(0); |
|
|
|
gotoDefaults.add(pc); |
|
|
|
return (int)label.hashCode(); |
|
|
|
} |
|
|
|
throw new CompileError("bad case label"); |
|
|
|
} |
|
|
|
|
|
|
|
private void atBreakStmnt(Stmnt st, boolean notCont) |
|
|
|
throws CompileError |
|
|
|
{ |