summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/CodeGen/CGFunctionInfo.h9
-rw-r--r--clang/include/clang/CodeGen/CodeGenABITypes.h2
-rw-r--r--clang/lib/CodeGen/CGBlocks.cpp26
-rw-r--r--clang/lib/CodeGen/CGCall.cpp50
-rw-r--r--clang/lib/CodeGen/CGDeclCXX.cpp8
-rw-r--r--clang/lib/CodeGen/CGObjC.cpp20
-rw-r--r--clang/lib/CodeGen/CGObjCMac.cpp27
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp4
-rw-r--r--clang/lib/CodeGen/CodeGenABITypes.cpp6
-rw-r--r--clang/lib/CodeGen/CodeGenTypes.h9
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp39
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp35
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp5
13 files changed, 142 insertions, 98 deletions
diff --git a/clang/include/clang/CodeGen/CGFunctionInfo.h b/clang/include/clang/CodeGen/CGFunctionInfo.h
index 30df50d01fe..5fe8bea90a4 100644
--- a/clang/include/clang/CodeGen/CGFunctionInfo.h
+++ b/clang/include/clang/CodeGen/CGFunctionInfo.h
@@ -242,6 +242,9 @@ class CGFunctionInfo : public llvm::FoldingSetNode {
/// The clang::CallingConv that this was originally created with.
unsigned ASTCallingConvention : 8;
+ /// Whether this is an instance method.
+ unsigned InstanceMethod : 1;
+
/// Whether this function is noreturn.
unsigned NoReturn : 1;
@@ -266,6 +269,7 @@ class CGFunctionInfo : public llvm::FoldingSetNode {
public:
static CGFunctionInfo *create(unsigned llvmCC,
+ bool InstanceMethod,
const FunctionType::ExtInfo &extInfo,
CanQualType resultType,
ArrayRef<CanQualType> argTypes,
@@ -284,6 +288,8 @@ public:
bool isVariadic() const { return Required.allowsOptionalArgs(); }
RequiredArgs getRequiredArgs() const { return Required; }
+ bool isInstanceMethod() const { return InstanceMethod; }
+
bool isNoReturn() const { return NoReturn; }
/// In ARC, whether this function retains its return value. This
@@ -326,6 +332,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) {
ID.AddInteger(getASTCallingConvention());
+ ID.AddBoolean(InstanceMethod);
ID.AddBoolean(NoReturn);
ID.AddBoolean(ReturnsRetained);
ID.AddBoolean(HasRegParm);
@@ -336,11 +343,13 @@ public:
it->type.Profile(ID);
}
static void Profile(llvm::FoldingSetNodeID &ID,
+ bool InstanceMethod,
const FunctionType::ExtInfo &info,
RequiredArgs required,
CanQualType resultType,
ArrayRef<CanQualType> argTypes) {
ID.AddInteger(info.getCC());
+ ID.AddBoolean(InstanceMethod);
ID.AddBoolean(info.getNoReturn());
ID.AddBoolean(info.getProducesResult());
ID.AddBoolean(info.getHasRegParm());
diff --git a/clang/include/clang/CodeGen/CodeGenABITypes.h b/clang/include/clang/CodeGen/CodeGenABITypes.h
index 0cefef3d57a..90c74942cb4 100644
--- a/clang/include/clang/CodeGen/CodeGenABITypes.h
+++ b/clang/include/clang/CodeGen/CodeGenABITypes.h
@@ -62,7 +62,7 @@ public:
CanQual<FunctionNoProtoType> Ty);
const CGFunctionInfo &arrangeCXXMethodType(const CXXRecordDecl *RD,
const FunctionProtoType *FTP);
- const CGFunctionInfo &arrangeLLVMFunctionInfo(CanQualType returnType,
+ const CGFunctionInfo &arrangeFreeFunctionCall(CanQualType returnType,
llvm::ArrayRef<CanQualType> argTypes,
FunctionType::ExtInfo info,
RequiredArgs args);
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index e174f8595ba..72828152472 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -1123,7 +1123,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
// Create the function declaration.
const FunctionProtoType *fnType = blockInfo.getBlockExpr()->getFunctionType();
- const CGFunctionInfo &fnInfo = CGM.getTypes().arrangeFunctionDeclaration(
+ const CGFunctionInfo &fnInfo = CGM.getTypes().arrangeFreeFunctionDeclaration(
fnType->getReturnType(), args, fnType->getExtInfo(),
fnType->isVariadic());
if (CGM.ReturnTypeUsesSRet(fnInfo))
@@ -1284,10 +1284,8 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy);
args.push_back(&srcDecl);
- const CGFunctionInfo &FI =
- CGM.getTypes().arrangeFunctionDeclaration(C.VoidTy, args,
- FunctionType::ExtInfo(),
- /*variadic*/ false);
+ const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
+ C.VoidTy, args, FunctionType::ExtInfo(), /*variadic=*/false);
// FIXME: it would be nice if these were mergeable with things with
// identical semantics.
@@ -1459,10 +1457,8 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy);
args.push_back(&srcDecl);
- const CGFunctionInfo &FI =
- CGM.getTypes().arrangeFunctionDeclaration(C.VoidTy, args,
- FunctionType::ExtInfo(),
- /*variadic*/ false);
+ const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
+ C.VoidTy, args, FunctionType::ExtInfo(), /*variadic=*/false);
// FIXME: We'd like to put these into a mergable by content, with
// internal linkage.
@@ -1750,10 +1746,8 @@ generateByrefCopyHelper(CodeGenFunction &CGF,
ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy);
args.push_back(&src);
- const CGFunctionInfo &FI =
- CGF.CGM.getTypes().arrangeFunctionDeclaration(R, args,
- FunctionType::ExtInfo(),
- /*variadic*/ false);
+ const CGFunctionInfo &FI = CGF.CGM.getTypes().arrangeFreeFunctionDeclaration(
+ R, args, FunctionType::ExtInfo(), /*variadic=*/false);
CodeGenTypes &Types = CGF.CGM.getTypes();
llvm::FunctionType *LTy = Types.GetFunctionType(FI);
@@ -1821,10 +1815,8 @@ generateByrefDisposeHelper(CodeGenFunction &CGF,
ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy);
args.push_back(&src);
- const CGFunctionInfo &FI =
- CGF.CGM.getTypes().arrangeFunctionDeclaration(R, args,
- FunctionType::ExtInfo(),
- /*variadic*/ false);
+ const CGFunctionInfo &FI = CGF.CGM.getTypes().arrangeFreeFunctionDeclaration(
+ R, args, FunctionType::ExtInfo(), /*variadic=*/false);
CodeGenTypes &Types = CGF.CGM.getTypes();
llvm::FunctionType *LTy = Types.GetFunctionType(FI);
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 8e676932455..c7290937a6f 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -80,13 +80,15 @@ CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> FTNP) {
// When translating an unprototyped function type, always use a
// variadic type.
return arrangeLLVMFunctionInfo(FTNP->getReturnType().getUnqualifiedType(),
- None, FTNP->getExtInfo(), RequiredArgs(0));
+ false, None, FTNP->getExtInfo(),
+ RequiredArgs(0));
}
/// Arrange the LLVM function layout for a value of the given function
/// type, on top of any implicit parameters already stored. Use the
/// given ExtInfo instead of the ExtInfo from the function type.
static const CGFunctionInfo &arrangeLLVMFunctionInfo(CodeGenTypes &CGT,
+ bool IsInstanceMethod,
SmallVectorImpl<CanQualType> &prefix,
CanQual<FunctionProtoType> FTP,
FunctionType::ExtInfo extInfo) {
@@ -95,7 +97,8 @@ static const CGFunctionInfo &arrangeLLVMFunctionInfo(CodeGenTypes &CGT,
for (unsigned i = 0, e = FTP->getNumParams(); i != e; ++i)
prefix.push_back(FTP->getParamType(i));
CanQualType resultType = FTP->getReturnType().getUnqualifiedType();
- return CGT.arrangeLLVMFunctionInfo(resultType, prefix, extInfo, required);
+ return CGT.arrangeLLVMFunctionInfo(resultType, IsInstanceMethod, prefix,
+ extInfo, required);
}
/// Arrange the argument and result information for a free function (i.e.
@@ -103,7 +106,7 @@ static const CGFunctionInfo &arrangeLLVMFunctionInfo(CodeGenTypes &CGT,
static const CGFunctionInfo &arrangeFreeFunctionType(CodeGenTypes &CGT,
SmallVectorImpl<CanQualType> &prefix,
CanQual<FunctionProtoType> FTP) {
- return arrangeLLVMFunctionInfo(CGT, prefix, FTP, FTP->getExtInfo());
+ return arrangeLLVMFunctionInfo(CGT, false, prefix, FTP, FTP->getExtInfo());
}
/// Arrange the argument and result information for a free function (i.e.
@@ -112,7 +115,7 @@ static const CGFunctionInfo &arrangeCXXMethodType(CodeGenTypes &CGT,
SmallVectorImpl<CanQualType> &prefix,
CanQual<FunctionProtoType> FTP) {
FunctionType::ExtInfo extInfo = FTP->getExtInfo();
- return arrangeLLVMFunctionInfo(CGT, prefix, FTP, extInfo);
+ return arrangeLLVMFunctionInfo(CGT, true, prefix, FTP, extInfo);
}
/// Arrange the argument and result information for a value of the
@@ -220,7 +223,7 @@ CodeGenTypes::arrangeCXXConstructorDeclaration(const CXXConstructorDecl *D,
(D->isVariadic() ? RequiredArgs(argTypes.size()) : RequiredArgs::All);
FunctionType::ExtInfo extInfo = FTP->getExtInfo();
- return arrangeLLVMFunctionInfo(resultType, argTypes, extInfo, required);
+ return arrangeLLVMFunctionInfo(resultType, true, argTypes, extInfo, required);
}
/// Arrange the argument and result information for a declaration,
@@ -243,7 +246,7 @@ CodeGenTypes::arrangeCXXDestructor(const CXXDestructorDecl *D,
assert(FTP->isVariadic() == 0 && "dtor with formal parameters");
FunctionType::ExtInfo extInfo = FTP->getExtInfo();
- return arrangeLLVMFunctionInfo(resultType, argTypes, extInfo,
+ return arrangeLLVMFunctionInfo(resultType, true, argTypes, extInfo,
RequiredArgs::All);
}
@@ -263,7 +266,7 @@ CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) {
// non-variadic type.
if (isa<FunctionNoProtoType>(FTy)) {
CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>();
- return arrangeLLVMFunctionInfo(noProto->getReturnType(), None,
+ return arrangeLLVMFunctionInfo(noProto->getReturnType(), false, None,
noProto->getExtInfo(), RequiredArgs::All);
}
@@ -309,8 +312,8 @@ CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
RequiredArgs required =
(MD->isVariadic() ? RequiredArgs(argTys.size()) : RequiredArgs::All);
- return arrangeLLVMFunctionInfo(GetReturnType(MD->getReturnType()), argTys,
- einfo, required);
+ return arrangeLLVMFunctionInfo(GetReturnType(MD->getReturnType()), false,
+ argTys, einfo, required);
}
const CGFunctionInfo &
@@ -388,8 +391,8 @@ CodeGenTypes::arrangeFreeFunctionCall(QualType resultType,
for (CallArgList::const_iterator i = args.begin(), e = args.end();
i != e; ++i)
argTypes.push_back(Context.getCanonicalParamType(i->Ty));
- return arrangeLLVMFunctionInfo(GetReturnType(resultType), argTypes, info,
- required);
+ return arrangeLLVMFunctionInfo(GetReturnType(resultType), false, argTypes,
+ info, required);
}
/// Arrange a call to a C++ method, passing the given arguments.
@@ -404,15 +407,13 @@ CodeGenTypes::arrangeCXXMethodCall(const CallArgList &args,
argTypes.push_back(Context.getCanonicalParamType(i->Ty));
FunctionType::ExtInfo info = FPT->getExtInfo();
- return arrangeLLVMFunctionInfo(GetReturnType(FPT->getReturnType()), argTypes,
- info, required);
+ return arrangeLLVMFunctionInfo(GetReturnType(FPT->getReturnType()), true,
+ argTypes, info, required);
}
-const CGFunctionInfo &
-CodeGenTypes::arrangeFunctionDeclaration(QualType resultType,
- const FunctionArgList &args,
- const FunctionType::ExtInfo &info,
- bool isVariadic) {
+const CGFunctionInfo &CodeGenTypes::arrangeFreeFunctionDeclaration(
+ QualType resultType, const FunctionArgList &args,
+ const FunctionType::ExtInfo &info, bool isVariadic) {
// FIXME: Kill copy.
SmallVector<CanQualType, 16> argTypes;
for (FunctionArgList::const_iterator i = args.begin(), e = args.end();
@@ -421,12 +422,12 @@ CodeGenTypes::arrangeFunctionDeclaration(QualType resultType,
RequiredArgs required =
(isVariadic ? RequiredArgs(args.size()) : RequiredArgs::All);
- return arrangeLLVMFunctionInfo(GetReturnType(resultType), argTypes, info,
+ return arrangeLLVMFunctionInfo(GetReturnType(resultType), false, argTypes, info,
required);
}
const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() {
- return arrangeLLVMFunctionInfo(getContext().VoidTy, None,
+ return arrangeLLVMFunctionInfo(getContext().VoidTy, false, None,
FunctionType::ExtInfo(), RequiredArgs::All);
}
@@ -435,6 +436,7 @@ const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() {
/// above functions ultimately defer to.
const CGFunctionInfo &
CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType,
+ bool IsInstanceMethod,
ArrayRef<CanQualType> argTypes,
FunctionType::ExtInfo info,
RequiredArgs required) {
@@ -448,7 +450,8 @@ CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType,
// Lookup or create unique function info.
llvm::FoldingSetNodeID ID;
- CGFunctionInfo::Profile(ID, info, required, resultType, argTypes);
+ CGFunctionInfo::Profile(ID, IsInstanceMethod, info, required, resultType,
+ argTypes);
void *insertPos = 0;
CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, insertPos);
@@ -456,7 +459,8 @@ CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType,
return *FI;
// Construct the function info. We co-allocate the ArgInfos.
- FI = CGFunctionInfo::create(CC, info, resultType, argTypes, required);
+ FI = CGFunctionInfo::create(CC, IsInstanceMethod, info, resultType, argTypes,
+ required);
FunctionInfos.InsertNode(FI, insertPos);
bool inserted = FunctionsBeingProcessed.insert(FI); (void)inserted;
@@ -484,6 +488,7 @@ CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType,
}
CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC,
+ bool IsInstanceMethod,
const FunctionType::ExtInfo &info,
CanQualType resultType,
ArrayRef<CanQualType> argTypes,
@@ -494,6 +499,7 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC,
FI->CallingConvention = llvmCC;
FI->EffectiveCallingConvention = llvmCC;
FI->ASTCallingConvention = info.getCC();
+ FI->InstanceMethod = IsInstanceMethod;
FI->NoReturn = info.getNoReturn();
FI->ReturnsRetained = info.getProducesResult();
FI->Required = required;
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index 73f3c987d1b..bc8620d4424 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -502,11 +502,9 @@ llvm::Function *CodeGenFunction::generateDestroyHelper(
FunctionArgList args;
ImplicitParamDecl dst(0, SourceLocation(), 0, getContext().VoidPtrTy);
args.push_back(&dst);
-
- const CGFunctionInfo &FI =
- CGM.getTypes().arrangeFunctionDeclaration(getContext().VoidTy, args,
- FunctionType::ExtInfo(),
- /*variadic*/ false);
+
+ const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
+ getContext().VoidTy, args, FunctionType::ExtInfo(), /*variadic=*/false);
llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
llvm::Function *fn =
CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor");
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp
index ae1349fbd8a..9a0b15d434c 100644
--- a/clang/lib/CodeGen/CGObjC.cpp
+++ b/clang/lib/CodeGen/CGObjC.cpp
@@ -2900,12 +2900,10 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
args.push_back(&dstDecl);
ImplicitParamDecl srcDecl(FD, SourceLocation(), 0, SrcTy);
args.push_back(&srcDecl);
-
- const CGFunctionInfo &FI =
- CGM.getTypes().arrangeFunctionDeclaration(C.VoidTy, args,
- FunctionType::ExtInfo(),
- RequiredArgs::All);
-
+
+ const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
+ C.VoidTy, args, FunctionType::ExtInfo(), RequiredArgs::All);
+
llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
llvm::Function *Fn =
@@ -2981,12 +2979,10 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
args.push_back(&dstDecl);
ImplicitParamDecl srcDecl(FD, SourceLocation(), 0, SrcTy);
args.push_back(&srcDecl);
-
- const CGFunctionInfo &FI =
- CGM.getTypes().arrangeFunctionDeclaration(C.VoidTy, args,
- FunctionType::ExtInfo(),
- RequiredArgs::All);
-
+
+ const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
+ C.VoidTy, args, FunctionType::ExtInfo(), RequiredArgs::All);
+
llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
llvm::Function *Fn =
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index b9d3698046c..eb6ca4cde0f 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -243,8 +243,8 @@ public:
Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Params.push_back(Ctx.BoolTy);
llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(IdType, Params,
- FunctionType::ExtInfo(),
+ Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(IdType, false, Params,
+ FunctionType::ExtInfo(),
RequiredArgs::All));
return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
}
@@ -263,8 +263,9 @@ public:
Params.push_back(Ctx.BoolTy);
Params.push_back(Ctx.BoolTy);
llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
- FunctionType::ExtInfo(),
+ Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false,
+ Params,
+ FunctionType::ExtInfo(),
RequiredArgs::All));
return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
}
@@ -289,7 +290,8 @@ public:
Params.push_back(IdType);
Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
+ Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false,
+ Params,
FunctionType::ExtInfo(),
RequiredArgs::All));
const char *name;
@@ -316,8 +318,9 @@ public:
Params.push_back(Ctx.BoolTy);
Params.push_back(Ctx.BoolTy);
llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
- FunctionType::ExtInfo(),
+ Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false,
+ Params,
+ FunctionType::ExtInfo(),
RequiredArgs::All));
return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
}
@@ -335,8 +338,9 @@ public:
Params.push_back(Ctx.VoidPtrTy);
Params.push_back(Ctx.VoidPtrTy);
llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
- FunctionType::ExtInfo(),
+ Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false,
+ Params,
+ FunctionType::ExtInfo(),
RequiredArgs::All));
return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
}
@@ -348,8 +352,9 @@ public:
SmallVector<CanQualType,1> Params;
Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
- FunctionType::ExtInfo(),
+ Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false,
+ Params,
+ FunctionType::ExtInfo(),
RequiredArgs::All));
return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
}
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index eba0c2dcac7..c8ca4c367be 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -2002,8 +2002,8 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedDecl *CD,
// Create the function declaration.
FunctionType::ExtInfo ExtInfo;
const CGFunctionInfo &FuncInfo =
- CGM.getTypes().arrangeFunctionDeclaration(Ctx.VoidTy, Args, ExtInfo,
- /*IsVariadic=*/false);
+ CGM.getTypes().arrangeFreeFunctionDeclaration(Ctx.VoidTy, Args, ExtInfo,
+ /*IsVariadic=*/false);
llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo);
llvm::Function *F =
diff --git a/clang/lib/CodeGen/CodeGenABITypes.cpp b/clang/lib/CodeGen/CodeGenABITypes.cpp
index 29def56d359..fba7184d55b 100644
--- a/clang/lib/CodeGen/CodeGenABITypes.cpp
+++ b/clang/lib/CodeGen/CodeGenABITypes.cpp
@@ -60,10 +60,10 @@ CodeGenABITypes::arrangeCXXMethodType(const CXXRecordDecl *RD,
}
const CGFunctionInfo &
-CodeGenABITypes::arrangeLLVMFunctionInfo(CanQualType returnType,
+CodeGenABITypes::arrangeFreeFunctionCall(CanQualType returnType,
llvm::ArrayRef<CanQualType> argTypes,
FunctionType::ExtInfo info,
RequiredArgs args) {
- return CGM->getTypes().arrangeLLVMFunctionInfo(returnType, argTypes,
- info, args);
+ return CGM->getTypes().arrangeLLVMFunctionInfo(
+ returnType, /*IsInstanceMethod=*/false, argTypes, info, args);
}
diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h
index 9b7797cb8e2..d74f589a749 100644
--- a/clang/lib/CodeGen/CodeGenTypes.h
+++ b/clang/lib/CodeGen/CodeGenTypes.h
@@ -175,10 +175,10 @@ public:
const CGFunctionInfo &arrangeGlobalDeclaration(GlobalDecl GD);
const CGFunctionInfo &arrangeFunctionDeclaration(const FunctionDecl *FD);
- const CGFunctionInfo &arrangeFunctionDeclaration(QualType ResTy,
- const FunctionArgList &Args,
- const FunctionType::ExtInfo &Info,
- bool isVariadic);
+ const CGFunctionInfo &
+ arrangeFreeFunctionDeclaration(QualType ResTy, const FunctionArgList &Args,
+ const FunctionType::ExtInfo &Info,
+ bool isVariadic);
const CGFunctionInfo &arrangeObjCMethodDeclaration(const ObjCMethodDecl *MD);
const CGFunctionInfo &arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
@@ -216,6 +216,7 @@ public:
///
/// \param argTypes - must all actually be canonical as params
const CGFunctionInfo &arrangeLLVMFunctionInfo(CanQualType returnType,
+ bool IsInstanceMethod,
ArrayRef<CanQualType> argTypes,
FunctionType::ExtInfo info,
RequiredArgs args);
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index c538234d009..bf968f34815 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -552,8 +552,8 @@ class X86_32ABIInfo : public ABIInfo {
return (Size == 8 || Size == 16 || Size == 32 || Size == 64);
}
- static bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context,
- unsigned callingConvention);
+ bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context,
+ bool IsInstanceMethod) const;
/// getIndirectResult - Give a source type \arg Ty, return a suitable result
/// such that the argument will be passed in memory.
@@ -565,7 +565,8 @@ class X86_32ABIInfo : public ABIInfo {
unsigned getTypeStackAlignInBytes(QualType Ty, unsigned Align) const;
Class classify(QualType Ty) const;
- ABIArgInfo classifyReturnType(QualType RetTy, CCState &State) const;
+ ABIArgInfo classifyReturnType(QualType RetTy, CCState &State,
+ bool IsInstanceMethod) const;
ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const;
bool shouldUseInReg(QualType Ty, CCState &State, bool &NeedsPadding) const;
@@ -622,9 +623,8 @@ public:
/// shouldReturnTypeInRegister - Determine if the given type should be
/// passed in a register (for the Darwin ABI).
-bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
- ASTContext &Context,
- unsigned callingConvention) {
+bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, ASTContext &Context,
+ bool IsInstanceMethod) const {
uint64_t Size = Context.getTypeSize(Ty);
// Type must be register sized.
@@ -650,7 +650,7 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
// Arrays are treated like records.
if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty))
return shouldReturnTypeInRegister(AT->getElementType(), Context,
- callingConvention);
+ IsInstanceMethod);
// Otherwise, it must be a record type.
const RecordType *RT = Ty->getAs<RecordType>();
@@ -660,10 +660,8 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
// For thiscall conventions, structures will never be returned in
// a register. This is for compatibility with the MSVC ABI
- if (callingConvention == llvm::CallingConv::X86_ThisCall &&
- RT->isStructureType()) {
+ if (IsWin32StructABI && IsInstanceMethod && RT->isStructureType())
return false;
- }
// Structure types are passed in register if all fields would be
// passed in a register.
@@ -676,8 +674,7 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
continue;
// Check fields recursively.
- if (!shouldReturnTypeInRegister(FD->getType(), Context,
- callingConvention))
+ if (!shouldReturnTypeInRegister(FD->getType(), Context, IsInstanceMethod))
return false;
}
return true;
@@ -693,8 +690,8 @@ ABIArgInfo X86_32ABIInfo::getIndirectReturnResult(CCState &State) const {
return ABIArgInfo::getIndirect(/*Align=*/0, /*ByVal=*/false);
}
-ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
- CCState &State) const {
+ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, CCState &State,
+ bool IsInstanceMethod) const {
if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
@@ -739,8 +736,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
// Small structures which are register sized are generally returned
// in a register.
- if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, getContext(),
- State.CC)) {
+ if (shouldReturnTypeInRegister(RetTy, getContext(), IsInstanceMethod)) {
uint64_t Size = getContext().getTypeSize(RetTy);
// As a special-case, if the struct is a "single-element" struct, and
@@ -987,7 +983,16 @@ void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const {
else
State.FreeRegs = DefaultNumRegisterParameters;
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), State);
+ FI.getReturnInfo() =
+ classifyReturnType(FI.getReturnType(), State, FI.isInstanceMethod());
+
+ // On win32, use the x86_cdeclmethodcc convention for cdecl methods that use
+ // sret. This convention swaps the order of the first two parameters behind
+ // the scenes to match MSVC.
+ if (IsWin32StructABI && FI.isInstanceMethod() &&
+ FI.getCallingConvention() == llvm::CallingConv::C &&
+ FI.getReturnInfo().isIndirect())
+ FI.setEffectiveCallingConvention(llvm::CallingConv::X86_CDeclMethod);
for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
it != ie; ++it)
diff --git a/clang/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp b/clang/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp
new file mode 100644
index 00000000000..fc3e2ca9bb4
--- /dev/null
+++ b/clang/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -triple i386-pc-win32 -emit-llvm %s -o - | FileCheck %s
+
+// PR15768
+
+// A trivial 12 byte struct is returned indirectly.
+struct S {
+ S();
+ int a, b, c;
+};
+
+struct C {
+ S variadic_sret(const char *f, ...);
+ S __cdecl cdecl_sret();
+ S __cdecl byval_and_sret(S a);
+ int c;
+};
+
+S C::variadic_sret(const char *f, ...) { return S(); }
+S C::cdecl_sret() { return S(); }
+S C::byval_and_sret(S a) { return S(); }
+
+// CHECK: define x86_cdeclmethodcc void @"\01?variadic_sret@C@@QAA?AUS@@PBDZZ"(%struct.S* noalias sret %agg.result, %struct.C* %this, i8* %f, ...)
+// CHECK: define x86_cdeclmethodcc void @"\01?cdecl_sret@C@@QAA?AUS@@XZ"(%struct.S* noalias sret %agg.result, %struct.C* %this)
+// CHECK: define x86_cdeclmethodcc void @"\01?byval_and_sret@C@@QAA?AUS@@U2@@Z"(%struct.S* noalias sret %agg.result, %struct.C* %this, %struct.S* byval align 4 %a)
+
+int main() {
+ C c;
+ c.variadic_sret("asdf");
+ c.cdecl_sret();
+ c.byval_and_sret(S());
+}
+// CHECK-LABEL: define i32 @main()
+// CHECK: call x86_cdeclmethodcc void {{.*}} @"\01?variadic_sret@C@@QAA?AUS@@PBDZZ"
+// CHECK: call x86_cdeclmethodcc void @"\01?cdecl_sret@C@@QAA?AUS@@XZ"
+// CHECK: call x86_cdeclmethodcc void @"\01?byval_and_sret@C@@QAA?AUS@@U2@@Z"
diff --git a/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
index 7a494715b58..bff5647fdd5 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -167,10 +167,7 @@ class Class {
Small __cdecl cdecl_method_small() { return Small(); }
// LINUX: define {{.*}} void @_ZN5Class18cdecl_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this)
- // FIXME: Interesting, cdecl returns structures differently for instance
- // methods and global functions. This is not supported by Clang yet...
- // FIXME: Replace WIN32-NOT with WIN32 when this is fixed.
- // WIN32-NOT: define {{.*}} void @"\01?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%struct.Small* noalias sret %agg.result, %class.Class* %this)
+ // WIN32: define {{.*}} void @"\01?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%struct.Small* noalias sret %agg.result, %class.Class* %this)
Big __cdecl cdecl_method_big() { return Big(); }
// LINUX: define {{.*}} void @_ZN5Class16cdecl_method_bigEv(%struct.Big* noalias sret %agg.result, %class.Class* %this)
OpenPOWER on IntegriCloud