]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Switch.java
SCL compiler generates line numbers to bytecode
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / ssa / exits / Switch.java
index 0bcb3dd596e3bc03cbc91779d40232ce3d787c02..55f38f809b540acbea4e3cf7baa47877e5965e1d 100644 (file)
@@ -1,11 +1,13 @@
 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;
@@ -25,12 +27,15 @@ import org.simantics.scl.compiler.types.TVar;
 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);
@@ -59,14 +64,19 @@ public class Switch extends SSAExit implements ValRefBinder {
         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();
@@ -81,6 +91,7 @@ public class Switch extends SSAExit implements ValRefBinder {
 
     @Override
     public void generateCode(MethodBuilder mb) {
+        mb.lineNumber(lineNumber);
         if(isIntegerSwitch()) {
             generateIntegerSwitch(mb);
             return;
@@ -159,7 +170,7 @@ public class Switch extends SSAExit implements ValRefBinder {
     
     @Override
     public SSAExit copy(CopyContext context) {
-        return new Switch(context.copy(scrutinee), 
+        return new Switch(lineNumber, context.copy(scrutinee), 
                 BranchRef.copy(context, branches));
     }
 
@@ -212,10 +223,11 @@ public class Switch extends SSAExit implements ValRefBinder {
             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);
             }
@@ -223,11 +235,15 @@ public class Switch extends SSAExit implements ValRefBinder {
             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,
@@ -266,4 +282,9 @@ public class Switch extends SSAExit implements ValRefBinder {
     public void forValRefs(ValRefVisitor visitor) {
         visitor.visit(scrutinee);
     }
+
+    @Override
+    public void cleanup() {
+        scrutinee.remove();
+    }
 }