Index: include/clang/CodeGen/CGFunctionInfo.h =================================================================== --- include/clang/CodeGen/CGFunctionInfo.h +++ include/clang/CodeGen/CGFunctionInfo.h @@ -518,6 +518,9 @@ /// Whether this function has nocf_check attribute. unsigned NoCfCheck : 1; + /// Whether the SRet attribute should be suppressed for this function. + unsigned SuppressSRet : 1; + RequiredArgs Required; /// The struct representing all arguments passed in memory. Only used when @@ -605,6 +608,10 @@ /// Whether this function has nocf_check attribute. bool isNoCfCheck() const { return NoCfCheck; } + /// Whether the SRet attribute should be suppresed for this function. + bool isSuppressSRet() const { return SuppressSRet; } + void setSuppressSRet(bool Value) { SuppressSRet = Value; } + /// getASTCallingConvention() - Return the AST-specified calling /// convention. CallingConv getASTCallingConvention() const { Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -825,6 +825,7 @@ FI->NumArgs = argTypes.size(); FI->HasExtParameterInfos = !paramInfos.empty(); FI->getArgsBuffer()[0].type = resultType; + FI->SuppressSRet = 0; for (unsigned i = 0, e = argTypes.size(); i != e; ++i) FI->getArgsBuffer()[i + 1].type = argTypes[i]; for (unsigned i = 0, e = paramInfos.size(); i != e; ++i) @@ -1984,7 +1985,12 @@ // Attach attributes to sret. if (IRFunctionArgs.hasSRetArg()) { llvm::AttrBuilder SRETAttrs; - SRETAttrs.addAttribute(llvm::Attribute::StructRet); + if (FI.isSuppressSRet()) { + const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl(); + if (RD && RD->isPOD()) + SRETAttrs.addAttribute(llvm::Attribute::StructRet); + } else + SRETAttrs.addAttribute(llvm::Attribute::StructRet); hasUsedSRet = true; if (RetAI.getInReg()) SRETAttrs.addAttribute(llvm::Attribute::InReg); Index: lib/CodeGen/TargetInfo.cpp =================================================================== --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -4923,6 +4923,8 @@ if (!::classifyReturnType(getCXXABI(), FI, *this)) FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + FI.setSuppressSRet(Kind == Win64); + for (auto &it : FI.arguments()) it.info = classifyArgumentType(it.type); } Index: test/CodeGen/arm64-microsoft-arguments.cpp =================================================================== --- /dev/null +++ test/CodeGen/arm64-microsoft-arguments.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm \ +// RUN: -x c++ -o - %s | FileCheck %s + +struct pod { int a, b, c, d, e; }; + +struct non_pod { + int a; + non_pod() {} +}; + +struct pod s; +struct non_pod t; + +struct pod bar() { return s; } +struct non_pod foo() { return t; } +// CHECK: define {{.*}} void @{{.*}}bar{{.*}}(%struct.pod* noalias sret %agg.result) +// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* noalias %agg.result) + + +// Check instance methods. +struct pod2 { int x; }; +struct Baz { + pod2 baz() { return pod2 {3}; } +}; + +int qux() { return Baz().baz().x; } +// CHECK: define {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz* %this, %struct.pod2* noalias sret %agg.result)