comparison gen/toobj.cpp @ 100:5071469303d4 trunk

[svn r104] TONS OF FIXES. Split up declaration, constant initializer gen and definition for globals, structs, classes and functions. Improved ClassInfo support (not complete), not in vtable yet. Fixed a bunch of forward reference problems. Much more. Major commit! :)
author lindquist
date Fri, 16 Nov 2007 08:21:47 +0100
parents 6789050b5ad1
children 027b8d8b71ec
comparison
equal deleted inserted replaced
99:a676a7743642 100:5071469303d4
34 #include "gen/irstate.h" 34 #include "gen/irstate.h"
35 #include "gen/logger.h" 35 #include "gen/logger.h"
36 #include "gen/tollvm.h" 36 #include "gen/tollvm.h"
37 #include "gen/arrays.h" 37 #include "gen/arrays.h"
38 #include "gen/structs.h" 38 #include "gen/structs.h"
39 #include "gen/classes.h"
40 #include "gen/functions.h"
39 #include "gen/todebug.h" 41 #include "gen/todebug.h"
40 #include "gen/runtime.h" 42 #include "gen/runtime.h"
41 43
42 ////////////////////////////////////////////////////////////////////////////////////////// 44 //////////////////////////////////////////////////////////////////////////////////////////
43 45
88 Dsymbol* dsym = (Dsymbol*)(members->data[k]); 90 Dsymbol* dsym = (Dsymbol*)(members->data[k]);
89 assert(dsym); 91 assert(dsym);
90 dsym->toObjFile(); 92 dsym->toObjFile();
91 } 93 }
92 94
93 // check if there are queued function definitions, if so process their bodies now 95 // process deferred const initializers
94 if (!ir.funcQueue.empty()) { 96 for (size_t i=0; i<ir.constInitQueue.size(); ++i) {
95 size_t n = ir.funcQueue.size(); 97 DtoConstInitDsymbol(ir.constInitQueue[i]);
96 for (size_t i=0; i<n; ++i) { 98 }
97 ir.funcQueue[i]->toObjFile(); 99
98 } 100 // process deferred definitions
101 for (size_t i=0; i<ir.defineQueue.size(); ++i) {
102 DtoDefineDsymbol(ir.defineQueue[i]);
99 } 103 }
100 104
101 // generate ModuleInfo 105 // generate ModuleInfo
102 genmoduleinfo(); 106 genmoduleinfo();
103 107
320 324
321 /* ================================================================== */ 325 /* ================================================================== */
322 326
323 void StructDeclaration::toObjFile() 327 void StructDeclaration::toObjFile()
324 { 328 {
325 TypeStruct* ts = (TypeStruct*)DtoDType(type); 329 DtoDeclareStruct(this);
326 if (llvmType != 0)
327 return;
328
329 static int sdi = 0;
330 Logger::print("StructDeclaration::toObjFile(%d): %s\n", sdi++, toChars());
331 LOG_SCOPE;
332
333 gIR->structs.push_back(IRStruct(ts));
334
335 for (int k=0; k < members->dim; k++) {
336 Dsymbol* dsym = (Dsymbol*)(members->data[k]);
337 dsym->toObjFile();
338 }
339
340 Logger::println("doing struct fields");
341
342 const llvm::StructType* structtype = 0;
343 std::vector<llvm::Constant*> fieldinits;
344
345 if (gIR->topstruct().offsets.empty())
346 {
347 std::vector<const llvm::Type*> fieldtypes;
348 Logger::println("has no fields");
349 fieldtypes.push_back(llvm::Type::Int8Ty);
350 fieldinits.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
351 structtype = llvm::StructType::get(fieldtypes);
352 }
353 else
354 {
355 Logger::println("has fields");
356 std::vector<const llvm::Type*> fieldtypes;
357 unsigned prevsize = (unsigned)-1;
358 unsigned lastoffset = (unsigned)-1;
359 const llvm::Type* fieldtype = NULL;
360 llvm::Constant* fieldinit = NULL;
361 size_t fieldpad = 0;
362 int idx = 0;
363 for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) {
364 // first iteration
365 if (lastoffset == (unsigned)-1) {
366 lastoffset = i->first;
367 assert(lastoffset == 0);
368 fieldtype = DtoType(i->second.var->type);
369 fieldinit = i->second.init;
370 prevsize = gTargetData->getTypeSize(fieldtype);
371 i->second.var->llvmFieldIndex = idx;
372 }
373 // colliding offset?
374 else if (lastoffset == i->first) {
375 const llvm::Type* t = DtoType(i->second.var->type);
376 size_t s = gTargetData->getTypeSize(t);
377 if (s > prevsize) {
378 fieldpad += s - prevsize;
379 prevsize = s;
380 }
381 llvmHasUnions = true;
382 i->second.var->llvmFieldIndex = idx;
383 }
384 // intersecting offset?
385 else if (i->first < (lastoffset + prevsize)) {
386 const llvm::Type* t = DtoType(i->second.var->type);
387 size_t s = gTargetData->getTypeSize(t);
388 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
389 llvmHasUnions = true;
390 i->second.var->llvmFieldIndex = idx;
391 i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s;
392 }
393 // fresh offset
394 else {
395 // commit the field
396 fieldtypes.push_back(fieldtype);
397 fieldinits.push_back(fieldinit);
398 if (fieldpad) {
399 // match up with below
400 std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
401 llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals);
402 fieldtypes.push_back(c->getType());
403 fieldinits.push_back(c);
404 idx++;
405 }
406
407 idx++;
408
409 // start new
410 lastoffset = i->first;
411 fieldtype = DtoType(i->second.var->type);
412 fieldinit = i->second.init;
413 prevsize = gTargetData->getTypeSize(fieldtype);
414 i->second.var->llvmFieldIndex = idx;
415 fieldpad = 0;
416 }
417 }
418 fieldtypes.push_back(fieldtype);
419 fieldinits.push_back(fieldinit);
420 if (fieldpad) {
421 // match up with above
422 std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
423 llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals);
424 fieldtypes.push_back(c->getType());
425 fieldinits.push_back(c);
426 }
427
428 Logger::println("creating struct type");
429 structtype = llvm::StructType::get(fieldtypes);
430 }
431
432 // refine abstract types for stuff like: struct S{S* next;}
433 if (gIR->topstruct().recty != 0)
434 {
435 llvm::PATypeHolder& pa = gIR->topstruct().recty;
436 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
437 structtype = isaStruct(pa.get());
438 }
439
440 ts->llvmType = structtype;
441 llvmType = structtype;
442
443 if (parent->isModule()) {
444 gIR->module->addTypeName(mangle(),ts->llvmType);
445 }
446
447 llvmUnion = new DUnion; // uses gIR->topstruct()
448
449 // generate static data
450 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
451 llvm::Constant* _init = 0;
452
453 // always generate the constant initalizer
454 if (!zeroInit) {
455 Logger::println("Not zero initialized");
456 //assert(tk == gIR->gIR->topstruct()().size());
457 #ifndef LLVMD_NO_LOGGER
458 Logger::cout() << "struct type: " << *structtype << '\n';
459 for (size_t k=0; k<fieldinits.size(); ++k) {
460 Logger::cout() << "Type:" << '\n';
461 Logger::cout() << *fieldinits[k]->getType() << '\n';
462 Logger::cout() << "Value:" << '\n';
463 Logger::cout() << *fieldinits[k] << '\n';
464 }
465 Logger::cout() << "Initializer printed" << '\n';
466 #endif
467 llvmInitZ = llvm::ConstantStruct::get(structtype,fieldinits);
468 }
469 else {
470 Logger::println("Zero initialized");
471 llvmInitZ = llvm::ConstantAggregateZero::get(structtype);
472 }
473
474 // only provide the constant initializer for the defining module
475 if (getModule() == gIR->dmodule)
476 {
477 _init = llvmInitZ;
478 }
479
480 std::string initname("_D");
481 initname.append(mangle());
482 initname.append("6__initZ");
483 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, _init, initname, gIR->module);
484 ts->llvmInit = initvar;
485
486 // generate member function definitions
487 gIR->topstruct().queueFuncs = false;
488 IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs;
489 size_t n = mfs.size();
490 for (size_t i=0; i<n; ++i) {
491 //mfs[i]->toObjFile();
492 gIR->funcQueue.push_back(mfs[i]);
493 }
494
495 llvmDModule = gIR->dmodule;
496
497 gIR->structs.pop_back();
498
499 // generate typeinfo
500 if (getModule() == gIR->dmodule && llvmInternal != LLVMnotypeinfo)
501 type->getTypeInfo(NULL);
502 } 330 }
503 331
504 /* ================================================================== */ 332 /* ================================================================== */
505 333
506 static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx) 334 static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx)
532 result.push_back(r+1); // vtable is 0 360 result.push_back(r+1); // vtable is 0
533 } 361 }
534 362
535 /* ================================================================== */ 363 /* ================================================================== */
536 364
537 static void LLVM_AddBaseClassData(BaseClasses* bcs)
538 {
539 // add base class data members first
540 for (int j=0; j<bcs->dim; j++)
541 {
542 BaseClass* bc = (BaseClass*)(bcs->data[j]);
543 assert(bc);
544 Logger::println("Adding base class members of %s", bc->base->toChars());
545 LOG_SCOPE;
546
547 LLVM_AddBaseClassData(&bc->base->baseclasses);
548 for (int k=0; k < bc->base->members->dim; k++) {
549 Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]);
550 if (dsym->isVarDeclaration())
551 {
552 dsym->toObjFile();
553 }
554 }
555 }
556 }
557
558 void ClassDeclaration::toObjFile() 365 void ClassDeclaration::toObjFile()
559 { 366 {
560 TypeClass* ts = (TypeClass*)DtoDType(type); 367 DtoDeclareClass(this);
561 if (ts->llvmType != 0 || llvmInProgress)
562 return;
563
564 llvmInProgress = true;
565
566 static int fdi = 0;
567 Logger::print("ClassDeclaration::toObjFile(%d): %s\n", fdi++, toChars());
568 LOG_SCOPE;
569
570 gIR->structs.push_back(IRStruct(ts));
571 gIR->classes.push_back(this);
572
573 // add vtable
574 llvm::PATypeHolder pa = llvm::OpaqueType::get();
575 const llvm::Type* vtabty = llvm::PointerType::get(pa);
576
577 std::vector<const llvm::Type*> fieldtypes;
578 fieldtypes.push_back(vtabty);
579
580 std::vector<llvm::Constant*> fieldinits;
581 fieldinits.push_back(0);
582
583 // base classes first
584 LLVM_AddBaseClassData(&baseclasses);
585
586 // then add own members
587 for (int k=0; k < members->dim; k++) {
588 Dsymbol* dsym = (Dsymbol*)(members->data[k]);
589 dsym->toObjFile();
590 }
591
592 // fill out fieldtypes/inits
593 for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) {
594 fieldtypes.push_back(DtoType(i->second.var->type));
595 fieldinits.push_back(i->second.init);
596 }
597
598 const llvm::StructType* structtype = llvm::StructType::get(fieldtypes);
599 // refine abstract types for stuff like: class C {C next;}
600 if (gIR->topstruct().recty != 0)
601 {
602 llvm::PATypeHolder& pa = gIR->topstruct().recty;
603 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
604 structtype = isaStruct(pa.get());
605 }
606
607 ts->llvmType = structtype;
608 llvmType = structtype;
609
610 bool needs_definition = false;
611 if (parent->isModule()) {
612 gIR->module->addTypeName(mangle(),ts->llvmType);
613 needs_definition = (getModule() == gIR->dmodule);
614 }
615 else {
616 assert(0 && "class parent is not a module");
617 }
618
619 // generate vtable
620 llvm::GlobalVariable* svtblVar = 0;
621 std::vector<llvm::Constant*> sinits;
622 std::vector<const llvm::Type*> sinits_ty;
623 sinits.reserve(vtbl.dim);
624 sinits_ty.reserve(vtbl.dim);
625
626 for (int k=0; k < vtbl.dim; k++)
627 {
628 Dsymbol* dsym = (Dsymbol*)vtbl.data[k];
629 assert(dsym);
630 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
631
632 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
633 fd->toObjFile();
634 assert(fd->llvmValue);
635 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
636 sinits.push_back(c);
637 sinits_ty.push_back(c->getType());
638 }
639 else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
640 const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty);
641 llvm::Constant* c = llvm::Constant::getNullValue(cty);
642 sinits.push_back(c);
643 sinits_ty.push_back(cty);
644 }
645 else
646 assert(0);
647 }
648
649 const llvm::StructType* svtbl_ty = 0;
650 if (!sinits.empty())
651 {
652 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
653
654 std::string varname("_D");
655 varname.append(mangle());
656 varname.append("6__vtblZ");
657
658 std::string styname(mangle());
659 styname.append("__vtblTy");
660
661 svtbl_ty = llvm::StructType::get(sinits_ty);
662 gIR->module->addTypeName(styname, svtbl_ty);
663 svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
664
665 llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(svtbl_ty, sinits));
666 if (needs_definition)
667 svtblVar->setInitializer(llvmConstVtbl);
668 llvmVtbl = svtblVar;
669 }
670
671 ////////////////////////////////////////////////////////////////////////////////
672
673 // refine for final vtable type
674 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(svtbl_ty);
675 svtbl_ty = isaStruct(pa.get());
676 structtype = isaStruct(gIR->topstruct().recty.get());
677 ts->llvmType = structtype;
678 llvmType = structtype;
679
680 // generate initializer
681 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
682 llvm::Constant* _init = 0;
683
684 // first field is always the vtable
685 assert(svtblVar != 0);
686 fieldinits[0] = svtblVar;
687
688 llvmInitZ = _init = llvm::ConstantStruct::get(structtype,fieldinits);
689 assert(_init);
690
691 std::string initname("_D");
692 initname.append(mangle());
693 initname.append("6__initZ");
694 //Logger::cout() << *_init << '\n';
695 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, NULL, initname, gIR->module);
696 ts->llvmInit = initvar;
697
698 if (needs_definition) {
699 initvar->setInitializer(_init);
700 // generate member functions
701 gIR->topstruct().queueFuncs = false;
702 IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs;
703 size_t n = mfs.size();
704 for (size_t i=0; i<n; ++i) {
705 //mfs[i]->toObjFile();
706 gIR->funcQueue.push_back(mfs[i]);
707 }
708 }
709
710 gIR->classes.pop_back();
711 gIR->structs.pop_back();
712
713 llvmInProgress = false;
714
715 // if (ClassDeclaration::classinfo != this)
716 // DtoClassInfo(this);
717 } 368 }
718 369
719 /****************************************** 370 /******************************************
720 * Get offset of base class's vtbl[] initializer from start of csym. 371 * Get offset of base class's vtbl[] initializer from start of csym.
721 * Returns ~0 if not this csym. 372 * Returns ~0 if not this csym.
730 381
731 void VarDeclaration::toObjFile() 382 void VarDeclaration::toObjFile()
732 { 383 {
733 Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars()); 384 Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars());
734 LOG_SCOPE; 385 LOG_SCOPE;
735 llvm::Module* M = gIR->module;
736 386
737 if (aliassym) 387 if (aliassym)
738 { 388 {
739 Logger::println("alias sym"); 389 Logger::println("alias sym");
740 toAlias()->toObjFile(); 390 toAlias()->toObjFile();
745 if (isDataseg()) 395 if (isDataseg())
746 { 396 {
747 if (llvmTouched) return; 397 if (llvmTouched) return;
748 else llvmTouched = true; 398 else llvmTouched = true;
749 399
750 bool _isconst = false; 400 llvmIRGlobal = new IRGlobal(this);
751 if (isConst() && (init && !init->isExpInitializer())) 401
752 _isconst = true; 402 Logger::println("parent: %s (%s)", parent->toChars(), parent->kind());
403
404 bool _isconst = isConst();
405 if (parent && parent->isFuncDeclaration() && init && init->isExpInitializer())
406 _isconst = false;
753 407
754 llvm::GlobalValue::LinkageTypes _linkage; 408 llvm::GlobalValue::LinkageTypes _linkage;
755 bool istempl = false; 409 bool istempl = false;
410 bool static_local = false;
756 if ((storage_class & STCcomdat) || (parent && DtoIsTemplateInstance(parent))) { 411 if ((storage_class & STCcomdat) || (parent && DtoIsTemplateInstance(parent))) {
757 _linkage = llvm::GlobalValue::WeakLinkage; 412 _linkage = llvm::GlobalValue::WeakLinkage;
758 istempl = true; 413 istempl = true;
759 } 414 }
760 else if (parent && parent->isFuncDeclaration()) 415 else if (parent && parent->isFuncDeclaration()) {
761 _linkage = llvm::GlobalValue::InternalLinkage; 416 _linkage = llvm::GlobalValue::InternalLinkage;
417 static_local = true;
418 }
762 else 419 else
763 _linkage = DtoLinkage(protection, storage_class); 420 _linkage = DtoLinkage(protection, storage_class);
764 421
765 Type* t = DtoDType(type); 422 const llvm::Type* _type = llvmIRGlobal->type.get();
766
767 const llvm::Type* _type = DtoType(t);
768 assert(_type);
769
770 llvm::Constant* _init = 0;
771 bool _signed = !type->isunsigned();
772 423
773 Logger::println("Creating global variable"); 424 Logger::println("Creating global variable");
774 std::string _name(mangle()); 425 std::string _name(mangle());
775 426
776 bool emitRTstaticInit = false; 427 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,NULL,_name,gIR->module);
777
778 if (!(storage_class & STCextern) && (getModule() == gIR->dmodule || istempl))
779 {
780 if (parent && parent->isFuncDeclaration() && init && init->isExpInitializer()) {
781 _init = DtoConstInitializer(t, NULL);
782 emitRTstaticInit = true;
783 }
784 else {
785 _init = DtoConstInitializer(t, init);
786 }
787
788 //Logger::cout() << "initializer: " << *_init << '\n';
789 if (_type != _init->getType()) {
790 Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n";
791 // zero initalizer
792 if (_init->isNullValue())
793 _init = llvm::Constant::getNullValue(_type);
794 // pointer to global constant (struct.init)
795 else if (llvm::isa<llvm::GlobalVariable>(_init))
796 {
797 assert(_init->getType()->getContainedType(0) == _type);
798 llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init);
799 assert(t->ty == Tstruct);
800 TypeStruct* ts = (TypeStruct*)t;
801 assert(ts->sym->llvmInitZ);
802 _init = ts->sym->llvmInitZ;
803 }
804 // array single value init
805 else if (isaArray(_type))
806 {
807 _init = DtoConstStaticArray(_type, _init);
808 }
809 else {
810 Logger::cout() << "Unexpected initializer type: " << *_type << '\n';
811 //assert(0);
812 }
813 }
814 }
815
816 if (_init && _init->getType() != _type)
817 _type = _init->getType();
818 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,_init,_name,M);
819 llvmValue = gvar; 428 llvmValue = gvar;
820 429
821 if (emitRTstaticInit) 430 if (static_local)
822 DtoLazyStaticInit(istempl, gvar, init, t); 431 DtoConstInitGlobal(this);
823 432 else
824 llvmDModule = gIR->dmodule; 433 gIR->constInitQueue.push_back(this);
825 434
826 //if (storage_class & STCprivate) 435 //if (storage_class & STCprivate)
827 // gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility); 436 // gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility);
828 } 437 }
829 438
830 // inside aggregate declaration. declare a field. 439 // inside aggregate declaration. declare a field.
831 else 440 else
832 { 441 {
833 Logger::println("Aggregate var declaration: '%s' offset=%d", toChars(), offset); 442 Logger::println("Aggregate var declaration: '%s' offset=%d", toChars(), offset);
834 443
835 Type* t = DtoDType(type); 444 const llvm::Type* _type = DtoType(type);
836 const llvm::Type* _type = DtoType(t);
837
838 llvm::Constant*_init = DtoConstInitializer(t, init);
839 assert(_init);
840 Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n';
841 if (_type != _init->getType())
842 {
843 if (t->ty == Tsarray)
844 {
845 const llvm::ArrayType* arrty = isaArray(_type);
846 uint64_t n = arrty->getNumElements();
847 std::vector<llvm::Constant*> vals(n,_init);
848 _init = llvm::ConstantArray::get(arrty, vals);
849 }
850 else if (t->ty == Tarray)
851 {
852 assert(isaStruct(_type));
853 _init = llvm::ConstantAggregateZero::get(_type);
854 }
855 else if (t->ty == Tstruct)
856 {
857 const llvm::StructType* structty = isaStruct(_type);
858 TypeStruct* ts = (TypeStruct*)t;
859 assert(ts);
860 assert(ts->sym);
861 assert(ts->sym->llvmInitZ);
862 _init = ts->sym->llvmInitZ;
863 }
864 else if (t->ty == Tclass)
865 {
866 _init = llvm::Constant::getNullValue(_type);
867 }
868 else {
869 Logger::println("failed for type %s", type->toChars());
870 assert(0);
871 }
872 }
873 445
874 // add the field in the IRStruct 446 // add the field in the IRStruct
875 gIR->topstruct().offsets.insert(std::make_pair(offset, IRStruct::Offset(this,_init))); 447 gIR->topstruct()->offsets.insert(std::make_pair(offset, IRStruct::Offset(this, _type)));
876 } 448 }
877 449
878 Logger::println("VarDeclaration::toObjFile is done"); 450 Logger::println("VarDeclaration::toObjFile is done");
879 } 451 }
880 452
899 471
900 /* ================================================================== */ 472 /* ================================================================== */
901 473
902 void FuncDeclaration::toObjFile() 474 void FuncDeclaration::toObjFile()
903 { 475 {
904 if (llvmDModule) { 476 DtoDeclareFunction(this);
905 assert(llvmValue != 0); 477 }
906 return;
907 }
908
909 if (llvmRunTimeHack) {
910 Logger::println("runtime hack func chars: %s", toChars());
911 if (!llvmValue)
912 llvmValue = LLVM_D_GetRuntimeFunction(gIR->module, toChars());
913 return;
914 }
915
916 if (isUnitTestDeclaration()) {
917 Logger::attention("ignoring unittest declaration: %s", toChars());
918 return;
919 }
920
921 Type* t = DtoDType(type);
922 TypeFunction* f = (TypeFunction*)t;
923
924 bool declareOnly = false;
925 if (parent)
926 {
927 if (TemplateInstance* tinst = parent->isTemplateInstance()) {
928 TemplateDeclaration* tempdecl = tinst->tempdecl;
929 if (tempdecl->llvmInternal == LLVMva_start)
930 {
931 Logger::println("magic va_start found");
932 llvmInternal = LLVMva_start;
933 declareOnly = true;
934 }
935 else if (tempdecl->llvmInternal == LLVMva_arg)
936 {
937 Logger::println("magic va_arg found");
938 llvmInternal = LLVMva_arg;
939 return;
940 }
941 }
942 }
943
944 llvm::Function* func = DtoDeclareFunction(this);
945
946 if (declareOnly)
947 return;
948
949 if (!gIR->structs.empty() && gIR->topstruct().queueFuncs) {
950 if (!llvmQueued) {
951 Logger::println("queueing %s", toChars());
952 gIR->topstruct().funcs.push_back(this);
953 llvmQueued = true;
954 }
955 return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete
956 }
957
958 // debug info
959 if (global.params.symdebug) {
960 Module* mo = getModule();
961 if (!mo->llvmCompileUnit) {
962 mo->llvmCompileUnit = DtoDwarfCompileUnit(mo,false);
963 }
964 llvmDwarfSubProgram = DtoDwarfSubProgram(this, mo->llvmCompileUnit);
965 }
966
967 assert(f->llvmType);
968 const llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(llvmValue->getType()->getContainedType(0));
969
970 // template instances should have weak linkage
971 if (parent && DtoIsTemplateInstance(parent)) {
972 func->setLinkage(llvm::GlobalValue::WeakLinkage);
973 }
974
975 // only members of the current module maybe be defined
976 if (getModule() == gIR->dmodule || DtoIsTemplateInstance(parent))
977 {
978 llvmDModule = gIR->dmodule;
979
980 // handle static constructor / destructor
981 if (isStaticCtorDeclaration() || isStaticDtorDeclaration()) {
982 const llvm::ArrayType* sctor_type = llvm::ArrayType::get(llvm::PointerType::get(functype),1);
983 //Logger::cout() << "static ctor type: " << *sctor_type << '\n';
984
985 llvm::Constant* sctor_func = llvm::cast<llvm::Constant>(llvmValue);
986 //Logger::cout() << "static ctor func: " << *sctor_func << '\n';
987
988 llvm::Constant* sctor_init = llvm::ConstantArray::get(sctor_type,&sctor_func,1);
989
990 //Logger::cout() << "static ctor init: " << *sctor_init << '\n';
991
992 // output the llvm.global_ctors array
993 const char* varname = isStaticCtorDeclaration() ? "_d_module_ctor_array" : "_d_module_dtor_array";
994 llvm::GlobalVariable* sctor_arr = new llvm::GlobalVariable(sctor_type, false, llvm::GlobalValue::AppendingLinkage, sctor_init, varname, gIR->module);
995 }
996
997 // function definition
998 if (fbody != 0)
999 {
1000 gIR->functions.push_back(IRFunction(this));
1001 gIR->func().func = func;
1002
1003 // first make absolutely sure the type is up to date
1004 f->llvmType = llvmValue->getType()->getContainedType(0);
1005
1006 //Logger::cout() << "func type: " << *f->llvmType << '\n';
1007
1008 // this handling
1009 if (f->llvmUsesThis) {
1010 Logger::println("uses this");
1011 if (f->llvmRetInPtr)
1012 llvmThisVar = ++func->arg_begin();
1013 else
1014 llvmThisVar = func->arg_begin();
1015 assert(llvmThisVar != 0);
1016 }
1017
1018 if (isMain())
1019 gIR->emitMain = true;
1020
1021 llvm::BasicBlock* beginbb = new llvm::BasicBlock("entry",func);
1022 llvm::BasicBlock* endbb = new llvm::BasicBlock("endentry",func);
1023
1024 //assert(gIR->scopes.empty());
1025 gIR->scopes.push_back(IRScope(beginbb, endbb));
1026
1027 // create alloca point
1028 f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb());
1029 gIR->func().allocapoint = f->llvmAllocaPoint;
1030
1031 // give arguments storage
1032 size_t n = Argument::dim(f->parameters);
1033 for (int i=0; i < n; ++i) {
1034 Argument* arg = Argument::getNth(f->parameters, i);
1035 if (arg && arg->vardecl) {
1036 VarDeclaration* vd = arg->vardecl;
1037 if (!vd->llvmNeedsStorage || vd->nestedref || vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))
1038 continue;
1039 llvm::Value* a = vd->llvmValue;
1040 assert(a);
1041 std::string s(a->getName());
1042 Logger::println("giving argument '%s' storage", s.c_str());
1043 s.append("_storage");
1044 llvm::Value* v = new llvm::AllocaInst(a->getType(),s,f->llvmAllocaPoint);
1045 gIR->ir->CreateStore(a,v);
1046 vd->llvmValue = v;
1047 }
1048 else {
1049 Logger::attention("some unknown argument: %s", arg ? arg->toChars() : 0);
1050 }
1051 }
1052
1053 // debug info
1054 if (global.params.symdebug) DtoDwarfFuncStart(this);
1055
1056 llvm::Value* parentNested = NULL;
1057 if (FuncDeclaration* fd = toParent()->isFuncDeclaration()) {
1058 parentNested = fd->llvmNested;
1059 }
1060
1061 // construct nested variables struct
1062 if (!llvmNestedVars.empty() || parentNested) {
1063 std::vector<const llvm::Type*> nestTypes;
1064 int j = 0;
1065 if (parentNested) {
1066 nestTypes.push_back(parentNested->getType());
1067 j++;
1068 }
1069 for (std::set<VarDeclaration*>::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) {
1070 VarDeclaration* vd = *i;
1071 vd->llvmNestedIndex = j++;
1072 if (vd->isParameter()) {
1073 assert(vd->llvmValue);
1074 nestTypes.push_back(vd->llvmValue->getType());
1075 }
1076 else {
1077 nestTypes.push_back(DtoType(vd->type));
1078 }
1079 }
1080 const llvm::StructType* nestSType = llvm::StructType::get(nestTypes);
1081 Logger::cout() << "nested var struct has type:" << '\n' << *nestSType;
1082 llvmNested = new llvm::AllocaInst(nestSType,"nestedvars",f->llvmAllocaPoint);
1083 if (parentNested) {
1084 assert(llvmThisVar);
1085 llvm::Value* ptr = gIR->ir->CreateBitCast(llvmThisVar, parentNested->getType(), "tmp");
1086 gIR->ir->CreateStore(ptr, DtoGEPi(llvmNested, 0,0, "tmp"));
1087 }
1088 for (std::set<VarDeclaration*>::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) {
1089 VarDeclaration* vd = *i;
1090 if (vd->isParameter()) {
1091 gIR->ir->CreateStore(vd->llvmValue, DtoGEPi(llvmNested, 0, vd->llvmNestedIndex, "tmp"));
1092 vd->llvmValue = llvmNested;
1093 }
1094 }
1095 }
1096
1097 // copy _argptr to a memory location
1098 if (f->linkage == LINKd && f->varargs == 1)
1099 {
1100 llvm::Value* argptrmem = new llvm::AllocaInst(llvmArgPtr->getType(), "_argptrmem", gIR->topallocapoint());
1101 new llvm::StoreInst(llvmArgPtr, argptrmem, gIR->scopebb());
1102 llvmArgPtr = argptrmem;
1103 }
1104
1105 // output function body
1106 fbody->toIR(gIR);
1107
1108 // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement
1109 // in automatically, so we do it here.
1110 if (!isMain()) {
1111 if (!gIR->scopereturned()) {
1112 // pass the previous block into this block
1113 if (global.params.symdebug) DtoDwarfFuncEnd(this);
1114 if (func->getReturnType() == llvm::Type::VoidTy) {
1115 new llvm::ReturnInst(gIR->scopebb());
1116 }
1117 else {
1118 new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), gIR->scopebb());
1119 }
1120 }
1121 }
1122
1123 // erase alloca point
1124 f->llvmAllocaPoint->eraseFromParent();
1125 f->llvmAllocaPoint = 0;
1126 gIR->func().allocapoint = 0;
1127
1128 gIR->scopes.pop_back();
1129
1130 // get rid of the endentry block, it's never used
1131 assert(!func->getBasicBlockList().empty());
1132 func->getBasicBlockList().pop_back();
1133
1134 // if the last block is empty now, it must be unreachable or it's a bug somewhere else
1135 // would be nice to figure out how to assert that this is correct
1136 llvm::BasicBlock* lastbb = &func->getBasicBlockList().back();
1137 if (lastbb->empty()) {
1138 if (lastbb->getNumUses() == 0)
1139 lastbb->eraseFromParent();
1140 else {
1141 new llvm::UnreachableInst(lastbb);
1142 /*if (func->getReturnType() == llvm::Type::VoidTy) {
1143 new llvm::ReturnInst(lastbb);
1144 }
1145 else {
1146 new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), lastbb);
1147 }*/
1148 }
1149 }
1150
1151 gIR->functions.pop_back();
1152 }
1153 }
1154 }