From 34802ed407fef78676ba27212988d904ab53514a Mon Sep 17 00:00:00 2001 From: zoecarver Date: Mon, 13 Jul 2020 19:55:03 -0700 Subject: [PATCH] [cxx-interop] Fix inline operators for address-only types. --- lib/SIL/IR/SILFunctionType.cpp | 16 +++++++++++++++- .../Interop/Cxx/operators/Inputs/member-inline.h | 10 ++++++++++ .../Cxx/operators/member-inline-irgen.swift | 11 +++++++++-- .../member-inline-module-interface.swift | 4 ++++ .../Cxx/operators/member-inline-silgen.swift | 14 ++++++++++++++ .../operators/member-inline-typechecker.swift | 5 ++++- test/Interop/Cxx/operators/member-inline.swift | 8 ++++++++ 7 files changed, 64 insertions(+), 4 deletions(-) diff --git a/lib/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp index bee58d4dac7dd..2329e9efad659 100644 --- a/lib/SIL/IR/SILFunctionType.cpp +++ b/lib/SIL/IR/SILFunctionType.cpp @@ -1572,13 +1572,27 @@ class DestructureInputs { // Add any foreign parameters that are positioned here. maybeAddForeignParameters(); + bool isCxxOperator = origType.isCXXMethod() && + origType.getCXXMethod()->isOverloadedOperator(); + // Process all the non-self parameters. for (unsigned i = 0; i != numNonSelfParams; ++i) { auto ty = params[i].getParameterType(); auto eltPattern = origType.getFunctionParamType(i); auto flags = params[i].getParameterFlags(); + bool forSelf = false; + + // If we have an inline operator, when it was imported, it was turned + // from a method into a static function. So, we need to shift over the + // params by one and use "self" as the first param's type. + if (isCxxOperator) { + if (i == 0) + forSelf = true; + else if (i == 1) + NextOrigParamIndex--; + } - visit(flags.getValueOwnership(), /*forSelf=*/false, eltPattern, ty, + visit(flags.getValueOwnership(), forSelf, eltPattern, ty, flags.isNoDerivative()); } diff --git a/test/Interop/Cxx/operators/Inputs/member-inline.h b/test/Interop/Cxx/operators/Inputs/member-inline.h index 48113df839c2a..f6ec64c037922 100644 --- a/test/Interop/Cxx/operators/Inputs/member-inline.h +++ b/test/Interop/Cxx/operators/Inputs/member-inline.h @@ -12,4 +12,14 @@ struct HasDeletedOperator { void operator!=(HasDeletedOperator) const = delete; }; +struct AddressOnlyIntWrapper { + int value; + AddressOnlyIntWrapper(int value) : value(value) {} + AddressOnlyIntWrapper(AddressOnlyIntWrapper const &other) + : value(other.value) {} + AddressOnlyIntWrapper operator-(AddressOnlyIntWrapper rhs) { + return AddressOnlyIntWrapper(value - rhs.value); + } +}; + #endif diff --git a/test/Interop/Cxx/operators/member-inline-irgen.swift b/test/Interop/Cxx/operators/member-inline-irgen.swift index 7395e06f39504..b7b099e7a06a5 100644 --- a/test/Interop/Cxx/operators/member-inline-irgen.swift +++ b/test/Interop/Cxx/operators/member-inline-irgen.swift @@ -5,7 +5,14 @@ import MemberInline -public func sub(_ lhs: inout LoadableIntWrapper, _ rhs: LoadableIntWrapper) -> LoadableIntWrapper { lhs - rhs } - // CHECK: call [[RES:i32|i64]] [[NAME:@(_ZN18LoadableIntWrappermiES_|"\?\?GLoadableIntWrapper@@QEAA\?AU0@U0@@Z")]](%struct.LoadableIntWrapper* {{%[0-9]+}}, {{i32|\[1 x i32\]|i64|%struct.LoadableIntWrapper\* byval align 4}} {{%[0-9]+}}) + // CHECK: define linkonce_odr [[RES]] [[NAME]](%struct.LoadableIntWrapper* %this, {{i32 %rhs.coerce|\[1 x i32\] %rhs.coerce|i64 %rhs.coerce|%struct.LoadableIntWrapper\* byval\(%struct.LoadableIntWrapper\) align 4 %rhs}}) +public func sub(_ lhs: inout LoadableIntWrapper, _ rhs: LoadableIntWrapper) -> LoadableIntWrapper { lhs - rhs } + +// CHECK-LABEL: define {{.*}}void @"$s4main24subAddressOnlyIntWrapperySo0cdeF0VADz_ADtF" +// CHECK: call void [[NAME:@(_ZN21AddressOnlyIntWrappermiES_|"\?\?GAddressOnlyIntWrapper@@QEAA\?AU0@U0@@Z")]](%struct.AddressOnlyIntWrapper* {{%[0-9]+}}, %struct.AddressOnlyIntWrapper* {{%[0-9]+}}, %struct.AddressOnlyIntWrapper* {{%[0-9]+}}) +// CHECK: ret void + +// CHECK: define linkonce_odr void [[NAME]](%struct.AddressOnlyIntWrapper* {{.*}}%agg.result, %struct.AddressOnlyIntWrapper* %this, %struct.AddressOnlyIntWrapper* %rhs) +public func subAddressOnlyIntWrapper(_ lhs: inout AddressOnlyIntWrapper, _ rhs: AddressOnlyIntWrapper) -> AddressOnlyIntWrapper { lhs - rhs } diff --git a/test/Interop/Cxx/operators/member-inline-module-interface.swift b/test/Interop/Cxx/operators/member-inline-module-interface.swift index 91d84ca87022e..82c425f52a542 100644 --- a/test/Interop/Cxx/operators/member-inline-module-interface.swift +++ b/test/Interop/Cxx/operators/member-inline-module-interface.swift @@ -6,3 +6,7 @@ // CHECK: struct HasDeletedOperator { // CHECK: } + +// CHECK: struct AddressOnlyIntWrapper { +// CHECK: static func - (lhs: inout AddressOnlyIntWrapper, rhs: AddressOnlyIntWrapper) -> AddressOnlyIntWrapper +// CHECK: } diff --git a/test/Interop/Cxx/operators/member-inline-silgen.swift b/test/Interop/Cxx/operators/member-inline-silgen.swift index c9e3c982971a1..fb3fddc1b160e 100644 --- a/test/Interop/Cxx/operators/member-inline-silgen.swift +++ b/test/Interop/Cxx/operators/member-inline-silgen.swift @@ -12,3 +12,17 @@ public func sub(_ lhs: inout LoadableIntWrapper, _ rhs: LoadableIntWrapper) -> L // CHECK: end_access [[SELFACCESS]] : $*LoadableIntWrapper // CHECK: sil [clang LoadableIntWrapper."-"] [[NAME]] : $@convention(c) (@inout LoadableIntWrapper, LoadableIntWrapper) -> LoadableIntWrapper + +// CHECK-LABEL: sil @$s4main24subAddressOnlyIntWrapperySo0cdeF0VADz_ADtF : $@convention(thin) (@inout AddressOnlyIntWrapper, @in_guaranteed AddressOnlyIntWrapper) -> @out AddressOnlyIntWrapper +// CHECK: bb0([[OUT:%.*]] : $*AddressOnlyIntWrapper, [[LHS:%.*]] : $*AddressOnlyIntWrapper, [[RHS:%.*]] : $*AddressOnlyIntWrapper): +// CHECK: [[RHS_TMP:%.*]] = alloc_stack $AddressOnlyIntWrapper +// CHECK: copy_addr [[RHS]] to [initialization] [[RHS_TMP]] : $*AddressOnlyIntWrapper +// CHECK: [[LHS_ACCESS:%.*]] = begin_access [modify] [static] [[LHS]] : $*AddressOnlyIntWrapper +// CHECK: [[FN:%.*]] = function_ref [[NAME:@(_ZN21AddressOnlyIntWrappermiES_|\?\?GAddressOnlyIntWrapper@@QEAA\?AU0@U0@@Z)]] : $@convention(c) (@inout AddressOnlyIntWrapper, @in AddressOnlyIntWrapper) -> @out AddressOnlyIntWrapper +// CHECK: apply [[FN]]([[OUT]], [[LHS_ACCESS]], [[RHS_TMP]]) : $@convention(c) (@inout AddressOnlyIntWrapper, @in AddressOnlyIntWrapper) -> @out AddressOnlyIntWrapper +// CHECK: end_access [[LHS_ACCESS]] +// CHECK: dealloc_stack [[RHS_TMP]] +// CHECK: end sil function '$s4main24subAddressOnlyIntWrapperySo0cdeF0VADz_ADtF' + +// CHECK: sil [clang AddressOnlyIntWrapper."-"] [[NAME]] : $@convention(c) (@inout AddressOnlyIntWrapper, @in AddressOnlyIntWrapper) -> @out AddressOnlyIntWrapper +public func subAddressOnlyIntWrapper(_ lhs: inout AddressOnlyIntWrapper, _ rhs: AddressOnlyIntWrapper) -> AddressOnlyIntWrapper { lhs - rhs } diff --git a/test/Interop/Cxx/operators/member-inline-typechecker.swift b/test/Interop/Cxx/operators/member-inline-typechecker.swift index d94c545884c40..06d5dadf92dfc 100644 --- a/test/Interop/Cxx/operators/member-inline-typechecker.swift +++ b/test/Interop/Cxx/operators/member-inline-typechecker.swift @@ -4,5 +4,8 @@ import MemberInline var lhs = LoadableIntWrapper(value: 42) let rhs = LoadableIntWrapper(value: 23) +let resultMinus = lhs - rhs -let resultPlus = lhs - rhs +var lhsAddressOnly = AddressOnlyIntWrapper(42) +var rhsAddressOnly = AddressOnlyIntWrapper(23) +let resultMinusAddressOnly = lhsAddressOnly - rhsAddressOnly diff --git a/test/Interop/Cxx/operators/member-inline.swift b/test/Interop/Cxx/operators/member-inline.swift index 67b2f801d0398..087749544f657 100644 --- a/test/Interop/Cxx/operators/member-inline.swift +++ b/test/Interop/Cxx/operators/member-inline.swift @@ -19,4 +19,12 @@ OperatorsTestSuite.test("LoadableIntWrapper.plus") { expectEqual(19, result.value) } +OperatorsTestSuite.test("AddressOnlyIntWrapper.plus") { + var lhs = AddressOnlyIntWrapper(42) + let rhs = AddressOnlyIntWrapper(23) + + let result = lhs - rhs + expectEqual(19, result.value) +} + runAllTests()