//===----- CGCall.h - Encapsulate calling convention details ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // These classes wrap the information about a call or function // definition used to handle ABI compliancy. // //===----------------------------------------------------------------------===// #include "CGCall.h" #include "CodeGenFunction.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "llvm/ParameterAttributes.h" using namespace clang; using namespace CodeGen; /***/ static void constructParamAttrListInternal(const Decl *TargetDecl, const llvm::SmallVector &ArgTypes, ParamAttrListType &PAL) { unsigned FuncAttrs = 0; if (TargetDecl) { if (TargetDecl->getAttr()) FuncAttrs |= llvm::ParamAttr::NoUnwind; if (TargetDecl->getAttr()) FuncAttrs |= llvm::ParamAttr::NoReturn; } unsigned Index = 1; if (CodeGenFunction::hasAggregateLLVMType(ArgTypes[0])) { PAL.push_back(llvm::ParamAttrsWithIndex::get(Index, llvm::ParamAttr::StructRet)); ++Index; } else if (ArgTypes[0]->isPromotableIntegerType()) { if (ArgTypes[0]->isSignedIntegerType()) { FuncAttrs |= llvm::ParamAttr::SExt; } else if (ArgTypes[0]->isUnsignedIntegerType()) { FuncAttrs |= llvm::ParamAttr::ZExt; } } if (FuncAttrs) PAL.push_back(llvm::ParamAttrsWithIndex::get(0, FuncAttrs)); for (llvm::SmallVector::const_iterator i = ArgTypes.begin() + 1, e = ArgTypes.end(); i != e; ++i, ++Index) { QualType ParamType = *i; unsigned ParamAttrs = 0; if (ParamType->isRecordType()) ParamAttrs |= llvm::ParamAttr::ByVal; if (ParamType->isPromotableIntegerType()) { if (ParamType->isSignedIntegerType()) { ParamAttrs |= llvm::ParamAttr::SExt; } else if (ParamType->isUnsignedIntegerType()) { ParamAttrs |= llvm::ParamAttr::ZExt; } } if (ParamAttrs) PAL.push_back(llvm::ParamAttrsWithIndex::get(Index, ParamAttrs)); } } /***/ // FIXME: Use iterator and sidestep silly type array creation. CGFunctionInfo::CGFunctionInfo(const FunctionDecl *FD) : TheDecl(FD) { const FunctionType *FTy = FD->getType()->getAsFunctionType(); const FunctionTypeProto *FTP = dyn_cast(FTy); ArgTypes.push_back(FTy->getResultType()); if (FTP) for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) ArgTypes.push_back(FTP->getArgType(i)); } CGFunctionInfo::CGFunctionInfo(const ObjCMethodDecl *MD, const ASTContext &Context) : TheDecl(MD) { ArgTypes.push_back(MD->getResultType()); ArgTypes.push_back(MD->getSelfDecl()->getType()); ArgTypes.push_back(Context.getObjCSelType()); for (ObjCMethodDecl::param_const_iterator i = MD->param_begin(), e = MD->param_end(); i != e; ++i) ArgTypes.push_back((*i)->getType()); } void CGFunctionInfo::constructParamAttrList(ParamAttrListType &PAL) const { constructParamAttrListInternal(TheDecl, ArgTypes, PAL); } /***/ CGCallInfo::CGCallInfo(QualType _ResultType, const CallArgList &_Args) : ResultType(_ResultType), Args(_Args) { ArgTypes.push_back(ResultType); for (CallArgList::const_iterator i = Args.begin(), e = Args.end(); i!=e; ++i) ArgTypes.push_back(i->second); } void CGCallInfo::constructParamAttrList(ParamAttrListType &PAL) const { // FIXME: Provide TargetDecl so nounwind, noreturn, etc, etc get set. constructParamAttrListInternal(0, ArgTypes, PAL); }