mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-10 12:59:21 +03:00
Added inreg attribute where appropriate on x86 to follow ABI docs.
Removed now unnecessary temporary variable in StringExp.
This commit is contained in:
parent
a52f0330d0
commit
f71b7ac284
5 changed files with 51 additions and 3 deletions
|
@ -2672,6 +2672,7 @@ TypeFunction::TypeFunction(Arguments *parameters, Type *treturn, int varargs, en
|
||||||
this->usesThis = false;
|
this->usesThis = false;
|
||||||
this->usesNest = false;
|
this->usesNest = false;
|
||||||
this->retAttrs = 0;
|
this->retAttrs = 0;
|
||||||
|
this->thisAttrs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *TypeFunction::syntaxCopy()
|
Type *TypeFunction::syntaxCopy()
|
||||||
|
@ -2683,6 +2684,7 @@ Type *TypeFunction::syntaxCopy()
|
||||||
t->usesThis = usesThis;
|
t->usesThis = usesThis;
|
||||||
t->usesNest = usesNest;
|
t->usesNest = usesNest;
|
||||||
t->retAttrs = retAttrs;
|
t->retAttrs = retAttrs;
|
||||||
|
t->thisAttrs = thisAttrs;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -439,6 +439,7 @@ struct TypeFunction : Type
|
||||||
bool usesThis;
|
bool usesThis;
|
||||||
bool usesNest;
|
bool usesNest;
|
||||||
unsigned retAttrs;
|
unsigned retAttrs;
|
||||||
|
unsigned thisAttrs; // also used for nest
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TypeDelegate : Type
|
struct TypeDelegate : Type
|
||||||
|
|
|
@ -171,6 +171,39 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
|
||||||
bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs;
|
bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs;
|
||||||
llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
|
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->retInPtr = retinptr;
|
||||||
f->usesThis = usesthis;
|
f->usesThis = usesthis;
|
||||||
f->usesNest = usesnest;
|
f->usesNest = usesnest;
|
||||||
|
@ -350,6 +383,14 @@ static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclarati
|
||||||
attrs.push_back(PAWI);
|
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
|
// set attrs on the rest of the arguments
|
||||||
for (; llidx <= funcNumArgs && Argument::dim(f->parameters) > k; ++llidx,++k)
|
for (; llidx <= funcNumArgs && Argument::dim(f->parameters) > k; ++llidx,++k)
|
||||||
{
|
{
|
||||||
|
|
|
@ -257,6 +257,8 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
||||||
LLValue* retvar = DtoAlloca(argiter->get()->getContainedType(0), ".rettmp");
|
LLValue* retvar = DtoAlloca(argiter->get()->getContainedType(0), ".rettmp");
|
||||||
++argiter;
|
++argiter;
|
||||||
args.push_back(retvar);
|
args.push_back(retvar);
|
||||||
|
|
||||||
|
// add attrs for hidden ptr
|
||||||
palist = palist.addAttr(1, llvm::Attribute::StructRet);
|
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");
|
error(loc, "Context argument required but none given");
|
||||||
fatal();
|
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
|
// handle the rest of the arguments based on param passing style
|
||||||
|
|
|
@ -373,9 +373,7 @@ DValue* StringExp::toElem(IRState* p)
|
||||||
|
|
||||||
if (dtype->ty == Tarray) {
|
if (dtype->ty == Tarray) {
|
||||||
LLConstant* clen = llvm::ConstantInt::get(DtoSize_t(),len,false);
|
LLConstant* clen = llvm::ConstantInt::get(DtoSize_t(),len,false);
|
||||||
LLValue* tmpmem = DtoAlloca(DtoType(dtype),"tempstring");
|
return new DImValue(type, DtoConstSlice(clen, arrptr));
|
||||||
DtoSetArray(tmpmem, clen, arrptr);
|
|
||||||
return new DVarValue(type, tmpmem);
|
|
||||||
}
|
}
|
||||||
else if (dtype->ty == Tsarray) {
|
else if (dtype->ty == Tsarray) {
|
||||||
const LLType* dstType = getPtrToType(LLArrayType::get(ct, len));
|
const LLType* dstType = getPtrToType(LLArrayType::get(ct, len));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue