From 0dbe227feccf6a8dbadfff8ca3f80416b7bf2f28 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Mon, 8 Sep 2008 21:33:45 +0000 Subject: [PATCH] Refactor parameter attribute handling: - Add CGCall.h for dealing with ABI issues related to calls. - Add CGFunctionInfo and CGCallInfo for capturing ABI relevant information about functions and calls. - Isolate LLVM parameter attribute handling inside CGCall.cpp git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55963 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCall.cpp | 117 ++++++++++++++++++++++++++++++++++ lib/CodeGen/CGCall.h | 76 ++++++++++++++++++++++ lib/CodeGen/CGExpr.cpp | 39 +++--------- lib/CodeGen/CodeGenFunction.h | 5 +- lib/CodeGen/CodeGenModule.cpp | 104 ++++++++---------------------- lib/CodeGen/CodeGenModule.h | 3 - 6 files changed, 230 insertions(+), 114 deletions(-) create mode 100644 lib/CodeGen/CGCall.cpp create mode 100644 lib/CodeGen/CGCall.h diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp new file mode 100644 index 0000000000..d342ef0af3 --- /dev/null +++ b/lib/CodeGen/CGCall.cpp @@ -0,0 +1,117 @@ +//===----- 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 llvm::SmallVector, 16> &_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); +} diff --git a/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h new file mode 100644 index 0000000000..b4e8d1f6da --- /dev/null +++ b/lib/CodeGen/CGCall.h @@ -0,0 +1,76 @@ +//===----- 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. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_CODEGEN_CGCALL_H +#define CLANG_CODEGEN_CGCALL_H + +#include "clang/AST/Type.h" + +namespace llvm { + class Function; + struct ParamAttrsWithIndex; + class Value; + + template class SmallVector; +} + +namespace clang { + class ASTContext; + class Decl; + class FunctionDecl; + class ObjCMethodDecl; + +namespace CodeGen { + typedef llvm::SmallVector ParamAttrListType; + + /// CallArgList - Type for representing both the value and type of + /// arguments in a call. + typedef llvm::SmallVector, 16> CallArgList; + + /// CGFunctionInfo - Class to encapsulate the information about a + /// function definition. + class CGFunctionInfo { + /// TheDecl - The decl we are storing information for. This is + /// either a Function or ObjCMethod Decl. + const Decl *TheDecl; + + llvm::SmallVector ArgTypes; + + public: + CGFunctionInfo(const FunctionDecl *FD); + CGFunctionInfo(const ObjCMethodDecl *MD, + const ASTContext &Context); + + const Decl* getDecl() const { return TheDecl; } + + void constructParamAttrList(ParamAttrListType &Args) const; + }; + + /// CGCallInfo - Class to encapsulate the arguments and clang types + /// used in a call. + class CGCallInfo { + QualType ResultType; + const CallArgList &Args; + + llvm::SmallVector ArgTypes; + + public: + CGCallInfo(QualType _ResultType, const CallArgList &Args); + + void constructParamAttrList(ParamAttrListType &Args) const; + }; +} // end namespace CodeGen +} // end namespace clang + +#endif diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index cc5e705c39..8a978160d0 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -13,6 +13,7 @@ #include "CodeGenFunction.h" #include "CodeGenModule.h" +#include "CGCall.h" #include "CGObjCRuntime.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -884,11 +885,12 @@ void CodeGenFunction::EmitCallArg(const Expr *E, CallArgList &Args) { RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType ResultType, const CallArgList &CallArgs) { + // FIXME: Factor out code to load from args into locals into target. llvm::SmallVector Args; llvm::Value *TempArg0 = 0; - // Handle struct-return functions by passing a pointer to the location that - // we would like to return into. + // Handle struct-return functions by passing a pointer to the + // location that we would like to return into. if (hasAggregateLLVMType(ResultType)) { // Create a temporary alloca to hold the result of the call. :( TempArg0 = CreateTempAlloca(ConvertType(ResultType)); @@ -900,35 +902,12 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee, Args.push_back(I->first); llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size()); + CGCallInfo CallInfo(ResultType, CallArgs); - // Note that there is parallel code in SetFunctionAttributes in CodeGenModule - llvm::SmallVector ParamAttrList; - unsigned Index = 1; - if (TempArg0) { - ParamAttrList.push_back( - llvm::ParamAttrsWithIndex::get(Index, llvm::ParamAttr::StructRet)); - ++Index; - } - - for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end(); - I != E; ++I, ++Index) { - QualType ParamType = I->second; - 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) - ParamAttrList.push_back(llvm::ParamAttrsWithIndex::get(Index, - ParamAttrs)); - } - CI->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(), - ParamAttrList.size())); + CodeGen::ParamAttrListType ParamAttrList; + CallInfo.constructParamAttrList(ParamAttrList); + CI->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(), + ParamAttrList.size())); if (const llvm::Function *F = dyn_cast(Callee)) CI->setCallingConv(F->getCallingConv()); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index b388153836..c38171a5f5 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -24,6 +24,7 @@ #include #include +#include "CGCall.h" #include "CGValue.h" namespace llvm { @@ -307,10 +308,6 @@ public: // Scalar Expression Emission //===--------------------------------------------------------------------===// - /// CallArgList - Type for representing both the value and type of - /// arguments in a call. - typedef llvm::SmallVector, 16> CallArgList; - /// EmitCallArg - Emit the given expression and append the result /// onto the given Args list. void EmitCallArg(const Expr *E, CallArgList &Args); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 373027bbff..f471565bc3 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -14,6 +14,7 @@ #include "CGDebugInfo.h" #include "CodeGenModule.h" #include "CodeGenFunction.h" +#include "CGCall.h" #include "CGObjCRuntime.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -172,78 +173,43 @@ void CodeGenModule::EmitAnnotations() { gv->setSection("llvm.metadata"); } -void CodeGenModule::SetGlobalValueAttributes(const FunctionDecl *FD, - llvm::GlobalValue *GV) { +static void SetGlobalValueAttributes(const Decl *D, + bool IsInternal, + bool IsInline, + llvm::GlobalValue *GV) { // TODO: Set up linkage and many other things. Note, this is a simple // approximation of what we really want. - if (FD->getStorageClass() == FunctionDecl::Static) + if (IsInternal) { GV->setLinkage(llvm::Function::InternalLinkage); - else if (FD->getAttr()) - GV->setLinkage(llvm::Function::DLLImportLinkage); - else if (FD->getAttr()) - GV->setLinkage(llvm::Function::DLLExportLinkage); - else if (FD->getAttr() || FD->isInline()) - GV->setLinkage(llvm::Function::WeakLinkage); + } else { + if (D->getAttr()) + GV->setLinkage(llvm::Function::DLLImportLinkage); + else if (D->getAttr()) + GV->setLinkage(llvm::Function::DLLExportLinkage); + else if (D->getAttr() || IsInline) + GV->setLinkage(llvm::Function::WeakLinkage); + } - if (const VisibilityAttr *attr = FD->getAttr()) + if (const VisibilityAttr *attr = D->getAttr()) setGlobalVisibility(GV, attr->getVisibility()); // FIXME: else handle -fvisibility - if (const AsmLabelAttr *ALA = FD->getAttr()) { + if (const AsmLabelAttr *ALA = D->getAttr()) { // Prefaced with special LLVM marker to indicate that the name // should not be munged. GV->setName("\01" + ALA->getLabel()); } } -static void -SetFunctionAttributesFromTypes(const Decl *FD, - llvm::Function *F, - const llvm::SmallVector &ArgTypes) { - unsigned FuncAttrs = 0; - if (FD->getAttr()) - FuncAttrs |= llvm::ParamAttr::NoUnwind; - if (FD->getAttr()) - FuncAttrs |= llvm::ParamAttr::NoReturn; - - llvm::SmallVector ParamAttrList; - // Note that there is parallel code in CodeGenFunction::EmitCallExpr - unsigned increment = 1; - if (CodeGenFunction::hasAggregateLLVMType(ArgTypes[0])) { - ParamAttrList.push_back( - llvm::ParamAttrsWithIndex::get(1, llvm::ParamAttr::StructRet)); - ++increment; - } else if (ArgTypes[0]->isPromotableIntegerType()) { - if (ArgTypes[0]->isSignedIntegerType()) { - FuncAttrs |= llvm::ParamAttr::SExt; - } else if (ArgTypes[0]->isUnsignedIntegerType()) { - FuncAttrs |= llvm::ParamAttr::ZExt; - } - } - if (FuncAttrs) - ParamAttrList.push_back(llvm::ParamAttrsWithIndex::get(0, FuncAttrs)); - for (llvm::SmallVector::const_iterator i = ArgTypes.begin() + 1, - e = ArgTypes.end(); i != e; ++i, ++increment) { - QualType ParamType = *i; - 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(increment, - ParamAttrs)); - } +static void SetFunctionAttrs(const CGFunctionInfo &Info, llvm::Function *F) { + ParamAttrListType ParamAttrList; + Info.constructParamAttrList(ParamAttrList); F->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(), ParamAttrList.size())); // Set the appropriate calling convention for the Function. - if (FD->getAttr()) + if (Info.getDecl()->getAttr()) F->setCallingConv(llvm::CallingConv::Fast); } @@ -256,36 +222,19 @@ void CodeGenModule::SetFunctionAttributesForDefinition(llvm::Function *F) { void CodeGenModule::SetMethodAttributes(const ObjCMethodDecl *MD, llvm::Function *F) { - llvm::SmallVector ArgTypes; - - 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()); - - SetFunctionAttributesFromTypes(MD, F, ArgTypes); + SetFunctionAttrs(CGFunctionInfo(MD, Context), F); SetFunctionAttributesForDefinition(F); - // FIXME: set visibility + SetGlobalValueAttributes(MD, true, false, F); } void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD, llvm::Function *F) { - llvm::SmallVector ArgTypes; - 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)); - - SetFunctionAttributesFromTypes(FD, F, ArgTypes); + SetFunctionAttrs(CGFunctionInfo(FD), F); - SetGlobalValueAttributes(FD, F); + SetGlobalValueAttributes(FD, FD->getStorageClass() == FunctionDecl::Static, + FD->isInline(), F); } void CodeGenModule::EmitStatics() { @@ -574,7 +523,8 @@ CodeGenModule::EmitForwardFunctionDefinition(const FunctionDecl *D) { D->getName(), aliasee, &getModule()); - SetGlobalValueAttributes(D, alias); + // Alias should never be internal + SetGlobalValueAttributes(D, false, false, alias); return alias; } else { const llvm::Type *Ty = getTypes().ConvertType(D->getType()); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index a6308736cc..41985fbac6 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -218,9 +218,6 @@ private: void SetFunctionAttributes(const FunctionDecl *FD, llvm::Function *F); - void SetGlobalValueAttributes(const FunctionDecl *FD, - llvm::GlobalValue *GV); - /// EmitGlobal - Emit code for a singal global function or var /// decl. Forward declarations are emitted lazily. void EmitGlobal(const ValueDecl *D); -- 2.40.0