mgrang updated this revision to Diff 196109.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D60349/new/
https://reviews.llvm.org/D60349
Files:
include/clang/CodeGen/CGFunctionInfo.h
lib/CodeGen/CGCall.cpp
lib/CodeGen/MicrosoftCXXABI.cpp
lib/Sema/SemaDeclCXX.cpp
test/CodeGen/arm64-microsoft-arguments.cpp
test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
Index: test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
===================================================================
--- test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -164,8 +164,8 @@
// WIN64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
// WIN64: call void @"??1SmallWithDtor@@QEAA@XZ"
// WIN64: }
-// WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i64 %s.coerce) {{.*}} {
-// WOA64: call void @"??1SmallWithDtor@@QEAA@XZ"
+// WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
+// WOA64: call void @"??1SmallWithDtor@@QEAA@XZ"(%struct.SmallWithDtor* %s)
// WOA64: }
// FIXME: MSVC incompatible!
Index: test/CodeGen/arm64-microsoft-arguments.cpp
===================================================================
--- test/CodeGen/arm64-microsoft-arguments.cpp
+++ test/CodeGen/arm64-microsoft-arguments.cpp
@@ -1,25 +1,31 @@
// RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \
// RUN: -x c++ -o - %s | FileCheck %s
-struct pod { int a, b, c, d, e; };
+// Return type size <= 8 bytes.
+// CHECK: define {{.*}} i64 @{{.*}}f1{{.*}}()
+struct S1 { int a, b; };
+S1 f1() { return S1{}; }
-struct non_pod {
- int a;
- non_pod() {}
-};
+// Return type size <= 16 bytes.
+// CHECK: define {{.*}} [2 x i64] @{{.*}}f2{{.*}}()
+struct S2 { int a, b, c, d; };
+S2 f2() { return S2{}; }
-struct pod s;
-struct non_pod t;
+// Return type size > 16 bytes.
+// CHECK: define {{.*}} void @{{.*}}f3{{.*}}(%struct.S3* noalias sret %agg.result)
+struct S3 { int a, b, c, d, e; };
+S3 f3() { return S3{}; }
-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)
+// Instance methods.
+// CHECK: define {{.*}} void @{{.*}}inst@C{{.*}}(%class.C* %this, %class.A* inreg noalias sret %agg.result)
+class A {};
-// Check instance methods.
-struct pod2 { int x; };
-struct Baz { pod2 baz(); };
+class C {
+public:
+ A inst();
+};
-int qux() { return Baz().baz().x; }
-// CHECK: declare {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz*, %struct.pod2*)
+A C::inst() {
+ return A();
+}
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -5902,8 +5902,13 @@
!D->hasNonTrivialCopyConstructorForCall();
if (CCK == TargetInfo::CCK_MicrosoftWin64) {
+ bool isAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
+ if (isAArch64 && !D->isAggregate())
+ return false;
+
bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false;
bool DtorIsTrivialForCall = false;
+ bool CopyAssignmentIsTrivial = !isAArch64;
// If a class has at least one non-deleted, trivial copy constructor, it
// is passed according to the C ABI. Otherwise, it is passed indirectly.
@@ -5929,6 +5934,9 @@
}
}
+ if (isAArch64 && D->needsImplicitCopyAssignment())
+ CopyAssignmentIsTrivial = D->hasTrivialCopyAssignment();
+
if (D->needsImplicitDestructor()) {
if (!D->defaultedDestructorIsDeleted() &&
D->hasTrivialDestructorForCall())
@@ -5939,7 +5947,8 @@
}
// If the copy ctor and dtor are both trivial-for-calls, pass direct.
- if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall)
+ if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall &&
+ CopyAssignmentIsTrivial)
return true;
// If a class has a destructor, we'd really like to pass it indirectly
@@ -5952,7 +5961,7 @@
// Note: This permits small classes with nontrivial destructors to be
// passed in registers, which is non-conforming.
- if (CopyCtorIsTrivial &&
+ if (!isAArch64 && CopyCtorIsTrivial &&
S.getASTContext().getTypeSize(D->getTypeForDecl()) <= 64)
return true;
return false;
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===================================================================
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -52,6 +52,10 @@
bool classifyReturnType(CGFunctionInfo &FI) const override;
+ bool passClassIndirect(const CXXRecordDecl *RD) const {
+ return !canCopyArgument(RD);
+ }
+
RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override;
bool isSRetParameterAfterThis() const override { return true; }
@@ -1056,28 +1060,17 @@
if (!RD)
return false;
- CharUnits Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
- if (FI.isInstanceMethod()) {
- // If it's an instance method, aggregates are always returned indirectly via
- // the second parameter.
- FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
- FI.getReturnInfo().setSRetAfterThis(FI.isInstanceMethod());
+ bool isAArch64 = CGM.getTarget().getTriple().isAArch64();
+ bool isIndirectReturn = isAArch64 ? passClassIndirect(RD) : !RD->isPOD();
+ bool isInstanceMethod = FI.isInstanceMethod();
- // aarch64-windows requires that instance methods use X1 for the return
- // address. So for aarch64-windows we do not mark the
- // return as SRet.
- FI.getReturnInfo().setSuppressSRet(CGM.getTarget().getTriple().getArch() ==
- llvm::Triple::aarch64);
- return true;
- } else if (!RD->isPOD()) {
- // If it's a free function, non-POD types are returned indirectly.
+ if (isIndirectReturn || isInstanceMethod) {
+ CharUnits Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
+ FI.getReturnInfo().setSRetAfterThis(isInstanceMethod);
+
+ FI.getReturnInfo().setInReg(isAArch64);
- // aarch64-windows requires that non-POD, non-instance returns use X0 for
- // the return address. So for aarch64-windows we do not mark the return as
- // SRet.
- FI.getReturnInfo().setSuppressSRet(CGM.getTarget().getTriple().getArch() ==
- llvm::Triple::aarch64);
return true;
}
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -1999,8 +1999,7 @@
// Attach attributes to sret.
if (IRFunctionArgs.hasSRetArg()) {
llvm::AttrBuilder SRETAttrs;
- if (!RetAI.getSuppressSRet())
- SRETAttrs.addAttribute(llvm::Attribute::StructRet);
+ SRETAttrs.addAttribute(llvm::Attribute::StructRet);
hasUsedSRet = true;
if (RetAI.getInReg())
SRETAttrs.addAttribute(llvm::Attribute::InReg);
Index: include/clang/CodeGen/CGFunctionInfo.h
===================================================================
--- include/clang/CodeGen/CGFunctionInfo.h
+++ include/clang/CodeGen/CGFunctionInfo.h
@@ -95,7 +95,6 @@
bool InReg : 1; // isDirect() || isExtend() || isIndirect()
bool CanBeFlattened: 1; // isDirect()
bool SignExt : 1; // isExtend()
- bool SuppressSRet : 1; // isIndirect()
bool canHavePaddingType() const {
return isDirect() || isExtend() || isIndirect() || isExpand();
@@ -111,14 +110,13 @@
}
ABIArgInfo(Kind K)
- : TheKind(K), PaddingInReg(false), InReg(false), SuppressSRet(false) {
+ : TheKind(K), PaddingInReg(false), InReg(false) {
}
public:
ABIArgInfo()
: TypeData(nullptr), PaddingType(nullptr), DirectOffset(0),
- TheKind(Direct), PaddingInReg(false), InReg(false),
- SuppressSRet(false) {}
+ TheKind(Direct), PaddingInReg(false), InReg(false) {}
static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
llvm::Type *Padding = nullptr,
@@ -407,16 +405,6 @@
CanBeFlattened = Flatten;
}
- bool getSuppressSRet() const {
- assert(isIndirect() && "Invalid kind!");
- return SuppressSRet;
- }
-
- void setSuppressSRet(bool Suppress) {
- assert(isIndirect() && "Invalid kind!");
- SuppressSRet = Suppress;
- }
-
void dump() const;
};
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits