Mercurial > projects > ldc
changeset 720:e177ae483f8e
Added inreg attribute where appropriate on x86 to follow ABI docs.
Removed now unnecessary temporary variable in StringExp.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Thu, 23 Oct 2008 00:34:46 +0200 |
parents | 7261ff0f95ff |
children | 51797efb6975 |
files | dmd/mtype.c dmd/mtype.h gen/functions.cpp gen/tocall.cpp gen/toir.cpp |
diffstat | 5 files changed, 51 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/dmd/mtype.c Wed Oct 22 21:50:08 2008 +0200 +++ b/dmd/mtype.c Thu Oct 23 00:34:46 2008 +0200 @@ -2672,6 +2672,7 @@ this->usesThis = false; this->usesNest = false; this->retAttrs = 0; + this->thisAttrs = 0; } Type *TypeFunction::syntaxCopy() @@ -2683,6 +2684,7 @@ t->usesThis = usesThis; t->usesNest = usesNest; t->retAttrs = retAttrs; + t->thisAttrs = thisAttrs; return t; }
--- a/dmd/mtype.h Wed Oct 22 21:50:08 2008 +0200 +++ b/dmd/mtype.h Thu Oct 23 00:34:46 2008 +0200 @@ -439,6 +439,7 @@ bool usesThis; bool usesNest; unsigned retAttrs; + unsigned thisAttrs; // also used for nest }; struct TypeDelegate : Type
--- a/gen/functions.cpp Wed Oct 22 21:50:08 2008 +0200 +++ b/gen/functions.cpp Thu Oct 23 00:34:46 2008 +0200 @@ -171,6 +171,39 @@ bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs; llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); + // tell first param to be passed in a register if we can + // ONLY extern(D) functions ! + if ((n > 0 || usesthis || usesnest) && f->linkage == LINKd) + { + // FIXME: Only x86 right now ... + if (global.params.cpu == ARCHx86) + { + // pass first param in EAX if it fits, is not floating point and is not a 3 byte struct. + // FIXME: struct are not passed in EAX yet + + // if there is a implicit context parameter, pass it in EAX + if (usesthis || usesnest) + { + f->thisAttrs |= llvm::Attribute::InReg; + } + // otherwise check the first formal parameter + else + { + Argument* arg = Argument::getNth(f->parameters, 0); + Type* t = arg->type->toBasetype(); + + // 32bit ints, pointers, classes and static arrays are candidate for being passed in EAX + if ((arg->storageClass & STCin) && + ((t->isscalar() && !t->isfloating()) || t->ty == Tclass || t->ty == Tsarray) && + (t->size() <= PTRSIZE)) + { + arg->llvmAttrs |= llvm::Attribute::InReg; + } + } + } + } + + // done f->retInPtr = retinptr; f->usesThis = usesthis; f->usesNest = usesnest; @@ -350,6 +383,14 @@ attrs.push_back(PAWI); } + // set this/nest param attrs + if (f->thisAttrs) + { + PAWI.Index = f->retInPtr ? 2 : 1; + PAWI.Attrs = f->thisAttrs; + attrs.push_back(PAWI); + } + // set attrs on the rest of the arguments for (; llidx <= funcNumArgs && Argument::dim(f->parameters) > k; ++llidx,++k) {
--- a/gen/tocall.cpp Wed Oct 22 21:50:08 2008 +0200 +++ b/gen/tocall.cpp Thu Oct 23 00:34:46 2008 +0200 @@ -257,6 +257,8 @@ LLValue* retvar = DtoAlloca(argiter->get()->getContainedType(0), ".rettmp"); ++argiter; args.push_back(retvar); + + // add attrs for hidden ptr palist = palist.addAttr(1, llvm::Attribute::StructRet); } @@ -299,6 +301,10 @@ error(loc, "Context argument required but none given"); fatal(); } + + // add attributes for context argument + if (tf->thisAttrs) + palist = palist.addAttr(retinptr?2:1, tf->thisAttrs); } // handle the rest of the arguments based on param passing style
--- a/gen/toir.cpp Wed Oct 22 21:50:08 2008 +0200 +++ b/gen/toir.cpp Thu Oct 23 00:34:46 2008 +0200 @@ -373,9 +373,7 @@ if (dtype->ty == Tarray) { LLConstant* clen = llvm::ConstantInt::get(DtoSize_t(),len,false); - LLValue* tmpmem = DtoAlloca(DtoType(dtype),"tempstring"); - DtoSetArray(tmpmem, clen, arrptr); - return new DVarValue(type, tmpmem); + return new DImValue(type, DtoConstSlice(clen, arrptr)); } else if (dtype->ty == Tsarray) { const LLType* dstType = getPtrToType(LLArrayType::get(ct, len));