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));