Skip to content

Commit 0059c42

Browse files
authored
Merge pull request swiftlang#84090 from egorzhdan/egorzhdan/6.2-frt-indirection
🍒[cxx-interop] Pass foreign reference types with correct level of indirection
2 parents 64e98e6 + da96a98 commit 0059c42

File tree

10 files changed

+148
-21
lines changed

10 files changed

+148
-21
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4551,22 +4551,6 @@ void CallEmission::externalizeArguments(IRGenFunction &IGF, const Callee &callee
45514551

45524552
bool isForwardableArgument = IGF.isForwardableArgument(i - firstParam);
45534553

4554-
// In Swift, values that are foreign references types will always be
4555-
// pointers. Additionally, we only import functions which use foreign
4556-
// reference types indirectly (as pointers), so we know in every case, if
4557-
// the argument type is a foreign reference type, the types will match up
4558-
// and we can simply use the input directly.
4559-
if (paramType.isForeignReferenceType()) {
4560-
auto *arg = in.claimNext();
4561-
if (isIndirectFormalParameter(params[i - firstParam].getConvention())) {
4562-
auto storageTy = IGF.IGM.getTypeInfo(paramType).getStorageType();
4563-
arg = IGF.Builder.CreateLoad(arg, storageTy,
4564-
IGF.IGM.getPointerAlignment());
4565-
}
4566-
out.add(arg);
4567-
continue;
4568-
}
4569-
45704554
bool passIndirectToDirect = paramInfo.isIndirectInGuaranteed() && paramType.isSensitive();
45714555
if (passIndirectToDirect) {
45724556
llvm::Value *ptr = in.claimNext();

lib/IRGen/GenClangType.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@ clang::CanQualType IRGenModule::getClangType(CanType type) {
3232
}
3333

3434
clang::CanQualType IRGenModule::getClangType(SILType type) {
35-
if (type.isForeignReferenceType())
36-
return getClangType(type.getASTType()
37-
->wrapInPointer(PTK_UnsafePointer)
38-
->getCanonicalType());
3935
return getClangType(type.getASTType());
4036
}
4137

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1537,7 +1537,12 @@ static bool isClangTypeMoreIndirectThanSubstType(TypeConverter &TC,
15371537
// Pass C++ const reference types indirectly. Right now there's no way to
15381538
// express immutable borrowed params, so we have to have this hack.
15391539
// Eventually, we should just express these correctly: rdar://89647503
1540-
if (importer::isCxxConstReferenceType(clangTy))
1540+
// If this is a const reference to a foreign reference type (const FRT&), this
1541+
// is equivalent to a pointer to the foreign reference type, which are passed
1542+
// directly.
1543+
if (importer::isCxxConstReferenceType(clangTy) &&
1544+
!(clangTy->getPointeeType()->getAs<clang::RecordType>() &&
1545+
substTy->isForeignReferenceType()))
15411546
return true;
15421547

15431548
if (clangTy->isRValueReferenceType())

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ module FunctionsAndMethodsReturningFRT {
6464
requires cplusplus
6565
}
6666

67+
module PassAsParameter {
68+
header "pass-as-parameter.h"
69+
requires cplusplus
70+
}
71+
6772
module Printed {
6873
header "printed.h"
6974
requires cplusplus
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
struct __attribute__((swift_attr("import_reference")))
2+
__attribute__((swift_attr("retain:immortal")))
3+
__attribute__((swift_attr("release:immortal"))) IntBox {
4+
int value;
5+
IntBox(int value) : value(value) {}
6+
7+
static IntBox *create(int value) { return new IntBox(value); }
8+
};
9+
10+
inline int extractValueFromPtr(IntBox *b) { return b->value; }
11+
inline int extractValueFromRef(IntBox &b) { return b.value; }
12+
inline int extractValueFromConstRef(const IntBox &b) { return b.value; }
13+
inline int extractValueFromRefToPtr(IntBox *&b) { return b->value; }
14+
inline int extractValueFromRefToConstPtr(IntBox const *&b) { return b->value; }
15+
inline int extractValueFromConstRefToPtr(IntBox *const &b) { return b->value; }
16+
inline int extractValueFromConstRefToConstPtr(IntBox const *const &b) { return b->value; }
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %target-swift-emit-irgen %s -I %S/Inputs -cxx-interoperability-mode=upcoming-swift -Xcc -fignore-exceptions -disable-availability-checking | %FileCheck %s
2+
3+
import PassAsParameter
4+
5+
public func refToPtr() {
6+
var a = IntBox.create(123)
7+
let aValue = extractValueFromRefToPtr(&a)
8+
print(aValue)
9+
}
10+
// CHECK: define{{.*}} void {{.*}}refToPtr{{.*}}()
11+
// CHECK: [[PTR_TO_PTR_TO_INT_BOX:%.*]] = alloca %TSo6IntBoxVSg
12+
// CHECK: {{.*}} = call {{.*}} @{{.*}}extractValueFromRefToPtr{{.*}}(ptr [[PTR_TO_PTR_TO_INT_BOX]])
13+
14+
public func constRefToPtr() {
15+
let a = IntBox.create(456)
16+
let aValue = extractValueFromConstRefToPtr(a)
17+
print(aValue)
18+
}
19+
// CHECK: define{{.*}} void {{.*}}constRefToPtr{{.*}}()
20+
// CHECK: [[PTR_TO_PTR_TO_INT_BOX2:%.*]] = alloca %TSo6IntBoxVSg
21+
// CHECK: {{.*}} = call {{.*}} @{{.*}}extractValueFromConstRefToPtr{{.*}}(ptr [[PTR_TO_PTR_TO_INT_BOX2]])
22+
23+
public func refToConstPtr() {
24+
var a = IntBox.create(321)
25+
let aValue = extractValueFromRefToConstPtr(&a)
26+
print(aValue)
27+
}
28+
// CHECK: define{{.*}} void {{.*}}refToConstPtr{{.*}}()
29+
// CHECK: [[PTR_TO_PTR_TO_INT_BOX3:%.*]] = alloca %TSo6IntBoxVSg
30+
// CHECK: {{.*}} = call {{.*}} @{{.*}}extractValueFromRefToConstPtr{{.*}}(ptr [[PTR_TO_PTR_TO_INT_BOX3]])
31+
32+
public func constRefToConstPtr() {
33+
let a = IntBox.create(789)
34+
let aValue = extractValueFromConstRefToConstPtr(a)
35+
print(aValue)
36+
}
37+
// CHECK: define{{.*}} void {{.*}}constRefToConstPtr{{.*}}()
38+
// CHECK: [[PTR_TO_PTR_TO_INT_BOX4:%.*]] = alloca %TSo6IntBoxVSg
39+
// CHECK: {{.*}} = call {{.*}} @{{.*}}extractValueFromConstRefToConstPtr{{.*}}(ptr [[PTR_TO_PTR_TO_INT_BOX4]])
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-swift-ide-test -print-module -module-to-print=PassAsParameter -I %S/Inputs -source-filename=x -cxx-interoperability-mode=upcoming-swift | %FileCheck %s
2+
3+
// CHECK: func extractValueFromPtr(_ b: IntBox!) -> Int32
4+
// CHECK: func extractValueFromRef(_ b: IntBox) -> Int32
5+
// CHECK: func extractValueFromConstRef(_ b: IntBox) -> Int32
6+
// CHECK: func extractValueFromRefToPtr(_ b: inout IntBox!) -> Int32
7+
// CHECK: func extractValueFromRefToConstPtr(_ b: inout IntBox!) -> Int32
8+
// CHECK: func extractValueFromConstRefToPtr(_ b: IntBox!) -> Int32
9+
// CHECK: func extractValueFromConstRefToConstPtr(_ b: IntBox!) -> Int32
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// RUN: %target-run-simple-swift(-I %S/Inputs -cxx-interoperability-mode=upcoming-swift -Xfrontend -disable-availability-checking)
2+
3+
// REQUIRES: executable_test
4+
5+
// Temporarily disable when running with an older runtime (rdar://128681137)
6+
// UNSUPPORTED: use_os_stdlib
7+
// UNSUPPORTED: back_deployment_runtime
8+
9+
import StdlibUnittest
10+
import PassAsParameter
11+
12+
var PassAsParameterTestSuite = TestSuite("Passing foreign reference type as parameter")
13+
14+
PassAsParameterTestSuite.test("pass as pointer") {
15+
let a = IntBox.create(123)
16+
let aValue = extractValueFromPtr(a)
17+
expectEqual(aValue, 123)
18+
}
19+
20+
PassAsParameterTestSuite.test("pass as reference") {
21+
let a = IntBox.create(321)!
22+
let aValue = extractValueFromRef(a)
23+
expectEqual(aValue, 321)
24+
}
25+
26+
PassAsParameterTestSuite.test("pass as const reference") {
27+
let a = IntBox.create(321)!
28+
let aValue = extractValueFromConstRef(a)
29+
expectEqual(aValue, 321)
30+
}
31+
32+
PassAsParameterTestSuite.test("pass as reference to pointer") {
33+
var a = IntBox.create(123)
34+
let aValue = extractValueFromRefToPtr(&a)
35+
expectEqual(aValue, 123)
36+
}
37+
38+
PassAsParameterTestSuite.test("pass as const reference to pointer") {
39+
let a = IntBox.create(456)
40+
let aValue = extractValueFromConstRefToPtr(a)
41+
expectEqual(aValue, 456)
42+
}
43+
44+
PassAsParameterTestSuite.test("pass as const reference to pointer") {
45+
var a = IntBox.create(654)
46+
let aValue = extractValueFromConstRefToPtr(a)
47+
expectEqual(aValue, 654)
48+
}
49+
50+
PassAsParameterTestSuite.test("pass as const reference to const pointer") {
51+
var a = IntBox.create(789)
52+
let aValue = extractValueFromConstRefToConstPtr(a)
53+
expectEqual(aValue, 789)
54+
}
55+
56+
runAllTests()

test/Interop/Cxx/stdlib/Inputs/std-vector.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,12 @@ class VectorOfStringSubclass : public std::vector<std::string> {
2222
using std::vector<std::string>::vector;
2323
};
2424

25+
struct __attribute__((swift_attr("import_reference")))
26+
__attribute__((swift_attr("retain:immortal")))
27+
__attribute__((swift_attr("release:immortal"))) ImmortalRef {
28+
int value;
29+
static ImmortalRef *create(int value) { return new ImmortalRef({value}); }
30+
};
31+
using VectorOfImmortalRefPtr = std::vector<ImmortalRef *>;
32+
2533
#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_VECTOR_H

test/Interop/Cxx/stdlib/use-std-vector.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,4 +202,13 @@ StdVectorTestSuite.test("VectorOfInt to span").require(.stdlib_6_2).code {
202202
expectEqual(s[2], 3)
203203
}
204204

205+
StdVectorTestSuite.test("VectorOfImmortalRefPtr").require(.stdlib_5_8).code {
206+
guard #available(SwiftStdlib 5.8, *) else { return }
207+
208+
var v = VectorOfImmortalRefPtr()
209+
let i = ImmortalRef.create(123)
210+
v.push_back(i)
211+
expectEqual(v[0]?.value, 123)
212+
}
213+
205214
runAllTests()

0 commit comments

Comments
 (0)