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. // 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) CGFunctionInfo::CGFunctionInfo(const FunctionDecl *FD)
: TheDecl(FD)
{ {
const FunctionType *FTy = FD->getType()->getAsFunctionType(); const FunctionType *FTy = FD->getType()->getAsFunctionType();
const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FTy); const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FTy);
ArgTypes.push_back(FTy->getResultType()); ArgTypes.push_back(FTy->getResultType());
if (FTP) if (FTP) {
IsVariadic = FTP->isVariadic();
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
ArgTypes.push_back(FTP->getArgType(i)); ArgTypes.push_back(FTP->getArgType(i));
} else {
IsVariadic = true;
}
} }
CGFunctionInfo::CGFunctionInfo(const ObjCMethodDecl *MD, CGFunctionInfo::CGFunctionInfo(const ObjCMethodDecl *MD,
const ASTContext &Context) const ASTContext &Context)
: TheDecl(MD) : IsVariadic(MD->isVariadic())
{ {
ArgTypes.push_back(MD->getResultType()); ArgTypes.push_back(MD->getResultType());
ArgTypes.push_back(MD->getSelfDecl()->getType()); ArgTypes.push_back(MD->getSelfDecl()->getType());
@ -105,6 +123,12 @@ public:
bool isDefault() const { return TheKind == Default; } bool isDefault() const { return TheKind == Default; }
bool isStructRet() const { return TheKind == StructRet; } bool isStructRet() const { return TheKind == StructRet; }
bool isCoerce() const { return TheKind == Coerce; } 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) { bool CodeGenModule::ReturnTypeUsesSret(QualType RetTy) {
return classifyReturnType(RetTy).isStructRet(); return classifyReturnType(RetTy).isStructRet();
} }
@ -138,8 +205,8 @@ void CodeGenModule::ConstructParamAttrList(const Decl *TargetDecl,
QualType RetTy = *begin; QualType RetTy = *begin;
unsigned Index = 1; unsigned Index = 1;
ABIArgInfo ResAI = classifyReturnType(RetTy); ABIArgInfo RetAI = classifyReturnType(RetTy);
switch (ResAI.getKind()) { switch (RetAI.getKind()) {
case ABIArgInfo::Default: case ABIArgInfo::Default:
if (RetTy->isPromotableIntegerType()) { if (RetTy->isPromotableIntegerType()) {
if (RetTy->isSignedIntegerType()) { if (RetTy->isSignedIntegerType()) {

View File

@ -54,18 +54,18 @@ namespace CodeGen {
/// CGFunctionInfo - Class to encapsulate the information about a /// CGFunctionInfo - Class to encapsulate the information about a
/// function definition. /// function definition.
class CGFunctionInfo { class CGFunctionInfo {
/// TheDecl - The decl we are storing information for. This is bool IsVariadic;
/// either a Function or ObjCMethod Decl.
const Decl *TheDecl;
llvm::SmallVector<QualType, 16> ArgTypes; llvm::SmallVector<QualType, 16> ArgTypes;
public: public:
CGFunctionInfo(const FunctionTypeNoProto *FTNP);
CGFunctionInfo(const FunctionTypeProto *FTP);
CGFunctionInfo(const FunctionDecl *FD); CGFunctionInfo(const FunctionDecl *FD);
CGFunctionInfo(const ObjCMethodDecl *MD, CGFunctionInfo(const ObjCMethodDecl *MD,
const ASTContext &Context); const ASTContext &Context);
const Decl* getDecl() const { return TheDecl; } bool isVariadic() const { return IsVariadic; }
ArgTypeIterator argtypes_begin() const; ArgTypeIterator argtypes_begin() const;
ArgTypeIterator argtypes_end() const; ArgTypeIterator argtypes_end() const;

View File

@ -921,40 +921,15 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
} }
llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD) { llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD) {
const llvm::Type *ReturnTy =
CGM.getTypes().ConvertReturnType(OMD->getResultType());
const ObjCCategoryImplDecl *OCD = const ObjCCategoryImplDecl *OCD =
dyn_cast<ObjCCategoryImplDecl>(OMD->getMethodContext()); dyn_cast<ObjCCategoryImplDecl>(OMD->getMethodContext());
const std::string &CategoryName = OCD ? OCD->getName() : ""; 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 &ClassName = OMD->getClassInterface()->getName();
const std::string &MethodName = OMD->getSelector().getName(); const std::string &MethodName = OMD->getSelector().getName();
unsigned ArgC = OMD->param_size();
bool isClassMethod = !OMD->isInstance(); bool isClassMethod = !OMD->isInstance();
bool isVarArg = OMD->isVariadic();
llvm::SmallVector<const llvm::Type *, 16> ArgTy; const llvm::FunctionType *MethodTy =
for (unsigned i=0 ; i<OMD->param_size() ; i++) { CGM.getTypes().GetFunctionType(CGFunctionInfo(OMD, CGM.getContext()));
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);
std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName, std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName,
MethodName, isClassMethod); MethodName, isClassMethod);

View File

@ -1344,66 +1344,18 @@ llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name,
} }
llvm::Function *CGObjCMac::GenerateMethod(const ObjCMethodDecl *OMD) { 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; std::string Name;
GetNameForMethod(OMD, Name); GetNameForMethod(OMD, Name);
const llvm::FunctionType *MethodTy =
CGM.getTypes().GetFunctionType(CGFunctionInfo(OMD, CGM.getContext()));
llvm::Function *Method = llvm::Function *Method =
llvm::Function::Create(llvm::FunctionType::get(ReturnTy, llvm::Function::Create(MethodTy,
ArgTys,
OMD->isVariadic()),
llvm::GlobalValue::InternalLinkage, llvm::GlobalValue::InternalLinkage,
Name, Name,
&CGM.getModule()); &CGM.getModule());
MethodDefinitions.insert(std::make_pair(OMD, Method)); 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; 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) { llvm::Function *F) {
ParamAttrListType ParamAttrList; ParamAttrListType ParamAttrList;
ConstructParamAttrList(Info.getDecl(), ConstructParamAttrList(D, Info.argtypes_begin(), Info.argtypes_end(),
Info.argtypes_begin(), Info.argtypes_end(),
ParamAttrList); ParamAttrList);
F->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(), F->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(),
ParamAttrList.size())); ParamAttrList.size()));
// Set the appropriate calling convention for the Function. // Set the appropriate calling convention for the Function.
if (Info.getDecl()->getAttr<FastCallAttr>()) if (D->getAttr<FastCallAttr>())
F->setCallingConv(llvm::CallingConv::Fast); F->setCallingConv(llvm::CallingConv::Fast);
} }
@ -245,19 +245,20 @@ void CodeGenModule::SetFunctionAttributesForDefinition(const Decl *D,
void CodeGenModule::SetMethodAttributes(const ObjCMethodDecl *MD, void CodeGenModule::SetMethodAttributes(const ObjCMethodDecl *MD,
llvm::Function *F) { llvm::Function *F) {
SetFunctionParamAttrs(CGFunctionInfo(MD, Context), F); SetFunctionParamAttrs(MD, CGFunctionInfo(MD, Context), F);
SetFunctionAttributesForDefinition(MD, F); SetFunctionAttributesForDefinition(MD, F);
} }
void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD, void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD,
llvm::Function *F) { llvm::Function *F) {
SetFunctionParamAttrs(CGFunctionInfo(FD), F); SetFunctionParamAttrs(FD, CGFunctionInfo(FD), F);
SetGlobalValueAttributes(FD, FD->getStorageClass() == FunctionDecl::Static, SetGlobalValueAttributes(FD, FD->getStorageClass() == FunctionDecl::Static,
FD->isInline(), F, false); FD->isInline(), F, false);
} }
void CodeGenModule::EmitAliases() { void CodeGenModule::EmitAliases() {
for (unsigned i = 0, e = Aliases.size(); i != e; ++i) { for (unsigned i = 0, e = Aliases.size(); i != e; ++i) {
const FunctionDecl *D = Aliases[i]; const FunctionDecl *D = Aliases[i];

View File

@ -217,7 +217,8 @@ public:
void SetMethodAttributes(const ObjCMethodDecl *MD, void SetMethodAttributes(const ObjCMethodDecl *MD,
llvm::Function *F); llvm::Function *F);
void SetFunctionParamAttrs(const CGFunctionInfo &Info, void SetFunctionParamAttrs(const Decl *D,
const CGFunctionInfo &Info,
llvm::Function *F); llvm::Function *F);
/// ReturnTypeUsesSret - Return true iff the given type uses 'sret' /// ReturnTypeUsesSret - Return true iff the given type uses 'sret'

View File

@ -20,6 +20,8 @@
#include "llvm/Module.h" #include "llvm/Module.h"
#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetData.h"
#include "CGCall.h"
using namespace clang; using namespace clang;
using namespace CodeGen; 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) { static const llvm::Type* getTypeForFormat(const llvm::fltSemantics &format) {
if (&format == &llvm::APFloat::IEEEsingle) if (&format == &llvm::APFloat::IEEEsingle)
return llvm::Type::FloatTy; return llvm::Type::FloatTy;
@ -273,35 +268,9 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
VT.getNumElements()); VT.getNumElements());
} }
case Type::FunctionNoProto: case Type::FunctionNoProto:
case Type::FunctionProto: { return GetFunctionType(CGFunctionInfo(cast<FunctionTypeNoProto>(&Ty)));
const FunctionType &FP = cast<FunctionType>(Ty); case Type::FunctionProto:
const llvm::Type *ResultType; return GetFunctionType(CGFunctionInfo(cast<FunctionTypeProto>(&Ty)));
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);
}
case Type::ASQual: case Type::ASQual:
return return
@ -364,18 +333,6 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
return llvm::OpaqueType::get(); 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 /// ConvertTagDeclType - Lay out a tagged decl type like struct or union or
/// enum. /// enum.
const llvm::Type *CodeGenTypes::ConvertTagDeclType(const TagDecl *TD) { const llvm::Type *CodeGenTypes::ConvertTagDeclType(const TagDecl *TD) {

View File

@ -19,28 +19,30 @@
#include <vector> #include <vector>
namespace llvm { namespace llvm {
class FunctionType;
class Module; class Module;
class Type;
class OpaqueType; class OpaqueType;
class PATypeHolder; class PATypeHolder;
class TargetData; class TargetData;
class Type;
} }
namespace clang { namespace clang {
class ASTContext; class ASTContext;
class TagDecl;
class TargetInfo;
class QualType;
class PointerType;
class PointerLikeType;
class Type;
class FunctionTypeProto;
class FieldDecl; class FieldDecl;
class RecordDecl; class FunctionTypeProto;
class ObjCInterfaceDecl; class ObjCInterfaceDecl;
class ObjCIvarDecl; class ObjCIvarDecl;
class PointerLikeType;
class PointerType;
class QualType;
class RecordDecl;
class TagDecl;
class TargetInfo;
class Type;
namespace CodeGen { namespace CodeGen {
class CGFunctionInfo;
class CodeGenTypes; class CodeGenTypes;
/// CGRecordLayout - This class handles struct and union layout info while /// CGRecordLayout - This class handles struct and union layout info while
@ -132,9 +134,6 @@ public:
/// ConvertType - Convert type T into a llvm::Type. /// ConvertType - Convert type T into a llvm::Type.
const llvm::Type *ConvertType(QualType T); const llvm::Type *ConvertType(QualType T);
const llvm::Type *ConvertTypeRecursive(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 /// ConvertTypeForMem - Convert type T into a llvm::Type. This differs from
/// ConvertType in that it is used to convert to the memory representation for /// ConvertType in that it is used to convert to the memory representation for
@ -142,6 +141,9 @@ public:
/// memory representation is usually i8 or i32, depending on the target. /// memory representation is usually i8 or i32, depending on the target.
const llvm::Type *ConvertTypeForMem(QualType T); 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, void CollectObjCIvarTypes(ObjCInterfaceDecl *ObjCClass,
std::vector<const llvm::Type*> &IvarTypes); std::vector<const llvm::Type*> &IvarTypes);
@ -160,9 +162,6 @@ public:
void UpdateCompletedType(const TagDecl *TD); void UpdateCompletedType(const TagDecl *TD);
public: // These are internal details of CGT that shouldn't be used externally. 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. /// addFieldInfo - Assign field number to field FD.
void addFieldInfo(const FieldDecl *FD, unsigned No); void addFieldInfo(const FieldDecl *FD, unsigned No);