Mercurial > projects > ldc
comparison gen/toobj.c @ 52:0c77619e803b trunk
[svn r56] Initial support for TypeInfo.
Enums not work.
Several other bugfixes.
author | lindquist |
---|---|
date | Tue, 23 Oct 2007 05:55:12 +0200 |
parents | 6fcc08a4d406 |
children | 28e99b04a132 |
comparison
equal
deleted
inserted
replaced
51:61bc1b4ad3c4 | 52:0c77619e803b |
---|---|
96 } | 96 } |
97 | 97 |
98 // run passes | 98 // run passes |
99 // TODO | 99 // TODO |
100 | 100 |
101 /*if (global.params.llvmLL) { | |
102 //assert(0); | |
103 std::ofstream os(llfile->name->toChars()); | |
104 //llvm::WriteAssemblyToFile(ir.module, os); | |
105 ir.module->print(os); | |
106 }*/ | |
107 | |
108 // write bytecode | 101 // write bytecode |
109 //if (global.params.llvmBC) { | 102 { |
110 Logger::println("Writing LLVM bitcode\n"); | 103 Logger::println("Writing LLVM bitcode\n"); |
111 std::ofstream os(bcfile->name->toChars(), std::ios::binary); | 104 std::ofstream bos(bcfile->name->toChars(), std::ios::binary); |
112 llvm::WriteBitcodeToFile(ir.module, os); | 105 llvm::WriteBitcodeToFile(ir.module, bos); |
113 //} | 106 } |
107 | |
108 // disassemble ? | |
109 if (global.params.disassemble) { | |
110 Logger::println("Writing LLVM asm to: %s\n", llfile->name->toChars()); | |
111 std::ofstream aos(llfile->name->toChars()); | |
112 ir.module->print(aos); | |
113 } | |
114 | 114 |
115 delete ir.module; | 115 delete ir.module; |
116 gIR = NULL; | 116 gIR = NULL; |
117 } | 117 } |
118 | 118 |
293 llvmDModule = gIR->dmodule; | 293 llvmDModule = gIR->dmodule; |
294 | 294 |
295 gIR->structs.pop_back(); | 295 gIR->structs.pop_back(); |
296 | 296 |
297 // generate typeinfo | 297 // generate typeinfo |
298 type->getTypeInfo(NULL); // generate TypeInfo | 298 //type->getTypeInfo(NULL); |
299 } | 299 } |
300 | 300 |
301 /* ================================================================== */ | 301 /* ================================================================== */ |
302 | 302 |
303 static void LLVM_AddBaseClassData(BaseClasses* bcs) | 303 static void LLVM_AddBaseClassData(BaseClasses* bcs) |
405 const llvm::StructType* svtbl_ty = 0; | 405 const llvm::StructType* svtbl_ty = 0; |
406 if (!sinits.empty()) | 406 if (!sinits.empty()) |
407 { | 407 { |
408 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; | 408 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; |
409 | 409 |
410 std::string varname(mangle()); | 410 std::string varname("_D"); |
411 varname.append("__vtblZ"); | 411 varname.append(mangle()); |
412 varname.append("6__vtblZ"); | |
413 | |
412 std::string styname(mangle()); | 414 std::string styname(mangle()); |
413 styname.append("__vtblTy"); | 415 styname.append("__vtblTy"); |
414 | 416 |
415 svtbl_ty = llvm::StructType::get(sinits_ty); | 417 svtbl_ty = llvm::StructType::get(sinits_ty); |
416 gIR->module->addTypeName(styname, svtbl_ty); | 418 gIR->module->addTypeName(styname, svtbl_ty); |
439 assert(svtblVar != 0); | 441 assert(svtblVar != 0); |
440 gIR->topstruct().inits[0] = svtblVar; | 442 gIR->topstruct().inits[0] = svtblVar; |
441 | 443 |
442 _init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits); | 444 _init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits); |
443 assert(_init); | 445 assert(_init); |
444 std::string initname(mangle()); | 446 |
445 initname.append("__initZ"); | 447 std::string initname("_D"); |
448 initname.append(mangle()); | |
449 initname.append("6__initZ"); | |
446 //Logger::cout() << *_init << '\n'; | 450 //Logger::cout() << *_init << '\n'; |
447 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, 0, initname, gIR->module); | 451 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, 0, initname, gIR->module); |
448 ts->llvmInit = initvar; | 452 ts->llvmInit = initvar; |
449 if (define_vtable) { | 453 if (define_vtable) { |
450 initvar->setInitializer(_init); | 454 initvar->setInitializer(_init); |
497 else llvmTouched = true; | 501 else llvmTouched = true; |
498 | 502 |
499 bool _isconst = isConst(); | 503 bool _isconst = isConst(); |
500 | 504 |
501 llvm::GlobalValue::LinkageTypes _linkage; | 505 llvm::GlobalValue::LinkageTypes _linkage; |
502 if (parent->isFuncDeclaration()) | 506 if (parent && parent->isFuncDeclaration()) |
503 _linkage = llvm::GlobalValue::InternalLinkage; | 507 _linkage = llvm::GlobalValue::InternalLinkage; |
504 else | 508 else |
505 _linkage = LLVM_DtoLinkage(protection, storage_class); | 509 _linkage = LLVM_DtoLinkage(protection, storage_class); |
506 | 510 |
507 Type* t = LLVM_DtoDType(type); | 511 Type* t = LLVM_DtoDType(type); |
512 llvm::Constant* _init = 0; | 516 llvm::Constant* _init = 0; |
513 bool _signed = !type->isunsigned(); | 517 bool _signed = !type->isunsigned(); |
514 | 518 |
515 Logger::println("Creating global variable"); | 519 Logger::println("Creating global variable"); |
516 std::string _name(mangle()); | 520 std::string _name(mangle()); |
521 | |
517 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,0,_name,M); | 522 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,0,_name,M); |
518 llvmValue = gvar; | 523 llvmValue = gvar; |
519 | 524 |
520 gIR->lvals.push_back(gvar); | 525 // if extern don't emit initializer |
521 _init = LLVM_DtoConstInitializer(t, init); | 526 if (!(storage_class & STCextern)) |
522 gIR->lvals.pop_back(); | 527 { |
523 | 528 gIR->lvals.push_back(gvar); |
524 //Logger::cout() << "initializer: " << *_init << '\n'; | 529 _init = LLVM_DtoConstInitializer(t, init); |
525 if (_type != _init->getType()) { | 530 gIR->lvals.pop_back(); |
526 Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n"; | 531 |
527 // zero initalizer | 532 //Logger::cout() << "initializer: " << *_init << '\n'; |
528 if (_init->isNullValue()) | 533 if (_type != _init->getType()) { |
529 _init = llvm::Constant::getNullValue(_type); | 534 Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n"; |
530 // pointer to global constant (struct.init) | 535 // zero initalizer |
531 else if (llvm::isa<llvm::GlobalVariable>(_init)) | 536 if (_init->isNullValue()) |
532 { | 537 _init = llvm::Constant::getNullValue(_type); |
533 assert(_init->getType()->getContainedType(0) == _type); | 538 // pointer to global constant (struct.init) |
534 llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init); | 539 else if (llvm::isa<llvm::GlobalVariable>(_init)) |
535 assert(t->ty == Tstruct); | 540 { |
536 TypeStruct* ts = (TypeStruct*)t; | 541 assert(_init->getType()->getContainedType(0) == _type); |
537 assert(ts->sym->llvmInitZ); | 542 llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init); |
538 _init = ts->sym->llvmInitZ; | 543 assert(t->ty == Tstruct); |
539 } | 544 TypeStruct* ts = (TypeStruct*)t; |
540 // array single value init | 545 assert(ts->sym->llvmInitZ); |
541 else if (llvm::isa<llvm::ArrayType>(_type)) | 546 _init = ts->sym->llvmInitZ; |
542 { | 547 } |
543 const llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(_type); | 548 // array single value init |
544 assert(_type->getContainedType(0) == _init->getType()); | 549 else if (llvm::isa<llvm::ArrayType>(_type)) |
545 std::vector<llvm::Constant*> initvals; | 550 { |
546 initvals.resize(at->getNumElements(), _init); | 551 const llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(_type); |
547 _init = llvm::ConstantArray::get(at, initvals); | 552 assert(_type->getContainedType(0) == _init->getType()); |
548 } | 553 std::vector<llvm::Constant*> initvals; |
549 else { | 554 initvals.resize(at->getNumElements(), _init); |
550 Logger::cout() << "Unexpected initializer type: " << *_type << '\n'; | 555 _init = llvm::ConstantArray::get(at, initvals); |
551 //assert(0); | 556 } |
552 } | 557 else { |
553 } | 558 Logger::cout() << "Unexpected initializer type: " << *_type << '\n'; |
554 | 559 //assert(0); |
555 gvar->setInitializer(_init); | 560 } |
556 | 561 } |
562 | |
563 gvar->setInitializer(_init); | |
564 } | |
565 | |
557 llvmDModule = gIR->dmodule; | 566 llvmDModule = gIR->dmodule; |
558 | 567 |
559 //if (storage_class & STCprivate) | 568 //if (storage_class & STCprivate) |
560 // gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility); | 569 // gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility); |
561 } | 570 } |
616 { | 625 { |
617 static int tdi = 0; | 626 static int tdi = 0; |
618 Logger::print("TypedefDeclaration::toObjFile(%d): %s\n", tdi++, toChars()); | 627 Logger::print("TypedefDeclaration::toObjFile(%d): %s\n", tdi++, toChars()); |
619 LOG_SCOPE; | 628 LOG_SCOPE; |
620 | 629 |
621 // TODO | 630 // generate typeinfo |
631 type->getTypeInfo(NULL); | |
622 } | 632 } |
623 | 633 |
624 /* ================================================================== */ | 634 /* ================================================================== */ |
625 | 635 |
626 void EnumDeclaration::toObjFile() | 636 void EnumDeclaration::toObjFile() |
693 gIR->func().func = func; | 703 gIR->func().func = func; |
694 | 704 |
695 // first make absolutely sure the type is up to date | 705 // first make absolutely sure the type is up to date |
696 f->llvmType = llvmValue->getType()->getContainedType(0); | 706 f->llvmType = llvmValue->getType()->getContainedType(0); |
697 | 707 |
698 Logger::cout() << "func type: " << *f->llvmType << '\n'; | 708 //Logger::cout() << "func type: " << *f->llvmType << '\n'; |
699 | 709 |
700 // this handling | 710 // this handling |
701 if (f->llvmUsesThis) { | 711 if (f->llvmUsesThis) { |
702 Logger::println("uses this"); | 712 Logger::println("uses this"); |
703 if (f->llvmRetInPtr) | 713 if (f->llvmRetInPtr) |
752 fbody->toIR(gIR); | 762 fbody->toIR(gIR); |
753 | 763 |
754 // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement | 764 // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement |
755 // in automatically, so we do it here. | 765 // in automatically, so we do it here. |
756 if (!isMain()) { | 766 if (!isMain()) { |
757 if (gIR->scopebb()->empty() || !llvm::isa<llvm::TerminatorInst>(gIR->scopebb()->back())) { | 767 if (!gIR->scopereturned()) { |
758 // pass the previous block into this block | 768 // pass the previous block into this block |
759 //new llvm::BranchInst(irs.end, irs.begin); | 769 //new llvm::BranchInst(irs.end, irs.begin); |
760 if (func->getReturnType() == llvm::Type::VoidTy) { | 770 if (func->getReturnType() == llvm::Type::VoidTy) { |
761 new llvm::ReturnInst(gIR->scopebb()); | 771 new llvm::ReturnInst(gIR->scopebb()); |
762 } | 772 } |
773 else { | |
774 new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), gIR->scopebb()); | |
775 } | |
763 } | 776 } |
764 } | 777 } |
765 | 778 |
766 // erase alloca point | 779 // erase alloca point |
767 f->llvmAllocaPoint->eraseFromParent(); | 780 f->llvmAllocaPoint->eraseFromParent(); |
776 | 789 |
777 // if the last block is empty now, it must be unreachable or it's a bug somewhere else | 790 // if the last block is empty now, it must be unreachable or it's a bug somewhere else |
778 // would be nice to figure out how to assert that this is correct | 791 // would be nice to figure out how to assert that this is correct |
779 llvm::BasicBlock* lastbb = &func->getBasicBlockList().back(); | 792 llvm::BasicBlock* lastbb = &func->getBasicBlockList().back(); |
780 if (lastbb->empty()) { | 793 if (lastbb->empty()) { |
781 lastbb->eraseFromParent(); | 794 if (lastbb->getNumUses() == 0) |
795 lastbb->eraseFromParent(); | |
796 else { | |
797 new llvm::UnreachableInst(lastbb); | |
798 /*if (func->getReturnType() == llvm::Type::VoidTy) { | |
799 new llvm::ReturnInst(lastbb); | |
800 } | |
801 else { | |
802 new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), lastbb); | |
803 }*/ | |
804 } | |
782 } | 805 } |
783 | 806 |
784 gIR->functions.pop_back(); | 807 gIR->functions.pop_back(); |
785 } | 808 } |
786 | 809 |