]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/If.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / ssa / exits / If.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/If.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/If.java
new file mode 100644 (file)
index 0000000..0f4673a
--- /dev/null
@@ -0,0 +1,203 @@
+package org.simantics.scl.compiler.internal.codegen.ssa.exits;
+
+import java.util.ArrayList;
+
+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.internal.codegen.continuations.Cont;
+import org.simantics.scl.compiler.internal.codegen.continuations.ContRef;
+import org.simantics.scl.compiler.internal.codegen.references.Val;
+import org.simantics.scl.compiler.internal.codegen.references.ValRef;
+import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock;
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAExit;
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
+import org.simantics.scl.compiler.internal.codegen.ssa.binders.ValRefBinder;
+import org.simantics.scl.compiler.internal.codegen.utils.CopyContext;
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
+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.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+
+public class If extends SSAExit implements ValRefBinder {
+    private ValRef condition;
+    private ContRef thenTarget;
+    private ContRef elseTarget;
+    
+    public If(ValRef condition, ContRef thenTarget, ContRef elseTarget) {
+        setCondition(condition);
+        setThenTarget(thenTarget);
+        setElseTarget(elseTarget);
+    }
+    
+    public void setCondition(ValRef condition) {
+        this.condition = condition;
+        condition.setParent(this);
+    }
+    
+    public void setThenTarget(ContRef thenTarget) {
+        this.thenTarget = thenTarget;
+        thenTarget.setParent(this);
+    }
+    
+    public void setElseTarget(ContRef elseTarget) {
+        this.elseTarget = elseTarget;
+        elseTarget.setParent(this);
+    }
+
+    @Override
+    public void generateCode(MethodBuilder mb) {
+        mb.push(condition.getBinding(), Types.BOOLEAN);
+        Label elseLabel = mb.getLabel(elseTarget.getBinding());
+        mb.ifZeroComparisonBranch(elseLabel, "==");
+        mb.jump(thenTarget.getBinding());
+        mb.ensureExists(elseTarget.getBinding());
+    }
+
+    @Override
+    public void toString(PrintingContext context) {
+        context.append("if ");
+        context.append(condition);
+        context.append(" then ");
+        {
+            Cont thenCont = thenTarget.getBinding();
+            if(thenCont instanceof SSABlock) {
+                SSABlock thenBlock = (SSABlock)thenCont;
+                if(thenCont.hasMoreThanOneOccurences()) {
+                    context.append(thenCont);
+                    context.addBlock(thenBlock);
+                    context.append(' ');
+                }
+                else {
+                    context.append('\n');
+                    thenBlock.bodyToString(context);
+                    context.indentation();
+                }
+            }
+            else {
+                context.append(thenCont);
+                context.append(' ');
+            }
+        }        
+        context.append("else ");
+        {
+            Cont elseCont = elseTarget.getBinding();
+            if(elseCont instanceof SSABlock) {
+                SSABlock elseBlock = (SSABlock)elseCont;
+                if(elseCont.hasMoreThanOneOccurences()) {
+                    context.append(elseCont);
+                    context.addBlock(elseBlock);
+                    context.append('\n');
+                }
+                else {
+                    context.append('\n');
+                    elseBlock.bodyToString(context);
+                }
+            }
+            else {
+                context.append(elseCont);
+                context.append('\n');
+            }
+        }
+    }
+
+    @Override
+    public void validate(SSAValidationContext context) {
+        context.validate(condition);
+        context.validate(elseTarget);
+        context.validate(thenTarget);
+        if(condition.getParent() != this)
+            throw new InternalCompilerError();
+        if(elseTarget.getParent() != this)
+            throw new InternalCompilerError();
+        if(thenTarget.getParent() != this)
+            throw new InternalCompilerError();
+        context.assertEquals(this, condition.getType(), Types.BOOLEAN);
+        context.assertEquals(elseTarget.getBinding().getArity(), 0);
+        context.assertEquals(thenTarget.getBinding().getArity(), 0);
+    }
+
+    @Override
+    public void destroy() {
+        condition.remove();
+        elseTarget.remove();
+        thenTarget.remove();
+    }
+
+    @Override
+    public SSAExit copy(CopyContext context) {
+        return new If(context.copy(condition),
+                context.copy(thenTarget),
+                context.copy(elseTarget));
+    }
+    
+    @Override
+    public void replace(TVar[] vars, Type[] replacements) {
+        condition.replace(vars, replacements);        
+    }
+    
+    @Override
+    public void simplify(SSASimplificationContext context) {
+        Val cond = condition.getBinding();
+        if(cond instanceof BooleanConstant) {
+            SSAExit newExit;
+            if(((BooleanConstant) cond).getValue()) {
+                newExit = new Jump(thenTarget);
+                elseTarget.remove();
+            }
+            else {
+                newExit = new Jump(elseTarget);
+                thenTarget.remove();
+            }
+            condition.remove();
+            getParent().setExit(newExit);
+            context.markModified("beta-if");
+        }
+        else if(thenTarget.getBinding() == elseTarget.getBinding()) {
+            elseTarget.remove();
+            condition.remove();
+            getParent().setExit(new Jump(thenTarget));
+            context.markModified("equal-branches-if");
+        }
+    }
+
+    @Override
+    public void collectFreeVariables(SSAFunction function,
+            ArrayList<ValRef> vars) {
+        condition.collectFreeVariables(function, vars);
+    }
+    
+    @Override
+    public Cont addParametersInFrontOf(ContRef contRef, Val[] newParameters, Val[] oldParameters,
+            Cont proxy) {
+        if(proxy == null)
+            proxy = contRef.getBinding().createProxy(getParent().getParent(), newParameters, oldParameters);
+        ContRef proxyRef = proxy.createOccurrence();
+        if(thenTarget == contRef)
+            setThenTarget(proxyRef);
+        else
+            setElseTarget(proxyRef);
+        return proxy;
+    }
+
+    @Override
+    public SSABlock[] getSuccessors() {
+        Cont thenCont = thenTarget.getBinding();
+        Cont elseCont = elseTarget.getBinding();
+        if(thenCont instanceof SSABlock) {
+            if(elseCont instanceof SSABlock)
+                return new SSABlock[] {(SSABlock)thenCont, (SSABlock)elseCont};
+            else
+                return new SSABlock[] {(SSABlock)thenCont};
+        }
+        else {
+            if(elseCont instanceof SSABlock)
+                return new SSABlock[] {(SSABlock)elseCont};
+            else
+                return SSABlock.EMPTY_ARRAY;
+        }
+    }
+}