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 }