Skip to content

Commit cdcdfa9

Browse files
committed
[cxx-interop][windows] additional fix for indirect return in methods for MSVC ABI
Fixes #67685
1 parent eebec9d commit cdcdfa9

File tree

4 files changed

+61
-16
lines changed

4 files changed

+61
-16
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,22 +1424,7 @@ void SignatureExpansion::expandExternalSignatureTypes() {
14241424
attrKindForExtending(signExt));
14251425
}
14261426

1427-
// If we return indirectly, that is the first parameter type.
1428-
if (returnInfo.isIndirect()) {
1429-
addIndirectResult();
1430-
}
1431-
1432-
size_t firstParamToLowerNormally = 0;
1433-
1434-
// Use a special IR type for passing block pointers.
1435-
if (FnType->getRepresentation() == SILFunctionTypeRepresentation::Block) {
1436-
assert(FI.arg_begin()[0].info.isDirect() &&
1437-
"block pointer not passed directly?");
1438-
ParamIRTypes.push_back(IGM.ObjCBlockPtrTy);
1439-
firstParamToLowerNormally = 1;
1440-
}
1441-
1442-
for (auto i : indices(paramTys).slice(firstParamToLowerNormally)) {
1427+
auto emitArg = [&](size_t i) {
14431428
auto &AI = FI.arg_begin()[i].info;
14441429

14451430
// Add a padding argument if required.
@@ -1528,8 +1513,35 @@ void SignatureExpansion::expandExternalSignatureTypes() {
15281513
case clang::CodeGen::ABIArgInfo::InAlloca:
15291514
llvm_unreachable("Need to handle InAlloca during signature expansion");
15301515
}
1516+
};
1517+
1518+
size_t firstParamToLowerNormally = 0;
1519+
1520+
// If we return indirectly, that is the first parameter type.
1521+
if (returnInfo.isIndirect()) {
1522+
if (IGM.Triple.isWindowsMSVCEnvironment() &&
1523+
FnType->getRepresentation() ==
1524+
SILFunctionTypeRepresentation::CXXMethod) {
1525+
// Windows ABI places `this` before the
1526+
// returned indirect values.
1527+
emitArg(0);
1528+
firstParamToLowerNormally = 1;
1529+
addIndirectResult();
1530+
} else
1531+
addIndirectResult();
15311532
}
15321533

1534+
// Use a special IR type for passing block pointers.
1535+
if (FnType->getRepresentation() == SILFunctionTypeRepresentation::Block) {
1536+
assert(FI.arg_begin()[0].info.isDirect() &&
1537+
"block pointer not passed directly?");
1538+
ParamIRTypes.push_back(IGM.ObjCBlockPtrTy);
1539+
firstParamToLowerNormally = 1;
1540+
}
1541+
1542+
for (auto i : indices(paramTys).slice(firstParamToLowerNormally))
1543+
emitArg(i);
1544+
15331545
if (returnInfo.isIndirect() || returnInfo.isIgnore()) {
15341546
ResultIRType = IGM.VoidTy;
15351547
} else {

test/Interop/Cxx/stdlib/Inputs/module.modulemap

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,9 @@ module StdPair {
2727
header "std-pair.h"
2828
requires cplusplus
2929
}
30+
31+
module MsvcUseVecIt {
32+
header "msvc-std-vector-it.h"
33+
requires cplusplus
34+
export *
35+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
#include <vector>
4+
#include <string>
5+
6+
struct FetchProvidersResult {
7+
std::vector<std::string> providers;
8+
};
9+
10+
inline FetchProvidersResult *f() noexcept {
11+
return new FetchProvidersResult();
12+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop -Xcc -std=c++17)
2+
3+
// REQUIRES: OS=windows-msvc
4+
// REQUIRES: executable_test
5+
6+
import MsvcUseVecIt
7+
8+
func test() -> Bool {
9+
let result = f()
10+
let begin = result.pointee.providers.__beginUnsafe()
11+
let end = result.pointee.providers.__endUnsafe()
12+
return begin != end
13+
}
14+
15+
let _ = test()

0 commit comments

Comments
 (0)