Mercurial > projects > ldc
comparison gen/toir.cpp @ 133:44a95ac7368a trunk
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
In particular, assertions has been fixed to include file/line info, and much more!
author | lindquist |
---|---|
date | Mon, 14 Jan 2008 05:11:54 +0100 |
parents | 1700239cab2e |
children | 0e28624814e8 |
comparison
equal
deleted
inserted
replaced
132:1700239cab2e | 133:44a95ac7368a |
---|---|
177 Logger::println("TypeInfoDeclaration"); | 177 Logger::println("TypeInfoDeclaration"); |
178 DtoForceDeclareDsymbol(tid); | 178 DtoForceDeclareDsymbol(tid); |
179 assert(tid->llvmValue); | 179 assert(tid->llvmValue); |
180 const llvm::Type* vartype = DtoType(type); | 180 const llvm::Type* vartype = DtoType(type); |
181 llvm::Value* m; | 181 llvm::Value* m; |
182 if (tid->llvmValue->getType() != llvm::PointerType::get(vartype)) | 182 if (tid->llvmValue->getType() != getPtrToType(vartype)) |
183 m = p->ir->CreateBitCast(tid->llvmValue, vartype, "tmp"); | 183 m = p->ir->CreateBitCast(tid->llvmValue, vartype, "tmp"); |
184 else | 184 else |
185 m = tid->llvmValue; | 185 m = tid->llvmValue; |
186 return new DVarValue(vd, m, true); | 186 return new DVarValue(vd, m, true); |
187 } | 187 } |
276 DtoForceDeclareDsymbol(ti); | 276 DtoForceDeclareDsymbol(ti); |
277 assert(ti->llvmValue); | 277 assert(ti->llvmValue); |
278 const llvm::Type* vartype = DtoType(type); | 278 const llvm::Type* vartype = DtoType(type); |
279 llvm::Constant* m = isaConstant(ti->llvmValue); | 279 llvm::Constant* m = isaConstant(ti->llvmValue); |
280 assert(m); | 280 assert(m); |
281 if (ti->llvmValue->getType() != llvm::PointerType::get(vartype)) | 281 if (ti->llvmValue->getType() != getPtrToType(vartype)) |
282 m = llvm::ConstantExpr::getBitCast(m, vartype); | 282 m = llvm::ConstantExpr::getBitCast(m, vartype); |
283 return m; | 283 return m; |
284 } | 284 } |
285 assert(0 && "Unsupported const VarExp kind"); | 285 assert(0 && "Unsupported const VarExp kind"); |
286 return NULL; | 286 return NULL; |
401 | 401 |
402 Type* dtype = DtoDType(type); | 402 Type* dtype = DtoDType(type); |
403 Type* cty = DtoDType(dtype->next); | 403 Type* cty = DtoDType(dtype->next); |
404 | 404 |
405 const llvm::Type* ct = DtoType(cty); | 405 const llvm::Type* ct = DtoType(cty); |
406 if (ct == llvm::Type::VoidTy) | |
407 ct = llvm::Type::Int8Ty; | |
406 //printf("ct = %s\n", type->next->toChars()); | 408 //printf("ct = %s\n", type->next->toChars()); |
407 const llvm::ArrayType* at = llvm::ArrayType::get(ct,len+1); | 409 const llvm::ArrayType* at = llvm::ArrayType::get(ct,len+1); |
408 | 410 |
409 llvm::Constant* _init; | 411 llvm::Constant* _init; |
410 if (cty->ty == Tchar) { | 412 if (cty->ty == Tchar || cty->ty == Tvoid) { |
411 uint8_t* str = (uint8_t*)string; | 413 uint8_t* str = (uint8_t*)string; |
412 std::string cont((char*)str, len); | 414 std::string cont((char*)str, len); |
413 _init = llvm::ConstantArray::get(cont,true); | 415 _init = llvm::ConstantArray::get(cont,true); |
414 } | 416 } |
415 else if (cty->ty == Twchar) { | 417 else if (cty->ty == Twchar) { |
432 } | 434 } |
433 else | 435 else |
434 assert(0); | 436 assert(0); |
435 | 437 |
436 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage; | 438 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage; |
439 Logger::cout() << "type: " << *at << "\ninit: " << *_init << '\n'; | |
437 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,"stringliteral",gIR->module); | 440 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,"stringliteral",gIR->module); |
438 | 441 |
439 llvm::ConstantInt* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | 442 llvm::ConstantInt* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); |
440 llvm::Constant* idxs[2] = { zero, zero }; | 443 llvm::Constant* idxs[2] = { zero, zero }; |
441 llvm::Constant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2); | 444 llvm::Constant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2); |
459 } | 462 } |
460 } | 463 } |
461 assert(0); | 464 assert(0); |
462 } | 465 } |
463 else if (dtype->ty == Tsarray) { | 466 else if (dtype->ty == Tsarray) { |
464 const llvm::Type* dstType = llvm::PointerType::get(llvm::ArrayType::get(ct, len)); | 467 const llvm::Type* dstType = getPtrToType(llvm::ArrayType::get(ct, len)); |
465 llvm::Value* emem = (gvar->getType() == dstType) ? gvar : DtoBitCast(gvar, dstType); | 468 llvm::Value* emem = (gvar->getType() == dstType) ? gvar : DtoBitCast(gvar, dstType); |
466 return new DVarValue(type, emem, true); | 469 return new DVarValue(type, emem, true); |
467 } | 470 } |
468 else if (dtype->ty == Tpointer) { | 471 else if (dtype->ty == Tpointer) { |
469 return new DImValue(type, arrptr); | 472 return new DImValue(type, arrptr); |
875 Expression* exp = (Expression*)arguments->data[0]; | 878 Expression* exp = (Expression*)arguments->data[0]; |
876 DValue* expelem = exp->toElem(p); | 879 DValue* expelem = exp->toElem(p); |
877 Type* t = DtoDType(type); | 880 Type* t = DtoDType(type); |
878 const llvm::Type* llt = DtoType(type); | 881 const llvm::Type* llt = DtoType(type); |
879 if (DtoIsPassedByRef(t)) | 882 if (DtoIsPassedByRef(t)) |
880 llt = llvm::PointerType::get(llt); | 883 llt = getPtrToType(llt); |
881 // TODO | 884 // TODO |
882 if (strcmp(global.params.llvmArch, "x86") != 0) { | 885 if (strcmp(global.params.llvmArch, "x86") != 0) { |
883 warning("%s: va_arg for C variadic functions is broken for anything but x86", loc.toChars()); | 886 warning("%s: va_arg for C variadic functions is broken for anything but x86", loc.toChars()); |
884 } | 887 } |
885 return new DImValue(type, p->ir->CreateVAArg(expelem->getLVal(),llt,"tmp")); | 888 return new DImValue(type, p->ir->CreateVAArg(expelem->getLVal(),llt,"tmp")); |
970 else { | 973 else { |
971 llargs[j] = new llvm::AllocaInst(argiter->get()->getContainedType(0),"rettmp",p->topallocapoint()); | 974 llargs[j] = new llvm::AllocaInst(argiter->get()->getContainedType(0),"rettmp",p->topallocapoint()); |
972 } | 975 } |
973 | 976 |
974 if (dfn && dfn->func && dfn->func->llvmRunTimeHack) { | 977 if (dfn && dfn->func && dfn->func->llvmRunTimeHack) { |
975 const llvm::Type* rettype = llvm::PointerType::get(DtoType(type)); | 978 const llvm::Type* rettype = getPtrToType(DtoType(type)); |
976 if (llargs[j]->getType() != llfnty->getParamType(j)) { | 979 if (llargs[j]->getType() != llfnty->getParamType(j)) { |
977 Logger::println("llvmRunTimeHack==true - force casting return value param"); | 980 Logger::println("llvmRunTimeHack==true - force casting return value param"); |
978 Logger::cout() << "casting: " << *llargs[j] << " to type: " << *llfnty->getParamType(j) << '\n'; | 981 Logger::cout() << "casting: " << *llargs[j] << " to type: " << *llfnty->getParamType(j) << '\n'; |
979 llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j)); | 982 llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j)); |
980 } | 983 } |
984 ++argiter; | 987 ++argiter; |
985 } | 988 } |
986 | 989 |
987 // this arguments | 990 // this arguments |
988 if (dfn && dfn->vthis) { | 991 if (dfn && dfn->vthis) { |
989 Logger::println("This Call"); | 992 Logger::cout() << "This Call func val:" << *funcval << '\n'; |
990 if (dfn->vthis->getType() != argiter->get()) { | 993 if (dfn->vthis->getType() != argiter->get()) { |
991 //Logger::cout() << *fn->thisparam << '|' << *argiter->get() << '\n'; | 994 //Logger::cout() << "value: " << *dfn->vthis << " totype: " << *argiter->get() << '\n'; |
992 llargs[j] = DtoBitCast(dfn->vthis, argiter->get()); | 995 llargs[j] = DtoBitCast(dfn->vthis, argiter->get()); |
993 } | 996 } |
994 else { | 997 else { |
995 llargs[j] = dfn->vthis; | 998 llargs[j] = dfn->vthis; |
996 } | 999 } |
1008 // nested call | 1011 // nested call |
1009 else if (dfn && dfn->func && dfn->func->isNested()) { | 1012 else if (dfn && dfn->func && dfn->func->isNested()) { |
1010 Logger::println("Nested Call"); | 1013 Logger::println("Nested Call"); |
1011 llvm::Value* contextptr = DtoNestedContext(dfn->func->toParent2()->isFuncDeclaration()); | 1014 llvm::Value* contextptr = DtoNestedContext(dfn->func->toParent2()->isFuncDeclaration()); |
1012 if (!contextptr) | 1015 if (!contextptr) |
1013 contextptr = llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)); | 1016 contextptr = llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)); |
1014 llargs[j] = DtoBitCast(contextptr, llvm::PointerType::get(llvm::Type::Int8Ty)); | 1017 llargs[j] = DtoBitCast(contextptr, getPtrToType(llvm::Type::Int8Ty)); |
1015 ++j; | 1018 ++j; |
1016 ++argiter; | 1019 ++argiter; |
1017 } | 1020 } |
1018 | 1021 |
1019 // va arg function special argument passing | 1022 // va arg function special argument passing |
1023 for (int i=0; i<n; i++,j++) | 1026 for (int i=0; i<n; i++,j++) |
1024 { | 1027 { |
1025 Argument* fnarg = Argument::getNth(tf->parameters, i); | 1028 Argument* fnarg = Argument::getNth(tf->parameters, i); |
1026 Expression* exp = (Expression*)arguments->data[i]; | 1029 Expression* exp = (Expression*)arguments->data[i]; |
1027 DValue* expelem = exp->toElem(p); | 1030 DValue* expelem = exp->toElem(p); |
1028 llargs[j] = DtoBitCast(expelem->getLVal(), llvm::PointerType::get(llvm::Type::Int8Ty)); | 1031 llargs[j] = DtoBitCast(expelem->getLVal(), getPtrToType(llvm::Type::Int8Ty)); |
1029 } | 1032 } |
1030 } | 1033 } |
1031 // regular arguments | 1034 // regular arguments |
1032 else | 1035 else |
1033 { | 1036 { |
1060 DtoVariadicArgument(argexp, DtoGEPi(mem,0,i,"tmp")); | 1063 DtoVariadicArgument(argexp, DtoGEPi(mem,0,i,"tmp")); |
1061 } | 1064 } |
1062 | 1065 |
1063 // build type info array | 1066 // build type info array |
1064 assert(Type::typeinfo->llvmConstInit); | 1067 assert(Type::typeinfo->llvmConstInit); |
1065 const llvm::Type* typeinfotype = llvm::PointerType::get(Type::typeinfo->llvmConstInit->getType()); | 1068 const llvm::Type* typeinfotype = getPtrToType(Type::typeinfo->llvmConstInit->getType()); |
1066 Logger::cout() << "typeinfo ptr type: " << *typeinfotype << '\n'; | 1069 Logger::cout() << "typeinfo ptr type: " << *typeinfotype << '\n'; |
1067 const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements()); | 1070 const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements()); |
1068 | 1071 |
1069 llvm::Value* typeinfomem = new llvm::AllocaInst(typeinfoarraytype,"_arguments_storage",p->topallocapoint()); | 1072 llvm::Value* typeinfomem = new llvm::AllocaInst(typeinfoarraytype,"_arguments_storage",p->topallocapoint()); |
1070 for (int i=0; i<arguments->dim; i++) | 1073 for (int i=0; i<arguments->dim; i++) |
1079 } | 1082 } |
1080 | 1083 |
1081 // put data in d-array | 1084 // put data in d-array |
1082 llvm::Value* typeinfoarrayparam = new llvm::AllocaInst(llfnty->getParamType(j)->getContainedType(0),"_arguments_array",p->topallocapoint()); | 1085 llvm::Value* typeinfoarrayparam = new llvm::AllocaInst(llfnty->getParamType(j)->getContainedType(0),"_arguments_array",p->topallocapoint()); |
1083 p->ir->CreateStore(DtoConstSize_t(vtype->getNumElements()), DtoGEPi(typeinfoarrayparam,0,0,"tmp")); | 1086 p->ir->CreateStore(DtoConstSize_t(vtype->getNumElements()), DtoGEPi(typeinfoarrayparam,0,0,"tmp")); |
1084 llvm::Value* casttypeinfomem = p->ir->CreateBitCast(typeinfomem, llvm::PointerType::get(typeinfotype), "tmp"); | 1087 llvm::Value* casttypeinfomem = p->ir->CreateBitCast(typeinfomem, getPtrToType(typeinfotype), "tmp"); |
1085 p->ir->CreateStore(casttypeinfomem, DtoGEPi(typeinfoarrayparam,0,1,"tmp")); | 1088 p->ir->CreateStore(casttypeinfomem, DtoGEPi(typeinfoarrayparam,0,1,"tmp")); |
1086 | 1089 |
1087 // specify arguments | 1090 // specify arguments |
1088 llargs[j] = typeinfoarrayparam;; | 1091 llargs[j] = typeinfoarrayparam;; |
1089 j++; | 1092 j++; |
1090 llargs[j] = p->ir->CreateBitCast(mem, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp"); | 1093 llargs[j] = p->ir->CreateBitCast(mem, getPtrToType(llvm::Type::Int8Ty), "tmp"); |
1091 j++; | 1094 j++; |
1092 llargs.resize(nimplicit+2); | 1095 llargs.resize(nimplicit+2); |
1093 } | 1096 } |
1094 // normal function | 1097 // normal function |
1095 else { | 1098 else { |
1126 // void returns cannot not be named | 1129 // void returns cannot not be named |
1127 const char* varname = ""; | 1130 const char* varname = ""; |
1128 if (llfnty->getReturnType() != llvm::Type::VoidTy) | 1131 if (llfnty->getReturnType() != llvm::Type::VoidTy) |
1129 varname = "tmp"; | 1132 varname = "tmp"; |
1130 | 1133 |
1131 Logger::cout() << "Calling: " << *funcval << '\n'; | 1134 //Logger::cout() << "Calling: " << *funcval << '\n'; |
1132 | 1135 |
1133 // call the function | 1136 // call the function |
1134 llvm::CallInst* call = new llvm::CallInst(funcval, llargs.begin(), llargs.end(), varname, p->scopebb()); | 1137 llvm::CallInst* call = new llvm::CallInst(funcval, llargs.begin(), llargs.end(), varname, p->scopebb()); |
1135 llvm::Value* retllval = (retinptr) ? llargs[0] : call; | 1138 llvm::Value* retllval = (retinptr) ? llargs[0] : call; |
1136 | 1139 |
1137 if (retinptr && dfn && dfn->func && dfn->func->llvmRunTimeHack) { | 1140 if (retinptr && dfn && dfn->func && dfn->func->llvmRunTimeHack) { |
1138 const llvm::Type* rettype = llvm::PointerType::get(DtoType(type)); | 1141 const llvm::Type* rettype = getPtrToType(DtoType(type)); |
1139 if (retllval->getType() != rettype) { | 1142 if (retllval->getType() != rettype) { |
1140 Logger::println("llvmRunTimeHack==true - force casting return value"); | 1143 Logger::println("llvmRunTimeHack==true - force casting return value"); |
1141 Logger::cout() << "from: " << *retllval->getType() << " to: " << *rettype << '\n'; | 1144 Logger::cout() << "from: " << *retllval->getType() << " to: " << *rettype << '\n'; |
1142 retllval = DtoBitCast(retllval, rettype); | 1145 retllval = DtoBitCast(retllval, rettype); |
1143 } | 1146 } |
1241 if (offset == 0) { | 1244 if (offset == 0) { |
1242 varmem = llvalue; | 1245 varmem = llvalue; |
1243 } | 1246 } |
1244 else { | 1247 else { |
1245 const llvm::Type* elemtype = llvalue->getType()->getContainedType(0)->getContainedType(0); | 1248 const llvm::Type* elemtype = llvalue->getType()->getContainedType(0)->getContainedType(0); |
1246 size_t elemsz = gTargetData->getTypeSize(elemtype); | 1249 size_t elemsz = getABITypeSize(elemtype); |
1247 varmem = DtoGEPi(llvalue, 0, offset / elemsz, "tmp"); | 1250 varmem = DtoGEPi(llvalue, 0, offset / elemsz, "tmp"); |
1248 } | 1251 } |
1249 } | 1252 } |
1250 else if (offset == 0) { | 1253 else if (offset == 0) { |
1251 Logger::println("normal symoff"); | 1254 Logger::println("normal symoff"); |
1386 } | 1389 } |
1387 llvm::Value* vthis = l->getRVal(); | 1390 llvm::Value* vthis = l->getRVal(); |
1388 if (!vthis2) vthis2 = vthis; | 1391 if (!vthis2) vthis2 = vthis; |
1389 //unsigned cc = (unsigned)-1; | 1392 //unsigned cc = (unsigned)-1; |
1390 | 1393 |
1391 // virtual call | 1394 // super call |
1392 if (!fdecl->isFinal() && fdecl->isVirtual()) { | 1395 if (e1->op == TOKsuper) { |
1396 DtoForceDeclareDsymbol(fdecl); | |
1397 funcval = fdecl->llvmValue; | |
1398 assert(funcval); | |
1399 } | |
1400 // normal virtual call | |
1401 else if (fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual())) { | |
1393 assert(fdecl->vtblIndex > 0); | 1402 assert(fdecl->vtblIndex > 0); |
1394 assert(e1type->ty == Tclass); | 1403 assert(e1type->ty == Tclass); |
1395 | 1404 |
1396 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | 1405 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); |
1397 llvm::Value* vtblidx = llvm::ConstantInt::get(llvm::Type::Int32Ty, (size_t)fdecl->vtblIndex, false); | 1406 llvm::Value* vtblidx = llvm::ConstantInt::get(llvm::Type::Int32Ty, (size_t)fdecl->vtblIndex, false); |
1426 { | 1435 { |
1427 Logger::print("ThisExp::toElem: %s | %s\n", toChars(), type->toChars()); | 1436 Logger::print("ThisExp::toElem: %s | %s\n", toChars(), type->toChars()); |
1428 LOG_SCOPE; | 1437 LOG_SCOPE; |
1429 | 1438 |
1430 if (VarDeclaration* vd = var->isVarDeclaration()) { | 1439 if (VarDeclaration* vd = var->isVarDeclaration()) { |
1431 llvm::Value* v = p->func()->decl->llvmThisVar; | 1440 llvm::Value* v; |
1441 v = p->func()->decl->llvmThisVar; | |
1432 if (llvm::isa<llvm::AllocaInst>(v)) | 1442 if (llvm::isa<llvm::AllocaInst>(v)) |
1433 v = new llvm::LoadInst(v, "tmp", p->scopebb()); | 1443 v = new llvm::LoadInst(v, "tmp", p->scopebb()); |
1434 return new DThisValue(vd, v); | 1444 return new DThisValue(vd, v); |
1435 } | 1445 } |
1436 | 1446 |
1816 post = new llvm::GetElementPtrInst(val, whichone, "tmp", p->scopebb()); | 1826 post = new llvm::GetElementPtrInst(val, whichone, "tmp", p->scopebb()); |
1817 } | 1827 } |
1818 else if (e1type->isfloating()) | 1828 else if (e1type->isfloating()) |
1819 { | 1829 { |
1820 assert(e2type->isfloating()); | 1830 assert(e2type->isfloating()); |
1821 llvm::Value* one = llvm::ConstantFP::get(val->getType(), 1.0f); | 1831 llvm::Value* one = llvm::ConstantFP::get(val->getType(), llvm::APFloat(1.0f)); |
1822 if (op == TOKplusplus) { | 1832 if (op == TOKplusplus) { |
1823 post = llvm::BinaryOperator::createAdd(val,one,"tmp",p->scopebb()); | 1833 post = llvm::BinaryOperator::createAdd(val,one,"tmp",p->scopebb()); |
1824 } | 1834 } |
1825 else if (op == TOKminusminus) { | 1835 else if (op == TOKminusminus) { |
1826 post = llvm::BinaryOperator::createSub(val,one,"tmp",p->scopebb()); | 1836 post = llvm::BinaryOperator::createSub(val,one,"tmp",p->scopebb()); |
1845 assert(newtype); | 1855 assert(newtype); |
1846 assert(!allocator && "custom allocators not yet supported"); | 1856 assert(!allocator && "custom allocators not yet supported"); |
1847 | 1857 |
1848 Type* ntype = DtoDType(newtype); | 1858 Type* ntype = DtoDType(newtype); |
1849 | 1859 |
1860 if (ntype->ty == Tclass) { | |
1861 return DtoNewClass((TypeClass*)ntype, this); | |
1862 } | |
1863 | |
1850 const llvm::Type* t = DtoType(ntype); | 1864 const llvm::Type* t = DtoType(ntype); |
1851 | 1865 |
1852 llvm::Value* emem = 0; | 1866 llvm::Value* emem = 0; |
1853 bool inplace = false; | 1867 bool inplace = false; |
1854 | 1868 |
1855 { | 1869 if (ntype->ty == Tarray) { |
1856 Logger::println("Allocating memory"); | 1870 assert(arguments); |
1857 LOG_SCOPE; | 1871 if (arguments->dim == 1) { |
1858 if (onstack) { | 1872 DValue* sz = ((Expression*)arguments->data[0])->toElem(p); |
1859 assert(ntype->ty == Tclass); | 1873 llvm::Value* dimval = sz->getRVal(); |
1860 emem = new llvm::AllocaInst(t->getContainedType(0),"tmp",p->topallocapoint()); | 1874 Type* nnt = DtoDType(ntype->next); |
1861 } | 1875 if (nnt->ty == Tvoid) |
1862 else if (ntype->ty == Tclass) { | 1876 nnt = Type::tint8; |
1863 emem = new llvm::MallocInst(t->getContainedType(0),"tmp",p->scopebb()); | 1877 |
1864 } | 1878 if (p->topexp() && p->topexp()->e2 == this) { |
1865 else if (ntype->ty == Tarray) { | 1879 assert(p->topexp()->v); |
1866 assert(arguments); | 1880 emem = p->topexp()->v->getLVal(); |
1867 if (arguments->dim == 1) { | 1881 DtoNewDynArray(emem, dimval, nnt); |
1868 DValue* sz = ((Expression*)arguments->data[0])->toElem(p); | 1882 inplace = true; |
1869 llvm::Value* dimval = sz->getRVal(); | |
1870 Type* nnt = DtoDType(ntype->next); | |
1871 if (nnt->ty == Tvoid) | |
1872 nnt = Type::tint8; | |
1873 | |
1874 if (p->topexp() && p->topexp()->e2 == this) { | |
1875 assert(p->topexp()->v); | |
1876 emem = p->topexp()->v->getLVal(); | |
1877 DtoNewDynArray(emem, dimval, nnt); | |
1878 inplace = true; | |
1879 } | |
1880 else { | |
1881 const llvm::Type* restype = DtoType(type); | |
1882 Logger::cout() << "restype = " << *restype << '\n'; | |
1883 emem = new llvm::AllocaInst(restype,"newstorage",p->topallocapoint()); | |
1884 DtoNewDynArray(emem, dimval, nnt); | |
1885 return new DVarValue(newtype, emem, true); | |
1886 } | |
1887 } | 1883 } |
1888 else { | 1884 else { |
1889 assert(0 && "num args to 'new' != 1"); | 1885 const llvm::Type* restype = DtoType(type); |
1886 Logger::cout() << "restype = " << *restype << '\n'; | |
1887 emem = new llvm::AllocaInst(restype,"newstorage",p->topallocapoint()); | |
1888 DtoNewDynArray(emem, dimval, nnt); | |
1889 return new DVarValue(newtype, emem, true); | |
1890 } | 1890 } |
1891 } | 1891 } |
1892 else { | 1892 else { |
1893 emem = new llvm::MallocInst(t,"tmp",p->scopebb()); | 1893 assert(0 && "num args to 'new' != 1"); |
1894 } | 1894 } |
1895 } | 1895 } |
1896 | 1896 else { |
1897 if (ntype->ty == Tclass) { | 1897 emem = new llvm::MallocInst(t,"tmp",p->scopebb()); |
1898 // first apply the static initializer | 1898 } |
1899 TypeClass* tc = (TypeClass*)ntype; | 1899 |
1900 DtoInitClass(tc, emem); | 1900 if (ntype->ty == Tstruct) { |
1901 | |
1902 // set the this var for nested classes | |
1903 if (thisexp) { | |
1904 Logger::println("Resolving 'this' expression"); | |
1905 LOG_SCOPE; | |
1906 DValue* thisval = thisexp->toElem(p); | |
1907 size_t idx = 2; | |
1908 idx += tc->sym->llvmIRStruct->interfaces.size(); | |
1909 llvm::Value* dst = thisval->getRVal(); | |
1910 llvm::Value* src = DtoGEPi(emem,0,idx,"tmp"); | |
1911 Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n'; | |
1912 DtoStore(dst, src); | |
1913 } | |
1914 else if (tc->sym->isNested()) | |
1915 { | |
1916 Logger::println("Resolving nested context"); | |
1917 LOG_SCOPE; | |
1918 size_t idx = 2; | |
1919 idx += tc->sym->llvmIRStruct->interfaces.size(); | |
1920 llvm::Value* nest = p->func()->decl->llvmNested; | |
1921 if (!nest) | |
1922 nest = p->func()->decl->llvmThisVar; | |
1923 assert(nest); | |
1924 llvm::Value* gep = DtoGEPi(emem,0,idx,"tmp"); | |
1925 nest = DtoBitCast(nest, gep->getType()->getContainedType(0)); | |
1926 DtoStore(nest, gep); | |
1927 } | |
1928 | |
1929 // then call constructor | |
1930 if (arguments) { | |
1931 Logger::println("Calling constructor"); | |
1932 LOG_SCOPE; | |
1933 assert(member); | |
1934 assert(member->llvmValue); | |
1935 llvm::Function* fn = llvm::cast<llvm::Function>(member->llvmValue); | |
1936 TypeFunction* tf = (TypeFunction*)DtoDType(member->type); | |
1937 | |
1938 std::vector<llvm::Value*> ctorargs; | |
1939 ctorargs.push_back(emem); | |
1940 for (size_t i=0; i<arguments->dim; ++i) | |
1941 { | |
1942 Expression* ex = (Expression*)arguments->data[i]; | |
1943 Argument* fnarg = Argument::getNth(tf->parameters, i); | |
1944 DValue* argval = DtoArgument(fnarg, ex); | |
1945 llvm::Value* a = argval->getRVal(); | |
1946 const llvm::Type* aty = fn->getFunctionType()->getParamType(i+1); | |
1947 if (a->getType() != aty) // this param might have type mismatch | |
1948 a = DtoBitCast(a, aty); | |
1949 ctorargs.push_back(a); | |
1950 } | |
1951 llvm::CallInst* call = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb()); | |
1952 call->setCallingConv(DtoCallingConv(LINKd)); | |
1953 emem = call; | |
1954 } | |
1955 } | |
1956 else if (ntype->ty == Tstruct) { | |
1957 TypeStruct* ts = (TypeStruct*)ntype; | 1901 TypeStruct* ts = (TypeStruct*)ntype; |
1958 if (ts->isZeroInit()) { | 1902 if (ts->isZeroInit()) { |
1959 DtoStructZeroInit(emem); | 1903 DtoStructZeroInit(emem); |
1960 } | 1904 } |
1961 else { | 1905 else { |
2051 DValue* AssertExp::toElem(IRState* p) | 1995 DValue* AssertExp::toElem(IRState* p) |
2052 { | 1996 { |
2053 Logger::print("AssertExp::toElem: %s | %s\n", toChars(), type->toChars()); | 1997 Logger::print("AssertExp::toElem: %s | %s\n", toChars(), type->toChars()); |
2054 LOG_SCOPE; | 1998 LOG_SCOPE; |
2055 | 1999 |
2056 DValue* u = e1->toElem(p); | 2000 // condition |
2057 DValue* m = msg ? msg->toElem(p) : NULL; | 2001 DValue* cond = e1->toElem(p); |
2058 | 2002 |
2059 DtoAssert(u->getRVal(), &loc, m); | 2003 // create basic blocks |
2060 | 2004 llvm::BasicBlock* oldend = p->scopeend(); |
2061 return 0; | 2005 llvm::BasicBlock* assertbb = new llvm::BasicBlock("assert", p->topfunc(), oldend); |
2006 llvm::BasicBlock* endbb = new llvm::BasicBlock("endassert", p->topfunc(), oldend); | |
2007 | |
2008 // test condition | |
2009 llvm::Value* condval = cond->getRVal(); | |
2010 condval = DtoBoolean(condval); | |
2011 | |
2012 // branch | |
2013 new llvm::BranchInst(endbb, assertbb, condval, p->scopebb()); | |
2014 | |
2015 // call assert runtime functions | |
2016 p->scope() = IRScope(assertbb,endbb); | |
2017 DtoAssert(&loc, msg ? msg->toElem(p) : NULL); | |
2018 | |
2019 if (!gIR->scopereturned()) | |
2020 new llvm::BranchInst(endbb, p->scopebb()); | |
2021 | |
2022 // rewrite the scope | |
2023 p->scope() = IRScope(endbb,oldend); | |
2024 | |
2025 // no meaningful return value | |
2026 return NULL; | |
2062 } | 2027 } |
2063 | 2028 |
2064 ////////////////////////////////////////////////////////////////////////////////////////// | 2029 ////////////////////////////////////////////////////////////////////////////////////////// |
2065 | 2030 |
2066 DValue* NotExp::toElem(IRState* p) | 2031 DValue* NotExp::toElem(IRState* p) |
2190 DValue* HaltExp::toElem(IRState* p) | 2155 DValue* HaltExp::toElem(IRState* p) |
2191 { | 2156 { |
2192 Logger::print("HaltExp::toElem: %s | %s\n", toChars(), type->toChars()); | 2157 Logger::print("HaltExp::toElem: %s | %s\n", toChars(), type->toChars()); |
2193 LOG_SCOPE; | 2158 LOG_SCOPE; |
2194 | 2159 |
2195 DtoAssert(DtoConstBool(false), &loc, NULL); | 2160 DtoAssert(&loc, NULL); |
2196 | 2161 |
2197 new llvm::UnreachableInst(p->scopebb()); | 2162 new llvm::UnreachableInst(p->scopebb()); |
2198 return 0; | 2163 return 0; |
2199 } | 2164 } |
2200 | 2165 |
2205 Logger::print("DelegateExp::toElem: %s | %s\n", toChars(), type->toChars()); | 2170 Logger::print("DelegateExp::toElem: %s | %s\n", toChars(), type->toChars()); |
2206 LOG_SCOPE; | 2171 LOG_SCOPE; |
2207 | 2172 |
2208 DValue* u = e1->toElem(p); | 2173 DValue* u = e1->toElem(p); |
2209 | 2174 |
2210 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | 2175 const llvm::PointerType* int8ptrty = getPtrToType(llvm::Type::Int8Ty); |
2211 llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); | |
2212 | |
2213 const llvm::Type* int8ptrty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
2214 | 2176 |
2215 llvm::Value* lval; | 2177 llvm::Value* lval; |
2216 if (p->topexp() && p->topexp()->e2 == this) { | 2178 if (p->topexp() && p->topexp()->e2 == this) { |
2217 assert(p->topexp()->v); | 2179 assert(p->topexp()->v); |
2218 lval = p->topexp()->v->getLVal(); | 2180 lval = p->topexp()->v->getLVal(); |
2227 //uval = f->vthis; | 2189 //uval = f->vthis; |
2228 llvm::Value* nestvar = p->func()->decl->llvmNested; | 2190 llvm::Value* nestvar = p->func()->decl->llvmNested; |
2229 if (nestvar) | 2191 if (nestvar) |
2230 uval = nestvar; | 2192 uval = nestvar; |
2231 else | 2193 else |
2232 uval = llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)); | 2194 uval = llvm::ConstantPointerNull::get(int8ptrty); |
2233 } | 2195 } |
2234 else { | 2196 else { |
2235 uval = u->getRVal(); | 2197 uval = u->getRVal(); |
2236 } | 2198 } |
2237 | 2199 |
2238 llvm::Value* context = DtoGEP(lval,zero,zero,"tmp",p->scopebb()); | 2200 llvm::Value* context = DtoGEPi(lval,0,0,"tmp"); |
2239 llvm::Value* castcontext = DtoBitCast(uval,int8ptrty); | 2201 llvm::Value* castcontext = DtoBitCast(uval, int8ptrty); |
2240 new llvm::StoreInst(castcontext, context, p->scopebb()); | 2202 DtoStore(castcontext, context); |
2241 | 2203 |
2242 llvm::Value* fptr = DtoGEP(lval,zero,one,"tmp",p->scopebb()); | 2204 llvm::Value* fptr = DtoGEPi(lval,0,1,"tmp"); |
2243 | 2205 |
2244 assert(func->llvmValue); | 2206 Logger::println("func: '%s'", func->toPrettyChars()); |
2245 llvm::Value* castfptr = DtoBitCast(func->llvmValue,fptr->getType()->getContainedType(0)); | 2207 |
2246 new llvm::StoreInst(castfptr, fptr, p->scopebb()); | 2208 llvm::Value* castfptr; |
2209 if (func->isVirtual()) | |
2210 castfptr = DtoVirtualFunctionPointer(u, func); | |
2211 else if (func->isAbstract()) | |
2212 assert(0 && "TODO delegate to abstract method"); | |
2213 else if (func->toParent()->isInterfaceDeclaration()) | |
2214 assert(0 && "TODO delegate to interface method"); | |
2215 else | |
2216 castfptr = func->llvmValue; | |
2217 | |
2218 castfptr = DtoBitCast(castfptr, fptr->getType()->getContainedType(0)); | |
2219 DtoStore(castfptr, fptr); | |
2247 | 2220 |
2248 return new DVarValue(type, lval, true); | 2221 return new DVarValue(type, lval, true); |
2249 } | 2222 } |
2250 | 2223 |
2251 ////////////////////////////////////////////////////////////////////////////////////////// | 2224 ////////////////////////////////////////////////////////////////////////////////////////// |
2277 else { | 2250 else { |
2278 llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE; | 2251 llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE; |
2279 if (t1->ty == Tpointer && v->isNull() && l->getType() != r->getType()) { | 2252 if (t1->ty == Tpointer && v->isNull() && l->getType() != r->getType()) { |
2280 r = llvm::ConstantPointerNull::get(isaPointer(l->getType())); | 2253 r = llvm::ConstantPointerNull::get(isaPointer(l->getType())); |
2281 } | 2254 } |
2282 Logger::cout() << "l = " << *l << " r = " << *r << '\n'; | 2255 //Logger::cout() << "l = " << *l << " r = " << *r << '\n'; |
2283 eval = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb()); | 2256 eval = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb()); |
2284 } | 2257 } |
2285 return new DImValue(type, eval); | 2258 return new DImValue(type, eval); |
2286 } | 2259 } |
2287 | 2260 |
2366 llvm::Value* zero = 0; | 2339 llvm::Value* zero = 0; |
2367 if (t->isintegral()) | 2340 if (t->isintegral()) |
2368 zero = llvm::ConstantInt::get(val->getType(), 0, true); | 2341 zero = llvm::ConstantInt::get(val->getType(), 0, true); |
2369 else if (t->isfloating()) { | 2342 else if (t->isfloating()) { |
2370 if (t->ty == Tfloat32 || t->ty == Timaginary32) | 2343 if (t->ty == Tfloat32 || t->ty == Timaginary32) |
2371 zero = llvm::ConstantFP::get(val->getType(), float(0)); | 2344 zero = llvm::ConstantFP::get(val->getType(), llvm::APFloat(0.0f)); |
2372 else if (t->ty == Tfloat64 || t->ty == Tfloat80 || t->ty == Timaginary64 || t->ty == Timaginary80) | 2345 else if (t->ty == Tfloat64 || t->ty == Tfloat80 || t->ty == Timaginary64 || t->ty == Timaginary80) |
2373 zero = llvm::ConstantFP::get(val->getType(), double(0)); | 2346 zero = llvm::ConstantFP::get(val->getType(), llvm::APFloat(0.0)); |
2374 else | 2347 else |
2375 assert(0); | 2348 assert(0); |
2376 } | 2349 } |
2377 else | 2350 else |
2378 assert(0); | 2351 assert(0); |
2617 if (!vx) continue; | 2590 if (!vx) continue; |
2618 tys.push_back(DtoType(vx->type)); | 2591 tys.push_back(DtoType(vx->type)); |
2619 } | 2592 } |
2620 const llvm::StructType* t = llvm::StructType::get(tys); | 2593 const llvm::StructType* t = llvm::StructType::get(tys); |
2621 if (t != llt) { | 2594 if (t != llt) { |
2622 if (gTargetData->getTypeSize(t) != gTargetData->getTypeSize(llt)) { | 2595 if (getABITypeSize(t) != getABITypeSize(llt)) { |
2623 Logger::cout() << "got size " << gTargetData->getTypeSize(t) << ", expected " << gTargetData->getTypeSize(llt) << '\n'; | 2596 Logger::cout() << "got size " << getABITypeSize(t) << ", expected " << getABITypeSize(llt) << '\n'; |
2624 assert(0 && "type size mismatch"); | 2597 assert(0 && "type size mismatch"); |
2625 } | 2598 } |
2626 sptr = p->ir->CreateBitCast(sptr, llvm::PointerType::get(t), "tmp"); | 2599 sptr = DtoBitCast(sptr, getPtrToType(t)); |
2627 Logger::cout() << "sptr type is now: " << *t << '\n'; | 2600 Logger::cout() << "sptr type is now: " << *t << '\n'; |
2628 } | 2601 } |
2629 } | 2602 } |
2630 | 2603 |
2631 // build | 2604 // build |