Mercurial > projects > ldc
comparison gen/functions.cpp @ 213:7816aafeea3c trunk
[svn r229] Updated the object.d implementation to the latest Tango.
Fixed a bunch of the built-in typeinfos for arrays, they did not inherit TypeInfo_Array.
Applied patch to tango/text/convert/Layout.d by fvbommel, closes #47 .
Cleaned up some type code.
Replaced uses of llvm::Type with LLType (a typedef), same for Value and Constant.
Fixed a few cases where typeinfo for user structs could be emitted multiple times, seems to still be some cases of this :/
author | lindquist |
---|---|
date | Fri, 30 May 2008 19:32:04 +0200 |
parents | 9d44ec83acd1 |
children | a58d8f4b84df |
comparison
equal
deleted
inserted
replaced
212:4c2689d57ba4 | 213:7816aafeea3c |
---|---|
16 #include "gen/functions.h" | 16 #include "gen/functions.h" |
17 #include "gen/todebug.h" | 17 #include "gen/todebug.h" |
18 #include "gen/classes.h" | 18 #include "gen/classes.h" |
19 #include "gen/dvalue.h" | 19 #include "gen/dvalue.h" |
20 | 20 |
21 const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype, bool ismain) | 21 const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bool ismain) |
22 { | 22 { |
23 TypeFunction* f = (TypeFunction*)type; | 23 TypeFunction* f = (TypeFunction*)type; |
24 assert(f != 0); | 24 assert(f != 0); |
25 | 25 |
26 if (type->ir.type != NULL) { | 26 if (type->ir.type != NULL) { |
36 else if (f->varargs == 2) | 36 else if (f->varargs == 2) |
37 arrayVararg = true; | 37 arrayVararg = true; |
38 } | 38 } |
39 | 39 |
40 // return value type | 40 // return value type |
41 const llvm::Type* rettype; | 41 const LLType* rettype; |
42 const llvm::Type* actualRettype; | 42 const LLType* actualRettype; |
43 Type* rt = f->next; | 43 Type* rt = f->next; |
44 bool retinptr = false; | 44 bool retinptr = false; |
45 bool usesthis = false; | 45 bool usesthis = false; |
46 | 46 |
47 if (ismain) { | 47 if (ismain) { |
61 actualRettype = rettype; | 61 actualRettype = rettype; |
62 } | 62 } |
63 } | 63 } |
64 | 64 |
65 // parameter types | 65 // parameter types |
66 std::vector<const llvm::Type*> paramvec; | 66 std::vector<const LLType*> paramvec; |
67 | 67 |
68 if (retinptr) { | 68 if (retinptr) { |
69 //Logger::cout() << "returning through pointer parameter: " << *rettype << '\n'; | 69 //Logger::cout() << "returning through pointer parameter: " << *rettype << '\n'; |
70 paramvec.push_back(rettype); | 70 paramvec.push_back(rettype); |
71 } | 71 } |
78 if (typesafeVararg) { | 78 if (typesafeVararg) { |
79 ClassDeclaration* ti = Type::typeinfo; | 79 ClassDeclaration* ti = Type::typeinfo; |
80 ti->toObjFile(); | 80 ti->toObjFile(); |
81 DtoForceConstInitDsymbol(ti); | 81 DtoForceConstInitDsymbol(ti); |
82 assert(ti->ir.irStruct->constInit); | 82 assert(ti->ir.irStruct->constInit); |
83 std::vector<const llvm::Type*> types; | 83 std::vector<const LLType*> types; |
84 types.push_back(DtoSize_t()); | 84 types.push_back(DtoSize_t()); |
85 types.push_back(getPtrToType(getPtrToType(ti->ir.irStruct->constInit->getType()))); | 85 types.push_back(getPtrToType(getPtrToType(ti->ir.irStruct->constInit->getType()))); |
86 const llvm::Type* t1 = llvm::StructType::get(types); | 86 const LLType* t1 = llvm::StructType::get(types); |
87 paramvec.push_back(getPtrToType(t1)); | 87 paramvec.push_back(getPtrToType(t1)); |
88 paramvec.push_back(getPtrToType(llvm::Type::Int8Ty)); | 88 paramvec.push_back(getPtrToType(llvm::Type::Int8Ty)); |
89 } | 89 } |
90 else if (arrayVararg) | 90 else if (arrayVararg) |
91 { | 91 { |
98 Argument* arg = Argument::getNth(f->parameters, i); | 98 Argument* arg = Argument::getNth(f->parameters, i); |
99 // ensure scalar | 99 // ensure scalar |
100 Type* argT = DtoDType(arg->type); | 100 Type* argT = DtoDType(arg->type); |
101 assert(argT); | 101 assert(argT); |
102 | 102 |
103 const llvm::Type* at = DtoType(argT); | 103 const LLType* at = DtoType(argT); |
104 if (isaStruct(at)) { | 104 if (isaStruct(at)) { |
105 Logger::println("struct param"); | 105 Logger::println("struct param"); |
106 paramvec.push_back(getPtrToType(at)); | 106 paramvec.push_back(getPtrToType(at)); |
107 } | 107 } |
108 else if (isaArray(at)) { | 108 else if (isaArray(at)) { |
154 | 154 |
155 TypeFunction* f = (TypeFunction*)fdecl->type; | 155 TypeFunction* f = (TypeFunction*)fdecl->type; |
156 assert(f != 0); | 156 assert(f != 0); |
157 | 157 |
158 const llvm::PointerType* i8pty = getPtrToType(llvm::Type::Int8Ty); | 158 const llvm::PointerType* i8pty = getPtrToType(llvm::Type::Int8Ty); |
159 std::vector<const llvm::Type*> args; | 159 std::vector<const LLType*> args; |
160 | 160 |
161 if (fdecl->llvmInternal == LLVMva_start) { | 161 if (fdecl->llvmInternal == LLVMva_start) { |
162 args.push_back(i8pty); | 162 args.push_back(i8pty); |
163 } | 163 } |
164 else if (fdecl->llvmInternal == LLVMva_intrinsic) { | 164 else if (fdecl->llvmInternal == LLVMva_intrinsic) { |
185 return DtoVaFunctionType(fdecl); | 185 return DtoVaFunctionType(fdecl); |
186 } | 186 } |
187 | 187 |
188 // unittest has null type, just build it manually | 188 // unittest has null type, just build it manually |
189 /*if (fdecl->isUnitTestDeclaration()) { | 189 /*if (fdecl->isUnitTestDeclaration()) { |
190 std::vector<const llvm::Type*> args; | 190 std::vector<const LLType*> args; |
191 return llvm::FunctionType::get(llvm::Type::VoidTy, args, false); | 191 return llvm::FunctionType::get(llvm::Type::VoidTy, args, false); |
192 }*/ | 192 }*/ |
193 | 193 |
194 // type has already been resolved | 194 // type has already been resolved |
195 if (fdecl->type->ir.type != 0) { | 195 if (fdecl->type->ir.type != 0) { |
196 return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get()); | 196 return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get()); |
197 } | 197 } |
198 | 198 |
199 const llvm::Type* thisty = NULL; | 199 const LLType* thisty = NULL; |
200 if (fdecl->needThis()) { | 200 if (fdecl->needThis()) { |
201 if (AggregateDeclaration* ad = fdecl->isMember2()) { | 201 if (AggregateDeclaration* ad = fdecl->isMember2()) { |
202 Logger::println("isMember = this is: %s", ad->type->toChars()); | 202 Logger::println("isMember = this is: %s", ad->type->toChars()); |
203 thisty = DtoType(ad->type); | 203 thisty = DtoType(ad->type); |
204 //Logger::cout() << "this llvm type: " << *thisty << '\n'; | 204 //Logger::cout() << "this llvm type: " << *thisty << '\n'; |
223 | 223 |
224 static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl) | 224 static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl) |
225 { | 225 { |
226 TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type); | 226 TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type); |
227 const llvm::FunctionType* fty = DtoVaFunctionType(fdecl); | 227 const llvm::FunctionType* fty = DtoVaFunctionType(fdecl); |
228 llvm::Constant* fn = 0; | 228 LLConstant* fn = 0; |
229 | 229 |
230 if (fdecl->llvmInternal == LLVMva_start) { | 230 if (fdecl->llvmInternal == LLVMva_start) { |
231 fn = gIR->module->getOrInsertFunction("llvm.va_start", fty); | 231 fn = gIR->module->getOrInsertFunction("llvm.va_start", fty); |
232 assert(fn); | 232 assert(fn); |
233 } | 233 } |
497 | 497 |
498 //assert(gIR->scopes.empty()); | 498 //assert(gIR->scopes.empty()); |
499 gIR->scopes.push_back(IRScope(beginbb, endbb)); | 499 gIR->scopes.push_back(IRScope(beginbb, endbb)); |
500 | 500 |
501 // create alloca point | 501 // create alloca point |
502 llvm::Instruction* allocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb()); | 502 llvm::Instruction* allocaPoint = new llvm::AllocaInst(llvm::Type::Int32Ty, "alloca point", beginbb); |
503 gIR->func()->allocapoint = allocaPoint; | 503 gIR->func()->allocapoint = allocaPoint; |
504 | 504 |
505 // need result variable? (not nested) | 505 // need result variable? (not nested) |
506 if (fd->vresult && !fd->vresult->nestedref) { | 506 if (fd->vresult && !fd->vresult->nestedref) { |
507 Logger::println("non-nested vresult value"); | 507 Logger::println("non-nested vresult value"); |
520 assert(vd); | 520 assert(vd); |
521 | 521 |
522 if (!vd->needsStorage || vd->nestedref || vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)) | 522 if (!vd->needsStorage || vd->nestedref || vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)) |
523 continue; | 523 continue; |
524 | 524 |
525 llvm::Value* a = vd->ir.irLocal->value; | 525 LLValue* a = vd->ir.irLocal->value; |
526 assert(a); | 526 assert(a); |
527 std::string s(a->getName()); | 527 std::string s(a->getName()); |
528 Logger::println("giving argument '%s' storage", s.c_str()); | 528 Logger::println("giving argument '%s' storage", s.c_str()); |
529 s.append("_storage"); | 529 s.append("_storage"); |
530 | 530 |
531 llvm::Value* v = new llvm::AllocaInst(a->getType(),s,allocaPoint); | 531 LLValue* v = new llvm::AllocaInst(a->getType(),s,allocaPoint); |
532 gIR->ir->CreateStore(a,v); | 532 gIR->ir->CreateStore(a,v); |
533 vd->ir.irLocal->value = v; | 533 vd->ir.irLocal->value = v; |
534 } | 534 } |
535 } | 535 } |
536 | 536 |
537 // debug info | 537 // debug info |
538 if (global.params.symdebug) DtoDwarfFuncStart(fd); | 538 if (global.params.symdebug) DtoDwarfFuncStart(fd); |
539 | 539 |
540 llvm::Value* parentNested = NULL; | 540 LLValue* parentNested = NULL; |
541 if (FuncDeclaration* fd2 = fd->toParent2()->isFuncDeclaration()) { | 541 if (FuncDeclaration* fd2 = fd->toParent2()->isFuncDeclaration()) { |
542 if (!fd->isStatic()) // huh? | 542 if (!fd->isStatic()) // huh? |
543 parentNested = fd2->ir.irFunc->nestedVar; | 543 parentNested = fd2->ir.irFunc->nestedVar; |
544 } | 544 } |
545 | 545 |
549 fd->nestedVars.insert(fd->vresult); | 549 fd->nestedVars.insert(fd->vresult); |
550 } | 550 } |
551 | 551 |
552 // construct nested variables struct | 552 // construct nested variables struct |
553 if (!fd->nestedVars.empty() || parentNested) { | 553 if (!fd->nestedVars.empty() || parentNested) { |
554 std::vector<const llvm::Type*> nestTypes; | 554 std::vector<const LLType*> nestTypes; |
555 int j = 0; | 555 int j = 0; |
556 if (parentNested) { | 556 if (parentNested) { |
557 nestTypes.push_back(parentNested->getType()); | 557 nestTypes.push_back(parentNested->getType()); |
558 j++; | 558 j++; |
559 } | 559 } |
578 const llvm::StructType* nestSType = llvm::StructType::get(nestTypes); | 578 const llvm::StructType* nestSType = llvm::StructType::get(nestTypes); |
579 Logger::cout() << "nested var struct has type:" << *nestSType << '\n'; | 579 Logger::cout() << "nested var struct has type:" << *nestSType << '\n'; |
580 fd->ir.irFunc->nestedVar = new llvm::AllocaInst(nestSType,"nestedvars",allocaPoint); | 580 fd->ir.irFunc->nestedVar = new llvm::AllocaInst(nestSType,"nestedvars",allocaPoint); |
581 if (parentNested) { | 581 if (parentNested) { |
582 assert(fd->ir.irFunc->thisVar); | 582 assert(fd->ir.irFunc->thisVar); |
583 llvm::Value* ptr = gIR->ir->CreateBitCast(fd->ir.irFunc->thisVar, parentNested->getType(), "tmp"); | 583 LLValue* ptr = gIR->ir->CreateBitCast(fd->ir.irFunc->thisVar, parentNested->getType(), "tmp"); |
584 gIR->ir->CreateStore(ptr, DtoGEPi(fd->ir.irFunc->nestedVar, 0,0, "tmp")); | 584 gIR->ir->CreateStore(ptr, DtoGEPi(fd->ir.irFunc->nestedVar, 0,0, "tmp")); |
585 } | 585 } |
586 for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) { | 586 for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) { |
587 VarDeclaration* vd = *i; | 587 VarDeclaration* vd = *i; |
588 if (vd->isParameter()) { | 588 if (vd->isParameter()) { |
594 } | 594 } |
595 | 595 |
596 // copy _argptr to a memory location | 596 // copy _argptr to a memory location |
597 if (f->linkage == LINKd && f->varargs == 1) | 597 if (f->linkage == LINKd && f->varargs == 1) |
598 { | 598 { |
599 llvm::Value* argptrmem = new llvm::AllocaInst(fd->ir.irFunc->_argptr->getType(), "_argptrmem", gIR->topallocapoint()); | 599 LLValue* argptrmem = new llvm::AllocaInst(fd->ir.irFunc->_argptr->getType(), "_argptrmem", gIR->topallocapoint()); |
600 new llvm::StoreInst(fd->ir.irFunc->_argptr, argptrmem, gIR->scopebb()); | 600 new llvm::StoreInst(fd->ir.irFunc->_argptr, argptrmem, gIR->scopebb()); |
601 fd->ir.irFunc->_argptr = argptrmem; | 601 fd->ir.irFunc->_argptr = argptrmem; |
602 } | 602 } |
603 | 603 |
604 // output function body | 604 // output function body |
663 IRState& ir = *gIR; | 663 IRState& ir = *gIR; |
664 | 664 |
665 assert(ir.emitMain && ir.mainFunc); | 665 assert(ir.emitMain && ir.mainFunc); |
666 | 666 |
667 // parameter types | 667 // parameter types |
668 std::vector<const llvm::Type*> pvec; | 668 std::vector<const LLType*> pvec; |
669 pvec.push_back((const llvm::Type*)llvm::Type::Int32Ty); | 669 pvec.push_back((const LLType*)llvm::Type::Int32Ty); |
670 const llvm::Type* chPtrType = (const llvm::Type*)getPtrToType(llvm::Type::Int8Ty); | 670 const LLType* chPtrType = (const LLType*)getPtrToType(llvm::Type::Int8Ty); |
671 pvec.push_back((const llvm::Type*)getPtrToType(chPtrType)); | 671 pvec.push_back((const LLType*)getPtrToType(chPtrType)); |
672 pvec.push_back((const llvm::Type*)getPtrToType(chPtrType)); | 672 pvec.push_back((const LLType*)getPtrToType(chPtrType)); |
673 const llvm::Type* rettype = (const llvm::Type*)llvm::Type::Int32Ty; | 673 const LLType* rettype = (const LLType*)llvm::Type::Int32Ty; |
674 | 674 |
675 llvm::FunctionType* functype = llvm::FunctionType::get(rettype, pvec, false); | 675 llvm::FunctionType* functype = llvm::FunctionType::get(rettype, pvec, false); |
676 llvm::Function* func = llvm::Function::Create(functype,llvm::GlobalValue::ExternalLinkage,"main",ir.module); | 676 llvm::Function* func = llvm::Function::Create(functype,llvm::GlobalValue::ExternalLinkage,"main",ir.module); |
677 | 677 |
678 llvm::BasicBlock* bb = llvm::BasicBlock::Create("entry",func); | 678 llvm::BasicBlock* bb = llvm::BasicBlock::Create("entry",func); |
692 llvm::CallInst* call; | 692 llvm::CallInst* call; |
693 if (mainty->getNumParams() > 0) | 693 if (mainty->getNumParams() > 0) |
694 { | 694 { |
695 // main with arguments | 695 // main with arguments |
696 assert(mainty->getNumParams() == 1); | 696 assert(mainty->getNumParams() == 1); |
697 std::vector<llvm::Value*> args; | 697 std::vector<LLValue*> args; |
698 llvm::Function* mfn = LLVM_D_GetRuntimeFunction(ir.module,"_d_main_args"); | 698 llvm::Function* mfn = LLVM_D_GetRuntimeFunction(ir.module,"_d_main_args"); |
699 | 699 |
700 llvm::Function::arg_iterator argi = func->arg_begin(); | 700 llvm::Function::arg_iterator argi = func->arg_begin(); |
701 args.push_back(argi++); | 701 args.push_back(argi++); |
702 args.push_back(argi++); | 702 args.push_back(argi++); |
703 | 703 |
704 const llvm::Type* at = mainty->getParamType(0)->getContainedType(0); | 704 const LLType* at = mainty->getParamType(0)->getContainedType(0); |
705 llvm::Value* arr = new llvm::AllocaInst(at->getContainedType(1)->getContainedType(0), func->arg_begin(), "argstorage", apt); | 705 LLValue* arr = new llvm::AllocaInst(at->getContainedType(1)->getContainedType(0), func->arg_begin(), "argstorage", apt); |
706 llvm::Value* a = new llvm::AllocaInst(at, "argarray", apt); | 706 LLValue* a = new llvm::AllocaInst(at, "argarray", apt); |
707 llvm::Value* ptr = DtoGEPi(a,0,0,"tmp",bb); | 707 LLValue* ptr = DtoGEPi(a,0,0,"tmp",bb); |
708 llvm::Value* v = args[0]; | 708 LLValue* v = args[0]; |
709 if (v->getType() != DtoSize_t()) | 709 if (v->getType() != DtoSize_t()) |
710 v = new llvm::ZExtInst(v, DtoSize_t(), "tmp", bb); | 710 v = new llvm::ZExtInst(v, DtoSize_t(), "tmp", bb); |
711 new llvm::StoreInst(v,ptr,bb); | 711 new llvm::StoreInst(v,ptr,bb); |
712 ptr = DtoGEPi(a,0,1,"tmp",bb); | 712 ptr = DtoGEPi(a,0,1,"tmp",bb); |
713 new llvm::StoreInst(arr,ptr,bb); | 713 new llvm::StoreInst(arr,ptr,bb); |
776 arg = new DImValue(argexp->type, arg->getRVal(), false); | 776 arg = new DImValue(argexp->type, arg->getRVal(), false); |
777 } | 777 } |
778 // aggregate arg | 778 // aggregate arg |
779 else if (DtoIsPassedByRef(argexp->type)) | 779 else if (DtoIsPassedByRef(argexp->type)) |
780 { | 780 { |
781 llvm::Value* alloc = new llvm::AllocaInst(DtoType(argexp->type), "tmpparam", gIR->topallocapoint()); | 781 LLValue* alloc = new llvm::AllocaInst(DtoType(argexp->type), "tmpparam", gIR->topallocapoint()); |
782 DVarValue* vv = new DVarValue(argexp->type, alloc, true); | 782 DVarValue* vv = new DVarValue(argexp->type, alloc, true); |
783 DtoAssign(vv, arg); | 783 DtoAssign(vv, arg); |
784 arg = vv; | 784 arg = vv; |
785 } | 785 } |
786 // normal arg (basic/value type) | 786 // normal arg (basic/value type) |
792 return arg; | 792 return arg; |
793 } | 793 } |
794 | 794 |
795 ////////////////////////////////////////////////////////////////////////////////////////// | 795 ////////////////////////////////////////////////////////////////////////////////////////// |
796 | 796 |
797 void DtoVariadicArgument(Expression* argexp, llvm::Value* dst) | 797 void DtoVariadicArgument(Expression* argexp, LLValue* dst) |
798 { | 798 { |
799 Logger::println("DtoVariadicArgument"); | 799 Logger::println("DtoVariadicArgument"); |
800 LOG_SCOPE; | 800 LOG_SCOPE; |
801 DVarValue* vv = new DVarValue(argexp->type, dst, true); | 801 DVarValue* vv = new DVarValue(argexp->type, dst, true); |
802 DtoAssign(vv, argexp->toElem(gIR)); | 802 DtoAssign(vv, argexp->toElem(gIR)); |