From 5fb97f3d3f19bde87a9a8d616c948d509c07c297 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Fri, 25 Feb 2011 22:28:59 +0300 Subject: [PATCH] Fix argument types of dvariadic functions --- gen/tocall.cpp | 116 ++++++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 54 deletions(-) diff --git a/gen/tocall.cpp b/gen/tocall.cpp index fcc9f7a9..2205b3a9 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -120,7 +120,60 @@ const LLFunctionType* DtoExtractFunctionType(const LLType* type) ////////////////////////////////////////////////////////////////////////////////////////// -void DtoBuildDVarArgList(std::vector& args, std::vector& 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& args, + std::vector& 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& args, std::vectorparameters, 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& args, std::vectorfty.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