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.internal.codegen.utils.PrintingContext;
import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;
import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;
+import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
public BranchRef[] getBranches() {
return branches;
}
+
+ private boolean isIntegerSwitch() {
+ if(scrutinee.getType() != Types.INTEGER)
+ return false;
+ for(BranchRef branch : branches)
+ if(branch.constructor != null && !(branch.constructor instanceof IntegerConstant))
+ return false;
+ return true;
+ }
+
+ private void generateIntegerSwitch(MethodBuilder mb) {
+ 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];
+ for(int i=0;i<defaultId;++i) {
+ values[i] = ((IntegerConstant)branches[i].constructor).getValue();
+ Cont cont = branches[i].cont.getBinding();
+ labels[i] = mb.getLabel(cont);
+ continuations[i] = cont;
+ }
+ Label defaultLabel;
+ {
+ Cont cont = branches[defaultId].cont.getBinding();
+ defaultLabel = mb.getLabel(cont);
+ continuations[defaultId] = cont;
+ }
+ mb.push(scrutinee, Types.INTEGER);
+ mb.switch_(values, labels, defaultLabel);
+ for(Cont cont : continuations)
+ mb.ensureExists(cont);
+ }
@Override
public void generateCode(MethodBuilder mb) {
+ if(isIntegerSwitch()) {
+ generateIntegerSwitch(mb);
+ return;
+ }
for(int i=0;i<branches.length;++i) {
BranchRef branch = branches[i];
- if(branch.constructor == null) {
+ if(branch.constructor == null)
mb.jump(branch.cont);
- }
else if(i < branches.length-1) {
Label failure = mb.createLabel();
branch.constructor.deconstruct(mb, scrutinee,
branch.cont.getBinding(), failure);
mb.setLocation(failure);
}
- else {
+ else
branch.constructor.deconstruct(mb, scrutinee,
branch.cont.getBinding(), null);
- }
}
}
Cont cont = branch.cont.getBinding();
if(cont instanceof SSABlock) {
SSABlock block = (SSABlock)cont;
- if(cont.hasMoreThanOneOccurences()) {
+ //if(cont.hasMoreThanOneOccurences()) {
context.append(cont);
context.append('\n');
context.addBlock(block);
- }
+ /*}
else {
block.parametersToString(context);
context.append('\n');
block.bodyToString(context);
- }
+ }*/
}
else {
context.append(cont);
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));
}
}
+
+ private static boolean isConstructorParameterless(BranchRef branch) {
+ return branch.constructor == null || branch.constructor instanceof NoRepConstant;
+ }
@Override
public void collectFreeVariables(SSAFunction function,
}
return result.toArray(new SSABlock[result.size()]);
}
+
+ @Override
+ public void forValRefs(ValRefVisitor visitor) {
+ visitor.visit(scrutinee);
+ }
}