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 }