Skip to content

Commit 50ea617

Browse files
committed
Fix the IR gen for C++ method calls and refactor around CGFunctionInfo
In GenCalls, fix the IR gen for C++ method calls as under MSVC as the calling conventions for free functions and C++ methods can be different. This also fixes the missing inreg (on sret arguments) issues on Windows ARM64. In GenCalls, refactor to use CGFunctionInfo returnInfo isSretAfterThis to detect when to reorder the sret and the this arguments under MSVC in GenCalls. In ClagImporter, don't drop the return type for the compound assignment operators such as operator+= when the return value is a reference so that the CGFunctionInfo will be correctly indicate an indirect return for the compound assignment operators.
1 parent 3ab2314 commit 50ea617

File tree

5 files changed

+58
-7
lines changed

5 files changed

+58
-7
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: 9 additions & 3 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() &&
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) {{.*}} %{{.*}})

0 commit comments

Comments
 (0)