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 {