Mercurial > projects > ldc
comparison gen/arrays.cpp @ 715:30b42a283c8e
Removed TypeOpaque from DMD.
Changed runtime functions taking opaque[] to void[].
Implemented proper type painting, to avoid "resizing" array casts in runtime calls that previously took opaque[].
Implemented dynamic arrays as first class types, this implements proper ABI for these types on x86.
Added dwarf region end after call to assert function, fixes some problems with llvm not allowing this to be missing.
Reverted change to WithStatement from rev [704] it breaks MiniD, mini/with2.d needs to be fixed some other way...
Fixed tango bug 1339 in runtime, problem with _adReverseChar on invalid UTF-8.
Disabled .bc generation in the compiler runtime part, genobj.d triggers some llvm bug when using debug info. the .o seems to work fine.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Wed, 22 Oct 2008 14:55:33 +0200 |
parents | b411c41a9716 |
children | f04dde6e882c |
comparison
equal
deleted
inserted
replaced
714:1e98c99a87cb | 715:30b42a283c8e |
---|---|
53 void DtoSetArrayToNull(LLValue* v) | 53 void DtoSetArrayToNull(LLValue* v) |
54 { | 54 { |
55 Logger::println("DtoSetArrayToNull"); | 55 Logger::println("DtoSetArrayToNull"); |
56 LOG_SCOPE; | 56 LOG_SCOPE; |
57 | 57 |
58 LLValue* len = DtoGEPi(v,0,0); | 58 assert(isaPointer(v)); |
59 LLValue* zerolen = llvm::ConstantInt::get(len->getType()->getContainedType(0), 0, false); | 59 const LLType* t = v->getType()->getContainedType(0); |
60 DtoStore(zerolen, len); | 60 |
61 | 61 DtoStore(LLConstant::getNullValue(t), v); |
62 LLValue* ptr = DtoGEPi(v,0,1); | |
63 const LLPointerType* pty = isaPointer(ptr->getType()->getContainedType(0)); | |
64 LLValue* nullptr = llvm::ConstantPointerNull::get(pty); | |
65 DtoStore(nullptr, ptr); | |
66 } | |
67 | |
68 ////////////////////////////////////////////////////////////////////////////////////////// | |
69 | |
70 void DtoArrayAssign(LLValue* dst, LLValue* src) | |
71 { | |
72 Logger::println("DtoArrayAssign"); | |
73 LOG_SCOPE; | |
74 | |
75 assert(gIR); | |
76 if (dst->getType() == src->getType()) | |
77 { | |
78 LLValue* ptr = DtoGEPi(src,0,0); | |
79 LLValue* val = DtoLoad(ptr); | |
80 ptr = DtoGEPi(dst,0,0); | |
81 DtoStore(val, ptr); | |
82 | |
83 ptr = DtoGEPi(src,0,1); | |
84 val = DtoLoad(ptr); | |
85 ptr = DtoGEPi(dst,0,1); | |
86 DtoStore(val, ptr); | |
87 } | |
88 else | |
89 { | |
90 if (Logger::enabled()) | |
91 Logger::cout() << "array assignment type dont match: " << *dst->getType() << "\n\n" << *src->getType() << '\n'; | |
92 const LLArrayType* arrty = isaArray(src->getType()->getContainedType(0)); | |
93 if (!arrty) | |
94 { | |
95 std::cout << "invalid: " << *src << '\n'; | |
96 assert(0); | |
97 } | |
98 const LLType* dstty = getPtrToType(arrty->getElementType()); | |
99 | |
100 LLValue* dstlen = DtoGEPi(dst,0,0); | |
101 LLValue* srclen = DtoConstSize_t(arrty->getNumElements()); | |
102 DtoStore(srclen, dstlen); | |
103 | |
104 LLValue* dstptr = DtoGEPi(dst,0,1); | |
105 LLValue* srcptr = DtoBitCast(src, dstty); | |
106 DtoStore(srcptr, dstptr); | |
107 } | |
108 } | 62 } |
109 | 63 |
110 ////////////////////////////////////////////////////////////////////////////////////////// | 64 ////////////////////////////////////////////////////////////////////////////////////////// |
111 | 65 |
112 void DtoArrayInit(Loc& loc, DValue* array, DValue* value) | 66 void DtoArrayInit(Loc& loc, DValue* array, DValue* value) |
682 { | 636 { |
683 Logger::println("comparing arrays"); | 637 Logger::println("comparing arrays"); |
684 LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, func); | 638 LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, func); |
685 assert(fn); | 639 assert(fn); |
686 | 640 |
641 // find common dynamic array type | |
642 Type* commonType = l->getType()->toBasetype()->nextOf()->arrayOf(); | |
643 | |
644 // cast static arrays to dynamic ones, this turns them into DSliceValues | |
645 Logger::println("casting to dynamic arrays"); | |
646 l = DtoCastArray(loc, l, commonType); | |
647 r = DtoCastArray(loc, r, commonType); | |
648 | |
687 LLValue* lmem; | 649 LLValue* lmem; |
688 LLValue* rmem; | 650 LLValue* rmem; |
689 | |
690 // cast static arrays to dynamic ones, this turns them into DSliceValues | |
691 Logger::println("casting to dynamic arrays"); | |
692 Type* l_ty = l->getType()->toBasetype(); | |
693 Type* r_ty = r->getType()->toBasetype(); | |
694 assert(l_ty->next == r_ty->next); | |
695 if ((l_ty->ty == Tsarray) || (r_ty->ty == Tsarray)) { | |
696 Type* a_ty = l_ty->next->arrayOf(); | |
697 if (l_ty->ty == Tsarray) | |
698 l = DtoCastArray(loc, l, a_ty); | |
699 if (r_ty->ty == Tsarray) | |
700 r = DtoCastArray(loc, r, a_ty); | |
701 } | |
702 | |
703 Logger::println("giving storage"); | |
704 | |
705 // we need to give slices storage | |
706 if (l->isSlice()) { | |
707 lmem = DtoAlloca(DtoType(l->getType()), "tmpparam"); | |
708 DtoSetArray(lmem, DtoArrayLen(l), DtoArrayPtr(l)); | |
709 } | |
710 // also null | |
711 else if (l->isNull()) | |
712 { | |
713 lmem = DtoAlloca(DtoType(l->getType()), "tmpparam"); | |
714 DtoSetArray(lmem, llvm::Constant::getNullValue(DtoSize_t()), llvm::Constant::getNullValue(DtoType(l->getType()->next->pointerTo()))); | |
715 } | |
716 else | |
717 lmem = l->getRVal(); | |
718 | |
719 // and for the rvalue ... | |
720 // we need to give slices storage | |
721 if (r->isSlice()) { | |
722 rmem = DtoAlloca(DtoType(r->getType()), "tmpparam"); | |
723 DtoSetArray(rmem, DtoArrayLen(r), DtoArrayPtr(r)); | |
724 } | |
725 // also null | |
726 else if (r->isNull()) | |
727 { | |
728 rmem = DtoAlloca(DtoType(r->getType()), "tmpparam"); | |
729 DtoSetArray(rmem, llvm::Constant::getNullValue(DtoSize_t()), llvm::Constant::getNullValue(DtoType(r->getType()->next->pointerTo()))); | |
730 } | |
731 else | |
732 rmem = r->getRVal(); | |
733 | |
734 const LLType* pt = fn->getFunctionType()->getParamType(0); | |
735 | |
736 LLSmallVector<LLValue*, 3> args; | 651 LLSmallVector<LLValue*, 3> args; |
737 if (Logger::enabled()) | 652 |
738 { | 653 // get values, reinterpret cast to void[] |
739 Logger::cout() << "bitcasting to " << *pt << '\n'; | 654 lmem = DtoAggrPaint(l->getRVal(), DtoArrayType(LLType::Int8Ty)); |
740 Logger::cout() << *lmem << '\n'; | 655 args.push_back(lmem); |
741 Logger::cout() << *rmem << '\n'; | 656 |
742 } | 657 rmem = DtoAggrPaint(r->getRVal(), DtoArrayType(LLType::Int8Ty)); |
743 args.push_back(DtoBitCast(lmem,pt)); | 658 args.push_back(rmem); |
744 args.push_back(DtoBitCast(rmem,pt)); | |
745 | 659 |
746 // pass array typeinfo ? | 660 // pass array typeinfo ? |
747 if (useti) { | 661 if (useti) { |
748 Type* t = l->getType(); | 662 Type* t = l->getType(); |
749 LLValue* tival = DtoTypeInfoOf(t); | 663 LLValue* tival = DtoTypeInfoOf(t); |
751 DtoForceConstInitDsymbol(t->vtinfo); | 665 DtoForceConstInitDsymbol(t->vtinfo); |
752 | 666 |
753 if (Logger::enabled()) | 667 if (Logger::enabled()) |
754 Logger::cout() << "typeinfo decl: " << *tival << '\n'; | 668 Logger::cout() << "typeinfo decl: " << *tival << '\n'; |
755 | 669 |
756 pt = fn->getFunctionType()->getParamType(2); | 670 args.push_back(DtoBitCast(tival, fn->getFunctionType()->getParamType(2))); |
757 args.push_back(DtoBitCast(tival, pt)); | |
758 } | 671 } |
759 | 672 |
760 CallOrInvoke* call = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), "tmp"); | 673 CallOrInvoke* call = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), "tmp"); |
761 | |
762 // set param attrs | |
763 llvm::AttrListPtr palist; | |
764 palist = palist.addAttr(1, llvm::Attribute::ByVal); | |
765 palist = palist.addAttr(2, llvm::Attribute::ByVal); | |
766 call->setAttributes(palist); | |
767 | 674 |
768 return call->get(); | 675 return call->get(); |
769 } | 676 } |
770 | 677 |
771 ////////////////////////////////////////////////////////////////////////////////////////// | 678 ////////////////////////////////////////////////////////////////////////////////////////// |
915 if (t->ty == Tarray) { | 822 if (t->ty == Tarray) { |
916 if (DSliceValue* s = v->isSlice()) | 823 if (DSliceValue* s = v->isSlice()) |
917 return s->len; | 824 return s->len; |
918 else if (v->isNull()) | 825 else if (v->isNull()) |
919 return DtoConstSize_t(0); | 826 return DtoConstSize_t(0); |
920 return DtoLoad(DtoGEPi(v->getRVal(), 0,0)); | 827 else if (v->isLVal()) |
828 return DtoLoad(DtoGEPi(v->getLVal(), 0,0), ".len"); | |
829 return gIR->ir->CreateExtractValue(v->getRVal(), 0, ".len"); | |
921 } | 830 } |
922 else if (t->ty == Tsarray) { | 831 else if (t->ty == Tsarray) { |
923 assert(!v->isSlice()); | 832 assert(!v->isSlice()); |
924 assert(!v->isNull()); | 833 assert(!v->isNull()); |
925 LLValue* rv = v->getRVal(); | 834 LLValue* rv = v->getRVal(); |
941 if (t->ty == Tarray) { | 850 if (t->ty == Tarray) { |
942 if (DSliceValue* s = v->isSlice()) | 851 if (DSliceValue* s = v->isSlice()) |
943 return s->ptr; | 852 return s->ptr; |
944 else if (v->isNull()) | 853 else if (v->isNull()) |
945 return getNullPtr(getPtrToType(DtoType(t->next))); | 854 return getNullPtr(getPtrToType(DtoType(t->next))); |
946 return DtoLoad(DtoGEPi(v->getRVal(), 0,1)); | 855 else if (v->isLVal()) |
856 return DtoLoad(DtoGEPi(v->getLVal(), 0,1), ".ptr"); | |
857 return gIR->ir->CreateExtractValue(v->getRVal(), 1, ".ptr"); | |
947 } | 858 } |
948 else if (t->ty == Tsarray) { | 859 else if (t->ty == Tsarray) { |
949 assert(!v->isSlice()); | 860 assert(!v->isSlice()); |
950 assert(!v->isNull()); | 861 assert(!v->isNull()); |
951 return DtoGEPi(v->getRVal(), 0,0); | 862 return DtoGEPi(v->getRVal(), 0,0); |
1044 } | 955 } |
1045 | 956 |
1046 return new DImValue(to, rval); | 957 return new DImValue(to, rval); |
1047 } | 958 } |
1048 | 959 |
1049 | |
1050 ////////////////////////////////////////////////////////////////////////////////////////// | 960 ////////////////////////////////////////////////////////////////////////////////////////// |
1051 void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index, bool isslice) | 961 void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index, bool isslice) |
1052 { | 962 { |
1053 Type* arrty = arr->getType()->toBasetype(); | 963 Type* arrty = arr->getType()->toBasetype(); |
1054 assert((arrty->ty == Tsarray || arrty->ty == Tarray) && "Can only array bounds check for static or dynamic arrays"); | 964 assert((arrty->ty == Tsarray || arrty->ty == Tarray) && "Can only array bounds check for static or dynamic arrays"); |
1069 // set up failbb to call the array bounds error runtime function | 979 // set up failbb to call the array bounds error runtime function |
1070 | 980 |
1071 gIR->scope() = IRScope(failbb, okbb); | 981 gIR->scope() = IRScope(failbb, okbb); |
1072 | 982 |
1073 std::vector<LLValue*> args; | 983 std::vector<LLValue*> args; |
1074 llvm::AttrListPtr palist; | |
1075 | 984 |
1076 // file param | 985 // file param |
1077 args.push_back(gIR->dmodule->ir.irModule->fileName); | 986 args.push_back(DtoLoad(gIR->dmodule->ir.irModule->fileName)); |
1078 palist = palist.addAttr(1, llvm::Attribute::ByVal); | |
1079 | 987 |
1080 // line param | 988 // line param |
1081 LLConstant* c = DtoConstUint(loc.linnum); | 989 LLConstant* c = DtoConstUint(loc.linnum); |
1082 args.push_back(c); | 990 args.push_back(c); |
1083 | 991 |
1084 // call | 992 // call |
1085 llvm::Function* errorfn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_bounds"); | 993 llvm::Function* errorfn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_bounds"); |
1086 CallOrInvoke* call = gIR->CreateCallOrInvoke(errorfn, args.begin(), args.end()); | 994 CallOrInvoke* call = gIR->CreateCallOrInvoke(errorfn, args.begin(), args.end()); |
1087 call->setAttributes(palist); | |
1088 | 995 |
1089 // the function does not return | 996 // the function does not return |
1090 gIR->ir->CreateUnreachable(); | 997 gIR->ir->CreateUnreachable(); |
1091 | 998 |
1092 | |
1093 // if ok, proceed in okbb | 999 // if ok, proceed in okbb |
1094 gIR->scope() = IRScope(okbb, oldend); | 1000 gIR->scope() = IRScope(okbb, oldend); |
1095 } | 1001 } |