Skip to content

Commit 3c50165

Browse files
authored
Merge pull request #76324 from hjyamauchi/issue74866
Fix the IR gen for C++ method calls and refactor around CGFunctionInfo
2 parents 1772f02 + fcc1f6b commit 3c50165

File tree

8 files changed

+78
-27
lines changed

8 files changed

+78
-27
lines changed

lib/ClangImporter/ImportType.cpp

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

22122213
// Fix up optionality.

lib/IRGen/GenCall.cpp

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,9 +1471,15 @@ void SignatureExpansion::expandExternalSignatureTypes() {
14711471
// Generate function info for this signature.
14721472
auto extInfo = clang::FunctionType::ExtInfo();
14731473

1474-
auto &FI = clang::CodeGen::arrangeFreeFunctionCall(IGM.ClangCodeGen->CGM(),
1475-
clangResultTy, paramTys, extInfo,
1476-
clang::CodeGen::RequiredArgs::All);
1474+
bool isCXXMethod =
1475+
FnType->getRepresentation() == SILFunctionTypeRepresentation::CXXMethod;
1476+
auto &FI = isCXXMethod ?
1477+
clang::CodeGen::arrangeCXXMethodCall(IGM.ClangCodeGen->CGM(),
1478+
clangResultTy, paramTys, extInfo, {},
1479+
clang::CodeGen::RequiredArgs::All) :
1480+
clang::CodeGen::arrangeFreeFunctionCall(IGM.ClangCodeGen->CGM(),
1481+
clangResultTy, paramTys, extInfo, {},
1482+
clang::CodeGen::RequiredArgs::All);
14771483
ForeignInfo.ClangInfo = &FI;
14781484

14791485
assert(FI.arg_size() == paramTys.size() &&
@@ -1595,9 +1601,7 @@ void SignatureExpansion::expandExternalSignatureTypes() {
15951601
if (returnInfo.isIndirect()) {
15961602
auto resultType = getSILFuncConventions().getSingleSILResultType(
15971603
IGM.getMaximalTypeExpansionContext());
1598-
if (IGM.Triple.isWindowsMSVCEnvironment() &&
1599-
FnType->getRepresentation() ==
1600-
SILFunctionTypeRepresentation::CXXMethod) {
1604+
if (returnInfo.isSRetAfterThis()) {
16011605
// Windows ABI places `this` before the
16021606
// returned indirect values.
16031607
emitArg(0);
@@ -2577,11 +2581,12 @@ class SyncCallEmission final : public CallEmission {
25772581

25782582
// Windows ABI places `this` before the
25792583
// returned indirect values.
2580-
bool isThisFirst = IGF.IGM.Triple.isWindowsMSVCEnvironment();
2581-
if (!isThisFirst)
2584+
auto &returnInfo =
2585+
getCallee().getForeignInfo().ClangInfo->getReturnInfo();
2586+
if (returnInfo.isIndirect() && !returnInfo.isSRetAfterThis())
25822587
passIndirectResults();
25832588
adjusted.add(arg);
2584-
if (isThisFirst)
2589+
if (returnInfo.isIndirect() && returnInfo.isSRetAfterThis())
25852590
passIndirectResults();
25862591
}
25872592

@@ -3171,9 +3176,10 @@ void CallEmission::emitToUnmappedMemory(Address result) {
31713176
assert(LastArgWritten == 1 && "emitting unnaturally to indirect result");
31723177

31733178
Args[0] = result.getAddress();
3174-
if (IGF.IGM.Triple.isWindowsMSVCEnvironment() &&
3175-
getCallee().getRepresentation() ==
3176-
SILFunctionTypeRepresentation::CXXMethod &&
3179+
3180+
auto *FI = getCallee().getForeignInfo().ClangInfo;
3181+
if (FI && FI->getReturnInfo().isIndirect() &&
3182+
FI->getReturnInfo().isSRetAfterThis() &&
31773183
Args[1] == getCallee().getCXXMethodSelf()) {
31783184
// C++ methods in MSVC ABI pass `this` before the
31793185
// indirectly returned value.
@@ -3566,10 +3572,10 @@ void CallEmission::emitToExplosion(Explosion &out, bool isOutlined) {
35663572
emitToMemory(temp, substResultTI, isOutlined);
35673573
return;
35683574
}
3569-
if (IGF.IGM.Triple.isWindowsMSVCEnvironment() &&
3570-
getCallee().getRepresentation() ==
3571-
SILFunctionTypeRepresentation::CXXMethod &&
3572-
substResultType.isVoid()) {
3575+
3576+
auto *FI = getCallee().getForeignInfo().ClangInfo;
3577+
if (FI && FI->getReturnInfo().isIndirect() &&
3578+
FI->getReturnInfo().isSRetAfterThis() && substResultType.isVoid()) {
35733579
// Some C++ methods return a value but are imported as
35743580
// returning `Void` (e.g. `operator +=`). In this case
35753581
// 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

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 SRetWinARM64 {
1919
header "sret-win-arm64.h"
2020
requires cplusplus
2121
}
22+
23+
module InRegSRet {
24+
header "inreg-sret.h"
25+
requires cplusplus
26+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %target-swift-emit-irgen -I %S/Inputs -cxx-interoperability-mode=default %s | %FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-%target-cpu
2+
3+
// REQUIRES: OS=windows-msvc
4+
5+
import InRegSRet
6+
7+
final public class BasicBlock {
8+
}
9+
10+
extension OptionalBridgedBasicBlock {
11+
public var block: BasicBlock? { nil }
12+
}
13+
14+
final public class Function {
15+
public var bridged: BridgedFunction {
16+
BridgedFunction()
17+
}
18+
19+
public var firstBlock : BasicBlock? { bridged.getFirstBlock().block }
20+
}
21+
22+
// Check that inreg on the sret isn't missing
23+
24+
// CHECK-x86_64: call void @"?getFirstBlock@BridgedFunction@@QEBA?AUOptionalBridgedBasicBlock@@XZ"(ptr {{.*}}, ptr noalias nocapture sret(%TSo25OptionalBridgedBasicBlockV) {{.*}})
25+
// CHECK-aarch64: call void @"?getFirstBlock@BridgedFunction@@QEBA?AUOptionalBridgedBasicBlock@@XZ"(ptr {{.*}}, ptr inreg noalias nocapture sret(%TSo25OptionalBridgedBasicBlockV) {{.*}})
26+
27+
// CHECK-x86_64: define {{.*}} void @"?getFirstBlock@BridgedFunction@@QEBA?AUOptionalBridgedBasicBlock@@XZ"(ptr {{.*}} %{{.*}}, ptr noalias sret(%struct.OptionalBridgedBasicBlock) {{.*}} %{{.*}})
28+
// CHECK-aarch64: define {{.*}} void @"?getFirstBlock@BridgedFunction@@QEBA?AUOptionalBridgedBasicBlock@@XZ"(ptr {{.*}} %{{.*}}, ptr inreg noalias sret(%struct.OptionalBridgedBasicBlock) {{.*}} %{{.*}})

test/Interop/Cxx/class/method/msvc-abi-return-indirect-trivial-record.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,15 @@ public func test(_ result: VecStr) -> CInt {
5757
}
5858

5959
// CHECK: swiftcc i32 @"$s4Test4testys5Int32VSo0014vecstr_yuJCataVF"({{.*}} %[[RESULT:.*]])
60-
// CHECK: call void @"?begin@?$vec@Vstr@@@@QEBA?AVIt@@XZ"(ptr %[[RESULT]], ptr sret{{.*}}
60+
// CHECK: call void @"?begin@?$vec@Vstr@@@@QEBA?AVIt@@XZ"(ptr %[[RESULT]], ptr {{.*}} sret{{.*}}
6161

6262
public func passTempForIndirectRetToVoidCall() {
6363
var lhs = LoadableIntWrapper(value: 2)
6464
let rhs = LoadableIntWrapper(value: 2)
6565
lhs += rhs
6666
}
6767

68-
// CHECK: void @"$sSo18LoadableIntWrapperV2peoiyyABz_ABtFZ"(ptr
69-
// CHECK: %[[OPRESULT:.*]] = alloca %struct.LoadableIntWrapper, align 16
70-
// CHECK-x86_64: call void @"??YLoadableIntWrapper@@QEAA?AU0@U0@@Z"(ptr {{.*}}, ptr sret(%struct.LoadableIntWrapper) %[[OPRESULT]], i32
71-
// CHECK-aarch64: call void @"??YLoadableIntWrapper@@QEAA?AU0@U0@@Z"(ptr {{.*}}, ptr sret(%struct.LoadableIntWrapper) %[[OPRESULT]], i64
68+
// CHECK: i32 @"$sSo18LoadableIntWrapperV2peoiyA2Bz_ABtFZ"(ptr
69+
// CHECK: %[[OPRESULT:.*]] = alloca %TSo18LoadableIntWrapperV, align 4
70+
// CHECK-x86_64: call void @"??YLoadableIntWrapper@@QEAA?AU0@U0@@Z"(ptr {{.*}}, ptr {{.*}} sret(%TSo18LoadableIntWrapperV) %[[OPRESULT]], i32
71+
// CHECK-aarch64: call void @"??YLoadableIntWrapper@@QEAA?AU0@U0@@Z"(ptr {{.*}}, ptr {{.*}} sret(%TSo18LoadableIntWrapperV) %[[OPRESULT]], i64

test/Interop/Cxx/operators/member-inline-irgen.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import MemberInline
55
public func sub(_ lhs: inout LoadableIntWrapper, _ rhs: LoadableIntWrapper) -> LoadableIntWrapper { lhs - rhs }
66

77
// CHECK-SYSV: call [[RESA:i32|i64]] [[NAMEA:@_ZN18LoadableIntWrappermiES_]](ptr {{%[0-9]+}}, {{i32|\[1 x i32\]|i64|%struct.LoadableIntWrapper\* byval\(.*\) align 4}} {{%[0-9]+}})
8-
// CHECK-WIN: call [[RESA:void]] [[NAMEA:@"\?\?GLoadableIntWrapper@@QEAA\?AU0@U0@@Z"]](ptr {{%[0-9]+}}, ptr sret(%struct.LoadableIntWrapper) {{.*}}, i32 {{%[0-9]+}})
8+
// CHECK-WIN: call [[RESA:void]] [[NAMEA:@"\?\?GLoadableIntWrapper@@QEAA\?AU0@U0@@Z"]](ptr {{%[0-9]+}}, ptr {{.*}} sret(%TSo18LoadableIntWrapperV) {{.*}}, i32 {{%[0-9]+}})
99

1010
public func call(_ wrapper: inout LoadableIntWrapper, _ arg: Int32) -> Int32 { wrapper(arg) }
1111

test/Interop/Cxx/operators/member-out-of-line-irgen.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ public func add(_ lhs: inout LoadableIntWrapper, _ rhs: LoadableIntWrapper) -> L
77
// CHECK-SYSV: call {{i32|i64}} [[NAME:@_ZNK18LoadableIntWrapperplES_]](ptr %{{[0-9]+}}, {{i32|\[1 x i32\]|i64|%struct.LoadableIntWrapper\* byval\(.*\)}}{{.*}})
88
// CHECK-SYSV: declare {{.*}}{{i32|i64}} [[NAME]](ptr {{.*}}, {{i32|\[1 x i32\]|i64|%struct.LoadableIntWrapper\* .*byval\(%struct.LoadableIntWrapper\)}}{{.*}})
99

10-
// CHECK-WIN: call void [[NAME:@"\?\?HLoadableIntWrapper@@QEBA\?AU0@U0@@Z"]](ptr %{{[0-9]+}}, ptr sret(%struct.LoadableIntWrapper) {{.*}}, i32 %{{[0-9]+}})
10+
// CHECK-WIN: call void [[NAME:@"\?\?HLoadableIntWrapper@@QEBA\?AU0@U0@@Z"]](ptr %{{[0-9]+}}, ptr {{.*}} sret(%TSo18LoadableIntWrapperV) {{.*}}, i32 %{{[0-9]+}})
1111
// CHECK-WIN: declare dso_local void [[NAME]](ptr {{.*}}, ptr sret(%struct.LoadableIntWrapper) {{.*}}, i32)

0 commit comments

Comments
 (0)