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
33 changes: 27 additions & 6 deletions lib/SIL/IR/SILFunctionType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "swift/AST/Expr.h"
#include "swift/AST/Type.h"
#include "swift/SIL/AbstractionPattern.h"
#define DEBUG_TYPE "libsil"

#include "swift/AST/AnyFunctionRef.h"
Expand Down Expand Up @@ -1467,7 +1468,10 @@ class DestructureResults {
ResultConvention convention;

if (isBorrowAccessor(constant)) {
if (substResultTL.isTrivial()) {
if (substResultTL.getRecursiveProperties()
.isAddressableForDependencies()) {
convention = ResultConvention::GuaranteedAddress;
} else if (substResultTL.isTrivial()) {
convention = ResultConvention::Unowned;
} else if (isFormallyReturnedIndirectly(origType, substType,
substResultTLForConvention)) {
Expand Down Expand Up @@ -1674,6 +1678,7 @@ class DestructureInputs {
AnyFunctionType::CanParam SubstSelfParam;
};
std::optional<ForeignSelfInfo> ForeignSelf;
std::optional<SILDeclRef> Constant;
AbstractionPattern TopLevelOrigType = AbstractionPattern::getInvalid();
SmallVectorImpl<SILParameterInfo> &Inputs;
SmallVectorImpl<int> &ParameterMap;
Expand All @@ -1695,9 +1700,11 @@ class DestructureInputs {
SmallVectorImpl<SILParameterInfo> &inputs,
SmallVectorImpl<int> &parameterMap,
SmallBitVector &addressableParams,
SmallBitVector &conditionallyAddressableParams)
SmallBitVector &conditionallyAddressableParams,
std::optional<SILDeclRef> constant)
: expansion(expansion), TC(TC), Convs(conventions), Foreign(foreign),
IsolationInfo(isolationInfo), Inputs(inputs),
IsolationInfo(isolationInfo),
Constant(constant), Inputs(inputs),
ParameterMap(parameterMap),
AddressableLoweredParameters(addressableParams),
ConditionallyAddressableLoweredParameters(conditionallyAddressableParams)
Expand Down Expand Up @@ -1851,8 +1858,20 @@ class DestructureInputs {
// parameter, we should have processed it earlier in a call to
// maybeAddForeignParameters().
if (hasSelf && !hasForeignSelf) {
auto origParamType = origType.getFunctionParamType(numOrigParams - 1);
auto origParamType
= origType.getFunctionParamType(numOrigParams - 1);
auto substParam = params.back();

// If the self type is addressable-for-dependencies, and this is a
// borrow accessor, then we should pass it indirectly, as an abstract.
// parameter.
if (isBorrowAccessor(Constant)
&& TC.getTypeLowering(origParamType,
substParam.getParameterType(), expansion)
.getRecursiveProperties()
.isAddressableForDependencies()) {
origParamType = AbstractionPattern::getOpaque();
}
visit(origParamType, substParam,
params.size() - 1,
/*forSelf*/true,
Expand Down Expand Up @@ -2717,7 +2736,8 @@ static CanSILFunctionType getSILFunctionType(
foreignInfo, actorIsolation, inputs,
parameterMap,
addressableParams,
conditionallyAddressableParams);
conditionallyAddressableParams,
constant);
destructurer.destructure(origType, substFnInterfaceType.getParams(),
extInfoBuilder, unimplementable);
}
Expand Down Expand Up @@ -2923,7 +2943,8 @@ static CanSILFunctionType getSILFunctionTypeForInitAccessor(
actorIsolation, inputs,
unusedParameterMap,
unusedAddressableParams,
unusedConditionalAddressableParams);
unusedConditionalAddressableParams,
constant);
destructurer.destructure(
origType, substAccessorType.getParams(),
extInfoBuilder.withRepresentation(SILFunctionTypeRepresentation::Thin),
Expand Down
1 change: 1 addition & 0 deletions lib/SILGen/SILGenLValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5750,6 +5750,7 @@ SILGenFunction::tryEmitProjectedLValue(SILLocation loc, LValue &&src,
for (auto component = src.begin(); component != src.end(); component++) {
if (component->get()->getKind() != PathComponent::BorrowMutateKind &&
component->get()->getKind() != PathComponent::StructElementKind &&
component->get()->getKind() != PathComponent::RefElementKind &&
component->get()->getKind() != PathComponent::TupleElementKind &&
component->get()->getKind() != PathComponent::ValueKind) {
return std::nullopt;
Expand Down
70 changes: 70 additions & 0 deletions test/SILGen/borrow_accessor_afd.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// RUN: %target-swift-emit-silgen -enable-experimental-feature BorrowAndMutateAccessors -enable-experimental-feature AddressableTypes %s

// REQUIRES: swift_feature_BorrowAndMutateAccessors
// REQUIRES: swift_feature_AddressableTypes

// When the `self` and/or result type of a borrow accessor is addressable-for-
// dependencies, the corresponding parameter and/or result is indirect.

@_addressableForDependencies
struct AFD { var x: Int }

struct DirectContainer {
let _value: AFD

let _nonAFDValue: AnyObject

// `self` and `result` are both AFD
// CHECK-LABEL: sil{{.*}} @$s{{.*}}15DirectContainerV5value{{.*}}vb :
// CHECK: bb0([[SELF:%.*]] : $*DirectContainer):
// CHECK: [[FIELD_ADDR:%.*]] = struct_element_addr [[SELF]]
// CHECK: return [[FIELD_ADDR]]
var value: AFD {
borrow { return _value }
}

// `self` is AFD, but `result` is not
// CHECK-LABEL: sil{{.*}} @$s{{.*}}15DirectContainerV11nonAFDValue{{.*}}vb :
// CHECK: bb0([[SELF:%.*]] : $*DirectContainer):
// CHECK: [[FIELD_ADDR:%.*]] = struct_element_addr [[SELF]]
// CHECK: [[FIELD:%.*]] = load_borrow [[FIELD_ADDR]]
// CHECK: [[FIELD_UNCHECKED:%.*]] = unchecked_ownership [[FIELD]]
// CHECK: return [[FIELD_UNCHECKED]]
var nonAFDValue: AnyObject {
borrow { return _nonAFDValue }
}
}

class Box {
let _value: AFD
let _nonAFDValue: AnyObject

init() {}
}

struct IndirectContainer {
let box: Box

// `self` is non-AFD, but `result` is
// CHECK-LABEL: sil{{.*}} @$s{{.*}}17IndirectContainerV5value{{.*}}vb :
// CHECK: bb0([[SELF:%.*]] : @guaranteed $IndirectContainer):
// CHECK: [[BOX:%.*]] = struct_extract [[SELF]]
// CHECK: [[FIELD_ADDR:%.*]] = ref_element_addr [[BOX]]
// CHECK: return [[FIELD_ADDR]]
var value: AFD {
borrow { return box._value }
}

// neither `self` nor `result` is AFD
// CHECK-LABEL: sil{{.*}} @$s{{.*}}17IndirectContainerV11nonAFDValue{{.*}}vb :
// CHECK: bb0([[SELF:%.*]] : @guaranteed $IndirectContainer):
// CHECK: [[BOX:%.*]] = struct_extract [[SELF]]
// CHECK: [[FIELD_ADDR:%.*]] = ref_element_addr [[BOX]]
// CHECK: [[FIELD:%.*]] = load_borrow [[FIELD_ADDR]]
// CHECK: [[FIELD_UNCHECKED:%.*]] = unchecked_ownership [[FIELD]]
// CHECK: return [[FIELD_UNCHECKED]]
var nonAFDValue: AnyObject {
borrow { return box._nonAFDValue }
}
}