diff --git a/include/swift/SIL/SILBridging.h b/include/swift/SIL/SILBridging.h index 13d028de94647..e7369c0555192 100644 --- a/include/swift/SIL/SILBridging.h +++ b/include/swift/SIL/SILBridging.h @@ -780,6 +780,10 @@ struct BridgedSubstitutionMap { struct BridgedTypeArray { BridgedArrayRef typeArray; + // Ensure that this struct value type will be indirectly returned on + // Windows ARM64, + BridgedTypeArray() : typeArray() {} + #ifdef USED_IN_CPP_SOURCE BridgedTypeArray(llvm::ArrayRef types) : typeArray(types) {} diff --git a/test/Interop/Cxx/class/method/Inputs/module.modulemap b/test/Interop/Cxx/class/method/Inputs/module.modulemap index 20e5779e5a331..ceb26fb064b91 100644 --- a/test/Interop/Cxx/class/method/Inputs/module.modulemap +++ b/test/Interop/Cxx/class/method/Inputs/module.modulemap @@ -14,3 +14,8 @@ module UnsafeProjections { export * } + +module SRetWinARM64 { + header "sret-win-arm64.h" + requires cplusplus +} diff --git a/test/Interop/Cxx/class/method/Inputs/sret-win-arm64.h b/test/Interop/Cxx/class/method/Inputs/sret-win-arm64.h new file mode 100644 index 0000000000000..c9abcc04d6168 --- /dev/null +++ b/test/Interop/Cxx/class/method/Inputs/sret-win-arm64.h @@ -0,0 +1,84 @@ +#ifndef TEST_INTEROP_CXX_CLASS_METHOD_SRET_WIN_ARM64_H +#define TEST_INTEROP_CXX_CLASS_METHOD_SRET_WIN_ARM64_H + +#include + +namespace llvm { + +template +class ArrayRef { +public: + const T *Data = nullptr; + size_t Length = 0; +}; + +} // namespace llvm + +namespace swift { + +class Type { +}; + +class SubstitutionMap { +private: + void *storage = nullptr; + +public: + llvm::ArrayRef getReplacementTypes() const; +}; + +} // namespace swift + +class BridgedArrayRef { +public: + const void * Data; + size_t Length; + + BridgedArrayRef() : Data(nullptr), Length(0) {} + +#ifdef USED_IN_CPP_SOURCE + template + BridgedArrayRef(llvm::ArrayRef arr) + : Data(arr.Data), Length(arr.Length) {} + + template + llvm::ArrayRef unbridged() const { + return {static_cast(Data), Length}; + } +#endif +}; + +struct BridgedSubstitutionMap { + uint64_t storage[1]; + +#ifdef USED_IN_CPP_SOURCE + BridgedSubstitutionMap(swift::SubstitutionMap map) { + *reinterpret_cast(&storage) = map; + } + swift::SubstitutionMap unbridged() const { + return *reinterpret_cast(&storage); + } +#endif + + BridgedSubstitutionMap() {} +}; + +struct BridgedTypeArray { + BridgedArrayRef typeArray; + +#ifdef AFTER_FIX + BridgedTypeArray() : typeArray() {} +#endif + +#ifdef USED_IN_CPP_SOURCE + BridgedTypeArray(llvm::ArrayRef types) : typeArray(types) {} + + llvm::ArrayRef unbridged() const { + return typeArray.unbridged(); + } +#endif + + static BridgedTypeArray fromReplacementTypes(BridgedSubstitutionMap substMap); +}; + +#endif // TEST_INTEROP_CXX_CLASS_METHOD_SRET_WIN_ARM64_H diff --git a/test/Interop/Cxx/class/method/sret-win-arm64.swift b/test/Interop/Cxx/class/method/sret-win-arm64.swift new file mode 100644 index 0000000000000..bd33cd34af01f --- /dev/null +++ b/test/Interop/Cxx/class/method/sret-win-arm64.swift @@ -0,0 +1,31 @@ +// RUN: %target-swift-emit-irgen -I %S/Inputs -cxx-interoperability-mode=default %s | %FileCheck %s -check-prefix=CHECK-before-fix +// RUN: %target-swift-emit-irgen -I %S/Inputs -cxx-interoperability-mode=default %s -Xcc -DAFTER_FIX | %FileCheck %s -check-prefix=CHECK-after-fix + +// REQUIRES: OS=windows-msvc && CPU=aarch64 + +import SRetWinARM64 + +public struct OptionalTypeArray { + private let bridged: BridgedTypeArray + public init(bridged: BridgedTypeArray) { + self.bridged = bridged + } +} + +public struct SubstitutionMap { + public let bridged: BridgedSubstitutionMap + + public var replacementTypes: OptionalTypeArray { + let types = BridgedTypeArray.fromReplacementTypes(bridged) + return OptionalTypeArray(bridged: types) + } +} + +public func test(sm: SubstitutionMap) -> OptionalTypeArray { + return sm.replacementTypes +} + +// Check that BridgedTypeArray is indirectly returned via sret after the fix + +// CHECK-before-fix: declare {{.*}} [2 x i64] @"?fromReplacementTypes@BridgedTypeArray@@SA?AU1@UBridgedSubstitutionMap@@@Z"(i64) +// CHECK-after-fix: declare {{.*}} void @"?fromReplacementTypes@BridgedTypeArray@@SA?AU1@UBridgedSubstitutionMap@@@Z"(ptr inreg sret(%struct.BridgedTypeArray) align 8, i64)