Skip to content

Commit c91e295

Browse files
authored
Merge pull request swiftlang#79576 from swiftlang/gaborh/fix-consume-calling-conv
[cxx-interop] Fix calling convention for rvalue reference params
2 parents 5bf5d20 + 00fa738 commit c91e295

File tree

6 files changed

+105
-1
lines changed

6 files changed

+105
-1
lines changed

lib/SIL/IR/SILFunctionType.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,9 @@ class Conventions {
12561256
case ValueOwnership::Shared:
12571257
return ParameterConvention::Indirect_In_Guaranteed;
12581258
case ValueOwnership::Owned:
1259+
if (kind == ConventionsKind::CFunction ||
1260+
kind == ConventionsKind::CFunctionType)
1261+
return getIndirectParameter(index, type, substTL);
12591262
return ParameterConvention::Indirect_In;
12601263
}
12611264
llvm_unreachable("unhandled ownership");
@@ -3392,6 +3395,8 @@ static ParameterConvention getIndirectCParameterConvention(clang::QualType type)
33923395
// A trivial const * parameter in C should be considered @in.
33933396
if (importer::isCxxConstReferenceType(type.getTypePtr()))
33943397
return ParameterConvention::Indirect_In_Guaranteed;
3398+
if (type->isRValueReferenceType())
3399+
return ParameterConvention::Indirect_In_CXX;
33953400
if (auto *decl = type->getAsRecordDecl()) {
33963401
if (!decl->isParamDestroyedInCallee())
33973402
return ParameterConvention::Indirect_In_CXX;

lib/SILGen/SILGenApply.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -4655,7 +4655,8 @@ static void emitConsumedLValueRecursive(SILGenFunction &SGF, SILLocation loc,
46554655

46564656
// Load if necessary.
46574657
if (value.getType().isAddress()) {
4658-
if (!param.isIndirectIn() || !SGF.silConv.useLoweredAddresses()) {
4658+
if ((!param.isIndirectIn() && !param.isIndirectInCXX()) ||
4659+
!SGF.silConv.useLoweredAddresses()) {
46594660
value = SGF.B.createFormalAccessLoadTake(loc, value);
46604661

46614662
// If our value is a moveonlywrapped type, unwrap it using owned so that

lib/SILOptimizer/Transforms/CopyForwarding.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ class AnalyzeForwardUse
341341
case SILArgumentConvention::Indirect_In:
342342
return true;
343343
case SILArgumentConvention::Indirect_In_Guaranteed:
344+
case SILArgumentConvention::Indirect_In_CXX:
344345
case SILArgumentConvention::Indirect_Inout:
345346
case SILArgumentConvention::Indirect_InoutAliasable:
346347
return false;
@@ -445,6 +446,7 @@ class AnalyzeBackwardUse
445446
case SILArgumentConvention::Indirect_InoutAliasable:
446447
case SILArgumentConvention::Indirect_In_Guaranteed:
447448
return false;
449+
case SILArgumentConvention::Indirect_In_CXX:
448450
case SILArgumentConvention::Indirect_In:
449451
llvm_unreachable("copy_addr src destroyed without reinitialization");
450452
default:

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

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ module Reference {
33
requires cplusplus
44
}
55

6+
module SpecialMembers {
7+
header "print-special-members.h"
8+
requires cplusplus
9+
}
10+
611
module Closures {
712
header "closures.h"
813
requires cplusplus
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
#include <cstdio>
3+
4+
struct MoveOnly {
5+
int id;
6+
MoveOnly() : id(0) { printf("MoveOnly %d created\n", id); }
7+
MoveOnly(const MoveOnly&) = delete;
8+
MoveOnly(MoveOnly&& other) : id(other.id + 1) { printf("MoveOnly %d move-created\n", id); }
9+
~MoveOnly() { printf("MoveOnly %d destroyed\n", id); }
10+
};
11+
12+
struct Copyable {
13+
int id;
14+
Copyable() : id(0) { printf("Copyable %d created\n", id); }
15+
Copyable(const Copyable& other) : id(other.id + 1) { printf("Copyable %d copy-created\n", id); }
16+
Copyable(Copyable&& other) : id(other.id + 1) { printf("Copyable %d move-created\n", id); }
17+
~Copyable() { printf("Copyable %d destroyed\n", id); }
18+
};
19+
20+
inline void byRValueRef(MoveOnly&& x) {}
21+
inline void byRValueRef(Copyable&& x) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -enable-experimental-cxx-interop -Onone) | %FileCheck -check-prefix=CHECK-DASH-ONONE %s
2+
// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -enable-experimental-cxx-interop -O) | %FileCheck -check-prefix=CHECK-DASH-O %s
3+
//
4+
// REQUIRES: executable_test
5+
6+
import SpecialMembers
7+
8+
func consume(_ x: consuming MoveOnly) {}
9+
func consume(_ x: consuming Copyable) {}
10+
11+
func moveOnly1() {
12+
let x = MoveOnly()
13+
// CHECK-DASH-ONONE: MoveOnly 0 created
14+
// CHECK-DASH-O: MoveOnly 0 created
15+
byRValueRef(consuming: x)
16+
// CHECK-DASH-ONONE-NEXT: MoveOnly 1 move-created
17+
// CHECK-DASH-O-NEXT: MoveOnly 1 move-created
18+
// CHECK-DASH-ONONE-NEXT: MoveOnly 0 destroyed
19+
// CHECK-DASH-O-NEXT: MoveOnly 0 destroyed
20+
// CHECK-DASH-ONONE-NEXT: MoveOnly 1 destroyed
21+
// CHECK-DASH-O-NEXT: MoveOnly 1 destroyed
22+
}
23+
24+
func moveOnly2() {
25+
let x = MoveOnly()
26+
// CHECK-DASH-ONONE-NEXT: MoveOnly 0 created
27+
// CHECK-DASH-O-NEXT: MoveOnly 0 created
28+
consume(x)
29+
// CHECK-DASH-ONONE-NEXT: MoveOnly 1 move-created
30+
// CHECK-DASH-ONONE-NEXT: MoveOnly 0 destroyed
31+
// CHECK-DASH-O-NEXT: MoveOnly 0 destroyed
32+
// CHECK-DASH-ONONE-NEXT: MoveOnly 2 move-created
33+
// CHECK-DASH-ONONE-NEXT: MoveOnly 1 destroyed
34+
// CHECK-DASH-ONONE-NEXT: MoveOnly 2 destroyed
35+
}
36+
37+
func copyable1() {
38+
let x = Copyable()
39+
// CHECK-DASH-ONONE-NEXT: Copyable 0 created
40+
// CHECK-DASH-O-NEXT: Copyable 0 created
41+
byRValueRef(consuming: x)
42+
// CHECK-DASH-ONONE-NEXT: Copyable 1 copy-created
43+
// CHECK-DASH-O-NEXT: Copyable 1 copy-created
44+
// CHECK-DASH-ONONE-NEXT: Copyable 1 destroyed
45+
// CHECK-DASH-O-NEXT: Copyable 1 destroyed
46+
// CHECK-DASH-ONONE-NEXT: Copyable 0 destroyed
47+
// CHECK-DASH-O-NEXT: Copyable 0 destroyed
48+
}
49+
50+
func copyable2() {
51+
let x4 = Copyable()
52+
// CHECK-DASH-ONONE-NEXT: Copyable 0 created
53+
// CHECK-DASH-O-NEXT: Copyable 0 created
54+
consume(x4)
55+
// CHECK-DASH-ONONE-NEXT: Copyable 1 copy-created
56+
// CHECK-DASH-ONONE-NEXT: Copyable 2 move-created
57+
// CHECK-DASH-ONONE-NEXT: Copyable 1 destroyed
58+
// CHECK-DASH-ONONE-NEXT: Copyable 2 destroyed
59+
// CHECK-DASH-ONONE-NEXT: Copyable 0 destroyed
60+
// CHECK-DASH-O-NEXT: Copyable 0 destroyed
61+
}
62+
63+
func main() {
64+
moveOnly1()
65+
moveOnly2()
66+
copyable1()
67+
copyable2()
68+
}
69+
70+
main()

0 commit comments

Comments
 (0)