]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAFunction.java
(refs #7250) CHR rules modularization (first working version)
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / ssa / SSAFunction.java
index c812db7c4476a3b8078847ad045d359cf618afc3..ab643f9a15b1669be060ae165c07a403cb3888c3 100644 (file)
@@ -5,41 +5,34 @@ import java.util.Arrays;
 
 import org.cojen.classfile.TypeDesc;
 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.constants.NoRepConstant;
 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.continuations.ReturnCont;
 import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
 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.binders.BoundVarBinder;
-import org.simantics.scl.compiler.internal.codegen.ssa.binders.FunctionBinder;
 import org.simantics.scl.compiler.internal.codegen.ssa.exits.Jump;
 import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;
 import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetFunctions;
 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
 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.Printable;
 import org.simantics.scl.compiler.internal.codegen.utils.PrintingContext;
 import org.simantics.scl.compiler.internal.codegen.utils.SSALambdaLiftingContext;
 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 final class SSAFunction implements Printable, BoundVarBinder {
-    Val target;
-    
+public final class SSAFunction extends SSAClosure {
     TVar[] typeParameters;
     Type effect;
     SSABlock firstBlock;
     SSABlock lastBlock;
-    ReturnCont returnCont;    
-    
-    FunctionBinder parent;
-    SSAFunction prev;
-    SSAFunction next;    
+    ReturnCont returnCont;
     
     public SSAFunction(TVar[] typeParameters, Type effect, Type returnType) {
         this(typeParameters, effect, new ReturnCont(returnType));
@@ -51,21 +44,6 @@ public final class SSAFunction implements Printable, BoundVarBinder {
         this.effect = Types.canonical(effect);
         returnCont.setParent(this);
     }
-
-    public Val getTarget() {
-        return target;
-    }
-    
-    public void setTarget(Val target) {
-        this.target = target;
-        if(target instanceof BoundVar)
-            ((BoundVar) target).parent = this;             
-    }
-    
-    public void setTarget(BoundVar target) {
-        this.target = target;
-        target.parent = this;             
-    }
     
     public boolean hasEffect() {
         return effect != Types.NO_EFFECTS;
@@ -116,6 +94,10 @@ public final class SSAFunction implements Printable, BoundVarBinder {
         for(int i=0,j=0;i<firstBlock.parameters.length;++i)
             if(!tt.toTypeDesc(firstBlock.parameters[i].getType()).equals(TypeDesc.VOID))
                 mb.setLocalVariable(firstBlock.parameters[i], mb.getParameter(j++));
+        generateCodeWithAlreadyPreparedParameters(mb);
+    }
+    
+    public void generateCodeWithAlreadyPreparedParameters(MethodBuilder mb) {
         for(SSABlock block = firstBlock; block != null; block = block.next)
             block.prepare(mb);
         firstBlock.generateCode(mb);
@@ -188,21 +170,97 @@ public final class SSAFunction implements Printable, BoundVarBinder {
         //context.reset(); // FIXME not good when there are nested functions
     }
     
-    public void simplify(SSASimplificationContext context) {        
-        /*if(target instanceof BoundVar) {
-            tryToMakeMonadic(context);
-        }*/
+    @Override
+    public void simplify(SSASimplificationContext context) {
         for(SSABlock block = firstBlock; block != null; block = block.next)
             block.simplify(context);
-        if(firstBlock == lastBlock && firstBlock.firstStatement == firstBlock.lastStatement &&
-                firstBlock.firstStatement instanceof LetFunctions) {
-            simplifySingleLambda(context);            
+        if(firstBlock == lastBlock && firstBlock.firstStatement == firstBlock.lastStatement) {
+            if(firstBlock.firstStatement instanceof LetApply)
+                simplifySingleApply(context);
+            else if(firstBlock.firstStatement instanceof LetFunctions)
+                simplifySingleLambda(context);
         }
     }
     
+    
+    /**
+     * Simplifies the following kind of function definition
+     *     \x -> f x
+     * to
+     *     f
+     */
+    private void simplifySingleApply(SSASimplificationContext context) {
+        if(!(parent instanceof LetFunctions) || parent.getFirstClosure().next != null)
+            return;
+        LetApply apply = (LetApply)firstBlock.firstStatement;
+        if(!(firstBlock.exit instanceof Jump))
+            return;
+        Jump exit = (Jump)firstBlock.exit;
+        if(exit.getTarget().getBinding() != returnCont)
+            return;
+        if(exit.getParameter(0).getBinding() != apply.getTarget())
+            return;
+        BoundVar[] functionParameters = getParameters();
+        ValRef[] applyParameters = apply.getParameters();
+        if(functionParameters.length > applyParameters.length)
+            return;
+        int extraApplyParameters = applyParameters.length - functionParameters.length;
+        for(int i=0;i<functionParameters.length;++i)
+            if(!representSameValues(functionParameters[i], applyParameters[extraApplyParameters+i]))
+                return;
+        for(int i=0;i<extraApplyParameters;++i) {
+            Val b = applyParameters[i].getBinding();
+            if(b instanceof BoundVar) {
+                BoundVar bv = (BoundVar)b;
+                if(bv == target || bv.getParent() == firstBlock)
+                    return;
+            }
+        }
+        if(!(target instanceof BoundVar))
+            return;
+        
+        // Transform
+        
+        LetFunctions binder = (LetFunctions)parent;
+        SSAFunction parentFunction = binder.getParentFunction();
+        if(extraApplyParameters > 0) {
+            //System.out.println("-------------------------------------------------------------");
+            //System.out.println(parentFunction);
+            //System.out.println("-------------------------------------------------------------");
+            apply.setTarget((BoundVar)target);
+            apply.setParameters(Arrays.copyOf(applyParameters, extraApplyParameters));
+            apply.insertBefore(binder);
+            binder.detach();
+            //System.out.println(parentFunction);
+            //System.out.println("-------------------------------------------------------------");
+        }
+        else {
+            binder.detach();
+            ((BoundVar)target).replaceBy(apply.getFunction());
+        }
+        context.markModified("SSAFunction.eta-reduce");
+    }
+    
+    private boolean representSameValues(BoundVar boundVar, ValRef valRef) {
+        Val val = valRef.getBinding(); 
+        if(val == boundVar && valRef.getTypeParameters().length == 0)
+            return true;
+        if(val instanceof NoRepConstant && Types.equals(valRef.getType(), boundVar.getType()))
+            return true;
+        return false;
+    }
+
+    /**
+     * Simplifies the following kind of function definition
+     *     \x -> \y -> e
+     * to
+     *     \x y -> e
+     */
     private void simplifySingleLambda(SSASimplificationContext context) {
         LetFunctions letF = (LetFunctions)firstBlock.firstStatement;
-        SSAFunction f = letF.getFirstFunction();
+        if(!(letF.getFirstClosure() instanceof SSAFunction))
+            return;
+        SSAFunction f = (SSAFunction)letF.getFirstClosure();
         if(f.getNext() != null)
             return;
         Val fVal = f.getTarget();
@@ -221,7 +279,7 @@ public final class SSAFunction implements Printable, BoundVarBinder {
         lastBlock = f.lastBlock;
         
         firstBlock.firstStatement = firstBlock.lastStatement = null;
-        setReturnCont(f.getReturnCont());        
+        setReturnCont(f.getReturnCont());
         effect = f.effect;
         BoundVar[] newParameters = BoundVar.copy(f.firstBlock.parameters);
         firstBlock.setParameters(BoundVar.concat(getParameters(), newParameters));
@@ -233,54 +291,6 @@ public final class SSAFunction implements Printable, BoundVarBinder {
         this.returnCont = returnCont;
         returnCont.setParent(this);
     }
-    
-    /*public void tryToMakeMonadic(SSASimplificationContext context) {
-        if(monadic)
-            return;
-        if(!Types.isApply(BTypes.PROC, 1, getReturnType()))
-            return;        
-        for(ValRef ref = target.getOccurrence(); ref != null; ref = ref.getNext()) {
-            ValRefBinder parent = ref.getParent();
-            if(!(parent instanceof LetApply))
-                return;
-            LetApply apply = (LetApply)parent;
-            if(apply.getFunction() != ref)
-                return;
-            if(apply.getParameters().length != getParameters().length)
-                return;
-            if(!apply.hasEffect())
-                return;
-        }        
-        makeMonadic(context);
-    }*/
-    
-    /*private void makeMonadic(SSASimplificationContext context) {
-        Type oldReturnType = returnCont.getType();
-        Type newReturnType;
-        try {
-            newReturnType = Types.matchApply(BTypes.PROC, oldReturnType);
-        } catch (MatchException e) {
-            throw new InternalCompilerError();
-        }
-        
-        //
-        returnCont.setType(newReturnType);
-        monadic = true;
-        
-        //
-        SSABlock block = new SSABlock(oldReturnType);
-        addBlock(block);
-        
-        returnCont.replaceWith(block);
-        
-        BoundVar x = new BoundVar(newReturnType);
-        LetApply apply = new LetApply(x, block.parameters[0].createOccurrence());
-        apply.setMonadic(true);
-        block.addStatement(apply);
-        
-        block.setExit(new Jump(returnCont.createOccurrence(), x.createOccurrence()));
-        context.markModified("SSAFunction.make-monadic");
-    }*/
 
     public ValRef isEqualToConstant() {
         if(firstBlock.parameters.length > 0)
@@ -309,12 +319,14 @@ public final class SSAFunction implements Printable, BoundVarBinder {
         return firstBlock.parameters.length;
     }
 
+    @Override
     public void markGenerateOnFly() {
         for(SSABlock block = firstBlock; block != null; block = block.next)
             block.markGenerateOnFly();
     }
 
-    public SSAFunction copy(CopyContext context) {
+    @Override
+    public SSAClosure copy(CopyContext context) {
         TVar[] newTypeParameters = context.copyParameters(typeParameters);
         SSAFunction newFunction = new SSAFunction(newTypeParameters, effect, context.copy(returnCont));
         for(SSABlock block = firstBlock;
@@ -322,11 +334,8 @@ public final class SSAFunction implements Printable, BoundVarBinder {
             newFunction.addBlock(context.copy(block));
         return newFunction;
     }
-
-    public SSAFunction copy() {
-        return copy(new CopyContext());
-    }
-
+    
+    @Override
     public void replace(TVar[] vars, Type[] replacements) {
         returnCont.replace(vars, replacements);
         for(SSABlock block = firstBlock;
@@ -338,6 +347,7 @@ public final class SSAFunction implements Printable, BoundVarBinder {
         this.typeParameters = typeParameters;
     }
 
+    @Override
     public Type getType() {
         Type type = returnCont.getType();
         type = Types.functionE(
@@ -361,73 +371,29 @@ public final class SSAFunction implements Printable, BoundVarBinder {
         return returnCont.getType();
     }
 
+    @Override
     public void destroy() {
         for(SSABlock block = firstBlock;
                 block != null; block = block.next)
             block.destroy();
     }
     
-    public void detach() {
-        if(prev == null)
-            parent.setFirstFunction(next);
-        else
-            prev.next = next;
-        if(next != null)
-            next.prev = prev;
-    }
-    
-    public void remove() {
-        destroy();
-        detach();
-    }
-    
-    public void addSibling(SSAFunction function) {
-        function.parent = parent;
-        function.next = next;
-        function.prev = this;
-        
-        next.prev = function;
-        next = function;
-    }
-
-    public SSAFunction getNext() {
-        return next;
-    }
-
-    public void setParent(FunctionBinder parent) {
-        this.parent = parent;
-    }
-
-    public void setPrev(SSAFunction function) {
-        this.prev = function;
-    }
-
-    public void setNext(SSAFunction function) {
-        this.next = function;
-    }
-    
+    @Override    
     public void collectFreeVariables(ArrayList<ValRef> vars) {
         for(SSABlock block = firstBlock;
                 block != null; block = block.next)
             block.collectFreeVariables(this, vars);
     }
-
-    @Override
-    public SSAFunction getParentFunction() {
-        return parent.getParentFunction();
-    }
-    
-    public FunctionBinder getParent() {
-        return parent;
-    }
     
+    @Override    
     public void lambdaLift(SSALambdaLiftingContext context) {
         for(SSABlock block = firstBlock;
                 block != null; block = block.next)
             block.lambdaLift(context);
     }
 
-    public void addParametersInFront(BoundVar[] parameters) {
+    @Override
+    public void parametrize(BoundVar[] parameters) {
         Cont proxy = null;
         for(ContRef ref = firstBlock.getOccurrence(); ref != null; ref = ref.getNext())
             proxy = ref.addParametersInFront(parameters, firstBlock.parameters, proxy);
@@ -481,11 +447,16 @@ public final class SSAFunction implements Printable, BoundVarBinder {
         return effect;
     }
 
-    public int getBlockCount() {
-        int count = 0;
-        for(SSABlock block = firstBlock;block != null;block = block.next)
-            ++count;
-        return count;
+    @Override
+    public boolean isValue() {
+        return getArity() == 0;
+    }
+
+    @Override
+    public void forValRefs(ValRefVisitor visitor) {
+        for(SSABlock block = firstBlock;
+                block != null; block = block.next)
+            block.forValRefs(visitor);
     }
 
 }