Mercurial > projects > ldc
comparison gen/toir.c @ 57:a9d29e9f1fed trunk
[svn r61] Added support for D-style variadic functions :)
author | lindquist |
---|---|
date | Thu, 25 Oct 2007 02:39:53 +0200 |
parents | 0ccfae271c45 |
children | 2c3cd3596187 |
comparison
equal
deleted
inserted
replaced
56:3a784f7790d6 | 57:a9d29e9f1fed |
---|---|
108 elem* e = new elem; | 108 elem* e = new elem; |
109 | 109 |
110 assert(var); | 110 assert(var); |
111 if (VarDeclaration* vd = var->isVarDeclaration()) | 111 if (VarDeclaration* vd = var->isVarDeclaration()) |
112 { | 112 { |
113 Logger::println("VarDeclaration"); | 113 Logger::println("VarDeclaration %s", vd->toChars()); |
114 | 114 |
115 if (vd->nestedref) { | 115 if (vd->nestedref) { |
116 Logger::println("has nested ref"); | 116 Logger::println("has nested ref"); |
117 } | |
118 | |
119 // _arguments | |
120 if (vd->ident == Id::_arguments) | |
121 { | |
122 vd->llvmValue = p->func().decl->llvmArguments; | |
123 assert(vd->llvmValue); | |
124 e->mem = vd->llvmValue; | |
125 e->type = elem::VAR; | |
126 return e; | |
127 } | |
128 // _argptr | |
129 else if (vd->ident == Id::_argptr) | |
130 { | |
131 vd->llvmValue = p->func().decl->llvmArgPtr; | |
132 assert(vd->llvmValue); | |
133 e->mem = vd->llvmValue; | |
134 e->type = elem::VAR; | |
135 return e; | |
117 } | 136 } |
118 | 137 |
119 // needed to take care of forward references of global variables | 138 // needed to take care of forward references of global variables |
120 if (!vd->llvmTouched && vd->isDataseg()) | 139 if (!vd->llvmTouched && vd->isDataseg()) |
121 vd->toObjFile(); | 140 vd->toObjFile(); |
145 { | 164 { |
146 assert(0); | 165 assert(0); |
147 } | 166 } |
148 // global forward ref | 167 // global forward ref |
149 else { | 168 else { |
150 Logger::println("unsupported: %s\n", vd->toChars()); | 169 Logger::println("unsupported magic: %s\n", vd->toChars()); |
151 assert(0 && "only magic supported is typeinfo"); | 170 assert(0 && "only magic supported is $, _arguments, _argptr"); |
152 } | 171 } |
153 return e; | 172 return e; |
154 } | 173 } |
155 | 174 |
156 // function parameter | 175 // function parameter |
445 | 464 |
446 ////////////////////////////////////////////////////////////////////////////////////////// | 465 ////////////////////////////////////////////////////////////////////////////////////////// |
447 | 466 |
448 elem* AssignExp::toElem(IRState* p) | 467 elem* AssignExp::toElem(IRState* p) |
449 { | 468 { |
450 Logger::print("AssignExp::toElem: %s | %s = %s\n", toChars(), e1->type->toChars(), e2->type->toChars()); | 469 Logger::print("AssignExp::toElem: %s | %s = %s\n", toChars(), e1->type->toChars(), e2->type ? e2->type->toChars() : 0); |
451 LOG_SCOPE; | 470 LOG_SCOPE; |
452 | 471 |
453 p->exps.push_back(IRExp(e1,e2,NULL)); | 472 p->exps.push_back(IRExp(e1,e2,NULL)); |
454 | 473 |
455 elem* l = e1->toElem(p); | 474 elem* l = e1->toElem(p); |
1044 size_t n = arguments->dim; | 1063 size_t n = arguments->dim; |
1045 if (fn->funcdecl && fn->funcdecl->llvmInternal == LLVMva_start) | 1064 if (fn->funcdecl && fn->funcdecl->llvmInternal == LLVMva_start) |
1046 n = 1; | 1065 n = 1; |
1047 if (fn->arg || delegateCall) n++; | 1066 if (fn->arg || delegateCall) n++; |
1048 if (retinptr) n++; | 1067 if (retinptr) n++; |
1068 if (tf->linkage == LINKd && tf->varargs == 1) n+=2; | |
1049 | 1069 |
1050 llvm::Value* funcval = fn->getValue(); | 1070 llvm::Value* funcval = fn->getValue(); |
1051 assert(funcval != 0); | 1071 assert(funcval != 0); |
1052 std::vector<llvm::Value*> llargs(n, 0); | 1072 std::vector<llvm::Value*> llargs(n, 0); |
1053 | 1073 |
1088 //Logger::cout() << "Function LLVM type: " << *llfnty << '\n'; | 1108 //Logger::cout() << "Function LLVM type: " << *llfnty << '\n'; |
1089 | 1109 |
1090 // argument handling | 1110 // argument handling |
1091 llvm::FunctionType::param_iterator argiter = llfnty->param_begin(); | 1111 llvm::FunctionType::param_iterator argiter = llfnty->param_begin(); |
1092 int j = 0; | 1112 int j = 0; |
1093 | |
1094 Logger::println("hidden struct return"); | |
1095 | 1113 |
1096 IRExp* topexp = p->topexp(); | 1114 IRExp* topexp = p->topexp(); |
1097 | 1115 |
1098 // hidden struct return arguments | 1116 // hidden struct return arguments |
1099 if (retinptr) { | 1117 if (retinptr) { |
1116 } | 1134 } |
1117 else { | 1135 else { |
1118 e->type = elem::VAL; | 1136 e->type = elem::VAL; |
1119 } | 1137 } |
1120 | 1138 |
1121 Logger::println("this arguments"); | |
1122 | |
1123 // this arguments | 1139 // this arguments |
1124 if (fn->arg) { | 1140 if (fn->arg) { |
1125 Logger::println("This Call"); | 1141 Logger::println("This Call"); |
1126 if (fn->arg->getType() != argiter->get()) { | 1142 if (fn->arg->getType() != argiter->get()) { |
1127 //Logger::cout() << *fn->thisparam << '|' << *argiter->get() << '\n'; | 1143 //Logger::cout() << *fn->thisparam << '|' << *argiter->get() << '\n'; |
1139 llvm::Value* contextptr = LLVM_DtoGEP(fn->mem,zero,zero,"tmp",p->scopebb()); | 1155 llvm::Value* contextptr = LLVM_DtoGEP(fn->mem,zero,zero,"tmp",p->scopebb()); |
1140 llargs[j] = new llvm::LoadInst(contextptr,"tmp",p->scopebb()); | 1156 llargs[j] = new llvm::LoadInst(contextptr,"tmp",p->scopebb()); |
1141 ++j; | 1157 ++j; |
1142 ++argiter; | 1158 ++argiter; |
1143 } | 1159 } |
1144 | |
1145 Logger::println("regular arguments"); | |
1146 | 1160 |
1147 // va arg function special argument passing | 1161 // va arg function special argument passing |
1148 if (va_magic) { | 1162 if (va_magic) { |
1149 size_t n = va_intrinsic ? arguments->dim : 1; | 1163 size_t n = va_intrinsic ? arguments->dim : 1; |
1150 for (int i=0; i<n; i++,j++) | 1164 for (int i=0; i<n; i++,j++) |
1157 delete expelem; | 1171 delete expelem; |
1158 } | 1172 } |
1159 } | 1173 } |
1160 // regular arguments | 1174 // regular arguments |
1161 else { | 1175 else { |
1162 for (int i=0; i<arguments->dim; i++,j++) | 1176 if (tf->linkage == LINKd && tf->varargs == 1) |
1163 { | 1177 { |
1164 Argument* fnarg = Argument::getNth(tf->parameters, i); | 1178 Logger::println("doing d-style variadic arguments"); |
1165 llargs[j] = LLVM_DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]); | 1179 |
1180 std::vector<const llvm::Type*> vtypes; | |
1181 std::vector<llvm::Value*> vvalues; | |
1182 std::vector<llvm::Value*> vtypeinfos; | |
1183 | |
1184 for (int i=0; i<arguments->dim; i++) { | |
1185 Argument* fnarg = Argument::getNth(tf->parameters, i); | |
1186 Expression* argexp = (Expression*)arguments->data[i]; | |
1187 vvalues.push_back(LLVM_DtoArgument(NULL, fnarg, argexp)); | |
1188 vtypes.push_back(vvalues.back()->getType()); | |
1189 | |
1190 TypeInfoDeclaration* tidecl = argexp->type->getTypeInfoDeclaration(); | |
1191 tidecl->toObjFile(); | |
1192 assert(tidecl->llvmValue); | |
1193 vtypeinfos.push_back(tidecl->llvmValue); | |
1194 } | |
1195 | |
1196 const llvm::StructType* vtype = llvm::StructType::get(vtypes); | |
1197 llvm::Value* mem = new llvm::AllocaInst(vtype,"_argptr_storage",p->topallocapoint()); | |
1198 for (unsigned i=0; i<vtype->getNumElements(); ++i) | |
1199 p->ir->CreateStore(vvalues[i], LLVM_DtoGEPi(mem,0,i,"tmp")); | |
1200 | |
1201 //llvm::Constant* typeinfoparam = llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(llfnty->getParamType(j))); | |
1202 assert(Type::typeinfo->llvmInitZ); | |
1203 const llvm::Type* typeinfotype = llvm::PointerType::get(Type::typeinfo->llvmInitZ->getType()); | |
1204 Logger::cout() << "typeinfo ptr type: " << *typeinfotype << '\n'; | |
1205 const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements()); | |
1206 llvm::Value* typeinfomem = new llvm::AllocaInst(typeinfoarraytype,"_arguments_storage",p->topallocapoint()); | |
1207 for (unsigned i=0; i<vtype->getNumElements(); ++i) { | |
1208 llvm::Value* v = p->ir->CreateBitCast(vtypeinfos[i], typeinfotype, "tmp"); | |
1209 p->ir->CreateStore(v, LLVM_DtoGEPi(typeinfomem,0,i,"tmp")); | |
1210 } | |
1211 | |
1212 llvm::Value* typeinfoarrayparam = new llvm::AllocaInst(llfnty->getParamType(j)->getContainedType(0),"_arguments_array",p->topallocapoint()); | |
1213 p->ir->CreateStore(LLVM_DtoConstSize_t(vtype->getNumElements()), LLVM_DtoGEPi(typeinfoarrayparam,0,0,"tmp")); | |
1214 llvm::Value* casttypeinfomem = p->ir->CreateBitCast(typeinfomem, llvm::PointerType::get(typeinfotype), "tmp"); | |
1215 p->ir->CreateStore(casttypeinfomem, LLVM_DtoGEPi(typeinfoarrayparam,0,1,"tmp")); | |
1216 | |
1217 llargs[j] = typeinfoarrayparam;; | |
1218 j++; | |
1219 llargs[j] = p->ir->CreateBitCast(mem, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp"); | |
1220 j++; | |
1221 llargs.resize(2); | |
1222 } | |
1223 else { | |
1224 Logger::println("doing normal arguments"); | |
1225 for (int i=0; i<arguments->dim; i++,j++) { | |
1226 Argument* fnarg = Argument::getNth(tf->parameters, i); | |
1227 llargs[j] = LLVM_DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]); | |
1228 } | |
1229 Logger::println("%d params passed", n); | |
1230 for (int i=0; i<n; ++i) { | |
1231 Logger::cout() << *llargs[i] << '\n'; | |
1232 } | |
1166 } | 1233 } |
1167 } | 1234 } |
1168 | 1235 |
1169 // void returns cannot not be named | 1236 // void returns cannot not be named |
1170 const char* varname = ""; | 1237 const char* varname = ""; |
1171 if (llfnty->getReturnType() != llvm::Type::VoidTy) | 1238 if (llfnty->getReturnType() != llvm::Type::VoidTy) |
1172 varname = "tmp"; | 1239 varname = "tmp"; |
1173 | |
1174 Logger::println("%d params passed", n); | |
1175 for (int i=0; i<n; ++i) | |
1176 { | |
1177 Logger::cout() << *llargs[i] << '\n'; | |
1178 } | |
1179 | 1240 |
1180 Logger::cout() << "Calling: " << *funcval->getType() << '\n'; | 1241 Logger::cout() << "Calling: " << *funcval->getType() << '\n'; |
1181 | 1242 |
1182 // call the function | 1243 // call the function |
1183 llvm::CallInst* call = new llvm::CallInst(funcval, llargs.begin(), llargs.end(), varname, p->scopebb()); | 1244 llvm::CallInst* call = new llvm::CallInst(funcval, llargs.begin(), llargs.end(), varname, p->scopebb()); |
1340 } | 1401 } |
1341 } | 1402 } |
1342 else if (fromtype->ty == Tpointer) { | 1403 else if (fromtype->ty == Tpointer) { |
1343 if (totype->ty == Tpointer || totype->ty == Tclass) { | 1404 if (totype->ty == Tpointer || totype->ty == Tclass) { |
1344 llvm::Value* src = u->getValue(); | 1405 llvm::Value* src = u->getValue(); |
1345 //Logger::cout() << *src << '|' << *totype << '\n'; | 1406 Logger::cout() << *src << '|' << *tolltype << '\n'; |
1346 e->val = new llvm::BitCastInst(src, tolltype, "tmp", p->scopebb()); | 1407 e->val = new llvm::BitCastInst(src, tolltype, "tmp", p->scopebb()); |
1347 } | 1408 } |
1348 else if (totype->isintegral()) { | 1409 else if (totype->isintegral()) { |
1349 e->val = new llvm::PtrToIntInst(u->getValue(), tolltype, "tmp", p->scopebb()); | 1410 e->val = new llvm::PtrToIntInst(u->getValue(), tolltype, "tmp", p->scopebb()); |
1350 } | 1411 } |