CGCall.cpp revision 3913f184c84135fb4612743f1faa6c1edd2dd055
1//===----- CGCall.h - Encapsulate calling convention details ----*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// These classes wrap the information about a call or function 11// definition used to handle ABI compliancy. 12// 13//===----------------------------------------------------------------------===// 14 15#include "CGCall.h" 16#include "CodeGenFunction.h" 17#include "clang/AST/ASTContext.h" 18#include "clang/AST/Decl.h" 19#include "clang/AST/DeclObjC.h" 20#include "llvm/ParameterAttributes.h" 21using namespace clang; 22using namespace CodeGen; 23 24/***/ 25 26static void 27constructParamAttrListInternal(const Decl *TargetDecl, 28 const llvm::SmallVector<QualType, 16> &ArgTypes, 29 ParamAttrListType &PAL) { 30 unsigned FuncAttrs = 0; 31 32 if (TargetDecl) { 33 if (TargetDecl->getAttr<NoThrowAttr>()) 34 FuncAttrs |= llvm::ParamAttr::NoUnwind; 35 if (TargetDecl->getAttr<NoReturnAttr>()) 36 FuncAttrs |= llvm::ParamAttr::NoReturn; 37 } 38 39 unsigned Index = 1; 40 if (CodeGenFunction::hasAggregateLLVMType(ArgTypes[0])) { 41 PAL.push_back(llvm::ParamAttrsWithIndex::get(Index, 42 llvm::ParamAttr::StructRet)); 43 ++Index; 44 } else if (ArgTypes[0]->isPromotableIntegerType()) { 45 if (ArgTypes[0]->isSignedIntegerType()) { 46 FuncAttrs |= llvm::ParamAttr::SExt; 47 } else if (ArgTypes[0]->isUnsignedIntegerType()) { 48 FuncAttrs |= llvm::ParamAttr::ZExt; 49 } 50 } 51 if (FuncAttrs) 52 PAL.push_back(llvm::ParamAttrsWithIndex::get(0, FuncAttrs)); 53 for (llvm::SmallVector<QualType, 8>::const_iterator i = ArgTypes.begin() + 1, 54 e = ArgTypes.end(); i != e; ++i, ++Index) { 55 QualType ParamType = *i; 56 unsigned ParamAttrs = 0; 57 if (ParamType->isRecordType()) 58 ParamAttrs |= llvm::ParamAttr::ByVal; 59 if (ParamType->isPromotableIntegerType()) { 60 if (ParamType->isSignedIntegerType()) { 61 ParamAttrs |= llvm::ParamAttr::SExt; 62 } else if (ParamType->isUnsignedIntegerType()) { 63 ParamAttrs |= llvm::ParamAttr::ZExt; 64 } 65 } 66 if (ParamAttrs) 67 PAL.push_back(llvm::ParamAttrsWithIndex::get(Index, ParamAttrs)); 68 } 69} 70 71/***/ 72 73// FIXME: Use iterator and sidestep silly type array creation. 74 75CGFunctionInfo::CGFunctionInfo(const FunctionDecl *FD) 76 : TheDecl(FD) 77{ 78 const FunctionType *FTy = FD->getType()->getAsFunctionType(); 79 const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FTy); 80 81 ArgTypes.push_back(FTy->getResultType()); 82 if (FTP) 83 for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) 84 ArgTypes.push_back(FTP->getArgType(i)); 85} 86 87CGFunctionInfo::CGFunctionInfo(const ObjCMethodDecl *MD, 88 const ASTContext &Context) 89 : TheDecl(MD) 90{ 91 ArgTypes.push_back(MD->getResultType()); 92 ArgTypes.push_back(MD->getSelfDecl()->getType()); 93 ArgTypes.push_back(Context.getObjCSelType()); 94 for (ObjCMethodDecl::param_const_iterator i = MD->param_begin(), 95 e = MD->param_end(); i != e; ++i) 96 ArgTypes.push_back((*i)->getType()); 97} 98 99void CGFunctionInfo::constructParamAttrList(ParamAttrListType &PAL) const { 100 constructParamAttrListInternal(TheDecl, ArgTypes, PAL); 101} 102 103/***/ 104 105CGCallInfo::CGCallInfo(QualType _ResultType, const CallArgList &_Args) 106 : ResultType(_ResultType), 107 Args(_Args) { 108 ArgTypes.push_back(ResultType); 109 for (CallArgList::const_iterator i = Args.begin(), e = Args.end(); i!=e; ++i) 110 ArgTypes.push_back(i->second); 111} 112 113void CGCallInfo::constructParamAttrList(ParamAttrListType &PAL) const { 114 // FIXME: Provide TargetDecl so nounwind, noreturn, etc, etc get set. 115 constructParamAttrListInternal(0, ArgTypes, PAL); 116} 117 118/***/ 119 120bool CodeGenFunction::ReturnTypeUsesSret(QualType RetTy) { 121 return hasAggregateLLVMType(RetTy); 122} 123 124void CodeGenFunction::EmitFunctionProlog(llvm::Function *Fn, 125 QualType RetTy, 126 const FunctionArgList &Args) { 127 // Emit allocs for param decls. Give the LLVM Argument nodes names. 128 llvm::Function::arg_iterator AI = Fn->arg_begin(); 129 130 // Name the struct return argument. 131 if (hasAggregateLLVMType(RetTy)) { 132 AI->setName("agg.result"); 133 ++AI; 134 } 135 136 for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); 137 i != e; ++i, ++AI) { 138 const VarDecl *Arg = i->first; 139 QualType T = i->second; 140 assert(AI != Fn->arg_end() && "Argument mismatch!"); 141 llvm::Value* V = AI; 142 if (!getContext().typesAreCompatible(T, Arg->getType())) { 143 // This must be a promotion, for something like 144 // "void a(x) short x; {..." 145 V = EmitScalarConversion(V, T, Arg->getType()); 146 } 147 EmitParmDecl(*Arg, V); 148 } 149 assert(AI == Fn->arg_end() && "Argument mismatch!"); 150} 151 152void CodeGenFunction::EmitFunctionEpilog(QualType RetTy, 153 llvm::Value *ReturnValue) { 154 if (!ReturnValue) { 155 Builder.CreateRetVoid(); 156 } else { 157 if (!hasAggregateLLVMType(RetTy)) { 158 Builder.CreateRet(Builder.CreateLoad(ReturnValue)); 159 } else if (RetTy->isAnyComplexType()) { 160 EmitAggregateCopy(CurFn->arg_begin(), ReturnValue, RetTy); 161 Builder.CreateRetVoid(); 162 } else { 163 EmitAggregateCopy(CurFn->arg_begin(), ReturnValue, RetTy); 164 Builder.CreateRetVoid(); 165 } 166 } 167} 168 169RValue CodeGenFunction::EmitCall(llvm::Value *Callee, 170 QualType ResultType, 171 const CallArgList &CallArgs) { 172 // FIXME: Factor out code to load from args into locals into target. 173 llvm::SmallVector<llvm::Value*, 16> Args; 174 llvm::Value *TempArg0 = 0; 175 176 // Handle struct-return functions by passing a pointer to the 177 // location that we would like to return into. 178 if (hasAggregateLLVMType(ResultType)) { 179 // Create a temporary alloca to hold the result of the call. :( 180 TempArg0 = CreateTempAlloca(ConvertType(ResultType)); 181 Args.push_back(TempArg0); 182 } 183 184 for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end(); 185 I != E; ++I) { 186 RValue RV = I->first; 187 if (RV.isScalar()) { 188 Args.push_back(RV.getScalarVal()); 189 } else if (RV.isComplex()) { 190 // Make a temporary alloca to pass the argument. 191 Args.push_back(CreateTempAlloca(ConvertType(I->second))); 192 StoreComplexToAddr(RV.getComplexVal(), Args.back(), false); 193 } else { 194 Args.push_back(RV.getAggregateAddr()); 195 } 196 } 197 198 llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size()); 199 CGCallInfo CallInfo(ResultType, CallArgs); 200 201 CodeGen::ParamAttrListType ParamAttrList; 202 CallInfo.constructParamAttrList(ParamAttrList); 203 CI->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(), 204 ParamAttrList.size())); 205 206 if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee)) 207 CI->setCallingConv(F->getCallingConv()); 208 if (CI->getType() != llvm::Type::VoidTy) 209 CI->setName("call"); 210 else if (ResultType->isAnyComplexType()) 211 return RValue::getComplex(LoadComplexFromAddr(TempArg0, false)); 212 else if (hasAggregateLLVMType(ResultType)) 213 // Struct return. 214 return RValue::getAggregate(TempArg0); 215 else { 216 // void return. 217 assert(ResultType->isVoidType() && "Should only have a void expr here"); 218 CI = 0; 219 } 220 221 return RValue::get(CI); 222} 223