Mercurial > projects > ldc
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 } |