diff --git a/clang/include/clang/CodeGen/SwiftCallingConv.h b/clang/include/clang/CodeGen/SwiftCallingConv.h index d7a0c84699ab0..806c3f13ffe62 100644 --- a/clang/include/clang/CodeGen/SwiftCallingConv.h +++ b/clang/include/clang/CodeGen/SwiftCallingConv.h @@ -88,6 +88,8 @@ class SwiftAggLowering { /// passed indirectly as an argument bool shouldPassIndirectly(bool asReturnValue) const; + bool shouldReturnTypedErrorIndirectly() const; + using EnumerationCallback = llvm::function_ref; diff --git a/clang/lib/CodeGen/ABIInfo.cpp b/clang/lib/CodeGen/ABIInfo.cpp index efcff958ce545..1b8d90e1caa57 100644 --- a/clang/lib/CodeGen/ABIInfo.cpp +++ b/clang/lib/CodeGen/ABIInfo.cpp @@ -275,6 +275,15 @@ bool SwiftABIInfo::shouldPassIndirectly(ArrayRef ComponentTys, return occupiesMoreThan(ComponentTys, /*total=*/4); } +bool SwiftABIInfo::shouldReturnTypedErrorIndirectly( + ArrayRef ComponentTys) const { + for (llvm::Type *type : ComponentTys) { + if (!type->isIntegerTy() && !type->isPointerTy()) + return true; + } + return shouldPassIndirectly(ComponentTys, /*AsReturnValue=*/true); +} + bool SwiftABIInfo::isLegalVectorType(CharUnits VectorSize, llvm::Type *EltTy, unsigned NumElts) const { // The default implementation of this assumes that the target guarantees diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h index ff4ae44a42c33..f0027b7c79e53 100644 --- a/clang/lib/CodeGen/ABIInfo.h +++ b/clang/lib/CodeGen/ABIInfo.h @@ -151,6 +151,9 @@ class SwiftABIInfo { /// Returns true if swifterror is lowered to a register by the target ABI. bool isSwiftErrorInRegister() const { return SwiftErrorInRegister; }; + + virtual bool + shouldReturnTypedErrorIndirectly(ArrayRef ComponentTys) const; }; } // end namespace CodeGen } // end namespace clang diff --git a/clang/lib/CodeGen/SwiftCallingConv.cpp b/clang/lib/CodeGen/SwiftCallingConv.cpp index 16fbf52a517db..8d7888552dd48 100644 --- a/clang/lib/CodeGen/SwiftCallingConv.cpp +++ b/clang/lib/CodeGen/SwiftCallingConv.cpp @@ -644,6 +644,27 @@ bool SwiftAggLowering::shouldPassIndirectly(bool asReturnValue) const { return getSwiftABIInfo(CGM).shouldPassIndirectly(componentTys, asReturnValue); } +bool SwiftAggLowering::shouldReturnTypedErrorIndirectly() const { + assert(Finished && "haven't yet finished lowering"); + + // Empty types don't need to be passed indirectly. + if (Entries.empty()) + return false; + + // Avoid copying the array of types when there's just a single element. + if (Entries.size() == 1) { + return getSwiftABIInfo(CGM).shouldReturnTypedErrorIndirectly( + Entries.back().Type); + } + + SmallVector componentTys; + componentTys.reserve(Entries.size()); + for (auto &entry : Entries) { + componentTys.push_back(entry.Type); + } + return getSwiftABIInfo(CGM).shouldReturnTypedErrorIndirectly(componentTys); +} + bool swiftcall::shouldPassIndirectly(CodeGenModule &CGM, ArrayRef componentTys, bool asReturnValue) {