}
llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size());
+
+ // Note that there is parallel code in SetFunctionAttributes in CodeGenModule
+ llvm::SmallVector<llvm::ParamAttrsWithIndex, 8> ParamAttrList;
+ if (hasAggregateLLVMType(ResultType))
+ ParamAttrList.push_back(
+ llvm::ParamAttrsWithIndex::get(1, llvm::ParamAttr::StructRet));
+ unsigned increment = hasAggregateLLVMType(ResultType) ? 2 : 1;
+ for (unsigned i = 0; i < NumArgs; i++) {
+ QualType ParamType = ArgExprs[i]->getType();
+ unsigned ParamAttrs = 0;
+ if (ParamType->isRecordType())
+ ParamAttrs |= llvm::ParamAttr::ByVal;
+ if (ParamType->isSignedIntegerType() && ParamType->isPromotableIntegerType())
+ ParamAttrs |= llvm::ParamAttr::SExt;
+ if (ParamType->isUnsignedIntegerType() && ParamType->isPromotableIntegerType())
+ ParamAttrs |= llvm::ParamAttr::ZExt;
+ if (ParamAttrs)
+ ParamAttrList.push_back(llvm::ParamAttrsWithIndex::get(i + increment,
+ ParamAttrs));
+ }
+ CI->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(),
+ ParamAttrList.size()));
+
if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee))
CI->setCallingConv(F->getCallingConv());
if (CI->getType() != llvm::Type::VoidTy)
CurFn = cast<llvm::Function>(CGM.GetAddrOfFunctionDecl(FD, true));
assert(CurFn->isDeclaration() && "Function already has body?");
-
- // TODO: Set up linkage and many other things. Note, this is a simple
- // approximation of what we really want.
- if (FD->getStorageClass() == FunctionDecl::Static)
- CurFn->setLinkage(llvm::Function::InternalLinkage);
- else if (FD->getAttr<DLLImportAttr>())
- CurFn->setLinkage(llvm::Function::DLLImportLinkage);
- else if (FD->getAttr<DLLExportAttr>())
- CurFn->setLinkage(llvm::Function::DLLExportLinkage);
- else if (FD->getAttr<WeakAttr>() || FD->isInline())
- CurFn->setLinkage(llvm::Function::WeakLinkage);
-
- if (FD->getAttr<FastCallAttr>())
- CurFn->setCallingConv(llvm::CallingConv::Fast);
-
- if (const VisibilityAttr *attr = FD->getAttr<VisibilityAttr>())
- CodeGenModule::setVisibility(CurFn, attr->getVisibility());
- // FIXME: else handle -fvisibility
-
-
- unsigned FuncAttrs = 0;
- if (FD->getAttr<NoThrowAttr>())
- FuncAttrs |= llvm::ParamAttr::NoUnwind;
- if (FD->getAttr<NoReturnAttr>())
- FuncAttrs |= llvm::ParamAttr::NoReturn;
-
- if (FuncAttrs) {
- llvm::ParamAttrsWithIndex PAWI =
- llvm::ParamAttrsWithIndex::get(0, FuncAttrs);
- CurFn->setParamAttrs(llvm::PAListPtr::get(&PAWI, 1));
- }
llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("entry", CurFn);
if (I->second == OldVal) I->second = NewVal;
}
+bool hasAggregateLLVMType(QualType T) {
+ return !T->isRealType() && !T->isPointerLikeType() &&
+ !T->isVoidType() && !T->isVectorType() && !T->isFunctionType();
+}
+
+void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD,
+ llvm::Function *F,
+ const llvm::FunctionType *FTy) {
+ unsigned FuncAttrs = 0;
+ if (FD->getAttr<NoThrowAttr>())
+ FuncAttrs |= llvm::ParamAttr::NoUnwind;
+ if (FD->getAttr<NoReturnAttr>())
+ FuncAttrs |= llvm::ParamAttr::NoReturn;
+
+ llvm::SmallVector<llvm::ParamAttrsWithIndex, 8> ParamAttrList;
+ if (FuncAttrs)
+ ParamAttrList.push_back(llvm::ParamAttrsWithIndex::get(0, FuncAttrs));
+ // Note that there is parallel code in CodeGenFunction::EmitCallExpr
+ bool AggregateReturn = hasAggregateLLVMType(FD->getResultType());
+ if (AggregateReturn)
+ ParamAttrList.push_back(
+ llvm::ParamAttrsWithIndex::get(1, llvm::ParamAttr::StructRet));
+ unsigned increment = AggregateReturn ? 2 : 1;
+ for (unsigned i = 0; i < FD->getNumParams(); i++) {
+ QualType ParamType = FD->getParamDecl(i)->getType();
+ unsigned ParamAttrs = 0;
+ if (ParamType->isRecordType())
+ ParamAttrs |= llvm::ParamAttr::ByVal;
+ if (ParamType->isSignedIntegerType() && ParamType->isPromotableIntegerType())
+ ParamAttrs |= llvm::ParamAttr::SExt;
+ if (ParamType->isUnsignedIntegerType() && ParamType->isPromotableIntegerType())
+ ParamAttrs |= llvm::ParamAttr::ZExt;
+ if (ParamAttrs)
+ ParamAttrList.push_back(llvm::ParamAttrsWithIndex::get(i + increment,
+ ParamAttrs));
+ }
+ F->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(),
+ ParamAttrList.size()));
+
+ // Set the appropriate calling convention for the Function.
+ if (FD->getAttr<FastCallAttr>())
+ F->setCallingConv(llvm::CallingConv::Fast);
+
+ // TODO: Set up linkage and many other things. Note, this is a simple
+ // approximation of what we really want.
+ if (FD->getStorageClass() == FunctionDecl::Static)
+ F->setLinkage(llvm::Function::InternalLinkage);
+ else if (FD->getAttr<DLLImportAttr>())
+ F->setLinkage(llvm::Function::DLLImportLinkage);
+ else if (FD->getAttr<DLLExportAttr>())
+ F->setLinkage(llvm::Function::DLLExportLinkage);
+ else if (FD->getAttr<WeakAttr>() || FD->isInline())
+ F->setLinkage(llvm::Function::WeakLinkage);
+
+ if (const VisibilityAttr *attr = FD->getAttr<VisibilityAttr>())
+ CodeGenModule::setVisibility(F, attr->getVisibility());
+ // FIXME: else handle -fvisibility
+}
+
+
llvm::Constant *CodeGenModule::GetAddrOfFunctionDecl(const FunctionDecl *D,
bool isDefinition) {
F = llvm::Function::Create(FTy, llvm::Function::ExternalLinkage,
D->getName(), &getModule());
- // Set the appropriate calling convention for the Function.
- if (D->getAttr<FastCallAttr>())
- F->setCallingConv(llvm::CallingConv::Fast);
+ SetFunctionAttributes(D, F, FTy);
return Entry = F;
}
assert(F->isDeclaration() && "Shouldn't replace non-declaration");
F->eraseFromParent();
+ SetFunctionAttributes(D, NewFn, FTy);
// Return the new function which has the right type.
return Entry = NewFn;
}