forked from OSchip/llvm-project
Move FunctionType conversion into CGCall.cpp:
- Added CodeGenTypes::GetFunctionType, taking a CGFunctionInfo. - Updated Obj-C runtimes to use this instead of rolling the llvm::FunctionType by hand. - Killed CodeGenTypes::{ConvertReturnType, DecodeArgumentTypes}. Add ABIArgInfo class to encapsulate ABI decision of how to lower types to LLVM. - Will move to target sometime soon. llvm-svn: 56047
This commit is contained in:
parent
a72d4aece6
commit
7a95ca3197
|
@ -26,21 +26,39 @@ using namespace CodeGen;
|
|||
|
||||
// FIXME: Use iterator and sidestep silly type array creation.
|
||||
|
||||
CGFunctionInfo::CGFunctionInfo(const FunctionTypeNoProto *FTNP)
|
||||
: IsVariadic(true)
|
||||
{
|
||||
ArgTypes.push_back(FTNP->getResultType());
|
||||
}
|
||||
|
||||
CGFunctionInfo::CGFunctionInfo(const FunctionTypeProto *FTP)
|
||||
: IsVariadic(FTP->isVariadic())
|
||||
{
|
||||
ArgTypes.push_back(FTP->getResultType());
|
||||
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
|
||||
ArgTypes.push_back(FTP->getArgType(i));
|
||||
}
|
||||
|
||||
// FIXME: Is there really any reason to have this still?
|
||||
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)
|
||||
if (FTP) {
|
||||
IsVariadic = FTP->isVariadic();
|
||||
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
|
||||
ArgTypes.push_back(FTP->getArgType(i));
|
||||
} else {
|
||||
IsVariadic = true;
|
||||
}
|
||||
}
|
||||
|
||||
CGFunctionInfo::CGFunctionInfo(const ObjCMethodDecl *MD,
|
||||
const ASTContext &Context)
|
||||
: TheDecl(MD)
|
||||
: IsVariadic(MD->isVariadic())
|
||||
{
|
||||
ArgTypes.push_back(MD->getResultType());
|
||||
ArgTypes.push_back(MD->getSelfDecl()->getType());
|
||||
|
@ -105,6 +123,12 @@ public:
|
|||
bool isDefault() const { return TheKind == Default; }
|
||||
bool isStructRet() const { return TheKind == StructRet; }
|
||||
bool isCoerce() const { return TheKind == Coerce; }
|
||||
|
||||
// Coerce accessors
|
||||
QualType getCoerceToType() const {
|
||||
assert(TheKind == Coerce && "Invalid kind!");
|
||||
return TypeData;
|
||||
}
|
||||
};
|
||||
|
||||
/***/
|
||||
|
@ -119,6 +143,49 @@ static ABIArgInfo classifyReturnType(QualType RetTy) {
|
|||
|
||||
/***/
|
||||
|
||||
const llvm::FunctionType *
|
||||
CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
|
||||
std::vector<const llvm::Type*> ArgTys;
|
||||
|
||||
const llvm::Type *ResultType = 0;
|
||||
|
||||
ArgTypeIterator begin = FI.argtypes_begin(), end = FI.argtypes_end();
|
||||
QualType RetTy = *begin;
|
||||
ABIArgInfo RetAI = classifyReturnType(RetTy);
|
||||
switch (RetAI.getKind()) {
|
||||
case ABIArgInfo::Default:
|
||||
if (RetTy->isVoidType()) {
|
||||
ResultType = llvm::Type::VoidTy;
|
||||
} else {
|
||||
ResultType = ConvertTypeRecursive(RetTy);
|
||||
}
|
||||
break;
|
||||
|
||||
case ABIArgInfo::StructRet: {
|
||||
ResultType = llvm::Type::VoidTy;
|
||||
const llvm::Type *STy = ConvertTypeRecursive(RetTy);
|
||||
ArgTys.push_back(llvm::PointerType::get(STy, RetTy.getAddressSpace()));
|
||||
break;
|
||||
}
|
||||
|
||||
case ABIArgInfo::Coerce:
|
||||
ResultType = llvm::Type::VoidTy;
|
||||
ArgTys.push_back(ConvertTypeRecursive(RetAI.getCoerceToType()));
|
||||
break;
|
||||
}
|
||||
|
||||
for (++begin; begin != end; ++begin) {
|
||||
const llvm::Type *Ty = ConvertTypeRecursive(*begin);
|
||||
if (Ty->isSingleValueType())
|
||||
ArgTys.push_back(Ty);
|
||||
else
|
||||
// byval arguments are always on the stack, which is addr space #0.
|
||||
ArgTys.push_back(llvm::PointerType::getUnqual(Ty));
|
||||
}
|
||||
|
||||
return llvm::FunctionType::get(ResultType, ArgTys, FI.isVariadic());
|
||||
}
|
||||
|
||||
bool CodeGenModule::ReturnTypeUsesSret(QualType RetTy) {
|
||||
return classifyReturnType(RetTy).isStructRet();
|
||||
}
|
||||
|
@ -138,8 +205,8 @@ void CodeGenModule::ConstructParamAttrList(const Decl *TargetDecl,
|
|||
|
||||
QualType RetTy = *begin;
|
||||
unsigned Index = 1;
|
||||
ABIArgInfo ResAI = classifyReturnType(RetTy);
|
||||
switch (ResAI.getKind()) {
|
||||
ABIArgInfo RetAI = classifyReturnType(RetTy);
|
||||
switch (RetAI.getKind()) {
|
||||
case ABIArgInfo::Default:
|
||||
if (RetTy->isPromotableIntegerType()) {
|
||||
if (RetTy->isSignedIntegerType()) {
|
||||
|
|
|
@ -54,18 +54,18 @@ namespace CodeGen {
|
|||
/// 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;
|
||||
bool IsVariadic;
|
||||
|
||||
llvm::SmallVector<QualType, 16> ArgTypes;
|
||||
|
||||
public:
|
||||
CGFunctionInfo(const FunctionTypeNoProto *FTNP);
|
||||
CGFunctionInfo(const FunctionTypeProto *FTP);
|
||||
CGFunctionInfo(const FunctionDecl *FD);
|
||||
CGFunctionInfo(const ObjCMethodDecl *MD,
|
||||
const ASTContext &Context);
|
||||
|
||||
const Decl* getDecl() const { return TheDecl; }
|
||||
bool isVariadic() const { return IsVariadic; }
|
||||
|
||||
ArgTypeIterator argtypes_begin() const;
|
||||
ArgTypeIterator argtypes_end() const;
|
||||
|
|
|
@ -921,40 +921,15 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
|
|||
}
|
||||
|
||||
llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD) {
|
||||
const llvm::Type *ReturnTy =
|
||||
CGM.getTypes().ConvertReturnType(OMD->getResultType());
|
||||
const ObjCCategoryImplDecl *OCD =
|
||||
dyn_cast<ObjCCategoryImplDecl>(OMD->getMethodContext());
|
||||
const std::string &CategoryName = OCD ? OCD->getName() : "";
|
||||
const llvm::Type *SelfTy = llvm::PointerType::getUnqual(llvm::Type::Int32Ty);
|
||||
const std::string &ClassName = OMD->getClassInterface()->getName();
|
||||
const std::string &MethodName = OMD->getSelector().getName();
|
||||
unsigned ArgC = OMD->param_size();
|
||||
bool isClassMethod = !OMD->isInstance();
|
||||
bool isVarArg = OMD->isVariadic();
|
||||
|
||||
llvm::SmallVector<const llvm::Type *, 16> ArgTy;
|
||||
for (unsigned i=0 ; i<OMD->param_size() ; i++) {
|
||||
const llvm::Type *Ty =
|
||||
CGM.getTypes().ConvertType(OMD->getParamDecl(i)->getType());
|
||||
if (Ty->isFirstClassType())
|
||||
ArgTy.push_back(Ty);
|
||||
else
|
||||
ArgTy.push_back(llvm::PointerType::getUnqual(Ty));
|
||||
}
|
||||
|
||||
std::vector<const llvm::Type*> Args;
|
||||
if (!ReturnTy->isSingleValueType() && ReturnTy != llvm::Type::VoidTy) {
|
||||
Args.push_back(llvm::PointerType::getUnqual(ReturnTy));
|
||||
ReturnTy = llvm::Type::VoidTy;
|
||||
}
|
||||
Args.push_back(SelfTy);
|
||||
Args.push_back(SelectorTy);
|
||||
Args.insert(Args.end(), ArgTy.begin(), ArgTy.begin()+ArgC);
|
||||
|
||||
llvm::FunctionType *MethodTy = llvm::FunctionType::get(ReturnTy,
|
||||
Args,
|
||||
isVarArg);
|
||||
const llvm::FunctionType *MethodTy =
|
||||
CGM.getTypes().GetFunctionType(CGFunctionInfo(OMD, CGM.getContext()));
|
||||
std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName,
|
||||
MethodName, isClassMethod);
|
||||
|
||||
|
|
|
@ -1344,66 +1344,18 @@ llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name,
|
|||
}
|
||||
|
||||
llvm::Function *CGObjCMac::GenerateMethod(const ObjCMethodDecl *OMD) {
|
||||
const llvm::Type *ReturnTy =
|
||||
CGM.getTypes().ConvertReturnType(OMD->getResultType());
|
||||
const llvm::Type *SelfTy =
|
||||
CGM.getTypes().ConvertType(OMD->getSelfDecl()->getType());
|
||||
|
||||
std::vector<const llvm::Type*> ArgTys;
|
||||
ArgTys.reserve(1 + 2 + OMD->param_size());
|
||||
|
||||
// FIXME: This is not something we should have to be dealing with
|
||||
// here.
|
||||
bool useStructRet =
|
||||
CodeGen::CodeGenFunction::hasAggregateLLVMType(OMD->getResultType());
|
||||
if (useStructRet) {
|
||||
ArgTys.push_back(llvm::PointerType::getUnqual(ReturnTy));
|
||||
ReturnTy = llvm::Type::VoidTy;
|
||||
}
|
||||
|
||||
// Implicit arguments
|
||||
ArgTys.push_back(SelfTy);
|
||||
ArgTys.push_back(ObjCTypes.SelectorPtrTy);
|
||||
|
||||
for (ObjCMethodDecl::param_const_iterator
|
||||
i = OMD->param_begin(), e = OMD->param_end();
|
||||
i != e; ++i) {
|
||||
const llvm::Type *Ty = CGM.getTypes().ConvertType((*i)->getType());
|
||||
if (Ty->isSingleValueType()) {
|
||||
ArgTys.push_back(Ty);
|
||||
} else {
|
||||
ArgTys.push_back(llvm::PointerType::getUnqual(Ty));
|
||||
}
|
||||
}
|
||||
|
||||
std::string Name;
|
||||
GetNameForMethod(OMD, Name);
|
||||
|
||||
const llvm::FunctionType *MethodTy =
|
||||
CGM.getTypes().GetFunctionType(CGFunctionInfo(OMD, CGM.getContext()));
|
||||
llvm::Function *Method =
|
||||
llvm::Function::Create(llvm::FunctionType::get(ReturnTy,
|
||||
ArgTys,
|
||||
OMD->isVariadic()),
|
||||
llvm::Function::Create(MethodTy,
|
||||
llvm::GlobalValue::InternalLinkage,
|
||||
Name,
|
||||
&CGM.getModule());
|
||||
MethodDefinitions.insert(std::make_pair(OMD, Method));
|
||||
|
||||
unsigned Offset = 3; // Return plus self and selector implicit args.
|
||||
if (useStructRet) {
|
||||
Method->addParamAttr(1, llvm::ParamAttr::StructRet);
|
||||
++Offset;
|
||||
}
|
||||
|
||||
// FIXME: This is horrible, we need to be reusing the machinery in
|
||||
// CodeGenModule.cpp (SetFunctionAttributes).
|
||||
for (ObjCMethodDecl::param_const_iterator
|
||||
i = OMD->param_begin(), e = OMD->param_end();
|
||||
i != e; ++i, ++Offset) {
|
||||
const llvm::Type *Ty = CGM.getTypes().ConvertType((*i)->getType());
|
||||
if (!Ty->isSingleValueType())
|
||||
Method->addParamAttr(Offset, llvm::ParamAttr::ByVal);
|
||||
}
|
||||
|
||||
return Method;
|
||||
}
|
||||
|
||||
|
|
|
@ -212,18 +212,18 @@ static void SetGlobalValueAttributes(const Decl *D,
|
|||
}
|
||||
}
|
||||
|
||||
void CodeGenModule::SetFunctionParamAttrs(const CGFunctionInfo &Info,
|
||||
void CodeGenModule::SetFunctionParamAttrs(const Decl *D,
|
||||
const CGFunctionInfo &Info,
|
||||
llvm::Function *F) {
|
||||
ParamAttrListType ParamAttrList;
|
||||
ConstructParamAttrList(Info.getDecl(),
|
||||
Info.argtypes_begin(), Info.argtypes_end(),
|
||||
ConstructParamAttrList(D, Info.argtypes_begin(), Info.argtypes_end(),
|
||||
ParamAttrList);
|
||||
|
||||
F->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(),
|
||||
ParamAttrList.size()));
|
||||
|
||||
// Set the appropriate calling convention for the Function.
|
||||
if (Info.getDecl()->getAttr<FastCallAttr>())
|
||||
if (D->getAttr<FastCallAttr>())
|
||||
F->setCallingConv(llvm::CallingConv::Fast);
|
||||
}
|
||||
|
||||
|
@ -245,19 +245,20 @@ void CodeGenModule::SetFunctionAttributesForDefinition(const Decl *D,
|
|||
|
||||
void CodeGenModule::SetMethodAttributes(const ObjCMethodDecl *MD,
|
||||
llvm::Function *F) {
|
||||
SetFunctionParamAttrs(CGFunctionInfo(MD, Context), F);
|
||||
SetFunctionParamAttrs(MD, CGFunctionInfo(MD, Context), F);
|
||||
|
||||
SetFunctionAttributesForDefinition(MD, F);
|
||||
}
|
||||
|
||||
void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD,
|
||||
llvm::Function *F) {
|
||||
SetFunctionParamAttrs(CGFunctionInfo(FD), F);
|
||||
|
||||
SetFunctionParamAttrs(FD, CGFunctionInfo(FD), F);
|
||||
|
||||
SetGlobalValueAttributes(FD, FD->getStorageClass() == FunctionDecl::Static,
|
||||
FD->isInline(), F, false);
|
||||
}
|
||||
|
||||
|
||||
void CodeGenModule::EmitAliases() {
|
||||
for (unsigned i = 0, e = Aliases.size(); i != e; ++i) {
|
||||
const FunctionDecl *D = Aliases[i];
|
||||
|
|
|
@ -217,7 +217,8 @@ public:
|
|||
void SetMethodAttributes(const ObjCMethodDecl *MD,
|
||||
llvm::Function *F);
|
||||
|
||||
void SetFunctionParamAttrs(const CGFunctionInfo &Info,
|
||||
void SetFunctionParamAttrs(const Decl *D,
|
||||
const CGFunctionInfo &Info,
|
||||
llvm::Function *F);
|
||||
|
||||
/// ReturnTypeUsesSret - Return true iff the given type uses 'sret'
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "llvm/Module.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
|
||||
#include "CGCall.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace CodeGen;
|
||||
|
||||
|
@ -167,13 +169,6 @@ void CodeGenTypes::CollectObjCIvarTypes(ObjCInterfaceDecl *ObjCClass,
|
|||
}
|
||||
}
|
||||
|
||||
const llvm::Type *CodeGenTypes::ConvertReturnType(QualType T) {
|
||||
if (T->isVoidType())
|
||||
return llvm::Type::VoidTy; // Result of function uses llvm void.
|
||||
else
|
||||
return ConvertType(T);
|
||||
}
|
||||
|
||||
static const llvm::Type* getTypeForFormat(const llvm::fltSemantics &format) {
|
||||
if (&format == &llvm::APFloat::IEEEsingle)
|
||||
return llvm::Type::FloatTy;
|
||||
|
@ -273,35 +268,9 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
|
|||
VT.getNumElements());
|
||||
}
|
||||
case Type::FunctionNoProto:
|
||||
case Type::FunctionProto: {
|
||||
const FunctionType &FP = cast<FunctionType>(Ty);
|
||||
const llvm::Type *ResultType;
|
||||
|
||||
if (FP.getResultType()->isVoidType())
|
||||
ResultType = llvm::Type::VoidTy; // Result of function uses llvm void.
|
||||
else
|
||||
ResultType = ConvertTypeRecursive(FP.getResultType());
|
||||
|
||||
// FIXME: Convert argument types.
|
||||
bool isVarArg;
|
||||
std::vector<const llvm::Type*> ArgTys;
|
||||
|
||||
// Struct return passes the struct byref.
|
||||
if (!ResultType->isSingleValueType() && ResultType != llvm::Type::VoidTy) {
|
||||
ArgTys.push_back(llvm::PointerType::get(ResultType,
|
||||
FP.getResultType().getAddressSpace()));
|
||||
ResultType = llvm::Type::VoidTy;
|
||||
}
|
||||
|
||||
if (const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(&FP)) {
|
||||
DecodeArgumentTypes(*FTP, ArgTys);
|
||||
isVarArg = FTP->isVariadic();
|
||||
} else {
|
||||
isVarArg = true;
|
||||
}
|
||||
|
||||
return llvm::FunctionType::get(ResultType, ArgTys, isVarArg);
|
||||
}
|
||||
return GetFunctionType(CGFunctionInfo(cast<FunctionTypeNoProto>(&Ty)));
|
||||
case Type::FunctionProto:
|
||||
return GetFunctionType(CGFunctionInfo(cast<FunctionTypeProto>(&Ty)));
|
||||
|
||||
case Type::ASQual:
|
||||
return
|
||||
|
@ -364,18 +333,6 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
|
|||
return llvm::OpaqueType::get();
|
||||
}
|
||||
|
||||
void CodeGenTypes::DecodeArgumentTypes(const FunctionTypeProto &FTP,
|
||||
std::vector<const llvm::Type*> &ArgTys) {
|
||||
for (unsigned i = 0, e = FTP.getNumArgs(); i != e; ++i) {
|
||||
const llvm::Type *Ty = ConvertTypeRecursive(FTP.getArgType(i));
|
||||
if (Ty->isSingleValueType())
|
||||
ArgTys.push_back(Ty);
|
||||
else
|
||||
// byval arguments are always on the stack, which is addr space #0.
|
||||
ArgTys.push_back(llvm::PointerType::getUnqual(Ty));
|
||||
}
|
||||
}
|
||||
|
||||
/// ConvertTagDeclType - Lay out a tagged decl type like struct or union or
|
||||
/// enum.
|
||||
const llvm::Type *CodeGenTypes::ConvertTagDeclType(const TagDecl *TD) {
|
||||
|
|
|
@ -19,28 +19,30 @@
|
|||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class FunctionType;
|
||||
class Module;
|
||||
class Type;
|
||||
class OpaqueType;
|
||||
class PATypeHolder;
|
||||
class TargetData;
|
||||
class Type;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class TagDecl;
|
||||
class TargetInfo;
|
||||
class QualType;
|
||||
class PointerType;
|
||||
class PointerLikeType;
|
||||
class Type;
|
||||
class FunctionTypeProto;
|
||||
class FieldDecl;
|
||||
class RecordDecl;
|
||||
class FunctionTypeProto;
|
||||
class ObjCInterfaceDecl;
|
||||
class ObjCIvarDecl;
|
||||
class PointerLikeType;
|
||||
class PointerType;
|
||||
class QualType;
|
||||
class RecordDecl;
|
||||
class TagDecl;
|
||||
class TargetInfo;
|
||||
class Type;
|
||||
|
||||
namespace CodeGen {
|
||||
class CGFunctionInfo;
|
||||
class CodeGenTypes;
|
||||
|
||||
/// CGRecordLayout - This class handles struct and union layout info while
|
||||
|
@ -132,15 +134,15 @@ public:
|
|||
/// ConvertType - Convert type T into a llvm::Type.
|
||||
const llvm::Type *ConvertType(QualType T);
|
||||
const llvm::Type *ConvertTypeRecursive(QualType T);
|
||||
/// ConvertReturnType - Convert T into an llvm::Type assuming that it will be
|
||||
/// used as a function return type.
|
||||
const llvm::Type *ConvertReturnType(QualType T);
|
||||
|
||||
/// ConvertTypeForMem - Convert type T into a llvm::Type. This differs from
|
||||
/// ConvertType in that it is used to convert to the memory representation for
|
||||
/// a type. For example, the scalar representation for _Bool is i1, but the
|
||||
/// memory representation is usually i8 or i32, depending on the target.
|
||||
const llvm::Type *ConvertTypeForMem(QualType T);
|
||||
|
||||
/// GetFunctionType - Get the LLVM function type from Info.
|
||||
const llvm::FunctionType *GetFunctionType(const CGFunctionInfo &Info);
|
||||
|
||||
void CollectObjCIvarTypes(ObjCInterfaceDecl *ObjCClass,
|
||||
std::vector<const llvm::Type*> &IvarTypes);
|
||||
|
@ -160,9 +162,6 @@ public:
|
|||
void UpdateCompletedType(const TagDecl *TD);
|
||||
|
||||
public: // These are internal details of CGT that shouldn't be used externally.
|
||||
void DecodeArgumentTypes(const FunctionTypeProto &FTP,
|
||||
std::vector<const llvm::Type*> &ArgTys);
|
||||
|
||||
/// addFieldInfo - Assign field number to field FD.
|
||||
void addFieldInfo(const FieldDecl *FD, unsigned No);
|
||||
|
||||
|
|
Loading…
Reference in New Issue