Mercurial > projects > ddmd
annotate dmd/IfStatement.d @ 130:60bb0fe4563e
dmdfe 2.037 first main iteration
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Thu, 09 Sep 2010 22:51:44 +0100 |
parents | e28b18c23469 |
children | 14feb7ae01a6 |
rev | line source |
---|---|
0 | 1 module dmd.IfStatement; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.Statement; |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
5 import dmd.Parameter; |
0 | 6 import dmd.Loc; |
7 import dmd.Expression; | |
8 import dmd.VarDeclaration; | |
9 import dmd.Scope; | |
10 import dmd.InterState; | |
11 import dmd.OutBuffer; | |
12 import dmd.HdrGenState; | |
13 import dmd.InlineCostState; | |
14 import dmd.InlineDoState; | |
15 import dmd.InlineScanState; | |
16 import dmd.IRState; | |
17 import dmd.BE; | |
18 import dmd.WANT; | |
19 import dmd.ScopeDsymbol; | |
20 import dmd.Type; | |
21 import dmd.CondExp; | |
22 import dmd.AndAndExp; | |
23 import dmd.OrOrExp; | |
24 import dmd.AssignExp; | |
25 import dmd.VarExp; | |
26 | |
27 import dmd.backend.elem; | |
28 import dmd.backend.Util; | |
29 import dmd.backend.block; | |
30 import dmd.backend.Blockx; | |
31 import dmd.backend.BC; | |
32 | |
33 class IfStatement : Statement | |
34 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
35 Parameter arg; |
0 | 36 Expression condition; |
37 Statement ifbody; | |
38 Statement elsebody; | |
39 | |
40 VarDeclaration match; // for MatchExpression results | |
41 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
42 this(Loc loc, Parameter arg, Expression condition, Statement ifbody, Statement elsebody) |
0 | 43 { |
44 super(loc); | |
45 this.arg = arg; | |
46 this.condition = condition; | |
47 this.ifbody = ifbody; | |
48 this.elsebody = elsebody; | |
49 } | |
50 | |
72 | 51 override Statement syntaxCopy() |
0 | 52 { |
51 | 53 Statement i = null; |
54 if (ifbody) | |
55 i = ifbody.syntaxCopy(); | |
56 | |
57 Statement e = null; | |
58 if (elsebody) | |
59 e = elsebody.syntaxCopy(); | |
60 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
61 Parameter a = arg ? arg.syntaxCopy() : null; |
51 | 62 IfStatement s = new IfStatement(loc, a, condition.syntaxCopy(), i, e); |
63 return s; | |
0 | 64 } |
65 | |
72 | 66 override Statement semantic(Scope sc) |
0 | 67 { |
68 condition = condition.semantic(sc); | |
69 condition = resolveProperties(sc, condition); | |
70 condition = condition.checkToBoolean(); | |
71 | |
72 // If we can short-circuit evaluate the if statement, don't do the | |
73 // semantic analysis of the skipped code. | |
74 // This feature allows a limited form of conditional compilation. | |
75 condition = condition.optimize(WANT.WANTflags); | |
76 | |
77 // Evaluate at runtime | |
78 uint cs0 = sc.callSuper; | |
79 uint cs1; | |
80 | |
81 Scope scd; | |
82 if (arg) | |
83 { | |
84 /* Declare arg, which we will set to be the | |
85 * result of condition. | |
86 */ | |
87 ScopeDsymbol sym = new ScopeDsymbol(); | |
88 sym.parent = sc.scopesym; | |
89 scd = sc.push(sym); | |
90 | |
91 Type t = arg.type ? arg.type : condition.type; | |
92 match = new VarDeclaration(loc, t, arg.ident, null); | |
93 match.noauto = true; | |
94 match.semantic(scd); | |
95 if (!scd.insert(match)) | |
96 assert(0); | |
97 | |
98 match.parent = sc.func; | |
99 | |
100 /* Generate: | |
101 * (arg = condition) | |
102 */ | |
103 VarExp v = new VarExp(Loc(0), match); | |
104 condition = new AssignExp(loc, v, condition); | |
105 condition = condition.semantic(scd); | |
106 } | |
107 else | |
108 scd = sc.push(); | |
109 | |
110 ifbody = ifbody.semantic(scd); | |
111 scd.pop(); | |
112 | |
113 cs1 = sc.callSuper; | |
114 sc.callSuper = cs0; | |
115 if (elsebody) | |
116 elsebody = elsebody.semanticScope(sc, null, null); | |
117 | |
118 sc.mergeCallSuper(loc, cs1); | |
119 | |
120 return this; | |
121 } | |
122 | |
72 | 123 override Expression interpret(InterState istate) |
0 | 124 { |
125 assert(false); | |
126 } | |
127 | |
72 | 128 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 129 { |
130 assert(false); | |
131 } | |
132 | |
72 | 133 override bool usesEH() |
0 | 134 { |
135 assert(false); | |
136 } | |
137 | |
72 | 138 override BE blockExit() |
0 | 139 { |
140 //printf("IfStatement::blockExit(%p)\n", this); | |
141 | |
142 BE result = BE.BEnone; | |
143 if (condition.canThrow()) | |
144 result |= BE.BEthrow; | |
145 if (condition.isBool(true)) | |
146 { | |
147 if (ifbody) | |
148 result |= ifbody.blockExit(); | |
149 else | |
150 result |= BE.BEfallthru; | |
151 } | |
152 else if (condition.isBool(false)) | |
153 { | |
154 if (elsebody) | |
155 result |= elsebody.blockExit(); | |
156 else | |
157 result |= BE.BEfallthru; | |
158 } | |
159 else | |
160 { | |
161 if (ifbody) | |
162 result |= ifbody.blockExit(); | |
163 else | |
164 result |= BE.BEfallthru; | |
165 | |
166 if (elsebody) | |
167 result |= elsebody.blockExit(); | |
168 else | |
169 result |= BE.BEfallthru; | |
170 } | |
171 | |
172 //printf("IfStatement::blockExit(%p) = x%x\n", this, result); | |
173 return result; | |
174 } | |
175 | |
72 | 176 override IfStatement isIfStatement() { return this; } |
0 | 177 |
72 | 178 override int inlineCost(InlineCostState* ics) |
0 | 179 { |
180 int cost; | |
181 | |
182 /* Can't declare variables inside ?: expressions, so | |
183 * we cannot inline if a variable is declared. | |
184 */ | |
185 if (arg) | |
186 return COST_MAX; | |
187 | |
188 cost = condition.inlineCost(ics); | |
189 | |
190 /* Specifically allow: | |
191 * if (condition) | |
192 * return exp1; | |
193 * else | |
194 * return exp2; | |
195 * Otherwise, we can't handle return statements nested in if's. | |
196 */ | |
197 | |
198 if (elsebody && ifbody && | |
199 ifbody.isReturnStatement() && | |
200 elsebody.isReturnStatement()) | |
201 { | |
202 cost += ifbody.inlineCost(ics); | |
203 cost += elsebody.inlineCost(ics); | |
204 //printf("cost = %d\n", cost); | |
205 } | |
206 else | |
207 { | |
208 ics.nested += 1; | |
209 if (ifbody) | |
210 cost += ifbody.inlineCost(ics); | |
211 if (elsebody) | |
212 cost += elsebody.inlineCost(ics); | |
213 ics.nested -= 1; | |
214 } | |
215 return cost; | |
216 } | |
217 | |
72 | 218 override Expression doInline(InlineDoState ids) |
0 | 219 { |
220 Expression econd; | |
221 Expression e1; | |
222 Expression e2; | |
223 Expression e; | |
224 | |
225 assert(!arg); | |
226 econd = condition.doInline(ids); | |
227 assert(econd); | |
228 if (ifbody) | |
229 e1 = ifbody.doInline(ids); | |
230 else | |
231 e1 = null; | |
232 if (elsebody) | |
233 e2 = elsebody.doInline(ids); | |
234 else | |
235 e2 = null; | |
236 if (e1 && e2) | |
237 { | |
238 e = new CondExp(econd.loc, econd, e1, e2); | |
239 e.type = e1.type; | |
240 } | |
241 else if (e1) | |
242 { | |
243 e = new AndAndExp(econd.loc, econd, e1); | |
244 e.type = Type.tvoid; | |
245 } | |
246 else if (e2) | |
247 { | |
248 e = new OrOrExp(econd.loc, econd, e2); | |
249 e.type = Type.tvoid; | |
250 } | |
251 else | |
252 { | |
253 e = econd; | |
254 } | |
255 return e; | |
256 } | |
257 | |
72 | 258 override Statement inlineScan(InlineScanState* iss) |
0 | 259 { |
260 condition = condition.inlineScan(iss); | |
261 if (ifbody) | |
262 ifbody = ifbody.inlineScan(iss); | |
263 if (elsebody) | |
264 elsebody = elsebody.inlineScan(iss); | |
265 return this; | |
266 } | |
267 | |
72 | 268 override void toIR(IRState* irs) |
0 | 269 { |
270 elem* e; | |
271 Blockx* blx = irs.blx; | |
272 | |
273 //printf("IfStatement::toIR('%s')\n", condition.toChars()); | |
274 | |
275 IRState mystate = IRState(irs, this); | |
276 | |
277 // bexit is the block that gets control after this IfStatement is done | |
278 block* bexit = mystate.breakBlock ? mystate.breakBlock : block_calloc(); | |
279 | |
280 incUsage(irs, loc); | |
281 static if (false) { | |
282 if (match) | |
283 { | |
284 /* Generate: | |
285 * if (match = RTLSYM_IFMATCH(string, pattern)) ... | |
286 */ | |
287 assert(condition.op == TOK.TOKmatch); | |
288 e = matchexp_toelem(cast(MatchExp)condition, &mystate, RTLSYM.RTLSYM_IFMATCH); | |
289 Symbol *s = match.toSymbol(); | |
290 symbol_add(s); | |
291 e = el_bin(OPeq, TYnptr, el_var(s), e); | |
292 } | |
293 else | |
294 { | |
295 e = condition.toElem(&mystate); | |
296 } | |
297 } else { | |
298 e = condition.toElem(&mystate); | |
299 } | |
300 block_appendexp(blx.curblock, e); | |
301 block* bcond = blx.curblock; | |
302 block_next(blx, BC.BCiftrue, null); | |
303 | |
304 list_append(&bcond.Bsucc, blx.curblock); | |
305 if (ifbody) | |
306 ifbody.toIR(&mystate); | |
307 | |
308 list_append(&blx.curblock.Bsucc, bexit); | |
309 | |
310 if (elsebody) | |
311 { | |
312 block_next(blx, BC.BCgoto, null); | |
313 list_append(&bcond.Bsucc, blx.curblock); | |
314 elsebody.toIR(&mystate); | |
315 list_append(&blx.curblock.Bsucc, bexit); | |
316 } | |
317 else | |
318 list_append(&bcond.Bsucc, bexit); | |
319 | |
320 block_next(blx, BC.BCgoto, bexit); | |
321 } | |
72 | 322 } |