mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-02 16:11:08 +03:00
Implemented correct parameter order according to x86-32 ABI documentation.
Changed AA types to just a void* .
This commit is contained in:
parent
5ed0ab3ab8
commit
3c3a5dda14
10 changed files with 199 additions and 35 deletions
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -309,6 +309,9 @@ enum LINK
|
||||||
LINKcpp,
|
LINKcpp,
|
||||||
LINKwindows,
|
LINKwindows,
|
||||||
LINKpascal,
|
LINKpascal,
|
||||||
|
|
||||||
|
// LDC
|
||||||
|
LINKintrinsic,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DYNCAST
|
enum DYNCAST
|
||||||
|
|
16
dmd/mtype.c
16
dmd/mtype.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
|
|
108
gen/tocall.cpp
108
gen/tocall.cpp
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue