Mercurial > projects > ldc
comparison gen/statements.cpp @ 94:61615fa85940 trunk
[svn r98] Added support for std.c.stdlib.alloca via pragma(LLVM_internal, "alloca").
Added support for array .sort and .reverse properties.
Fixed some bugs with pointer arithmetic.
Disabled some DMD AST optimizations that was messing things up, destroying valuable information.
Added a KDevelop project file, this is what I use for coding LLVMDC now :)
Other minor stuff.
author | lindquist |
---|---|
date | Mon, 12 Nov 2007 06:32:46 +0100 |
parents | fd32135dca3e |
children | ce7ed8f59b99 |
comparison
equal
deleted
inserted
replaced
93:08508eebbb3e | 94:61615fa85940 |
---|---|
5 #include <sstream> | 5 #include <sstream> |
6 #include <fstream> | 6 #include <fstream> |
7 #include <iostream> | 7 #include <iostream> |
8 | 8 |
9 #include "gen/llvm.h" | 9 #include "gen/llvm.h" |
10 #include "llvm/Transforms/Utils/Cloning.h" | |
11 | 10 |
12 #include "total.h" | 11 #include "total.h" |
13 #include "init.h" | 12 #include "init.h" |
14 #include "symbol.h" | 13 #include "symbol.h" |
15 #include "mtype.h" | 14 #include "mtype.h" |
37 { | 36 { |
38 Statement* s = (Statement*)statements->data[i]; | 37 Statement* s = (Statement*)statements->data[i]; |
39 if (s) | 38 if (s) |
40 s->toIR(p); | 39 s->toIR(p); |
41 else { | 40 else { |
42 Logger::println("*** ATTENTION: null statement found in CompoundStatement"); | 41 Logger::println("??? null statement found in CompoundStatement"); |
43 //assert(0); | |
44 } | 42 } |
45 } | 43 } |
46 } | 44 } |
47 | 45 |
48 ////////////////////////////////////////////////////////////////////////////// | 46 ////////////////////////////////////////////////////////////////////////////// |
131 { | 129 { |
132 static int esi = 0; | 130 static int esi = 0; |
133 Logger::println("ExpStatement::toIR(%d): %s", esi++, toChars()); | 131 Logger::println("ExpStatement::toIR(%d): %s", esi++, toChars()); |
134 LOG_SCOPE; | 132 LOG_SCOPE; |
135 | 133 |
136 if (global.params.symdebug) | 134 // if (global.params.symdebug) |
137 DtoDwarfStopPoint(loc.linnum); | 135 // DtoDwarfStopPoint(loc.linnum); |
138 | 136 |
139 if (exp != 0) { | 137 if (exp != 0) { |
140 elem* e = exp->toElem(p); | 138 elem* e = exp->toElem(p); |
141 delete e; | 139 delete e; |
142 } | 140 } |
253 llvm::Value* ifbreak = new llvm::BranchInst(whilebodybb, endbb, cond_val, p->scopebb()); | 251 llvm::Value* ifbreak = new llvm::BranchInst(whilebodybb, endbb, cond_val, p->scopebb()); |
254 | 252 |
255 // rewrite scope | 253 // rewrite scope |
256 gIR->scope() = IRScope(whilebodybb,endbb); | 254 gIR->scope() = IRScope(whilebodybb,endbb); |
257 | 255 |
258 // do while body code | 256 // while body code |
257 p->loopbbs.push_back(IRScope(whilebb,endbb)); | |
259 body->toIR(p); | 258 body->toIR(p); |
259 p->loopbbs.pop_back(); | |
260 | 260 |
261 // loop | 261 // loop |
262 new llvm::BranchInst(whilebb, gIR->scopebegin()); | 262 new llvm::BranchInst(whilebb, gIR->scopebegin()); |
263 | 263 |
264 // rewrite the scope | 264 // rewrite the scope |
282 new llvm::BranchInst(dowhilebb, gIR->scopebegin()); | 282 new llvm::BranchInst(dowhilebb, gIR->scopebegin()); |
283 | 283 |
284 // replace current scope | 284 // replace current scope |
285 gIR->scope() = IRScope(dowhilebb,endbb); | 285 gIR->scope() = IRScope(dowhilebb,endbb); |
286 | 286 |
287 // do do-while body code | 287 // do-while body code |
288 body->toIR(p); | 288 body->toIR(p); |
289 | 289 |
290 // create the condition | 290 // create the condition |
291 DValue* cond_e = condition->toElem(p); | 291 DValue* cond_e = condition->toElem(p); |
292 llvm::Value* cond_val = DtoBoolean(cond_e->getRVal()); | 292 llvm::Value* cond_val = DtoBoolean(cond_e->getRVal()); |
361 | 361 |
362 ////////////////////////////////////////////////////////////////////////////// | 362 ////////////////////////////////////////////////////////////////////////////// |
363 | 363 |
364 void BreakStatement::toIR(IRState* p) | 364 void BreakStatement::toIR(IRState* p) |
365 { | 365 { |
366 static int wsi = 0; | 366 Logger::println("BreakStatement::toIR(): %s", toChars()); |
367 Logger::println("BreakStatement::toIR(%d): %s", wsi++, toChars()); | |
368 LOG_SCOPE; | 367 LOG_SCOPE; |
369 | 368 |
370 if (ident != 0) { | 369 if (ident != 0) { |
371 Logger::println("ident = %s", ident->toChars()); | 370 Logger::println("ident = %s", ident->toChars()); |
372 assert(0); | 371 assert(0); |
378 | 377 |
379 ////////////////////////////////////////////////////////////////////////////// | 378 ////////////////////////////////////////////////////////////////////////////// |
380 | 379 |
381 void ContinueStatement::toIR(IRState* p) | 380 void ContinueStatement::toIR(IRState* p) |
382 { | 381 { |
383 static int wsi = 0; | 382 Logger::println("ContinueStatement::toIR(): %s", toChars()); |
384 Logger::println("ContinueStatement::toIR(%d): %s", wsi++, toChars()); | |
385 LOG_SCOPE; | 383 LOG_SCOPE; |
386 | 384 |
387 if (ident != 0) { | 385 if (ident != 0) { |
388 Logger::println("ident = %s", ident->toChars()); | 386 Logger::println("ident = %s", ident->toChars()); |
389 assert(0); | 387 assert(0); |
395 | 393 |
396 ////////////////////////////////////////////////////////////////////////////// | 394 ////////////////////////////////////////////////////////////////////////////// |
397 | 395 |
398 void OnScopeStatement::toIR(IRState* p) | 396 void OnScopeStatement::toIR(IRState* p) |
399 { | 397 { |
400 static int wsi = 0; | 398 Logger::println("OnScopeStatement::toIR(): %s", toChars()); |
401 Logger::println("OnScopeStatement::toIR(%d): %s", wsi++, toChars()); | |
402 LOG_SCOPE; | 399 LOG_SCOPE; |
403 | 400 |
404 assert(statement); | 401 assert(statement); |
405 //statement->toIR(p); // this seems to be redundant | 402 //statement->toIR(p); // this seems to be redundant |
406 } | 403 } |
407 | 404 |
408 ////////////////////////////////////////////////////////////////////////////// | 405 ////////////////////////////////////////////////////////////////////////////// |
409 | |
410 static void replaceFinallyBBs(std::vector<llvm::BasicBlock*>& a, std::vector<llvm::BasicBlock*>& b) | |
411 { | |
412 } | |
413 | 406 |
414 void TryFinallyStatement::toIR(IRState* p) | 407 void TryFinallyStatement::toIR(IRState* p) |
415 { | 408 { |
416 Logger::println("TryFinallyStatement::toIR(): %s", toChars()); | 409 Logger::println("TryFinallyStatement::toIR(): %s", toChars()); |
417 LOG_SCOPE; | 410 LOG_SCOPE; |
493 { | 486 { |
494 static int wsi = 0; | 487 static int wsi = 0; |
495 Logger::println("TryCatchStatement::toIR(%d): %s", wsi++, toChars()); | 488 Logger::println("TryCatchStatement::toIR(%d): %s", wsi++, toChars()); |
496 LOG_SCOPE; | 489 LOG_SCOPE; |
497 | 490 |
498 Logger::println("*** ATTENTION: try-catch is not yet fully implemented, only the try block will be emitted."); | 491 Logger::attention("try-catch is not yet fully implemented, only the try block will be emitted."); |
499 | 492 |
500 assert(body); | 493 assert(body); |
501 body->toIR(p); | 494 body->toIR(p); |
502 | 495 |
503 /*assert(catches); | 496 /*assert(catches); |
514 { | 507 { |
515 static int wsi = 0; | 508 static int wsi = 0; |
516 Logger::println("ThrowStatement::toIR(%d): %s", wsi++, toChars()); | 509 Logger::println("ThrowStatement::toIR(%d): %s", wsi++, toChars()); |
517 LOG_SCOPE; | 510 LOG_SCOPE; |
518 | 511 |
519 Logger::println("*** ATTENTION: throw is not yet implemented, replacing expression with assert(0);"); | 512 Logger::attention("throw is not yet implemented, replacing expression with assert(0);"); |
520 | 513 |
521 llvm::Value* line = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false); | 514 DtoAssert(NULL, &loc, NULL); |
522 DtoAssert(NULL, line, NULL); | |
523 | 515 |
524 /* | 516 /* |
525 assert(exp); | 517 assert(exp); |
526 DValue* e = exp->toElem(p); | 518 DValue* e = exp->toElem(p); |
527 delete e; | 519 delete e; |
655 | 647 |
656 //Argument* arg = (Argument*)arguments->data[0]; | 648 //Argument* arg = (Argument*)arguments->data[0]; |
657 //Logger::println("Argument is %s", arg->toChars()); | 649 //Logger::println("Argument is %s", arg->toChars()); |
658 | 650 |
659 Logger::println("aggr = %s", aggr->toChars()); | 651 Logger::println("aggr = %s", aggr->toChars()); |
660 Logger::println("func = %s", func->toChars()); | 652 |
661 | 653 // key |
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(); | 654 const llvm::Type* keytype = key ? DtoType(key->type) : DtoSize_t(); |
672 llvm::Value* keyvar = new llvm::AllocaInst(keytype, "foreachkey", p->topallocapoint()); | 655 llvm::Value* keyvar = new llvm::AllocaInst(keytype, "foreachkey", p->topallocapoint()); |
673 if (key) key->llvmValue = keyvar; | 656 if (key) key->llvmValue = keyvar; |
674 | 657 llvm::Value* zerokey = llvm::ConstantInt::get(keytype,0,false); |
658 | |
659 // value | |
675 const llvm::Type* valtype = DtoType(value->type); | 660 const llvm::Type* valtype = DtoType(value->type); |
676 llvm::Value* valvar = !(value->isRef() || value->isOut()) ? new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint()) : NULL; | 661 llvm::Value* valvar = NULL; |
677 | 662 if (!value->isRef() && !value->isOut()) |
663 valvar = new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint()); | |
664 | |
665 // what to iterate | |
666 DValue* aggrval = aggr->toElem(p); | |
678 Type* aggrtype = DtoDType(aggr->type); | 667 Type* aggrtype = DtoDType(aggr->type); |
668 | |
669 // get length and pointer | |
670 llvm::Value* val = 0; | |
671 llvm::Value* niters = 0; | |
672 | |
673 // static array | |
679 if (aggrtype->ty == Tsarray) | 674 if (aggrtype->ty == Tsarray) |
680 { | 675 { |
676 Logger::println("foreach over static array"); | |
677 val = aggrval->getRVal(); | |
681 assert(llvm::isa<llvm::PointerType>(val->getType())); | 678 assert(llvm::isa<llvm::PointerType>(val->getType())); |
682 assert(llvm::isa<llvm::ArrayType>(val->getType()->getContainedType(0))); | 679 assert(llvm::isa<llvm::ArrayType>(val->getType()->getContainedType(0))); |
683 size_t n = llvm::cast<llvm::ArrayType>(val->getType()->getContainedType(0))->getNumElements(); | 680 size_t nelems = llvm::cast<llvm::ArrayType>(val->getType()->getContainedType(0))->getNumElements(); |
684 assert(n > 0); | 681 assert(nelems > 0); |
685 numiters = llvm::ConstantInt::get(keytype,n,false); | 682 niters = llvm::ConstantInt::get(keytype,nelems,false); |
686 } | 683 } |
684 // dynamic array | |
687 else if (aggrtype->ty == Tarray) | 685 else if (aggrtype->ty == Tarray) |
688 { | 686 { |
689 if (DSliceValue* slice = arr->isSlice()) { | 687 if (DSliceValue* slice = aggrval->isSlice()) { |
690 numiters = slice->len; | 688 Logger::println("foreach over slice"); |
689 niters = slice->len; | |
690 assert(niters); | |
691 if (llvm::isa<llvm::ConstantInt>(niters)) { | |
692 llvm::ConstantInt* ci = llvm::cast<llvm::ConstantInt>(niters); | |
693 Logger::println("const num iters: %u", ci); | |
694 } | |
695 else { | |
696 Logger::cout() << "numiters: " << *niters <<'\n'; | |
697 } | |
691 val = slice->ptr; | 698 val = slice->ptr; |
699 assert(val); | |
692 } | 700 } |
693 else { | 701 else { |
694 numiters = p->ir->CreateLoad(DtoGEPi(val,0,0,"tmp",p->scopebb())); | 702 Logger::println("foreach over dynamic array"); |
695 val = p->ir->CreateLoad(DtoGEPi(val,0,1,"tmp",p->scopebb())); | 703 val = aggrval->getRVal(); |
704 niters = DtoGEPi(val,0,0,"tmp",p->scopebb()); | |
705 niters = p->ir->CreateLoad(niters, "numiterations"); | |
706 val = DtoGEPi(val,0,1,"tmp",p->scopebb()); | |
707 val = p->ir->CreateLoad(val, "collection"); | |
696 } | 708 } |
697 } | 709 } |
698 else | 710 else |
699 { | 711 { |
700 assert(0 && "aggregate type is not Tarray or Tsarray"); | 712 assert(0 && "aggregate type is not Tarray or Tsarray"); |
701 } | 713 } |
702 | 714 |
715 llvm::Constant* delta = 0; | |
703 if (op == TOKforeach) { | 716 if (op == TOKforeach) { |
704 new llvm::StoreInst(llvm::ConstantInt::get(keytype,0,false), keyvar, p->scopebb()); | 717 new llvm::StoreInst(zerokey, keyvar, p->scopebb()); |
705 } | 718 } |
706 else if (op == TOKforeach_reverse) { | 719 else { |
707 llvm::Value* v = llvm::BinaryOperator::createSub(numiters, llvm::ConstantInt::get(keytype,1,false),"tmp",p->scopebb()); | 720 new llvm::StoreInst(niters, keyvar, p->scopebb()); |
708 new llvm::StoreInst(v, keyvar, p->scopebb()); | 721 } |
709 } | |
710 | |
711 delete arr; | |
712 | 722 |
713 llvm::BasicBlock* oldend = gIR->scopeend(); | 723 llvm::BasicBlock* oldend = gIR->scopeend(); |
714 llvm::BasicBlock* nexbb = new llvm::BasicBlock("foreachnext", p->topfunc(), oldend); | 724 llvm::BasicBlock* condbb = new llvm::BasicBlock("foreachcond", p->topfunc(), oldend); |
715 llvm::BasicBlock* begbb = new llvm::BasicBlock("foreachbegin", p->topfunc(), oldend); | 725 llvm::BasicBlock* bodybb = new llvm::BasicBlock("foreachbody", p->topfunc(), oldend); |
726 llvm::BasicBlock* nextbb = new llvm::BasicBlock("foreachnext", p->topfunc(), oldend); | |
716 llvm::BasicBlock* endbb = new llvm::BasicBlock("foreachend", p->topfunc(), oldend); | 727 llvm::BasicBlock* endbb = new llvm::BasicBlock("foreachend", p->topfunc(), oldend); |
717 | 728 |
718 new llvm::BranchInst(begbb, p->scopebb()); | 729 new llvm::BranchInst(condbb, p->scopebb()); |
719 | 730 |
720 // next | 731 // condition |
721 p->scope() = IRScope(nexbb,begbb); | 732 p->scope() = IRScope(condbb,bodybb); |
733 | |
722 llvm::Value* done = 0; | 734 llvm::Value* done = 0; |
723 llvm::Value* load = new llvm::LoadInst(keyvar, "tmp", p->scopebb()); | 735 llvm::Value* load = new llvm::LoadInst(keyvar, "tmp", p->scopebb()); |
724 if (op == TOKforeach) { | 736 if (op == TOKforeach) { |
725 load = llvm::BinaryOperator::createAdd(load,llvm::ConstantInt::get(keytype, 1, false),"tmp",p->scopebb()); | 737 done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_ULT, load, niters, "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 } | 738 } |
729 else if (op == TOKforeach_reverse) { | 739 else if (op == TOKforeach_reverse) { |
730 done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_UGT, load, llvm::ConstantInt::get(keytype, 0, false), "tmp", p->scopebb()); | 740 done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_UGT, load, zerokey, "tmp", p->scopebb()); |
731 load = llvm::BinaryOperator::createSub(load,llvm::ConstantInt::get(keytype, 1, false),"tmp",p->scopebb()); | 741 load = llvm::BinaryOperator::createSub(load,llvm::ConstantInt::get(keytype, 1, false),"tmp",p->scopebb()); |
732 new llvm::StoreInst(load, keyvar, p->scopebb()); | 742 new llvm::StoreInst(load, keyvar, p->scopebb()); |
733 } | 743 } |
734 new llvm::BranchInst(begbb, endbb, done, p->scopebb()); | 744 new llvm::BranchInst(bodybb, endbb, done, p->scopebb()); |
735 | 745 |
736 // begin | 746 // body |
737 p->scope() = IRScope(begbb,nexbb); | 747 p->scope() = IRScope(bodybb,nextbb); |
738 | 748 |
739 // get value for this iteration | 749 // get value for this iteration |
740 llvm::Constant* zero = llvm::ConstantInt::get(keytype,0,false); | 750 llvm::Constant* zero = llvm::ConstantInt::get(keytype,0,false); |
741 llvm::Value* loadedKey = p->ir->CreateLoad(keyvar,"tmp"); | 751 llvm::Value* loadedKey = p->ir->CreateLoad(keyvar,"tmp"); |
742 if (aggrtype->ty == Tsarray) | 752 if (aggrtype->ty == Tsarray) |
752 delete src; | 762 delete src; |
753 value->llvmValue = valvar; | 763 value->llvmValue = valvar; |
754 } | 764 } |
755 | 765 |
756 // body | 766 // body |
757 p->scope() = IRScope(p->scopebb(),endbb); | 767 p->loopbbs.push_back(IRScope(nextbb,endbb)); |
758 p->loopbbs.push_back(IRScope(nexbb,endbb)); | |
759 body->toIR(p); | 768 body->toIR(p); |
760 p->loopbbs.pop_back(); | 769 p->loopbbs.pop_back(); |
761 | 770 |
762 if (!p->scopereturned()) | 771 if (!p->scopereturned()) |
763 new llvm::BranchInst(nexbb, p->scopebb()); | 772 new llvm::BranchInst(nextbb, p->scopebb()); |
773 | |
774 // next | |
775 p->scope() = IRScope(nextbb,endbb); | |
776 if (op == TOKforeach) { | |
777 llvm::Value* load = DtoLoad(keyvar); | |
778 load = p->ir->CreateAdd(load, llvm::ConstantInt::get(keytype, 1, false), "tmp"); | |
779 DtoStore(load, keyvar); | |
780 } | |
781 new llvm::BranchInst(condbb, p->scopebb()); | |
764 | 782 |
765 // end | 783 // end |
766 p->scope() = IRScope(endbb,oldend); | 784 p->scope() = IRScope(endbb,oldend); |
767 } | 785 } |
768 | 786 |
826 body->toIR(p); | 844 body->toIR(p); |
827 } | 845 } |
828 | 846 |
829 ////////////////////////////////////////////////////////////////////////////// | 847 ////////////////////////////////////////////////////////////////////////////// |
830 | 848 |
849 void SynchronizedStatement::toIR(IRState* p) | |
850 { | |
851 Logger::println("SynchronizedStatement::toIR(): %s", toChars()); | |
852 LOG_SCOPE; | |
853 | |
854 Logger::attention("synchronized is currently ignored. only the body will be emitted"); | |
855 | |
856 body->toIR(p); | |
857 } | |
858 | |
859 ////////////////////////////////////////////////////////////////////////////// | |
860 | |
831 ////////////////////////////////////////////////////////////////////////////// | 861 ////////////////////////////////////////////////////////////////////////////// |
832 | 862 |
833 #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();} | 863 #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();} |
834 //STUBST(BreakStatement); | 864 //STUBST(BreakStatement); |
835 //STUBST(ForStatement); | 865 //STUBST(ForStatement); |
836 //STUBST(WithStatement); | 866 //STUBST(WithStatement); |
837 STUBST(SynchronizedStatement); | 867 //STUBST(SynchronizedStatement); |
838 //STUBST(ReturnStatement); | 868 //STUBST(ReturnStatement); |
839 //STUBST(ContinueStatement); | 869 //STUBST(ContinueStatement); |
840 STUBST(DefaultStatement); | 870 STUBST(DefaultStatement); |
841 STUBST(CaseStatement); | 871 STUBST(CaseStatement); |
842 //STUBST(SwitchStatement); | 872 //STUBST(SwitchStatement); |