Implemented correct parameter order according to x86-32 ABI documentation.

Changed AA types to just a void* .
This commit is contained in:
Tomas Lindquist Olsen 2008-10-25 06:03:28 +02:00
parent 5ed0ab3ab8
commit 3c3a5dda14
10 changed files with 199 additions and 35 deletions

View file

@ -416,6 +416,10 @@ void LinkDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
case LINKcpp: p = "C++"; break; case LINKcpp: p = "C++"; break;
case LINKwindows: p = "Windows"; break; case LINKwindows: p = "Windows"; break;
case LINKpascal: p = "Pascal"; break; case LINKpascal: p = "Pascal"; break;
// LDC
case LINKintrinsic: p = "Intrinsic"; break;
default: default:
assert(0); assert(0);
break; break;
@ -1003,6 +1007,8 @@ void PragmaDeclaration::semantic(Scope *sc)
{ {
fd->llvmInternal = llvm_internal; fd->llvmInternal = llvm_internal;
fd->intrinsicName = arg1str; fd->intrinsicName = arg1str;
fd->linkage = LINKintrinsic;
((TypeFunction*)fd->type)->linkage = LINKintrinsic;
} }
else if (TemplateDeclaration* td = s->isTemplateDeclaration()) else if (TemplateDeclaration* td = s->isTemplateDeclaration())
{ {

View file

@ -684,12 +684,16 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
//arg->error("cannot modify slice %s", arg->toChars()); //arg->error("cannot modify slice %s", arg->toChars());
} }
// LDC we don't want this!
#if !IN_LLVM
// Convert static arrays to pointers // Convert static arrays to pointers
tb = arg->type->toBasetype(); tb = arg->type->toBasetype();
if (tb->ty == Tsarray) if (tb->ty == Tsarray)
{ {
arg = arg->checkToPointer(); arg = arg->checkToPointer();
} }
#endif
// Convert lazy argument to a delegate // Convert lazy argument to a delegate
if (p->storageClass & STClazy) if (p->storageClass & STClazy)
@ -701,7 +705,8 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
{ {
// If not D linkage, do promotions // If not D linkage, do promotions
if (tf->linkage != LINKd) // LDC: don't do promotions on intrinsics
if (tf->linkage != LINKd && tf->linkage != LINKintrinsic)
{ {
// Promote bytes, words, etc., to ints // Promote bytes, words, etc., to ints
arg = arg->integralPromotions(sc); arg = arg->integralPromotions(sc);

View file

@ -104,6 +104,9 @@ char *Declaration::mangle()
case LINKd: case LINKd:
break; break;
// LDC
case LINKintrinsic:
case LINKc: case LINKc:
case LINKwindows: case LINKwindows:
case LINKpascal: case LINKpascal:

View file

@ -309,6 +309,9 @@ enum LINK
LINKcpp, LINKcpp,
LINKwindows, LINKwindows,
LINKpascal, LINKpascal,
// LDC
LINKintrinsic,
}; };
enum DYNCAST enum DYNCAST

View file

@ -2673,6 +2673,8 @@ TypeFunction::TypeFunction(Arguments *parameters, Type *treturn, int varargs, en
this->usesNest = false; this->usesNest = false;
this->retAttrs = 0; this->retAttrs = 0;
this->thisAttrs = 0; this->thisAttrs = 0;
this->reverseParams = false;
this->reverseIndex = 0;
} }
Type *TypeFunction::syntaxCopy() Type *TypeFunction::syntaxCopy()
@ -2685,6 +2687,8 @@ Type *TypeFunction::syntaxCopy()
t->usesNest = usesNest; t->usesNest = usesNest;
t->retAttrs = retAttrs; t->retAttrs = retAttrs;
t->thisAttrs = thisAttrs; t->thisAttrs = thisAttrs;
t->reverseParams = reverseParams;
t->reverseIndex = reverseIndex;
return t; return t;
} }
@ -2794,6 +2798,10 @@ void TypeFunction::toDecoBuffer(OutBuffer *buf)
case LINKwindows: mc = 'W'; break; case LINKwindows: mc = 'W'; break;
case LINKpascal: mc = 'V'; break; case LINKpascal: mc = 'V'; break;
case LINKcpp: mc = 'R'; break; case LINKcpp: mc = 'R'; break;
// LDC
case LINKintrinsic: mc = 'Q'; break;
default: default:
assert(0); assert(0);
} }
@ -2826,6 +2834,10 @@ void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs
case LINKwindows: p = "Windows "; break; case LINKwindows: p = "Windows "; break;
case LINKpascal: p = "Pascal "; break; case LINKpascal: p = "Pascal "; break;
case LINKcpp: p = "C++ "; break; case LINKcpp: p = "C++ "; break;
// LDC
case LINKintrinsic: p = "Intrinsic"; break;
default: default:
assert(0); assert(0);
} }
@ -2861,6 +2873,10 @@ void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
case LINKwindows: p = "Windows "; break; case LINKwindows: p = "Windows "; break;
case LINKpascal: p = "Pascal "; break; case LINKpascal: p = "Pascal "; break;
case LINKcpp: p = "C++ "; break; case LINKcpp: p = "C++ "; break;
// LDC
case LINKintrinsic: p = "Intrinsic"; break;
default: default:
assert(0); assert(0);
} }

View file

@ -440,6 +440,9 @@ struct TypeFunction : Type
bool usesNest; bool usesNest;
unsigned retAttrs; unsigned retAttrs;
unsigned thisAttrs; // also used for nest unsigned thisAttrs; // also used for nest
bool reverseParams;
size_t reverseIndex;
}; };
struct TypeDelegate : Type struct TypeDelegate : Type

View file

@ -21,6 +21,8 @@
#include "gen/classes.h" #include "gen/classes.h"
#include "gen/dvalue.h" #include "gen/dvalue.h"
#include <algorithm>
const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, const LLType* nesttype, bool ismain) const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, const LLType* nesttype, bool ismain)
{ {
assert(type->ty == Tfunction); assert(type->ty == Tfunction);
@ -111,8 +113,23 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
// do nothing? // do nothing?
} }
// number of formal params
size_t n = Argument::dim(f->parameters); size_t n = Argument::dim(f->parameters);
// on x86 we need to reverse the formal params in some cases to match the ABI
if (global.params.cpu == ARCHx86)
{
// more than one formal arg,
// extern(D) linkage
// not a D-style vararg
if (n > 1 && f->linkage == LINKd && !typesafeVararg)
{
f->reverseParams = true;
f->reverseIndex = paramvec.size();
}
}
for (int i=0; i < n; ++i) { for (int i=0; i < n; ++i) {
Argument* arg = Argument::getNth(f->parameters, i); Argument* arg = Argument::getNth(f->parameters, i);
// ensure scalar // ensure scalar
@ -167,6 +184,12 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
} }
} }
// reverse params?
if (f->reverseParams)
{
std::reverse(paramvec.begin() + f->reverseIndex, paramvec.end());
}
// construct function type // construct function type
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);
@ -189,6 +212,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
// otherwise check the first formal parameter // otherwise check the first formal parameter
else else
{ {
int inreg = f->reverseParams ? n - 1 : 0;
Argument* arg = Argument::getNth(f->parameters, 0); Argument* arg = Argument::getNth(f->parameters, 0);
Type* t = arg->type->toBasetype(); Type* t = arg->type->toBasetype();
@ -340,6 +364,8 @@ void DtoResolveFunction(FuncDeclaration* fdecl)
Logger::println("overloaded intrinsic found"); Logger::println("overloaded intrinsic found");
fdecl->llvmInternal = LLVMintrinsic; fdecl->llvmInternal = LLVMintrinsic;
DtoOverloadedIntrinsicName(tinst, tempdecl, fdecl->intrinsicName); DtoOverloadedIntrinsicName(tinst, tempdecl, fdecl->intrinsicName);
fdecl->linkage = LINKintrinsic;
((TypeFunction*)fdecl->type)->linkage = LINKintrinsic;
} }
} }
@ -354,7 +380,7 @@ void DtoResolveFunction(FuncDeclaration* fdecl)
static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclaration* fdecl) static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclaration* fdecl)
{ {
int llidx = 1; int llidx = 0;
if (f->retInPtr) ++llidx; if (f->retInPtr) ++llidx;
if (f->usesThis) ++llidx; if (f->usesThis) ++llidx;
else if (f->usesNest) ++llidx; else if (f->usesNest) ++llidx;
@ -362,9 +388,8 @@ static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclarati
llidx += 2; llidx += 2;
int funcNumArgs = func->getArgumentList().size(); int funcNumArgs = func->getArgumentList().size();
std::vector<llvm::AttributeWithIndex> attrs;
int k = 0;
LLSmallVector<llvm::AttributeWithIndex, 9> attrs;
llvm::AttributeWithIndex PAWI; llvm::AttributeWithIndex PAWI;
// set return value attrs if any // set return value attrs if any
@ -392,20 +417,38 @@ static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclarati
} }
// 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) size_t n = Argument::dim(f->parameters);
assert(funcNumArgs >= n); // main might mismatch, for the implicit char[][] arg
LLSmallVector<unsigned,8> attrptr(n, 0);
for (size_t k = 0; k < n; ++k)
{ {
Argument* fnarg = Argument::getNth(f->parameters, k); Argument* fnarg = Argument::getNth(f->parameters, k);
assert(fnarg); assert(fnarg);
PAWI.Index = llidx; attrptr[k] = fnarg->llvmAttrs;
PAWI.Attrs = fnarg->llvmAttrs;
if (PAWI.Attrs)
attrs.push_back(PAWI);
} }
llvm::AttrListPtr palist = llvm::AttrListPtr::get(attrs.begin(), attrs.end()); // reverse params?
func->setAttributes(palist); if (f->reverseParams)
{
std::reverse(attrptr.begin(), attrptr.end());
}
// build rest of attrs list
for (int i = 0; i < n; i++)
{
if (attrptr[i])
{
PAWI.Index = llidx+i+1;
PAWI.Attrs = attrptr[i];
attrs.push_back(PAWI);
}
}
llvm::AttrListPtr attrlist = llvm::AttrListPtr::get(attrs.begin(), attrs.end());
func->setAttributes(attrlist);
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -503,13 +546,13 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
{ {
// name parameters // name parameters
llvm::Function::arg_iterator iarg = func->arg_begin(); llvm::Function::arg_iterator iarg = func->arg_begin();
int k = 0;
if (f->retInPtr) { if (f->retInPtr) {
iarg->setName(".sretarg"); iarg->setName(".sretarg");
fdecl->ir.irFunc->retArg = iarg; fdecl->ir.irFunc->retArg = iarg;
++iarg; ++iarg;
} }
if (f->usesThis) { if (f->usesThis) {
iarg->setName("this"); iarg->setName("this");
fdecl->ir.irFunc->thisArg = iarg; fdecl->ir.irFunc->thisArg = iarg;
@ -532,17 +575,26 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
++iarg; ++iarg;
} }
int k = 0;
for (; iarg != func->arg_end(); ++iarg) for (; iarg != func->arg_end(); ++iarg)
{ {
if (fdecl->parameters && fdecl->parameters->dim > k) if (fdecl->parameters && fdecl->parameters->dim > k)
{ {
Dsymbol* argsym = (Dsymbol*)fdecl->parameters->data[k++]; Dsymbol* argsym;
if (f->reverseParams)
argsym = (Dsymbol*)fdecl->parameters->data[fdecl->parameters->dim-k-1];
else
argsym = (Dsymbol*)fdecl->parameters->data[k];
VarDeclaration* argvd = argsym->isVarDeclaration(); VarDeclaration* argvd = argsym->isVarDeclaration();
assert(argvd); assert(argvd);
assert(!argvd->ir.irLocal); assert(!argvd->ir.irLocal);
argvd->ir.irLocal = new IrLocal(argvd); argvd->ir.irLocal = new IrLocal(argvd);
argvd->ir.irLocal->value = iarg; argvd->ir.irLocal->value = iarg;
iarg->setName(argvd->ident->toChars()); iarg->setName(argvd->ident->toChars());
k++;
} }
else else
{ {
@ -902,7 +954,7 @@ DValue* DtoArgument(Argument* fnarg, Expression* argexp)
DValue* arg = argexp->toElem(gIR); DValue* arg = argexp->toElem(gIR);
// ref/out arg // ref/out arg
if (fnarg && ((fnarg->storageClass & STCref) || (fnarg->storageClass & STCout))) if (fnarg && (fnarg->storageClass & (STCref | STCout)))
{ {
if (arg->isVar() || arg->isLRValue()) if (arg->isVar() || arg->isLRValue())
arg = new DImValue(argexp->type, arg->getLVal()); arg = new DImValue(argexp->type, arg->getLVal());

View file

@ -34,7 +34,7 @@ TypeFunction* DtoTypeFunction(DValue* fnval)
unsigned DtoCallingConv(LINK l) unsigned DtoCallingConv(LINK l)
{ {
if (l == LINKc || l == LINKcpp) if (l == LINKc || l == LINKcpp || l == LINKintrinsic)
return llvm::CallingConv::C; return llvm::CallingConv::C;
else if (l == LINKd || l == LINKdefault) else if (l == LINKd || l == LINKdefault)
{ {
@ -111,7 +111,7 @@ const LLFunctionType* DtoExtractFunctionType(const LLType* type)
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
void DtoBuildDVarArgList(std::vector<LLValue*>& args, llvm::AttrListPtr& palist, TypeFunction* tf, Expressions* arguments, size_t argidx) void DtoBuildDVarArgList(std::vector<LLValue*>& args, std::vector<llvm::AttributeWithIndex>& attrs, TypeFunction* tf, Expressions* arguments, size_t argidx)
{ {
Logger::println("doing d-style variadic arguments"); Logger::println("doing d-style variadic arguments");
@ -195,7 +195,12 @@ void DtoBuildDVarArgList(std::vector<LLValue*>& args, llvm::AttrListPtr& palist,
args.push_back(argval->getRVal()); args.push_back(argval->getRVal());
if (fnarg->llvmAttrs) if (fnarg->llvmAttrs)
palist = palist.addAttr(argidx, fnarg->llvmAttrs); {
llvm::AttributeWithIndex Attr;
Attr.Index = argidx;
Attr.Attrs = fnarg->llvmAttrs;
attrs.push_back(Attr);
}
++argidx; ++argidx;
} }
@ -234,6 +239,11 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
const LLFunctionType* callableTy = DtoExtractFunctionType(callable->getType()); const LLFunctionType* callableTy = DtoExtractFunctionType(callable->getType());
assert(callableTy); assert(callableTy);
if (Logger::enabled())
{
Logger::cout() << "callable: " << *callable << '\n';
}
// get n arguments // get n arguments
size_t n_arguments = arguments ? arguments->dim : 0; size_t n_arguments = arguments ? arguments->dim : 0;
@ -242,11 +252,16 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
LLFunctionType::param_iterator argiter = argbegin; LLFunctionType::param_iterator argiter = argbegin;
// parameter attributes // parameter attributes
llvm::AttrListPtr palist; std::vector<llvm::AttributeWithIndex> attrs;
llvm::AttributeWithIndex Attr;
// return attrs // return attrs
if (tf->retAttrs) if (tf->retAttrs)
palist = palist.addAttr(0, tf->retAttrs); {
Attr.Index = 0;
Attr.Attrs = tf->retAttrs;
attrs.push_back(Attr);
}
// handle implicit arguments // handle implicit arguments
std::vector<LLValue*> args; std::vector<LLValue*> args;
@ -259,7 +274,9 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
args.push_back(retvar); args.push_back(retvar);
// add attrs for hidden ptr // add attrs for hidden ptr
palist = palist.addAttr(1, llvm::Attribute::StructRet); Attr.Index = 1;
Attr.Attrs = llvm::Attribute::StructRet;
attrs.push_back(Attr);
} }
// then comes a context argument... // then comes a context argument...
@ -304,7 +321,11 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
// add attributes for context argument // add attributes for context argument
if (tf->thisAttrs) if (tf->thisAttrs)
palist = palist.addAttr(retinptr?2:1, tf->thisAttrs); {
Attr.Index = retinptr ? 2 : 1;
Attr.Attrs = tf->thisAttrs;
attrs.push_back(Attr);
}
} }
// handle the rest of the arguments based on param passing style // handle the rest of the arguments based on param passing style
@ -326,33 +347,83 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
// d style varargs needs a few more hidden arguments as well as special passing // d style varargs needs a few more hidden arguments as well as special passing
else if (dvarargs) else if (dvarargs)
{ {
DtoBuildDVarArgList(args, palist, tf, arguments, argiter-argbegin+1); DtoBuildDVarArgList(args, attrs, tf, arguments, argiter-argbegin+1);
} }
// otherwise we're looking at a normal function call // otherwise we're looking at a normal function call
// or a C style vararg call
else else
{ {
Logger::println("doing normal arguments"); Logger::println("doing normal arguments");
for (int i=0; i<n_arguments; i++) {
int j = argiter-argbegin; size_t n = Argument::dim(tf->parameters);
LLSmallVector<unsigned, 10> attrptr(n, 0);
// do formal params
int beg = argiter-argbegin;
for (int i=0; i<n; i++)
{
Argument* fnarg = Argument::getNth(tf->parameters, i); Argument* fnarg = Argument::getNth(tf->parameters, i);
assert(fnarg);
DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
LLValue* arg = argval->getRVal(); LLValue* arg = argval->getRVal();
if (fnarg) // can fnarg ever be null in this block?
int j = tf->reverseParams ? beg + n - i - 1 : beg + i;
// parameter type mismatch, this is hard to get rid of
if (arg->getType() != callableTy->getParamType(j))
{ {
#if 0
if (Logger::enabled()) if (Logger::enabled())
{ {
Logger::cout() << "arg: " << *arg << '\n'; Logger::cout() << "arg: " << *arg << '\n';
Logger::cout() << "expects: " << *callableTy->getParamType(j) << '\n'; Logger::cout() << "expects: " << *callableTy->getParamType(j) << '\n';
} }
if (arg->getType() != callableTy->getParamType(j)) #endif
arg = DtoBitCast(arg, callableTy->getParamType(j)); arg = DtoBitCast(arg, callableTy->getParamType(j));
if (fnarg->llvmAttrs)
palist = palist.addAttr(j+1, fnarg->llvmAttrs);
} }
// param attrs
attrptr[i] = fnarg->llvmAttrs;
++argiter; ++argiter;
args.push_back(arg); args.push_back(arg);
} }
// reverse the relevant params as well as the param attrs
if (tf->reverseParams)
{
std::reverse(args.begin() + tf->reverseIndex, args.end());
std::reverse(attrptr.begin(), attrptr.end());
}
// add attributes
for (int i = 0; i < n; i++)
{
if (attrptr[i])
{
Attr.Index = beg + i + 1;
Attr.Attrs = attrptr[i];
attrs.push_back(Attr);
}
}
// do C varargs
if (n_arguments > n)
{
for (int i=n; i<n_arguments; i++)
{
Argument* fnarg = Argument::getNth(tf->parameters, i);
DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
LLValue* arg = argval->getRVal();
// FIXME: do we need any param attrs here ?
++argiter;
args.push_back(arg);
}
}
} }
#if 0 #if 0
@ -405,17 +476,18 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
} }
// set calling convention and parameter attributes // set calling convention and parameter attributes
llvm::AttrListPtr attrlist = llvm::AttrListPtr::get(attrs.begin(), attrs.end());
if (dfnval && dfnval->func) if (dfnval && dfnval->func)
{ {
LLFunction* llfunc = llvm::dyn_cast<LLFunction>(dfnval->val); LLFunction* llfunc = llvm::dyn_cast<LLFunction>(dfnval->val);
if (llfunc && llfunc->isIntrinsic()) if (llfunc && llfunc->isIntrinsic()) // override intrinsic attrs
palist = llvm::Intrinsic::getAttributes((llvm::Intrinsic::ID)llfunc->getIntrinsicID()); attrlist = llvm::Intrinsic::getAttributes((llvm::Intrinsic::ID)llfunc->getIntrinsicID());
else else
call->setCallingConv(callconv); call->setCallingConv(callconv);
} }
else else
call->setCallingConv(callconv); call->setCallingConv(callconv);
call->setAttributes(palist); call->setAttributes(attrlist);
return new DImValue(resulttype, retllval); return new DImValue(resulttype, retllval);
} }

View file

@ -163,11 +163,15 @@ const LLType* DtoType(Type* t)
// associative arrays // associative arrays
case Taarray: case Taarray:
#if 1
return getVoidPtrType();
#else
{ {
TypeAArray* taa = (TypeAArray*)t; TypeAArray* taa = (TypeAArray*)t;
// aa key/val can't be void // aa key/val can't be void
return getPtrToType(LLStructType::get(DtoType(taa->key), DtoType(taa->next), 0)); return getPtrToType(LLStructType::get(DtoType(taa->key), DtoType(taa->next), 0));
} }
#endif
/* /*
Not needed atm as VarDecls for tuples are rewritten as a string of Not needed atm as VarDecls for tuples are rewritten as a string of

View file

@ -21,7 +21,7 @@ void main()
real r; real r;
printf("Enter real: "); printf("Enter real: ");
//scanf("%lf", &d); //scanf("%llf", &r);
r = 3.2311167891231231234754764576; r = 3.2311167891231231234754764576;
version(X86) version(X86)
{ {