//
// Pull in code of cases.
//
final Label[] labels = caseLabels.get();
final SwitchInfo switchInfo = switchExpression.getUserData(AstKeys.SWITCH_INFO);
final int lowValue = switchInfo.getLowValue();
final int[] keys = switchInfo.getKeys();
final Label defaultLabel = labels[0];
final ControlFlowNode defaultTarget = labelsToNodes.get(defaultLabel);
boolean defaultFollowsSwitch = false;
for (int i = 1; i < labels.length; i++) {
final Label caseLabel = labels[i];
if (caseLabel == defaultLabel) {
continue;
}
//
// Find or create a new case block.
//
CaseBlock caseBlock = null;
for (final CaseBlock cb : switchNode.getCaseBlocks()) {
if (cb.getEntryGoto().getOperand() == caseLabel) {
caseBlock = cb;
break;
}
}
if (caseBlock == null) {
caseBlock = new CaseBlock();
caseBlock.setEntryGoto(new Expression(AstCode.Goto, caseLabel, Expression.MYSTERY_OFFSET));
final ControlFlowNode caseTarget = labelsToNodes.get(caseLabel);
final List<Node> caseBody = caseBlock.getBody();
switchNode.getCaseBlocks().add(caseBlock);
if (caseTarget != null) {
if (caseTarget.getDominanceFrontier().contains(defaultTarget)) {
defaultFollowsSwitch = true;
}
final Set<ControlFlowNode> content = findDominatedNodes(scope, caseTarget);
scope.removeAll(content);
caseBody.addAll(findConditions(content, caseTarget));
}
else {
final BasicBlock explicitGoto = new BasicBlock();
explicitGoto.getBody().add(new Label("SwitchGoto_" + _nextLabelIndex++));
explicitGoto.getBody().add(new Expression(AstCode.Goto, caseLabel, Expression.MYSTERY_OFFSET));
caseBody.add(explicitGoto);
}
if (caseBody.isEmpty() ||
!matchLast((BasicBlock) caseBody.get(caseBody.size() - 1), AstCode.Goto, tempTarget) ||
!ArrayUtilities.contains(labels, tempTarget.get())) {
//
// Add explicit break that should not be used by default, but which might be used
// by goto removal.
//
final BasicBlock explicitBreak = new BasicBlock();
explicitBreak.getBody().add(new Label("SwitchBreak_" + _nextLabelIndex++));
explicitBreak.getBody().add(new Expression(AstCode.LoopOrSwitchBreak, null, Expression.MYSTERY_OFFSET));
caseBody.add(explicitBreak);
}
}
if (switchInfo.hasKeys()) {
caseBlock.getValues().add(keys[i - 1]);
}
else {
caseBlock.getValues().add(lowValue + i - 1);
}