Commit 4e7ef9f4 authored by Skylot's avatar Skylot

Fix 'switch' codegen for empty case block

parent e60b5992
...@@ -36,6 +36,13 @@ public class CodeWriter { ...@@ -36,6 +36,13 @@ public class CodeWriter {
return this; return this;
} }
public CodeWriter startLine(char c) {
buf.append(NL);
buf.append(indentStr);
buf.append(c);
return this;
}
public CodeWriter startLine(int ind, String str) { public CodeWriter startLine(int ind, String str) {
buf.append(NL); buf.append(NL);
buf.append(indentStr); buf.append(indentStr);
......
...@@ -107,7 +107,7 @@ public class RegionGen extends InsnGen { ...@@ -107,7 +107,7 @@ public class RegionGen extends InsnGen {
IfNode insn = region.getIfInsn(); IfNode insn = region.getIfInsn();
code.add("if ").add(makeCondition(insn)).add(" {"); code.add("if ").add(makeCondition(insn)).add(" {");
makeRegionIndent(code, region.getThenRegion()); makeRegionIndent(code, region.getThenRegion());
code.startLine("}"); code.startLine('}');
IContainer els = region.getElseRegion(); IContainer els = region.getElseRegion();
if (els != null && RegionUtils.notEmpty(els)) { if (els != null && RegionUtils.notEmpty(els)) {
...@@ -123,11 +123,11 @@ public class RegionGen extends InsnGen { ...@@ -123,11 +123,11 @@ public class RegionGen extends InsnGen {
} }
} }
code.add("{"); code.add('{');
code.incIndent(); code.incIndent();
makeRegion(code, els); makeRegion(code, els);
code.decIndent(); code.decIndent();
code.startLine("}"); code.startLine('}');
} }
} }
...@@ -136,7 +136,7 @@ public class RegionGen extends InsnGen { ...@@ -136,7 +136,7 @@ public class RegionGen extends InsnGen {
// infinite loop // infinite loop
code.startLine("while (true) {"); code.startLine("while (true) {");
makeRegionIndent(code, region.getBody()); makeRegionIndent(code, region.getBody());
code.startLine("}"); code.startLine('}');
return code; return code;
} }
...@@ -144,11 +144,11 @@ public class RegionGen extends InsnGen { ...@@ -144,11 +144,11 @@ public class RegionGen extends InsnGen {
if (!region.isConditionAtEnd()) { if (!region.isConditionAtEnd()) {
code.startLine("while ").add(makeCondition(insn)).add(" {"); code.startLine("while ").add(makeCondition(insn)).add(" {");
makeRegionIndent(code, region.getBody()); makeRegionIndent(code, region.getBody());
code.startLine("}"); code.startLine('}');
} else { } else {
code.startLine("do {"); code.startLine("do {");
makeRegionIndent(code, region.getBody()); makeRegionIndent(code, region.getBody());
code.startLine("} while ").add(makeCondition(insn)).add(";"); code.startLine("} while ").add(makeCondition(insn)).add(';');
} }
return code; return code;
} }
...@@ -156,7 +156,7 @@ public class RegionGen extends InsnGen { ...@@ -156,7 +156,7 @@ public class RegionGen extends InsnGen {
private void makeSynchronizedRegion(SynchronizedRegion cont, CodeWriter code) throws CodegenException { private void makeSynchronizedRegion(SynchronizedRegion cont, CodeWriter code) throws CodegenException {
code.startLine("synchronized(").add(arg(cont.getArg())).add(") {"); code.startLine("synchronized(").add(arg(cont.getArg())).add(") {");
makeRegionIndent(code, cont.getRegion()); makeRegionIndent(code, cont.getRegion());
code.startLine("}"); code.startLine('}');
} }
private String makeCondition(IfNode insn) throws CodegenException { private String makeCondition(IfNode insn) throws CodegenException {
...@@ -194,25 +194,37 @@ public class RegionGen extends InsnGen { ...@@ -194,25 +194,37 @@ public class RegionGen extends InsnGen {
List<Integer> keys = sw.getKeys().get(i); List<Integer> keys = sw.getKeys().get(i);
IContainer c = sw.getCases().get(i); IContainer c = sw.getCases().get(i);
for (Integer k : keys) { for (Integer k : keys) {
code.startLine("case ") code.startLine("case ");
.add(TypeGen.literalToString(k, arg.getType())) code.add(TypeGen.literalToString(k, arg.getType()));
.add(":"); code.add(':');
} }
makeRegionIndent(code, c); makeCaseBlock(c, code);
if (RegionUtils.hasExitEdge(c))
code.startLine(1, "break;");
} }
if (sw.getDefaultCase() != null) { if (sw.getDefaultCase() != null) {
code.startLine("default:"); code.startLine("default:");
makeRegionIndent(code, sw.getDefaultCase()); makeCaseBlock(sw.getDefaultCase(), code);
if (RegionUtils.hasExitEdge(sw.getDefaultCase()))
code.startLine(1, "break;");
} }
code.decIndent(); code.decIndent();
code.startLine("}"); code.startLine('}');
return code; return code;
} }
private void makeCaseBlock(IContainer c, CodeWriter code) throws CodegenException {
if (RegionUtils.notEmpty(c)) {
boolean closeBlock = RegionUtils.hasExitEdge(c);
if (closeBlock) {
code.add(" {");
}
makeRegionIndent(code, c);
if (closeBlock) {
code.startLine(1, "break;");
code.startLine('}');
}
} else {
code.startLine(1, "break;");
}
}
private void makeTryCatch(IContainer region, TryCatchBlock tryCatchBlock, CodeWriter code) private void makeTryCatch(IContainer region, TryCatchBlock tryCatchBlock, CodeWriter code)
throws CodegenException { throws CodegenException {
code.startLine("try {"); code.startLine("try {");
...@@ -235,7 +247,7 @@ public class RegionGen extends InsnGen { ...@@ -235,7 +247,7 @@ public class RegionGen extends InsnGen {
code.startLine("} finally {"); code.startLine("} finally {");
makeRegionIndent(code, tryCatchBlock.getFinalBlock()); makeRegionIndent(code, tryCatchBlock.getFinalBlock());
} }
code.startLine("}"); code.startLine('}');
} }
private void makeCatchBlock(CodeWriter code, ExceptionHandler handler) private void makeCatchBlock(CodeWriter code, ExceptionHandler handler)
......
...@@ -148,10 +148,13 @@ public class ModVisitor extends AbstractVisitor { ...@@ -148,10 +148,13 @@ public class ModVisitor extends AbstractVisitor {
break; break;
case RETURN: case RETURN:
if (insn.getArgsCount() == 0 if (insn.getArgsCount() == 0) {
&& mth.getBasicBlocks().size() == 1 if (mth.getBasicBlocks().size() == 1 && i == size - 1) {
&& i == size - 1) remover.add(insn);
} else if (mth.getMethodInfo().isClassInit()) {
remover.add(insn); remover.add(insn);
}
}
break; break;
default: default:
......
...@@ -404,7 +404,6 @@ public class RegionMaker { ...@@ -404,7 +404,6 @@ public class RegionMaker {
} }
Map<BlockNode, List<Integer>> blocksMap = new LinkedHashMap<BlockNode, List<Integer>>(len); Map<BlockNode, List<Integer>> blocksMap = new LinkedHashMap<BlockNode, List<Integer>>(len);
for (Entry<Integer, List<Integer>> entry : casesMap.entrySet()) { for (Entry<Integer, List<Integer>> entry : casesMap.entrySet()) {
BlockNode c = BlockUtils.getBlockByOffset(entry.getKey(), block.getSuccessors()); BlockNode c = BlockUtils.getBlockByOffset(entry.getKey(), block.getSuccessors());
assert c != null; assert c != null;
...@@ -413,7 +412,7 @@ public class RegionMaker { ...@@ -413,7 +412,7 @@ public class RegionMaker {
BitSet succ = BlockUtils.blocksToBitSet(mth, block.getSuccessors()); BitSet succ = BlockUtils.blocksToBitSet(mth, block.getSuccessors());
BitSet domsOn = BlockUtils.blocksToBitSet(mth, block.getDominatesOn()); BitSet domsOn = BlockUtils.blocksToBitSet(mth, block.getDominatesOn());
domsOn.andNot(succ); // filter 'out' block domsOn.and(succ); // filter 'out' block
BlockNode defCase = BlockUtils.getBlockByOffset(insn.getDefaultCaseOffset(), block.getSuccessors()); BlockNode defCase = BlockUtils.getBlockByOffset(insn.getDefaultCaseOffset(), block.getSuccessors());
if (defCase != null) { if (defCase != null) {
...@@ -458,8 +457,13 @@ public class RegionMaker { ...@@ -458,8 +457,13 @@ public class RegionMaker {
} }
for (Entry<BlockNode, List<Integer>> entry : blocksMap.entrySet()) { for (Entry<BlockNode, List<Integer>> entry : blocksMap.entrySet()) {
BlockNode c = entry.getKey(); BlockNode c = entry.getKey();
if (stack.containsExit(c)) {
// empty case block
sw.addCase(entry.getValue(), new Region(stack.peekRegion()));
} else {
sw.addCase(entry.getValue(), makeRegion(c, stack)); sw.addCase(entry.getValue(), makeRegion(c, stack));
} }
}
stack.pop(); stack.pop();
return out; return out;
......
...@@ -15,4 +15,13 @@ public abstract class AbstractTest { ...@@ -15,4 +15,13 @@ public abstract class AbstractTest {
throw new AssertionError(a1 + " != " + a2); throw new AssertionError(a1 + " != " + a2);
} }
} }
public static void assertEquals(Object a1, Object a2) {
if (a1 == null) {
if (a2 != null)
throw new AssertionError(a1 + " != " + a2);
} else if (!a1.equals(a2)) {
throw new AssertionError(a1 + " != " + a2);
}
}
} }
...@@ -78,13 +78,43 @@ public class TestSwitch extends AbstractTest { ...@@ -78,13 +78,43 @@ public class TestSwitch extends AbstractTest {
return -1; return -1;
} }
public String escape(String str) {
int len = str.length();
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++) {
char c = str.charAt(i);
switch (c) {
case '.':
case '/':
sb.append('_');
break;
case ']':
sb.append('A');
break;
case '?':
break;
default:
sb.append(c);
break;
}
}
return sb.toString();
}
@Override @Override
public boolean testRun() { public boolean testRun() {
assertTrue(test1(25) == 2); assertTrue(test1(25) == 2);
assertTrue(test2(5) == 3); assertTrue(test2(5) == 3);
assertTrue(test3(1, 0) == 0); assertTrue(test3(1, 0) == 0);
assertTrue(test4(2) == 1); assertTrue(test4(2) == 1);
assertEquals(escape("a.b/c]d?e"), "a_b_cAde");
return true; return true;
} }
public static void main(String[] args) {
new TestSwitch().testRun();
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment