comparison gen/tollvm.c @ 40:8b0e809563df trunk

[svn r44] Lots of bug fixes. New array literal support New array ~= operator support (for single element) New with statement support More...
author lindquist
date Fri, 19 Oct 2007 07:43:21 +0200
parents 4648206ca213
children e5c4bece7fa1
comparison
equal deleted inserted replaced
39:fd5e8bbfcb25 40:8b0e809563df
1 #include <iostream> 1 #include <iostream>
2 2
3 #include "llvm/Constants.h" 3 #include "gen/llvm.h"
4 #include "llvm/Type.h"
5 #include "llvm/DerivedTypes.h"
6 #include "llvm/GlobalValue.h"
7 #include "llvm/Instructions.h"
8 #include "llvm/CallingConv.h"
9 4
10 #include "mtype.h" 5 #include "mtype.h"
11 #include "dsymbol.h" 6 #include "dsymbol.h"
12 #include "aggregate.h" 7 #include "aggregate.h"
13 #include "declaration.h" 8 #include "declaration.h"
17 #include "gen/irstate.h" 12 #include "gen/irstate.h"
18 #include "gen/logger.h" 13 #include "gen/logger.h"
19 #include "gen/runtime.h" 14 #include "gen/runtime.h"
20 #include "gen/elem.h" 15 #include "gen/elem.h"
21 #include "gen/arrays.h" 16 #include "gen/arrays.h"
17
18 bool LLVM_DtoIsPassedByRef(Type* type)
19 {
20 TY t = type->ty;
21 if (t == Tstruct || t == Tarray || t == Tdelegate)
22 return true;
23 else if (t == Ttypedef) {
24 Type* bt = type->toBasetype();
25 assert(bt);
26 return LLVM_DtoIsPassedByRef(bt);
27 }
28 return false;
29 }
30
31 Type* LLVM_DtoDType(Type* t)
32 {
33 if (t->ty == Ttypedef) {
34 Type* bt = t->toBasetype();
35 assert(bt);
36 return LLVM_DtoDType(bt);
37 }
38 return t;
39 }
22 40
23 const llvm::Type* LLVM_DtoType(Type* t) 41 const llvm::Type* LLVM_DtoType(Type* t)
24 { 42 {
25 assert(t); 43 assert(t);
26 switch (t->ty) 44 switch (t->ty)
165 183
166 // parameter types 184 // parameter types
167 const llvm::Type* rettype; 185 const llvm::Type* rettype;
168 std::vector<const llvm::Type*> paramvec; 186 std::vector<const llvm::Type*> paramvec;
169 187
170 TY retty = f->next->ty; 188 if (LLVM_DtoIsPassedByRef(f->next)) {
171
172 if (retty == Tstruct || retty == Tdelegate || retty == Tarray) {
173 rettype = llvm::PointerType::get(LLVM_DtoType(f->next)); 189 rettype = llvm::PointerType::get(LLVM_DtoType(f->next));
174 paramvec.push_back(rettype); 190 paramvec.push_back(rettype);
175 rettype = llvm::Type::VoidTy; 191 rettype = llvm::Type::VoidTy;
176 } 192 }
177 else { 193 else {
223 if (fdecl->isMain()) { 239 if (fdecl->isMain()) {
224 rettype = llvm::Type::Int32Ty; 240 rettype = llvm::Type::Int32Ty;
225 actualRettype = rettype; 241 actualRettype = rettype;
226 } 242 }
227 else if (rt) { 243 else if (rt) {
228 if (rt->ty == Tstruct || rt->ty == Tdelegate || rt->ty == Tarray) { 244 if (LLVM_DtoIsPassedByRef(rt)) {
229 rettype = llvm::PointerType::get(LLVM_DtoType(rt)); 245 rettype = llvm::PointerType::get(LLVM_DtoType(rt));
230 actualRettype = llvm::Type::VoidTy; 246 actualRettype = llvm::Type::VoidTy;
231 f->llvmRetInPtr = retinptr = true; 247 f->llvmRetInPtr = retinptr = true;
232 } 248 }
233 else { 249 else {
263 279
264 size_t n = Argument::dim(f->parameters); 280 size_t n = Argument::dim(f->parameters);
265 for (int i=0; i < n; ++i) { 281 for (int i=0; i < n; ++i) {
266 Argument* arg = Argument::getNth(f->parameters, i); 282 Argument* arg = Argument::getNth(f->parameters, i);
267 // ensure scalar 283 // ensure scalar
268 Type* argT = arg->type; 284 Type* argT = LLVM_DtoDType(arg->type);
269 assert(argT); 285 assert(argT);
270 286
271 if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) { 287 if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
272 //assert(arg->vardecl); 288 //assert(arg->vardecl);
273 //arg->vardecl->refparam = true; 289 //arg->vardecl->refparam = true;
284 Logger::println("sarray param"); 300 Logger::println("sarray param");
285 assert(argT->ty == Tsarray); 301 assert(argT->ty == Tsarray);
286 //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0))); 302 //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0)));
287 paramvec.push_back(llvm::PointerType::get(at)); 303 paramvec.push_back(llvm::PointerType::get(at));
288 } 304 }
305 else if (llvm::isa<llvm::OpaqueType>(at)) {
306 Logger::println("opaque param");
307 if (argT->ty == Tstruct || argT->ty == Tclass)
308 paramvec.push_back(llvm::PointerType::get(at));
309 else
310 assert(0);
311 }
312 /*if (llvm::isa<llvm::StructType>(at) || argT->ty == Tstruct || argT->ty == Tsarray) {
313 paramvec.push_back(llvm::PointerType::get(at));
314 }*/
289 else { 315 else {
290 if (!arg->llvmCopy) { 316 if (!arg->llvmCopy) {
291 Logger::println("ref param"); 317 Logger::println("ref param");
292 at = llvm::PointerType::get(at); 318 at = llvm::PointerType::get(at);
293 } 319 }
451 477
452 return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); 478 return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
453 } 479 }
454 480
455 ////////////////////////////////////////////////////////////////////////////////////////// 481 //////////////////////////////////////////////////////////////////////////////////////////
456 llvm::Constant* LLVM_DtoStructInitializer(StructInitializer* si) 482 llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si)
457 { 483 {
458 llvm::StructType* structtype = llvm::cast<llvm::StructType>(si->ad->llvmType); 484 llvm::StructType* structtype = llvm::cast<llvm::StructType>(si->ad->llvmType);
459 size_t n = structtype->getNumElements(); 485 size_t n = structtype->getNumElements();
460 486
461 assert(si->value.dim == si->vars.dim); 487 assert(si->value.dim == si->vars.dim);
466 { 492 {
467 Initializer* ini = (Initializer*)si->value.data[i]; 493 Initializer* ini = (Initializer*)si->value.data[i];
468 assert(ini); 494 assert(ini);
469 495
470 VarDeclaration* vd = (VarDeclaration*)si->vars.data[i]; 496 VarDeclaration* vd = (VarDeclaration*)si->vars.data[i];
497 Type* vdtype = LLVM_DtoDType(vd->type);
471 assert(vd); 498 assert(vd);
472 Logger::println("vars[%d] = %s", i, vd->toChars()); 499 Logger::println("vars[%d] = %s", i, vd->toChars());
473 500
474 std::vector<unsigned> idxs; 501 std::vector<unsigned> idxs;
475 si->ad->offsetToIndex(vd->type, vd->offset, idxs); 502 si->ad->offsetToIndex(vdtype, vd->offset, idxs);
476 assert(idxs.size() == 1); 503 assert(idxs.size() == 1);
477 unsigned idx = idxs[0]; 504 unsigned idx = idxs[0];
478 505
479 llvm::Constant* v = 0; 506 llvm::Constant* v = 0;
480 507
481 if (ExpInitializer* ex = ini->isExpInitializer()) 508 if (ExpInitializer* ex = ini->isExpInitializer())
482 { 509 {
483 elem* e = ex->exp->toElem(gIR); 510 v = ex->exp->toConstElem(gIR);
484 v = llvm::cast<llvm::Constant>(e->val);
485 delete e;
486 } 511 }
487 else if (StructInitializer* si = ini->isStructInitializer()) 512 else if (StructInitializer* si = ini->isStructInitializer())
488 { 513 {
489 v = LLVM_DtoStructInitializer(si); 514 v = LLVM_DtoConstStructInitializer(si);
490 } 515 }
491 else if (ArrayInitializer* ai = ini->isArrayInitializer()) 516 else if (ArrayInitializer* ai = ini->isArrayInitializer())
492 { 517 {
493 v = LLVM_DtoArrayInitializer(ai); 518 v = LLVM_DtoConstArrayInitializer(ai);
494 } 519 }
495 else if (ini->isVoidInitializer()) 520 else if (ini->isVoidInitializer())
496 { 521 {
497 v = llvm::UndefValue::get(structtype->getElementType(idx)); 522 v = llvm::UndefValue::get(structtype->getElementType(idx));
498 } 523 }
729 fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_dtors"); 754 fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_dtors");
730 new llvm::CallInst(fn,"",bb); 755 new llvm::CallInst(fn,"",bb);
731 756
732 // return 757 // return
733 new llvm::ReturnInst(call,bb); 758 new llvm::ReturnInst(call,bb);
734
735 /*
736 // return value type
737 const llvm::Type* rettype;
738 Type* rt = f->next;
739 if (rt) {
740 rettype = LLVM_DtoType(rt);
741 }
742 else {
743 assert(0);
744 }
745
746 llvm::FunctionType* functype = llvm::FunctionType::get(rettype, paramvec, false);
747 */
748 } 759 }
749 760
750 ////////////////////////////////////////////////////////////////////////////////////////// 761 //////////////////////////////////////////////////////////////////////////////////////////
751 762
752 void LLVM_DtoCallClassDtors(TypeClass* tc, llvm::Value* instance) 763 void LLVM_DtoCallClassDtors(TypeClass* tc, llvm::Value* instance)
800 } 811 }
801 } 812 }
802 813
803 ////////////////////////////////////////////////////////////////////////////////////////// 814 //////////////////////////////////////////////////////////////////////////////////////////
804 815
805 llvm::Constant* LLVM_DtoInitializer(Type* type, Initializer* init) 816 llvm::Constant* LLVM_DtoConstInitializer(Type* type, Initializer* init)
806 { 817 {
807 llvm::Constant* _init = 0; // may return zero 818 llvm::Constant* _init = 0; // may return zero
808 if (!init) 819 if (!init)
809 { 820 {
810 Logger::println("default initializer"); 821 Logger::println("const default initializer for %s", type->toChars());
811 elem* e = type->defaultInit()->toElem(gIR); 822 _init = type->defaultInit()->toConstElem(gIR);
812 if (!e->inplace && !e->isNull()) {
813 _init = llvm::cast<llvm::Constant>(e->getValue());
814 }
815 delete e;
816 } 823 }
817 else if (ExpInitializer* ex = init->isExpInitializer()) 824 else if (ExpInitializer* ex = init->isExpInitializer())
825 {
826 Logger::println("const expression initializer");
827 _init = ex->exp->toConstElem(gIR);
828 }
829 else if (StructInitializer* si = init->isStructInitializer())
830 {
831 Logger::println("const struct initializer");
832 _init = LLVM_DtoConstStructInitializer(si);
833 }
834 else if (ArrayInitializer* ai = init->isArrayInitializer())
835 {
836 Logger::println("const array initializer");
837 _init = LLVM_DtoConstArrayInitializer(ai);
838 }
839 else if (init->isVoidInitializer())
840 {
841 Logger::println("const void initializer");
842 const llvm::Type* ty = LLVM_DtoType(type);
843 _init = llvm::Constant::getNullValue(ty);
844 }
845 else {
846 Logger::println("unsupported const initializer: %s", init->toChars());
847 }
848 return _init;
849 }
850
851 //////////////////////////////////////////////////////////////////////////////////////////
852
853 void LLVM_DtoInitializer(Initializer* init)
854 {
855 if (ExpInitializer* ex = init->isExpInitializer())
818 { 856 {
819 Logger::println("expression initializer"); 857 Logger::println("expression initializer");
820 elem* e = ex->exp->toElem(gIR); 858 elem* e = ex->exp->toElem(gIR);
821 if (!e->inplace && !e->isNull()) {
822 _init = llvm::cast<llvm::Constant>(e->getValue());
823 }
824 delete e; 859 delete e;
825 }
826 else if (StructInitializer* si = init->isStructInitializer())
827 {
828 Logger::println("struct initializer");
829 _init = LLVM_DtoStructInitializer(si);
830 }
831 else if (ArrayInitializer* ai = init->isArrayInitializer())
832 {
833 Logger::println("array initializer");
834 _init = LLVM_DtoArrayInitializer(ai);
835 }
836 else if (init->isVoidInitializer())
837 {
838 Logger::println("void initializer");
839 const llvm::Type* ty = LLVM_DtoType(type);
840 _init = llvm::Constant::getNullValue(ty);
841 } 860 }
842 else { 861 else {
843 Logger::println("unsupported initializer: %s", init->toChars()); 862 Logger::println("unsupported initializer: %s", init->toChars());
844 } 863 }
845 return _init;
846 } 864 }
847 865
848 ////////////////////////////////////////////////////////////////////////////////////////// 866 //////////////////////////////////////////////////////////////////////////////////////////
849 867
850 llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, llvm::Value* i0, llvm::Value* i1, const std::string& var, llvm::BasicBlock* bb) 868 llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, llvm::Value* i0, llvm::Value* i1, const std::string& var, llvm::BasicBlock* bb)
860 878
861 llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, const std::vector<unsigned>& src, const std::string& var, llvm::BasicBlock* bb) 879 llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, const std::vector<unsigned>& src, const std::string& var, llvm::BasicBlock* bb)
862 { 880 {
863 size_t n = src.size(); 881 size_t n = src.size();
864 std::vector<llvm::Value*> dst(n); 882 std::vector<llvm::Value*> dst(n);
865 Logger::cout() << "indices:"; 883 std::ostream& ostr = Logger::cout();
884 ostr << "indices for '" << *ptr << "':";
866 for (size_t i=0; i<n; ++i) 885 for (size_t i=0; i<n; ++i)
867 { 886 {
868 Logger::cout() << ' ' << i; 887 ostr << ' ' << i;
869 dst[i] = llvm::ConstantInt::get(llvm::Type::Int32Ty, src[i], false); 888 dst[i] = llvm::ConstantInt::get(llvm::Type::Int32Ty, src[i], false);
870 } 889 }
871 Logger::cout() << '\n'; 890 ostr << '\n';
872 return new llvm::GetElementPtrInst(ptr, dst.begin(), dst.end(), var, bb); 891 return new llvm::GetElementPtrInst(ptr, dst.begin(), dst.end(), var, bb);
873 } 892 }
874 893
875 ////////////////////////////////////////////////////////////////////////////////////////// 894 //////////////////////////////////////////////////////////////////////////////////////////
876 895
910 return func; 929 return func;
911 */ 930 */
912 } 931 }
913 932
914 // regular function 933 // regular function
915 TypeFunction* f = (TypeFunction*)fdecl->type; 934 TypeFunction* f = (TypeFunction*)LLVM_DtoDType(fdecl->type);
916 assert(f != 0); 935 assert(f != 0);
917 936
918 if (fdecl->llvmValue != 0) { 937 if (fdecl->llvmValue != 0) {
919 if (!llvm::isa<llvm::Function>(fdecl->llvmValue)) 938 if (!llvm::isa<llvm::Function>(fdecl->llvmValue))
920 { 939 {
1052 assert(fn); 1071 assert(fn);
1053 llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); 1072 llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
1054 call->setCallingConv(llvm::CallingConv::C); 1073 call->setCallingConv(llvm::CallingConv::C);
1055 } 1074 }
1056 1075
1057 1076 //////////////////////////////////////////////////////////////////////////////////////////
1058 1077
1059 1078 llvm::Value* LLVM_DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp)
1060 1079 {
1061 1080 llvm::Value* retval = 0;
1062 1081
1082 bool haslvals = !gIR->lvals.empty();
1083 if (haslvals)
1084 gIR->lvals.push_back(NULL);
1085
1086 elem* arg = argexp->toElem(gIR);
1087
1088 if (haslvals)
1089 gIR->lvals.pop_back();
1090
1091 if (arg->inplace) {
1092 assert(arg->mem != 0);
1093 retval = arg->mem;
1094 delete arg;
1095 return retval;
1096 }
1097
1098 Type* realtype = LLVM_DtoDType(argexp->type);
1099 TY argty = realtype->ty;
1100 if (LLVM_DtoIsPassedByRef(realtype)) {
1101 if (!fnarg || !fnarg->llvmCopy) {
1102 retval = arg->getValue();
1103 assert(retval != 0);
1104 }
1105 else {
1106 llvm::Value* allocaInst = 0;
1107 llvm::BasicBlock* entryblock = &gIR->topfunc()->front();
1108 //const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(arg->mem->getType());
1109 const llvm::PointerType* pty = llvm::PointerType::get(LLVM_DtoType(argexp->type));
1110 if (argty == Tstruct) {
1111 allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
1112 TypeStruct* ts = (TypeStruct*)LLVM_DtoDType(argexp->type);
1113 LLVM_DtoStructCopy(ts,allocaInst,arg->mem);
1114 }
1115 else if (argty == Tdelegate) {
1116 allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
1117 LLVM_DtoDelegateCopy(allocaInst,arg->mem);
1118 }
1119 else if (argty == Tarray) {
1120 if (arg->type == elem::SLICE) {
1121 allocaInst = new llvm::AllocaInst(LLVM_DtoType(argexp->type), "tmpparam", gIR->topallocapoint());
1122 LLVM_DtoSetArray(allocaInst, arg->arg, arg->mem);
1123 }
1124 else {
1125 allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
1126 LLVM_DtoArrayAssign(allocaInst,arg->mem);
1127 }
1128 }
1129 else
1130 assert(0);
1131
1132 assert(allocaInst != 0);
1133 retval = allocaInst;
1134 }
1135 }
1136 else if (!fnarg || fnarg->llvmCopy) {
1137 Logger::println("regular arg");
1138 assert(arg->type != elem::SLICE);
1139 if (arg->mem) Logger::cout() << "mem = " << *arg->mem << '\n';
1140 if (arg->val) Logger::cout() << "val = " << *arg->val << '\n';
1141 if (arg->arg) Logger::cout() << "arg = " << *arg->arg << '\n';
1142 retval = arg->arg ? arg->arg : arg->field ? arg->mem : arg->getValue();
1143 }
1144 else {
1145 Logger::println("as ptr arg");
1146 retval = arg->mem ? arg->mem : arg->val;
1147 if (retval->getType() != paramtype)
1148 {
1149 assert(retval->getType() == paramtype->getContainedType(0));
1150 LLVM_DtoGiveArgumentStorage(arg);
1151 new llvm::StoreInst(retval, arg->mem, gIR->scopebb());
1152 retval = arg->mem;
1153 }
1154 }
1155
1156 delete arg;
1157
1158 if (fnarg && retval->getType() != paramtype) {
1159 Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n";
1160 assert(0 && "parameter type that was actually passed is invalid");
1161 }
1162 return retval;
1163 }
1164
1165