From: Daniel Dunbar Date: Wed, 10 Sep 2008 04:01:49 +0000 (+0000) Subject: Move FunctionType conversion into CGCall.cpp: X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=45c25ba11cbf8c9a461def5b03f6ee9481e06769;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56047 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 7095165ec8..b684b4463e 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -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(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 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()) { diff --git a/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h index c51c1d0565..ffb9baaebb 100644 --- a/lib/CodeGen/CGCall.h +++ b/lib/CodeGen/CGCall.h @@ -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 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; diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 2641d9d8bd..2c030e9f5a 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -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(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 ArgTy; - for (unsigned i=0 ; iparam_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 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); diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index e3fcbdf11d..d63004f212 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -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 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; } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index e5acc505f5..c0863578e8 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -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()) + if (D->getAttr()) 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]; diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 4976e3474a..b47b1ca97f 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -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' diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index c91f801873..c156f7f7a9 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -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(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 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(&FP)) { - DecodeArgumentTypes(*FTP, ArgTys); - isVarArg = FTP->isVariadic(); - } else { - isVarArg = true; - } - - return llvm::FunctionType::get(ResultType, ArgTys, isVarArg); - } + return GetFunctionType(CGFunctionInfo(cast(&Ty))); + case Type::FunctionProto: + return GetFunctionType(CGFunctionInfo(cast(&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 &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) { diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h index 150e0d615d..d89dfa6d0f 100644 --- a/lib/CodeGen/CodeGenTypes.h +++ b/lib/CodeGen/CodeGenTypes.h @@ -19,28 +19,30 @@ #include 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 &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 &ArgTys); - /// addFieldInfo - Assign field number to field FD. void addFieldInfo(const FieldDecl *FD, unsigned No);