diff options
Diffstat (limited to 'lib/CodeGen/CGCall.cpp')
| -rw-r--r-- | lib/CodeGen/CGCall.cpp | 176 | 
1 files changed, 103 insertions, 73 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index b064c125ad00..072b1f6585fd 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -41,21 +41,54 @@ static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) {    }  } -const -CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionNoProtoType *FTNP) { -  return getFunctionInfo(FTNP->getResultType(), -                         llvm::SmallVector<QualType, 16>(), -                         FTNP->getCallConv(), FTNP->getNoReturnAttr()); +/// Derives the 'this' type for codegen purposes, i.e. ignoring method +/// qualification. +/// FIXME: address space qualification? +static CanQualType GetThisType(ASTContext &Context, const CXXRecordDecl *RD) { +  QualType RecTy = Context.getTagDeclType(RD)->getCanonicalTypeInternal(); +  return Context.getPointerType(CanQualType::CreateUnsafe(RecTy));  } -const -CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionProtoType *FTP) { -  llvm::SmallVector<QualType, 16> ArgTys; +/// Returns the canonical formal type of the given C++ method. +static CanQual<FunctionProtoType> GetFormalType(const CXXMethodDecl *MD) { +  return MD->getType()->getCanonicalTypeUnqualified() +           .getAs<FunctionProtoType>(); +} + +/// Returns the "extra-canonicalized" return type, which discards +/// qualifiers on the return type.  Codegen doesn't care about them, +/// and it makes ABI code a little easier to be able to assume that +/// all parameter and return types are top-level unqualified. +static CanQualType GetReturnType(QualType RetTy) { +  return RetTy->getCanonicalTypeUnqualified().getUnqualifiedType(); +} + +const CGFunctionInfo & +CodeGenTypes::getFunctionInfo(CanQual<FunctionNoProtoType> FTNP) { +  return getFunctionInfo(FTNP->getResultType().getUnqualifiedType(), +                         llvm::SmallVector<CanQualType, 16>(), +                         FTNP->getCallConv(), +                         FTNP->getNoReturnAttr()); +} + +/// \param Args - contains any initial parameters besides those +///   in the formal type +static const CGFunctionInfo &getFunctionInfo(CodeGenTypes &CGT, +                                  llvm::SmallVectorImpl<CanQualType> &ArgTys, +                                             CanQual<FunctionProtoType> FTP) {    // FIXME: Kill copy.    for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)      ArgTys.push_back(FTP->getArgType(i)); -  return getFunctionInfo(FTP->getResultType(), ArgTys, -                         FTP->getCallConv(), FTP->getNoReturnAttr()); +  CanQualType ResTy = FTP->getResultType().getUnqualifiedType(); +  return CGT.getFunctionInfo(ResTy, ArgTys, +                             FTP->getCallConv(), +                             FTP->getNoReturnAttr()); +} + +const CGFunctionInfo & +CodeGenTypes::getFunctionInfo(CanQual<FunctionProtoType> FTP) { +  llvm::SmallVector<CanQualType, 16> ArgTys; +  return ::getFunctionInfo(*this, ArgTys, FTP);  }  static CallingConv getCallingConventionForDecl(const Decl *D) { @@ -71,67 +104,51 @@ static CallingConv getCallingConventionForDecl(const Decl *D) {  const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXRecordDecl *RD,                                                   const FunctionProtoType *FTP) { -  llvm::SmallVector<QualType, 16> ArgTys; -   +  llvm::SmallVector<CanQualType, 16> ArgTys; +    // Add the 'this' pointer. -  ArgTys.push_back(Context.getPointerType(Context.getTagDeclType(RD))); -   -  for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) -    ArgTys.push_back(FTP->getArgType(i)); -   -  // FIXME: Set calling convention correctly, it needs to be associated with the -  // type somehow. -  return getFunctionInfo(FTP->getResultType(), ArgTys, -                         FTP->getCallConv(), FTP->getNoReturnAttr()); +  ArgTys.push_back(GetThisType(Context, RD)); + +  return ::getFunctionInfo(*this, ArgTys, +              FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>());  }  const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) { -  llvm::SmallVector<QualType, 16> ArgTys; +  llvm::SmallVector<CanQualType, 16> ArgTys; +    // Add the 'this' pointer unless this is a static method.    if (MD->isInstance()) -    ArgTys.push_back(MD->getThisType(Context)); +    ArgTys.push_back(GetThisType(Context, MD->getParent())); -  const FunctionProtoType *FTP = MD->getType()->getAs<FunctionProtoType>(); -  for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) -    ArgTys.push_back(FTP->getArgType(i)); -  return getFunctionInfo(FTP->getResultType(), ArgTys, FTP->getCallConv(), -                         FTP->getNoReturnAttr()); +  return ::getFunctionInfo(*this, ArgTys, GetFormalType(MD));  }  const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXConstructorDecl *D,                                                       CXXCtorType Type) { -  llvm::SmallVector<QualType, 16> ArgTys; +  llvm::SmallVector<CanQualType, 16> ArgTys;    // Add the 'this' pointer. -  ArgTys.push_back(D->getThisType(Context)); +  ArgTys.push_back(GetThisType(Context, D->getParent()));    // Check if we need to add a VTT parameter (which has type void **).    if (Type == Ctor_Base && D->getParent()->getNumVBases() != 0)      ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); -   -  const FunctionProtoType *FTP = D->getType()->getAs<FunctionProtoType>(); -  for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) -    ArgTys.push_back(FTP->getArgType(i)); -  return getFunctionInfo(FTP->getResultType(), ArgTys, FTP->getCallConv(), -                         FTP->getNoReturnAttr()); + +  return ::getFunctionInfo(*this, ArgTys, GetFormalType(D));  }  const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXDestructorDecl *D,                                                      CXXDtorType Type) { -  llvm::SmallVector<QualType, 16> ArgTys; +  llvm::SmallVector<CanQualType, 16> ArgTys;    // Add the 'this' pointer. -  ArgTys.push_back(D->getThisType(Context)); +  ArgTys.push_back(GetThisType(Context, D->getParent()));    // Check if we need to add a VTT parameter (which has type void **).    if (Type == Dtor_Base && D->getParent()->getNumVBases() != 0)      ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); -   -  const FunctionProtoType *FTP = D->getType()->getAs<FunctionProtoType>(); -  for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) -    ArgTys.push_back(FTP->getArgType(i)); -  return getFunctionInfo(FTP->getResultType(), ArgTys, FTP->getCallConv(), -                         FTP->getNoReturnAttr()); + +  return ::getFunctionInfo(*this, ArgTys, GetFormalType(D));  }  const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionDecl *FD) { @@ -139,30 +156,25 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionDecl *FD) {      if (MD->isInstance())        return getFunctionInfo(MD); -  const FunctionType *FTy = FD->getType()->getAs<FunctionType>(); -  if (const FunctionNoProtoType *FNTP = dyn_cast<FunctionNoProtoType>(FTy)) -    return getFunctionInfo(FNTP->getResultType(),  -                           llvm::SmallVector<QualType, 16>(), -                           FNTP->getCallConv(), FNTP->getNoReturnAttr()); -   -  const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy); -  llvm::SmallVector<QualType, 16> ArgTys; -  // FIXME: Kill copy. -  for (unsigned i = 0, e = FPT->getNumArgs(); i != e; ++i) -    ArgTys.push_back(FPT->getArgType(i)); -  return getFunctionInfo(FPT->getResultType(), ArgTys, -                         FPT->getCallConv(), FPT->getNoReturnAttr()); +  CanQualType FTy = FD->getType()->getCanonicalTypeUnqualified(); +  assert(isa<FunctionType>(FTy)); +  if (isa<FunctionNoProtoType>(FTy)) +    return getFunctionInfo(FTy.getAs<FunctionNoProtoType>());   +  assert(isa<FunctionProtoType>(FTy)); +  return getFunctionInfo(FTy.getAs<FunctionProtoType>());  }  const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const ObjCMethodDecl *MD) { -  llvm::SmallVector<QualType, 16> ArgTys; -  ArgTys.push_back(MD->getSelfDecl()->getType()); -  ArgTys.push_back(Context.getObjCSelType()); +  llvm::SmallVector<CanQualType, 16> ArgTys; +  ArgTys.push_back(Context.getCanonicalParamType(MD->getSelfDecl()->getType())); +  ArgTys.push_back(Context.getCanonicalParamType(Context.getObjCSelType()));    // FIXME: Kill copy?    for (ObjCMethodDecl::param_iterator i = MD->param_begin(), -         e = MD->param_end(); i != e; ++i) -    ArgTys.push_back((*i)->getType()); -  return getFunctionInfo(MD->getResultType(), ArgTys, +         e = MD->param_end(); i != e; ++i) { +    ArgTys.push_back(Context.getCanonicalParamType((*i)->getType())); +  } +  return getFunctionInfo(GetReturnType(MD->getResultType()), +                         ArgTys,                           getCallingConventionForDecl(MD),                           /*NoReturn*/ false);  } @@ -185,11 +197,11 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy,                                                      CallingConv CC,                                                      bool NoReturn) {    // FIXME: Kill copy. -  llvm::SmallVector<QualType, 16> ArgTys; +  llvm::SmallVector<CanQualType, 16> ArgTys;    for (CallArgList::const_iterator i = Args.begin(), e = Args.end();         i != e; ++i) -    ArgTys.push_back(i->second); -  return getFunctionInfo(ResTy, ArgTys, CC, NoReturn); +    ArgTys.push_back(Context.getCanonicalParamType(i->second)); +  return getFunctionInfo(GetReturnType(ResTy), ArgTys, CC, NoReturn);  }  const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy, @@ -197,17 +209,23 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy,                                                      CallingConv CC,                                                      bool NoReturn) {    // FIXME: Kill copy. -  llvm::SmallVector<QualType, 16> ArgTys; +  llvm::SmallVector<CanQualType, 16> ArgTys;    for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();         i != e; ++i) -    ArgTys.push_back(i->second); -  return getFunctionInfo(ResTy, ArgTys, CC, NoReturn); +    ArgTys.push_back(Context.getCanonicalParamType(i->second)); +  return getFunctionInfo(GetReturnType(ResTy), ArgTys, CC, NoReturn);  } -const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy, -                                  const llvm::SmallVector<QualType, 16> &ArgTys, +const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy, +                           const llvm::SmallVectorImpl<CanQualType> &ArgTys,                                                      CallingConv CallConv,                                                      bool NoReturn) { +#ifndef NDEBUG +  for (llvm::SmallVectorImpl<CanQualType>::const_iterator +         I = ArgTys.begin(), E = ArgTys.end(); I != E; ++I) +    assert(I->isCanonicalAsParam()); +#endif +    unsigned CC = ClangCallConvToLLVMCallConv(CallConv);    // Lookup or create unique function info. @@ -232,8 +250,8 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy,  CGFunctionInfo::CGFunctionInfo(unsigned _CallingConvention,                                 bool _NoReturn, -                               QualType ResTy, -                               const llvm::SmallVector<QualType, 16> &ArgTys)  +                               CanQualType ResTy, +                               const llvm::SmallVectorImpl<CanQualType> &ArgTys)    : CallingConvention(_CallingConvention),      EffectiveCallingConvention(_CallingConvention),      NoReturn(_NoReturn) @@ -416,6 +434,18 @@ bool CodeGenModule::ReturnTypeUsesSret(const CGFunctionInfo &FI) {    return FI.getReturnInfo().isIndirect();  } +const llvm::FunctionType *CodeGenTypes::GetFunctionType(GlobalDecl GD) { +  const CGFunctionInfo &FI = getFunctionInfo(GD); +   +  // For definition purposes, don't consider a K&R function variadic. +  bool Variadic = false; +  if (const FunctionProtoType *FPT = +        cast<FunctionDecl>(GD.getDecl())->getType()->getAs<FunctionProtoType>()) +    Variadic = FPT->isVariadic(); + +  return GetFunctionType(FI, Variadic); +} +  const llvm::FunctionType *  CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic) {    std::vector<const llvm::Type*> ArgTys;  | 
