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);