Skip to content

Commit 18faa24

Browse files
authored
Merge pull request #85780 from jckarter/borrow-accessor-afd
Borrow accessors for addressable-for-dependencies types should pass and return by address.
2 parents 0488a41 + fa2d467 commit 18faa24

File tree

3 files changed

+98
-6
lines changed

3 files changed

+98
-6
lines changed

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "swift/AST/Expr.h"
2020
#include "swift/AST/Type.h"
21+
#include "swift/SIL/AbstractionPattern.h"
2122
#define DEBUG_TYPE "libsil"
2223

2324
#include "swift/AST/AnyFunctionRef.h"
@@ -1467,7 +1468,10 @@ class DestructureResults {
14671468
ResultConvention convention;
14681469

14691470
if (isBorrowAccessor(constant)) {
1470-
if (substResultTL.isTrivial()) {
1471+
if (substResultTL.getRecursiveProperties()
1472+
.isAddressableForDependencies()) {
1473+
convention = ResultConvention::GuaranteedAddress;
1474+
} else if (substResultTL.isTrivial()) {
14711475
convention = ResultConvention::Unowned;
14721476
} else if (isFormallyReturnedIndirectly(origType, substType,
14731477
substResultTLForConvention)) {
@@ -1674,6 +1678,7 @@ class DestructureInputs {
16741678
AnyFunctionType::CanParam SubstSelfParam;
16751679
};
16761680
std::optional<ForeignSelfInfo> ForeignSelf;
1681+
std::optional<SILDeclRef> Constant;
16771682
AbstractionPattern TopLevelOrigType = AbstractionPattern::getInvalid();
16781683
SmallVectorImpl<SILParameterInfo> &Inputs;
16791684
SmallVectorImpl<int> &ParameterMap;
@@ -1695,9 +1700,11 @@ class DestructureInputs {
16951700
SmallVectorImpl<SILParameterInfo> &inputs,
16961701
SmallVectorImpl<int> &parameterMap,
16971702
SmallBitVector &addressableParams,
1698-
SmallBitVector &conditionallyAddressableParams)
1703+
SmallBitVector &conditionallyAddressableParams,
1704+
std::optional<SILDeclRef> constant)
16991705
: expansion(expansion), TC(TC), Convs(conventions), Foreign(foreign),
1700-
IsolationInfo(isolationInfo), Inputs(inputs),
1706+
IsolationInfo(isolationInfo),
1707+
Constant(constant), Inputs(inputs),
17011708
ParameterMap(parameterMap),
17021709
AddressableLoweredParameters(addressableParams),
17031710
ConditionallyAddressableLoweredParameters(conditionallyAddressableParams)
@@ -1851,8 +1858,20 @@ class DestructureInputs {
18511858
// parameter, we should have processed it earlier in a call to
18521859
// maybeAddForeignParameters().
18531860
if (hasSelf && !hasForeignSelf) {
1854-
auto origParamType = origType.getFunctionParamType(numOrigParams - 1);
1861+
auto origParamType
1862+
= origType.getFunctionParamType(numOrigParams - 1);
18551863
auto substParam = params.back();
1864+
1865+
// If the self type is addressable-for-dependencies, and this is a
1866+
// borrow accessor, then we should pass it indirectly, as an abstract.
1867+
// parameter.
1868+
if (isBorrowAccessor(Constant)
1869+
&& TC.getTypeLowering(origParamType,
1870+
substParam.getParameterType(), expansion)
1871+
.getRecursiveProperties()
1872+
.isAddressableForDependencies()) {
1873+
origParamType = AbstractionPattern::getOpaque();
1874+
}
18561875
visit(origParamType, substParam,
18571876
params.size() - 1,
18581877
/*forSelf*/true,
@@ -2717,7 +2736,8 @@ static CanSILFunctionType getSILFunctionType(
27172736
foreignInfo, actorIsolation, inputs,
27182737
parameterMap,
27192738
addressableParams,
2720-
conditionallyAddressableParams);
2739+
conditionallyAddressableParams,
2740+
constant);
27212741
destructurer.destructure(origType, substFnInterfaceType.getParams(),
27222742
extInfoBuilder, unimplementable);
27232743
}
@@ -2923,7 +2943,8 @@ static CanSILFunctionType getSILFunctionTypeForInitAccessor(
29232943
actorIsolation, inputs,
29242944
unusedParameterMap,
29252945
unusedAddressableParams,
2926-
unusedConditionalAddressableParams);
2946+
unusedConditionalAddressableParams,
2947+
constant);
29272948
destructurer.destructure(
29282949
origType, substAccessorType.getParams(),
29292950
extInfoBuilder.withRepresentation(SILFunctionTypeRepresentation::Thin),

lib/SILGen/SILGenLValue.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5750,6 +5750,7 @@ SILGenFunction::tryEmitProjectedLValue(SILLocation loc, LValue &&src,
57505750
for (auto component = src.begin(); component != src.end(); component++) {
57515751
if (component->get()->getKind() != PathComponent::BorrowMutateKind &&
57525752
component->get()->getKind() != PathComponent::StructElementKind &&
5753+
component->get()->getKind() != PathComponent::RefElementKind &&
57535754
component->get()->getKind() != PathComponent::TupleElementKind &&
57545755
component->get()->getKind() != PathComponent::ValueKind) {
57555756
return std::nullopt;
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// RUN: %target-swift-emit-silgen -enable-experimental-feature BorrowAndMutateAccessors -enable-experimental-feature AddressableTypes %s
2+
3+
// REQUIRES: swift_feature_BorrowAndMutateAccessors
4+
// REQUIRES: swift_feature_AddressableTypes
5+
6+
// When the `self` and/or result type of a borrow accessor is addressable-for-
7+
// dependencies, the corresponding parameter and/or result is indirect.
8+
9+
@_addressableForDependencies
10+
struct AFD { var x: Int }
11+
12+
struct DirectContainer {
13+
let _value: AFD
14+
15+
let _nonAFDValue: AnyObject
16+
17+
// `self` and `result` are both AFD
18+
// CHECK-LABEL: sil{{.*}} @$s{{.*}}15DirectContainerV5value{{.*}}vb :
19+
// CHECK: bb0([[SELF:%.*]] : $*DirectContainer):
20+
// CHECK: [[FIELD_ADDR:%.*]] = struct_element_addr [[SELF]]
21+
// CHECK: return [[FIELD_ADDR]]
22+
var value: AFD {
23+
borrow { return _value }
24+
}
25+
26+
// `self` is AFD, but `result` is not
27+
// CHECK-LABEL: sil{{.*}} @$s{{.*}}15DirectContainerV11nonAFDValue{{.*}}vb :
28+
// CHECK: bb0([[SELF:%.*]] : $*DirectContainer):
29+
// CHECK: [[FIELD_ADDR:%.*]] = struct_element_addr [[SELF]]
30+
// CHECK: [[FIELD:%.*]] = load_borrow [[FIELD_ADDR]]
31+
// CHECK: [[FIELD_UNCHECKED:%.*]] = unchecked_ownership [[FIELD]]
32+
// CHECK: return [[FIELD_UNCHECKED]]
33+
var nonAFDValue: AnyObject {
34+
borrow { return _nonAFDValue }
35+
}
36+
}
37+
38+
class Box {
39+
let _value: AFD
40+
let _nonAFDValue: AnyObject
41+
42+
init() {}
43+
}
44+
45+
struct IndirectContainer {
46+
let box: Box
47+
48+
// `self` is non-AFD, but `result` is
49+
// CHECK-LABEL: sil{{.*}} @$s{{.*}}17IndirectContainerV5value{{.*}}vb :
50+
// CHECK: bb0([[SELF:%.*]] : @guaranteed $IndirectContainer):
51+
// CHECK: [[BOX:%.*]] = struct_extract [[SELF]]
52+
// CHECK: [[FIELD_ADDR:%.*]] = ref_element_addr [[BOX]]
53+
// CHECK: return [[FIELD_ADDR]]
54+
var value: AFD {
55+
borrow { return box._value }
56+
}
57+
58+
// neither `self` nor `result` is AFD
59+
// CHECK-LABEL: sil{{.*}} @$s{{.*}}17IndirectContainerV11nonAFDValue{{.*}}vb :
60+
// CHECK: bb0([[SELF:%.*]] : @guaranteed $IndirectContainer):
61+
// CHECK: [[BOX:%.*]] = struct_extract [[SELF]]
62+
// CHECK: [[FIELD_ADDR:%.*]] = ref_element_addr [[BOX]]
63+
// CHECK: [[FIELD:%.*]] = load_borrow [[FIELD_ADDR]]
64+
// CHECK: [[FIELD_UNCHECKED:%.*]] = unchecked_ownership [[FIELD]]
65+
// CHECK: return [[FIELD_UNCHECKED]]
66+
var nonAFDValue: AnyObject {
67+
borrow { return box._nonAFDValue }
68+
}
69+
}
70+

0 commit comments

Comments
 (0)