Mercurial > projects > ldc
comparison gen/functions.cpp @ 136:0e28624814e8 trunk
[svn r140] did a lot of the work towards being able to pass multiple modules on the command line. not complete yet though
author | lindquist |
---|---|
date | Thu, 17 Jan 2008 03:15:12 +0100 |
parents | 44a95ac7368a |
children | ce7b81fb957f |
comparison
equal
deleted
inserted
replaced
135:176bd52b3cf5 | 136:0e28624814e8 |
---|---|
230 assert(0); | 230 assert(0); |
231 | 231 |
232 llvm::Function* func = llvm::dyn_cast<llvm::Function>(fn); | 232 llvm::Function* func = llvm::dyn_cast<llvm::Function>(fn); |
233 assert(func); | 233 assert(func); |
234 assert(func->isIntrinsic()); | 234 assert(func->isIntrinsic()); |
235 fdecl->llvmValue = func; | 235 fdecl->irFunc->func = func; |
236 return func; | 236 return func; |
237 } | 237 } |
238 | 238 |
239 ////////////////////////////////////////////////////////////////////////////////////////// | 239 ////////////////////////////////////////////////////////////////////////////////////////// |
240 | 240 |
255 fdecl->llvmResolved = true; | 255 fdecl->llvmResolved = true; |
256 | 256 |
257 Logger::println("DtoResolveFunction(%s): %s", fdecl->toPrettyChars(), fdecl->loc.toChars()); | 257 Logger::println("DtoResolveFunction(%s): %s", fdecl->toPrettyChars(), fdecl->loc.toChars()); |
258 LOG_SCOPE; | 258 LOG_SCOPE; |
259 | 259 |
260 if (fdecl->llvmRunTimeHack) { | 260 if (fdecl->runTimeHack) { |
261 gIR->declareList.push_back(fdecl); | 261 gIR->declareList.push_back(fdecl); |
262 TypeFunction* tf = (TypeFunction*)fdecl->type; | 262 TypeFunction* tf = (TypeFunction*)fdecl->type; |
263 tf->llvmRetInPtr = DtoIsPassedByRef(tf->next); | 263 tf->llvmRetInPtr = DtoIsPassedByRef(tf->next); |
264 return; | 264 return; |
265 } | 265 } |
307 if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) { | 307 if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) { |
308 error(fdecl->loc, "intrinsics cannot have function bodies"); | 308 error(fdecl->loc, "intrinsics cannot have function bodies"); |
309 fatal(); | 309 fatal(); |
310 } | 310 } |
311 | 311 |
312 if (fdecl->llvmRunTimeHack) { | 312 if (fdecl->runTimeHack) { |
313 Logger::println("runtime hack func chars: %s", fdecl->toChars()); | 313 Logger::println("runtime hack func chars: %s", fdecl->toChars()); |
314 if (!fdecl->llvmValue) | 314 if (!fdecl->irFunc) { |
315 fdecl->llvmValue = LLVM_D_GetRuntimeFunction(gIR->module, fdecl->toChars()); | 315 fdecl->irFunc = new IrFunction(fdecl); |
316 fdecl->irFunc->func = LLVM_D_GetRuntimeFunction(gIR->module, fdecl->toChars()); | |
317 } | |
316 return; | 318 return; |
317 } | 319 } |
318 | 320 |
319 bool declareOnly = false; | 321 bool declareOnly = false; |
320 bool templInst = fdecl->parent && DtoIsTemplateInstance(fdecl->parent); | 322 bool templInst = fdecl->parent && DtoIsTemplateInstance(fdecl->parent); |
321 if (!templInst && fdecl->getModule() != gIR->dmodule) | 323 if (!templInst && fdecl->getModule() != gIR->dmodule) |
322 declareOnly = true; | 324 declareOnly = true; |
323 else if (fdecl->llvmInternal == LLVMva_start) | 325 else if (fdecl->llvmInternal == LLVMva_start) |
324 declareOnly = true; | 326 declareOnly = true; |
325 | 327 |
326 if (!fdecl->llvmIRFunc) { | 328 if (!fdecl->irFunc) { |
327 fdecl->llvmIRFunc = new IRFunction(fdecl); | 329 fdecl->irFunc = new IrFunction(fdecl); |
328 } | 330 } |
329 | 331 |
330 // mangled name | 332 // mangled name |
331 char* mangled_name; | 333 char* mangled_name; |
332 if (fdecl->llvmInternal == LLVMintrinsic) | 334 if (fdecl->llvmInternal == LLVMintrinsic) |
349 func = new llvm::Function(functype, DtoLinkage(fdecl->protection, fdecl->storage_class), mangled_name, gIR->module); | 351 func = new llvm::Function(functype, DtoLinkage(fdecl->protection, fdecl->storage_class), mangled_name, gIR->module); |
350 else | 352 else |
351 assert(func->getFunctionType() == functype); | 353 assert(func->getFunctionType() == functype); |
352 | 354 |
353 // add func to IRFunc | 355 // add func to IRFunc |
354 fdecl->llvmIRFunc->func = func; | 356 fdecl->irFunc->func = func; |
355 | 357 |
356 // calling convention | 358 // calling convention |
357 if (!vafunc && fdecl->llvmInternal != LLVMintrinsic) | 359 if (!vafunc && fdecl->llvmInternal != LLVMintrinsic) |
358 func->setCallingConv(DtoCallingConv(f->linkage)); | 360 func->setCallingConv(DtoCallingConv(f->linkage)); |
359 | 361 |
370 { | 372 { |
371 func->setLinkage(llvm::GlobalValue::ExternalLinkage); | 373 func->setLinkage(llvm::GlobalValue::ExternalLinkage); |
372 func->setCallingConv(llvm::CallingConv::C); | 374 func->setCallingConv(llvm::CallingConv::C); |
373 } | 375 } |
374 | 376 |
375 fdecl->llvmValue = func; | 377 fdecl->irFunc->func = func; |
376 assert(llvm::isa<llvm::FunctionType>(f->llvmType->get())); | 378 assert(llvm::isa<llvm::FunctionType>(f->llvmType->get())); |
377 | 379 |
378 // main | 380 // main |
379 if (fdecl->isMain()) { | 381 if (fdecl->isMain()) { |
380 gIR->mainFunc = func; | 382 gIR->mainFunc = func; |
392 // name parameters | 394 // name parameters |
393 llvm::Function::arg_iterator iarg = func->arg_begin(); | 395 llvm::Function::arg_iterator iarg = func->arg_begin(); |
394 int k = 0; | 396 int k = 0; |
395 if (f->llvmRetInPtr) { | 397 if (f->llvmRetInPtr) { |
396 iarg->setName("retval"); | 398 iarg->setName("retval"); |
397 fdecl->llvmRetArg = iarg; | 399 fdecl->irFunc->retArg = iarg; |
398 ++iarg; | 400 ++iarg; |
399 } | 401 } |
400 if (f->llvmUsesThis) { | 402 if (f->llvmUsesThis) { |
401 iarg->setName("this"); | 403 iarg->setName("this"); |
402 fdecl->llvmThisVar = iarg; | 404 fdecl->irFunc->thisVar = iarg; |
403 assert(fdecl->llvmThisVar); | 405 assert(fdecl->irFunc->thisVar); |
404 ++iarg; | 406 ++iarg; |
405 } | 407 } |
406 | 408 |
407 if (f->linkage == LINKd && f->varargs == 1) { | 409 if (f->linkage == LINKd && f->varargs == 1) { |
408 iarg->setName("_arguments"); | 410 iarg->setName("_arguments"); |
409 fdecl->llvmArguments = iarg; | 411 fdecl->irFunc->_arguments = iarg; |
410 ++iarg; | 412 ++iarg; |
411 iarg->setName("_argptr"); | 413 iarg->setName("_argptr"); |
412 fdecl->llvmArgPtr = iarg; | 414 fdecl->irFunc->_argptr = iarg; |
413 ++iarg; | 415 ++iarg; |
414 } | 416 } |
415 | 417 |
416 for (; iarg != func->arg_end(); ++iarg) | 418 for (; iarg != func->arg_end(); ++iarg) |
417 { | 419 { |
418 Argument* arg = Argument::getNth(f->parameters, k++); | 420 Argument* arg = Argument::getNth(f->parameters, k++); |
419 //arg->llvmValue = iarg; | 421 //arg->llvmValue = iarg; |
420 //Logger::println("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident); | 422 //Logger::println("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident); |
421 if (arg && arg->ident != 0) { | 423 if (arg && arg->ident != 0) { |
422 if (arg->vardecl) { | 424 if (arg->vardecl) { |
423 arg->vardecl->llvmValue = iarg; | 425 assert(!arg->vardecl->irLocal); |
426 arg->vardecl->irLocal = new IrLocal(arg->vardecl); | |
427 arg->vardecl->irLocal->value = iarg; | |
424 } | 428 } |
425 iarg->setName(arg->ident->toChars()); | 429 iarg->setName(arg->ident->toChars()); |
426 } | 430 } |
427 else { | 431 else { |
428 iarg->setName("unnamed"); | 432 iarg->setName("unnamed"); |
456 if (global.params.symdebug) { | 460 if (global.params.symdebug) { |
457 Module* mo = fd->getModule(); | 461 Module* mo = fd->getModule(); |
458 if (!mo->llvmCompileUnit) { | 462 if (!mo->llvmCompileUnit) { |
459 mo->llvmCompileUnit = DtoDwarfCompileUnit(mo,false); | 463 mo->llvmCompileUnit = DtoDwarfCompileUnit(mo,false); |
460 } | 464 } |
461 fd->llvmDwarfSubProgram = DtoDwarfSubProgram(fd, mo->llvmCompileUnit); | 465 fd->irFunc->dwarfSubProg = DtoDwarfSubProgram(fd, mo->llvmCompileUnit); |
462 } | 466 } |
463 | 467 |
464 Type* t = DtoDType(fd->type); | 468 Type* t = DtoDType(fd->type); |
465 TypeFunction* f = (TypeFunction*)t; | 469 TypeFunction* f = (TypeFunction*)t; |
466 assert(f->llvmType); | 470 assert(f->llvmType); |
467 | 471 |
468 llvm::Function* func = fd->llvmIRFunc->func; | 472 llvm::Function* func = fd->irFunc->func; |
469 const llvm::FunctionType* functype = func->getFunctionType(); | 473 const llvm::FunctionType* functype = func->getFunctionType(); |
470 | 474 |
471 // only members of the current module or template instances maybe be defined | 475 // only members of the current module or template instances maybe be defined |
472 if (fd->getModule() == gIR->dmodule || DtoIsTemplateInstance(fd->parent)) | 476 if (fd->getModule() == gIR->dmodule || DtoIsTemplateInstance(fd->parent)) |
473 { | 477 { |
475 | 479 |
476 // function definition | 480 // function definition |
477 if (fd->fbody != 0) | 481 if (fd->fbody != 0) |
478 { | 482 { |
479 Logger::println("Doing function body for: %s", fd->toChars()); | 483 Logger::println("Doing function body for: %s", fd->toChars()); |
480 assert(fd->llvmIRFunc); | 484 assert(fd->irFunc); |
481 gIR->functions.push_back(fd->llvmIRFunc); | 485 gIR->functions.push_back(fd->irFunc); |
482 | 486 |
483 if (fd->isMain()) | 487 if (fd->isMain()) |
484 gIR->emitMain = true; | 488 gIR->emitMain = true; |
485 | 489 |
486 llvm::BasicBlock* beginbb = new llvm::BasicBlock("entry",func); | 490 llvm::BasicBlock* beginbb = new llvm::BasicBlock("entry",func); |
494 gIR->func()->allocapoint = allocaPoint; | 498 gIR->func()->allocapoint = allocaPoint; |
495 | 499 |
496 // need result variable? (not nested) | 500 // need result variable? (not nested) |
497 if (fd->vresult && !fd->vresult->nestedref) { | 501 if (fd->vresult && !fd->vresult->nestedref) { |
498 Logger::println("non-nested vresult value"); | 502 Logger::println("non-nested vresult value"); |
499 fd->vresult->llvmValue = new llvm::AllocaInst(DtoType(fd->vresult->type),"function_vresult",allocaPoint); | 503 fd->vresult->irLocal = new IrLocal(fd->vresult); |
504 fd->vresult->irLocal->value = new llvm::AllocaInst(DtoType(fd->vresult->type),"function_vresult",allocaPoint); | |
500 } | 505 } |
501 | 506 |
502 // give arguments storage | 507 // give arguments storage |
503 size_t n = Argument::dim(f->parameters); | 508 size_t n = Argument::dim(f->parameters); |
504 for (int i=0; i < n; ++i) { | 509 for (int i=0; i < n; ++i) { |
505 Argument* arg = Argument::getNth(f->parameters, i); | 510 Argument* arg = Argument::getNth(f->parameters, i); |
506 if (arg && arg->vardecl) { | 511 if (arg && arg->vardecl) { |
507 VarDeclaration* vd = arg->vardecl; | 512 VarDeclaration* vd = arg->vardecl; |
508 if (!vd->llvmNeedsStorage || vd->nestedref || vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)) | 513 if (!vd->needsStorage || vd->nestedref || vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)) |
509 continue; | 514 continue; |
510 llvm::Value* a = vd->llvmValue; | 515 llvm::Value* a = vd->irLocal->value; |
511 assert(a); | 516 assert(a); |
512 std::string s(a->getName()); | 517 std::string s(a->getName()); |
513 Logger::println("giving argument '%s' storage", s.c_str()); | 518 Logger::println("giving argument '%s' storage", s.c_str()); |
514 s.append("_storage"); | 519 s.append("_storage"); |
515 llvm::Value* v = new llvm::AllocaInst(a->getType(),s,allocaPoint); | 520 llvm::Value* v = new llvm::AllocaInst(a->getType(),s,allocaPoint); |
516 gIR->ir->CreateStore(a,v); | 521 gIR->ir->CreateStore(a,v); |
517 vd->llvmValue = v; | 522 vd->irLocal->value = v; |
518 } | 523 } |
519 else { | 524 else { |
520 Logger::attention(fd->loc, "some unknown argument: %s", arg ? arg->toChars() : 0); | 525 Logger::attention(fd->loc, "some unknown argument: %s", arg ? arg->toChars() : 0); |
521 } | 526 } |
522 } | 527 } |
525 if (global.params.symdebug) DtoDwarfFuncStart(fd); | 530 if (global.params.symdebug) DtoDwarfFuncStart(fd); |
526 | 531 |
527 llvm::Value* parentNested = NULL; | 532 llvm::Value* parentNested = NULL; |
528 if (FuncDeclaration* fd2 = fd->toParent2()->isFuncDeclaration()) { | 533 if (FuncDeclaration* fd2 = fd->toParent2()->isFuncDeclaration()) { |
529 if (!fd->isStatic()) // huh? | 534 if (!fd->isStatic()) // huh? |
530 parentNested = fd2->llvmNested; | 535 parentNested = fd2->irFunc->nestedVar; |
531 } | 536 } |
532 | 537 |
533 // need result variable? (nested) | 538 // need result variable? (nested) |
534 if (fd->vresult && fd->vresult->nestedref) { | 539 if (fd->vresult && fd->vresult->nestedref) { |
535 Logger::println("nested vresult value: %s", fd->vresult->toChars()); | 540 Logger::println("nested vresult value: %s", fd->vresult->toChars()); |
536 fd->llvmNestedVars.insert(fd->vresult); | 541 fd->nestedVars.insert(fd->vresult); |
537 } | 542 } |
538 | 543 |
539 // construct nested variables struct | 544 // construct nested variables struct |
540 if (!fd->llvmNestedVars.empty() || parentNested) { | 545 if (!fd->nestedVars.empty() || parentNested) { |
541 std::vector<const llvm::Type*> nestTypes; | 546 std::vector<const llvm::Type*> nestTypes; |
542 int j = 0; | 547 int j = 0; |
543 if (parentNested) { | 548 if (parentNested) { |
544 nestTypes.push_back(parentNested->getType()); | 549 nestTypes.push_back(parentNested->getType()); |
545 j++; | 550 j++; |
546 } | 551 } |
547 for (std::set<VarDeclaration*>::iterator i=fd->llvmNestedVars.begin(); i!=fd->llvmNestedVars.end(); ++i) { | 552 for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) { |
548 VarDeclaration* vd = *i; | 553 VarDeclaration* vd = *i; |
549 vd->llvmNestedIndex = j++; | 554 if (!vd->irLocal) |
555 vd->irLocal = new IrLocal(vd); | |
556 vd->irLocal->nestedIndex = j++; | |
550 if (vd->isParameter()) { | 557 if (vd->isParameter()) { |
551 assert(vd->llvmValue); | 558 |
552 nestTypes.push_back(vd->llvmValue->getType()); | 559 assert(vd->irLocal->value); |
560 nestTypes.push_back(vd->irLocal->value->getType()); | |
553 } | 561 } |
554 else { | 562 else { |
555 nestTypes.push_back(DtoType(vd->type)); | 563 nestTypes.push_back(DtoType(vd->type)); |
556 } | 564 } |
557 } | 565 } |
558 const llvm::StructType* nestSType = llvm::StructType::get(nestTypes); | 566 const llvm::StructType* nestSType = llvm::StructType::get(nestTypes); |
559 Logger::cout() << "nested var struct has type:" << *nestSType << '\n'; | 567 Logger::cout() << "nested var struct has type:" << *nestSType << '\n'; |
560 fd->llvmNested = new llvm::AllocaInst(nestSType,"nestedvars",allocaPoint); | 568 fd->irFunc->nestedVar = new llvm::AllocaInst(nestSType,"nestedvars",allocaPoint); |
561 if (parentNested) { | 569 if (parentNested) { |
562 assert(fd->llvmThisVar); | 570 assert(fd->irFunc->thisVar); |
563 llvm::Value* ptr = gIR->ir->CreateBitCast(fd->llvmThisVar, parentNested->getType(), "tmp"); | 571 llvm::Value* ptr = gIR->ir->CreateBitCast(fd->irFunc->thisVar, parentNested->getType(), "tmp"); |
564 gIR->ir->CreateStore(ptr, DtoGEPi(fd->llvmNested, 0,0, "tmp")); | 572 gIR->ir->CreateStore(ptr, DtoGEPi(fd->irFunc->nestedVar, 0,0, "tmp")); |
565 } | 573 } |
566 for (std::set<VarDeclaration*>::iterator i=fd->llvmNestedVars.begin(); i!=fd->llvmNestedVars.end(); ++i) { | 574 for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) { |
567 VarDeclaration* vd = *i; | 575 VarDeclaration* vd = *i; |
568 if (vd->isParameter()) { | 576 if (vd->isParameter()) { |
569 gIR->ir->CreateStore(vd->llvmValue, DtoGEPi(fd->llvmNested, 0, vd->llvmNestedIndex, "tmp")); | 577 assert(vd->irLocal); |
570 vd->llvmValue = fd->llvmNested; | 578 gIR->ir->CreateStore(vd->irLocal->value, DtoGEPi(fd->irFunc->nestedVar, 0, vd->irLocal->nestedIndex, "tmp")); |
579 vd->irLocal->value = fd->irFunc->nestedVar; | |
571 } | 580 } |
572 } | 581 } |
573 } | 582 } |
574 | 583 |
575 // copy _argptr to a memory location | 584 // copy _argptr to a memory location |
576 if (f->linkage == LINKd && f->varargs == 1) | 585 if (f->linkage == LINKd && f->varargs == 1) |
577 { | 586 { |
578 llvm::Value* argptrmem = new llvm::AllocaInst(fd->llvmArgPtr->getType(), "_argptrmem", gIR->topallocapoint()); | 587 llvm::Value* argptrmem = new llvm::AllocaInst(fd->irFunc->_argptr->getType(), "_argptrmem", gIR->topallocapoint()); |
579 new llvm::StoreInst(fd->llvmArgPtr, argptrmem, gIR->scopebb()); | 588 new llvm::StoreInst(fd->irFunc->_argptr, argptrmem, gIR->scopebb()); |
580 fd->llvmArgPtr = argptrmem; | 589 fd->irFunc->_argptr = argptrmem; |
581 } | 590 } |
582 | 591 |
583 // output function body | 592 // output function body |
584 fd->fbody->toIR(gIR); | 593 fd->fbody->toIR(gIR); |
585 | 594 |