Mercurial > projects > ldc
comparison gen/toobj.c @ 40:8b0e809563df trunk
[svn r44] Lots of bug fixes.
New array literal support
New array ~= operator support (for single element)
New with statement support
More...
author | lindquist |
---|---|
date | Fri, 19 Oct 2007 07:43:21 +0200 |
parents | 27b2f40bdb58 |
children | 6fcc08a4d406 |
comparison
equal
deleted
inserted
replaced
39:fd5e8bbfcb25 | 40:8b0e809563df |
---|---|
9 | 9 |
10 #include <cstddef> | 10 #include <cstddef> |
11 #include <iostream> | 11 #include <iostream> |
12 #include <fstream> | 12 #include <fstream> |
13 | 13 |
14 #include "llvm/Type.h" | 14 #include "gen/llvm.h" |
15 #include "llvm/Constants.h" | |
16 #include "llvm/DerivedTypes.h" | |
17 #include "llvm/Instructions.h" | |
18 #include "llvm/Analysis/Verifier.h" | 15 #include "llvm/Analysis/Verifier.h" |
19 #include "llvm/Bitcode/ReaderWriter.h" | 16 #include "llvm/Bitcode/ReaderWriter.h" |
20 | |
21 #include "llvm/Target/TargetData.h" | |
22 #include "llvm/Target/TargetMachine.h" | 17 #include "llvm/Target/TargetMachine.h" |
23 #include "llvm/Target/TargetMachineRegistry.h" | 18 #include "llvm/Target/TargetMachineRegistry.h" |
24 | 19 |
25 #include "mars.h" | 20 #include "mars.h" |
26 #include "module.h" | 21 #include "module.h" |
150 { | 145 { |
151 Logger::println("checking for offset %u type %s:", os, t->toChars()); | 146 Logger::println("checking for offset %u type %s:", os, t->toChars()); |
152 LOG_SCOPE; | 147 LOG_SCOPE; |
153 for (unsigned i=0; i<fields.dim; ++i) { | 148 for (unsigned i=0; i<fields.dim; ++i) { |
154 VarDeclaration* vd = (VarDeclaration*)fields.data[i]; | 149 VarDeclaration* vd = (VarDeclaration*)fields.data[i]; |
155 Logger::println("found %u type %s", vd->offset, vd->type->toChars()); | 150 Type* vdtype = LLVM_DtoDType(vd->type); |
156 if (os == vd->offset && vd->type == t) { | 151 Logger::println("found %u type %s", vd->offset, vdtype->toChars()); |
152 if (os == vd->offset && vdtype == t) { | |
157 result.push_back(i); | 153 result.push_back(i); |
158 return; | 154 return; |
159 } | 155 } |
160 else if (vd->type->ty == Tstruct && (vd->offset + vd->type->size()) > os) { | 156 else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) { |
161 TypeStruct* ts = (TypeStruct*)vd->type; | 157 TypeStruct* ts = (TypeStruct*)vdtype; |
162 StructDeclaration* sd = ts->sym; | 158 StructDeclaration* sd = ts->sym; |
163 result.push_back(i); | 159 result.push_back(i); |
164 sd->offsetToIndex(t, os - vd->offset, result); | 160 sd->offsetToIndex(t, os - vd->offset, result); |
165 return; | 161 return; |
166 } | 162 } |
210 | 206 |
211 /* ================================================================== */ | 207 /* ================================================================== */ |
212 | 208 |
213 void StructDeclaration::toObjFile() | 209 void StructDeclaration::toObjFile() |
214 { | 210 { |
215 TypeStruct* ts = (TypeStruct*)type; | 211 TypeStruct* ts = (TypeStruct*)LLVM_DtoDType(type); |
216 if (llvmType != 0) | 212 if (llvmType != 0) |
217 return; | 213 return; |
218 | 214 |
219 static int sdi = 0; | 215 static int sdi = 0; |
220 Logger::print("StructDeclaration::toObjFile(%d): %s\n", sdi++, toChars()); | 216 Logger::print("StructDeclaration::toObjFile(%d): %s\n", sdi++, toChars()); |
286 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, _init, initname, gIR->module); | 282 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, _init, initname, gIR->module); |
287 ts->llvmInit = initvar; | 283 ts->llvmInit = initvar; |
288 | 284 |
289 // generate member function definitions | 285 // generate member function definitions |
290 gIR->topstruct().queueFuncs = false; | 286 gIR->topstruct().queueFuncs = false; |
291 IRState::FuncDeclVec& mfs = gIR->topstruct().funcs; | 287 IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs; |
292 size_t n = mfs.size(); | 288 size_t n = mfs.size(); |
293 for (size_t i=0; i<n; ++i) { | 289 for (size_t i=0; i<n; ++i) { |
294 mfs[i]->toObjFile(); | 290 mfs[i]->toObjFile(); |
295 } | 291 } |
296 | 292 |
309 // add base class data members first | 305 // add base class data members first |
310 for (int j=0; j<bcs->dim; j++) | 306 for (int j=0; j<bcs->dim; j++) |
311 { | 307 { |
312 BaseClass* bc = (BaseClass*)(bcs->data[j]); | 308 BaseClass* bc = (BaseClass*)(bcs->data[j]); |
313 assert(bc); | 309 assert(bc); |
310 Logger::println("Adding base class members of %s", bc->base->toChars()); | |
311 LOG_SCOPE; | |
312 | |
314 LLVM_AddBaseClassData(&bc->base->baseclasses); | 313 LLVM_AddBaseClassData(&bc->base->baseclasses); |
315 for (int k=0; k < bc->base->members->dim; k++) { | 314 for (int k=0; k < bc->base->members->dim; k++) { |
316 Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]); | 315 Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]); |
317 if (dsym->isVarDeclaration()) | 316 if (dsym->isVarDeclaration()) |
318 { | 317 { |
322 } | 321 } |
323 } | 322 } |
324 | 323 |
325 void ClassDeclaration::toObjFile() | 324 void ClassDeclaration::toObjFile() |
326 { | 325 { |
327 TypeClass* ts = (TypeClass*)type; | 326 TypeClass* ts = (TypeClass*)LLVM_DtoDType(type); |
328 if (ts->llvmType != 0 || llvmInProgress) | 327 if (ts->llvmType != 0 || llvmInProgress) |
329 return; | 328 return; |
330 | 329 |
331 llvmInProgress = true; | 330 llvmInProgress = true; |
332 | 331 |
451 initvar->setInitializer(_init); | 450 initvar->setInitializer(_init); |
452 } | 451 } |
453 | 452 |
454 // generate member function definitions | 453 // generate member function definitions |
455 gIR->topstruct().queueFuncs = false; | 454 gIR->topstruct().queueFuncs = false; |
456 IRState::FuncDeclVec& mfs = gIR->topstruct().funcs; | 455 IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs; |
457 size_t n = mfs.size(); | 456 size_t n = mfs.size(); |
458 for (size_t i=0; i<n; ++i) { | 457 for (size_t i=0; i<n; ++i) { |
459 mfs[i]->toObjFile(); | 458 mfs[i]->toObjFile(); |
460 } | 459 } |
461 | 460 |
477 | 476 |
478 /* ================================================================== */ | 477 /* ================================================================== */ |
479 | 478 |
480 void VarDeclaration::toObjFile() | 479 void VarDeclaration::toObjFile() |
481 { | 480 { |
482 static int vdi = 0; | 481 Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars()); |
483 Logger::print("VarDeclaration::toObjFile(%d): %s | %s\n", vdi++, toChars(), type->toChars()); | |
484 LOG_SCOPE; | 482 LOG_SCOPE; |
485 llvm::Module* M = gIR->module; | 483 llvm::Module* M = gIR->module; |
486 | 484 |
487 // handle bind pragma | 485 // handle bind pragma |
488 if (llvmInternal == LLVMbind) { | 486 if (llvmInternal == LLVMbind) { |
491 assert(llvmValue); | 489 assert(llvmValue); |
492 return; | 490 return; |
493 } | 491 } |
494 | 492 |
495 // global variable or magic | 493 // global variable or magic |
496 if (isDataseg()) | 494 if (isDataseg() || parent->isModule()) |
497 { | 495 { |
496 if (llvmTouched) return; | |
497 else llvmTouched = true; | |
498 | |
498 bool _isconst = isConst(); | 499 bool _isconst = isConst(); |
499 | 500 |
500 llvm::GlobalValue::LinkageTypes _linkage; | 501 llvm::GlobalValue::LinkageTypes _linkage; |
501 if (parent->isFuncDeclaration()) | 502 if (parent->isFuncDeclaration()) |
502 _linkage = llvm::GlobalValue::InternalLinkage; | 503 _linkage = llvm::GlobalValue::InternalLinkage; |
503 else | 504 else |
504 _linkage = LLVM_DtoLinkage(protection, storage_class); | 505 _linkage = LLVM_DtoLinkage(protection, storage_class); |
505 | 506 |
506 const llvm::Type* _type = LLVM_DtoType(type); | 507 Type* t = LLVM_DtoDType(type); |
508 | |
509 const llvm::Type* _type = LLVM_DtoType(t); | |
507 assert(_type); | 510 assert(_type); |
508 | 511 |
509 llvm::Constant* _init = 0; | 512 llvm::Constant* _init = 0; |
510 bool _signed = !type->isunsigned(); | 513 bool _signed = !type->isunsigned(); |
511 | 514 |
512 Logger::println("Creating global variable"); | 515 Logger::println("Creating global variable"); |
513 std::string _name(mangle()); | 516 std::string _name(mangle()); |
514 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,0,_name,M); | 517 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,0,_name,M); |
515 llvmValue = gvar; | 518 llvmValue = gvar; |
519 | |
516 gIR->lvals.push_back(gvar); | 520 gIR->lvals.push_back(gvar); |
517 | 521 _init = LLVM_DtoConstInitializer(t, init); |
518 _init = LLVM_DtoInitializer(type, init); | 522 gIR->lvals.pop_back(); |
519 assert(_init); | |
520 | 523 |
521 //Logger::cout() << "initializer: " << *_init << '\n'; | 524 //Logger::cout() << "initializer: " << *_init << '\n'; |
522 if (_type != _init->getType()) { | 525 if (_type != _init->getType()) { |
523 Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n"; | 526 Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n"; |
524 // zero initalizer | 527 // zero initalizer |
527 // pointer to global constant (struct.init) | 530 // pointer to global constant (struct.init) |
528 else if (llvm::isa<llvm::GlobalVariable>(_init)) | 531 else if (llvm::isa<llvm::GlobalVariable>(_init)) |
529 { | 532 { |
530 assert(_init->getType()->getContainedType(0) == _type); | 533 assert(_init->getType()->getContainedType(0) == _type); |
531 llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init); | 534 llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init); |
532 assert(type->ty == Tstruct); | 535 assert(t->ty == Tstruct); |
533 TypeStruct* ts = (TypeStruct*)type; | 536 TypeStruct* ts = (TypeStruct*)t; |
534 assert(ts->sym->llvmInitZ); | 537 assert(ts->sym->llvmInitZ); |
535 _init = ts->sym->llvmInitZ; | 538 _init = ts->sym->llvmInitZ; |
536 } | 539 } |
537 // array single value init | 540 // array single value init |
538 else if (llvm::isa<llvm::ArrayType>(_type)) | 541 else if (llvm::isa<llvm::ArrayType>(_type)) |
547 Logger::cout() << "Unexpected initializer type: " << *_type << '\n'; | 550 Logger::cout() << "Unexpected initializer type: " << *_type << '\n'; |
548 //assert(0); | 551 //assert(0); |
549 } | 552 } |
550 } | 553 } |
551 | 554 |
552 gIR->lvals.pop_back(); | |
553 | |
554 gvar->setInitializer(_init); | 555 gvar->setInitializer(_init); |
556 | |
557 llvmDModule = gIR->dmodule; | |
555 | 558 |
556 //if (storage_class & STCprivate) | 559 //if (storage_class & STCprivate) |
557 // gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility); | 560 // gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility); |
558 } | 561 } |
559 | 562 |
560 // inside aggregate declaration. declare a field. | 563 // inside aggregate declaration. declare a field. |
561 else | 564 else |
562 { | 565 { |
563 Logger::println("Aggregate var declaration: '%s' offset=%d", toChars(), offset); | 566 Logger::println("Aggregate var declaration: '%s' offset=%d", toChars(), offset); |
564 | 567 |
565 const llvm::Type* _type = LLVM_DtoType(type); | 568 Type* t = LLVM_DtoDType(type); |
569 const llvm::Type* _type = LLVM_DtoType(t); | |
566 gIR->topstruct().fields.push_back(_type); | 570 gIR->topstruct().fields.push_back(_type); |
567 | 571 |
568 llvm::Constant*_init = LLVM_DtoInitializer(type, init); | 572 llvm::Constant*_init = LLVM_DtoConstInitializer(t, init); |
569 assert(_init); | 573 assert(_init); |
570 Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n'; | 574 Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n'; |
571 if (!_init || _type != _init->getType()) | 575 if (_type != _init->getType()) |
572 { | 576 { |
573 if (type->ty == Tsarray) | 577 if (t->ty == Tsarray) |
574 { | 578 { |
575 const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(_type); | 579 const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(_type); |
576 uint64_t n = arrty->getNumElements(); | 580 uint64_t n = arrty->getNumElements(); |
577 std::vector<llvm::Constant*> vals(n,_init); | 581 std::vector<llvm::Constant*> vals(n,_init); |
578 _init = llvm::ConstantArray::get(arrty, vals); | 582 _init = llvm::ConstantArray::get(arrty, vals); |
579 } | 583 } |
580 else if (type->ty == Tarray) | 584 else if (t->ty == Tarray) |
581 { | 585 { |
582 assert(llvm::isa<llvm::StructType>(_type)); | 586 assert(llvm::isa<llvm::StructType>(_type)); |
583 _init = llvm::ConstantAggregateZero::get(_type); | 587 _init = llvm::ConstantAggregateZero::get(_type); |
584 } | 588 } |
585 else if (type->ty == Tstruct) | 589 else if (t->ty == Tstruct) |
586 { | 590 { |
587 const llvm::StructType* structty = llvm::cast<llvm::StructType>(_type); | 591 const llvm::StructType* structty = llvm::cast<llvm::StructType>(_type); |
588 TypeStruct* ts = (TypeStruct*)type; | 592 TypeStruct* ts = (TypeStruct*)t; |
589 assert(ts); | 593 assert(ts); |
590 assert(ts->sym); | 594 assert(ts->sym); |
591 assert(ts->sym->llvmInitZ); | 595 assert(ts->sym->llvmInitZ); |
592 _init = ts->sym->llvmInitZ; | 596 _init = ts->sym->llvmInitZ; |
593 } | 597 } |
594 else if (type->ty == Tclass) | 598 else if (t->ty == Tclass) |
595 { | 599 { |
596 _init = llvm::Constant::getNullValue(_type); | 600 _init = llvm::Constant::getNullValue(_type); |
597 } | 601 } |
598 else { | 602 else { |
599 Logger::println("failed for type %s", type->toChars()); | 603 Logger::println("failed for type %s", type->toChars()); |
642 llvmQueued = true; | 646 llvmQueued = true; |
643 } | 647 } |
644 return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete | 648 return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete |
645 } | 649 } |
646 | 650 |
647 TypeFunction* f = (TypeFunction*)type; | 651 Type* t = LLVM_DtoDType(type); |
652 TypeFunction* f = (TypeFunction*)t; | |
648 assert(f->llvmType); | 653 assert(f->llvmType); |
649 const llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(llvmValue->getType()->getContainedType(0)); | 654 const llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(llvmValue->getType()->getContainedType(0)); |
650 | 655 |
651 // only members of the current module maybe be defined | 656 // only members of the current module maybe be defined |
652 if (getModule() == gIR->dmodule || parent->isTemplateInstance()) | 657 if (getModule() == gIR->dmodule || parent->isTemplateInstance()) |
682 } | 687 } |
683 | 688 |
684 // function definition | 689 // function definition |
685 if (allow_fbody && fbody != 0) | 690 if (allow_fbody && fbody != 0) |
686 { | 691 { |
687 gIR->funcdecls.push_back(this); | 692 gIR->functions.push_back(IRFunction(this)); |
693 gIR->func().func = func; | |
688 | 694 |
689 // first make absolutely sure the type is up to date | 695 // first make absolutely sure the type is up to date |
690 f->llvmType = llvmValue->getType()->getContainedType(0); | 696 f->llvmType = llvmValue->getType()->getContainedType(0); |
691 | 697 |
692 Logger::cout() << "func type: " << *f->llvmType << '\n'; | 698 Logger::cout() << "func type: " << *f->llvmType << '\n'; |
701 } | 707 } |
702 | 708 |
703 if (isMain()) | 709 if (isMain()) |
704 gIR->emitMain = true; | 710 gIR->emitMain = true; |
705 | 711 |
706 gIR->funcs.push(func); | 712 llvm::BasicBlock* beginbb = new llvm::BasicBlock("entry",func); |
707 gIR->functypes.push(f); | 713 llvm::BasicBlock* endbb = new llvm::BasicBlock("endentry",func); |
708 | |
709 IRScope irs; | |
710 irs.begin = new llvm::BasicBlock("entry",func); | |
711 irs.end = new llvm::BasicBlock("endentry",func); | |
712 | 714 |
713 //assert(gIR->scopes.empty()); | 715 //assert(gIR->scopes.empty()); |
714 gIR->scopes.push_back(irs); | 716 gIR->scopes.push_back(IRScope(beginbb, endbb)); |
715 | 717 |
716 // create alloca point | 718 // create alloca point |
717 f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb()); | 719 f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb()); |
720 gIR->func().allocapoint = f->llvmAllocaPoint; | |
718 | 721 |
719 // output function body | 722 // output function body |
720 fbody->toIR(gIR); | 723 fbody->toIR(gIR); |
721 | 724 |
722 // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement | 725 // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement |
723 // in automatically, so we do it here. | 726 // in automatically, so we do it here. |
724 if (!isMain() && (gIR->scopebb()->empty() || !llvm::isa<llvm::TerminatorInst>(gIR->scopebb()->back()))) { | 727 if (!isMain()) { |
725 // pass the previous block into this block | 728 if (gIR->scopebb()->empty() || !llvm::isa<llvm::TerminatorInst>(gIR->scopebb()->back())) { |
726 //new llvm::BranchInst(irs.end, irs.begin); | 729 // pass the previous block into this block |
727 new llvm::ReturnInst(gIR->scopebb()); | 730 //new llvm::BranchInst(irs.end, irs.begin); |
731 if (func->getReturnType() == llvm::Type::VoidTy) { | |
732 new llvm::ReturnInst(gIR->scopebb()); | |
733 } | |
734 | |
735 } | |
728 } | 736 } |
729 | 737 |
730 // erase alloca point | 738 // erase alloca point |
731 f->llvmAllocaPoint->eraseFromParent(); | 739 f->llvmAllocaPoint->eraseFromParent(); |
732 f->llvmAllocaPoint = 0; | 740 f->llvmAllocaPoint = 0; |
741 gIR->func().allocapoint = 0; | |
733 | 742 |
734 gIR->scopes.pop_back(); | 743 gIR->scopes.pop_back(); |
735 //assert(gIR->scopes.empty()); | |
736 | |
737 gIR->functypes.pop(); | |
738 gIR->funcs.pop(); | |
739 | 744 |
740 // get rid of the endentry block, it's never used | 745 // get rid of the endentry block, it's never used |
741 assert(!func->getBasicBlockList().empty()); | 746 assert(!func->getBasicBlockList().empty()); |
742 func->getBasicBlockList().pop_back(); | 747 func->getBasicBlockList().pop_back(); |
743 | 748 |
744 // if the last block is empty now, it must be unreachable or it's a bug somewhere else | 749 // if the last block is empty now, it must be unreachable or it's a bug somewhere else |
745 // would be nice to figure out how to assert that this is correct | 750 // would be nice to figure out how to assert that this is correct |
746 llvm::BasicBlock* lastbb = &func->getBasicBlockList().back(); | 751 llvm::BasicBlock* lastbb = &func->getBasicBlockList().back(); |
747 if (lastbb->empty()) { | 752 if (lastbb->empty()) { |
748 // possibly assert(lastbb->getNumPredecessors() == 0); ??? try it out sometime ... | 753 lastbb->eraseFromParent(); |
749 new llvm::UnreachableInst(lastbb); | 754 } |
750 } | 755 |
751 | 756 gIR->functions.pop_back(); |
752 gIR->funcdecls.pop_back(); | |
753 } | 757 } |
754 | 758 |
755 // template instances should have weak linkage | 759 // template instances should have weak linkage |
756 if (parent->isTemplateInstance()) { | 760 if (parent->isTemplateInstance()) { |
757 func->setLinkage(llvm::GlobalValue::WeakLinkage); | 761 func->setLinkage(llvm::GlobalValue::WeakLinkage); |