Changeset 9:dafae18f9c08
- Timestamp:
- 10/01/07 15:19:53 (1 year ago)
- Files:
-
- dmd/declaration.h (modified) (1 diff)
- dmd/mars.c (modified) (1 diff)
- dmd/mtype.c (modified) (1 diff)
- dmd/mtype.h (modified) (1 diff)
- gen/toir.c (modified) (1 diff)
- gen/tollvm.c (modified) (4 diffs)
- gen/tollvm.h (modified) (1 diff)
- gen/toobj.c (modified) (9 diffs)
- lib/llvmdcore.bc (modified) (previous)
- lphobos/build.sh (modified) (2 diffs)
- test/classes6.d (added)
- test/funcs2.d (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
dmd/declaration.h
r1 r9 127 127 128 128 virtual void toObjFile(); // compile to .obj file 129 130 // llvm stuff131 llvm::Value* llvmValue;132 129 }; 133 130 dmd/mars.c
r1 r9 159 159 global.llvmdc_version, global.version, global.copyright, global.written); 160 160 printf("\ 161 Documentation: http://www.digitalmars.com/d/1.0/index.html\n\ 161 D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n\ 162 LLVMDC Homepage: http://www.dsource.org/projects/llvmdc\n\ 162 163 Usage:\n\ 163 164 dmd files.d ... { -switch }\n\ dmd/mtype.c
r1 r9 2542 2542 this->inuse = 0; 2543 2543 this->llvmRetInPtr = false; 2544 this->llvmUsesThis = false; 2544 2545 this->llvmRetArg = 0; 2545 2546 this->llvmAllocaPoint = 0; dmd/mtype.h
r1 r9 434 434 435 435 bool llvmRetInPtr; 436 bool llvmUsesThis; 436 437 llvm::Value* llvmRetArg; 437 438 llvm::Instruction* llvmAllocaPoint; gen/toir.c
r8 r9 1247 1247 assert(e1->type->ty == Tclass); 1248 1248 1249 const llvm::Type* vtbltype = llvm::PointerType::get(llvm::ArrayType::get(llvm::PointerType::get(llvm::Type::Int8Ty),0));1250 1251 1249 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); 1252 1250 llvm::Value* vtblidx = llvm::ConstantInt::get(llvm::Type::Int32Ty, (size_t)fdecl->vtblIndex, false); 1253 1251 funcval = LLVM_DtoGEP(e->arg, zero, zero, "tmp", p->scopebb()); 1254 1252 funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb()); 1255 funcval = new llvm::BitCastInst(funcval, vtbltype, "tmp", p->scopebb());1256 1253 funcval = LLVM_DtoGEP(funcval, zero, vtblidx, "tmp", p->scopebb()); 1257 1254 funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb()); 1258 funcval = new llvm::BitCastInst(funcval, fdecl->llvmValue->getType(), "tmp", p->scopebb()); 1255 assert(funcval->getType() == fdecl->llvmValue->getType()); 1256 //funcval = new llvm::BitCastInst(funcval, fdecl->llvmValue->getType(), "tmp", p->scopebb()); 1259 1257 } 1260 1258 e->val = funcval; gen/tollvm.c
r8 r9 209 209 assert(f != 0); 210 210 211 // has already been pulled in by a reference to (211 // type has already been resolved 212 212 if (f->llvmType != 0) { 213 213 return llvm::cast<llvm::FunctionType>(f->llvmType); … … 248 248 } 249 249 250 if (fdecl->needThis() && fdecl->vthis) { 251 Logger::print("this is: %s\n", fdecl->vthis->type->toChars()); 252 paramvec.push_back(LLVM_DtoType(fdecl->vthis->type)); 253 usesthis = true; 250 if (fdecl->needThis()) { 251 if (AggregateDeclaration* ad = fdecl->isMember()) { 252 Logger::print("isMember = this is: %s\n", ad->type->toChars()); 253 const llvm::Type* thisty = LLVM_DtoType(ad->type); 254 if (llvm::isa<llvm::StructType>(thisty)) 255 thisty = llvm::PointerType::get(thisty); 256 paramvec.push_back(thisty); 257 usesthis = true; 258 } 259 else 260 assert(0); 254 261 } 255 262 … … 296 303 297 304 f->llvmType = functype; 305 f->llvmRetInPtr = retinptr; 306 f->llvmUsesThis = usesthis; 298 307 return functype; 299 308 } … … 838 847 return new llvm::GetElementPtrInst(ptr, dst.begin(), dst.end(), var, bb); 839 848 } 849 850 llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl) 851 { 852 if (fdecl->llvmValue != 0) { 853 return llvm::cast<llvm::Function>(fdecl->llvmValue); 854 } 855 856 static int fdi = 0; 857 Logger::print("FuncDeclaration::toObjFile(%d,%s): %s\n", fdi++, fdecl->needThis()?"this":"static",fdecl->toChars()); 858 LOG_SCOPE; 859 860 if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) { 861 error("intrinsics cannot have function bodies"); 862 fatal(); 863 } 864 865 // construct function 866 TypeFunction* f = (TypeFunction*)fdecl->type; 867 assert(f != 0); 868 llvm::FunctionType* functype = (f->llvmType == 0) ? LLVM_DtoFunctionType(fdecl) : llvm::cast<llvm::FunctionType>(f->llvmType); 869 870 // mangled name 871 char* mangled_name = (fdecl->llvmInternal == LLVMintrinsic) ? fdecl->llvmInternal1 : fdecl->mangle(); 872 873 // make the function 874 llvm::Function* func = gIR->module->getFunction(mangled_name); 875 if (func == 0) { 876 func = new llvm::Function(functype,LLVM_DtoLinkage(fdecl->protection, fdecl->storage_class),mangled_name,gIR->module); 877 } 878 879 if (fdecl->llvmInternal != LLVMintrinsic) 880 func->setCallingConv(LLVM_DtoCallingConv(f->linkage)); 881 882 fdecl->llvmValue = func; 883 f->llvmType = functype; 884 885 if (fdecl->isMain()) { 886 gIR->mainFunc = func; 887 } 888 889 // name parameters 890 llvm::Function::arg_iterator iarg = func->arg_begin(); 891 int k = 0; 892 if (f->llvmRetInPtr) { 893 iarg->setName("retval"); 894 f->llvmRetArg = iarg; 895 ++iarg; 896 } 897 if (f->llvmUsesThis) { 898 iarg->setName("this"); 899 ++iarg; 900 } 901 for (; iarg != func->arg_end(); ++iarg) 902 { 903 Argument* arg = Argument::getNth(f->parameters, k++); 904 assert(arg != 0); 905 //arg->llvmValue = iarg; 906 //printf("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident); 907 if (arg->ident != 0) { 908 if (arg->vardecl) { 909 arg->vardecl->llvmValue = iarg; 910 } 911 iarg->setName(arg->ident->toChars()); 912 } 913 else { 914 iarg->setName("unnamed"); 915 } 916 } 917 918 return func; 919 } gen/tollvm.h
r8 r9 12 12 llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam = 0); 13 13 llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl); 14 llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl); 14 15 15 16 llvm::StructType* LLVM_DtoDelegateType(Type* t); gen/toobj.c
r8 r9 337 337 338 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 341 gIR->topstruct().fields.push_back(vtabty); 341 342 gIR->topstruct().inits.push_back(0); … … 362 363 llvmType = structtype; 363 364 364 bool emit_vtable = false;365 365 bool define_vtable = false; 366 366 if (parent->isModule()) { 367 367 gIR->module->addTypeName(mangle(),ts->llvmType); 368 emit_vtable = true;369 368 define_vtable = (getModule() == gIR->dmodule); 370 369 } … … 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 458 gIR->queueClassMethods.back() = false; 377 459 IRState::FuncDeclVec& mfs = gIR->classmethods.back(); … … 379 461 for (size_t i=0; i<n; ++i) { 380 462 mfs[i]->toObjFile(); 381 }382 383 // create vtable initializer384 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 else407 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 initializer427 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;428 llvm::Constant* _init = 0;429 430 // first field is always the vtable431 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_LOGGER437 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 #endif441 _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 … … 561 573 const llvm::StructType* structty = llvm::cast<llvm::StructType>(_type); 562 574 TypeStruct* ts = (TypeStruct*)type; 575 assert(ts); 576 assert(ts->sym); 563 577 assert(ts->sym->llvmInitZ); 564 578 _init = ts->sym->llvmInitZ; … … 595 609 void FuncDeclaration::toObjFile() 596 610 { 597 if (llvmValue != 0 && llvmDModule == gIR->dmodule) { 611 if (llvmDModule == gIR->dmodule) { 612 assert(llvmValue != 0); 598 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 618 if (!gIR->queueClassMethods.empty() && gIR->queueClassMethods.back()) { 603 619 Logger::println("queueing %s", toChars()); … … 607 623 } 608 624 609 static int fdi = 0; 610 Logger::print("FuncDeclaration::toObjFile(%d,%s): %s\n", fdi++, needThis()?"this":"static",toChars()); 611 LOG_SCOPE; 612 613 if (llvmInternal == LLVMintrinsic && fbody) { 614 error("intrinsics cannot have function bodies"); 615 fatal(); 616 } 625 if (llvmNeedsDefinition) 626 { 617 627 618 628 TypeFunction* f = (TypeFunction*)type; 619 assert(f != 0); 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 } 629 llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(f->llvmType); 763 630 764 631 // only members of the current module maybe be defined … … 797 664 if (allow_fbody && fbody != 0) 798 665 { 799 assert(nunnamed == 0); 666 if (isMain()) 667 gIR->emitMain = true; 668 800 669 gIR->funcs.push(func); 801 670 gIR->functypes.push(f); … … 833 702 834 703 // get rid of the endentry block, it's never used 704 assert(!func->getBasicBlockList().empty()); 835 705 func->getBasicBlockList().pop_back(); 836 706 837 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 709 llvm::BasicBlock* lastbb = &func->getBasicBlockList().back(); 839 710 if (lastbb->empty()) { 711 // possibly assert(lastbb->getNumPredecessors() == 0); ??? try it out sometime ... 840 712 new llvm::UnreachableInst(lastbb); 841 713 } 842 714 } 843 715 } 844 else 845 { 846 Logger::println("only declaration"); 716 847 717 } 848 718 lphobos/build.sh
r1 r9 2 2 3 3 if [ "$1" = "gdb" ]; then 4 dc_cmd="gdb --args llvmd md"4 dc_cmd="gdb --args llvmdc" 5 5 else 6 6 dc_cmd="llvmdc" … … 12 12 -c -noruntime -odobj || exit 1 13 13 14 llvm-as -f -o=obj/moduleinit_backend.bc internal/moduleinit_backend.ll || exit 1 15 llvm-link -f -o=../lib/llvmdcore.bc obj/contract.bc obj/arrays.bc obj/moduleinit.bc obj/moduleinit_backend.bc || exit 1 16 14 17 $dc_cmd internal/objectimpl.d -c -odobj || exit 1 15 16 llvm-as -f -o=obj/moduleinit_backend.bc internal/moduleinit_backend.ll || exit 1 17 18 llvm-link -f -o=obj/all.bc obj/contract.bc obj/arrays.bc obj/moduleinit.bc obj/objectimpl.bc obj/moduleinit_backend.bc || return 1 18 llvm-link -f -o=obj/all.bc obj/contract.bc obj/arrays.bc obj/moduleinit.bc obj/objectimpl.bc obj/moduleinit_backend.bc || exit 1 19 19 20 20 opt -f -std-compile-opts -o=../lib/llvmdcore.bc obj/all.bc || exit 1

