package org.simantics.scl.compiler.internal.codegen.ssa.exits;
import java.util.ArrayList;
+import java.util.Arrays;
import org.objectweb.asm.Label;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.constants.BooleanConstant;
import org.simantics.scl.compiler.constants.IntegerConstant;
+import org.simantics.scl.compiler.constants.NoRepConstant;
import org.simantics.scl.compiler.internal.codegen.continuations.BranchRef;
import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
import org.simantics.scl.compiler.internal.codegen.continuations.ContRef;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
+import gnu.trove.map.hash.TIntObjectHashMap;
+
public class Switch extends SSAExit implements ValRefBinder {
ValRef scrutinee;
BranchRef[] branches;
- public Switch(ValRef scrutinee, BranchRef[] branches) {
+ public Switch(int lineNumber, ValRef scrutinee, BranchRef[] branches) {
+ super(lineNumber);
this.scrutinee = scrutinee;
this.branches = branches;
scrutinee.setParent(this);
int defaultId;
for(defaultId=0;defaultId<branches.length-1&&branches[defaultId].constructor!=null;++defaultId);
int[] values = new int[defaultId];
- Label[] labels = new Label[defaultId];
Cont[] continuations = new Cont[defaultId+1];
+ TIntObjectHashMap<Label> labelMap = new TIntObjectHashMap<Label>(defaultId);
for(int i=0;i<defaultId;++i) {
- values[i] = ((IntegerConstant)branches[i].constructor).getValue();
+ int value = ((IntegerConstant)branches[i].constructor).getValue();
+ values[i] = value;
Cont cont = branches[i].cont.getBinding();
- labels[i] = mb.getLabel(cont);
+ labelMap.put(value, mb.getLabel(cont));
continuations[i] = cont;
}
+ Arrays.sort(values);
+ Label[] labels = new Label[defaultId];
+ for(int i=0;i<defaultId;++i)
+ labels[i] = labelMap.get(values[i]);
Label defaultLabel;
{
Cont cont = branches[defaultId].cont.getBinding();
@Override
public void generateCode(MethodBuilder mb) {
+ mb.lineNumber(lineNumber);
if(isIntegerSwitch()) {
generateIntegerSwitch(mb);
return;
@Override
public SSAExit copy(CopyContext context) {
- return new Switch(context.copy(scrutinee),
+ return new Switch(lineNumber, context.copy(scrutinee),
BranchRef.copy(context, branches));
}
SSAExit newExit;
if(thenTarget == elseTarget) {
scrutinee.remove();
- newExit = new Jump(thenTarget);
+ newExit = new Jump(lineNumber, thenTarget);
}
else {
- newExit = new If(scrutinee,
+ newExit = new If(lineNumber,
+ scrutinee,
thenTarget,
elseTarget);
}
context.markModified("switch-to-if");
newExit.simplify(context);
}
- else if(branches.length == 1 && branches[0].constructor == null) {
+ else if(branches.length == 1 && isConstructorParameterless(branches[0])) {
scrutinee.remove();
- getParent().setExit(new Jump(branches[0].cont));
+ getParent().setExit(new Jump(lineNumber, branches[0].cont));
}
}
+
+ private static boolean isConstructorParameterless(BranchRef branch) {
+ return branch.constructor == null || branch.constructor instanceof NoRepConstant;
+ }
@Override
public void collectFreeVariables(SSAFunction function,
public void forValRefs(ValRefVisitor visitor) {
visitor.visit(scrutinee);
}
+
+ @Override
+ public void cleanup() {
+ scrutinee.remove();
+ }
}