Fix argument types of dvariadic functions

This commit is contained in:
Alexey Prokhin
2011-02-25 22:28:59 +03:00
parent 12984d9cc7
commit 5fb97f3d3f

View File

@@ -120,7 +120,60 @@ const LLFunctionType* DtoExtractFunctionType(const LLType* type)
//////////////////////////////////////////////////////////////////////////////////////////
void DtoBuildDVarArgList(std::vector<LLValue*>& args, std::vector<llvm::AttributeWithIndex>& attrs, TypeFunction* tf, Expressions* arguments, size_t argidx)
static LLValue *fixArgument(DValue *argval, TypeFunction* tf, const LLType *callableArgType, int argIndex)
{
#if 0
if (Logger::enabled()) {
Logger::cout() << "Argument before ABI: " << *argval->getRVal() << '\n';
Logger::cout() << "Argument type before ABI: " << *DtoType(argval->getType()) << '\n';
}
#endif
// give the ABI a say
LLValue* arg = tf->fty.putParam(argval->getType(), argIndex, argval);
#if 0
if (Logger::enabled()) {
Logger::cout() << "Argument after ABI: " << *arg << '\n';
Logger::cout() << "Argument type after ABI: " << *arg->getType() << '\n';
}
#endif
// Hack around LDC assuming structs are in memory:
// If the function wants a struct, and the argument value is a
// pointer to a struct, load from it before passing it in.
if (argval->getType()->ty == Tstruct
&& isaPointer(arg) && !isaPointer(callableArgType)) {
Logger::println("Loading struct type for function argument");
arg = DtoLoad(arg);
}
// parameter type mismatch, this is hard to get rid of
if (arg->getType() != callableArgType)
{
#if 1
if (Logger::enabled())
{
Logger::cout() << "arg: " << *arg << '\n';
Logger::cout() << "of type: " << *arg->getType() << '\n';
Logger::cout() << "expects: " << *callableArgType << '\n';
}
#endif
if (isaStruct(arg))
arg = DtoAggrPaint(arg, callableArgType);
else
arg = DtoBitCast(arg, callableArgType);
}
return arg;
}
//////////////////////////////////////////////////////////////////////////////////////////
void DtoBuildDVarArgList(std::vector<LLValue*>& args,
std::vector<llvm::AttributeWithIndex>& attrs,
TypeFunction* tf, Expressions* arguments,
size_t argidx,
const LLFunctionType* callableTy)
{
Logger::println("doing d-style variadic arguments");
LOG_SCOPE
@@ -227,14 +280,13 @@ void DtoBuildDVarArgList(std::vector<LLValue*>& args, std::vector<llvm::Attribut
Attr.Attrs = atts;
attrs.push_back(Attr);
}
++argidx;
// pass non variadic args
for (int i=0; i<begin; i++)
{
Parameter* fnarg = Parameter::getNth(tf->parameters, i);
DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
args.push_back(argval->getRVal());
args.push_back(fixArgument(argval, tf, callableTy->getParamType(argidx++), i));
if (tf->fty.args[i]->attrs)
{
@@ -243,11 +295,11 @@ void DtoBuildDVarArgList(std::vector<LLValue*>& args, std::vector<llvm::Attribut
Attr.Attrs = tf->fty.args[i]->attrs;
attrs.push_back(Attr);
}
++argidx;
}
}
//////////////////////////////////////////////////////////////////////////////////////////
// FIXME: this function is a mess !
DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* arguments)
@@ -405,7 +457,7 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
// d style varargs needs a few more hidden arguments as well as special passing
else if (dvarargs)
{
DtoBuildDVarArgList(args, attrs, tf, arguments, argiter-argbegin+1);
DtoBuildDVarArgList(args, attrs, tf, arguments, argiter-argbegin+1, callableTy);
}
// otherwise we're looking at a normal function call
@@ -452,56 +504,12 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
{
DValue* argval = argvals.at(i);
#if 0
if (Logger::enabled()) {
Logger::cout() << "Argument before ABI: " << *argval->getRVal() << '\n';
Logger::cout() << "Argument type before ABI: " << *DtoType(argval->getType()) << '\n';
}
#endif
// give the ABI a say
LLValue* arg = tf->fty.putParam(argval->getType(), i, argval);
#if 0
if (Logger::enabled()) {
Logger::cout() << "Argument after ABI: " << *arg << '\n';
Logger::cout() << "Argument type after ABI: " << *arg->getType() << '\n';
}
#endif
int j = tf->fty.reverseParams ? beg + n - i - 1 : beg + i;
// Hack around LDC assuming structs are in memory:
// If the function wants a struct, and the argument value is a
// pointer to a struct, load from it before passing it in.
if (argval->getType()->ty == Tstruct
&& isaPointer(arg) && !isaPointer(callableTy->getParamType(j))) {
Logger::println("Loading struct type for function argument");
arg = DtoLoad(arg);
}
// parameter type mismatch, this is hard to get rid of
if (arg->getType() != callableTy->getParamType(j))
{
#if 1
if (Logger::enabled())
{
Logger::cout() << "arg: " << *arg << '\n';
Logger::cout() << "of type: " << *arg->getType() << '\n';
Logger::cout() << "expects: " << *callableTy->getParamType(j) << '\n';
}
#endif
if (isaStruct(arg))
arg = DtoAggrPaint(arg, callableTy->getParamType(j));
else
arg = DtoBitCast(arg, callableTy->getParamType(j));
}
// param attrs
attrptr[i] = tf->fty.args[i]->attrs;
++argiter;
LLValue *arg = fixArgument(argval, tf, callableTy->getParamType(j), i);
args.push_back(arg);
attrptr[i] = tf->fty.args[i]->attrs;
++argiter;
}
// reverse the relevant params as well as the param attrs