Mercurial > projects > ldc
diff gen/tocall.cpp @ 723:55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Changed AA types to just a void* .
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Sat, 25 Oct 2008 06:03:28 +0200 |
parents | e177ae483f8e |
children | f04dde6e882c |
line wrap: on
line diff
--- a/gen/tocall.cpp Thu Oct 23 19:42:55 2008 +0200 +++ b/gen/tocall.cpp Sat Oct 25 06:03:28 2008 +0200 @@ -34,7 +34,7 @@ unsigned DtoCallingConv(LINK l) { - if (l == LINKc || l == LINKcpp) + if (l == LINKc || l == LINKcpp || l == LINKintrinsic) return llvm::CallingConv::C; else if (l == LINKd || l == LINKdefault) { @@ -111,7 +111,7 @@ ////////////////////////////////////////////////////////////////////////////////////////// -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"); @@ -195,7 +195,12 @@ args.push_back(argval->getRVal()); if (fnarg->llvmAttrs) - palist = palist.addAttr(argidx, fnarg->llvmAttrs); + { + llvm::AttributeWithIndex Attr; + Attr.Index = argidx; + Attr.Attrs = fnarg->llvmAttrs; + attrs.push_back(Attr); + } ++argidx; } @@ -234,6 +239,11 @@ const LLFunctionType* callableTy = DtoExtractFunctionType(callable->getType()); assert(callableTy); + if (Logger::enabled()) + { + Logger::cout() << "callable: " << *callable << '\n'; + } + // get n arguments size_t n_arguments = arguments ? arguments->dim : 0; @@ -242,11 +252,16 @@ LLFunctionType::param_iterator argiter = argbegin; // parameter attributes - llvm::AttrListPtr palist; + std::vector<llvm::AttributeWithIndex> attrs; + llvm::AttributeWithIndex Attr; // return attrs if (tf->retAttrs) - palist = palist.addAttr(0, tf->retAttrs); + { + Attr.Index = 0; + Attr.Attrs = tf->retAttrs; + attrs.push_back(Attr); + } // handle implicit arguments std::vector<LLValue*> args; @@ -259,7 +274,9 @@ args.push_back(retvar); // 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... @@ -304,7 +321,11 @@ // add attributes for context argument 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 @@ -326,33 +347,83 @@ // d style varargs needs a few more hidden arguments as well as special passing 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 + // or a C style vararg call else { 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); + assert(fnarg); DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); 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()) { Logger::cout() << "arg: " << *arg << '\n'; Logger::cout() << "expects: " << *callableTy->getParamType(j) << '\n'; } - if (arg->getType() != callableTy->getParamType(j)) - arg = DtoBitCast(arg, callableTy->getParamType(j)); - if (fnarg->llvmAttrs) - palist = palist.addAttr(j+1, fnarg->llvmAttrs); + #endif + arg = DtoBitCast(arg, callableTy->getParamType(j)); } + + // param attrs + attrptr[i] = fnarg->llvmAttrs; + ++argiter; 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 @@ -405,17 +476,18 @@ } // set calling convention and parameter attributes + llvm::AttrListPtr attrlist = llvm::AttrListPtr::get(attrs.begin(), attrs.end()); if (dfnval && dfnval->func) { LLFunction* llfunc = llvm::dyn_cast<LLFunction>(dfnval->val); - if (llfunc && llfunc->isIntrinsic()) - palist = llvm::Intrinsic::getAttributes((llvm::Intrinsic::ID)llfunc->getIntrinsicID()); + if (llfunc && llfunc->isIntrinsic()) // override intrinsic attrs + attrlist = llvm::Intrinsic::getAttributes((llvm::Intrinsic::ID)llfunc->getIntrinsicID()); else call->setCallingConv(callconv); } else call->setCallingConv(callconv); - call->setAttributes(palist); + call->setAttributes(attrlist); return new DImValue(resulttype, retllval); }