diff options
-rw-r--r-- | clang/include/clang/CodeGen/CGFunctionInfo.h | 9 | ||||
-rw-r--r-- | clang/include/clang/CodeGen/CodeGenABITypes.h | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGBlocks.cpp | 26 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 50 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDeclCXX.cpp | 8 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjC.cpp | 20 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjCMac.cpp | 27 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenABITypes.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.h | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 39 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp | 35 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp | 5 |
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) |