X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Finternal%2Fcodegen%2Fssa%2Fstatements%2FLetFunctions.java;h=ee5dcc7148533bfcaf8a8e44ee7d426b794ce1ca;hp=25d9c2544bffd4ab6bb8470ead45408e0900d683;hb=a8758de5bc19e5adb3f618d3038743a164f09912;hpb=12d9af17384d960b75d58c3935d2b7b46d93e87b diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetFunctions.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetFunctions.java index 25d9c2544..ee5dcc714 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetFunctions.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetFunctions.java @@ -3,57 +3,61 @@ package org.simantics.scl.compiler.internal.codegen.ssa.statements; import java.util.ArrayList; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.constants.Constant; import org.simantics.scl.compiler.constants.SCLConstant; import org.simantics.scl.compiler.internal.codegen.references.BoundVar; import org.simantics.scl.compiler.internal.codegen.references.ValRef; +import org.simantics.scl.compiler.internal.codegen.ssa.SSAClosure; import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction; import org.simantics.scl.compiler.internal.codegen.ssa.SSAStatement; -import org.simantics.scl.compiler.internal.codegen.ssa.binders.FunctionBinder; +import org.simantics.scl.compiler.internal.codegen.ssa.binders.ClosureBinder; 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.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; import gnu.trove.map.hash.THashMap; import gnu.trove.set.hash.THashSet; -public class LetFunctions extends SSAStatement implements FunctionBinder { +public class LetFunctions extends SSAStatement implements ClosureBinder { long recursiveGroupLocation; - SSAFunction firstFunction; + SSAClosure firstClosure; public LetFunctions() { } - public LetFunctions(SSAFunction function) { - firstFunction = function; - function.setParent(this); + public LetFunctions(SSAClosure closure) { + firstClosure = closure; + closure.setParent(this); } @Override public void toString(PrintingContext context) { - for(SSAFunction function = firstFunction; function != null; function = function.getNext()) { + for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) { context.indentation(); - context.append(function.getTarget()); - context.append("(" + function.getTarget().occurrenceCount() + ")"); + context.append(closure.getTarget()); + context.append("(" + closure.getTarget().occurrenceCount() + ")"); context.append(" :: "); - context.append(function.getTarget().getType()); + context.append(closure.getTarget().getType()); context.append(" = \n"); context.indent(); - function.toString(context); + closure.toString(context); context.dedent(); } } - public void addFunction(SSAFunction function) { - function.setParent(this); - function.setNext(firstFunction); - if(firstFunction != null) - firstFunction.setPrev(function); - firstFunction = function; + public void addClosure(SSAClosure closure) { + closure.setParent(this); + closure.setNext(firstClosure); + if(firstClosure != null) + firstClosure.setPrev(closure); + firstClosure = closure; } @Override @@ -63,52 +67,52 @@ public class LetFunctions extends SSAStatement implements FunctionBinder { @Override public void validate(SSAValidationContext context) { - for(SSAFunction function = firstFunction; function != null; function = function.getNext()) { - if(!(function.getTarget() instanceof BoundVar)) + for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) { + if(!(closure.getTarget() instanceof BoundVar)) throw new InternalCompilerError(); - function.validate(context); + closure.validate(context); } } @Override public void destroy() { - for(SSAFunction function = firstFunction; function != null; function = function.getNext()) - function.destroy(); + for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) + closure.destroy(); } @Override public SSAStatement copy(CopyContext context) { LetFunctions result = new LetFunctions(); - for(SSAFunction function = firstFunction; function != null; function = function.getNext()) { - SSAFunction newFunction = function.copy(context); - newFunction.setTarget(context.copy(function.getTarget())); - result.addFunction(newFunction); + for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) { + SSAClosure newFunction = closure.copy(context); + newFunction.setTarget(context.copy(closure.getTarget())); + result.addClosure(newFunction); } return result; } @Override public void replace(TVar[] vars, Type[] replacements) { - for(SSAFunction function = firstFunction; function != null; function = function.getNext()) { - ((BoundVar)function.getTarget()).replace(vars, replacements); - function.replace(vars, replacements); + for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) { + ((BoundVar)closure.getTarget()).replace(vars, replacements); + closure.replace(vars, replacements); } } @Override public void addBoundVariablesTo(SSAValidationContext context) { - for(SSAFunction function = firstFunction; function != null; function = function.getNext()) - context.validBoundVariables.add((BoundVar)function.getTarget()); + for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) + context.validBoundVariables.add((BoundVar)closure.getTarget()); } @Override - public SSAFunction getFirstFunction() { - return firstFunction; + public SSAClosure getFirstClosure() { + return firstClosure; } @Override - public void setFirstFunction(SSAFunction function) { - this.firstFunction = function; + public void setFirstClosure(SSAClosure function) { + this.firstClosure = function; if(function == null) detach(); } @@ -132,16 +136,46 @@ public class LetFunctions extends SSAStatement implements FunctionBinder { boolean hasValues = false; boolean isRecursive = false; - // Lambda lift functions and collect free variables + // Lambda lift substructure and collect free variables THashSet targets = new THashSet(); ArrayList freeVars = new ArrayList(); - for(SSAFunction function = firstFunction; - function != null; - function = function.getNext()) { - hasValues |= function.getArity() == 0; - function.lambdaLift(context); - targets.add((BoundVar)function.getTarget()); - function.collectFreeVariables(freeVars); + for(SSAClosure closure = firstClosure; + closure != null; + closure = closure.getNext()) { + hasValues |= closure.isValue(); + closure.lambdaLift(context); + targets.add((BoundVar)closure.getTarget()); + closure.collectFreeVariables(freeVars); + } + + if(!(firstClosure instanceof SSAFunction) && firstClosure.getNext() == null) { + THashMap varMap = new THashMap(); + ArrayList oldVarsList = new ArrayList(4); + ArrayList newVarsList = new ArrayList(4); + BoundVar newTarget = null; + for(ValRef ref : freeVars) { + BoundVar var = (BoundVar)ref.getBinding(); + if(targets.contains(var)) { + if(newTarget == null) + newTarget = new BoundVar(var.getType()); + ref.replaceBy(newTarget); + continue; + } + BoundVar newVar = varMap.get(var); + if(newVar == null) { + newVar = new BoundVar(var.getType()); + oldVarsList.add(var); + newVarsList.add(newVar); + varMap.put(var, newVar); + } + ref.replaceBy(newVar); + } + Constant constant = firstClosure.liftClosure(newTarget, newVarsList.toArray(new BoundVar[newVarsList.size()])); + new LetApply(targets.iterator().next(), Types.PROC, constant.createOccurrence(), ValRef.createOccurrences(oldVarsList)) + .insertBefore(this); + detach(); + context.addClosure(firstClosure); + return; } // Classify by BoundVars @@ -157,40 +191,32 @@ public class LetFunctions extends SSAStatement implements FunctionBinder { if(boundVars.add(var)) boundVarsList.add(var); newFreeVars.add(ref); - /*BoundVar inVar = map.get(outVar); - if(inVar == null) { - inVar = new BoundVar(outVar.getType()); - map.put(outVar, inVar); - outParameters.add(outVar); - inParameters.add(inVar); - } - ref.replaceBy(inVar);*/ } BoundVar[] outVars = boundVarsList.toArray(new BoundVar[boundVarsList.size()]); freeVars = newFreeVars; // Modify functions - THashMap> varMap = new THashMap>(); - THashMap inVarsMap = new THashMap(); - THashMap oldTargets = new THashMap(); - for(SSAFunction function = firstFunction; - function != null; - function = function.getNext()) { - THashMap map = new THashMap(2*outVars.length); + THashMap> varMap = new THashMap>(); + THashMap inVarsMap = new THashMap(); + THashMap oldTargets = new THashMap(); + for(SSAClosure closure = firstClosure; + closure != null; + closure = closure.getNext()) { + THashMap map = new THashMap(outVars.length); BoundVar[] inVars = new BoundVar[outVars.length]; for(int i=0;i 0) - ref.replaceByApply(function.getTarget(), vars); + ref.replaceByApply(closure.getTarget(), vars); else - ref.replaceBy(function.getTarget()); + ref.replaceBy(closure.getTarget()); } } @@ -233,7 +259,7 @@ public class LetFunctions extends SSAStatement implements FunctionBinder { @Override public void simplify(SSASimplificationContext context) { - for(SSAFunction function = firstFunction; + for(SSAClosure function = firstClosure; function != null; function = function.getNext()) function.simplify(context); @@ -242,4 +268,10 @@ public class LetFunctions extends SSAStatement implements FunctionBinder { public void setRecursiveGroupLocation(long recursiveGroupLocation) { this.recursiveGroupLocation = recursiveGroupLocation; } + + @Override + public void forValRefs(ValRefVisitor visitor) { + for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) + closure.forValRefs(visitor); + } }