Mercurial > projects > ldc
comparison gen/tocall.cpp @ 1024:9167d492cbc2
Abstracted more (most) ABI details out of the normal codegen.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 03 Mar 2009 02:51:21 +0100 |
parents | e8c6dbcd33d1 |
children | 3ead5c40b7d6 |
comparison
equal
deleted
inserted
replaced
1023:ca191c141cec | 1024:9167d492cbc2 |
---|---|
199 { | 199 { |
200 Argument* fnarg = Argument::getNth(tf->parameters, i); | 200 Argument* fnarg = Argument::getNth(tf->parameters, i); |
201 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); | 201 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); |
202 args.push_back(argval->getRVal()); | 202 args.push_back(argval->getRVal()); |
203 | 203 |
204 if (fnarg->llvmAttrs) | 204 if (tf->fty->args[i]->attrs) |
205 { | 205 { |
206 llvm::AttributeWithIndex Attr; | 206 llvm::AttributeWithIndex Attr; |
207 Attr.Index = argidx; | 207 Attr.Index = argidx; |
208 Attr.Attrs = fnarg->llvmAttrs; | 208 Attr.Attrs = tf->fty->args[i]->attrs; |
209 attrs.push_back(Attr); | 209 attrs.push_back(Attr); |
210 } | 210 } |
211 | 211 |
212 ++argidx; | 212 ++argidx; |
213 } | 213 } |
214 } | 214 } |
215 | 215 |
216 // FIXME: this function is a mess ! | |
216 | 217 |
217 DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* arguments) | 218 DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* arguments) |
218 { | 219 { |
219 // the callee D type | 220 // the callee D type |
220 Type* calleeType = fnval->getType(); | 221 Type* calleeType = fnval->getType(); |
231 | 232 |
232 // get function type info | 233 // get function type info |
233 TypeFunction* tf = DtoTypeFunction(fnval); | 234 TypeFunction* tf = DtoTypeFunction(fnval); |
234 | 235 |
235 // misc | 236 // misc |
236 bool retinptr = tf->retInPtr; | 237 bool retinptr = tf->fty->arg_sret; |
237 bool thiscall = tf->usesThis; | 238 bool thiscall = tf->fty->arg_this; |
238 bool delegatecall = (calleeType->toBasetype()->ty == Tdelegate); | 239 bool delegatecall = (calleeType->toBasetype()->ty == Tdelegate); |
239 bool nestedcall = tf->usesNest; | 240 bool nestedcall = tf->fty->arg_nest; |
240 bool dvarargs = (tf->linkage == LINKd && tf->varargs == 1); | 241 bool dvarargs = (tf->linkage == LINKd && tf->varargs == 1); |
241 | 242 |
242 unsigned callconv = DtoCallingConv(loc, tf->linkage); | 243 unsigned callconv = DtoCallingConv(loc, tf->linkage); |
243 | 244 |
244 // get callee llvm value | 245 // get callee llvm value |
259 // parameter attributes | 260 // parameter attributes |
260 std::vector<llvm::AttributeWithIndex> attrs; | 261 std::vector<llvm::AttributeWithIndex> attrs; |
261 llvm::AttributeWithIndex Attr; | 262 llvm::AttributeWithIndex Attr; |
262 | 263 |
263 // return attrs | 264 // return attrs |
264 if (tf->retAttrs) | 265 if (tf->fty->ret->attrs) |
265 { | 266 { |
266 Attr.Index = 0; | 267 Attr.Index = 0; |
267 Attr.Attrs = tf->retAttrs; | 268 Attr.Attrs = tf->fty->ret->attrs; |
268 attrs.push_back(Attr); | 269 attrs.push_back(Attr); |
269 } | 270 } |
270 | 271 |
271 // handle implicit arguments | 272 // handle implicit arguments |
272 std::vector<LLValue*> args; | 273 std::vector<LLValue*> args; |
274 args.reserve(tf->fty->args.size()); | |
273 | 275 |
274 // return in hidden ptr is first | 276 // return in hidden ptr is first |
275 if (retinptr) | 277 if (retinptr) |
276 { | 278 { |
277 LLValue* retvar = DtoAlloca(argiter->get()->getContainedType(0), ".rettmp"); | 279 LLValue* retvar = DtoAlloca(argiter->get()->getContainedType(0), ".rettmp"); |
323 error(loc, "Context argument required but none given"); | 325 error(loc, "Context argument required but none given"); |
324 fatal(); | 326 fatal(); |
325 } | 327 } |
326 | 328 |
327 // add attributes for context argument | 329 // add attributes for context argument |
328 if (tf->thisAttrs) | 330 if (tf->fty->arg_this && tf->fty->arg_this->attrs) |
329 { | 331 { |
330 Attr.Index = retinptr ? 2 : 1; | 332 Attr.Index = retinptr ? 2 : 1; |
331 Attr.Attrs = tf->thisAttrs; | 333 Attr.Attrs = tf->fty->arg_this->attrs; |
334 attrs.push_back(Attr); | |
335 } | |
336 else if (tf->fty->arg_nest && tf->fty->arg_nest->attrs) | |
337 { | |
338 Attr.Index = retinptr ? 2 : 1; | |
339 Attr.Attrs = tf->fty->arg_nest->attrs; | |
332 attrs.push_back(Attr); | 340 attrs.push_back(Attr); |
333 } | 341 } |
334 } | 342 } |
335 | 343 |
336 // handle the rest of the arguments based on param passing style | 344 // handle the rest of the arguments based on param passing style |
372 Argument* fnarg = Argument::getNth(tf->parameters, i); | 380 Argument* fnarg = Argument::getNth(tf->parameters, i); |
373 assert(fnarg); | 381 assert(fnarg); |
374 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); | 382 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); |
375 LLValue* arg = argval->getRVal(); | 383 LLValue* arg = argval->getRVal(); |
376 | 384 |
377 int j = tf->reverseParams ? beg + n - i - 1 : beg + i; | 385 int j = tf->fty->reverseParams ? beg + n - i - 1 : beg + i; |
378 | 386 |
379 // if it's a struct inreg arg, load first to pass as first-class value | 387 // give the ABI a say |
380 if (tf->structInregArg && i == (tf->reverseParams ? n - 1 : 0)) | 388 arg = tf->fty->putParam(argval->getType(), i, arg); |
381 { | |
382 assert((fnarg->llvmAttrs & llvm::Attribute::InReg) && isaStruct(tf->structInregArg)); | |
383 arg = DtoBitCast(arg, getPtrToType(callableTy->getParamType(j))); | |
384 arg = DtoLoad(arg); | |
385 } | |
386 | 389 |
387 // parameter type mismatch, this is hard to get rid of | 390 // parameter type mismatch, this is hard to get rid of |
388 if (arg->getType() != callableTy->getParamType(j)) | 391 if (arg->getType() != callableTy->getParamType(j)) |
389 { | 392 { |
390 #if 0 | 393 #if 1 |
391 if (Logger::enabled()) | 394 if (Logger::enabled()) |
392 { | 395 { |
393 Logger::cout() << "arg: " << *arg << '\n'; | 396 Logger::cout() << "arg: " << *arg << '\n'; |
394 Logger::cout() << "expects: " << *callableTy->getParamType(j) << '\n'; | 397 Logger::cout() << "expects: " << *callableTy->getParamType(j) << '\n'; |
395 } | 398 } |
396 #endif | 399 #endif |
397 arg = DtoBitCast(arg, callableTy->getParamType(j)); | 400 arg = DtoBitCast(arg, callableTy->getParamType(j)); |
398 } | 401 } |
399 | 402 |
400 // param attrs | 403 // param attrs |
401 attrptr[i] = fnarg->llvmAttrs; | 404 attrptr[i] = tf->fty->args[i]->attrs; |
402 | 405 |
403 ++argiter; | 406 ++argiter; |
404 args.push_back(arg); | 407 args.push_back(arg); |
405 } | 408 } |
406 | 409 |
407 // reverse the relevant params as well as the param attrs | 410 // reverse the relevant params as well as the param attrs |
408 if (tf->reverseParams) | 411 if (tf->fty->reverseParams) |
409 { | 412 { |
410 std::reverse(args.begin() + tf->firstRealArg, args.end()); | 413 std::reverse(args.begin() + beg, args.end()); |
411 std::reverse(attrptr.begin(), attrptr.end()); | 414 std::reverse(attrptr.begin(), attrptr.end()); |
412 } | 415 } |
413 | 416 |
414 // add attributes | 417 // add attributes |
415 for (int i = 0; i < n; i++) | 418 for (int i = 0; i < n; i++) |
473 LLValue* mem = DtoAlloca(retllval->getType()); | 476 LLValue* mem = DtoAlloca(retllval->getType()); |
474 DtoStore(retllval, mem); | 477 DtoStore(retllval, mem); |
475 retllval = mem; | 478 retllval = mem; |
476 } | 479 } |
477 } | 480 } |
478 else | 481 else if (!retinptr) |
479 { | 482 { |
480 // do abi specific return value fixups | 483 // do abi specific return value fixups |
481 retllval = gABI->getRet(tf, retllval); | 484 retllval = tf->fty->getRet(tf->next, retllval); |
482 } | 485 } |
483 | 486 |
484 // repaint the type if necessary | 487 // repaint the type if necessary |
485 if (resulttype) | 488 if (resulttype) |
486 { | 489 { |