Skip to content

Commit 6d3eed5

Browse files
authored
Merge pull request #77261 from hjyamauchi/release/6.0
Cherrypick fixes for issue 74866 to release/6.0
2 parents 5aec83c + 36f450c commit 6d3eed5

16 files changed

+299
-34
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ class BridgedDeclBaseName {
8080
BridgedIdentifier Ident;
8181

8282
public:
83+
// Ensure that this struct value type will be indirectly returned on
84+
// Windows ARM64
85+
BridgedDeclBaseName() : Ident() {}
86+
8387
#ifdef USED_IN_CPP_SOURCE
8488
BridgedDeclBaseName(swift::DeclBaseName baseName) : Ident(baseName.Ident) {}
8589

@@ -106,6 +110,10 @@ class BridgedDeclNameRef {
106110
void *_Nonnull opaque;
107111

108112
public:
113+
// Ensure that this struct value type will be indirectly returned on
114+
// Windows ARM64
115+
BridgedDeclNameRef() : opaque() {}
116+
109117
#ifdef USED_IN_CPP_SOURCE
110118
BridgedDeclNameRef(swift::DeclNameRef name) : opaque(name.getOpaqueValue()) {}
111119

@@ -162,6 +170,10 @@ class BridgedASTContext {
162170
swift::ASTContext * _Nonnull Ctx;
163171

164172
public:
173+
// Ensure that this struct value type will be indirectly returned on
174+
// Windows ARM64
175+
BridgedASTContext() : Ctx() {}
176+
165177
#ifdef USED_IN_CPP_SOURCE
166178
SWIFT_UNAVAILABLE("Use init(raw:) instead")
167179
BridgedASTContext(swift::ASTContext &ctx) : Ctx(&ctx) {}
@@ -317,6 +329,10 @@ class BridgedDiagnosticArgument {
317329
int64_t storage[3];
318330

319331
public:
332+
// Ensure that this struct value type will be indirectly returned on
333+
// Windows ARM64
334+
BridgedDiagnosticArgument() {}
335+
320336
#ifdef USED_IN_CPP_SOURCE
321337
BridgedDiagnosticArgument(const swift::DiagnosticArgument &arg) {
322338
*reinterpret_cast<swift::DiagnosticArgument *>(&storage) = arg;
@@ -334,6 +350,10 @@ class BridgedDiagnosticFixIt {
334350
int64_t storage[7];
335351

336352
public:
353+
// Ensure that this struct value type will be indirectly returned on
354+
// Windows ARM64
355+
BridgedDiagnosticFixIt() {}
356+
337357
#ifdef USED_IN_CPP_SOURCE
338358
BridgedDiagnosticFixIt(const swift::DiagnosticInfo::FixIt &fixit){
339359
*reinterpret_cast<swift::DiagnosticInfo::FixIt *>(&storage) = fixit;
@@ -1333,6 +1353,10 @@ class BridgedStmtConditionElement {
13331353
void *_Nonnull Raw;
13341354

13351355
public:
1356+
// Ensure that this struct value type will be indirectly returned on
1357+
// Windows ARM64
1358+
BridgedStmtConditionElement() {}
1359+
13361360
#ifdef USED_IN_CPP_SOURCE
13371361
BridgedStmtConditionElement(swift::StmtConditionElement elem)
13381362
: Raw(elem.getOpaqueValue()) {}

include/swift/Basic/BasicBridging.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@
2323
// Pure bridging mode does not permit including any C++/llvm/swift headers.
2424
// See also the comments for `BRIDGING_MODE` in the top-level CMakeLists.txt file.
2525
//
26+
//
27+
// Note: On Windows ARM64, how a C++ struct/class value type is
28+
// returned is sensitive to conditions including whether a
29+
// user-defined constructor exists, etc. See
30+
// https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#return-values
31+
// So, if a C++ struct/class type is returned as a value between Swift
32+
// and C++, we need to be careful to match the return convention
33+
// matches between the non-USED_IN_CPP_SOURCE (Swift) side and the
34+
// USE_IN_CPP_SOURCE (C++) side.
2635
#include "swift/Basic/BridgedSwiftObject.h"
2736
#include "swift/Basic/Compiler.h"
2837

@@ -228,6 +237,10 @@ class BridgedOwnedString {
228237
size_t Length;
229238

230239
public:
240+
// Ensure that this struct value type will be indirectly returned on
241+
// Windows ARM64
242+
BridgedOwnedString() {}
243+
231244
#ifdef USED_IN_CPP_SOURCE
232245
BridgedOwnedString(const std::string &stringToCopy);
233246

include/swift/Parse/ParseBridging.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ class BridgedLegacyParser {
3030
swift::Parser *_Nonnull const handle;
3131

3232
public:
33+
// Ensure that this struct value type will be indirectly returned on
34+
// Windows ARM64
35+
BridgedLegacyParser() : handle(nullptr) {}
36+
3337
#ifdef USED_IN_CPP_SOURCE
3438
BridgedLegacyParser(swift::Parser &P) : handle(&P) {}
3539

include/swift/SIL/SILBridging.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ struct BridgedResultInfo {
8282
swift::TypeBase * _Nonnull type;
8383
BridgedResultConvention convention;
8484

85+
// Ensure that this struct value type will be indirectly returned on
86+
// Windows ARM64
87+
BridgedResultInfo() {}
88+
8589
#ifdef USED_IN_CPP_SOURCE
8690
inline static BridgedResultConvention
8791
castToResultConvention(swift::ResultConvention convention) {
@@ -99,6 +103,10 @@ struct OptionalBridgedResultInfo {
99103
swift::TypeBase * _Nullable type = nullptr;
100104
BridgedResultConvention convention = BridgedResultConvention::Indirect;
101105

106+
// Ensure that this struct value type will be indirectly returned on
107+
// Windows ARM64
108+
OptionalBridgedResultInfo() {}
109+
102110
#ifdef USED_IN_CPP_SOURCE
103111
OptionalBridgedResultInfo(std::optional<swift::SILResultInfo> resultInfo) {
104112
if (resultInfo) {
@@ -113,6 +121,10 @@ struct OptionalBridgedResultInfo {
113121
struct BridgedResultInfoArray {
114122
BridgedArrayRef resultInfoArray;
115123

124+
// Ensure that this struct value type will be indirectly returned on
125+
// Windows ARM64
126+
BridgedResultInfoArray() {}
127+
116128
#ifdef USED_IN_CPP_SOURCE
117129
BridgedResultInfoArray(llvm::ArrayRef<swift::SILResultInfo> results)
118130
: resultInfoArray(results) {}
@@ -195,6 +207,10 @@ struct BridgedParameterInfo {
195207
struct BridgedParameterInfoArray {
196208
BridgedArrayRef parameterInfoArray;
197209

210+
// Ensure that this struct value type will be indirectly returned on
211+
// Windows ARM64
212+
BridgedParameterInfoArray() {}
213+
198214
#ifdef USED_IN_CPP_SOURCE
199215
BridgedParameterInfoArray(llvm::ArrayRef<swift::SILParameterInfo> parameters)
200216
: parameterInfoArray(parameters) {}
@@ -213,6 +229,10 @@ struct BridgedParameterInfoArray {
213229
struct BridgedYieldInfoArray {
214230
BridgedArrayRef yieldInfoArray;
215231

232+
// Ensure that this struct value type will be indirectly returned on
233+
// Windows ARM64
234+
BridgedYieldInfoArray() {}
235+
216236
#ifdef USED_IN_CPP_SOURCE
217237
BridgedYieldInfoArray(llvm::ArrayRef<swift::SILYieldInfo> yields)
218238
: yieldInfoArray(yields) {}
@@ -303,6 +323,10 @@ struct BridgedType {
303323
struct EnumElementIterator {
304324
uint64_t storage[4];
305325

326+
// Ensure that this struct value type will be indirectly returned on
327+
// Windows ARM64
328+
EnumElementIterator() {}
329+
306330
#ifdef USED_IN_CPP_SOURCE
307331
EnumElementIterator(swift::EnumDecl::ElementRange::iterator i) {
308332
static_assert(sizeof(EnumElementIterator) >= sizeof(swift::EnumDecl::ElementRange::iterator));
@@ -316,6 +340,10 @@ struct BridgedType {
316340
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE EnumElementIterator getNext() const;
317341
};
318342

343+
// Ensure that this struct value type will be indirectly returned on
344+
// Windows ARM64
345+
BridgedType() {}
346+
319347
#ifdef USED_IN_CPP_SOURCE
320348
BridgedType(swift::SILType t) : opaqueValue(t.getOpaqueValue()) {}
321349

@@ -674,6 +702,10 @@ struct BridgedSubstitutionMap {
674702
struct BridgedTypeArray {
675703
BridgedArrayRef typeArray;
676704

705+
// Ensure that this struct value type will be indirectly returned on
706+
// Windows ARM64,
707+
BridgedTypeArray() : typeArray() {}
708+
677709
#ifdef USED_IN_CPP_SOURCE
678710
BridgedTypeArray(llvm::ArrayRef<swift::Type> types) : typeArray(types) {}
679711

@@ -694,6 +726,10 @@ struct BridgedTypeArray {
694726
struct BridgedSILTypeArray {
695727
BridgedArrayRef typeArray;
696728

729+
// Ensure that this struct value type will be indirectly returned on
730+
// Windows ARM64
731+
BridgedSILTypeArray() {}
732+
697733
#ifdef USED_IN_CPP_SOURCE
698734
BridgedSILTypeArray(llvm::ArrayRef<swift::SILType> silTypes)
699735
: typeArray(silTypes) {}
@@ -712,6 +748,10 @@ struct BridgedSILTypeArray {
712748
struct BridgedLocation {
713749
uint64_t storage[3];
714750

751+
// Ensure that this struct value type will be indirectly returned on
752+
// Windows ARM64
753+
BridgedLocation() {}
754+
715755
#ifdef USED_IN_CPP_SOURCE
716756
BridgedLocation(const swift::SILDebugLocation &loc) {
717757
*reinterpret_cast<swift::SILDebugLocation *>(&storage) = loc;
@@ -738,6 +778,10 @@ struct BridgedGenericSpecializationInformation {
738778
struct OptionalBridgedSILDebugVariable {
739779
uint64_t storage[16];
740780

781+
// Ensure that this struct value type will be indirectly returned on
782+
// Windows ARM64
783+
OptionalBridgedSILDebugVariable() {}
784+
741785
#ifdef USED_IN_CPP_SOURCE
742786
using OptionalSILDebugVariable = std::optional<swift::SILDebugVariable>;
743787

include/swift/SILOptimizer/OptimizerBridging.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ struct BridgedCalleeAnalysis {
8585
struct CalleeList {
8686
uint64_t storage[3];
8787

88+
// Ensure that this struct value type will be indirectly returned on
89+
// Windows ARM64
90+
CalleeList() {}
91+
8892
#ifdef USED_IN_CPP_SOURCE
8993
CalleeList(swift::CalleeList list) {
9094
*reinterpret_cast<swift::CalleeList *>(&storage) = list;

lib/ClangImporter/ImportType.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,10 +2204,11 @@ ImportedType ClangImporter::Implementation::importFunctionReturnType(
22042204
// C++ operators +=, -=, *=, /= may return a reference to self. This is not
22052205
// idiomatic in Swift, let's drop these return values.
22062206
clang::OverloadedOperatorKind op = clangDecl->getOverloadedOperator();
2207-
if (op == clang::OverloadedOperatorKind::OO_PlusEqual ||
2208-
op == clang::OverloadedOperatorKind::OO_MinusEqual ||
2209-
op == clang::OverloadedOperatorKind::OO_StarEqual ||
2210-
op == clang::OverloadedOperatorKind::OO_SlashEqual)
2207+
if ((op == clang::OverloadedOperatorKind::OO_PlusEqual ||
2208+
op == clang::OverloadedOperatorKind::OO_MinusEqual ||
2209+
op == clang::OverloadedOperatorKind::OO_StarEqual ||
2210+
op == clang::OverloadedOperatorKind::OO_SlashEqual) &&
2211+
clangDecl->getReturnType()->isReferenceType())
22112212
return {SwiftContext.getVoidType(), false};
22122213

22132214
// Fix up optionality.

lib/IRGen/GenCall.cpp

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,8 @@ static void addIndirectResultAttributes(IRGenModule &IGM,
358358
llvm::AttributeList &attrs,
359359
unsigned paramIndex, bool allowSRet,
360360
llvm::Type *storageType,
361-
const TypeInfo &typeInfo) {
361+
const TypeInfo &typeInfo,
362+
bool useInReg = false) {
362363
llvm::AttrBuilder b(IGM.getLLVMContext());
363364
b.addAttribute(llvm::Attribute::NoAlias);
364365
// Bitwise takable value types are guaranteed not to capture
@@ -368,6 +369,8 @@ static void addIndirectResultAttributes(IRGenModule &IGM,
368369
if (allowSRet) {
369370
assert(storageType);
370371
b.addStructRetAttr(storageType);
372+
if (useInReg)
373+
b.addAttribute(llvm::Attribute::InReg);
371374
}
372375
attrs = attrs.addParamAttributes(IGM.getLLVMContext(), paramIndex, b);
373376
}
@@ -475,7 +478,7 @@ namespace {
475478

476479
private:
477480
const TypeInfo &expand(SILParameterInfo param);
478-
llvm::Type *addIndirectResult(SILType resultType);
481+
llvm::Type *addIndirectResult(SILType resultType, bool useInReg = false);
479482

480483
SILFunctionConventions getSILFuncConventions() const {
481484
return SILFunctionConventions(FnType, IGM.getSILModule());
@@ -533,11 +536,12 @@ namespace {
533536
} // end namespace irgen
534537
} // end namespace swift
535538

536-
llvm::Type *SignatureExpansion::addIndirectResult(SILType resultType) {
539+
llvm::Type *SignatureExpansion::addIndirectResult(SILType resultType,
540+
bool useInReg) {
537541
const TypeInfo &resultTI = IGM.getTypeInfo(resultType);
538542
auto storageTy = resultTI.getStorageType();
539543
addIndirectResultAttributes(IGM, Attrs, ParamIRTypes.size(), claimSRet(),
540-
storageTy, resultTI);
544+
storageTy, resultTI, useInReg);
541545
addPointerParameter(storageTy);
542546
return IGM.VoidTy;
543547
}
@@ -1449,9 +1453,15 @@ void SignatureExpansion::expandExternalSignatureTypes() {
14491453
// Generate function info for this signature.
14501454
auto extInfo = clang::FunctionType::ExtInfo();
14511455

1452-
auto &FI = clang::CodeGen::arrangeFreeFunctionCall(IGM.ClangCodeGen->CGM(),
1453-
clangResultTy, paramTys, extInfo,
1454-
clang::CodeGen::RequiredArgs::All);
1456+
bool isCXXMethod =
1457+
FnType->getRepresentation() == SILFunctionTypeRepresentation::CXXMethod;
1458+
auto &FI = isCXXMethod ?
1459+
clang::CodeGen::arrangeCXXMethodCall(IGM.ClangCodeGen->CGM(),
1460+
clangResultTy, paramTys, extInfo, {},
1461+
clang::CodeGen::RequiredArgs::All) :
1462+
clang::CodeGen::arrangeFreeFunctionCall(IGM.ClangCodeGen->CGM(),
1463+
clangResultTy, paramTys, extInfo, {},
1464+
clang::CodeGen::RequiredArgs::All);
14551465
ForeignInfo.ClangInfo = &FI;
14561466

14571467
assert(FI.arg_size() == paramTys.size() &&
@@ -1573,16 +1583,14 @@ void SignatureExpansion::expandExternalSignatureTypes() {
15731583
if (returnInfo.isIndirect()) {
15741584
auto resultType = getSILFuncConventions().getSingleSILResultType(
15751585
IGM.getMaximalTypeExpansionContext());
1576-
if (IGM.Triple.isWindowsMSVCEnvironment() &&
1577-
FnType->getRepresentation() ==
1578-
SILFunctionTypeRepresentation::CXXMethod) {
1586+
if (returnInfo.isSRetAfterThis()) {
15791587
// Windows ABI places `this` before the
15801588
// returned indirect values.
15811589
emitArg(0);
15821590
firstParamToLowerNormally = 1;
1583-
addIndirectResult(resultType);
1591+
addIndirectResult(resultType, returnInfo.getInReg());
15841592
} else
1585-
addIndirectResult(resultType);
1593+
addIndirectResult(resultType, returnInfo.getInReg());
15861594
}
15871595

15881596
// Use a special IR type for passing block pointers.
@@ -2534,11 +2542,12 @@ class SyncCallEmission final : public CallEmission {
25342542

25352543
// Windows ABI places `this` before the
25362544
// returned indirect values.
2537-
bool isThisFirst = IGF.IGM.Triple.isWindowsMSVCEnvironment();
2538-
if (!isThisFirst)
2545+
auto &returnInfo =
2546+
getCallee().getForeignInfo().ClangInfo->getReturnInfo();
2547+
if (returnInfo.isIndirect() && !returnInfo.isSRetAfterThis())
25392548
passIndirectResults();
25402549
adjusted.add(arg);
2541-
if (isThisFirst)
2550+
if (returnInfo.isIndirect() && returnInfo.isSRetAfterThis())
25422551
passIndirectResults();
25432552
}
25442553

@@ -3115,9 +3124,10 @@ void CallEmission::emitToUnmappedMemory(Address result) {
31153124
assert(LastArgWritten == 1 && "emitting unnaturally to indirect result");
31163125

31173126
Args[0] = result.getAddress();
3118-
if (IGF.IGM.Triple.isWindowsMSVCEnvironment() &&
3119-
getCallee().getRepresentation() ==
3120-
SILFunctionTypeRepresentation::CXXMethod &&
3127+
3128+
auto *FI = getCallee().getForeignInfo().ClangInfo;
3129+
if (FI && FI->getReturnInfo().isIndirect() &&
3130+
FI->getReturnInfo().isSRetAfterThis() &&
31213131
Args[1] == getCallee().getCXXMethodSelf()) {
31223132
// C++ methods in MSVC ABI pass `this` before the
31233133
// indirectly returned value.
@@ -3482,10 +3492,10 @@ void CallEmission::emitToExplosion(Explosion &out, bool isOutlined) {
34823492
emitToMemory(temp, substResultTI, isOutlined);
34833493
return;
34843494
}
3485-
if (IGF.IGM.Triple.isWindowsMSVCEnvironment() &&
3486-
getCallee().getRepresentation() ==
3487-
SILFunctionTypeRepresentation::CXXMethod &&
3488-
substResultType.isVoid()) {
3495+
3496+
auto *FI = getCallee().getForeignInfo().ClangInfo;
3497+
if (FI && FI->getReturnInfo().isIndirect() &&
3498+
FI->getReturnInfo().isSRetAfterThis() && substResultType.isVoid()) {
34893499
// Some C++ methods return a value but are imported as
34903500
// returning `Void` (e.g. `operator +=`). In this case
34913501
// we should allocate the correct temp indirect return
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#ifndef TEST_INTEROP_CXX_CLASS_METHOD_INREG_SRET_H
2+
#define TEST_INTEROP_CXX_CLASS_METHOD_INREG_SRET_H
3+
4+
struct OptionalBridgedBasicBlock {
5+
};
6+
7+
struct BridgedFunction {
8+
OptionalBridgedBasicBlock getFirstBlock() const { return {}; }
9+
};
10+
11+
#endif // TEST_INTEROP_CXX_CLASS_METHOD_INREG_SRET_H

0 commit comments

Comments
 (0)