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