]> gerrit.simantics Code Review - simantics/platform.git/blob
0f4673aada2d4a30738710c55d7b293e7e861d62
[simantics/platform.git] /
1 package org.simantics.scl.compiler.internal.codegen.ssa.exits;
2
3 import java.util.ArrayList;
4
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;
24
25 public class If extends SSAExit implements ValRefBinder {
26     private ValRef condition;
27     private ContRef thenTarget;
28     private ContRef elseTarget;
29     
30     public If(ValRef condition, ContRef thenTarget, ContRef elseTarget) {
31         setCondition(condition);
32         setThenTarget(thenTarget);
33         setElseTarget(elseTarget);
34     }
35     
36     public void setCondition(ValRef condition) {
37         this.condition = condition;
38         condition.setParent(this);
39     }
40     
41     public void setThenTarget(ContRef thenTarget) {
42         this.thenTarget = thenTarget;
43         thenTarget.setParent(this);
44     }
45     
46     public void setElseTarget(ContRef elseTarget) {
47         this.elseTarget = elseTarget;
48         elseTarget.setParent(this);
49     }
50
51     @Override
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());
58     }
59
60     @Override
61     public void toString(PrintingContext context) {
62         context.append("if ");
63         context.append(condition);
64         context.append(" then ");
65         {
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);
72                     context.append(' ');
73                 }
74                 else {
75                     context.append('\n');
76                     thenBlock.bodyToString(context);
77                     context.indentation();
78                 }
79             }
80             else {
81                 context.append(thenCont);
82                 context.append(' ');
83             }
84         }        
85         context.append("else ");
86         {
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);
93                     context.append('\n');
94                 }
95                 else {
96                     context.append('\n');
97                     elseBlock.bodyToString(context);
98                 }
99             }
100             else {
101                 context.append(elseCont);
102                 context.append('\n');
103             }
104         }
105     }
106
107     @Override
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);
121     }
122
123     @Override
124     public void destroy() {
125         condition.remove();
126         elseTarget.remove();
127         thenTarget.remove();
128     }
129
130     @Override
131     public SSAExit copy(CopyContext context) {
132         return new If(context.copy(condition),
133                 context.copy(thenTarget),
134                 context.copy(elseTarget));
135     }
136     
137     @Override
138     public void replace(TVar[] vars, Type[] replacements) {
139         condition.replace(vars, replacements);        
140     }
141     
142     @Override
143     public void simplify(SSASimplificationContext context) {
144         Val cond = condition.getBinding();
145         if(cond instanceof BooleanConstant) {
146             SSAExit newExit;
147             if(((BooleanConstant) cond).getValue()) {
148                 newExit = new Jump(thenTarget);
149                 elseTarget.remove();
150             }
151             else {
152                 newExit = new Jump(elseTarget);
153                 thenTarget.remove();
154             }
155             condition.remove();
156             getParent().setExit(newExit);
157             context.markModified("beta-if");
158         }
159         else if(thenTarget.getBinding() == elseTarget.getBinding()) {
160             elseTarget.remove();
161             condition.remove();
162             getParent().setExit(new Jump(thenTarget));
163             context.markModified("equal-branches-if");
164         }
165     }
166
167     @Override
168     public void collectFreeVariables(SSAFunction function,
169             ArrayList<ValRef> vars) {
170         condition.collectFreeVariables(function, vars);
171     }
172     
173     @Override
174     public Cont addParametersInFrontOf(ContRef contRef, Val[] newParameters, Val[] oldParameters,
175             Cont proxy) {
176         if(proxy == null)
177             proxy = contRef.getBinding().createProxy(getParent().getParent(), newParameters, oldParameters);
178         ContRef proxyRef = proxy.createOccurrence();
179         if(thenTarget == contRef)
180             setThenTarget(proxyRef);
181         else
182             setElseTarget(proxyRef);
183         return proxy;
184     }
185
186     @Override
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};
193             else
194                 return new SSABlock[] {(SSABlock)thenCont};
195         }
196         else {
197             if(elseCont instanceof SSABlock)
198                 return new SSABlock[] {(SSABlock)elseCont};
199             else
200                 return SSABlock.EMPTY_ARRAY;
201         }
202     }
203 }