annotate gen/functions.cpp @ 883:b52d5de7783f

GC defines and linkage changes.
author Christian Kamm <kamm incasoftware de>
date Thu, 08 Jan 2009 18:20:02 +0100
parents 94ba810ea2b0
children 545f54041d91
rev   line source
lindquist@100 1 #include "gen/llvm.h"
lindquist@262 2 #include "llvm/Support/CFG.h"
tomas@445 3 #include "llvm/Intrinsics.h"
lindquist@100 4
lindquist@100 5 #include "mtype.h"
lindquist@100 6 #include "aggregate.h"
lindquist@100 7 #include "init.h"
lindquist@100 8 #include "declaration.h"
lindquist@100 9 #include "template.h"
lindquist@100 10 #include "module.h"
lindquist@100 11 #include "statement.h"
lindquist@100 12
lindquist@100 13 #include "gen/irstate.h"
lindquist@100 14 #include "gen/tollvm.h"
lindquist@244 15 #include "gen/llvmhelpers.h"
lindquist@100 16 #include "gen/runtime.h"
lindquist@100 17 #include "gen/arrays.h"
lindquist@100 18 #include "gen/logger.h"
lindquist@100 19 #include "gen/functions.h"
lindquist@100 20 #include "gen/todebug.h"
lindquist@100 21 #include "gen/classes.h"
lindquist@131 22 #include "gen/dvalue.h"
lindquist@100 23
tomas@723 24 #include <algorithm>
tomas@723 25
tomas@486 26 const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, const LLType* nesttype, bool ismain)
lindquist@100 27 {
tomas@435 28 assert(type->ty == Tfunction);
lindquist@100 29 TypeFunction* f = (TypeFunction*)type;
lindquist@100 30
ChristianK@173 31 if (type->ir.type != NULL) {
ChristianK@173 32 return llvm::cast<llvm::FunctionType>(type->ir.type->get());
lindquist@100 33 }
lindquist@100 34
tomas@758 35 bool dVararg = false;
lindquist@162 36 bool arrayVararg = false;
lindquist@162 37 if (f->linkage == LINKd)
lindquist@162 38 {
lindquist@162 39 if (f->varargs == 1)
tomas@758 40 dVararg = true;
lindquist@162 41 else if (f->varargs == 2)
lindquist@162 42 arrayVararg = true;
lindquist@100 43 }
lindquist@100 44
lindquist@100 45 // return value type
lindquist@213 46 const LLType* rettype;
lindquist@213 47 const LLType* actualRettype;
lindquist@100 48 Type* rt = f->next;
lindquist@100 49 bool retinptr = false;
lindquist@100 50 bool usesthis = false;
tomas@486 51 bool usesnest = false;
lindquist@100 52
lindquist@234 53 // parameter types
lindquist@234 54 std::vector<const LLType*> paramvec;
lindquist@234 55
lindquist@234 56 if (ismain)
lindquist@234 57 {
lindquist@244 58 rettype = LLType::Int32Ty;
lindquist@100 59 actualRettype = rettype;
lindquist@234 60 if (Argument::dim(f->parameters) == 0)
lindquist@234 61 {
lindquist@234 62 const LLType* arrTy = DtoArrayType(LLType::Int8Ty);
lindquist@234 63 const LLType* arrArrTy = DtoArrayType(arrTy);
tomas@715 64 paramvec.push_back(arrArrTy);
lindquist@234 65 }
lindquist@100 66 }
lindquist@234 67 else{
lindquist@100 68 assert(rt);
lindquist@217 69 if (DtoIsReturnedInArg(rt)) {
lindquist@133 70 rettype = getPtrToType(DtoType(rt));
lindquist@244 71 actualRettype = LLType::VoidTy;
tomas@486 72 f->retInPtr = retinptr = true;
lindquist@100 73 }
lindquist@100 74 else {
lindquist@100 75 rettype = DtoType(rt);
lindquist@100 76 actualRettype = rettype;
lindquist@100 77 }
tomas@445 78
tomas@445 79 if (unsigned ea = DtoShouldExtend(rt))
tomas@445 80 {
tomas@486 81 f->retAttrs |= ea;
tomas@445 82 }
lindquist@100 83 }
lindquist@100 84
lindquist@100 85 if (retinptr) {
lindquist@123 86 //Logger::cout() << "returning through pointer parameter: " << *rettype << '\n';
lindquist@100 87 paramvec.push_back(rettype);
lindquist@100 88 }
lindquist@100 89
lindquist@100 90 if (thistype) {
lindquist@100 91 paramvec.push_back(thistype);
lindquist@100 92 usesthis = true;
lindquist@100 93 }
tomas@486 94 else if (nesttype) {
tomas@486 95 paramvec.push_back(nesttype);
tomas@486 96 usesnest = true;
tomas@486 97 }
lindquist@100 98
tomas@758 99 if (dVararg) {
tomas@797 100 paramvec.push_back(DtoType(Type::typeinfo->type->arrayOf())); // _arguments
tomas@797 101 paramvec.push_back(getVoidPtrType()); // _argptr
lindquist@100 102 }
lindquist@100 103
tomas@723 104 // number of formal params
lindquist@100 105 size_t n = Argument::dim(f->parameters);
lindquist@100 106
tomas@724 107 #if X86_REVERSE_PARAMS
tomas@723 108 // on x86 we need to reverse the formal params in some cases to match the ABI
tomas@723 109 if (global.params.cpu == ARCHx86)
tomas@723 110 {
tomas@723 111 // more than one formal arg,
tomas@723 112 // extern(D) linkage
tomas@723 113 // not a D-style vararg
tomas@758 114 if (n > 1 && f->linkage == LINKd && !dVararg)
tomas@723 115 {
tomas@723 116 f->reverseParams = true;
tomas@723 117 f->reverseIndex = paramvec.size();
tomas@723 118 }
tomas@723 119 }
tomas@724 120 #endif // X86_REVERSE_PARAMS
tomas@723 121
tomas@723 122
lindquist@100 123 for (int i=0; i < n; ++i) {
lindquist@100 124 Argument* arg = Argument::getNth(f->parameters, i);
lindquist@100 125 // ensure scalar
tomas@486 126 Type* argT = arg->type->toBasetype();
lindquist@100 127 assert(argT);
lindquist@100 128
lindquist@217 129 bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout));
lindquist@217 130
lindquist@213 131 const LLType* at = DtoType(argT);
tomas@585 132
tomas@719 133 // handle lazy args
tomas@719 134 if (arg->storageClass & STClazy)
tomas@719 135 {
tomas@719 136 Logger::println("lazy param");
tomas@719 137 TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd);
tomas@719 138 TypeDelegate *ltd = new TypeDelegate(ltf);
tomas@719 139 at = DtoType(ltd);
tomas@719 140 paramvec.push_back(at);
tomas@719 141 }
tomas@715 142 // opaque types need special handling
tomas@719 143 else if (llvm::isa<llvm::OpaqueType>(at)) {
lindquist@100 144 Logger::println("opaque param");
lindquist@100 145 assert(argT->ty == Tstruct || argT->ty == Tclass);
lindquist@133 146 paramvec.push_back(getPtrToType(at));
lindquist@100 147 }
tomas@719 148 // structs are passed as a reference, but by value
tomas@719 149 else if (argT->ty == Tstruct) {
tomas@719 150 Logger::println("struct param");
tomas@715 151 if (!refOrOut)
tomas@715 152 arg->llvmAttrs |= llvm::Attribute::ByVal;
tomas@715 153 paramvec.push_back(getPtrToType(at));
tomas@715 154 }
tomas@715 155 // static arrays are passed directly by reference
tomas@715 156 else if (argT->ty == Tsarray)
tomas@715 157 {
tomas@715 158 Logger::println("static array param");
tomas@715 159 at = getPtrToType(at);
tomas@715 160 paramvec.push_back(at);
tomas@715 161 }
tomas@715 162 // firstclass ' ref/out ' parameter
tomas@715 163 else if (refOrOut) {
tomas@715 164 Logger::println("ref/out param");
tomas@715 165 at = getPtrToType(at);
tomas@715 166 paramvec.push_back(at);
tomas@715 167 }
tomas@715 168 // firstclass ' in ' parameter
lindquist@100 169 else {
tomas@715 170 Logger::println("in param");
tomas@715 171 if (unsigned ea = DtoShouldExtend(argT))
tomas@715 172 arg->llvmAttrs |= ea;
lindquist@100 173 paramvec.push_back(at);
lindquist@100 174 }
lindquist@100 175 }
lindquist@100 176
tomas@723 177 // reverse params?
tomas@723 178 if (f->reverseParams)
tomas@723 179 {
tomas@723 180 std::reverse(paramvec.begin() + f->reverseIndex, paramvec.end());
tomas@723 181 }
tomas@723 182
lindquist@100 183 // construct function type
tomas@758 184 bool isvararg = !(dVararg || arrayVararg) && f->varargs;
lindquist@100 185 llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
lindquist@100 186
tomas@724 187 #if X86_PASS_IN_EAX
tomas@720 188 // tell first param to be passed in a register if we can
tomas@720 189 // ONLY extern(D) functions !
tomas@720 190 if ((n > 0 || usesthis || usesnest) && f->linkage == LINKd)
tomas@720 191 {
tomas@720 192 // FIXME: Only x86 right now ...
tomas@720 193 if (global.params.cpu == ARCHx86)
tomas@720 194 {
tomas@720 195 // pass first param in EAX if it fits, is not floating point and is not a 3 byte struct.
tomas@720 196 // FIXME: struct are not passed in EAX yet
tomas@720 197
kamm@739 198 int n_inreg = f->reverseParams ? n - 1 : 0;
kamm@739 199 Argument* arg = Argument::getNth(f->parameters, n_inreg);
kamm@739 200
tomas@720 201 // if there is a implicit context parameter, pass it in EAX
tomas@720 202 if (usesthis || usesnest)
tomas@720 203 {
tomas@720 204 f->thisAttrs |= llvm::Attribute::InReg;
kamm@739 205 assert((!arg || (arg->llvmAttrs & llvm::Attribute::InReg) == 0) && "can't have two inreg args!");
tomas@720 206 }
tomas@720 207 // otherwise check the first formal parameter
tomas@720 208 else
tomas@720 209 {
tomas@720 210 Type* t = arg->type->toBasetype();
tomas@720 211
tomas@724 212 // 32bit ints, pointers, classes, static arrays and AAs
tomas@724 213 // are candidate for being passed in EAX
tomas@720 214 if ((arg->storageClass & STCin) &&
tomas@724 215 ((t->isscalar() && !t->isfloating()) ||
tomas@724 216 t->ty == Tclass || t->ty == Tsarray || t->ty == Taarray) &&
tomas@720 217 (t->size() <= PTRSIZE))
tomas@720 218 {
tomas@720 219 arg->llvmAttrs |= llvm::Attribute::InReg;
kamm@739 220 assert((f->thisAttrs & llvm::Attribute::InReg) == 0 && "can't have two inreg args!");
tomas@720 221 }
tomas@720 222 }
tomas@720 223 }
tomas@720 224 }
tomas@724 225 #endif // X86_PASS_IN_EAX
tomas@720 226
tomas@720 227 // done
tomas@486 228 f->retInPtr = retinptr;
tomas@486 229 f->usesThis = usesthis;
tomas@486 230 f->usesNest = usesnest;
lindquist@100 231
lindquist@217 232 f->ir.type = new llvm::PATypeHolder(functype);
lindquist@100 233
lindquist@100 234 return functype;
lindquist@100 235 }
lindquist@100 236
lindquist@100 237 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@100 238
lindquist@100 239 static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
lindquist@100 240 {
lindquist@102 241 // type has already been resolved
ChristianK@173 242 if (fdecl->type->ir.type != 0) {
ChristianK@173 243 return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get());
lindquist@102 244 }
lindquist@102 245
lindquist@100 246 TypeFunction* f = (TypeFunction*)fdecl->type;
tomas@445 247 const llvm::FunctionType* fty = 0;
lindquist@100 248
tomas@445 249 if (fdecl->llvmInternal == LLVMva_start)
tomas@445 250 fty = GET_INTRINSIC_DECL(vastart)->getFunctionType();
tomas@445 251 else if (fdecl->llvmInternal == LLVMva_copy)
tomas@445 252 fty = GET_INTRINSIC_DECL(vacopy)->getFunctionType();
tomas@445 253 else if (fdecl->llvmInternal == LLVMva_end)
tomas@445 254 fty = GET_INTRINSIC_DECL(vaend)->getFunctionType();
tomas@445 255 assert(fty);
lindquist@100 256
ChristianK@173 257 f->ir.type = new llvm::PATypeHolder(fty);
lindquist@100 258 return fty;
lindquist@100 259 }
lindquist@100 260
lindquist@100 261 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@100 262
lindquist@100 263 const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
lindquist@100 264 {
tomas@445 265 // handle for C vararg intrinsics
tomas@445 266 if (fdecl->isVaIntrinsic())
lindquist@100 267 return DtoVaFunctionType(fdecl);
lindquist@100 268
lindquist@100 269 // type has already been resolved
tomas@445 270 if (fdecl->type->ir.type != 0)
ChristianK@173 271 return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get());
lindquist@100 272
tomas@486 273 const LLType* thisty = 0;
tomas@486 274 const LLType* nestty = 0;
tomas@486 275
lindquist@100 276 if (fdecl->needThis()) {
lindquist@132 277 if (AggregateDeclaration* ad = fdecl->isMember2()) {
lindquist@132 278 Logger::println("isMember = this is: %s", ad->type->toChars());
lindquist@100 279 thisty = DtoType(ad->type);
lindquist@113 280 //Logger::cout() << "this llvm type: " << *thisty << '\n';
tomas@797 281 if (isaStruct(thisty) || (!gIR->structs.empty() && thisty == gIR->topstruct()->type->ir.type->get()))
lindquist@133 282 thisty = getPtrToType(thisty);
lindquist@100 283 }
lindquist@132 284 else {
lindquist@132 285 Logger::println("chars: %s type: %s kind: %s", fdecl->toChars(), fdecl->type->toChars(), fdecl->kind());
lindquist@132 286 assert(0);
lindquist@132 287 }
lindquist@100 288 }
lindquist@100 289 else if (fdecl->isNested()) {
tomas@486 290 nestty = getPtrToType(LLType::Int8Ty);
lindquist@100 291 }
lindquist@100 292
tomas@486 293 const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, nestty, fdecl->isMain());
lindquist@100 294
lindquist@100 295 return functype;
lindquist@100 296 }
lindquist@100 297
lindquist@100 298 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@100 299
lindquist@100 300 static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl)
lindquist@100 301 {
tomas@486 302 TypeFunction* f = (TypeFunction*)fdecl->type->toBasetype();
lindquist@100 303 const llvm::FunctionType* fty = DtoVaFunctionType(fdecl);
tomas@445 304 llvm::Function* func = 0;
lindquist@100 305
tomas@445 306 if (fdecl->llvmInternal == LLVMva_start)
tomas@445 307 func = GET_INTRINSIC_DECL(vastart);
tomas@445 308 else if (fdecl->llvmInternal == LLVMva_copy)
tomas@445 309 func = GET_INTRINSIC_DECL(vacopy);
tomas@445 310 else if (fdecl->llvmInternal == LLVMva_end)
tomas@445 311 func = GET_INTRINSIC_DECL(vaend);
tomas@445 312 assert(func);
lindquist@100 313
ChristianK@173 314 fdecl->ir.irFunc->func = func;
lindquist@100 315 return func;
lindquist@100 316 }
lindquist@100 317
lindquist@100 318 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@100 319
lindquist@102 320 void DtoResolveFunction(FuncDeclaration* fdecl)
lindquist@102 321 {
lindquist@121 322 if (!global.params.useUnitTests && fdecl->isUnitTestDeclaration()) {
lindquist@121 323 return; // ignore declaration completely
lindquist@121 324 }
lindquist@121 325
lindquist@133 326 // is imported and we don't have access?
lindquist@133 327 if (fdecl->getModule() != gIR->dmodule)
lindquist@133 328 {
lindquist@133 329 if (fdecl->prot() == PROTprivate)
lindquist@133 330 return;
lindquist@133 331 }
lindquist@133 332
ChristianK@173 333 if (fdecl->ir.resolved) return;
ChristianK@173 334 fdecl->ir.resolved = true;
lindquist@102 335
lindquist@132 336 Logger::println("DtoResolveFunction(%s): %s", fdecl->toPrettyChars(), fdecl->loc.toChars());
lindquist@102 337 LOG_SCOPE;
lindquist@102 338
tomas@622 339 //printf("resolve function: %s\n", fdecl->toPrettyChars());
tomas@622 340
lindquist@102 341 if (fdecl->parent)
lindquist@102 342 if (TemplateInstance* tinst = fdecl->parent->isTemplateInstance())
lindquist@102 343 {
lindquist@102 344 TemplateDeclaration* tempdecl = tinst->tempdecl;
lindquist@102 345 if (tempdecl->llvmInternal == LLVMva_arg)
lindquist@102 346 {
lindquist@102 347 Logger::println("magic va_arg found");
lindquist@102 348 fdecl->llvmInternal = LLVMva_arg;
ChristianK@173 349 fdecl->ir.declared = true;
ChristianK@173 350 fdecl->ir.initialized = true;
ChristianK@173 351 fdecl->ir.defined = true;
lindquist@102 352 return; // this gets mapped to an instruction so a declaration makes no sence
lindquist@102 353 }
lindquist@102 354 else if (tempdecl->llvmInternal == LLVMva_start)
lindquist@102 355 {
lindquist@102 356 Logger::println("magic va_start found");
lindquist@102 357 fdecl->llvmInternal = LLVMva_start;
lindquist@102 358 }
tomas@527 359 else if (tempdecl->llvmInternal == LLVMintrinsic)
tomas@527 360 {
tomas@527 361 Logger::println("overloaded intrinsic found");
tomas@527 362 fdecl->llvmInternal = LLVMintrinsic;
tomas@527 363 DtoOverloadedIntrinsicName(tinst, tempdecl, fdecl->intrinsicName);
tomas@723 364 fdecl->linkage = LINKintrinsic;
tomas@723 365 ((TypeFunction*)fdecl->type)->linkage = LINKintrinsic;
tomas@527 366 }
lindquist@102 367 }
lindquist@102 368
lindquist@102 369 DtoFunctionType(fdecl);
lindquist@102 370
lindquist@102 371 // queue declaration
lindquist@113 372 if (!fdecl->isAbstract())
lindquist@113 373 gIR->declareList.push_back(fdecl);
lindquist@102 374 }
lindquist@102 375
lindquist@102 376 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@102 377
lindquist@240 378 static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclaration* fdecl)
lindquist@240 379 {
tomas@723 380 int llidx = 0;
tomas@486 381 if (f->retInPtr) ++llidx;
tomas@486 382 if (f->usesThis) ++llidx;
tomas@486 383 else if (f->usesNest) ++llidx;
lindquist@240 384 if (f->linkage == LINKd && f->varargs == 1)
lindquist@240 385 llidx += 2;
lindquist@240 386
lindquist@240 387 int funcNumArgs = func->getArgumentList().size();
lindquist@240 388
tomas@723 389 LLSmallVector<llvm::AttributeWithIndex, 9> attrs;
tomas@632 390 llvm::AttributeWithIndex PAWI;
lindquist@240 391
tomas@446 392 // set return value attrs if any
tomas@486 393 if (f->retAttrs)
tomas@445 394 {
tomas@445 395 PAWI.Index = 0;
tomas@486 396 PAWI.Attrs = f->retAttrs;
tomas@445 397 attrs.push_back(PAWI);
tomas@445 398 }
tomas@445 399
tomas@454 400 // set sret param
tomas@486 401 if (f->retInPtr)
tomas@454 402 {
tomas@454 403 PAWI.Index = 1;
tomas@632 404 PAWI.Attrs = llvm::Attribute::StructRet;
tomas@454 405 attrs.push_back(PAWI);
tomas@454 406 }
tomas@454 407
tomas@720 408 // set this/nest param attrs
tomas@720 409 if (f->thisAttrs)
tomas@720 410 {
tomas@720 411 PAWI.Index = f->retInPtr ? 2 : 1;
tomas@720 412 PAWI.Attrs = f->thisAttrs;
tomas@720 413 attrs.push_back(PAWI);
tomas@720 414 }
tomas@720 415
tomas@445 416 // set attrs on the rest of the arguments
tomas@723 417 size_t n = Argument::dim(f->parameters);
tomas@723 418 assert(funcNumArgs >= n); // main might mismatch, for the implicit char[][] arg
tomas@723 419
tomas@723 420 LLSmallVector<unsigned,8> attrptr(n, 0);
tomas@723 421
tomas@723 422 for (size_t k = 0; k < n; ++k)
lindquist@240 423 {
tomas@454 424 Argument* fnarg = Argument::getNth(f->parameters, k);
lindquist@240 425 assert(fnarg);
tomas@445 426
tomas@723 427 attrptr[k] = fnarg->llvmAttrs;
lindquist@240 428 }
lindquist@240 429
tomas@723 430 // reverse params?
tomas@723 431 if (f->reverseParams)
tomas@723 432 {
tomas@723 433 std::reverse(attrptr.begin(), attrptr.end());
tomas@723 434 }
tomas@723 435
tomas@723 436 // build rest of attrs list
tomas@723 437 for (int i = 0; i < n; i++)
tomas@723 438 {
tomas@723 439 if (attrptr[i])
tomas@723 440 {
tomas@723 441 PAWI.Index = llidx+i+1;
tomas@723 442 PAWI.Attrs = attrptr[i];
tomas@723 443 attrs.push_back(PAWI);
tomas@723 444 }
tomas@723 445 }
tomas@723 446
tomas@723 447 llvm::AttrListPtr attrlist = llvm::AttrListPtr::get(attrs.begin(), attrs.end());
tomas@723 448 func->setAttributes(attrlist);
lindquist@240 449 }
lindquist@240 450
lindquist@240 451 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@240 452
lindquist@100 453 void DtoDeclareFunction(FuncDeclaration* fdecl)
lindquist@100 454 {
ChristianK@173 455 if (fdecl->ir.declared) return;
ChristianK@173 456 fdecl->ir.declared = true;
lindquist@102 457
lindquist@132 458 Logger::println("DtoDeclareFunction(%s): %s", fdecl->toPrettyChars(), fdecl->loc.toChars());
lindquist@100 459 LOG_SCOPE;
lindquist@100 460
tomas@622 461 //printf("declare function: %s\n", fdecl->toPrettyChars());
tomas@622 462
lindquist@121 463 // intrinsic sanity check
lindquist@121 464 if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) {
lindquist@121 465 error(fdecl->loc, "intrinsics cannot have function bodies");
lindquist@121 466 fatal();
lindquist@121 467 }
lindquist@121 468
lindquist@240 469 // get TypeFunction*
tomas@486 470 Type* t = fdecl->type->toBasetype();
lindquist@240 471 TypeFunction* f = (TypeFunction*)t;
lindquist@240 472
lindquist@100 473 bool declareOnly = false;
lindquist@102 474 bool templInst = fdecl->parent && DtoIsTemplateInstance(fdecl->parent);
lindquist@102 475 if (!templInst && fdecl->getModule() != gIR->dmodule)
lindquist@144 476 {
lindquist@144 477 Logger::println("not template instance, and not in this module. declare only!");
lindquist@144 478 Logger::println("current module: %s", gIR->dmodule->ident->toChars());
kamm@378 479 if(fdecl->getModule())
kamm@378 480 Logger::println("func module: %s", fdecl->getModule()->ident->toChars());
kamm@379 481 else {
kamm@379 482 Logger::println("func not in a module, is runtime");
kamm@379 483 }
lindquist@102 484 declareOnly = true;
lindquist@144 485 }
lindquist@102 486 else if (fdecl->llvmInternal == LLVMva_start)
lindquist@102 487 declareOnly = true;
lindquist@100 488
ChristianK@173 489 if (!fdecl->ir.irFunc) {
ChristianK@173 490 fdecl->ir.irFunc = new IrFunction(fdecl);
lindquist@100 491 }
lindquist@100 492
lindquist@100 493 // mangled name
tomas@443 494 const char* mangled_name;
lindquist@100 495 if (fdecl->llvmInternal == LLVMintrinsic)
tomas@443 496 mangled_name = fdecl->intrinsicName.c_str();
lindquist@100 497 else
lindquist@100 498 mangled_name = fdecl->mangle();
lindquist@100 499
lindquist@100 500 llvm::Function* vafunc = 0;
tomas@445 501 if (fdecl->isVaIntrinsic())
lindquist@100 502 vafunc = DtoDeclareVaFunction(fdecl);
lindquist@100 503
lindquist@100 504 // construct function
lindquist@100 505 const llvm::FunctionType* functype = DtoFunctionType(fdecl);
lindquist@100 506 llvm::Function* func = vafunc ? vafunc : gIR->module->getFunction(mangled_name);
lindquist@100 507 if (!func)
lindquist@205 508 func = llvm::Function::Create(functype, DtoLinkage(fdecl), mangled_name, gIR->module);
lindquist@100 509
lindquist@100 510 // add func to IRFunc
ChristianK@173 511 fdecl->ir.irFunc->func = func;
lindquist@100 512
lindquist@100 513 // calling convention
lindquist@100 514 if (!vafunc && fdecl->llvmInternal != LLVMintrinsic)
lindquist@100 515 func->setCallingConv(DtoCallingConv(f->linkage));
lindquist@149 516 else // fall back to C, it should be the right thing to do
lindquist@132 517 func->setCallingConv(llvm::CallingConv::C);
lindquist@132 518
ChristianK@173 519 fdecl->ir.irFunc->func = func;
ChristianK@173 520 assert(llvm::isa<llvm::FunctionType>(f->ir.type->get()));
lindquist@100 521
lindquist@217 522 // parameter attributes
tomas@454 523 if (!fdecl->isIntrinsic()) {
lindquist@240 524 set_param_attrs(f, func, fdecl);
lindquist@217 525 }
lindquist@217 526
lindquist@116 527 // main
lindquist@100 528 if (fdecl->isMain()) {
lindquist@100 529 gIR->mainFunc = func;
lindquist@100 530 }
lindquist@100 531
lindquist@116 532 // static ctor
lindquist@163 533 if (fdecl->isStaticCtorDeclaration() && fdecl->getModule() == gIR->dmodule) {
lindquist@116 534 gIR->ctors.push_back(fdecl);
lindquist@116 535 }
lindquist@116 536 // static dtor
lindquist@163 537 else if (fdecl->isStaticDtorDeclaration() && fdecl->getModule() == gIR->dmodule) {
lindquist@116 538 gIR->dtors.push_back(fdecl);
lindquist@116 539 }
lindquist@116 540
lindquist@162 541 // we never reference parameters of function prototypes
tomas@797 542 std::string str;
lindquist@162 543 if (!declareOnly)
lindquist@162 544 {
lindquist@162 545 // name parameters
lindquist@162 546 llvm::Function::arg_iterator iarg = func->arg_begin();
tomas@723 547
tomas@486 548 if (f->retInPtr) {
tomas@797 549 iarg->setName(".sret_arg");
ChristianK@173 550 fdecl->ir.irFunc->retArg = iarg;
lindquist@162 551 ++iarg;
lindquist@162 552 }
tomas@723 553
tomas@486 554 if (f->usesThis) {
tomas@797 555 iarg->setName(".this_arg");
tomas@486 556 fdecl->ir.irFunc->thisArg = iarg;
tomas@486 557 assert(fdecl->ir.irFunc->thisArg);
tomas@486 558 ++iarg;
tomas@486 559 }
tomas@486 560 else if (f->usesNest) {
tomas@797 561 iarg->setName(".nest_arg");
tomas@486 562 fdecl->ir.irFunc->nestArg = iarg;
tomas@486 563 assert(fdecl->ir.irFunc->nestArg);
lindquist@162 564 ++iarg;
lindquist@162 565 }
lindquist@119 566
lindquist@162 567 if (f->linkage == LINKd && f->varargs == 1) {
tomas@797 568 iarg->setName("._arguments");
ChristianK@173 569 fdecl->ir.irFunc->_arguments = iarg;
lindquist@162 570 ++iarg;
tomas@797 571 iarg->setName("._argptr");
ChristianK@173 572 fdecl->ir.irFunc->_argptr = iarg;
lindquist@162 573 ++iarg;
lindquist@162 574 }
lindquist@119 575
tomas@723 576 int k = 0;
tomas@723 577
lindquist@162 578 for (; iarg != func->arg_end(); ++iarg)
lindquist@162 579 {
lindquist@162 580 if (fdecl->parameters && fdecl->parameters->dim > k)
lindquist@162 581 {
tomas@723 582 Dsymbol* argsym;
tomas@723 583 if (f->reverseParams)
tomas@723 584 argsym = (Dsymbol*)fdecl->parameters->data[fdecl->parameters->dim-k-1];
tomas@723 585 else
tomas@723 586 argsym = (Dsymbol*)fdecl->parameters->data[k];
tomas@723 587
lindquist@162 588 VarDeclaration* argvd = argsym->isVarDeclaration();
lindquist@162 589 assert(argvd);
ChristianK@173 590 assert(!argvd->ir.irLocal);
ChristianK@173 591 argvd->ir.irLocal = new IrLocal(argvd);
ChristianK@173 592 argvd->ir.irLocal->value = iarg;
tomas@797 593
tomas@797 594 str = argvd->ident->toChars();
tomas@797 595 str.append("_arg");
tomas@797 596 iarg->setName(str);
tomas@723 597
tomas@723 598 k++;
lindquist@100 599 }
lindquist@162 600 else
lindquist@162 601 {
lindquist@162 602 iarg->setName("unnamed");
lindquist@162 603 }
lindquist@100 604 }
lindquist@100 605 }
lindquist@100 606
kamm@830 607 if (fdecl->isUnitTestDeclaration() && !declareOnly)
lindquist@121 608 gIR->unitTests.push_back(fdecl);
lindquist@121 609
lindquist@100 610 if (!declareOnly)
lindquist@102 611 gIR->defineList.push_back(fdecl);
lindquist@133 612 else
lindquist@133 613 assert(func->getLinkage() != llvm::GlobalValue::InternalLinkage);
lindquist@100 614
tomas@622 615 if (Logger::enabled())
tomas@622 616 Logger::cout() << "func decl: " << *func << '\n';
lindquist@100 617 }
lindquist@100 618
lindquist@100 619 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@100 620
lindquist@100 621 void DtoDefineFunc(FuncDeclaration* fd)
lindquist@100 622 {
ChristianK@173 623 if (fd->ir.defined) return;
ChristianK@173 624 fd->ir.defined = true;
lindquist@102 625
ChristianK@173 626 assert(fd->ir.declared);
lindquist@108 627
lindquist@132 628 Logger::println("DtoDefineFunc(%s): %s", fd->toPrettyChars(), fd->loc.toChars());
lindquist@102 629 LOG_SCOPE;
lindquist@102 630
lindquist@100 631 // debug info
lindquist@100 632 if (global.params.symdebug) {
lindquist@100 633 Module* mo = fd->getModule();
lindquist@250 634 fd->ir.irFunc->dwarfSubProg = DtoDwarfSubProgram(fd);
lindquist@100 635 }
lindquist@100 636
tomas@486 637 Type* t = fd->type->toBasetype();
lindquist@100 638 TypeFunction* f = (TypeFunction*)t;
ChristianK@173 639 assert(f->ir.type);
lindquist@100 640
ChristianK@173 641 llvm::Function* func = fd->ir.irFunc->func;
lindquist@100 642 const llvm::FunctionType* functype = func->getFunctionType();
lindquist@100 643
lindquist@100 644 // only members of the current module or template instances maybe be defined
lindquist@244 645 if (!(fd->getModule() == gIR->dmodule || DtoIsTemplateInstance(fd->parent)))
lindquist@244 646 return;
lindquist@244 647
lindquist@244 648 // set module owner
lindquist@244 649 fd->ir.DModule = gIR->dmodule;
lindquist@244 650
lindquist@244 651 // is there a body?
lindquist@244 652 if (fd->fbody == NULL)
lindquist@244 653 return;
lindquist@244 654
lindquist@244 655 Logger::println("Doing function body for: %s", fd->toChars());
lindquist@244 656 assert(fd->ir.irFunc);
tomas@468 657 IrFunction* irfunction = fd->ir.irFunc;
tomas@468 658 gIR->functions.push_back(irfunction);
lindquist@244 659
lindquist@244 660 if (fd->isMain())
lindquist@244 661 gIR->emitMain = true;
lindquist@244 662
tomas@797 663 std::string entryname("entry");
lindquist@244 664
lindquist@244 665 llvm::BasicBlock* beginbb = llvm::BasicBlock::Create(entryname,func);
lindquist@244 666 llvm::BasicBlock* endbb = llvm::BasicBlock::Create("endentry",func);
lindquist@244 667
lindquist@244 668 //assert(gIR->scopes.empty());
lindquist@244 669 gIR->scopes.push_back(IRScope(beginbb, endbb));
lindquist@244 670
lindquist@244 671 // create alloca point
lindquist@244 672 llvm::Instruction* allocaPoint = new llvm::AllocaInst(LLType::Int32Ty, "alloca point", beginbb);
tomas@468 673 irfunction->allocapoint = allocaPoint;
lindquist@244 674
tomas@452 675 // debug info - after all allocas, but before any llvm.dbg.declare etc
tomas@452 676 if (global.params.symdebug) DtoDwarfFuncStart(fd);
tomas@452 677
tomas@486 678 // need result variable?
tomas@486 679 if (fd->vresult) {
tomas@486 680 Logger::println("vresult value");
lindquist@244 681 fd->vresult->ir.irLocal = new IrLocal(fd->vresult);
tomas@486 682 fd->vresult->ir.irLocal->value = DtoAlloca(DtoType(fd->vresult->type), "function_vresult");
lindquist@244 683 }
tomas@526 684
tomas@526 685 // this hack makes sure the frame pointer elimination optimization is disabled.
tomas@526 686 // this this eliminates a bunch of inline asm related issues.
tomas@526 687 // naked must always eliminate the framepointer however...
tomas@526 688 if (fd->inlineAsm && !fd->naked)
tomas@526 689 {
tomas@526 690 // emit a call to llvm_eh_unwind_init
tomas@526 691 LLFunction* hack = GET_INTRINSIC_DECL(eh_unwind_init);
tomas@526 692 gIR->ir->CreateCall(hack, "");
tomas@526 693 }
lindquist@244 694
tomas@468 695 // give the 'this' argument storage and debug info
tomas@486 696 if (f->usesThis)
lindquist@254 697 {
tomas@486 698 LLValue* thisvar = irfunction->thisArg;
tomas@468 699 assert(thisvar);
tomas@468 700
tomas@797 701 LLValue* thismem = DtoAlloca(thisvar->getType(), "this");
tomas@468 702 DtoStore(thisvar, thismem);
tomas@486 703 irfunction->thisArg = thismem;
tomas@486 704
tomas@486 705 assert(!fd->vthis->ir.irLocal);
tomas@486 706 fd->vthis->ir.irLocal = new IrLocal(fd->vthis);
tomas@486 707 fd->vthis->ir.irLocal->value = thismem;
tomas@468 708
tomas@468 709 if (global.params.symdebug)
tomas@468 710 DtoDwarfLocalVariable(thismem, fd->vthis);
tomas@758 711
tomas@758 712 #if DMDV2
tomas@758 713 if (fd->vthis->nestedrefs.dim)
tomas@758 714 #else
tomas@486 715 if (fd->vthis->nestedref)
tomas@758 716 #endif
tomas@758 717 {
tomas@486 718 fd->nestedVars.insert(fd->vthis);
tomas@758 719 }
lindquist@254 720 }
lindquist@254 721
lindquist@244 722 // give arguments storage
tomas@468 723 // and debug info
lindquist@244 724 if (fd->parameters)
lindquist@100 725 {
lindquist@244 726 size_t n = fd->parameters->dim;
lindquist@244 727 for (int i=0; i < n; ++i)
lindquist@244 728 {
lindquist@244 729 Dsymbol* argsym = (Dsymbol*)fd->parameters->data[i];
lindquist@244 730 VarDeclaration* vd = argsym->isVarDeclaration();
lindquist@244 731 assert(vd);
tomas@758 732
tomas@758 733 #if DMDV2
tomas@758 734 if (vd->nestedrefs.dim)
tomas@758 735 #else
tomas@486 736 if (vd->nestedref)
tomas@758 737 #endif
tomas@758 738 {
tomas@486 739 fd->nestedVars.insert(vd);
tomas@758 740 }
lindquist@100 741
tomas@468 742 IrLocal* irloc = vd->ir.irLocal;
tomas@468 743 assert(irloc);
tomas@468 744
tomas@719 745 bool refout = vd->storage_class & (STCref | STCout);
tomas@719 746 bool lazy = vd->storage_class & STClazy;
tomas@457 747
kamm@752 748 if (!refout && (!DtoIsPassedByRef(vd->type) || lazy))
tomas@449 749 {
kamm@752 750 LLValue* a = irloc->value;
tomas@797 751 LLValue* v = DtoAlloca(a->getType(), vd->ident->toChars());
kamm@752 752 DtoStore(a,v);
kamm@752 753 irloc->value = v;
tomas@449 754 }
kamm@752 755 if (global.params.symdebug && !(isaArgument(irloc->value) && !isaArgument(irloc->value)->hasByValAttr()) && !refout)
kamm@752 756 DtoDwarfLocalVariable(irloc->value, vd);
lindquist@100 757 }
lindquist@100 758 }
lindquist@244 759
tomas@758 760 // need result variable? (nested)
tomas@758 761 #if DMDV2
tomas@758 762 if (fd->vresult && fd->vresult->nestedrefs.dim) {
tomas@758 763 #else
lindquist@244 764 if (fd->vresult && fd->vresult->nestedref) {
tomas@758 765 #endif
lindquist@244 766 Logger::println("nested vresult value: %s", fd->vresult->toChars());
lindquist@244 767 fd->nestedVars.insert(fd->vresult);
lindquist@244 768 }
lindquist@244 769
tomas@486 770 // construct nested variables array
tomas@486 771 if (!fd->nestedVars.empty())
tomas@486 772 {
tomas@486 773 Logger::println("has nested frame");
tomas@838 774 // start with adding all enclosing parent frames until a static parent is reached
tomas@486 775 int nparelems = 0;
tomas@838 776 if (!fd->isStatic())
tomas@486 777 {
tomas@838 778 Dsymbol* par = fd->toParent2();
tomas@838 779 while (par)
tomas@486 780 {
tomas@838 781 if (FuncDeclaration* parfd = par->isFuncDeclaration())
tomas@838 782 {
tomas@838 783 nparelems += parfd->nestedVars.size();
tomas@838 784 // stop at first static
tomas@838 785 if (parfd->isStatic())
tomas@838 786 break;
tomas@838 787 }
tomas@838 788 else if (ClassDeclaration* parcd = par->isClassDeclaration())
tomas@838 789 {
tomas@838 790 // nothing needed
tomas@838 791 }
tomas@838 792 else
tomas@838 793 {
tomas@838 794 break;
tomas@838 795 }
tomas@838 796
tomas@838 797 par = par->toParent2();
tomas@486 798 }
lindquist@244 799 }
tomas@486 800 int nelems = fd->nestedVars.size() + nparelems;
tomas@486 801
tomas@486 802 // make array type for nested vars
tomas@486 803 const LLType* nestedVarsTy = LLArrayType::get(getVoidPtrType(), nelems);
tomas@486 804
tomas@486 805 // alloca it
tomas@486 806 LLValue* nestedVars = DtoAlloca(nestedVarsTy, ".nested_vars");
tomas@486 807
tomas@486 808 // copy parent frame into beginning
tomas@486 809 if (nparelems)
tomas@486 810 {
tomas@486 811 LLValue* src = irfunction->nestArg;
tomas@486 812 if (!src)
tomas@486 813 {
tomas@486 814 assert(irfunction->thisArg);
tomas@486 815 assert(fd->isMember2());
tomas@486 816 LLValue* thisval = DtoLoad(irfunction->thisArg);
tomas@486 817 ClassDeclaration* cd = fd->isMember2()->isClassDeclaration();
tomas@486 818 assert(cd);
tomas@486 819 assert(cd->vthis);
tomas@797 820 src = DtoLoad(DtoGEPi(thisval, 0,cd->vthis->ir.irField->index, ".vthis"));
tomas@486 821 }
tomas@486 822 DtoMemCpy(nestedVars, src, DtoConstSize_t(nparelems*PTRSIZE));
tomas@486 823 }
tomas@486 824
tomas@486 825 // store in IrFunction
tomas@486 826 irfunction->nestedVar = nestedVars;
tomas@486 827
tomas@486 828 // go through all nested vars and assign indices
tomas@486 829 int idx = nparelems;
tomas@486 830 for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i)
tomas@486 831 {
lindquist@244 832 VarDeclaration* vd = *i;
lindquist@244 833 if (!vd->ir.irLocal)
lindquist@244 834 vd->ir.irLocal = new IrLocal(vd);
tomas@486 835
tomas@486 836 if (vd->isParameter())
tomas@486 837 {
tomas@486 838 Logger::println("nested param: %s", vd->toChars());
tomas@486 839 LLValue* gep = DtoGEPi(nestedVars, 0, idx);
tomas@486 840 LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
tomas@486 841 DtoStore(val, gep);
lindquist@244 842 }
tomas@486 843 else
tomas@486 844 {
tomas@486 845 Logger::println("nested var: %s", vd->toChars());
lindquist@244 846 }
tomas@486 847
tomas@486 848 vd->ir.irLocal->nestedIndex = idx++;
lindquist@244 849 }
tomas@758 850
tomas@486 851 // fixup nested result variable
tomas@758 852 #if DMDV2
tomas@758 853 if (fd->vresult && fd->vresult->nestedrefs.dim) {
tomas@758 854 #else
tomas@486 855 if (fd->vresult && fd->vresult->nestedref) {
tomas@758 856 #endif
tomas@486 857 Logger::println("nested vresult value: %s", fd->vresult->toChars());
tomas@486 858 LLValue* gep = DtoGEPi(nestedVars, 0, fd->vresult->ir.irLocal->nestedIndex);
tomas@486 859 LLValue* val = DtoBitCast(fd->vresult->ir.irLocal->value, getVoidPtrType());
tomas@486 860 DtoStore(val, gep);
lindquist@244 861 }
lindquist@244 862 }
lindquist@244 863
tomas@715 864 // copy _argptr and _arguments to a memory location
lindquist@244 865 if (f->linkage == LINKd && f->varargs == 1)
lindquist@244 866 {
tomas@715 867 // _argptr
tomas@486 868 LLValue* argptrmem = DtoAlloca(fd->ir.irFunc->_argptr->getType(), "_argptr_mem");
lindquist@244 869 new llvm::StoreInst(fd->ir.irFunc->_argptr, argptrmem, gIR->scopebb());
lindquist@244 870 fd->ir.irFunc->_argptr = argptrmem;
tomas@715 871
tomas@715 872 // _arguments
tomas@715 873 LLValue* argumentsmem = DtoAlloca(fd->ir.irFunc->_arguments->getType(), "_arguments_mem");
tomas@715 874 new llvm::StoreInst(fd->ir.irFunc->_arguments, argumentsmem, gIR->scopebb());
tomas@715 875 fd->ir.irFunc->_arguments = argumentsmem;
lindquist@244 876 }
lindquist@244 877
lindquist@244 878 // output function body
lindquist@244 879 fd->fbody->toIR(gIR);
lindquist@244 880
lindquist@244 881 // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement
lindquist@244 882 // in automatically, so we do it here.
kamm@428 883 if (!gIR->scopereturned()) {
kamm@428 884 // pass the previous block into this block
kamm@428 885 if (global.params.symdebug) DtoDwarfFuncEnd(fd);
kamm@428 886 if (func->getReturnType() == LLType::VoidTy) {
kamm@428 887 llvm::ReturnInst::Create(gIR->scopebb());
kamm@428 888 }
kamm@428 889 else {
kamm@428 890 if (!fd->isMain())
lindquist@244 891 llvm::ReturnInst::Create(llvm::UndefValue::get(func->getReturnType()), gIR->scopebb());
kamm@428 892 else
kamm@428 893 llvm::ReturnInst::Create(llvm::Constant::getNullValue(func->getReturnType()), gIR->scopebb());
lindquist@244 894 }
lindquist@244 895 }
lindquist@244 896
lindquist@244 897 // erase alloca point
lindquist@244 898 allocaPoint->eraseFromParent();
lindquist@244 899 allocaPoint = 0;
lindquist@244 900 gIR->func()->allocapoint = 0;
lindquist@244 901
lindquist@244 902 gIR->scopes.pop_back();
lindquist@244 903
lindquist@244 904 // get rid of the endentry block, it's never used
lindquist@244 905 assert(!func->getBasicBlockList().empty());
lindquist@244 906 func->getBasicBlockList().pop_back();
lindquist@244 907
lindquist@244 908 // if the last block is empty now, it must be unreachable or it's a bug somewhere else
lindquist@244 909 // would be nice to figure out how to assert that this is correct
lindquist@244 910 llvm::BasicBlock* lastbb = &func->getBasicBlockList().back();
lindquist@328 911 if (lastbb->empty())
lindquist@328 912 {
lindquist@262 913 new llvm::UnreachableInst(lastbb);
lindquist@244 914 }
lindquist@244 915
lindquist@244 916 // if the last block is not terminated we return a null value or void
lindquist@244 917 // for some unknown reason this is needed when a void main() has a inline asm block ...
lindquist@244 918 // this should be harmless for well formed code!
lindquist@244 919 lastbb = &func->getBasicBlockList().back();
lindquist@244 920 if (!lastbb->getTerminator())
lindquist@244 921 {
lindquist@244 922 Logger::println("adding missing return statement");
lindquist@244 923 if (func->getReturnType() == LLType::VoidTy)
lindquist@244 924 llvm::ReturnInst::Create(lastbb);
lindquist@244 925 else
lindquist@244 926 llvm::ReturnInst::Create(llvm::Constant::getNullValue(func->getReturnType()), lastbb);
lindquist@244 927 }
lindquist@244 928
lindquist@244 929 gIR->functions.pop_back();
lindquist@100 930 }
lindquist@100 931
lindquist@100 932 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@100 933
lindquist@117 934 const llvm::FunctionType* DtoBaseFunctionType(FuncDeclaration* fdecl)
lindquist@117 935 {
lindquist@117 936 Dsymbol* parent = fdecl->toParent();
lindquist@117 937 ClassDeclaration* cd = parent->isClassDeclaration();
lindquist@117 938 assert(cd);
lindquist@117 939
lindquist@117 940 FuncDeclaration* f = fdecl;
lindquist@117 941
lindquist@117 942 while (cd)
lindquist@117 943 {
lindquist@117 944 ClassDeclaration* base = cd->baseClass;
lindquist@117 945 if (!base)
lindquist@117 946 break;
lindquist@117 947 FuncDeclaration* f2 = base->findFunc(fdecl->ident, (TypeFunction*)fdecl->type);
lindquist@117 948 if (f2) {
lindquist@117 949 f = f2;
lindquist@117 950 cd = base;
lindquist@117 951 }
lindquist@117 952 else
lindquist@117 953 break;
lindquist@117 954 }
lindquist@117 955
lindquist@117 956 DtoResolveDsymbol(f);
lindquist@117 957 return llvm::cast<llvm::FunctionType>(DtoType(f->type));
lindquist@117 958 }
lindquist@117 959
lindquist@117 960 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@131 961
lindquist@131 962 DValue* DtoArgument(Argument* fnarg, Expression* argexp)
lindquist@131 963 {
lindquist@131 964 Logger::println("DtoArgument");
lindquist@131 965 LOG_SCOPE;
lindquist@131 966
lindquist@131 967 DValue* arg = argexp->toElem(gIR);
lindquist@131 968
lindquist@131 969 // ref/out arg
tomas@723 970 if (fnarg && (fnarg->storageClass & (STCref | STCout)))
lindquist@131 971 {
lindquist@131 972 if (arg->isVar() || arg->isLRValue())
tomas@486 973 arg = new DImValue(argexp->type, arg->getLVal());
lindquist@131 974 else
tomas@486 975 arg = new DImValue(argexp->type, arg->getRVal());
lindquist@131 976 }
tomas@719 977 // lazy arg
tomas@719 978 else if (fnarg && (fnarg->storageClass & STClazy))
tomas@719 979 {
tomas@719 980 assert(argexp->type->toBasetype()->ty == Tdelegate);
tomas@719 981 assert(!arg->isLVal());
tomas@719 982 return arg;
tomas@719 983 }
lindquist@217 984 // byval arg, but expr has no storage yet
tomas@585 985 else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isNull()))
lindquist@131 986 {
tomas@486 987 LLValue* alloc = DtoAlloca(DtoType(argexp->type), ".tmp_arg");
tomas@585 988 DVarValue* vv = new DVarValue(argexp->type, alloc);
kamm@399 989 DtoAssign(argexp->loc, vv, arg);
lindquist@131 990 arg = vv;
lindquist@131 991 }
lindquist@131 992
lindquist@131 993 return arg;
lindquist@131 994 }
lindquist@131 995
lindquist@131 996 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@131 997
lindquist@213 998 void DtoVariadicArgument(Expression* argexp, LLValue* dst)
lindquist@131 999 {
lindquist@131 1000 Logger::println("DtoVariadicArgument");
lindquist@131 1001 LOG_SCOPE;
tomas@585 1002 DVarValue vv(argexp->type, dst);
kamm@399 1003 DtoAssign(argexp->loc, &vv, argexp->toElem(gIR));
lindquist@131 1004 }
lindquist@131 1005
lindquist@131 1006 //////////////////////////////////////////////////////////////////////////////////////////
tomas@445 1007
tomas@445 1008 bool FuncDeclaration::isIntrinsic()
tomas@445 1009 {
tomas@445 1010 return (llvmInternal == LLVMintrinsic || isVaIntrinsic());
tomas@445 1011 }
tomas@445 1012
tomas@445 1013 bool FuncDeclaration::isVaIntrinsic()
tomas@445 1014 {
tomas@445 1015 return (llvmInternal == LLVMva_start ||
tomas@445 1016 llvmInternal == LLVMva_copy ||
tomas@445 1017 llvmInternal == LLVMva_end);
tomas@445 1018 }