forked from OSchip/llvm-project
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 llvm-svn: 55963
This commit is contained in:
parent
ea9285e643
commit
3d7c90b8ec
|
@ -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<QualType, 16> &ArgTypes,
|
||||
ParamAttrListType &PAL) {
|
||||
unsigned FuncAttrs = 0;
|
||||
|
||||
if (TargetDecl) {
|
||||
if (TargetDecl->getAttr<NoThrowAttr>())
|
||||
FuncAttrs |= llvm::ParamAttr::NoUnwind;
|
||||
if (TargetDecl->getAttr<NoReturnAttr>())
|
||||
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<QualType, 8>::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<FunctionTypeProto>(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<std::pair<llvm::Value*, QualType>, 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);
|
||||
}
|
|
@ -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<typename T, unsigned> class SmallVector;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class Decl;
|
||||
class FunctionDecl;
|
||||
class ObjCMethodDecl;
|
||||
|
||||
namespace CodeGen {
|
||||
typedef llvm::SmallVector<llvm::ParamAttrsWithIndex, 8> ParamAttrListType;
|
||||
|
||||
/// CallArgList - Type for representing both the value and type of
|
||||
/// arguments in a call.
|
||||
typedef llvm::SmallVector<std::pair<llvm::Value*, QualType>, 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<QualType, 16> 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<QualType, 16> ArgTypes;
|
||||
|
||||
public:
|
||||
CGCallInfo(QualType _ResultType, const CallArgList &Args);
|
||||
|
||||
void constructParamAttrList(ParamAttrListType &Args) const;
|
||||
};
|
||||
} // end namespace CodeGen
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
|
@ -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<llvm::Value*, 16> 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<llvm::ParamAttrsWithIndex, 8> 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<llvm::Function>(Callee))
|
||||
CI->setCallingConv(F->getCallingConv());
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#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<std::pair<llvm::Value*, QualType>, 16> CallArgList;
|
||||
|
||||
/// EmitCallArg - Emit the given expression and append the result
|
||||
/// onto the given Args list.
|
||||
void EmitCallArg(const Expr *E, CallArgList &Args);
|
||||
|
|
|
@ -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<DLLImportAttr>())
|
||||
GV->setLinkage(llvm::Function::DLLImportLinkage);
|
||||
else if (FD->getAttr<DLLExportAttr>())
|
||||
GV->setLinkage(llvm::Function::DLLExportLinkage);
|
||||
else if (FD->getAttr<WeakAttr>() || FD->isInline())
|
||||
GV->setLinkage(llvm::Function::WeakLinkage);
|
||||
} else {
|
||||
if (D->getAttr<DLLImportAttr>())
|
||||
GV->setLinkage(llvm::Function::DLLImportLinkage);
|
||||
else if (D->getAttr<DLLExportAttr>())
|
||||
GV->setLinkage(llvm::Function::DLLExportLinkage);
|
||||
else if (D->getAttr<WeakAttr>() || IsInline)
|
||||
GV->setLinkage(llvm::Function::WeakLinkage);
|
||||
}
|
||||
|
||||
if (const VisibilityAttr *attr = FD->getAttr<VisibilityAttr>())
|
||||
if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>())
|
||||
setGlobalVisibility(GV, attr->getVisibility());
|
||||
// FIXME: else handle -fvisibility
|
||||
|
||||
if (const AsmLabelAttr *ALA = FD->getAttr<AsmLabelAttr>()) {
|
||||
if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
|
||||
// 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<QualType, 16> &ArgTypes) {
|
||||
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;
|
||||
// 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<QualType, 8>::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<FastCallAttr>())
|
||||
if (Info.getDecl()->getAttr<FastCallAttr>())
|
||||
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<QualType, 16> 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<QualType, 16> ArgTypes;
|
||||
const FunctionType *FTy = FD->getType()->getAsFunctionType();
|
||||
const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FTy);
|
||||
|
||||
ArgTypes.push_back(FTy->getResultType());
|
||||
if (FTP)
|
||||
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
|
||||
ArgTypes.push_back(FTP->getArgType(i));
|
||||
SetFunctionAttrs(CGFunctionInfo(FD), F);
|
||||
|
||||
SetFunctionAttributesFromTypes(FD, F, ArgTypes);
|
||||
|
||||
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());
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue