comparison gen/functions.cpp @ 1051:dc608dc33081

Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the same LDC call.
author Christian Kamm <kamm incasoftware de>
date Sat, 07 Mar 2009 14:25:30 +0100
parents afe271b0e271
children 802d508f66f1
comparison
equal deleted inserted replaced
1050:32ead42679d1 1051:dc608dc33081
31 assert(type->ty == Tfunction); 31 assert(type->ty == Tfunction);
32 TypeFunction* f = (TypeFunction*)type; 32 TypeFunction* f = (TypeFunction*)type;
33 33
34 // already built ? 34 // already built ?
35 if (type->ir.type != NULL) { 35 if (type->ir.type != NULL) {
36 assert(f->fty != NULL); 36 //assert(f->fty != NULL);
37 return llvm::cast<llvm::FunctionType>(type->ir.type->get()); 37 return llvm::cast<llvm::FunctionType>(type->ir.type->get());
38 } 38 }
39 39
40 // Tell the ABI we're resolving a new function type 40 // Tell the ABI we're resolving a new function type
41 gABI->newFunctionType(f); 41 gABI->newFunctionType(f);
42 42
43 // create new ir funcTy 43 // start new ir funcTy
44 assert(f->fty == NULL); 44 f->fty.reset();
45 f->fty = new IrFuncTy();
46 45
47 // llvm idx counter 46 // llvm idx counter
48 size_t lidx = 0; 47 size_t lidx = 0;
49 48
50 // main needs a little special handling 49 // main needs a little special handling
51 if (ismain) 50 if (ismain)
52 { 51 {
53 f->fty->ret = new IrFuncTyArg(Type::tint32, false); 52 f->fty.ret = new IrFuncTyArg(Type::tint32, false);
54 } 53 }
55 // sane return value 54 // sane return value
56 else 55 else
57 { 56 {
58 Type* rt = f->next; 57 Type* rt = f->next;
59 unsigned a = 0; 58 unsigned a = 0;
60 // sret return 59 // sret return
61 if (gABI->returnInArg(f)) 60 if (gABI->returnInArg(f))
62 { 61 {
63 f->fty->arg_sret = new IrFuncTyArg(rt, true, llvm::Attribute::StructRet); 62 f->fty.arg_sret = new IrFuncTyArg(rt, true, llvm::Attribute::StructRet);
64 rt = Type::tvoid; 63 rt = Type::tvoid;
65 lidx++; 64 lidx++;
66 } 65 }
67 // sext/zext return 66 // sext/zext return
68 else if (unsigned se = DtoShouldExtend(rt)) 67 else if (unsigned se = DtoShouldExtend(rt))
69 { 68 {
70 a = se; 69 a = se;
71 } 70 }
72 f->fty->ret = new IrFuncTyArg(rt, false, a); 71 f->fty.ret = new IrFuncTyArg(rt, false, a);
73 } 72 }
74 lidx++; 73 lidx++;
75 74
76 // member functions 75 // member functions
77 if (thistype) 76 if (thistype)
78 { 77 {
79 bool toref = (thistype->toBasetype()->ty == Tstruct); 78 bool toref = (thistype->toBasetype()->ty == Tstruct);
80 f->fty->arg_this = new IrFuncTyArg(thistype, toref); 79 f->fty.arg_this = new IrFuncTyArg(thistype, toref);
81 lidx++; 80 lidx++;
82 } 81 }
83 82
84 // and nested functions 83 // and nested functions
85 else if (nesttype) 84 else if (nesttype)
86 { 85 {
87 f->fty->arg_nest = new IrFuncTyArg(nesttype, false); 86 f->fty.arg_nest = new IrFuncTyArg(nesttype, false);
88 lidx++; 87 lidx++;
89 } 88 }
90 89
91 // vararg functions are special too 90 // vararg functions are special too
92 if (f->varargs) 91 if (f->varargs)
96 // d style with hidden args 95 // d style with hidden args
97 // 2 (array) is handled by the frontend 96 // 2 (array) is handled by the frontend
98 if (f->varargs == 1) 97 if (f->varargs == 1)
99 { 98 {
100 // _arguments 99 // _arguments
101 f->fty->arg_arguments = new IrFuncTyArg(Type::typeinfo->type->arrayOf(), false); 100 f->fty.arg_arguments = new IrFuncTyArg(Type::typeinfo->type->arrayOf(), false);
102 lidx++; 101 lidx++;
103 // _argptr 102 // _argptr
104 f->fty->arg_argptr = new IrFuncTyArg(Type::tvoid->pointerTo(), false); 103 f->fty.arg_argptr = new IrFuncTyArg(Type::tvoid->pointerTo(), false);
105 lidx++; 104 lidx++;
106 } 105 }
107 } 106 }
108 else if (f->linkage == LINKc) 107 else if (f->linkage == LINKc)
109 { 108 {
110 f->fty->c_vararg = true; 109 f->fty.c_vararg = true;
111 } 110 }
112 else 111 else
113 { 112 {
114 type->error(0, "invalid linkage for variadic function"); 113 type->error(0, "invalid linkage for variadic function");
115 fatal(); 114 fatal();
120 int nargs = Argument::dim(f->parameters); 119 int nargs = Argument::dim(f->parameters);
121 120
122 if (ismain && nargs == 0) 121 if (ismain && nargs == 0)
123 { 122 {
124 Type* mainargs = Type::tchar->arrayOf()->arrayOf(); 123 Type* mainargs = Type::tchar->arrayOf()->arrayOf();
125 f->fty->args.push_back(new IrFuncTyArg(mainargs, false)); 124 f->fty.args.push_back(new IrFuncTyArg(mainargs, false));
126 lidx++; 125 lidx++;
127 } 126 }
128 // add explicit parameters 127 // add explicit parameters
129 else for (int i = 0; i < nargs; i++) 128 else for (int i = 0; i < nargs; i++)
130 { 129 {
155 else if (!byref) 154 else if (!byref)
156 { 155 {
157 a |= DtoShouldExtend(argtype); 156 a |= DtoShouldExtend(argtype);
158 } 157 }
159 158
160 f->fty->args.push_back(new IrFuncTyArg(argtype, byref, a)); 159 f->fty.args.push_back(new IrFuncTyArg(argtype, byref, a));
161 lidx++; 160 lidx++;
162 } 161 }
163 162
164 // let the abi rewrite the types as necesary 163 // let the abi rewrite the types as necesary
165 gABI->rewriteFunctionType(f); 164 gABI->rewriteFunctionType(f);
169 168
170 // build the function type 169 // build the function type
171 std::vector<const LLType*> argtypes; 170 std::vector<const LLType*> argtypes;
172 argtypes.reserve(lidx); 171 argtypes.reserve(lidx);
173 172
174 if (f->fty->arg_sret) argtypes.push_back(f->fty->arg_sret->ltype); 173 if (f->fty.arg_sret) argtypes.push_back(f->fty.arg_sret->ltype);
175 if (f->fty->arg_this) argtypes.push_back(f->fty->arg_this->ltype); 174 if (f->fty.arg_this) argtypes.push_back(f->fty.arg_this->ltype);
176 if (f->fty->arg_nest) argtypes.push_back(f->fty->arg_nest->ltype); 175 if (f->fty.arg_nest) argtypes.push_back(f->fty.arg_nest->ltype);
177 if (f->fty->arg_arguments) argtypes.push_back(f->fty->arg_arguments->ltype); 176 if (f->fty.arg_arguments) argtypes.push_back(f->fty.arg_arguments->ltype);
178 if (f->fty->arg_argptr) argtypes.push_back(f->fty->arg_argptr->ltype); 177 if (f->fty.arg_argptr) argtypes.push_back(f->fty.arg_argptr->ltype);
179 178
180 size_t beg = argtypes.size(); 179 size_t beg = argtypes.size();
181 size_t nargs2 = f->fty->args.size(); 180 size_t nargs2 = f->fty.args.size();
182 for (size_t i = 0; i < nargs2; i++) 181 for (size_t i = 0; i < nargs2; i++)
183 { 182 {
184 argtypes.push_back(f->fty->args[i]->ltype); 183 argtypes.push_back(f->fty.args[i]->ltype);
185 } 184 }
186 185
187 // reverse params? 186 // reverse params?
188 if (f->fty->reverseParams && nargs2 > 1) 187 if (f->fty.reverseParams && nargs2 > 1)
189 { 188 {
190 std::reverse(argtypes.begin() + beg, argtypes.end()); 189 std::reverse(argtypes.begin() + beg, argtypes.end());
191 } 190 }
192 191
193 llvm::FunctionType* functype = llvm::FunctionType::get(f->fty->ret->ltype, argtypes, f->fty->c_vararg); 192 llvm::FunctionType* functype = llvm::FunctionType::get(f->fty.ret->ltype, argtypes, f->fty.c_vararg);
194 f->ir.type = new llvm::PATypeHolder(functype); 193 f->ir.type = new llvm::PATypeHolder(functype);
195 194
196 Logger::cout() << "Final function type: " << *functype << "\n"; 195 Logger::cout() << "Final function type: " << *functype << "\n";
197 196
198 return functype; 197 return functype;
209 208
210 TypeFunction* f = (TypeFunction*)fdecl->type; 209 TypeFunction* f = (TypeFunction*)fdecl->type;
211 const llvm::FunctionType* fty = 0; 210 const llvm::FunctionType* fty = 0;
212 211
213 // create new ir funcTy 212 // create new ir funcTy
214 assert(f->fty == NULL); 213 f->fty.reset();
215 f->fty = new IrFuncTy(); 214 f->fty.ret = new IrFuncTyArg(Type::tvoid, false);
216 f->fty->ret = new IrFuncTyArg(Type::tvoid, false); 215
217 216 f->fty.args.push_back(new IrFuncTyArg(Type::tvoid->pointerTo(), false));
218 f->fty->args.push_back(new IrFuncTyArg(Type::tvoid->pointerTo(), false));
219 217
220 if (fdecl->llvmInternal == LLVMva_start) 218 if (fdecl->llvmInternal == LLVMva_start)
221 fty = GET_INTRINSIC_DECL(vastart)->getFunctionType(); 219 fty = GET_INTRINSIC_DECL(vastart)->getFunctionType();
222 else if (fdecl->llvmInternal == LLVMva_copy) { 220 else if (fdecl->llvmInternal == LLVMva_copy) {
223 fty = GET_INTRINSIC_DECL(vacopy)->getFunctionType(); 221 fty = GET_INTRINSIC_DECL(vacopy)->getFunctionType();
224 f->fty->args.push_back(new IrFuncTyArg(Type::tvoid->pointerTo(), false)); 222 f->fty.args.push_back(new IrFuncTyArg(Type::tvoid->pointerTo(), false));
225 } 223 }
226 else if (fdecl->llvmInternal == LLVMva_end) 224 else if (fdecl->llvmInternal == LLVMva_end)
227 fty = GET_INTRINSIC_DECL(vaend)->getFunctionType(); 225 fty = GET_INTRINSIC_DECL(vaend)->getFunctionType();
228 assert(fty); 226 assert(fty);
229 227
357 355
358 int idx = 0; 356 int idx = 0;
359 357
360 // handle implicit args 358 // handle implicit args
361 #define ADD_PA(X) \ 359 #define ADD_PA(X) \
362 if (f->fty->X) { \ 360 if (f->fty.X) { \
363 if (f->fty->X->attrs) { \ 361 if (f->fty.X->attrs) { \
364 PAWI.Index = idx; \ 362 PAWI.Index = idx; \
365 PAWI.Attrs = f->fty->X->attrs; \ 363 PAWI.Attrs = f->fty.X->attrs; \
366 attrs.push_back(PAWI); \ 364 attrs.push_back(PAWI); \
367 } \ 365 } \
368 idx++; \ 366 idx++; \
369 } 367 }
370 368
384 for (size_t k = 0; k < n; ++k) 382 for (size_t k = 0; k < n; ++k)
385 { 383 {
386 Argument* fnarg = Argument::getNth(f->parameters, k); 384 Argument* fnarg = Argument::getNth(f->parameters, k);
387 assert(fnarg); 385 assert(fnarg);
388 386
389 attrptr[k] = f->fty->args[k]->attrs; 387 attrptr[k] = f->fty.args[k]->attrs;
390 } 388 }
391 389
392 // reverse params? 390 // reverse params?
393 if (f->fty->reverseParams) 391 if (f->fty.reverseParams)
394 { 392 {
395 std::reverse(attrptr.begin(), attrptr.end()); 393 std::reverse(attrptr.begin(), attrptr.end());
396 } 394 }
397 395
398 // build rest of attrs list 396 // build rest of attrs list
498 if (!declareOnly) 496 if (!declareOnly)
499 { 497 {
500 // name parameters 498 // name parameters
501 llvm::Function::arg_iterator iarg = func->arg_begin(); 499 llvm::Function::arg_iterator iarg = func->arg_begin();
502 500
503 if (f->fty->arg_sret) { 501 if (f->fty.arg_sret) {
504 iarg->setName(".sret_arg"); 502 iarg->setName(".sret_arg");
505 fdecl->ir.irFunc->retArg = iarg; 503 fdecl->ir.irFunc->retArg = iarg;
506 ++iarg; 504 ++iarg;
507 } 505 }
508 506
509 if (f->fty->arg_this) { 507 if (f->fty.arg_this) {
510 iarg->setName(".this_arg"); 508 iarg->setName(".this_arg");
511 fdecl->ir.irFunc->thisArg = iarg; 509 fdecl->ir.irFunc->thisArg = iarg;
512 assert(fdecl->ir.irFunc->thisArg); 510 assert(fdecl->ir.irFunc->thisArg);
513 ++iarg; 511 ++iarg;
514 } 512 }
515 else if (f->fty->arg_nest) { 513 else if (f->fty.arg_nest) {
516 iarg->setName(".nest_arg"); 514 iarg->setName(".nest_arg");
517 fdecl->ir.irFunc->nestArg = iarg; 515 fdecl->ir.irFunc->nestArg = iarg;
518 assert(fdecl->ir.irFunc->nestArg); 516 assert(fdecl->ir.irFunc->nestArg);
519 ++iarg; 517 ++iarg;
520 } 518 }
521 519
522 if (f->fty->arg_argptr) { 520 if (f->fty.arg_argptr) {
523 iarg->setName("._arguments"); 521 iarg->setName("._arguments");
524 fdecl->ir.irFunc->_arguments = iarg; 522 fdecl->ir.irFunc->_arguments = iarg;
525 ++iarg; 523 ++iarg;
526 iarg->setName("._argptr"); 524 iarg->setName("._argptr");
527 fdecl->ir.irFunc->_argptr = iarg; 525 fdecl->ir.irFunc->_argptr = iarg;
533 for (; iarg != func->arg_end(); ++iarg) 531 for (; iarg != func->arg_end(); ++iarg)
534 { 532 {
535 if (fdecl->parameters && fdecl->parameters->dim > k) 533 if (fdecl->parameters && fdecl->parameters->dim > k)
536 { 534 {
537 Dsymbol* argsym; 535 Dsymbol* argsym;
538 if (f->fty->reverseParams) 536 if (f->fty.reverseParams)
539 argsym = (Dsymbol*)fdecl->parameters->data[fdecl->parameters->dim-k-1]; 537 argsym = (Dsymbol*)fdecl->parameters->data[fdecl->parameters->dim-k-1];
540 else 538 else
541 argsym = (Dsymbol*)fdecl->parameters->data[k]; 539 argsym = (Dsymbol*)fdecl->parameters->data[k];
542 540
543 VarDeclaration* argvd = argsym->isVarDeclaration(); 541 VarDeclaration* argvd = argsym->isVarDeclaration();
653 LLFunction* hack = GET_INTRINSIC_DECL(eh_unwind_init); 651 LLFunction* hack = GET_INTRINSIC_DECL(eh_unwind_init);
654 gIR->ir->CreateCall(hack, ""); 652 gIR->ir->CreateCall(hack, "");
655 } 653 }
656 654
657 // give the 'this' argument storage and debug info 655 // give the 'this' argument storage and debug info
658 if (f->fty->arg_this) 656 if (f->fty.arg_this)
659 { 657 {
660 LLValue* thisvar = irfunction->thisArg; 658 LLValue* thisvar = irfunction->thisArg;
661 assert(thisvar); 659 assert(thisvar);
662 660
663 LLValue* thismem = DtoAlloca(thisvar->getType(), "this"); 661 LLValue* thismem = DtoAlloca(thisvar->getType(), "this");
683 681
684 // give arguments storage 682 // give arguments storage
685 // and debug info 683 // and debug info
686 if (fd->parameters) 684 if (fd->parameters)
687 { 685 {
688 size_t n = f->fty->args.size(); 686 size_t n = f->fty.args.size();
689 assert(n == fd->parameters->dim); 687 assert(n == fd->parameters->dim);
690 for (int i=0; i < n; ++i) 688 for (int i=0; i < n; ++i)
691 { 689 {
692 Dsymbol* argsym = (Dsymbol*)fd->parameters->data[i]; 690 Dsymbol* argsym = (Dsymbol*)fd->parameters->data[i];
693 VarDeclaration* vd = argsym->isVarDeclaration(); 691 VarDeclaration* vd = argsym->isVarDeclaration();
706 } 704 }
707 705
708 bool refout = vd->storage_class & (STCref | STCout); 706 bool refout = vd->storage_class & (STCref | STCout);
709 bool lazy = vd->storage_class & STClazy; 707 bool lazy = vd->storage_class & STClazy;
710 708
711 if (!refout && (!f->fty->args[i]->byref || lazy)) 709 if (!refout && (!f->fty.args[i]->byref || lazy))
712 { 710 {
713 // alloca a stack slot for this first class value arg 711 // alloca a stack slot for this first class value arg
714 const LLType* argt; 712 const LLType* argt;
715 if (lazy) 713 if (lazy)
716 argt = irloc->value->getType(); 714 argt = irloc->value->getType();
718 argt = DtoType(vd->type); 716 argt = DtoType(vd->type);
719 LLValue* mem = DtoAlloca(argt, vd->ident->toChars()); 717 LLValue* mem = DtoAlloca(argt, vd->ident->toChars());
720 718
721 // let the abi transform the argument back first 719 // let the abi transform the argument back first
722 DImValue arg_dval(vd->type, irloc->value); 720 DImValue arg_dval(vd->type, irloc->value);
723 f->fty->getParam(vd->type, i, &arg_dval, mem); 721 f->fty.getParam(vd->type, i, &arg_dval, mem);
724 722
725 // set the arg var value to the alloca 723 // set the arg var value to the alloca
726 irloc->value = mem; 724 irloc->value = mem;
727 } 725 }
728 726