return lookupSwitchInfo;
}
private InstructionList reduce_lookup_switchStmt(IASNode iNode, InstructionList switch_expr, Vector<ConditionalFragment> cases, LookupSwitchInfo lookupSwitchInfo)
{
InstructionList result = createInstructionList(iNode);
result.addAll(switch_expr);
result.addInstruction(OP_convert_i);
// save some space in the case table, by not generating entries
// for any values between 0 and the min case value
int caseOffset = 0;
if (lookupSwitchInfo.minCase > 0)
{
caseOffset = lookupSwitchInfo.minCase;
lookupSwitchInfo.minCase = 0;
lookupSwitchInfo.maxCase = lookupSwitchInfo.maxCase - caseOffset;
result.addInstruction(OP_pushint, Integer.valueOf(caseOffset));
result.addInstruction(OP_subtract_i);
}
// if we have negative values in the case expression, need
// to offset from zero
else if (lookupSwitchInfo.minCase < 0)
{
caseOffset = lookupSwitchInfo.minCase;
lookupSwitchInfo.minCase = 0;
lookupSwitchInfo.maxCase = lookupSwitchInfo.maxCase - caseOffset;
result.addInstruction(OP_pushint, new Integer(lookupSwitchInfo.minCase + 1));
result.addInstruction(OP_add_i);
}
Label switchTail = null;
Label defaultLabel;
if (lookupSwitchInfo.defaultCase != null)
defaultLabel = lookupSwitchInfo.defaultCase.getLabel();
else
defaultLabel = switchTail = new Label();
// generate the case table, maxCase+2, as count from zero
// and add one for the default label at the end
Label[] caseLabels = new Label[lookupSwitchInfo.maxCase + 2];
// pre-fill the case label table with the default label.
Arrays.fill(caseLabels, defaultLabel);
// fill in specific labels for any specified values
for (ConditionalFragment current_case : cases)
{
if (current_case.isUnconditionalAlternative())
continue;
Object caseValue = current_case.constantCondition;
// a constant of value 90000 was in a SWC as a double even though
// the type of the constant was int
if (caseValue instanceof Double)
caseValue = new Integer(((Double)caseValue).intValue());
assert (caseValue instanceof Integer) : "reduce_lookup_switchStmt called on non integer case value";
final int index = (Integer)caseValue - caseOffset;
// if there is already a non-default value for this
// index, ignore it, as only the first case counts
if (caseLabels[index] != defaultLabel)
continue;
caseLabels[index] = current_case.getLabel();
}
result.addInstruction(OP_lookupswitch, caseLabels);
Label default_case_label = null;
for (ConditionalFragment current_case : cases)
{
if (current_case.isUnconditionalAlternative())
{
// The parser rejects duplicate default alternatives
// in some situations, but not in others.
if (default_case_label == null)
default_case_label = current_case.statement.getLabel();
else
currentScope.addProblem(new MultipleSwitchDefaultsProblem(current_case.site));
}
result.addAll(current_case.statement);
}
switchTail = addInterstitialControlFlow(result, switchTail);
// No continue here, and thus there is no need
// to check for previous labeled flow contexts.
currentScope.getFlowManager().finishSwitchControlFlowContext(result);
if ( switchTail != null )
result.labelNext(switchTail);
return result;
}