comparison gen/toobj.c @ 9:dafae18f9c08 trunk

[svn r13] * Updated for LLVM 2.1 * Class v-tables are now typesafe * Code cleanups
author lindquist
date Mon, 01 Oct 2007 21:19:53 +0200
parents 5e69b77a5c51
children c0f2c47e5034
comparison
equal deleted inserted replaced
8:5e69b77a5c51 9:dafae18f9c08
334 gIR->classes.push_back(this); 334 gIR->classes.push_back(this);
335 gIR->classmethods.push_back(IRState::FuncDeclVec()); 335 gIR->classmethods.push_back(IRState::FuncDeclVec());
336 gIR->queueClassMethods.push_back(true); 336 gIR->queueClassMethods.push_back(true);
337 337
338 // add vtable 338 // add vtable
339 const llvm::Type* vtabty = llvm::PointerType::get(llvm::Type::Int8Ty); 339 llvm::PATypeHolder pa = llvm::OpaqueType::get();
340 const llvm::Type* vtabty = llvm::PointerType::get(pa);
340 gIR->topstruct().fields.push_back(vtabty); 341 gIR->topstruct().fields.push_back(vtabty);
341 gIR->topstruct().inits.push_back(0); 342 gIR->topstruct().inits.push_back(0);
342 343
343 // base classes first 344 // base classes first
344 LLVM_AddBaseClassData(&baseclasses); 345 LLVM_AddBaseClassData(&baseclasses);
359 } 360 }
360 361
361 ts->llvmType = structtype; 362 ts->llvmType = structtype;
362 llvmType = structtype; 363 llvmType = structtype;
363 364
364 bool emit_vtable = false;
365 bool define_vtable = false; 365 bool define_vtable = false;
366 if (parent->isModule()) { 366 if (parent->isModule()) {
367 gIR->module->addTypeName(mangle(),ts->llvmType); 367 gIR->module->addTypeName(mangle(),ts->llvmType);
368 emit_vtable = true;
369 define_vtable = (getModule() == gIR->dmodule); 368 define_vtable = (getModule() == gIR->dmodule);
370 } 369 }
371 else { 370 else {
372 assert(0 && "class parent is not a module"); 371 assert(0 && "class parent is not a module");
373 } 372 }
374 373
375 // generate member functions 374 // generate vtable
375 llvm::GlobalVariable* svtblVar = 0;
376 std::vector<llvm::Constant*> sinits;
377 std::vector<const llvm::Type*> sinits_ty;
378 sinits.reserve(vtbl.dim);
379 sinits_ty.reserve(vtbl.dim);
380
381 for (int k=0; k < vtbl.dim; k++)
382 {
383 Dsymbol* dsym = (Dsymbol*)vtbl.data[k];
384 assert(dsym);
385 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
386
387 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
388 fd->toObjFile();
389 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
390 sinits.push_back(c);
391 sinits_ty.push_back(c->getType());
392 }
393 else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
394 const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty);
395 llvm::Constant* c = llvm::Constant::getNullValue(cty);
396 sinits.push_back(c);
397 sinits_ty.push_back(cty);
398 }
399 else
400 assert(0);
401 }
402
403 const llvm::StructType* svtbl_ty = 0;
404 if (!sinits.empty())
405 {
406 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
407
408 std::string varname(mangle());
409 varname.append("__vtblZ");
410 std::string styname(mangle());
411 styname.append("__vtblTy");
412
413 svtbl_ty = llvm::StructType::get(sinits_ty);
414 gIR->module->addTypeName(styname, svtbl_ty);
415 svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
416
417 if (define_vtable) {
418 svtblVar->setInitializer(llvm::ConstantStruct::get(svtbl_ty, sinits));
419 }
420 llvmVtbl = svtblVar;
421 }
422
423 ////////////////////////////////////////////////////////////////////////////////
424
425 // refine for final vtable type
426 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(svtbl_ty);
427 svtbl_ty = llvm::cast<llvm::StructType>(pa.get());
428 structtype = llvm::cast<llvm::StructType>(gIR->topstruct().recty.get());
429 ts->llvmType = structtype;
430 llvmType = structtype;
431
432 // generate initializer
433 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
434 llvm::Constant* _init = 0;
435
436 // first field is always the vtable
437 assert(svtblVar != 0);
438 gIR->topstruct().inits[0] = svtblVar;
439
440 //assert(tk == gIR->topstruct().size());
441 #ifndef LLVMD_NO_LOGGER
442 Logger::cout() << *structtype << '\n';
443 //for (size_t k=0; k<gIR->topstruct().inits.size(); ++k)
444 // Logger::cout() << *gIR->topstruct().inits[k] << '\n';
445 #endif
446 _init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits);
447 assert(_init);
448 std::string initname(mangle());
449 initname.append("__initZ");
450 Logger::cout() << *_init << '\n';
451 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, 0, initname, gIR->module);
452 ts->llvmInit = initvar;
453 if (define_vtable) {
454 initvar->setInitializer(_init);
455 }
456
457 // generate member function definitions
376 gIR->queueClassMethods.back() = false; 458 gIR->queueClassMethods.back() = false;
377 IRState::FuncDeclVec& mfs = gIR->classmethods.back(); 459 IRState::FuncDeclVec& mfs = gIR->classmethods.back();
378 size_t n = mfs.size(); 460 size_t n = mfs.size();
379 for (size_t i=0; i<n; ++i) { 461 for (size_t i=0; i<n; ++i) {
380 mfs[i]->toObjFile(); 462 mfs[i]->toObjFile();
381 }
382
383 // create vtable initializer
384 if (emit_vtable)
385 {
386 llvm::GlobalVariable* vtblVar = 0;
387 std::vector<llvm::Constant*> inits;
388 inits.reserve(vtbl.dim);
389 for (int k=0; k < vtbl.dim; k++)
390 {
391 Dsymbol* dsym = (Dsymbol*)vtbl.data[k];
392 assert(dsym);
393 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
394
395 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
396 fd->toObjFile();
397 Logger::cout() << "casting to constant" << *fd->llvmValue << '\n';
398 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
399 c = llvm::ConstantExpr::getBitCast(c, llvm::PointerType::get(llvm::Type::Int8Ty));
400 inits.push_back(c);
401 }
402 else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
403 llvm::Constant* c = llvm::Constant::getNullValue(llvm::PointerType::get(llvm::Type::Int8Ty));
404 inits.push_back(c);
405 }
406 else
407 assert(0);
408 }
409 if (!inits.empty())
410 {
411 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
412 std::string varname(mangle());
413 varname.append("__vtblZ");
414 const llvm::ArrayType* vtbl_ty = llvm::ArrayType::get(llvm::PointerType::get(llvm::Type::Int8Ty), inits.size());
415 vtblVar = new llvm::GlobalVariable(vtbl_ty, true, _linkage, 0, varname, gIR->module);
416 if (define_vtable) {
417 //Logger::cout() << "vtbl:::" << '\n' << *vtbl_st << '\n';// << " == | == " << _init << '\n';
418 llvm::Constant* _init = llvm::ConstantArray::get(vtbl_ty, inits);
419 vtblVar->setInitializer(_init);
420 }
421 llvmVtbl = vtblVar;
422 }
423
424 ////////////////////////////////////////////////////////////////////////////////
425
426 // generate initializer
427 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
428 llvm::Constant* _init = 0;
429
430 // first field is always the vtable
431 assert(vtblVar != 0);
432 llvm::Constant* vtbl_init_var = llvm::ConstantExpr::getBitCast(vtblVar, llvm::PointerType::get(llvm::Type::Int8Ty));
433 gIR->topstruct().inits[0] = vtbl_init_var;
434
435 //assert(tk == gIR->topstruct().size());
436 #ifndef LLVMD_NO_LOGGER
437 Logger::cout() << *structtype << '\n';
438 for (size_t k=0; k<gIR->topstruct().inits.size(); ++k)
439 Logger::cout() << *gIR->topstruct().inits[k] << '\n';
440 #endif
441 _init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits);
442 assert(_init);
443 std::string initname(mangle());
444 initname.append("__initZ");
445 Logger::cout() << *_init << '\n';
446 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, 0, initname, gIR->module);
447 ts->llvmInit = initvar;
448 if (define_vtable) {
449 initvar->setInitializer(_init);
450 }
451 } 463 }
452 464
453 gIR->queueClassMethods.pop_back(); 465 gIR->queueClassMethods.pop_back();
454 gIR->classmethods.pop_back(); 466 gIR->classmethods.pop_back();
455 gIR->classes.pop_back(); 467 gIR->classes.pop_back();
558 _init = llvm::ConstantArray::get(arrty, vals); 570 _init = llvm::ConstantArray::get(arrty, vals);
559 } 571 }
560 else if (llvm::isa<llvm::StructType>(_type)) { 572 else if (llvm::isa<llvm::StructType>(_type)) {
561 const llvm::StructType* structty = llvm::cast<llvm::StructType>(_type); 573 const llvm::StructType* structty = llvm::cast<llvm::StructType>(_type);
562 TypeStruct* ts = (TypeStruct*)type; 574 TypeStruct* ts = (TypeStruct*)type;
575 assert(ts);
576 assert(ts->sym);
563 assert(ts->sym->llvmInitZ); 577 assert(ts->sym->llvmInitZ);
564 _init = ts->sym->llvmInitZ; 578 _init = ts->sym->llvmInitZ;
565 } 579 }
566 else 580 else
567 assert(0); 581 assert(0);
592 606
593 /* ================================================================== */ 607 /* ================================================================== */
594 608
595 void FuncDeclaration::toObjFile() 609 void FuncDeclaration::toObjFile()
596 { 610 {
597 if (llvmValue != 0 && llvmDModule == gIR->dmodule) { 611 if (llvmDModule == gIR->dmodule) {
612 assert(llvmValue != 0);
598 return; 613 return;
599 } 614 }
600 615
601 // has already been pulled in by a reference to ( 616 llvm::Function* func = LLVM_DtoDeclareFunction(this);
617
602 if (!gIR->queueClassMethods.empty() && gIR->queueClassMethods.back()) { 618 if (!gIR->queueClassMethods.empty() && gIR->queueClassMethods.back()) {
603 Logger::println("queueing %s", toChars()); 619 Logger::println("queueing %s", toChars());
604 assert(!gIR->classmethods.empty()); 620 assert(!gIR->classmethods.empty());
605 gIR->classmethods.back().push_back(this); 621 gIR->classmethods.back().push_back(this);
606 return; // will be generated later when the this parameter has a type 622 return; // will be generated later when the this parameter has a type
607 } 623 }
608 624
609 static int fdi = 0; 625 if (llvmNeedsDefinition)
610 Logger::print("FuncDeclaration::toObjFile(%d,%s): %s\n", fdi++, needThis()?"this":"static",toChars()); 626 {
611 LOG_SCOPE;
612
613 if (llvmInternal == LLVMintrinsic && fbody) {
614 error("intrinsics cannot have function bodies");
615 fatal();
616 }
617 627
618 TypeFunction* f = (TypeFunction*)type; 628 TypeFunction* f = (TypeFunction*)type;
619 assert(f != 0); 629 llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(f->llvmType);
620
621 // return value type
622 const llvm::Type* rettype;
623 const llvm::Type* actualRettype;
624 Type* rt = f->next;
625 bool retinptr = false;
626 bool usesthis = false;
627
628 if (isMain()) {
629 rettype = llvm::Type::Int32Ty;
630 actualRettype = rettype;
631 gIR->emitMain = true;
632 }
633 else if (rt) {
634 if (rt->ty == Tstruct || rt->ty == Tdelegate || rt->ty == Tarray) {
635 rettype = llvm::PointerType::get(LLVM_DtoType(rt));
636 actualRettype = llvm::Type::VoidTy;
637 f->llvmRetInPtr = retinptr = true;
638 }
639 else {
640 rettype = LLVM_DtoType(rt);
641 actualRettype = rettype;
642 }
643 }
644 else {
645 assert(0);
646 }
647
648 // parameter types
649 std::vector<const llvm::Type*> paramvec;
650
651 if (retinptr) {
652 Logger::print("returning through pointer parameter\n");
653 paramvec.push_back(rettype);
654 }
655
656 if (needThis()) {
657 if (AggregateDeclaration* ad = isMember()) {
658 Logger::print("isMember = this is: %s\n", ad->type->toChars());
659 const llvm::Type* thisty = LLVM_DtoType(ad->type);
660 if (llvm::isa<llvm::StructType>(thisty))
661 thisty = llvm::PointerType::get(thisty);
662 paramvec.push_back(thisty);
663 usesthis = true;
664 }
665 else
666 assert(0);
667 }
668
669 size_t n = Argument::dim(f->parameters);
670 for (int i=0; i < n; ++i) {
671 Argument* arg = Argument::getNth(f->parameters, i);
672 // ensure scalar
673 Type* argT = arg->type;
674 assert(argT);
675
676 if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
677 //assert(arg->vardecl);
678 //arg->vardecl->refparam = true;
679 }
680 else
681 arg->llvmCopy = true;
682
683 const llvm::Type* at = LLVM_DtoType(argT);
684 if (llvm::isa<llvm::StructType>(at)) {
685 Logger::println("struct param");
686 paramvec.push_back(llvm::PointerType::get(at));
687 }
688 else if (llvm::isa<llvm::ArrayType>(at)) {
689 Logger::println("sarray param");
690 assert(argT->ty == Tsarray);
691 //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0)));
692 paramvec.push_back(llvm::PointerType::get(at));
693 }
694 else {
695 if (!arg->llvmCopy) {
696 Logger::println("ref param");
697 at = llvm::PointerType::get(at);
698 }
699 else {
700 Logger::println("in param");
701 }
702 paramvec.push_back(at);
703 }
704 }
705
706 // construct function
707 bool isvararg = f->varargs;
708 llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
709
710 // mangled name
711 char* mangled_name = (llvmInternal == LLVMintrinsic) ? llvmInternal1 : mangle();
712 llvm::Function* func = gIR->module->getFunction(mangled_name);
713
714 // make the function
715 /*if (func != 0) {
716 llvmValue = func;
717 f->llvmType = functype;
718 return; // already pulled in from a forward declaration
719 }
720 else */
721 if (func == 0) {
722 func = new llvm::Function(functype,LLVM_DtoLinkage(protection, storage_class),mangled_name,gIR->module);
723 }
724
725 if (llvmInternal != LLVMintrinsic)
726 func->setCallingConv(LLVM_DtoCallingConv(f->linkage));
727
728 llvmValue = func;
729 f->llvmType = functype;
730
731 if (isMain()) {
732 gIR->mainFunc = func;
733 }
734
735 // name parameters
736 llvm::Function::arg_iterator iarg = func->arg_begin();
737 int k = 0;
738 int nunnamed = 0;
739 if (retinptr) {
740 iarg->setName("retval");
741 f->llvmRetArg = iarg;
742 ++iarg;
743 }
744 if (usesthis) {
745 iarg->setName("this");
746 ++iarg;
747 }
748 for (; iarg != func->arg_end(); ++iarg)
749 {
750 Argument* arg = Argument::getNth(f->parameters, k++);
751 //arg->llvmValue = iarg;
752 //printf("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident);
753 if (arg->ident != 0) {
754 if (arg->vardecl) {
755 arg->vardecl->llvmValue = iarg;
756 }
757 iarg->setName(arg->ident->toChars());
758 }
759 else {
760 ++nunnamed;
761 }
762 }
763 630
764 // only members of the current module maybe be defined 631 // only members of the current module maybe be defined
765 if (getModule() == gIR->dmodule) 632 if (getModule() == gIR->dmodule)
766 { 633 {
767 bool allow_fbody = true; 634 bool allow_fbody = true;
794 } 661 }
795 662
796 // function definition 663 // function definition
797 if (allow_fbody && fbody != 0) 664 if (allow_fbody && fbody != 0)
798 { 665 {
799 assert(nunnamed == 0); 666 if (isMain())
667 gIR->emitMain = true;
668
800 gIR->funcs.push(func); 669 gIR->funcs.push(func);
801 gIR->functypes.push(f); 670 gIR->functypes.push(f);
802 671
803 IRScope irs; 672 IRScope irs;
804 irs.begin = new llvm::BasicBlock("entry",func); 673 irs.begin = new llvm::BasicBlock("entry",func);
830 699
831 gIR->functypes.pop(); 700 gIR->functypes.pop();
832 gIR->funcs.pop(); 701 gIR->funcs.pop();
833 702
834 // get rid of the endentry block, it's never used 703 // get rid of the endentry block, it's never used
704 assert(!func->getBasicBlockList().empty());
835 func->getBasicBlockList().pop_back(); 705 func->getBasicBlockList().pop_back();
836 706
837 // if the last block is empty now, it must be unreachable or it's a bug somewhere else 707 // if the last block is empty now, it must be unreachable or it's a bug somewhere else
708 // would be nice to figure out how to assert that this is correct
838 llvm::BasicBlock* lastbb = &func->getBasicBlockList().back(); 709 llvm::BasicBlock* lastbb = &func->getBasicBlockList().back();
839 if (lastbb->empty()) { 710 if (lastbb->empty()) {
711 // possibly assert(lastbb->getNumPredecessors() == 0); ??? try it out sometime ...
840 new llvm::UnreachableInst(lastbb); 712 new llvm::UnreachableInst(lastbb);
841 } 713 }
842 } 714 }
843 } 715 }
844 else 716
845 {
846 Logger::println("only declaration");
847 } 717 }
848 718
849 llvmDModule = gIR->dmodule; 719 llvmDModule = gIR->dmodule;
850 720
851 Logger::println("FuncDeclaration done\n"); 721 Logger::println("FuncDeclaration done\n");