Mercurial > projects > ldc
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 |