Mercurial > projects > ldc
comparison gen/statements.c @ 14:0e86428ee567 trunk
[svn r18] * Initial support for switch statements - No string switches yet.
* Moved Statement::toIR definitions into gen/statements.c - toir.c is still too big.
* Removed some BB bloat with ScopeStatements.
author | lindquist |
---|---|
date | Wed, 03 Oct 2007 02:15:12 +0200 |
parents | |
children | 37a4fdab33fc |
comparison
equal
deleted
inserted
replaced
13:3d1d98329fa7 | 14:0e86428ee567 |
---|---|
1 // Statements: D -> LLVM glue | |
2 | |
3 #include <stdio.h> | |
4 #include <math.h> | |
5 #include <sstream> | |
6 #include <fstream> | |
7 #include <iostream> | |
8 | |
9 #include "llvm/Type.h" | |
10 #include "llvm/DerivedTypes.h" | |
11 #include "llvm/Constants.h" | |
12 #include "llvm/Instructions.h" | |
13 #include "llvm/IntrinsicInst.h" | |
14 #include "llvm/CallingConv.h" | |
15 | |
16 #include "total.h" | |
17 #include "init.h" | |
18 #include "symbol.h" | |
19 #include "mtype.h" | |
20 #include "hdrgen.h" | |
21 #include "port.h" | |
22 | |
23 #include "gen/irstate.h" | |
24 #include "gen/elem.h" | |
25 #include "gen/logger.h" | |
26 #include "gen/tollvm.h" | |
27 #include "gen/runtime.h" | |
28 #include "gen/arrays.h" | |
29 | |
30 /* --------------------------------------------------------------------------------------- */ | |
31 | |
32 void CompoundStatement::toIR(IRState* p) | |
33 { | |
34 static int csi = 0; | |
35 Logger::println("CompoundStatement::toIR(%d):\n<<<\n%s>>>", csi++, toChars()); | |
36 LOG_SCOPE; | |
37 | |
38 /* | |
39 const char* labelname; | |
40 bool insterm = false; | |
41 | |
42 if (!p->scopes()) { | |
43 labelname = "bb"; | |
44 insterm = true; | |
45 } | |
46 else | |
47 labelname = "entry"; | |
48 | |
49 //if (!llvm::isa<llvm::TerminatorInst>(p->topfunc()->back().back())) | |
50 // insterm = true; | |
51 | |
52 llvm::BasicBlock* bb = new llvm::BasicBlock(labelname, p->topfunc()); | |
53 | |
54 if (insterm) { | |
55 new llvm::BranchInst(bb,p->topbb()); | |
56 } | |
57 | |
58 p->bbs.push(bb); | |
59 */ | |
60 | |
61 size_t n = statements->dim; | |
62 for (size_t i=0; i<n; i++) | |
63 { | |
64 Statement* s = (Statement*)statements->data[i]; | |
65 if (s) | |
66 s->toIR(p); | |
67 else | |
68 Logger::println("NULL statement found in CompoundStatement !! :S"); | |
69 } | |
70 | |
71 //p->bbs.pop(); | |
72 } | |
73 | |
74 void ReturnStatement::toIR(IRState* p) | |
75 { | |
76 static int rsi = 0; | |
77 Logger::println("ReturnStatement::toIR(%d): %s", rsi++, toChars()); | |
78 LOG_SCOPE; | |
79 | |
80 if (exp) | |
81 { | |
82 TY expty = exp->type->ty; | |
83 if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) { | |
84 assert(expty == Tstruct || expty == Tdelegate || expty == Tarray); | |
85 | |
86 TypeFunction* f = p->topfunctype(); | |
87 assert(f->llvmRetInPtr && f->llvmRetArg); | |
88 | |
89 p->lvals.push_back(f->llvmRetArg); | |
90 elem* e = exp->toElem(p); | |
91 p->lvals.pop_back(); | |
92 | |
93 // structliterals do this themselves | |
94 // also they dont produce any value | |
95 if (expty == Tstruct) { | |
96 if (!e->inplace) { | |
97 TypeStruct* ts = (TypeStruct*)exp->type; | |
98 assert(e->mem); | |
99 LLVM_DtoStructCopy(ts,f->llvmRetArg,e->mem); | |
100 } | |
101 } | |
102 else if (expty == Tdelegate) { | |
103 // do nothing, handled by the DelegateExp | |
104 LLVM_DtoDelegateCopy(f->llvmRetArg,e->mem); | |
105 } | |
106 else if (expty == Tarray) { | |
107 if (e->type == elem::SLICE) { | |
108 LLVM_DtoSetArray(f->llvmRetArg,e->arg,e->mem); | |
109 } | |
110 // else the return value is a variable and should already have been assigned by now | |
111 } | |
112 else | |
113 assert(0); | |
114 | |
115 new llvm::ReturnInst(p->scopebb()); | |
116 delete e; | |
117 } | |
118 else { | |
119 elem* e = exp->toElem(p); | |
120 llvm::Value* v = e->getValue(); | |
121 Logger::cout() << *v << '\n'; | |
122 new llvm::ReturnInst(v, p->scopebb()); | |
123 delete e; | |
124 } | |
125 } | |
126 else | |
127 { | |
128 if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) | |
129 new llvm::ReturnInst(p->scopebb()); | |
130 else | |
131 new llvm::UnreachableInst(p->scopebb()); | |
132 } | |
133 | |
134 p->scope().returned = true; | |
135 } | |
136 | |
137 void ExpStatement::toIR(IRState* p) | |
138 { | |
139 static int esi = 0; | |
140 Logger::println("ExpStatement::toIR(%d): %s", esi++, toChars()); | |
141 LOG_SCOPE; | |
142 | |
143 if (exp != 0) { | |
144 elem* e = exp->toElem(p); | |
145 delete e; | |
146 } | |
147 /*elem* e = exp->toElem(p); | |
148 p->buf.printf("%s", e->toChars()); | |
149 delete e; | |
150 p->buf.writenl();*/ | |
151 } | |
152 | |
153 void IfStatement::toIR(IRState* p) | |
154 { | |
155 static int wsi = 0; | |
156 Logger::println("IfStatement::toIR(%d): %s", wsi++, toChars()); | |
157 LOG_SCOPE; | |
158 | |
159 elem* cond_e = condition->toElem(p); | |
160 llvm::Value* cond_val = cond_e->getValue(); | |
161 delete cond_e; | |
162 | |
163 llvm::BasicBlock* oldend = gIR->scopeend(); | |
164 | |
165 llvm::BasicBlock* ifbb = new llvm::BasicBlock("if", gIR->topfunc(), oldend); | |
166 llvm::BasicBlock* endbb = new llvm::BasicBlock("endif", gIR->topfunc(), oldend); | |
167 llvm::BasicBlock* elsebb = 0; | |
168 if (elsebody) { | |
169 elsebb = new llvm::BasicBlock("else", gIR->topfunc(), endbb); | |
170 } | |
171 else { | |
172 elsebb = endbb; | |
173 } | |
174 | |
175 if (cond_val->getType() != llvm::Type::Int1Ty) { | |
176 Logger::cout() << "if conditional: " << *cond_val << '\n'; | |
177 cond_val = LLVM_DtoBoolean(cond_val); | |
178 } | |
179 llvm::Value* ifgoback = new llvm::BranchInst(ifbb, elsebb, cond_val, gIR->scopebegin()); | |
180 | |
181 // replace current scope | |
182 gIR->scope() = IRScope(ifbb,elsebb); | |
183 | |
184 bool endifUsed = false; | |
185 | |
186 // do scoped statements | |
187 ifbody->toIR(p); | |
188 if (!gIR->scopereturned()) { | |
189 new llvm::BranchInst(endbb,gIR->scopebegin()); | |
190 endifUsed = true; | |
191 } | |
192 | |
193 if (elsebody) { | |
194 //assert(0); | |
195 gIR->scope() = IRScope(elsebb,endbb); | |
196 elsebody->toIR(p); | |
197 if (!gIR->scopereturned()) { | |
198 new llvm::BranchInst(endbb,gIR->scopebegin()); | |
199 endifUsed = true; | |
200 } | |
201 } | |
202 | |
203 // rewrite the scope | |
204 gIR->scope() = IRScope(endbb,oldend); | |
205 } | |
206 | |
207 void ScopeStatement::toIR(IRState* p) | |
208 { | |
209 Logger::println("ScopeStatement::toIR(): %s", toChars()); | |
210 LOG_SCOPE; | |
211 | |
212 llvm::BasicBlock* oldend = p->scopeend(); | |
213 | |
214 IRScope irs; | |
215 // remove useless branches by clearing and reusing the current basicblock | |
216 llvm::BasicBlock* bb = p->scopebegin(); | |
217 if (bb->empty()) { | |
218 irs.begin = bb; | |
219 } | |
220 else { | |
221 irs.begin = new llvm::BasicBlock("scope", p->topfunc(), oldend); | |
222 new llvm::BranchInst(irs.begin, p->scopebegin()); | |
223 } | |
224 irs.end = new llvm::BasicBlock("endscope", p->topfunc(), oldend); | |
225 | |
226 gIR->scope() = irs; | |
227 | |
228 statement->toIR(p); | |
229 | |
230 p->scope() = IRScope(p->scopebb(),oldend); | |
231 irs.end->eraseFromParent(); | |
232 | |
233 /* | |
234 if (!gIR->scopereturned()) { | |
235 new llvm::BranchInst(irs.end, gIR->scopebegin()); | |
236 } | |
237 | |
238 // rewrite the scope | |
239 gIR->scope() = IRScope(irs.end,oldend); | |
240 */ | |
241 } | |
242 | |
243 void WhileStatement::toIR(IRState* p) | |
244 { | |
245 static int wsi = 0; | |
246 Logger::println("WhileStatement::toIR(%d): %s", wsi++, toChars()); | |
247 LOG_SCOPE; | |
248 | |
249 // create while blocks | |
250 llvm::BasicBlock* oldend = gIR->scopeend(); | |
251 llvm::BasicBlock* whilebb = new llvm::BasicBlock("whilecond", gIR->topfunc(), oldend); | |
252 llvm::BasicBlock* endbb = new llvm::BasicBlock("endwhile", gIR->topfunc(), oldend); | |
253 | |
254 // move into the while block | |
255 new llvm::BranchInst(whilebb, gIR->scopebegin()); | |
256 | |
257 // replace current scope | |
258 gIR->scope() = IRScope(whilebb,endbb); | |
259 | |
260 // create the condition | |
261 elem* cond_e = condition->toElem(p); | |
262 llvm::Value* cond_val = LLVM_DtoBoolean(cond_e->getValue()); | |
263 delete cond_e; | |
264 | |
265 // while body block | |
266 llvm::BasicBlock* whilebodybb = new llvm::BasicBlock("whilebody", gIR->topfunc(), endbb); | |
267 | |
268 // conditional branch | |
269 llvm::Value* ifbreak = new llvm::BranchInst(whilebodybb, endbb, cond_val, whilebb); | |
270 | |
271 // rewrite scope | |
272 gIR->scope() = IRScope(whilebodybb,endbb); | |
273 | |
274 // do while body code | |
275 body->toIR(p); | |
276 | |
277 // loop | |
278 new llvm::BranchInst(whilebb, gIR->scopebegin()); | |
279 | |
280 // rewrite the scope | |
281 gIR->scope() = IRScope(endbb,oldend); | |
282 } | |
283 | |
284 void DoStatement::toIR(IRState* p) | |
285 { | |
286 static int wsi = 0; | |
287 Logger::println("DoStatement::toIR(%d): %s", wsi++, toChars()); | |
288 LOG_SCOPE; | |
289 | |
290 // create while blocks | |
291 llvm::BasicBlock* oldend = gIR->scopeend(); | |
292 llvm::BasicBlock* dowhilebb = new llvm::BasicBlock("dowhile", gIR->topfunc(), oldend); | |
293 llvm::BasicBlock* endbb = new llvm::BasicBlock("enddowhile", gIR->topfunc(), oldend); | |
294 | |
295 // move into the while block | |
296 new llvm::BranchInst(dowhilebb, gIR->scopebegin()); | |
297 | |
298 // replace current scope | |
299 gIR->scope() = IRScope(dowhilebb,endbb); | |
300 | |
301 // do do-while body code | |
302 body->toIR(p); | |
303 | |
304 // create the condition | |
305 elem* cond_e = condition->toElem(p); | |
306 llvm::Value* cond_val = LLVM_DtoBoolean(cond_e->getValue()); | |
307 delete cond_e; | |
308 | |
309 // conditional branch | |
310 llvm::Value* ifbreak = new llvm::BranchInst(dowhilebb, endbb, cond_val, gIR->scopebegin()); | |
311 | |
312 // rewrite the scope | |
313 gIR->scope() = IRScope(endbb,oldend); | |
314 } | |
315 | |
316 void ForStatement::toIR(IRState* p) | |
317 { | |
318 static int wsi = 0; | |
319 Logger::println("ForStatement::toIR(%d): %s", wsi++, toChars()); | |
320 LOG_SCOPE; | |
321 | |
322 // create for blocks | |
323 llvm::BasicBlock* oldend = gIR->scopeend(); | |
324 llvm::BasicBlock* forbb = new llvm::BasicBlock("forcond", gIR->topfunc(), oldend); | |
325 llvm::BasicBlock* forbodybb = new llvm::BasicBlock("forbody", gIR->topfunc(), oldend); | |
326 llvm::BasicBlock* forincbb = new llvm::BasicBlock("forinc", gIR->topfunc(), oldend); | |
327 llvm::BasicBlock* endbb = new llvm::BasicBlock("endfor", gIR->topfunc(), oldend); | |
328 | |
329 // init | |
330 if (init != 0) | |
331 init->toIR(p); | |
332 | |
333 // move into the for condition block, ie. start the loop | |
334 new llvm::BranchInst(forbb, gIR->scopebegin()); | |
335 | |
336 IRScope loop; | |
337 loop.begin = forincbb; | |
338 loop.end = endbb; | |
339 p->loopbbs.push_back(loop); | |
340 | |
341 // replace current scope | |
342 gIR->scope() = IRScope(forbb,forbodybb); | |
343 | |
344 // create the condition | |
345 elem* cond_e = condition->toElem(p); | |
346 llvm::Value* cond_val = LLVM_DtoBoolean(cond_e->getValue()); | |
347 delete cond_e; | |
348 | |
349 // conditional branch | |
350 llvm::Value* ifbreak = new llvm::BranchInst(forbodybb, endbb, cond_val, forbb); | |
351 | |
352 // rewrite scope | |
353 gIR->scope() = IRScope(forbodybb,forincbb); | |
354 | |
355 // do for body code | |
356 body->toIR(p); | |
357 | |
358 // move into the for increment block | |
359 new llvm::BranchInst(forincbb, gIR->scopebegin()); | |
360 gIR->scope() = IRScope(forincbb, endbb); | |
361 | |
362 // increment | |
363 if (increment) { | |
364 elem* inc = increment->toElem(p); | |
365 delete inc; | |
366 } | |
367 | |
368 // loop | |
369 new llvm::BranchInst(forbb, gIR->scopebegin()); | |
370 | |
371 p->loopbbs.pop_back(); | |
372 | |
373 // rewrite the scope | |
374 gIR->scope() = IRScope(endbb,oldend); | |
375 } | |
376 | |
377 void BreakStatement::toIR(IRState* p) | |
378 { | |
379 static int wsi = 0; | |
380 Logger::println("BreakStatement::toIR(%d): %s", wsi++, toChars()); | |
381 LOG_SCOPE; | |
382 | |
383 if (ident != 0) { | |
384 Logger::println("ident = %s", ident->toChars()); | |
385 assert(0); | |
386 } | |
387 else { | |
388 new llvm::BranchInst(gIR->loopbbs.back().end, gIR->scopebegin()); | |
389 } | |
390 } | |
391 | |
392 void ContinueStatement::toIR(IRState* p) | |
393 { | |
394 static int wsi = 0; | |
395 Logger::println("ContinueStatement::toIR(%d): %s", wsi++, toChars()); | |
396 LOG_SCOPE; | |
397 | |
398 if (ident != 0) { | |
399 Logger::println("ident = %s", ident->toChars()); | |
400 assert(0); | |
401 } | |
402 else { | |
403 new llvm::BranchInst(gIR->loopbbs.back().begin, gIR->scopebegin()); | |
404 } | |
405 } | |
406 | |
407 void OnScopeStatement::toIR(IRState* p) | |
408 { | |
409 static int wsi = 0; | |
410 Logger::println("OnScopeStatement::toIR(%d): %s", wsi++, toChars()); | |
411 LOG_SCOPE; | |
412 | |
413 assert(statement); | |
414 //statement->toIR(p); // this seems to be redundant | |
415 } | |
416 | |
417 void TryFinallyStatement::toIR(IRState* p) | |
418 { | |
419 static int wsi = 0; | |
420 Logger::println("TryFinallyStatement::toIR(%d): %s", wsi++, toChars()); | |
421 LOG_SCOPE; | |
422 | |
423 llvm::BasicBlock* oldend = gIR->scopeend(); | |
424 | |
425 llvm::BasicBlock* trybb = new llvm::BasicBlock("try", gIR->topfunc(), oldend); | |
426 llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", gIR->topfunc(), oldend); | |
427 llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", gIR->topfunc(), oldend); | |
428 | |
429 // pass the previous BB into this | |
430 new llvm::BranchInst(trybb, gIR->scopebegin()); | |
431 | |
432 gIR->scope() = IRScope(trybb,finallybb); | |
433 | |
434 assert(body); | |
435 body->toIR(p); | |
436 new llvm::BranchInst(finallybb, gIR->scopebegin()); | |
437 | |
438 // rewrite the scope | |
439 gIR->scope() = IRScope(finallybb,endbb); | |
440 | |
441 assert(finalbody); | |
442 finalbody->toIR(p); | |
443 new llvm::BranchInst(endbb, gIR->scopebegin()); | |
444 | |
445 // rewrite the scope | |
446 gIR->scope() = IRScope(endbb,oldend); | |
447 } | |
448 | |
449 void TryCatchStatement::toIR(IRState* p) | |
450 { | |
451 static int wsi = 0; | |
452 Logger::println("TryCatchStatement::toIR(%d): %s", wsi++, toChars()); | |
453 LOG_SCOPE; | |
454 | |
455 assert(0 && "try-catch is not properly"); | |
456 | |
457 assert(body); | |
458 body->toIR(p); | |
459 | |
460 assert(catches); | |
461 for(size_t i=0; i<catches->dim; ++i) | |
462 { | |
463 Catch* c = (Catch*)catches->data[i]; | |
464 c->handler->toIR(p); | |
465 } | |
466 } | |
467 | |
468 void ThrowStatement::toIR(IRState* p) | |
469 { | |
470 static int wsi = 0; | |
471 Logger::println("ThrowStatement::toIR(%d): %s", wsi++, toChars()); | |
472 LOG_SCOPE; | |
473 | |
474 assert(0 && "throw is not implemented"); | |
475 | |
476 assert(exp); | |
477 elem* e = exp->toElem(p); | |
478 delete e; | |
479 } | |
480 | |
481 void SwitchStatement::toIR(IRState* p) | |
482 { | |
483 Logger::println("SwitchStatement::toIR(): %s", toChars()); | |
484 LOG_SCOPE; | |
485 | |
486 llvm::BasicBlock* oldend = gIR->scopeend(); | |
487 | |
488 // collect the needed cases | |
489 typedef std::pair<llvm::BasicBlock*, llvm::ConstantInt*> CasePair; | |
490 std::vector<CasePair> vcases; | |
491 for (int i=0; i<cases->dim; ++i) | |
492 { | |
493 CaseStatement* cs = (CaseStatement*)cases->data[i]; | |
494 | |
495 // get the case value | |
496 elem* e = cs->exp->toElem(p); | |
497 assert(e->val && llvm::isa<llvm::ConstantInt>(e->val)); | |
498 llvm::ConstantInt* ec = llvm::cast<llvm::ConstantInt>(e->val); | |
499 delete e; | |
500 | |
501 // create the case bb with a nice label | |
502 std::string lblname("case"+std::string(cs->exp->toChars())); | |
503 llvm::BasicBlock* bb = new llvm::BasicBlock(lblname, p->topfunc(), oldend); | |
504 | |
505 vcases.push_back(CasePair(bb,ec)); | |
506 } | |
507 | |
508 // default | |
509 llvm::BasicBlock* defbb = 0; | |
510 if (!hasNoDefault) { | |
511 defbb = new llvm::BasicBlock("default", p->topfunc(), oldend); | |
512 } | |
513 | |
514 // end (break point) | |
515 llvm::BasicBlock* endbb = new llvm::BasicBlock("switchend", p->topfunc(), oldend); | |
516 | |
517 // condition var | |
518 elem* cond = condition->toElem(p); | |
519 llvm::SwitchInst* si = new llvm::SwitchInst(cond->getValue(), defbb ? defbb : endbb, cases->dim, p->scopebb()); | |
520 delete cond; | |
521 | |
522 // add the cases | |
523 size_t n = vcases.size(); | |
524 for (size_t i=0; i<n; ++i) | |
525 { | |
526 si->addCase(vcases[i].second, vcases[i].first); | |
527 } | |
528 | |
529 // insert case statements | |
530 for (size_t i=0; i<n; ++i) | |
531 { | |
532 llvm::BasicBlock* nextbb = (i == n-1) ? (defbb ? defbb : endbb) : vcases[i+1].first; | |
533 p->scope() = IRScope(vcases[i].first,nextbb); | |
534 | |
535 p->loopbbs.push_back(IRScope(p->scopebb(),endbb)); | |
536 static_cast<CaseStatement*>(cases->data[i])->statement->toIR(p); | |
537 p->loopbbs.pop_back(); | |
538 | |
539 llvm::BasicBlock* curbb = p->scopebb(); | |
540 if (!curbb->empty() && !curbb->back().isTerminator()) | |
541 { | |
542 new llvm::BranchInst(nextbb, curbb); | |
543 } | |
544 } | |
545 | |
546 // default statement | |
547 if (defbb) | |
548 { | |
549 p->scope() = IRScope(defbb,endbb); | |
550 p->loopbbs.push_back(IRScope(defbb,endbb)); | |
551 sdefault->statement->toIR(p); | |
552 p->loopbbs.pop_back(); | |
553 | |
554 llvm::BasicBlock* curbb = p->scopebb(); | |
555 if (!curbb->empty() && !curbb->back().isTerminator()) | |
556 { | |
557 new llvm::BranchInst(endbb, curbb); | |
558 } | |
559 } | |
560 | |
561 gIR->scope() = IRScope(endbb,oldend); | |
562 } | |
563 | |
564 #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();} | |
565 //STUBST(BreakStatement); | |
566 //STUBST(ForStatement); | |
567 STUBST(WithStatement); | |
568 STUBST(SynchronizedStatement); | |
569 //STUBST(ReturnStatement); | |
570 //STUBST(ContinueStatement); | |
571 STUBST(DefaultStatement); | |
572 STUBST(CaseStatement); | |
573 //STUBST(SwitchStatement); | |
574 STUBST(SwitchErrorStatement); | |
575 STUBST(Statement); | |
576 //STUBST(IfStatement); | |
577 STUBST(ForeachStatement); | |
578 //STUBST(DoStatement); | |
579 //STUBST(WhileStatement); | |
580 //STUBST(ExpStatement); | |
581 //STUBST(CompoundStatement); | |
582 //STUBST(ScopeStatement); | |
583 STUBST(AsmStatement); | |
584 //STUBST(TryCatchStatement); | |
585 //STUBST(TryFinallyStatement); | |
586 STUBST(VolatileStatement); | |
587 STUBST(LabelStatement); | |
588 //STUBST(ThrowStatement); | |
589 STUBST(GotoCaseStatement); | |
590 STUBST(GotoDefaultStatement); | |
591 STUBST(GotoStatement); | |
592 STUBST(UnrolledLoopStatement); | |
593 //STUBST(OnScopeStatement); |