comparison gen/tollvm.cpp @ 131:5825d48b27d1 trunk

[svn r135] * Merged DMD 1.025 * * Fixed a minor linking order mishap * * Added an command line option -annotate * * Fixed some problems with running optimizations * * Added std.stdio and dependencies to lphobos (still not 100% working, but compiles and links) * * Fixed problems with passing aggregate types to variadic functions * * Added initial code towards full GC support, currently based on malloc and friends, not all the runtime calls the GC yet for memory * * Fixed problems with resolving nested function context pointers for some heavily nested cases * * Redid function argument passing + other minor code cleanups, still lots to do on this end... *
author lindquist
date Fri, 04 Jan 2008 01:38:42 +0100
parents 8096ba7082db
children 1700239cab2e
comparison
equal deleted inserted replaced
130:a7dfa0ed966c 131:5825d48b27d1
671 call->setCallingConv(llvm::CallingConv::C); 671 call->setCallingConv(llvm::CallingConv::C);
672 } 672 }
673 673
674 ////////////////////////////////////////////////////////////////////////////////////////// 674 //////////////////////////////////////////////////////////////////////////////////////////
675 675
676 llvm::Value* DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp)
677 {
678 llvm::Value* retval = 0;
679
680 bool haslvals = !gIR->exps.empty();
681 if (haslvals)
682 gIR->exps.push_back(IRExp(NULL,NULL,NULL));
683
684 DValue* arg = argexp->toElem(gIR);
685
686 if (haslvals)
687 gIR->exps.pop_back();
688
689 if (arg->inPlace()) {
690 retval = arg->getRVal();
691 return retval;
692 }
693
694 Type* realtype = DtoDType(argexp->type);
695 TY argty = realtype->ty;
696 if (DtoIsPassedByRef(realtype)) {
697 if (!fnarg || !fnarg->llvmCopy) {
698 if (DSliceValue* sv = arg->isSlice()) {
699 retval = new llvm::AllocaInst(DtoType(realtype), "tmpparam", gIR->topallocapoint());
700 DtoSetArray(retval, DtoArrayLen(sv), DtoArrayPtr(sv));
701 }
702 else if (DComplexValue* cv = arg->isComplex()) {
703 retval = new llvm::AllocaInst(DtoType(realtype), "tmpparam", gIR->topallocapoint());
704 DtoComplexSet(retval, cv->re, cv->im);
705 }
706 else {
707 retval = arg->getRVal();
708 }
709 }
710 else {
711 llvm::Value* allocaInst = 0;
712 llvm::BasicBlock* entryblock = &gIR->topfunc()->front();
713
714 const llvm::Type* realtypell = DtoType(realtype);
715 const llvm::PointerType* pty = llvm::PointerType::get(realtypell);
716 if (argty == Tstruct) {
717 allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
718 DValue* dst = new DVarValue(realtype, allocaInst, true);
719 DtoAssign(dst,arg);
720 delete dst;
721 }
722 else if (argty == Tdelegate) {
723 allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
724 DValue* dst = new DVarValue(realtype, allocaInst, true);
725 DtoAssign(dst,arg);
726 delete dst;
727 }
728 else if (argty == Tarray) {
729 if (arg->isSlice()) {
730 allocaInst = new llvm::AllocaInst(realtypell, "tmpparam", gIR->topallocapoint());
731 }
732 else {
733 allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
734 }
735 }
736 else if (realtype->iscomplex()) {
737 if (arg->isComplex()) {
738 allocaInst = new llvm::AllocaInst(realtypell, "tmpparam", gIR->topallocapoint());
739 }
740 else {
741 allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
742 }
743 }
744 else
745 assert(0);
746
747 DValue* dst = new DVarValue(realtype, allocaInst, true);
748 DtoAssign(dst,arg);
749 delete dst;
750
751 retval = allocaInst;
752 }
753 }
754 else if (!fnarg || fnarg->llvmCopy) {
755 Logger::println("regular arg");
756 if (DSliceValue* sl = arg->isSlice()) {
757 if (sl->ptr) Logger::cout() << "ptr = " << *sl->ptr << '\n';
758 if (sl->len) Logger::cout() << "len = " << *sl->len << '\n';
759 assert(0);
760 }
761 else if (DComplexValue* cl = arg->isComplex()) {
762 assert(0 && "complex in the wrong place");
763 }
764 else {
765 retval = arg->getRVal();
766 }
767 }
768 else {
769 Logger::println("as ptr arg");
770 retval = arg->getLVal();
771 if (paramtype && retval->getType() != paramtype)
772 {
773 assert(0);
774 /*assert(retval->getType() == paramtype->getContainedType(0));
775 new llvm::StoreInst(retval, arg->getLVal(), gIR->scopebb());
776 retval = arg->getLVal();*/
777 }
778 }
779
780 if (fnarg && paramtype && retval->getType() != paramtype) {
781 // this is unfortunately needed with the way SymOffExp is overused
782 // and static arrays can end up being a pointer to their element type
783 if (arg->isField()) {
784 retval = gIR->ir->CreateBitCast(retval, paramtype, "tmp");
785 }
786 else {
787 Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n";
788 assert(0 && "parameter type that was actually passed is invalid");
789 }
790 }
791
792 delete arg;
793
794 return retval;
795 }
796
797 //////////////////////////////////////////////////////////////////////////////////////////
798
799 static void print_frame_worker(VarDeclaration* var, Dsymbol* par)
800 {
801 if (var->toParent2() == par)
802 {
803 Logger::println("parent found: '%s' kind: '%s'", par->toChars(), par->kind());
804 return;
805 }
806
807 Logger::println("diving into parent: '%s' kind: '%s'", par->toChars(), par->kind());
808 LOG_SCOPE;
809 print_frame_worker(var, par->toParent2());
810 }
811
812 static void print_nested_frame_list(VarDeclaration* var, Dsymbol* par)
813 {
814 Logger::println("PRINTING FRAME LIST FOR NESTED VAR: '%s'", var->toChars());
815 {
816 LOG_SCOPE;
817 print_frame_worker(var, par);
818 }
819 Logger::println("DONE");
820 }
821
822 static const llvm::Type* get_next_frame_ptr_type(Dsymbol* sc) 676 static const llvm::Type* get_next_frame_ptr_type(Dsymbol* sc)
823 { 677 {
824 assert(sc->isFuncDeclaration() || sc->isClassDeclaration()); 678 assert(sc->isFuncDeclaration() || sc->isClassDeclaration());
825 Dsymbol* p = sc->toParent2(); 679 Dsymbol* p = sc->toParent2();
680 if (!p->isFuncDeclaration() && !p->isClassDeclaration())
681 Logger::println("unexpected parent symbol found while resolving frame pointer - '%s' kind: '%s'", p->toChars(), p->kind());
826 assert(p->isFuncDeclaration() || p->isClassDeclaration()); 682 assert(p->isFuncDeclaration() || p->isClassDeclaration());
827 if (FuncDeclaration* fd = p->isFuncDeclaration()) 683 if (FuncDeclaration* fd = p->isFuncDeclaration())
828 { 684 {
829 llvm::Value* v = fd->llvmNested; 685 llvm::Value* v = fd->llvmNested;
830 assert(v); 686 assert(v);
839 Logger::println("symbol: '%s' kind: '%s'", sc->toChars(), sc->kind()); 695 Logger::println("symbol: '%s' kind: '%s'", sc->toChars(), sc->kind());
840 assert(0); 696 assert(0);
841 } 697 }
842 } 698 }
843 699
844 static llvm::Value* get_frame_ptr_impl(VarDeclaration* vd, Dsymbol* sc, llvm::Value* v) 700 //////////////////////////////////////////////////////////////////////////////////////////
845 { 701
846 if (vd->toParent2() == sc) 702 static llvm::Value* get_frame_ptr_impl(FuncDeclaration* func, Dsymbol* sc, llvm::Value* v)
703 {
704 LOG_SCOPE;
705 if (sc == func)
847 { 706 {
848 return v; 707 return v;
849 } 708 }
850 else if (FuncDeclaration* fd = sc->isFuncDeclaration()) 709 else if (FuncDeclaration* fd = sc->isFuncDeclaration())
851 { 710 {
852 Logger::println("scope is function"); 711 Logger::println("scope is function: %s", fd->toChars());
712
713 if (fd->toParent2() == func)
714 {
715 if (!func->llvmNested)
716 return NULL;
717 return DtoBitCast(v, func->llvmNested->getType());
718 }
719
853 v = DtoBitCast(v, get_next_frame_ptr_type(fd)); 720 v = DtoBitCast(v, get_next_frame_ptr_type(fd));
854 Logger::cout() << "v = " << *v << '\n'; 721 Logger::cout() << "v = " << *v << '\n';
855
856 if (fd->toParent2() == vd->toParent2())
857 return v;
858 722
859 if (fd->toParent2()->isFuncDeclaration()) 723 if (fd->toParent2()->isFuncDeclaration())
860 { 724 {
861 v = DtoGEPi(v, 0,0, "tmp"); 725 v = DtoGEPi(v, 0,0, "tmp");
862 v = DtoLoad(v); 726 v = DtoLoad(v);
870 } 734 }
871 else 735 else
872 { 736 {
873 assert(0); 737 assert(0);
874 } 738 }
875 return get_frame_ptr_impl(vd, fd->toParent2(), v); 739 return get_frame_ptr_impl(func, fd->toParent2(), v);
876 } 740 }
877 else if (ClassDeclaration* cd = sc->isClassDeclaration()) 741 else if (ClassDeclaration* cd = sc->isClassDeclaration())
878 { 742 {
879 Logger::println("scope is class"); 743 Logger::println("scope is class: %s", cd->toChars());
880 /*size_t idx = 2; 744 /*size_t idx = 2;
881 idx += cd->llvmIRStruct->interfaces.size(); 745 idx += cd->llvmIRStruct->interfaces.size();
882 v = DtoGEPi(v,0,idx,"tmp"); 746 v = DtoGEPi(v,0,idx,"tmp");
883 Logger::cout() << "gep = " << *v << '\n'; 747 Logger::cout() << "gep = " << *v << '\n';
884 v = DtoLoad(v);*/ 748 v = DtoLoad(v);*/
885 return get_frame_ptr_impl(vd, cd->toParent2(), v); 749 return get_frame_ptr_impl(func, cd->toParent2(), v);
886 } 750 }
887 else 751 else
888 { 752 {
889 Logger::println("symbol: '%s'", sc->toChars()); 753 Logger::println("symbol: '%s'", sc->toPrettyChars());
890 assert(0); 754 assert(0);
891 } 755 }
892 } 756 }
893 757
894 static llvm::Value* get_frame_ptr(VarDeclaration* vd) 758 //////////////////////////////////////////////////////////////////////////////////////////
895 { 759
896 Logger::println("RESOLVING FRAME PTR FOR NESTED VAR: '%s'", vd->toChars()); 760 static llvm::Value* get_frame_ptr(FuncDeclaration* func)
761 {
762 Logger::println("Resolving context pointer for nested function: '%s'", func->toPrettyChars());
897 LOG_SCOPE; 763 LOG_SCOPE;
898 IRFunction* irfunc = gIR->func(); 764 IRFunction* irfunc = gIR->func();
899 765
900 // in the parent scope already 766 // in the right scope already
901 if (vd->toParent2() == irfunc->decl) 767 if (func == irfunc->decl)
902 return irfunc->decl->llvmNested; 768 return irfunc->decl->llvmNested;
903 769
904 // use the 'this' pointer 770 // use the 'this' pointer
905 llvm::Value* ptr = irfunc->decl->llvmThisVar; 771 llvm::Value* ptr = irfunc->decl->llvmThisVar;
906 assert(ptr); 772 assert(ptr);
907 773
908 // return the fully resolved frame pointer 774 // return the fully resolved frame pointer
909 ptr = get_frame_ptr_impl(vd, irfunc->decl, ptr); 775 ptr = get_frame_ptr_impl(func, irfunc->decl, ptr);
910 Logger::cout() << "FOUND: '" << *ptr << "'\n"; 776 if (ptr) Logger::cout() << "Found context!" << *ptr;
777 else Logger::cout() << "NULL context!\n";
911 778
912 return ptr; 779 return ptr;
913 } 780 }
781
782 //////////////////////////////////////////////////////////////////////////////////////////
783
784 llvm::Value* DtoNestedContext(FuncDeclaration* func)
785 {
786 // resolve frame ptr
787 llvm::Value* ptr = get_frame_ptr(func);
788 Logger::cout() << "Nested context ptr = ";
789 if (ptr) Logger::cout() << *ptr;
790 else Logger::cout() << "NULL";
791 Logger::cout() << '\n';
792 return ptr;
793 }
794
795 //////////////////////////////////////////////////////////////////////////////////////////
796
797 static void print_frame_worker(VarDeclaration* vd, Dsymbol* par)
798 {
799 if (vd->toParent2() == par)
800 {
801 Logger::println("found: '%s' kind: '%s'", par->toChars(), par->kind());
802 return;
803 }
804
805 Logger::println("diving into: '%s' kind: '%s'", par->toChars(), par->kind());
806 LOG_SCOPE;
807 print_frame_worker(vd, par->toParent2());
808 }
809
810 //////////////////////////////////////////////////////////////////////////////////////////
811
812 static void print_nested_frame_list(VarDeclaration* vd, Dsymbol* par)
813 {
814 Logger::println("Frame pointer list for nested var: '%s'", vd->toPrettyChars());
815 LOG_SCOPE;
816 if (vd->toParent2() != par)
817 print_frame_worker(vd, par);
818 else
819 Logger::println("Found at level 0");
820 Logger::println("Done");
821 }
822
823 //////////////////////////////////////////////////////////////////////////////////////////
914 824
915 llvm::Value* DtoNestedVariable(VarDeclaration* vd) 825 llvm::Value* DtoNestedVariable(VarDeclaration* vd)
916 { 826 {
917 // log the frame list 827 // log the frame list
918 IRFunction* irfunc = gIR->func(); 828 IRFunction* irfunc = gIR->func();
919 print_nested_frame_list(vd, irfunc->decl); 829 if (Logger::enabled)
830 print_nested_frame_list(vd, irfunc->decl);
920 831
921 // resolve frame ptr 832 // resolve frame ptr
922 llvm::Value* ptr = get_frame_ptr(vd); 833 FuncDeclaration* func = vd->toParent2()->isFuncDeclaration();
923 Logger::cout() << "nested ptr = " << *ptr << '\n'; 834 assert(func);
835 llvm::Value* ptr = DtoNestedContext(func);
836 assert(ptr && "nested var, but no context");
924 837
925 // we must cast here to be sure. nested classes just have a void* 838 // we must cast here to be sure. nested classes just have a void*
926 ptr = DtoBitCast(ptr, vd->toParent2()->isFuncDeclaration()->llvmNested->getType()); 839 ptr = DtoBitCast(ptr, func->llvmNested->getType());
927 840
928 // index nested var and load (if necessary) 841 // index nested var and load (if necessary)
929 llvm::Value* v = DtoGEPi(ptr, 0, vd->llvmNestedIndex, "tmp"); 842 llvm::Value* v = DtoGEPi(ptr, 0, vd->llvmNestedIndex, "tmp");
930 // references must be loaded, for normal variables this IS already the variable storage!!! 843 // references must be loaded, for normal variables this IS already the variable storage!!!
931 if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) 844 if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)))
932 v = DtoLoad(v); 845 v = DtoLoad(v);
933 846
934 Logger::cout() << "FINAL RESULT: " << *v << '\n'; 847 // log and return
848 Logger::cout() << "Nested var ptr = " << *v << '\n';
935 return v; 849 return v;
936 } 850 }
937 851
938 ////////////////////////////////////////////////////////////////////////////////////////// 852 //////////////////////////////////////////////////////////////////////////////////////////
939 853
940 void DtoAssign(DValue* lhs, DValue* rhs) 854 void DtoAssign(DValue* lhs, DValue* rhs)
941 { 855 {
942 Logger::cout() << "DtoAssign(...);\n"; 856 Logger::cout() << "DtoAssign(...);\n";
857 LOG_SCOPE;
858
943 Type* t = DtoDType(lhs->getType()); 859 Type* t = DtoDType(lhs->getType());
944 Type* t2 = DtoDType(rhs->getType()); 860 Type* t2 = DtoDType(rhs->getType());
945 861
946 if (t->ty == Tstruct) { 862 if (t->ty == Tstruct) {
947 if (t2 != t) { 863 if (t2 != t) {
1022 DtoComplexSet(dst, cx->re, cx->im); 938 DtoComplexSet(dst, cx->re, cx->im);
1023 else 939 else
1024 DtoComplexAssign(dst, rhs->getRVal()); 940 DtoComplexAssign(dst, rhs->getRVal());
1025 } 941 }
1026 else { 942 else {
1027 llvm::Value* l; 943 llvm::Value* l = lhs->getLVal();
1028 if (DLRValue* lr = lhs->isLRValue()) {
1029 l = lr->getLVal();
1030 rhs = DtoCast(rhs, lr->getLType());
1031 }
1032 else {
1033 l = lhs->getLVal();
1034 }
1035 llvm::Value* r = rhs->getRVal(); 944 llvm::Value* r = rhs->getRVal();
1036 Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n'; 945 Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n';
1037 const llvm::Type* lit = l->getType()->getContainedType(0); 946 const llvm::Type* lit = l->getType()->getContainedType(0);
1038 if (r->getType() != lit) { // :( 947 if (r->getType() != lit) {
1039 r = DtoBitCast(r, lit); 948 if (DLRValue* lr = lhs->isLRValue()) // handle lvalue cast assignments
949 r = DtoCast(rhs, lr->getLType())->getRVal();
950 else
951 r = DtoCast(rhs, lhs->getType())->getRVal();
1040 Logger::cout() << "really assign\nlhs: " << *l << "rhs: " << *r << '\n'; 952 Logger::cout() << "really assign\nlhs: " << *l << "rhs: " << *r << '\n';
1041 } 953 }
1042 gIR->ir->CreateStore(r, l); 954 gIR->ir->CreateStore(r, l);
1043 } 955 }
1044 } 956 }
1053 assert(from->isintegral()); 965 assert(from->isintegral());
1054 966
1055 size_t fromsz = from->size(); 967 size_t fromsz = from->size();
1056 size_t tosz = to->size(); 968 size_t tosz = to->size();
1057 969
1058 llvm::Value* rval; 970 llvm::Value* rval = val->getRVal();
971 if (rval->getType() == tolltype) {
972 return new DImValue(_to, rval);
973 }
1059 974
1060 if (to->isintegral()) { 975 if (to->isintegral()) {
1061 if (fromsz < tosz) { 976 if (fromsz < tosz) {
1062 Logger::cout() << "cast to: " << *tolltype << '\n'; 977 Logger::cout() << "cast to: " << *tolltype << '\n';
1063 if (from->isunsigned() || from->ty == Tbool) { 978 if (from->isunsigned() || from->ty == Tbool) {
1064 rval = new llvm::ZExtInst(val->getRVal(), tolltype, "tmp", gIR->scopebb()); 979 rval = new llvm::ZExtInst(rval, tolltype, "tmp", gIR->scopebb());
1065 } else { 980 } else {
1066 rval = new llvm::SExtInst(val->getRVal(), tolltype, "tmp", gIR->scopebb()); 981 rval = new llvm::SExtInst(rval, tolltype, "tmp", gIR->scopebb());
1067 } 982 }
1068 } 983 }
1069 else if (fromsz > tosz) { 984 else if (fromsz > tosz) {
1070 rval = new llvm::TruncInst(val->getRVal(), tolltype, "tmp", gIR->scopebb()); 985 rval = new llvm::TruncInst(rval, tolltype, "tmp", gIR->scopebb());
1071 } 986 }
1072 else { 987 else {
1073 rval = new llvm::BitCastInst(val->getRVal(), tolltype, "tmp", gIR->scopebb()); 988 rval = new llvm::BitCastInst(rval, tolltype, "tmp", gIR->scopebb());
1074 } 989 }
1075 } 990 }
1076 else if (to->isfloating()) { 991 else if (to->isfloating()) {
1077 if (from->isunsigned()) { 992 if (from->isunsigned()) {
1078 rval = new llvm::UIToFPInst(val->getRVal(), tolltype, "tmp", gIR->scopebb()); 993 rval = new llvm::UIToFPInst(rval, tolltype, "tmp", gIR->scopebb());
1079 } 994 }
1080 else { 995 else {
1081 rval = new llvm::SIToFPInst(val->getRVal(), tolltype, "tmp", gIR->scopebb()); 996 rval = new llvm::SIToFPInst(rval, tolltype, "tmp", gIR->scopebb());
1082 } 997 }
1083 } 998 }
1084 else if (to->ty == Tpointer) { 999 else if (to->ty == Tpointer) {
1085 rval = gIR->ir->CreateIntToPtr(val->getRVal(), tolltype, "tmp"); 1000 Logger::cout() << "cast pointer: " << *tolltype << '\n';
1001 rval = gIR->ir->CreateIntToPtr(rval, tolltype, "tmp");
1086 } 1002 }
1087 else { 1003 else {
1088 assert(0 && "bad int cast"); 1004 assert(0 && "bad int cast");
1089 } 1005 }
1090 1006
1769 DtoEmptyDeclareList(); 1685 DtoEmptyDeclareList();
1770 DtoEmptyConstInitList(); 1686 DtoEmptyConstInitList();
1771 1687
1772 DtoDefineDsymbol(dsym); 1688 DtoDefineDsymbol(dsym);
1773 } 1689 }
1690
1691 //////////////////////////////////////////////////////////////////////////////////////////
1692
1693 void DtoAnnotation(const char* str)
1694 {
1695 std::string s("CODE: ");
1696 s.append(str);
1697 char* p = &s[0];
1698 while (*p)
1699 {
1700 if (*p == '"')
1701 *p = '\'';
1702 ++p;
1703 }
1704 // create a noop with the code as the result name!
1705 gIR->ir->CreateAnd(DtoConstSize_t(0),DtoConstSize_t(0),s.c_str());
1706 }