comparison gen/statements.cpp @ 262:88252a1af660 trunk

[svn r280] Fixed a bunch of issues with switch statements. Ended up a bit far reaching...
author lindquist
date Sat, 14 Jun 2008 05:13:49 +0200
parents a95056b3c996
children 2be09ee06bc7
comparison
equal deleted inserted replaced
261:5723b7385c25 262:88252a1af660
221 void ScopeStatement::toIR(IRState* p) 221 void ScopeStatement::toIR(IRState* p)
222 { 222 {
223 Logger::println("ScopeStatement::toIR(): %s", loc.toChars()); 223 Logger::println("ScopeStatement::toIR(): %s", loc.toChars());
224 LOG_SCOPE; 224 LOG_SCOPE;
225 225
226 llvm::BasicBlock* oldend = p->scopeend(); 226 /*llvm::BasicBlock* oldend = p->scopeend();
227 227
228 llvm::BasicBlock* beginbb = 0; 228 llvm::BasicBlock* beginbb = 0;
229 229
230 // remove useless branches by clearing and reusing the current basicblock 230 // remove useless branches by clearing and reusing the current basicblock
231 llvm::BasicBlock* bb = p->scopebb(); 231 llvm::BasicBlock* bb = p->scopebb();
232 if (bb->empty()) { 232 if (bb->empty()) {
233 beginbb = bb; 233 beginbb = bb;
234 } 234 }
235 else { 235 else {
236 assert(!p->scopereturned());
237 beginbb = llvm::BasicBlock::Create("scope", p->topfunc(), oldend); 236 beginbb = llvm::BasicBlock::Create("scope", p->topfunc(), oldend);
238 llvm::BranchInst::Create(beginbb, p->scopebb()); 237 if (!p->scopereturned())
239 } 238 llvm::BranchInst::Create(beginbb, bb);
239 }
240
240 llvm::BasicBlock* endbb = llvm::BasicBlock::Create("endscope", p->topfunc(), oldend); 241 llvm::BasicBlock* endbb = llvm::BasicBlock::Create("endscope", p->topfunc(), oldend);
241 242 if (beginbb != bb)
242 gIR->scope() = IRScope(beginbb, endbb); 243 p->scope() = IRScope(beginbb, endbb);
244 else
245 p->scope().end = endbb;*/
243 246
244 if (statement) 247 if (statement)
245 statement->toIR(p); 248 statement->toIR(p);
246 249
247 p->scope() = IRScope(p->scopebb(),oldend); 250 /*p->scope().end = oldend;
248 endbb->eraseFromParent(); 251 Logger::println("Erasing scope endbb");
252 endbb->eraseFromParent();*/
249 } 253 }
250 254
251 ////////////////////////////////////////////////////////////////////////////// 255 //////////////////////////////////////////////////////////////////////////////
252 256
253 void WhileStatement::toIR(IRState* p) 257 void WhileStatement::toIR(IRState* p)
396 void BreakStatement::toIR(IRState* p) 400 void BreakStatement::toIR(IRState* p)
397 { 401 {
398 Logger::println("BreakStatement::toIR(): %s", loc.toChars()); 402 Logger::println("BreakStatement::toIR(): %s", loc.toChars());
399 LOG_SCOPE; 403 LOG_SCOPE;
400 404
405 // don't emit two terminators in a row
406 // happens just before DMD generated default statements if the last case terminates
407 if (p->scopereturned())
408 return;
409
401 if (ident != 0) { 410 if (ident != 0) {
402 Logger::println("ident = %s", ident->toChars()); 411 Logger::println("ident = %s", ident->toChars());
403 412
404 emit_finallyblocks(p, enclosingtryfinally, target->enclosingtryfinally); 413 emit_finallyblocks(p, enclosingtryfinally, target->enclosingtryfinally);
405 414
409 while(tmp = targetLoopStatement->isScopeStatement()) 418 while(tmp = targetLoopStatement->isScopeStatement())
410 targetLoopStatement = tmp->statement; 419 targetLoopStatement = tmp->statement;
411 420
412 // find the right break block and jump there 421 // find the right break block and jump there
413 IRState::LoopScopeVec::reverse_iterator it; 422 IRState::LoopScopeVec::reverse_iterator it;
414 for(it = gIR->loopbbs.rbegin(); it != gIR->loopbbs.rend(); ++it) { 423 for(it = p->loopbbs.rbegin(); it != p->loopbbs.rend(); ++it) {
415 if(it->s == targetLoopStatement) { 424 if(it->s == targetLoopStatement) {
416 llvm::BranchInst::Create(it->end, gIR->scopebb()); 425 llvm::BranchInst::Create(it->end, p->scopebb());
417 return; 426 return;
418 } 427 }
419 } 428 }
420 assert(0); 429 assert(0);
421 } 430 }
422 else { 431 else {
423 emit_finallyblocks(p, enclosingtryfinally, gIR->loopbbs.back().enclosingtryfinally); 432 emit_finallyblocks(p, enclosingtryfinally, p->loopbbs.back().enclosingtryfinally);
424 llvm::BranchInst::Create(gIR->loopbbs.back().end, gIR->scopebb()); 433 llvm::BranchInst::Create(p->loopbbs.back().end, p->scopebb());
425 } 434 }
426 } 435 }
427 436
428 ////////////////////////////////////////////////////////////////////////////// 437 //////////////////////////////////////////////////////////////////////////////
429 438
640 Logger::println("SwitchStatement::toIR(): %s", loc.toChars()); 649 Logger::println("SwitchStatement::toIR(): %s", loc.toChars());
641 LOG_SCOPE; 650 LOG_SCOPE;
642 651
643 llvm::BasicBlock* oldend = gIR->scopeend(); 652 llvm::BasicBlock* oldend = gIR->scopeend();
644 653
645 // collect the needed cases
646 typedef std::pair<llvm::BasicBlock*, std::vector<llvm::ConstantInt*> > CasePair;
647 std::vector<CasePair> vcases;
648 std::vector<Statement*> vbodies;
649 Array caseArray;
650 for (int i=0; i<cases->dim; ++i)
651 {
652 CaseStatement* cs = (CaseStatement*)cases->data[i];
653
654 std::string lblname("case");
655 llvm::BasicBlock* bb = llvm::BasicBlock::Create(lblname, p->topfunc(), oldend);
656 cs->bodyBB = bb;
657
658 std::vector<llvm::ConstantInt*> tmp;
659 CaseStatement* last;
660 bool first = true;
661 do {
662 // integral case
663 if (cs->exp->type->isintegral()) {
664 LLConstant* c = cs->exp->toConstElem(p);
665 tmp.push_back(isaConstantInt(c));
666 }
667 // string case
668 else {
669 assert(cs->exp->op == TOKstring);
670 // for string switches this is unfortunately necessary or there will be duplicates in the list
671 if (first) {
672 caseArray.push(new Case((StringExp*)cs->exp, i));
673 first = false;
674 }
675 }
676 last = cs;
677 }
678 while (cs = cs->statement->isCaseStatement());
679
680 vcases.push_back(CasePair(bb, tmp));
681 vbodies.push_back(last->statement);
682 }
683
684 // string switch? 654 // string switch?
685 llvm::GlobalVariable* switchTable = 0; 655 llvm::GlobalVariable* switchTable = 0;
656 Array caseArray;
686 if (!condition->type->isintegral()) 657 if (!condition->type->isintegral())
687 { 658 {
659 Logger::println("is string switch");
660 // build array of the stringexpS
661 for (int i=0; i<cases->dim; ++i)
662 {
663 CaseStatement* cs = (CaseStatement*)cases->data[i];
664
665 assert(cs->exp->op == TOKstring);
666 caseArray.push(new Case((StringExp*)cs->exp, i));
667 }
688 // first sort it 668 // first sort it
689 caseArray.sort(); 669 caseArray.sort();
690 // iterate and add indices to cases 670 // iterate and add indices to cases
691 std::vector<LLConstant*> inits; 671 std::vector<LLConstant*> inits;
692 for (size_t i=0; i<caseArray.dim; ++i) 672 for (size_t i=0; i<caseArray.dim; ++i)
693 { 673 {
674 CaseStatement* cs = (CaseStatement*)cases->data[i];
675 cs->llvmIdx = DtoConstUint(i);
694 Case* c = (Case*)caseArray.data[i]; 676 Case* c = (Case*)caseArray.data[i];
695 vcases[c->index].second.push_back(DtoConstUint(i));
696 inits.push_back(c->str->toConstElem(p)); 677 inits.push_back(c->str->toConstElem(p));
697 } 678 }
698 // build static array for ptr or final array 679 // build static array for ptr or final array
699 const LLType* elemTy = DtoType(condition->type); 680 const LLType* elemTy = DtoType(condition->type);
700 const llvm::ArrayType* arrTy = llvm::ArrayType::get(elemTy, inits.size()); 681 const llvm::ArrayType* arrTy = llvm::ArrayType::get(elemTy, inits.size());
715 LLConstant* sInit = llvm::ConstantStruct::get(sTy, sinits); 696 LLConstant* sInit = llvm::ConstantStruct::get(sTy, sinits);
716 697
717 switchTable = new llvm::GlobalVariable(sTy, true, llvm::GlobalValue::InternalLinkage, sInit, "string_switch_table", gIR->module); 698 switchTable = new llvm::GlobalVariable(sTy, true, llvm::GlobalValue::InternalLinkage, sInit, "string_switch_table", gIR->module);
718 } 699 }
719 700
701 // body block
702 llvm::BasicBlock* bodybb = llvm::BasicBlock::Create("switchbody", p->topfunc(), oldend);
703
720 // default 704 // default
721 llvm::BasicBlock* defbb = 0; 705 llvm::BasicBlock* defbb = 0;
722 if (!hasNoDefault) { 706 if (sdefault) {
707 Logger::println("has default");
723 defbb = llvm::BasicBlock::Create("default", p->topfunc(), oldend); 708 defbb = llvm::BasicBlock::Create("default", p->topfunc(), oldend);
724 sdefault->bodyBB = defbb; 709 sdefault->bodyBB = defbb;
725 } 710 }
726 711
727 // end (break point) 712 // end (break point)
738 else { 723 else {
739 condVal = call_string_switch_runtime(switchTable, condition); 724 condVal = call_string_switch_runtime(switchTable, condition);
740 } 725 }
741 llvm::SwitchInst* si = llvm::SwitchInst::Create(condVal, defbb ? defbb : endbb, cases->dim, p->scopebb()); 726 llvm::SwitchInst* si = llvm::SwitchInst::Create(condVal, defbb ? defbb : endbb, cases->dim, p->scopebb());
742 727
728 // do switch body
729 assert(body);
730
731 p->scope() = IRScope(bodybb, endbb);
732 p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,p->scopebb(),endbb));
733 body->toIR(p);
734 p->loopbbs.pop_back();
735
736 if (!p->scopereturned())
737 llvm::BranchInst::Create(endbb, p->scopebb());
738
743 // add the cases 739 // add the cases
744 size_t n = vcases.size(); 740 for (int i=0; i<cases->dim; ++i)
745 for (size_t i=0; i<n; ++i) 741 {
746 { 742 CaseStatement* cs = (CaseStatement*)cases->data[i];
747 size_t nc = vcases[i].second.size(); 743 si->addCase(cs->llvmIdx, cs->bodyBB);
748 for (size_t j=0; j<nc; ++j)
749 {
750 si->addCase(vcases[i].second[j], vcases[i].first);
751 }
752 }
753
754 // insert case statements
755 for (size_t i=0; i<n; ++i)
756 {
757 llvm::BasicBlock* nextbb = (i == n-1) ? (defbb ? defbb : endbb) : vcases[i+1].first;
758 p->scope() = IRScope(vcases[i].first,nextbb);
759 p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,p->scopebb(),endbb));
760 vbodies[i]->toIR(p);
761 p->loopbbs.pop_back();
762
763 llvm::BasicBlock* curbb = p->scopebb();
764 if (curbb->empty() || !curbb->back().isTerminator())
765 {
766 llvm::BranchInst::Create(nextbb, curbb);
767 }
768 }
769
770 // default statement
771 if (defbb)
772 {
773 p->scope() = IRScope(defbb,endbb);
774 p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,p->scopebb(),endbb));
775 Logger::println("doing default statement");
776 sdefault->statement->toIR(p);
777 p->loopbbs.pop_back();
778
779 llvm::BasicBlock* curbb = p->scopebb();
780 if (curbb->empty() || !curbb->back().isTerminator())
781 {
782 llvm::BranchInst::Create(endbb, curbb);
783 }
784 } 744 }
785 745
786 gIR->scope() = IRScope(endbb,oldend); 746 gIR->scope() = IRScope(endbb,oldend);
787 } 747 }
788 748
790 void CaseStatement::toIR(IRState* p) 750 void CaseStatement::toIR(IRState* p)
791 { 751 {
792 Logger::println("CaseStatement::toIR(): %s", loc.toChars()); 752 Logger::println("CaseStatement::toIR(): %s", loc.toChars());
793 LOG_SCOPE; 753 LOG_SCOPE;
794 754
795 assert(0); 755 if (!bodyBB)
756 {
757 bodyBB = llvm::BasicBlock::Create("case", p->topfunc(), p->scopeend());
758 }
759 else
760 {
761 bodyBB->moveAfter(p->scopebb());
762 }
763
764 if (exp->type->isintegral()) {
765 assert(!llvmIdx);
766 LLConstant* c = exp->toConstElem(p);
767 llvmIdx = isaConstantInt(c);
768 }
769 else {
770 assert(llvmIdx);
771 }
772
773 if (!p->scopereturned())
774 llvm::BranchInst::Create(bodyBB, p->scopebb());
775
776 p->scope() = IRScope(bodyBB, p->scopeend());
777
778 assert(statement);
779 statement->toIR(p);
780 }
781
782 //////////////////////////////////////////////////////////////////////////////
783 void DefaultStatement::toIR(IRState* p)
784 {
785 Logger::println("DefaultStatement::toIR(): %s", loc.toChars());
786 LOG_SCOPE;
787
788 assert(bodyBB);
789
790 bodyBB->moveAfter(p->scopebb());
791
792 if (!p->scopereturned())
793 llvm::BranchInst::Create(bodyBB, p->scopebb());
794
795 p->scope() = IRScope(bodyBB, p->scopeend());
796
797 assert(statement);
798 statement->toIR(p);
796 } 799 }
797 800
798 ////////////////////////////////////////////////////////////////////////////// 801 //////////////////////////////////////////////////////////////////////////////
799 802
800 void UnrolledLoopStatement::toIR(IRState* p) 803 void UnrolledLoopStatement::toIR(IRState* p)
1081 1084
1082 llvm::BasicBlock* oldend = gIR->scopeend(); 1085 llvm::BasicBlock* oldend = gIR->scopeend();
1083 llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergotocase", p->topfunc(), oldend); 1086 llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergotocase", p->topfunc(), oldend);
1084 1087
1085 assert(!p->scopereturned()); 1088 assert(!p->scopereturned());
1086 assert(cs->bodyBB); 1089 if (!cs->bodyBB)
1090 {
1091 cs->bodyBB = llvm::BasicBlock::Create("case", p->topfunc(), p->scopeend());
1092 }
1087 1093
1088 emit_finallyblocks(p, enclosingtryfinally, sw->enclosingtryfinally); 1094 emit_finallyblocks(p, enclosingtryfinally, sw->enclosingtryfinally);
1089 1095
1090 llvm::BranchInst::Create(cs->bodyBB, p->scopebb()); 1096 llvm::BranchInst::Create(cs->bodyBB, p->scopebb());
1091 p->scope() = IRScope(bb,oldend); 1097 p->scope() = IRScope(bb,oldend);
1203 //STUBST(ForStatement); 1209 //STUBST(ForStatement);
1204 //STUBST(WithStatement); 1210 //STUBST(WithStatement);
1205 //STUBST(SynchronizedStatement); 1211 //STUBST(SynchronizedStatement);
1206 //STUBST(ReturnStatement); 1212 //STUBST(ReturnStatement);
1207 //STUBST(ContinueStatement); 1213 //STUBST(ContinueStatement);
1208 STUBST(DefaultStatement); 1214 //STUBST(DefaultStatement);
1209 //STUBST(CaseStatement); 1215 //STUBST(CaseStatement);
1210 //STUBST(SwitchStatement); 1216 //STUBST(SwitchStatement);
1211 STUBST(SwitchErrorStatement); 1217 STUBST(SwitchErrorStatement);
1212 STUBST(Statement); 1218 STUBST(Statement);
1213 //STUBST(IfStatement); 1219 //STUBST(IfStatement);