1 package org.simantics.scl.compiler.internal.codegen.ssa.exits;
3 import java.util.ArrayList;
5 import org.objectweb.asm.Label;
6 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
7 import org.simantics.scl.compiler.constants.BooleanConstant;
8 import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
9 import org.simantics.scl.compiler.internal.codegen.continuations.ContRef;
10 import org.simantics.scl.compiler.internal.codegen.references.Val;
11 import org.simantics.scl.compiler.internal.codegen.references.ValRef;
12 import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock;
13 import org.simantics.scl.compiler.internal.codegen.ssa.SSAExit;
14 import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
15 import org.simantics.scl.compiler.internal.codegen.ssa.binders.ValRefBinder;
16 import org.simantics.scl.compiler.internal.codegen.utils.CopyContext;
17 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
18 import org.simantics.scl.compiler.internal.codegen.utils.PrintingContext;
19 import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;
20 import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;
21 import org.simantics.scl.compiler.types.TVar;
22 import org.simantics.scl.compiler.types.Type;
23 import org.simantics.scl.compiler.types.Types;
25 public class If extends SSAExit implements ValRefBinder {
26 private ValRef condition;
27 private ContRef thenTarget;
28 private ContRef elseTarget;
30 public If(ValRef condition, ContRef thenTarget, ContRef elseTarget) {
31 setCondition(condition);
32 setThenTarget(thenTarget);
33 setElseTarget(elseTarget);
36 public void setCondition(ValRef condition) {
37 this.condition = condition;
38 condition.setParent(this);
41 public void setThenTarget(ContRef thenTarget) {
42 this.thenTarget = thenTarget;
43 thenTarget.setParent(this);
46 public void setElseTarget(ContRef elseTarget) {
47 this.elseTarget = elseTarget;
48 elseTarget.setParent(this);
52 public void generateCode(MethodBuilder mb) {
53 mb.push(condition.getBinding(), Types.BOOLEAN);
54 Label elseLabel = mb.getLabel(elseTarget.getBinding());
55 mb.ifZeroComparisonBranch(elseLabel, "==");
56 mb.jump(thenTarget.getBinding());
57 mb.ensureExists(elseTarget.getBinding());
61 public void toString(PrintingContext context) {
62 context.append("if ");
63 context.append(condition);
64 context.append(" then ");
66 Cont thenCont = thenTarget.getBinding();
67 if(thenCont instanceof SSABlock) {
68 SSABlock thenBlock = (SSABlock)thenCont;
69 if(thenCont.hasMoreThanOneOccurences()) {
70 context.append(thenCont);
71 context.addBlock(thenBlock);
76 thenBlock.bodyToString(context);
77 context.indentation();
81 context.append(thenCont);
85 context.append("else ");
87 Cont elseCont = elseTarget.getBinding();
88 if(elseCont instanceof SSABlock) {
89 SSABlock elseBlock = (SSABlock)elseCont;
90 if(elseCont.hasMoreThanOneOccurences()) {
91 context.append(elseCont);
92 context.addBlock(elseBlock);
97 elseBlock.bodyToString(context);
101 context.append(elseCont);
102 context.append('\n');
108 public void validate(SSAValidationContext context) {
109 context.validate(condition);
110 context.validate(elseTarget);
111 context.validate(thenTarget);
112 if(condition.getParent() != this)
113 throw new InternalCompilerError();
114 if(elseTarget.getParent() != this)
115 throw new InternalCompilerError();
116 if(thenTarget.getParent() != this)
117 throw new InternalCompilerError();
118 context.assertEquals(this, condition.getType(), Types.BOOLEAN);
119 context.assertEquals(elseTarget.getBinding().getArity(), 0);
120 context.assertEquals(thenTarget.getBinding().getArity(), 0);
124 public void destroy() {
131 public SSAExit copy(CopyContext context) {
132 return new If(context.copy(condition),
133 context.copy(thenTarget),
134 context.copy(elseTarget));
138 public void replace(TVar[] vars, Type[] replacements) {
139 condition.replace(vars, replacements);
143 public void simplify(SSASimplificationContext context) {
144 Val cond = condition.getBinding();
145 if(cond instanceof BooleanConstant) {
147 if(((BooleanConstant) cond).getValue()) {
148 newExit = new Jump(thenTarget);
152 newExit = new Jump(elseTarget);
156 getParent().setExit(newExit);
157 context.markModified("beta-if");
159 else if(thenTarget.getBinding() == elseTarget.getBinding()) {
162 getParent().setExit(new Jump(thenTarget));
163 context.markModified("equal-branches-if");
168 public void collectFreeVariables(SSAFunction function,
169 ArrayList<ValRef> vars) {
170 condition.collectFreeVariables(function, vars);
174 public Cont addParametersInFrontOf(ContRef contRef, Val[] newParameters, Val[] oldParameters,
177 proxy = contRef.getBinding().createProxy(getParent().getParent(), newParameters, oldParameters);
178 ContRef proxyRef = proxy.createOccurrence();
179 if(thenTarget == contRef)
180 setThenTarget(proxyRef);
182 setElseTarget(proxyRef);
187 public SSABlock[] getSuccessors() {
188 Cont thenCont = thenTarget.getBinding();
189 Cont elseCont = elseTarget.getBinding();
190 if(thenCont instanceof SSABlock) {
191 if(elseCont instanceof SSABlock)
192 return new SSABlock[] {(SSABlock)thenCont, (SSABlock)elseCont};
194 return new SSABlock[] {(SSABlock)thenCont};
197 if(elseCont instanceof SSABlock)
198 return new SSABlock[] {(SSABlock)elseCont};
200 return SSABlock.EMPTY_ARRAY;