Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions lib/IRGen/GenCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4551,22 +4551,6 @@ void CallEmission::externalizeArguments(IRGenFunction &IGF, const Callee &callee

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

// In Swift, values that are foreign references types will always be
// pointers. Additionally, we only import functions which use foreign
// reference types indirectly (as pointers), so we know in every case, if
// the argument type is a foreign reference type, the types will match up
// and we can simply use the input directly.
if (paramType.isForeignReferenceType()) {
auto *arg = in.claimNext();
if (isIndirectFormalParameter(params[i - firstParam].getConvention())) {
auto storageTy = IGF.IGM.getTypeInfo(paramType).getStorageType();
arg = IGF.Builder.CreateLoad(arg, storageTy,
IGF.IGM.getPointerAlignment());
}
out.add(arg);
continue;
}

bool passIndirectToDirect = paramInfo.isIndirectInGuaranteed() && paramType.isSensitive();
if (passIndirectToDirect) {
llvm::Value *ptr = in.claimNext();
Expand Down
4 changes: 0 additions & 4 deletions lib/IRGen/GenClangType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@ clang::CanQualType IRGenModule::getClangType(CanType type) {
}

clang::CanQualType IRGenModule::getClangType(SILType type) {
if (type.isForeignReferenceType())
return getClangType(type.getASTType()
->wrapInPointer(PTK_UnsafePointer)
->getCanonicalType());
return getClangType(type.getASTType());
}

Expand Down
7 changes: 6 additions & 1 deletion lib/SIL/IR/SILFunctionType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1537,7 +1537,12 @@ static bool isClangTypeMoreIndirectThanSubstType(TypeConverter &TC,
// Pass C++ const reference types indirectly. Right now there's no way to
// express immutable borrowed params, so we have to have this hack.
// Eventually, we should just express these correctly: rdar://89647503
if (importer::isCxxConstReferenceType(clangTy))
// If this is a const reference to a foreign reference type (const FRT&), this
// is equivalent to a pointer to the foreign reference type, which are passed
// directly.
if (importer::isCxxConstReferenceType(clangTy) &&
!(clangTy->getPointeeType()->getAs<clang::RecordType>() &&
substTy->isForeignReferenceType()))
return true;

if (clangTy->isRValueReferenceType())
Expand Down
5 changes: 5 additions & 0 deletions test/Interop/Cxx/foreign-reference/Inputs/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ module FunctionsAndMethodsReturningFRT {
requires cplusplus
}

module PassAsParameter {
header "pass-as-parameter.h"
requires cplusplus
}

module Printed {
header "printed.h"
requires cplusplus
Expand Down
16 changes: 16 additions & 0 deletions test/Interop/Cxx/foreign-reference/Inputs/pass-as-parameter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
struct __attribute__((swift_attr("import_reference")))
__attribute__((swift_attr("retain:immortal")))
__attribute__((swift_attr("release:immortal"))) IntBox {
int value;
IntBox(int value) : value(value) {}

static IntBox *create(int value) { return new IntBox(value); }
};

inline int extractValueFromPtr(IntBox *b) { return b->value; }
inline int extractValueFromRef(IntBox &b) { return b.value; }
inline int extractValueFromConstRef(const IntBox &b) { return b.value; }
inline int extractValueFromRefToPtr(IntBox *&b) { return b->value; }
inline int extractValueFromRefToConstPtr(IntBox const *&b) { return b->value; }
inline int extractValueFromConstRefToPtr(IntBox *const &b) { return b->value; }
inline int extractValueFromConstRefToConstPtr(IntBox const *const &b) { return b->value; }
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// RUN: %target-swift-emit-irgen %s -I %S/Inputs -cxx-interoperability-mode=upcoming-swift -Xcc -fignore-exceptions -disable-availability-checking | %FileCheck %s

import PassAsParameter

public func refToPtr() {
var a = IntBox.create(123)
let aValue = extractValueFromRefToPtr(&a)
print(aValue)
}
// CHECK: define{{.*}} void {{.*}}refToPtr{{.*}}()
// CHECK: [[PTR_TO_PTR_TO_INT_BOX:%.*]] = alloca %TSo6IntBoxVSg
// CHECK: {{.*}} = call {{.*}} @{{.*}}extractValueFromRefToPtr{{.*}}(ptr [[PTR_TO_PTR_TO_INT_BOX]])

public func constRefToPtr() {
let a = IntBox.create(456)
let aValue = extractValueFromConstRefToPtr(a)
print(aValue)
}
// CHECK: define{{.*}} void {{.*}}constRefToPtr{{.*}}()
// CHECK: [[PTR_TO_PTR_TO_INT_BOX2:%.*]] = alloca %TSo6IntBoxVSg
// CHECK: {{.*}} = call {{.*}} @{{.*}}extractValueFromConstRefToPtr{{.*}}(ptr [[PTR_TO_PTR_TO_INT_BOX2]])

public func refToConstPtr() {
var a = IntBox.create(321)
let aValue = extractValueFromRefToConstPtr(&a)
print(aValue)
}
// CHECK: define{{.*}} void {{.*}}refToConstPtr{{.*}}()
// CHECK: [[PTR_TO_PTR_TO_INT_BOX3:%.*]] = alloca %TSo6IntBoxVSg
// CHECK: {{.*}} = call {{.*}} @{{.*}}extractValueFromRefToConstPtr{{.*}}(ptr [[PTR_TO_PTR_TO_INT_BOX3]])

public func constRefToConstPtr() {
let a = IntBox.create(789)
let aValue = extractValueFromConstRefToConstPtr(a)
print(aValue)
}
// CHECK: define{{.*}} void {{.*}}constRefToConstPtr{{.*}}()
// CHECK: [[PTR_TO_PTR_TO_INT_BOX4:%.*]] = alloca %TSo6IntBoxVSg
// CHECK: {{.*}} = call {{.*}} @{{.*}}extractValueFromConstRefToConstPtr{{.*}}(ptr [[PTR_TO_PTR_TO_INT_BOX4]])
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// RUN: %target-swift-ide-test -print-module -module-to-print=PassAsParameter -I %S/Inputs -source-filename=x -cxx-interoperability-mode=upcoming-swift | %FileCheck %s

// CHECK: func extractValueFromPtr(_ b: IntBox!) -> Int32
// CHECK: func extractValueFromRef(_ b: IntBox) -> Int32
// CHECK: func extractValueFromConstRef(_ b: IntBox) -> Int32
// CHECK: func extractValueFromRefToPtr(_ b: inout IntBox!) -> Int32
// CHECK: func extractValueFromRefToConstPtr(_ b: inout IntBox!) -> Int32
// CHECK: func extractValueFromConstRefToPtr(_ b: IntBox!) -> Int32
// CHECK: func extractValueFromConstRefToConstPtr(_ b: IntBox!) -> Int32
56 changes: 56 additions & 0 deletions test/Interop/Cxx/foreign-reference/pass-as-parameter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// RUN: %target-run-simple-swift(-I %S/Inputs -cxx-interoperability-mode=upcoming-swift -Xfrontend -disable-availability-checking)

// REQUIRES: executable_test

// Temporarily disable when running with an older runtime (rdar://128681137)
// UNSUPPORTED: use_os_stdlib
// UNSUPPORTED: back_deployment_runtime

import StdlibUnittest
import PassAsParameter

var PassAsParameterTestSuite = TestSuite("Passing foreign reference type as parameter")

PassAsParameterTestSuite.test("pass as pointer") {
let a = IntBox.create(123)
let aValue = extractValueFromPtr(a)
expectEqual(aValue, 123)
}

PassAsParameterTestSuite.test("pass as reference") {
let a = IntBox.create(321)!
let aValue = extractValueFromRef(a)
expectEqual(aValue, 321)
}

PassAsParameterTestSuite.test("pass as const reference") {
let a = IntBox.create(321)!
let aValue = extractValueFromConstRef(a)
expectEqual(aValue, 321)
}

PassAsParameterTestSuite.test("pass as reference to pointer") {
var a = IntBox.create(123)
let aValue = extractValueFromRefToPtr(&a)
expectEqual(aValue, 123)
}

PassAsParameterTestSuite.test("pass as const reference to pointer") {
let a = IntBox.create(456)
let aValue = extractValueFromConstRefToPtr(a)
expectEqual(aValue, 456)
}

PassAsParameterTestSuite.test("pass as const reference to pointer") {
var a = IntBox.create(654)
let aValue = extractValueFromConstRefToPtr(a)
expectEqual(aValue, 654)
}

PassAsParameterTestSuite.test("pass as const reference to const pointer") {
var a = IntBox.create(789)
let aValue = extractValueFromConstRefToConstPtr(a)
expectEqual(aValue, 789)
}

runAllTests()
8 changes: 8 additions & 0 deletions test/Interop/Cxx/stdlib/Inputs/std-vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@ class VectorOfStringSubclass : public std::vector<std::string> {
using std::vector<std::string>::vector;
};

struct __attribute__((swift_attr("import_reference")))
__attribute__((swift_attr("retain:immortal")))
__attribute__((swift_attr("release:immortal"))) ImmortalRef {
int value;
static ImmortalRef *create(int value) { return new ImmortalRef({value}); }
};
using VectorOfImmortalRefPtr = std::vector<ImmortalRef *>;

#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_VECTOR_H
9 changes: 9 additions & 0 deletions test/Interop/Cxx/stdlib/use-std-vector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -202,4 +202,13 @@ StdVectorTestSuite.test("VectorOfInt to span").require(.stdlib_6_2).code {
expectEqual(s[2], 3)
}

StdVectorTestSuite.test("VectorOfImmortalRefPtr").require(.stdlib_5_8).code {
guard #available(SwiftStdlib 5.8, *) else { return }

var v = VectorOfImmortalRefPtr()
let i = ImmortalRef.create(123)
v.push_back(i)
expectEqual(v[0]?.value, 123)
}

runAllTests()