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:
Daniel Dunbar 2008-09-10 04:01:49 +00:00
parent a72d4aece6
commit 7a95ca3197
8 changed files with 111 additions and 159 deletions

View File

@ -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()) {

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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];

View File

@ -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'

View File

@ -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) {

View File

@ -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);