From 4982b82b739199de64e852b114cd70b65a29cf8c Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Fri, 31 Jan 2014 22:54:50 +0000 Subject: [ms-cxxabi] Use x86_cdeclmethodcc for __cdecl methods on win32 This fixes PR15768, where the sret parameter and the 'this' parameter are in the wrong order. Instance methods compiled by MSVC never return records in registers, they always return indirectly through an sret pointer. That sret pointer always comes after the 'this' parameter, for both __cdecl and __thiscall methods. Unfortunately, the same is true for other calling conventions, so we'll have to change the overall approach here relatively soon. Reviewers: rsmith Differential Revision: http://llvm-reviews.chandlerc.com/D2664 llvm-svn: 200587 --- clang/lib/CodeGen/CGBlocks.cpp | 26 +++++++----------- clang/lib/CodeGen/CGCall.cpp | 50 ++++++++++++++++++++--------------- clang/lib/CodeGen/CGDeclCXX.cpp | 8 +++--- clang/lib/CodeGen/CGObjC.cpp | 20 ++++++-------- clang/lib/CodeGen/CGObjCMac.cpp | 27 +++++++++++-------- clang/lib/CodeGen/CGStmt.cpp | 4 +-- clang/lib/CodeGen/CodeGenABITypes.cpp | 6 ++--- clang/lib/CodeGen/CodeGenTypes.h | 9 ++++--- clang/lib/CodeGen/TargetInfo.cpp | 39 +++++++++++++++------------ 9 files changed, 96 insertions(+), 93 deletions(-) (limited to 'clang/lib/CodeGen') 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 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 &prefix, CanQual 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 &prefix, CanQual 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 &prefix, CanQual 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(FTy)) { CanQual noProto = FTy.getAs(); - 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 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 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 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 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 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 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(); @@ -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) -- cgit v1.2.3