Fix switch generation for general case

This commit is contained in:
Alexey Andreev 2016-08-12 21:44:52 +03:00
parent 850609bb72
commit 1aacbea4d0

View File

@ -15,6 +15,7 @@
*/ */
package org.teavm.wasm.generate; package org.teavm.wasm.generate;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
@ -490,19 +491,36 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
public void visit(SwitchStatement statement) { public void visit(SwitchStatement statement) {
WasmBlock defaultBlock = new WasmBlock(false); WasmBlock defaultBlock = new WasmBlock(false);
int min = statement.getClauses().stream()
.flatMapToInt(clause -> Arrays.stream(clause.getConditions()))
.min().orElse(0);
int max = statement.getClauses().stream()
.flatMapToInt(clause -> Arrays.stream(clause.getConditions()))
.max().orElse(0);
breakTargets.put(statement, defaultBlock); breakTargets.put(statement, defaultBlock);
IdentifiedStatement oldBreakTarget = currentBreakTarget; IdentifiedStatement oldBreakTarget = currentBreakTarget;
currentBreakTarget = statement; currentBreakTarget = statement;
WasmBlock wrapper = new WasmBlock(false); WasmBlock wrapper = new WasmBlock(false);
statement.getValue().acceptVisitor(this); statement.getValue().acceptVisitor(this);
if (min > 0) {
result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SUB, result,
new WasmInt32Constant(min));
}
WasmSwitch wasmSwitch = new WasmSwitch(result, wrapper); WasmSwitch wasmSwitch = new WasmSwitch(result, wrapper);
wrapper.getBody().add(wasmSwitch); wrapper.getBody().add(wasmSwitch);
WasmBlock[] targets = new WasmBlock[max - min + 1];
for (SwitchClause clause : statement.getClauses()) { for (SwitchClause clause : statement.getClauses()) {
WasmBlock caseBlock = new WasmBlock(false); WasmBlock caseBlock = new WasmBlock(false);
caseBlock.getBody().add(wrapper); caseBlock.getBody().add(wrapper);
wasmSwitch.getTargets().add(wrapper);
for (int condition : clause.getConditions()) {
targets[condition - min] = wrapper;
}
for (Statement part : clause.getBody()) { for (Statement part : clause.getBody()) {
part.acceptVisitor(this); part.acceptVisitor(this);
if (result != null) { if (result != null) {
@ -522,6 +540,10 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
wasmSwitch.setDefaultTarget(wrapper); wasmSwitch.setDefaultTarget(wrapper);
wrapper = defaultBlock; wrapper = defaultBlock;
for (WasmBlock target : targets) {
wasmSwitch.getTargets().add(target != null ? target : wasmSwitch.getDefaultTarget());
}
breakTargets.remove(statement); breakTargets.remove(statement);
currentBreakTarget = oldBreakTarget; currentBreakTarget = oldBreakTarget;