summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CGCall.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGCall.cpp')
-rw-r--r--lib/CodeGen/CGCall.cpp176
1 files changed, 103 insertions, 73 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index b064c12..072b1f6 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;
OpenPOWER on IntegriCloud