Mercurial > projects > ldc
comparison gen/tollvm.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 |
---|---|
260 // type has already been resolved | 260 // type has already been resolved |
261 if (f->llvmType != 0) { | 261 if (f->llvmType != 0) { |
262 return llvm::cast<llvm::FunctionType>(f->llvmType); | 262 return llvm::cast<llvm::FunctionType>(f->llvmType); |
263 } | 263 } |
264 | 264 |
265 bool typesafeVararg = false; | |
266 if (f->linkage == LINKd && f->varargs == 1) { | |
267 assert(fdecl->v_arguments); | |
268 Logger::println("v_arguments = %s", fdecl->v_arguments->toChars()); | |
269 assert(fdecl->v_arguments->isParameter()); | |
270 typesafeVararg = true; | |
271 } | |
272 | |
265 // return value type | 273 // return value type |
266 const llvm::Type* rettype; | 274 const llvm::Type* rettype; |
267 const llvm::Type* actualRettype; | 275 const llvm::Type* actualRettype; |
268 Type* rt = f->next; | 276 Type* rt = f->next; |
269 bool retinptr = false; | 277 bool retinptr = false; |
289 } | 297 } |
290 | 298 |
291 // parameter types | 299 // parameter types |
292 std::vector<const llvm::Type*> paramvec; | 300 std::vector<const llvm::Type*> paramvec; |
293 | 301 |
294 if (fdecl->llvmInternal == LLVMva_start) { | 302 if (retinptr) { |
303 Logger::cout() << "returning through pointer parameter: " << *rettype << '\n'; | |
304 paramvec.push_back(rettype); | |
305 } | |
306 | |
307 if (fdecl->needThis()) { | |
308 if (AggregateDeclaration* ad = fdecl->isMember()) { | |
309 Logger::print("isMember = this is: %s\n", ad->type->toChars()); | |
310 const llvm::Type* thisty = LLVM_DtoType(ad->type); | |
311 Logger::cout() << "this llvm type: " << *thisty << '\n'; | |
312 if (llvm::isa<llvm::StructType>(thisty) || thisty == gIR->topstruct().recty.get()) | |
313 thisty = llvm::PointerType::get(thisty); | |
314 paramvec.push_back(thisty); | |
315 usesthis = true; | |
316 } | |
317 else | |
318 assert(0); | |
319 } | |
320 else if (fdecl->isNested()) { | |
295 paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty)); | 321 paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty)); |
296 } | 322 usesthis = true; |
297 else { | 323 } |
298 if (retinptr) { | 324 |
299 Logger::cout() << "returning through pointer parameter: " << *rettype << '\n'; | 325 if (typesafeVararg) { |
300 paramvec.push_back(rettype); | 326 ClassDeclaration* ti = Type::typeinfo; |
301 } | 327 if (!ti->llvmInitZ) |
302 | 328 ti->toObjFile(); |
303 if (fdecl->needThis()) { | 329 assert(ti->llvmInitZ); |
304 if (AggregateDeclaration* ad = fdecl->isMember()) { | 330 std::vector<const llvm::Type*> types; |
305 Logger::print("isMember = this is: %s\n", ad->type->toChars()); | 331 types.push_back(LLVM_DtoSize_t()); |
306 const llvm::Type* thisty = LLVM_DtoType(ad->type); | 332 types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmInitZ->getType()))); |
307 Logger::cout() << "this llvm type: " << *thisty << '\n'; | 333 const llvm::Type* t1 = llvm::StructType::get(types); |
308 if (llvm::isa<llvm::StructType>(thisty) || thisty == gIR->topstruct().recty.get()) | 334 paramvec.push_back(llvm::PointerType::get(t1)); |
309 thisty = llvm::PointerType::get(thisty); | 335 paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty)); |
310 paramvec.push_back(thisty); | 336 } |
311 usesthis = true; | 337 |
312 } | 338 size_t n = Argument::dim(f->parameters); |
339 | |
340 for (int i=0; i < n; ++i) { | |
341 Argument* arg = Argument::getNth(f->parameters, i); | |
342 // ensure scalar | |
343 Type* argT = LLVM_DtoDType(arg->type); | |
344 assert(argT); | |
345 | |
346 if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) { | |
347 //assert(arg->vardecl); | |
348 //arg->vardecl->refparam = true; | |
349 } | |
350 else | |
351 arg->llvmCopy = true; | |
352 | |
353 const llvm::Type* at = LLVM_DtoType(argT); | |
354 if (llvm::isa<llvm::StructType>(at)) { | |
355 Logger::println("struct param"); | |
356 paramvec.push_back(llvm::PointerType::get(at)); | |
357 } | |
358 else if (llvm::isa<llvm::ArrayType>(at)) { | |
359 Logger::println("sarray param"); | |
360 assert(argT->ty == Tsarray); | |
361 //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0))); | |
362 paramvec.push_back(llvm::PointerType::get(at)); | |
363 } | |
364 else if (llvm::isa<llvm::OpaqueType>(at)) { | |
365 Logger::println("opaque param"); | |
366 if (argT->ty == Tstruct || argT->ty == Tclass) | |
367 paramvec.push_back(llvm::PointerType::get(at)); | |
313 else | 368 else |
314 assert(0); | 369 assert(0); |
315 } | 370 } |
316 else if (fdecl->isNested()) { | 371 /*if (llvm::isa<llvm::StructType>(at) || argT->ty == Tstruct || argT->ty == Tsarray) { |
317 paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty)); | 372 paramvec.push_back(llvm::PointerType::get(at)); |
318 usesthis = true; | 373 }*/ |
319 } | 374 else { |
320 | 375 if (!arg->llvmCopy) { |
321 size_t n = Argument::dim(f->parameters); | 376 Logger::println("ref param"); |
322 | 377 at = llvm::PointerType::get(at); |
323 for (int i=0; i < n; ++i) { | |
324 Argument* arg = Argument::getNth(f->parameters, i); | |
325 // ensure scalar | |
326 Type* argT = LLVM_DtoDType(arg->type); | |
327 assert(argT); | |
328 | |
329 if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) { | |
330 //assert(arg->vardecl); | |
331 //arg->vardecl->refparam = true; | |
332 } | 378 } |
333 else | 379 else { |
334 arg->llvmCopy = true; | 380 Logger::println("in param"); |
335 | |
336 const llvm::Type* at = LLVM_DtoType(argT); | |
337 if (llvm::isa<llvm::StructType>(at)) { | |
338 Logger::println("struct param"); | |
339 paramvec.push_back(llvm::PointerType::get(at)); | |
340 } | 381 } |
341 else if (llvm::isa<llvm::ArrayType>(at)) { | 382 paramvec.push_back(at); |
342 Logger::println("sarray param"); | |
343 assert(argT->ty == Tsarray); | |
344 //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0))); | |
345 paramvec.push_back(llvm::PointerType::get(at)); | |
346 } | |
347 else if (llvm::isa<llvm::OpaqueType>(at)) { | |
348 Logger::println("opaque param"); | |
349 if (argT->ty == Tstruct || argT->ty == Tclass) | |
350 paramvec.push_back(llvm::PointerType::get(at)); | |
351 else | |
352 assert(0); | |
353 } | |
354 /*if (llvm::isa<llvm::StructType>(at) || argT->ty == Tstruct || argT->ty == Tsarray) { | |
355 paramvec.push_back(llvm::PointerType::get(at)); | |
356 }*/ | |
357 else { | |
358 if (!arg->llvmCopy) { | |
359 Logger::println("ref param"); | |
360 at = llvm::PointerType::get(at); | |
361 } | |
362 else { | |
363 Logger::println("in param"); | |
364 } | |
365 paramvec.push_back(at); | |
366 } | |
367 } | 383 } |
368 } | 384 } |
369 | 385 |
370 // construct function type | 386 // construct function type |
371 bool isvararg = f->varargs; | 387 bool isvararg = !typesafeVararg && f->varargs; |
372 llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); | 388 llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); |
373 | 389 |
374 f->llvmType = functype; | 390 f->llvmType = functype; |
375 f->llvmRetInPtr = retinptr; | 391 f->llvmRetInPtr = retinptr; |
376 f->llvmUsesThis = usesthis; | 392 f->llvmUsesThis = usesthis; |
1073 } | 1089 } |
1074 if (f->llvmUsesThis) { | 1090 if (f->llvmUsesThis) { |
1075 iarg->setName("this"); | 1091 iarg->setName("this"); |
1076 ++iarg; | 1092 ++iarg; |
1077 } | 1093 } |
1094 int varargs = -1; | |
1095 if (f->linkage == LINKd && f->varargs == 1) | |
1096 varargs = 0; | |
1078 for (; iarg != func->arg_end(); ++iarg) | 1097 for (; iarg != func->arg_end(); ++iarg) |
1079 { | 1098 { |
1080 Argument* arg = Argument::getNth(f->parameters, k++); | 1099 Argument* arg = Argument::getNth(f->parameters, k++); |
1081 assert(arg != 0); | |
1082 //arg->llvmValue = iarg; | 1100 //arg->llvmValue = iarg; |
1083 //printf("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident); | 1101 //printf("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident); |
1084 if (arg->ident != 0) { | 1102 if (arg && arg->ident != 0) { |
1085 if (arg->vardecl) { | 1103 if (arg->vardecl) { |
1086 arg->vardecl->llvmValue = iarg; | 1104 arg->vardecl->llvmValue = iarg; |
1087 } | 1105 } |
1088 iarg->setName(arg->ident->toChars()); | 1106 iarg->setName(arg->ident->toChars()); |
1107 } | |
1108 else if (!arg && varargs >= 0) { | |
1109 if (varargs == 0) { | |
1110 iarg->setName("_arguments"); | |
1111 fdecl->llvmArguments = iarg; | |
1112 } | |
1113 else if (varargs == 1) { | |
1114 iarg->setName("_argptr"); | |
1115 fdecl->llvmArgPtr = iarg; | |
1116 } | |
1117 else | |
1118 assert(0); | |
1119 varargs++; | |
1089 } | 1120 } |
1090 else { | 1121 else { |
1091 iarg->setName("unnamed"); | 1122 iarg->setName("unnamed"); |
1092 } | 1123 } |
1093 } | 1124 } |
1234 retval = arg->arg ? arg->arg : arg->field ? arg->mem : arg->getValue(); | 1265 retval = arg->arg ? arg->arg : arg->field ? arg->mem : arg->getValue(); |
1235 } | 1266 } |
1236 else { | 1267 else { |
1237 Logger::println("as ptr arg"); | 1268 Logger::println("as ptr arg"); |
1238 retval = arg->mem ? arg->mem : arg->val; | 1269 retval = arg->mem ? arg->mem : arg->val; |
1239 if (retval->getType() != paramtype) | 1270 if (paramtype && retval->getType() != paramtype) |
1240 { | 1271 { |
1241 assert(retval->getType() == paramtype->getContainedType(0)); | 1272 assert(retval->getType() == paramtype->getContainedType(0)); |
1242 LLVM_DtoGiveArgumentStorage(arg); | 1273 LLVM_DtoGiveArgumentStorage(arg); |
1243 new llvm::StoreInst(retval, arg->mem, gIR->scopebb()); | 1274 new llvm::StoreInst(retval, arg->mem, gIR->scopebb()); |
1244 retval = arg->mem; | 1275 retval = arg->mem; |
1245 } | 1276 } |
1246 } | 1277 } |
1247 | 1278 |
1248 delete arg; | 1279 delete arg; |
1249 | 1280 |
1250 if (fnarg && retval->getType() != paramtype) { | 1281 if (fnarg && paramtype && retval->getType() != paramtype) { |
1251 Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n"; | 1282 Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n"; |
1252 assert(0 && "parameter type that was actually passed is invalid"); | 1283 assert(0 && "parameter type that was actually passed is invalid"); |
1253 } | 1284 } |
1254 return retval; | 1285 return retval; |
1255 } | 1286 } |