Fix 'switch' codegen for empty case block
This commit is contained in:
@@ -36,6 +36,13 @@ public class CodeWriter {
|
||||
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) {
|
||||
buf.append(NL);
|
||||
buf.append(indentStr);
|
||||
|
||||
@@ -107,7 +107,7 @@ public class RegionGen extends InsnGen {
|
||||
IfNode insn = region.getIfInsn();
|
||||
code.add("if ").add(makeCondition(insn)).add(" {");
|
||||
makeRegionIndent(code, region.getThenRegion());
|
||||
code.startLine("}");
|
||||
code.startLine('}');
|
||||
|
||||
IContainer els = region.getElseRegion();
|
||||
if (els != null && RegionUtils.notEmpty(els)) {
|
||||
@@ -123,11 +123,11 @@ public class RegionGen extends InsnGen {
|
||||
}
|
||||
}
|
||||
|
||||
code.add("{");
|
||||
code.add('{');
|
||||
code.incIndent();
|
||||
makeRegion(code, els);
|
||||
code.decIndent();
|
||||
code.startLine("}");
|
||||
code.startLine('}');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ public class RegionGen extends InsnGen {
|
||||
// infinite loop
|
||||
code.startLine("while (true) {");
|
||||
makeRegionIndent(code, region.getBody());
|
||||
code.startLine("}");
|
||||
code.startLine('}');
|
||||
return code;
|
||||
}
|
||||
|
||||
@@ -144,11 +144,11 @@ public class RegionGen extends InsnGen {
|
||||
if (!region.isConditionAtEnd()) {
|
||||
code.startLine("while ").add(makeCondition(insn)).add(" {");
|
||||
makeRegionIndent(code, region.getBody());
|
||||
code.startLine("}");
|
||||
code.startLine('}');
|
||||
} else {
|
||||
code.startLine("do {");
|
||||
makeRegionIndent(code, region.getBody());
|
||||
code.startLine("} while ").add(makeCondition(insn)).add(";");
|
||||
code.startLine("} while ").add(makeCondition(insn)).add(';');
|
||||
}
|
||||
return code;
|
||||
}
|
||||
@@ -156,7 +156,7 @@ public class RegionGen extends InsnGen {
|
||||
private void makeSynchronizedRegion(SynchronizedRegion cont, CodeWriter code) throws CodegenException {
|
||||
code.startLine("synchronized(").add(arg(cont.getArg())).add(") {");
|
||||
makeRegionIndent(code, cont.getRegion());
|
||||
code.startLine("}");
|
||||
code.startLine('}');
|
||||
}
|
||||
|
||||
private String makeCondition(IfNode insn) throws CodegenException {
|
||||
@@ -194,25 +194,37 @@ public class RegionGen extends InsnGen {
|
||||
List<Integer> keys = sw.getKeys().get(i);
|
||||
IContainer c = sw.getCases().get(i);
|
||||
for (Integer k : keys) {
|
||||
code.startLine("case ")
|
||||
.add(TypeGen.literalToString(k, arg.getType()))
|
||||
.add(":");
|
||||
code.startLine("case ");
|
||||
code.add(TypeGen.literalToString(k, arg.getType()));
|
||||
code.add(':');
|
||||
}
|
||||
makeRegionIndent(code, c);
|
||||
if (RegionUtils.hasExitEdge(c))
|
||||
code.startLine(1, "break;");
|
||||
makeCaseBlock(c, code);
|
||||
}
|
||||
if (sw.getDefaultCase() != null) {
|
||||
code.startLine("default:");
|
||||
makeRegionIndent(code, sw.getDefaultCase());
|
||||
if (RegionUtils.hasExitEdge(sw.getDefaultCase()))
|
||||
code.startLine(1, "break;");
|
||||
makeCaseBlock(sw.getDefaultCase(), code);
|
||||
}
|
||||
code.decIndent();
|
||||
code.startLine("}");
|
||||
code.startLine('}');
|
||||
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)
|
||||
throws CodegenException {
|
||||
code.startLine("try {");
|
||||
@@ -235,7 +247,7 @@ public class RegionGen extends InsnGen {
|
||||
code.startLine("} finally {");
|
||||
makeRegionIndent(code, tryCatchBlock.getFinalBlock());
|
||||
}
|
||||
code.startLine("}");
|
||||
code.startLine('}');
|
||||
}
|
||||
|
||||
private void makeCatchBlock(CodeWriter code, ExceptionHandler handler)
|
||||
|
||||
@@ -148,10 +148,13 @@ public class ModVisitor extends AbstractVisitor {
|
||||
break;
|
||||
|
||||
case RETURN:
|
||||
if (insn.getArgsCount() == 0
|
||||
&& mth.getBasicBlocks().size() == 1
|
||||
&& i == size - 1)
|
||||
remover.add(insn);
|
||||
if (insn.getArgsCount() == 0) {
|
||||
if (mth.getBasicBlocks().size() == 1 && i == size - 1) {
|
||||
remover.add(insn);
|
||||
} else if (mth.getMethodInfo().isClassInit()) {
|
||||
remover.add(insn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -404,7 +404,6 @@ public class RegionMaker {
|
||||
}
|
||||
|
||||
Map<BlockNode, List<Integer>> blocksMap = new LinkedHashMap<BlockNode, List<Integer>>(len);
|
||||
|
||||
for (Entry<Integer, List<Integer>> entry : casesMap.entrySet()) {
|
||||
BlockNode c = BlockUtils.getBlockByOffset(entry.getKey(), block.getSuccessors());
|
||||
assert c != null;
|
||||
@@ -413,7 +412,7 @@ public class RegionMaker {
|
||||
|
||||
BitSet succ = BlockUtils.blocksToBitSet(mth, block.getSuccessors());
|
||||
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());
|
||||
if (defCase != null) {
|
||||
@@ -458,7 +457,12 @@ public class RegionMaker {
|
||||
}
|
||||
for (Entry<BlockNode, List<Integer>> entry : blocksMap.entrySet()) {
|
||||
BlockNode c = entry.getKey();
|
||||
sw.addCase(entry.getValue(), makeRegion(c, stack));
|
||||
if (stack.containsExit(c)) {
|
||||
// empty case block
|
||||
sw.addCase(entry.getValue(), new Region(stack.peekRegion()));
|
||||
} else {
|
||||
sw.addCase(entry.getValue(), makeRegion(c, stack));
|
||||
}
|
||||
}
|
||||
|
||||
stack.pop();
|
||||
|
||||
@@ -15,4 +15,13 @@ public abstract class AbstractTest {
|
||||
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 {
|
||||
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
|
||||
public boolean testRun() {
|
||||
assertTrue(test1(25) == 2);
|
||||
assertTrue(test2(5) == 3);
|
||||
assertTrue(test3(1, 0) == 0);
|
||||
assertTrue(test4(2) == 1);
|
||||
assertEquals(escape("a.b/c]d?e"), "a_b_cAde");
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new TestSwitch().testRun();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user