Mercurial > projects > ldc
comparison gen/statements.c @ 40:8b0e809563df trunk
[svn r44] Lots of bug fixes.
New array literal support
New array ~= operator support (for single element)
New with statement support
More...
author | lindquist |
---|---|
date | Fri, 19 Oct 2007 07:43:21 +0200 |
parents | 77cdca8c210f |
children | ff359b65fa62 |
comparison
equal
deleted
inserted
replaced
39:fd5e8bbfcb25 | 40:8b0e809563df |
---|---|
4 #include <math.h> | 4 #include <math.h> |
5 #include <sstream> | 5 #include <sstream> |
6 #include <fstream> | 6 #include <fstream> |
7 #include <iostream> | 7 #include <iostream> |
8 | 8 |
9 #include "llvm/Type.h" | 9 #include "gen/llvm.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 | 10 |
16 #include "total.h" | 11 #include "total.h" |
17 #include "init.h" | 12 #include "init.h" |
18 #include "symbol.h" | 13 #include "symbol.h" |
19 #include "mtype.h" | 14 #include "mtype.h" |
39 { | 34 { |
40 Statement* s = (Statement*)statements->data[i]; | 35 Statement* s = (Statement*)statements->data[i]; |
41 if (s) | 36 if (s) |
42 s->toIR(p); | 37 s->toIR(p); |
43 else { | 38 else { |
44 Logger::println("NULL statement found in CompoundStatement !! :S"); | 39 Logger::println("*** ATTENTION: null statement found in CompoundStatement"); |
45 assert(0); | 40 //assert(0); |
46 } | 41 } |
47 } | 42 } |
48 | 43 |
49 } | 44 } |
50 | 45 |
54 { | 49 { |
55 static int rsi = 0; | 50 static int rsi = 0; |
56 Logger::println("ReturnStatement::toIR(%d): %s", rsi++, toChars()); | 51 Logger::println("ReturnStatement::toIR(%d): %s", rsi++, toChars()); |
57 LOG_SCOPE; | 52 LOG_SCOPE; |
58 | 53 |
54 IRFunction::FinallyVec& fin = p->func().finallys; | |
55 | |
59 if (exp) | 56 if (exp) |
60 { | 57 { |
61 TY expty = exp->type->ty; | 58 Type* exptype = LLVM_DtoDType(exp->type); |
59 TY expty = exptype->ty; | |
62 if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) { | 60 if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) { |
63 assert(expty == Tstruct || expty == Tdelegate || expty == Tarray); | 61 assert(LLVM_DtoIsPassedByRef(exptype)); |
64 | 62 |
65 TypeFunction* f = p->topfunctype(); | 63 TypeFunction* f = p->topfunctype(); |
66 assert(f->llvmRetInPtr && f->llvmRetArg); | 64 assert(f->llvmRetInPtr && f->llvmRetArg); |
67 | 65 |
68 p->lvals.push_back(f->llvmRetArg); | 66 p->lvals.push_back(f->llvmRetArg); |
69 elem* e = exp->toElem(p); | 67 elem* e = exp->toElem(p); |
70 p->lvals.pop_back(); | 68 p->lvals.pop_back(); |
71 | 69 |
72 // structliterals do this themselves | |
73 // also they dont produce any value | |
74 if (expty == Tstruct) { | 70 if (expty == Tstruct) { |
75 if (!e->inplace) { | 71 if (!e->inplace) { |
76 TypeStruct* ts = (TypeStruct*)exp->type; | 72 TypeStruct* ts = (TypeStruct*)exptype; |
77 assert(e->mem); | 73 assert(e->mem); |
78 LLVM_DtoStructCopy(ts,f->llvmRetArg,e->mem); | 74 LLVM_DtoStructCopy(ts,f->llvmRetArg,e->mem); |
79 } | 75 } |
80 } | 76 } |
81 else if (expty == Tdelegate) { | 77 else if (expty == Tdelegate) { |
82 // do nothing, handled by the DelegateExp | |
83 LLVM_DtoDelegateCopy(f->llvmRetArg,e->mem); | 78 LLVM_DtoDelegateCopy(f->llvmRetArg,e->mem); |
84 } | 79 } |
85 else if (expty == Tarray) { | 80 else if (expty == Tarray) { |
86 if (e->type == elem::SLICE) { | 81 if (e->type == elem::SLICE) { |
87 LLVM_DtoSetArray(f->llvmRetArg,e->arg,e->mem); | 82 LLVM_DtoSetArray(f->llvmRetArg,e->arg,e->mem); |
89 // else the return value is a variable and should already have been assigned by now | 84 // else the return value is a variable and should already have been assigned by now |
90 } | 85 } |
91 else | 86 else |
92 assert(0); | 87 assert(0); |
93 | 88 |
94 new llvm::ReturnInst(p->scopebb()); | 89 if (fin.empty()) |
90 new llvm::ReturnInst(p->scopebb()); | |
91 else { | |
92 new llvm::BranchInst(fin.back().bb); | |
93 fin.back().ret = true; | |
94 } | |
95 delete e; | 95 delete e; |
96 } | 96 } |
97 else { | 97 else { |
98 elem* e = exp->toElem(p); | 98 elem* e = exp->toElem(p); |
99 llvm::Value* v = e->getValue(); | 99 llvm::Value* v = e->getValue(); |
100 Logger::cout() << *v << '\n'; | |
101 new llvm::ReturnInst(v, p->scopebb()); | |
102 delete e; | 100 delete e; |
101 Logger::cout() << "return value is '" <<*v << "'\n"; | |
102 if (fin.empty()) { | |
103 new llvm::ReturnInst(v, p->scopebb()); | |
104 } | |
105 else { | |
106 llvm::Value* rettmp = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint()); | |
107 new llvm::StoreInst(v,rettmp,p->scopebb()); | |
108 new llvm::BranchInst(fin.back().bb, p->scopebb()); | |
109 fin.back().ret = true; | |
110 fin.back().retval = rettmp; | |
111 } | |
103 } | 112 } |
104 } | 113 } |
105 else | 114 else |
106 { | 115 { |
107 if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) | 116 if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) { |
108 new llvm::ReturnInst(p->scopebb()); | 117 if (fin.empty()) { |
109 else | 118 new llvm::ReturnInst(p->scopebb()); |
119 } | |
120 else { | |
121 new llvm::BranchInst(fin.back().bb); | |
122 fin.back().ret = true; | |
123 } | |
124 } | |
125 else { | |
126 assert(0); // why should this ever happen? | |
110 new llvm::UnreachableInst(p->scopebb()); | 127 new llvm::UnreachableInst(p->scopebb()); |
111 } | 128 } |
112 | 129 } |
113 p->scope().returned = true; | |
114 } | 130 } |
115 | 131 |
116 ////////////////////////////////////////////////////////////////////////////// | 132 ////////////////////////////////////////////////////////////////////////////// |
117 | 133 |
118 void ExpStatement::toIR(IRState* p) | 134 void ExpStatement::toIR(IRState* p) |
194 Logger::println("ScopeStatement::toIR(): %s", toChars()); | 210 Logger::println("ScopeStatement::toIR(): %s", toChars()); |
195 LOG_SCOPE; | 211 LOG_SCOPE; |
196 | 212 |
197 llvm::BasicBlock* oldend = p->scopeend(); | 213 llvm::BasicBlock* oldend = p->scopeend(); |
198 | 214 |
199 IRScope irs; | 215 llvm::BasicBlock* beginbb = 0; |
216 | |
200 // remove useless branches by clearing and reusing the current basicblock | 217 // remove useless branches by clearing and reusing the current basicblock |
201 llvm::BasicBlock* bb = p->scopebegin(); | 218 llvm::BasicBlock* bb = p->scopebegin(); |
202 if (bb->empty()) { | 219 if (bb->empty()) { |
203 irs.begin = bb; | 220 beginbb = bb; |
204 } | 221 } |
205 else { | 222 else { |
206 irs.begin = new llvm::BasicBlock("scope", p->topfunc(), oldend); | 223 assert(!p->scopereturned()); |
207 new llvm::BranchInst(irs.begin, p->scopebegin()); | 224 beginbb = new llvm::BasicBlock("scope", p->topfunc(), oldend); |
208 } | 225 new llvm::BranchInst(beginbb, p->scopebegin()); |
209 irs.end = new llvm::BasicBlock("endscope", p->topfunc(), oldend); | 226 } |
210 | 227 llvm::BasicBlock* endbb = new llvm::BasicBlock("endscope", p->topfunc(), oldend); |
211 gIR->scope() = irs; | 228 |
229 gIR->scope() = IRScope(beginbb, endbb); | |
212 | 230 |
213 statement->toIR(p); | 231 statement->toIR(p); |
214 | 232 |
215 p->scope() = IRScope(p->scopebb(),oldend); | 233 p->scope() = IRScope(p->scopebb(),oldend); |
216 irs.end->eraseFromParent(); | 234 endbb->eraseFromParent(); |
217 | |
218 /* | |
219 if (!gIR->scopereturned()) { | |
220 new llvm::BranchInst(irs.end, gIR->scopebegin()); | |
221 } | |
222 | |
223 // rewrite the scope | |
224 gIR->scope() = IRScope(irs.end,oldend); | |
225 */ | |
226 } | 235 } |
227 | 236 |
228 ////////////////////////////////////////////////////////////////////////////// | 237 ////////////////////////////////////////////////////////////////////////////// |
229 | 238 |
230 void WhileStatement::toIR(IRState* p) | 239 void WhileStatement::toIR(IRState* p) |
237 llvm::BasicBlock* oldend = gIR->scopeend(); | 246 llvm::BasicBlock* oldend = gIR->scopeend(); |
238 llvm::BasicBlock* whilebb = new llvm::BasicBlock("whilecond", gIR->topfunc(), oldend); | 247 llvm::BasicBlock* whilebb = new llvm::BasicBlock("whilecond", gIR->topfunc(), oldend); |
239 llvm::BasicBlock* endbb = new llvm::BasicBlock("endwhile", gIR->topfunc(), oldend); | 248 llvm::BasicBlock* endbb = new llvm::BasicBlock("endwhile", gIR->topfunc(), oldend); |
240 | 249 |
241 // move into the while block | 250 // move into the while block |
242 new llvm::BranchInst(whilebb, gIR->scopebegin()); | 251 p->ir->CreateBr(whilebb); |
252 //new llvm::BranchInst(whilebb, gIR->scopebegin()); | |
243 | 253 |
244 // replace current scope | 254 // replace current scope |
245 gIR->scope() = IRScope(whilebb,endbb); | 255 gIR->scope() = IRScope(whilebb,endbb); |
246 | 256 |
247 // create the condition | 257 // create the condition |
322 init->toIR(p); | 332 init->toIR(p); |
323 | 333 |
324 // move into the for condition block, ie. start the loop | 334 // move into the for condition block, ie. start the loop |
325 new llvm::BranchInst(forbb, gIR->scopebegin()); | 335 new llvm::BranchInst(forbb, gIR->scopebegin()); |
326 | 336 |
327 IRScope loop; | 337 p->loopbbs.push_back(IRScope(forincbb,endbb)); |
328 loop.begin = forincbb; | |
329 loop.end = endbb; | |
330 p->loopbbs.push_back(loop); | |
331 | 338 |
332 // replace current scope | 339 // replace current scope |
333 gIR->scope() = IRScope(forbb,forbodybb); | 340 gIR->scope() = IRScope(forbb,forbodybb); |
334 | 341 |
335 // create the condition | 342 // create the condition |
417 { | 424 { |
418 static int wsi = 0; | 425 static int wsi = 0; |
419 Logger::println("TryFinallyStatement::toIR(%d): %s", wsi++, toChars()); | 426 Logger::println("TryFinallyStatement::toIR(%d): %s", wsi++, toChars()); |
420 LOG_SCOPE; | 427 LOG_SCOPE; |
421 | 428 |
422 llvm::BasicBlock* oldend = gIR->scopeend(); | 429 llvm::BasicBlock* oldend = p->scopeend(); |
423 | 430 |
424 llvm::BasicBlock* trybb = new llvm::BasicBlock("try", gIR->topfunc(), oldend); | 431 llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend); |
425 llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", gIR->topfunc(), oldend); | 432 llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", p->topfunc(), oldend); |
426 llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", gIR->topfunc(), oldend); | 433 llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", p->topfunc(), oldend); |
427 | 434 |
428 // pass the previous BB into this | 435 // pass the previous BB into this |
429 new llvm::BranchInst(trybb, gIR->scopebegin()); | 436 new llvm::BranchInst(trybb, p->scopebb()); |
430 | 437 |
431 gIR->scope() = IRScope(trybb,finallybb); | 438 p->scope() = IRScope(trybb,finallybb); |
432 | 439 |
433 assert(body); | 440 assert(body); |
441 gIR->func().finallys.push_back(IRFinally(finallybb)); | |
434 body->toIR(p); | 442 body->toIR(p); |
435 new llvm::BranchInst(finallybb, gIR->scopebegin()); | 443 if (!gIR->scopereturned()) |
444 new llvm::BranchInst(finallybb, p->scopebb()); | |
436 | 445 |
437 // rewrite the scope | 446 // rewrite the scope |
438 gIR->scope() = IRScope(finallybb,endbb); | 447 p->scope() = IRScope(finallybb,endbb); |
439 | 448 |
440 assert(finalbody); | 449 assert(finalbody); |
441 finalbody->toIR(p); | 450 finalbody->toIR(p); |
442 new llvm::BranchInst(endbb, gIR->scopebegin()); | 451 if (gIR->func().finallys.back().ret) { |
452 llvm::Value* retval = p->func().finallys.back().retval; | |
453 if (retval) { | |
454 retval = new llvm::LoadInst(retval,"tmp",p->scopebb()); | |
455 new llvm::ReturnInst(retval, p->scopebb()); | |
456 } | |
457 else { | |
458 new llvm::ReturnInst(p->scopebb()); | |
459 } | |
460 } | |
461 else if (!gIR->scopereturned()) { | |
462 new llvm::BranchInst(endbb, p->scopebb()); | |
463 } | |
464 | |
465 p->func().finallys.pop_back(); | |
443 | 466 |
444 // rewrite the scope | 467 // rewrite the scope |
445 gIR->scope() = IRScope(endbb,oldend); | 468 p->scope() = IRScope(endbb,oldend); |
446 } | 469 } |
447 | 470 |
448 ////////////////////////////////////////////////////////////////////////////// | 471 ////////////////////////////////////////////////////////////////////////////// |
449 | 472 |
450 void TryCatchStatement::toIR(IRState* p) | 473 void TryCatchStatement::toIR(IRState* p) |
626 if (key) key->llvmValue = keyvar; | 649 if (key) key->llvmValue = keyvar; |
627 | 650 |
628 const llvm::Type* valtype = LLVM_DtoType(value->type); | 651 const llvm::Type* valtype = LLVM_DtoType(value->type); |
629 llvm::Value* valvar = new llvm::AllocaInst(keytype, "foreachval", p->topallocapoint()); | 652 llvm::Value* valvar = new llvm::AllocaInst(keytype, "foreachval", p->topallocapoint()); |
630 | 653 |
631 if (aggr->type->ty == Tsarray) | 654 if (LLVM_DtoDType(aggr->type)->ty == Tsarray) |
632 { | 655 { |
633 assert(llvm::isa<llvm::PointerType>(val->getType())); | 656 assert(llvm::isa<llvm::PointerType>(val->getType())); |
634 assert(llvm::isa<llvm::ArrayType>(val->getType()->getContainedType(0))); | 657 assert(llvm::isa<llvm::ArrayType>(val->getType()->getContainedType(0))); |
635 size_t n = llvm::cast<llvm::ArrayType>(val->getType()->getContainedType(0))->getNumElements(); | 658 size_t n = llvm::cast<llvm::ArrayType>(val->getType()->getContainedType(0))->getNumElements(); |
636 assert(n > 0); | 659 assert(n > 0); |
684 p->scope() = IRScope(p->scopebb(),endbb); | 707 p->scope() = IRScope(p->scopebb(),endbb); |
685 p->loopbbs.push_back(IRScope(nexbb,endbb)); | 708 p->loopbbs.push_back(IRScope(nexbb,endbb)); |
686 body->toIR(p); | 709 body->toIR(p); |
687 p->loopbbs.pop_back(); | 710 p->loopbbs.pop_back(); |
688 | 711 |
689 if (!p->scope().returned) | 712 if (!p->scopereturned()) |
690 new llvm::BranchInst(nexbb, p->scopebb()); | 713 new llvm::BranchInst(nexbb, p->scopebb()); |
691 | 714 |
692 // end | 715 // end |
693 p->scope() = IRScope(endbb,oldend); | 716 p->scope() = IRScope(endbb,oldend); |
694 } | 717 } |
732 p->scope() = IRScope(bb,oldend); | 755 p->scope() = IRScope(bb,oldend); |
733 } | 756 } |
734 | 757 |
735 ////////////////////////////////////////////////////////////////////////////// | 758 ////////////////////////////////////////////////////////////////////////////// |
736 | 759 |
760 void WithStatement::toIR(IRState* p) | |
761 { | |
762 Logger::println("WithStatement::toIR(): %s", toChars()); | |
763 LOG_SCOPE; | |
764 | |
765 assert(exp); | |
766 assert(body); | |
767 | |
768 elem* e = exp->toElem(p); | |
769 wthis->llvmValue = e->getValue(); | |
770 delete e; | |
771 | |
772 body->toIR(p); | |
773 } | |
774 | |
775 ////////////////////////////////////////////////////////////////////////////// | |
776 | |
737 ////////////////////////////////////////////////////////////////////////////// | 777 ////////////////////////////////////////////////////////////////////////////// |
738 | 778 |
739 #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();} | 779 #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();} |
740 //STUBST(BreakStatement); | 780 //STUBST(BreakStatement); |
741 //STUBST(ForStatement); | 781 //STUBST(ForStatement); |
742 STUBST(WithStatement); | 782 //STUBST(WithStatement); |
743 STUBST(SynchronizedStatement); | 783 STUBST(SynchronizedStatement); |
744 //STUBST(ReturnStatement); | 784 //STUBST(ReturnStatement); |
745 //STUBST(ContinueStatement); | 785 //STUBST(ContinueStatement); |
746 STUBST(DefaultStatement); | 786 STUBST(DefaultStatement); |
747 STUBST(CaseStatement); | 787 STUBST(CaseStatement); |