Skip to content

Commit 986ea7f

Browse files
committed
Ensure that BridgedTypeArray is indirectly returned
On Windows ARM64, how a struct value type is returned is sensitive to conditions including whether a user-defined constructor exists, etc. See https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#return-values That caused a calling convention mismatch between the non-USED_IN_CPP_SOURCE (Swift) side and the USE_IN_CPP_SOURCE (C++) side and a crash. Add this constructor so that the calling convention matches. This is a fix for the OnoneSimplification crash in and is a partial fix for Cherrypick #76324
1 parent b7dad2a commit 986ea7f

File tree

4 files changed

+124
-0
lines changed

4 files changed

+124
-0
lines changed

include/swift/SIL/SILBridging.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,10 @@ struct BridgedSubstitutionMap {
674674
struct BridgedTypeArray {
675675
BridgedArrayRef typeArray;
676676

677+
// Ensure that this struct value type will be indirectly returned on
678+
// Windows ARM64,
679+
BridgedTypeArray() : typeArray() {}
680+
677681
#ifdef USED_IN_CPP_SOURCE
678682
BridgedTypeArray(llvm::ArrayRef<swift::Type> types) : typeArray(types) {}
679683

test/Interop/Cxx/class/method/Inputs/module.modulemap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,8 @@ module InRegSRet {
1919
header "inreg-sret.h"
2020
requires cplusplus
2121
}
22+
23+
module SRetWinARM64 {
24+
header "sret-win-arm64.h"
25+
requires cplusplus
26+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#ifndef TEST_INTEROP_CXX_CLASS_METHOD_SRET_WIN_ARM64_H
2+
#define TEST_INTEROP_CXX_CLASS_METHOD_SRET_WIN_ARM64_H
3+
4+
#include <stdint.h>
5+
6+
namespace llvm {
7+
8+
template<typename T>
9+
class ArrayRef {
10+
public:
11+
const T *Data = nullptr;
12+
size_t Length = 0;
13+
};
14+
15+
} // namespace llvm
16+
17+
namespace swift {
18+
19+
class Type {
20+
};
21+
22+
class SubstitutionMap {
23+
private:
24+
void *storage = nullptr;
25+
26+
public:
27+
llvm::ArrayRef<Type> getReplacementTypes() const;
28+
};
29+
30+
} // namespace swift
31+
32+
class BridgedArrayRef {
33+
public:
34+
const void * Data;
35+
size_t Length;
36+
37+
BridgedArrayRef() : Data(nullptr), Length(0) {}
38+
39+
#ifdef USED_IN_CPP_SOURCE
40+
template <typename T>
41+
BridgedArrayRef(llvm::ArrayRef<T> arr)
42+
: Data(arr.Data), Length(arr.Length) {}
43+
44+
template <typename T>
45+
llvm::ArrayRef<T> unbridged() const {
46+
return {static_cast<const T *>(Data), Length};
47+
}
48+
#endif
49+
};
50+
51+
struct BridgedSubstitutionMap {
52+
uint64_t storage[1];
53+
54+
#ifdef USED_IN_CPP_SOURCE
55+
BridgedSubstitutionMap(swift::SubstitutionMap map) {
56+
*reinterpret_cast<swift::SubstitutionMap *>(&storage) = map;
57+
}
58+
swift::SubstitutionMap unbridged() const {
59+
return *reinterpret_cast<const swift::SubstitutionMap *>(&storage);
60+
}
61+
#endif
62+
63+
BridgedSubstitutionMap() {}
64+
};
65+
66+
struct BridgedTypeArray {
67+
BridgedArrayRef typeArray;
68+
69+
#ifdef AFTER_FIX
70+
BridgedTypeArray() : typeArray() {}
71+
#endif
72+
73+
#ifdef USED_IN_CPP_SOURCE
74+
BridgedTypeArray(llvm::ArrayRef<swift::Type> types) : typeArray(types) {}
75+
76+
llvm::ArrayRef<swift::Type> unbridged() const {
77+
return typeArray.unbridged<swift::Type>();
78+
}
79+
#endif
80+
81+
static BridgedTypeArray fromReplacementTypes(BridgedSubstitutionMap substMap);
82+
};
83+
84+
#endif // TEST_INTEROP_CXX_CLASS_METHOD_SRET_WIN_ARM64_H
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %target-swift-emit-irgen -I %S/Inputs -cxx-interoperability-mode=default %s | %FileCheck %s -check-prefix=CHECK-before-fix
2+
// RUN: %target-swift-emit-irgen -I %S/Inputs -cxx-interoperability-mode=default %s -Xcc -DAFTER_FIX | %FileCheck %s -check-prefix=CHECK-after-fix
3+
4+
// REQUIRES: OS=windows-msvc && CPU=aarch64
5+
6+
import SRetWinARM64
7+
8+
public struct OptionalTypeArray {
9+
private let bridged: BridgedTypeArray
10+
public init(bridged: BridgedTypeArray) {
11+
self.bridged = bridged
12+
}
13+
}
14+
15+
public struct SubstitutionMap {
16+
public let bridged: BridgedSubstitutionMap
17+
18+
public var replacementTypes: OptionalTypeArray {
19+
let types = BridgedTypeArray.fromReplacementTypes(bridged)
20+
return OptionalTypeArray(bridged: types)
21+
}
22+
}
23+
24+
public func test(sm: SubstitutionMap) -> OptionalTypeArray {
25+
return sm.replacementTypes
26+
}
27+
28+
// Check that BridgedTypeArray is indirectly returned via sret after the fix
29+
30+
// CHECK-before-fix: declare {{.*}} [2 x i64] @"?fromReplacementTypes@BridgedTypeArray@@SA?AU1@UBridgedSubstitutionMap@@@Z"(i64)
31+
// CHECK-after-fix: declare {{.*}} void @"?fromReplacementTypes@BridgedTypeArray@@SA?AU1@UBridgedSubstitutionMap@@@Z"(ptr inreg sret(%struct.BridgedTypeArray) align 8, i64)

0 commit comments

Comments
 (0)