comparison gen/statements.cpp @ 86:fd32135dca3e trunk

[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!! Lots of bugfixes. Added support for special foreach on strings. Added std.array, std.utf, std.ctype and std.uni to phobos. Changed all the .c files in the gen dir to .cpp (it *is* C++ after all)
author lindquist
date Sat, 03 Nov 2007 14:44:58 +0100
parents gen/statements.c@d8dd47ef3973
children 61615fa85940
comparison
equal deleted inserted replaced
85:f869c636a113 86:fd32135dca3e
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 "gen/llvm.h"
10 #include "llvm/Transforms/Utils/Cloning.h"
11
12 #include "total.h"
13 #include "init.h"
14 #include "symbol.h"
15 #include "mtype.h"
16 #include "hdrgen.h"
17 #include "port.h"
18
19 #include "gen/irstate.h"
20 #include "gen/elem.h"
21 #include "gen/logger.h"
22 #include "gen/tollvm.h"
23 #include "gen/runtime.h"
24 #include "gen/arrays.h"
25 #include "gen/todebug.h"
26 #include "gen/dvalue.h"
27
28 //////////////////////////////////////////////////////////////////////////////
29
30 void CompoundStatement::toIR(IRState* p)
31 {
32 static int csi = 0;
33 Logger::println("CompoundStatement::toIR(%d):\n<<<\n%s>>>", csi++, toChars());
34 LOG_SCOPE;
35
36 for (int i=0; i<statements->dim; i++)
37 {
38 Statement* s = (Statement*)statements->data[i];
39 if (s)
40 s->toIR(p);
41 else {
42 Logger::println("*** ATTENTION: null statement found in CompoundStatement");
43 //assert(0);
44 }
45 }
46 }
47
48 //////////////////////////////////////////////////////////////////////////////
49
50 void ReturnStatement::toIR(IRState* p)
51 {
52 static int rsi = 0;
53 Logger::println("ReturnStatement::toIR(%d): %s", rsi++, toChars());
54 LOG_SCOPE;
55
56 if (exp)
57 {
58 Logger::println("return type is: %s", exp->type->toChars());
59
60 Type* exptype = DtoDType(exp->type);
61 TY expty = exptype->ty;
62 if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
63 assert(DtoIsPassedByRef(exptype));
64
65 TypeFunction* f = p->topfunctype();
66 assert(f->llvmRetInPtr && f->llvmRetArg);
67
68 if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
69
70 DValue* rvar = new DVarValue(f->next, f->llvmRetArg, true);
71
72 p->exps.push_back(IRExp(NULL,exp,rvar));
73 DValue* e = exp->toElem(p);
74 p->exps.pop_back();
75
76 if (!e->inPlace())
77 DtoAssign(rvar, e);
78
79 IRFunction::FinallyVec& fin = p->func().finallys;
80 if (fin.empty()) {
81 if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
82 new llvm::ReturnInst(p->scopebb());
83 }
84 else {
85 new llvm::BranchInst(fin.back().retbb, p->scopebb());
86 }
87 }
88 else {
89 if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
90 DValue* e = exp->toElem(p);
91 llvm::Value* v = e->getRVal();
92 delete e;
93 Logger::cout() << "return value is '" <<*v << "'\n";
94
95 IRFunction::FinallyVec& fin = p->func().finallys;
96 if (fin.empty()) {
97 if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
98 new llvm::ReturnInst(v, p->scopebb());
99 }
100 else {
101 if (!p->func().finallyretval)
102 p->func().finallyretval = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint());
103 llvm::Value* rettmp = p->func().finallyretval;
104 new llvm::StoreInst(v,rettmp,p->scopebb());
105 new llvm::BranchInst(fin.back().retbb, p->scopebb());
106 }
107 }
108 }
109 else
110 {
111 if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
112 IRFunction::FinallyVec& fin = p->func().finallys;
113 if (fin.empty()) {
114 if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
115 new llvm::ReturnInst(p->scopebb());
116 }
117 else {
118 new llvm::BranchInst(fin.back().retbb, p->scopebb());
119 }
120 }
121 else {
122 assert(0); // why should this ever happen?
123 new llvm::UnreachableInst(p->scopebb());
124 }
125 }
126 }
127
128 //////////////////////////////////////////////////////////////////////////////
129
130 void ExpStatement::toIR(IRState* p)
131 {
132 static int esi = 0;
133 Logger::println("ExpStatement::toIR(%d): %s", esi++, toChars());
134 LOG_SCOPE;
135
136 if (global.params.symdebug)
137 DtoDwarfStopPoint(loc.linnum);
138
139 if (exp != 0) {
140 elem* e = exp->toElem(p);
141 delete e;
142 }
143 /*elem* e = exp->toElem(p);
144 p->buf.printf("%s", e->toChars());
145 delete e;
146 p->buf.writenl();*/
147 }
148
149 //////////////////////////////////////////////////////////////////////////////
150
151 void IfStatement::toIR(IRState* p)
152 {
153 static int wsi = 0;
154 Logger::println("IfStatement::toIR(%d): %s", wsi++, toChars());
155 LOG_SCOPE;
156
157 DValue* cond_e = condition->toElem(p);
158 llvm::Value* cond_val = cond_e->getRVal();
159 delete cond_e;
160
161 llvm::BasicBlock* oldend = gIR->scopeend();
162
163 llvm::BasicBlock* ifbb = new llvm::BasicBlock("if", gIR->topfunc(), oldend);
164 llvm::BasicBlock* endbb = new llvm::BasicBlock("endif", gIR->topfunc(), oldend);
165 llvm::BasicBlock* elsebb = elsebody ? new llvm::BasicBlock("else", gIR->topfunc(), endbb) : endbb;
166
167 if (cond_val->getType() != llvm::Type::Int1Ty) {
168 Logger::cout() << "if conditional: " << *cond_val << '\n';
169 cond_val = DtoBoolean(cond_val);
170 }
171 llvm::Value* ifgoback = new llvm::BranchInst(ifbb, elsebb, cond_val, gIR->scopebegin());
172
173 // replace current scope
174 gIR->scope() = IRScope(ifbb,elsebb);
175
176 // do scoped statements
177 ifbody->toIR(p);
178 if (!gIR->scopereturned()) {
179 new llvm::BranchInst(endbb,gIR->scopebegin());
180 }
181
182 if (elsebody) {
183 //assert(0);
184 gIR->scope() = IRScope(elsebb,endbb);
185 elsebody->toIR(p);
186 if (!gIR->scopereturned()) {
187 new llvm::BranchInst(endbb,gIR->scopebegin());
188 }
189 }
190
191 // rewrite the scope
192 gIR->scope() = IRScope(endbb,oldend);
193 }
194
195 //////////////////////////////////////////////////////////////////////////////
196
197 void ScopeStatement::toIR(IRState* p)
198 {
199 Logger::println("ScopeStatement::toIR(): %s", toChars());
200 LOG_SCOPE;
201
202 llvm::BasicBlock* oldend = p->scopeend();
203
204 llvm::BasicBlock* beginbb = 0;
205
206 // remove useless branches by clearing and reusing the current basicblock
207 llvm::BasicBlock* bb = p->scopebegin();
208 if (bb->empty()) {
209 beginbb = bb;
210 }
211 else {
212 assert(!p->scopereturned());
213 beginbb = new llvm::BasicBlock("scope", p->topfunc(), oldend);
214 new llvm::BranchInst(beginbb, p->scopebegin());
215 }
216 llvm::BasicBlock* endbb = new llvm::BasicBlock("endscope", p->topfunc(), oldend);
217
218 gIR->scope() = IRScope(beginbb, endbb);
219
220 statement->toIR(p);
221
222 p->scope() = IRScope(p->scopebb(),oldend);
223 endbb->eraseFromParent();
224 }
225
226 //////////////////////////////////////////////////////////////////////////////
227
228 void WhileStatement::toIR(IRState* p)
229 {
230 static int wsi = 0;
231 Logger::println("WhileStatement::toIR(%d): %s", wsi++, toChars());
232 LOG_SCOPE;
233
234 // create while blocks
235 llvm::BasicBlock* oldend = gIR->scopeend();
236 llvm::BasicBlock* whilebb = new llvm::BasicBlock("whilecond", gIR->topfunc(), oldend);
237 llvm::BasicBlock* whilebodybb = new llvm::BasicBlock("whilebody", gIR->topfunc(), oldend);
238 llvm::BasicBlock* endbb = new llvm::BasicBlock("endwhile", gIR->topfunc(), oldend);
239
240 // move into the while block
241 p->ir->CreateBr(whilebb);
242 //new llvm::BranchInst(whilebb, gIR->scopebegin());
243
244 // replace current scope
245 gIR->scope() = IRScope(whilebb,endbb);
246
247 // create the condition
248 DValue* cond_e = condition->toElem(p);
249 llvm::Value* cond_val = DtoBoolean(cond_e->getRVal());
250 delete cond_e;
251
252 // conditional branch
253 llvm::Value* ifbreak = new llvm::BranchInst(whilebodybb, endbb, cond_val, p->scopebb());
254
255 // rewrite scope
256 gIR->scope() = IRScope(whilebodybb,endbb);
257
258 // do while body code
259 body->toIR(p);
260
261 // loop
262 new llvm::BranchInst(whilebb, gIR->scopebegin());
263
264 // rewrite the scope
265 gIR->scope() = IRScope(endbb,oldend);
266 }
267
268 //////////////////////////////////////////////////////////////////////////////
269
270 void DoStatement::toIR(IRState* p)
271 {
272 static int wsi = 0;
273 Logger::println("DoStatement::toIR(%d): %s", wsi++, toChars());
274 LOG_SCOPE;
275
276 // create while blocks
277 llvm::BasicBlock* oldend = gIR->scopeend();
278 llvm::BasicBlock* dowhilebb = new llvm::BasicBlock("dowhile", gIR->topfunc(), oldend);
279 llvm::BasicBlock* endbb = new llvm::BasicBlock("enddowhile", gIR->topfunc(), oldend);
280
281 // move into the while block
282 new llvm::BranchInst(dowhilebb, gIR->scopebegin());
283
284 // replace current scope
285 gIR->scope() = IRScope(dowhilebb,endbb);
286
287 // do do-while body code
288 body->toIR(p);
289
290 // create the condition
291 DValue* cond_e = condition->toElem(p);
292 llvm::Value* cond_val = DtoBoolean(cond_e->getRVal());
293 delete cond_e;
294
295 // conditional branch
296 llvm::Value* ifbreak = new llvm::BranchInst(dowhilebb, endbb, cond_val, gIR->scopebegin());
297
298 // rewrite the scope
299 gIR->scope() = IRScope(endbb,oldend);
300 }
301
302 //////////////////////////////////////////////////////////////////////////////
303
304 void ForStatement::toIR(IRState* p)
305 {
306 static int wsi = 0;
307 Logger::println("ForStatement::toIR(%d): %s", wsi++, toChars());
308 LOG_SCOPE;
309
310 // create for blocks
311 llvm::BasicBlock* oldend = gIR->scopeend();
312 llvm::BasicBlock* forbb = new llvm::BasicBlock("forcond", gIR->topfunc(), oldend);
313 llvm::BasicBlock* forbodybb = new llvm::BasicBlock("forbody", gIR->topfunc(), oldend);
314 llvm::BasicBlock* forincbb = new llvm::BasicBlock("forinc", gIR->topfunc(), oldend);
315 llvm::BasicBlock* endbb = new llvm::BasicBlock("endfor", gIR->topfunc(), oldend);
316
317 // init
318 if (init != 0)
319 init->toIR(p);
320
321 // move into the for condition block, ie. start the loop
322 new llvm::BranchInst(forbb, gIR->scopebegin());
323
324 p->loopbbs.push_back(IRScope(forincbb,endbb));
325
326 // replace current scope
327 gIR->scope() = IRScope(forbb,forbodybb);
328
329 // create the condition
330 DValue* cond_e = condition->toElem(p);
331 llvm::Value* cond_val = DtoBoolean(cond_e->getRVal());
332 delete cond_e;
333
334 // conditional branch
335 llvm::Value* ifbreak = new llvm::BranchInst(forbodybb, endbb, cond_val, forbb);
336
337 // rewrite scope
338 gIR->scope() = IRScope(forbodybb,forincbb);
339
340 // do for body code
341 body->toIR(p);
342
343 // move into the for increment block
344 new llvm::BranchInst(forincbb, gIR->scopebegin());
345 gIR->scope() = IRScope(forincbb, endbb);
346
347 // increment
348 if (increment) {
349 DValue* inc = increment->toElem(p);
350 delete inc;
351 }
352
353 // loop
354 new llvm::BranchInst(forbb, gIR->scopebegin());
355
356 p->loopbbs.pop_back();
357
358 // rewrite the scope
359 gIR->scope() = IRScope(endbb,oldend);
360 }
361
362 //////////////////////////////////////////////////////////////////////////////
363
364 void BreakStatement::toIR(IRState* p)
365 {
366 static int wsi = 0;
367 Logger::println("BreakStatement::toIR(%d): %s", wsi++, toChars());
368 LOG_SCOPE;
369
370 if (ident != 0) {
371 Logger::println("ident = %s", ident->toChars());
372 assert(0);
373 }
374 else {
375 new llvm::BranchInst(gIR->loopbbs.back().end, gIR->scopebegin());
376 }
377 }
378
379 //////////////////////////////////////////////////////////////////////////////
380
381 void ContinueStatement::toIR(IRState* p)
382 {
383 static int wsi = 0;
384 Logger::println("ContinueStatement::toIR(%d): %s", wsi++, toChars());
385 LOG_SCOPE;
386
387 if (ident != 0) {
388 Logger::println("ident = %s", ident->toChars());
389 assert(0);
390 }
391 else {
392 new llvm::BranchInst(gIR->loopbbs.back().begin, gIR->scopebegin());
393 }
394 }
395
396 //////////////////////////////////////////////////////////////////////////////
397
398 void OnScopeStatement::toIR(IRState* p)
399 {
400 static int wsi = 0;
401 Logger::println("OnScopeStatement::toIR(%d): %s", wsi++, toChars());
402 LOG_SCOPE;
403
404 assert(statement);
405 //statement->toIR(p); // this seems to be redundant
406 }
407
408 //////////////////////////////////////////////////////////////////////////////
409
410 static void replaceFinallyBBs(std::vector<llvm::BasicBlock*>& a, std::vector<llvm::BasicBlock*>& b)
411 {
412 }
413
414 void TryFinallyStatement::toIR(IRState* p)
415 {
416 Logger::println("TryFinallyStatement::toIR(): %s", toChars());
417 LOG_SCOPE;
418
419 // create basic blocks
420 llvm::BasicBlock* oldend = p->scopeend();
421
422 llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend);
423 llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", p->topfunc(), oldend);
424 llvm::BasicBlock* finallyretbb = new llvm::BasicBlock("finallyreturn", p->topfunc(), oldend);
425 llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", p->topfunc(), oldend);
426
427 // pass the previous BB into this
428 assert(!gIR->scopereturned());
429 new llvm::BranchInst(trybb, p->scopebb());
430
431 // do the try block
432 p->scope() = IRScope(trybb,finallybb);
433 gIR->func().finallys.push_back(IRFinally(finallybb,finallyretbb));
434 IRFinally& fin = p->func().finallys.back();
435
436 assert(body);
437 body->toIR(p);
438
439 // terminate try BB
440 if (!p->scopereturned())
441 new llvm::BranchInst(finallybb, p->scopebb());
442
443 // do finally block
444 p->scope() = IRScope(finallybb,finallyretbb);
445 assert(finalbody);
446 finalbody->toIR(p);
447
448 // terminate finally
449 if (!gIR->scopereturned()) {
450 new llvm::BranchInst(endbb, p->scopebb());
451 }
452
453 // do finally block (return path)
454 p->scope() = IRScope(finallyretbb,endbb);
455 assert(finalbody);
456 finalbody->toIR(p); // hope this will work, otherwise it's time it gets fixed
457
458 // terminate finally (return path)
459 size_t nfin = p->func().finallys.size();
460 if (nfin > 1) {
461 IRFinally& ofin = p->func().finallys[nfin-2];
462 p->ir->CreateBr(ofin.retbb);
463 }
464 // no outer
465 else
466 {
467 if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
468 llvm::Value* retval = p->func().finallyretval;
469 if (retval) {
470 retval = p->ir->CreateLoad(retval,"tmp");
471 p->ir->CreateRet(retval);
472 }
473 else {
474 FuncDeclaration* fd = p->func().decl;
475 if (fd->isMain()) {
476 assert(fd->type->next->ty == Tvoid);
477 p->ir->CreateRet(DtoConstInt(0));
478 }
479 else {
480 p->ir->CreateRetVoid();
481 }
482 }
483 }
484
485 // rewrite the scope
486 p->func().finallys.pop_back();
487 p->scope() = IRScope(endbb,oldend);
488 }
489
490 //////////////////////////////////////////////////////////////////////////////
491
492 void TryCatchStatement::toIR(IRState* p)
493 {
494 static int wsi = 0;
495 Logger::println("TryCatchStatement::toIR(%d): %s", wsi++, toChars());
496 LOG_SCOPE;
497
498 Logger::println("*** ATTENTION: try-catch is not yet fully implemented, only the try block will be emitted.");
499
500 assert(body);
501 body->toIR(p);
502
503 /*assert(catches);
504 for(size_t i=0; i<catches->dim; ++i)
505 {
506 Catch* c = (Catch*)catches->data[i];
507 c->handler->toIR(p);
508 }*/
509 }
510
511 //////////////////////////////////////////////////////////////////////////////
512
513 void ThrowStatement::toIR(IRState* p)
514 {
515 static int wsi = 0;
516 Logger::println("ThrowStatement::toIR(%d): %s", wsi++, toChars());
517 LOG_SCOPE;
518
519 Logger::println("*** ATTENTION: throw is not yet implemented, replacing expression with assert(0);");
520
521 llvm::Value* line = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
522 DtoAssert(NULL, line, NULL);
523
524 /*
525 assert(exp);
526 DValue* e = exp->toElem(p);
527 delete e;
528 */
529 }
530
531 //////////////////////////////////////////////////////////////////////////////
532
533 void SwitchStatement::toIR(IRState* p)
534 {
535 Logger::println("SwitchStatement::toIR(): %s", toChars());
536 LOG_SCOPE;
537
538 llvm::BasicBlock* oldend = gIR->scopeend();
539
540 // collect the needed cases
541 typedef std::pair<llvm::BasicBlock*, llvm::ConstantInt*> CasePair;
542 std::vector<CasePair> vcases;
543 for (int i=0; i<cases->dim; ++i)
544 {
545 CaseStatement* cs = (CaseStatement*)cases->data[i];
546
547 // get the case value
548 DValue* e = cs->exp->toElem(p);
549 DConstValue* ce = e->isConst();
550 assert(ce && llvm::isa<llvm::ConstantInt>(ce->c));
551 llvm::ConstantInt* ec = llvm::cast<llvm::ConstantInt>(ce->c);
552 delete e;
553
554 // create the case bb with a nice label
555 std::string lblname("case"+std::string(cs->exp->toChars()));
556 llvm::BasicBlock* bb = new llvm::BasicBlock(lblname, p->topfunc(), oldend);
557
558 vcases.push_back(CasePair(bb,ec));
559 }
560
561 // default
562 llvm::BasicBlock* defbb = 0;
563 if (!hasNoDefault) {
564 defbb = new llvm::BasicBlock("default", p->topfunc(), oldend);
565 }
566
567 // end (break point)
568 llvm::BasicBlock* endbb = new llvm::BasicBlock("switchend", p->topfunc(), oldend);
569
570 // condition var
571 DValue* cond = condition->toElem(p);
572 llvm::SwitchInst* si = new llvm::SwitchInst(cond->getRVal(), defbb ? defbb : endbb, cases->dim, p->scopebb());
573 delete cond;
574
575 // add the cases
576 size_t n = vcases.size();
577 for (size_t i=0; i<n; ++i)
578 {
579 si->addCase(vcases[i].second, vcases[i].first);
580 }
581
582 // insert case statements
583 for (size_t i=0; i<n; ++i)
584 {
585 llvm::BasicBlock* nextbb = (i == n-1) ? (defbb ? defbb : endbb) : vcases[i+1].first;
586 p->scope() = IRScope(vcases[i].first,nextbb);
587
588 p->loopbbs.push_back(IRScope(p->scopebb(),endbb));
589 static_cast<CaseStatement*>(cases->data[i])->statement->toIR(p);
590 p->loopbbs.pop_back();
591
592 llvm::BasicBlock* curbb = p->scopebb();
593 if (curbb->empty() || !curbb->back().isTerminator())
594 {
595 new llvm::BranchInst(nextbb, curbb);
596 }
597 }
598
599 // default statement
600 if (defbb)
601 {
602 p->scope() = IRScope(defbb,endbb);
603 p->loopbbs.push_back(IRScope(defbb,endbb));
604 Logger::println("doing default statement");
605 sdefault->statement->toIR(p);
606 p->loopbbs.pop_back();
607
608 llvm::BasicBlock* curbb = p->scopebb();
609 if (curbb->empty() || !curbb->back().isTerminator())
610 {
611 new llvm::BranchInst(endbb, curbb);
612 }
613 }
614
615 gIR->scope() = IRScope(endbb,oldend);
616 }
617
618 //////////////////////////////////////////////////////////////////////////////
619
620 void UnrolledLoopStatement::toIR(IRState* p)
621 {
622 Logger::println("UnrolledLoopStatement::toIR(): %s", toChars());
623 LOG_SCOPE;
624
625 llvm::BasicBlock* oldend = gIR->scopeend();
626 llvm::BasicBlock* endbb = new llvm::BasicBlock("unrolledend", p->topfunc(), oldend);
627
628 p->scope() = IRScope(p->scopebb(),endbb);
629 p->loopbbs.push_back(IRScope(p->scopebb(),endbb));
630
631 for (int i=0; i<statements->dim; ++i)
632 {
633 Statement* s = (Statement*)statements->data[i];
634 s->toIR(p);
635 }
636
637 p->loopbbs.pop_back();
638
639 new llvm::BranchInst(endbb, p->scopebb());
640 p->scope() = IRScope(endbb,oldend);
641 }
642
643 //////////////////////////////////////////////////////////////////////////////
644
645 void ForeachStatement::toIR(IRState* p)
646 {
647 Logger::println("ForeachStatement::toIR(): %s", toChars());
648 LOG_SCOPE;
649
650 //assert(arguments->dim == 1);
651 assert(value != 0);
652 assert(body != 0);
653 assert(aggr != 0);
654 assert(func != 0);
655
656 //Argument* arg = (Argument*)arguments->data[0];
657 //Logger::println("Argument is %s", arg->toChars());
658
659 Logger::println("aggr = %s", aggr->toChars());
660 Logger::println("func = %s", func->toChars());
661
662 DValue* arr = aggr->toElem(p);
663 llvm::Value* val = 0;
664 if (!arr->isSlice()) {
665 val = arr->getRVal();
666 Logger::cout() << "aggr2llvm = " << *val << '\n';
667 }
668
669 llvm::Value* numiters = 0;
670
671 const llvm::Type* keytype = key ? DtoType(key->type) : DtoSize_t();
672 llvm::Value* keyvar = new llvm::AllocaInst(keytype, "foreachkey", p->topallocapoint());
673 if (key) key->llvmValue = keyvar;
674
675 const llvm::Type* valtype = DtoType(value->type);
676 llvm::Value* valvar = !(value->isRef() || value->isOut()) ? new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint()) : NULL;
677
678 Type* aggrtype = DtoDType(aggr->type);
679 if (aggrtype->ty == Tsarray)
680 {
681 assert(llvm::isa<llvm::PointerType>(val->getType()));
682 assert(llvm::isa<llvm::ArrayType>(val->getType()->getContainedType(0)));
683 size_t n = llvm::cast<llvm::ArrayType>(val->getType()->getContainedType(0))->getNumElements();
684 assert(n > 0);
685 numiters = llvm::ConstantInt::get(keytype,n,false);
686 }
687 else if (aggrtype->ty == Tarray)
688 {
689 if (DSliceValue* slice = arr->isSlice()) {
690 numiters = slice->len;
691 val = slice->ptr;
692 }
693 else {
694 numiters = p->ir->CreateLoad(DtoGEPi(val,0,0,"tmp",p->scopebb()));
695 val = p->ir->CreateLoad(DtoGEPi(val,0,1,"tmp",p->scopebb()));
696 }
697 }
698 else
699 {
700 assert(0 && "aggregate type is not Tarray or Tsarray");
701 }
702
703 if (op == TOKforeach) {
704 new llvm::StoreInst(llvm::ConstantInt::get(keytype,0,false), keyvar, p->scopebb());
705 }
706 else if (op == TOKforeach_reverse) {
707 llvm::Value* v = llvm::BinaryOperator::createSub(numiters, llvm::ConstantInt::get(keytype,1,false),"tmp",p->scopebb());
708 new llvm::StoreInst(v, keyvar, p->scopebb());
709 }
710
711 delete arr;
712
713 llvm::BasicBlock* oldend = gIR->scopeend();
714 llvm::BasicBlock* nexbb = new llvm::BasicBlock("foreachnext", p->topfunc(), oldend);
715 llvm::BasicBlock* begbb = new llvm::BasicBlock("foreachbegin", p->topfunc(), oldend);
716 llvm::BasicBlock* endbb = new llvm::BasicBlock("foreachend", p->topfunc(), oldend);
717
718 new llvm::BranchInst(begbb, p->scopebb());
719
720 // next
721 p->scope() = IRScope(nexbb,begbb);
722 llvm::Value* done = 0;
723 llvm::Value* load = new llvm::LoadInst(keyvar, "tmp", p->scopebb());
724 if (op == TOKforeach) {
725 load = llvm::BinaryOperator::createAdd(load,llvm::ConstantInt::get(keytype, 1, false),"tmp",p->scopebb());
726 new llvm::StoreInst(load, keyvar, p->scopebb());
727 done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_ULT, load, numiters, "tmp", p->scopebb());
728 }
729 else if (op == TOKforeach_reverse) {
730 done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_UGT, load, llvm::ConstantInt::get(keytype, 0, false), "tmp", p->scopebb());
731 load = llvm::BinaryOperator::createSub(load,llvm::ConstantInt::get(keytype, 1, false),"tmp",p->scopebb());
732 new llvm::StoreInst(load, keyvar, p->scopebb());
733 }
734 new llvm::BranchInst(begbb, endbb, done, p->scopebb());
735
736 // begin
737 p->scope() = IRScope(begbb,nexbb);
738
739 // get value for this iteration
740 llvm::Constant* zero = llvm::ConstantInt::get(keytype,0,false);
741 llvm::Value* loadedKey = p->ir->CreateLoad(keyvar,"tmp");
742 if (aggrtype->ty == Tsarray)
743 value->llvmValue = DtoGEP(val,zero,loadedKey,"tmp");
744 else if (aggrtype->ty == Tarray)
745 value->llvmValue = new llvm::GetElementPtrInst(val,loadedKey,"tmp",p->scopebb());
746
747 if (!value->isRef() && !value->isOut()) {
748 DValue* dst = new DVarValue(value->type, valvar, true);
749 DValue* src = new DVarValue(value->type, value->llvmValue, true);
750 DtoAssign(dst, src);
751 delete dst;
752 delete src;
753 value->llvmValue = valvar;
754 }
755
756 // body
757 p->scope() = IRScope(p->scopebb(),endbb);
758 p->loopbbs.push_back(IRScope(nexbb,endbb));
759 body->toIR(p);
760 p->loopbbs.pop_back();
761
762 if (!p->scopereturned())
763 new llvm::BranchInst(nexbb, p->scopebb());
764
765 // end
766 p->scope() = IRScope(endbb,oldend);
767 }
768
769 //////////////////////////////////////////////////////////////////////////////
770
771 void LabelStatement::toIR(IRState* p)
772 {
773 Logger::println("LabelStatement::toIR(): %s", toChars());
774 LOG_SCOPE;
775
776 assert(tf == NULL);
777 assert(!isReturnLabel);
778
779 llvm::BasicBlock* oldend = gIR->scopeend();
780 if (llvmBB)
781 llvmBB->moveBefore(oldend);
782 else
783 llvmBB = new llvm::BasicBlock("label", p->topfunc(), oldend);
784
785 if (!p->scopereturned())
786 new llvm::BranchInst(llvmBB, p->scopebb());
787
788 p->scope() = IRScope(llvmBB,oldend);
789 if (statement)
790 statement->toIR(p);
791 }
792
793 //////////////////////////////////////////////////////////////////////////////
794
795 void GotoStatement::toIR(IRState* p)
796 {
797 Logger::println("GotoStatement::toIR(): %s", toChars());
798 LOG_SCOPE;
799
800 assert(tf == NULL);
801
802 llvm::BasicBlock* oldend = gIR->scopeend();
803 llvm::BasicBlock* bb = new llvm::BasicBlock("aftergoto", p->topfunc(), oldend);
804
805 if (label->statement->llvmBB == NULL)
806 label->statement->llvmBB = new llvm::BasicBlock("label", p->topfunc());
807 assert(!p->scopereturned());
808 new llvm::BranchInst(label->statement->llvmBB, p->scopebb());
809 p->scope() = IRScope(bb,oldend);
810 }
811
812 //////////////////////////////////////////////////////////////////////////////
813
814 void WithStatement::toIR(IRState* p)
815 {
816 Logger::println("WithStatement::toIR(): %s", toChars());
817 LOG_SCOPE;
818
819 assert(exp);
820 assert(body);
821
822 DValue* e = exp->toElem(p);
823 wthis->llvmValue = e->getRVal();
824 delete e;
825
826 body->toIR(p);
827 }
828
829 //////////////////////////////////////////////////////////////////////////////
830
831 //////////////////////////////////////////////////////////////////////////////
832
833 #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();}
834 //STUBST(BreakStatement);
835 //STUBST(ForStatement);
836 //STUBST(WithStatement);
837 STUBST(SynchronizedStatement);
838 //STUBST(ReturnStatement);
839 //STUBST(ContinueStatement);
840 STUBST(DefaultStatement);
841 STUBST(CaseStatement);
842 //STUBST(SwitchStatement);
843 STUBST(SwitchErrorStatement);
844 STUBST(Statement);
845 //STUBST(IfStatement);
846 //STUBST(ForeachStatement);
847 //STUBST(DoStatement);
848 //STUBST(WhileStatement);
849 //STUBST(ExpStatement);
850 //STUBST(CompoundStatement);
851 //STUBST(ScopeStatement);
852 STUBST(AsmStatement);
853 //STUBST(TryCatchStatement);
854 //STUBST(TryFinallyStatement);
855 STUBST(VolatileStatement);
856 //STUBST(LabelStatement);
857 //STUBST(ThrowStatement);
858 STUBST(GotoCaseStatement);
859 STUBST(GotoDefaultStatement);
860 //STUBST(GotoStatement);
861 //STUBST(UnrolledLoopStatement);
862 //STUBST(OnScopeStatement);