Added inreg attribute where appropriate on x86 to follow ABI docs.

Removed now unnecessary temporary variable in StringExp.
This commit is contained in:
Tomas Lindquist Olsen 2008-10-23 00:34:46 +02:00
parent a52f0330d0
commit f71b7ac284
5 changed files with 51 additions and 3 deletions

View file

@ -2672,6 +2672,7 @@ TypeFunction::TypeFunction(Arguments *parameters, Type *treturn, int varargs, en
this->usesThis = false;
this->usesNest = false;
this->retAttrs = 0;
this->thisAttrs = 0;
}
Type *TypeFunction::syntaxCopy()
@ -2683,6 +2684,7 @@ Type *TypeFunction::syntaxCopy()
t->usesThis = usesThis;
t->usesNest = usesNest;
t->retAttrs = retAttrs;
t->thisAttrs = thisAttrs;
return t;
}

View file

@ -439,6 +439,7 @@ struct TypeFunction : Type
bool usesThis;
bool usesNest;
unsigned retAttrs;
unsigned thisAttrs; // also used for nest
};
struct TypeDelegate : Type

View file

@ -171,6 +171,39 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
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 @@ static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclarati
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)
{

View file

@ -257,6 +257,8 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
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 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
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

View file

@ -373,9 +373,7 @@ DValue* StringExp::toElem(IRState* p)
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));