X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Finternal%2Fcodegen%2Fssa%2Fexits%2FIf.java;fp=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Finternal%2Fcodegen%2Fssa%2Fexits%2FIf.java;h=0f4673aada2d4a30738710c55d7b293e7e861d62;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git 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 index 000000000..0f4673aad --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/If.java @@ -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 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; + } + } +}