Skip to content

Commit 6e8f83c

Browse files
committed
[noImplicitCopy] Teach SIL Lowering that noImplicitCopy params are passed at +1 by default.
1 parent 4e2e017 commit 6e8f83c

File tree

2 files changed

+65
-26
lines changed

2 files changed

+65
-26
lines changed

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,13 +1573,17 @@ class DestructureInputs {
15731573
SmallVectorImpl<SILParameterInfo> &Inputs;
15741574
SubstFunctionTypeCollector &Subst;
15751575
unsigned NextOrigParamIndex = 0;
1576+
Optional<SmallBitVector> NoImplicitCopyIndices;
1577+
15761578
public:
15771579
DestructureInputs(TypeExpansionContext expansion, TypeConverter &TC,
15781580
const Conventions &conventions, const ForeignInfo &foreign,
15791581
SmallVectorImpl<SILParameterInfo> &inputs,
1580-
SubstFunctionTypeCollector &subst)
1582+
SubstFunctionTypeCollector &subst,
1583+
Optional<SmallBitVector> noImplicitCopyIndices)
15811584
: expansion(expansion), TC(TC), Convs(conventions), Foreign(foreign),
1582-
Inputs(inputs), Subst(subst) {}
1585+
Inputs(inputs), Subst(subst),
1586+
NoImplicitCopyIndices(noImplicitCopyIndices) {}
15831587

15841588
void destructure(AbstractionPattern origType,
15851589
CanAnyFunctionType::CanParamArrayRef params,
@@ -1617,14 +1621,18 @@ class DestructureInputs {
16171621
// Add any foreign parameters that are positioned here.
16181622
maybeAddForeignParameters();
16191623

1624+
bool hasNoImplicitCopy =
1625+
NoImplicitCopyIndices.hasValue() && NoImplicitCopyIndices->any();
1626+
16201627
// Process all the non-self parameters.
16211628
for (unsigned i = 0; i != numNonSelfParams; ++i) {
16221629
auto ty = params[i].getParameterType();
16231630
auto eltPattern = origType.getFunctionParamType(i);
16241631
auto flags = params[i].getParameterFlags();
16251632

16261633
visit(flags.getValueOwnership(), /*forSelf=*/false, eltPattern, ty,
1627-
flags.isNoDerivative());
1634+
flags.isNoDerivative(),
1635+
hasNoImplicitCopy && (*NoImplicitCopyIndices)[i]);
16281636
}
16291637

16301638
// Process the self parameter. Note that we implicitly drop self
@@ -1635,8 +1643,8 @@ class DestructureInputs {
16351643
auto eltPattern = origType.getFunctionParamType(numNonSelfParams);
16361644
auto flags = selfParam.getParameterFlags();
16371645

1638-
visit(flags.getValueOwnership(), /*forSelf=*/true,
1639-
eltPattern, ty);
1646+
visit(flags.getValueOwnership(), /*forSelf=*/true, eltPattern, ty, false,
1647+
false);
16401648
}
16411649

16421650
TopLevelOrigType = AbstractionPattern::getInvalid();
@@ -1645,7 +1653,7 @@ class DestructureInputs {
16451653

16461654
void visit(ValueOwnership ownership, bool forSelf,
16471655
AbstractionPattern origType, CanType substType,
1648-
bool isNonDifferentiable = false) {
1656+
bool isNonDifferentiable, bool isNoImplicitCopy) {
16491657
assert(!isa<InOutType>(substType));
16501658

16511659
// Tuples get handled specially, in some cases:
@@ -1662,9 +1670,8 @@ class DestructureInputs {
16621670
auto ownership = elt.getParameterFlags().getValueOwnership();
16631671
assert(ownership == ValueOwnership::Default);
16641672
assert(!elt.isVararg());
1665-
visit(ownership, forSelf,
1666-
origType.getTupleElementType(i),
1667-
CanType(elt.getRawType()));
1673+
visit(ownership, forSelf, origType.getTupleElementType(i),
1674+
CanType(elt.getRawType()), false, false);
16681675
}
16691676
return;
16701677
case ValueOwnership::InOut:
@@ -1692,6 +1699,9 @@ class DestructureInputs {
16921699
} else if (substTL.isTrivial()) {
16931700
convention = ParameterConvention::Direct_Unowned;
16941701
} else {
1702+
// If we are no implicit copy, our ownership is always Owned.
1703+
if (isNoImplicitCopy)
1704+
ownership = ValueOwnership::Owned;
16951705
convention = Convs.getDirect(ownership, forSelf, origParamIndex, origType,
16961706
substTLConv);
16971707
assert(!isIndirectFormalParameter(convention));
@@ -1757,9 +1767,8 @@ class DestructureInputs {
17571767
if (ForeignSelf) {
17581768
// This is a "self", but it's not a Swift self, we handle it differently.
17591769
visit(ForeignSelf->SubstSelfParam.getValueOwnership(),
1760-
/*forSelf=*/false,
1761-
ForeignSelf->OrigSelfParam,
1762-
ForeignSelf->SubstSelfParam.getParameterType());
1770+
/*forSelf=*/false, ForeignSelf->OrigSelfParam,
1771+
ForeignSelf->SubstSelfParam.getParameterType(), false, false);
17631772
}
17641773
return true;
17651774
}
@@ -2107,7 +2116,8 @@ static CanSILFunctionType getSILFunctionType(
21072116
SILExtInfoBuilder extInfoBuilder, const Conventions &conventions,
21082117
const ForeignInfo &foreignInfo, Optional<SILDeclRef> origConstant,
21092118
Optional<SILDeclRef> constant, Optional<SubstitutionMap> reqtSubs,
2110-
ProtocolConformanceRef witnessMethodConformance) {
2119+
ProtocolConformanceRef witnessMethodConformance,
2120+
Optional<SmallBitVector> noImplicitCopyIndices) {
21112121
// Find the generic parameters.
21122122
CanGenericSignature genericSig =
21132123
substFnInterfaceType.getOptGenericSignature();
@@ -2197,7 +2207,8 @@ static CanSILFunctionType getSILFunctionType(
21972207
SmallVector<SILParameterInfo, 8> inputs;
21982208
{
21992209
DestructureInputs destructurer(expansionContext, TC, conventions,
2200-
foreignInfo, inputs, subst);
2210+
foreignInfo, inputs, subst,
2211+
noImplicitCopyIndices);
22012212
destructurer.destructure(origType, substFnInterfaceType.getParams(),
22022213
extInfoBuilder);
22032214
}
@@ -2498,14 +2509,15 @@ static CanSILFunctionType getNativeSILFunctionType(
24982509
AbstractionPattern origType, CanAnyFunctionType substInterfaceType,
24992510
SILExtInfoBuilder extInfoBuilder, Optional<SILDeclRef> origConstant,
25002511
Optional<SILDeclRef> constant, Optional<SubstitutionMap> reqtSubs,
2501-
ProtocolConformanceRef witnessMethodConformance) {
2512+
ProtocolConformanceRef witnessMethodConformance,
2513+
Optional<SmallBitVector> noImplicitCopyIndices) {
25022514
assert(bool(origConstant) == bool(constant));
25032515
auto getSILFunctionTypeForConventions =
25042516
[&](const Conventions &convs) -> CanSILFunctionType {
25052517
return getSILFunctionType(TC, context, origType, substInterfaceType,
25062518
extInfoBuilder, convs, ForeignInfo(),
25072519
origConstant, constant, reqtSubs,
2508-
witnessMethodConformance);
2520+
witnessMethodConformance, noImplicitCopyIndices);
25092521
};
25102522
switch (extInfoBuilder.getRepresentation()) {
25112523
case SILFunctionType::Representation::Block:
@@ -2568,7 +2580,7 @@ CanSILFunctionType swift::getNativeSILFunctionType(
25682580

25692581
return ::getNativeSILFunctionType(
25702582
TC, context, origType, substType, silExtInfo.intoBuilder(), origConstant,
2571-
substConstant, reqtSubs, witnessMethodConformance);
2583+
substConstant, reqtSubs, witnessMethodConformance, None);
25722584
}
25732585

25742586
//===----------------------------------------------------------------------===//
@@ -2947,7 +2959,7 @@ static CanSILFunctionType getSILFunctionTypeForClangDecl(
29472959
return getSILFunctionType(
29482960
TC, TypeExpansionContext::minimal(), origPattern, substInterfaceType,
29492961
extInfoBuilder, ObjCMethodConventions(method), foreignInfo, constant,
2950-
constant, None, ProtocolConformanceRef());
2962+
constant, None, ProtocolConformanceRef(), None);
29512963
}
29522964

29532965
if (auto method = dyn_cast<clang::CXXMethodDecl>(clangDecl)) {
@@ -2963,7 +2975,7 @@ static CanSILFunctionType getSILFunctionTypeForClangDecl(
29632975
return getSILFunctionType(TC, TypeExpansionContext::minimal(), origPattern,
29642976
substInterfaceType, extInfoBuilder, conventions,
29652977
foreignInfo, constant, constant, None,
2966-
ProtocolConformanceRef());
2978+
ProtocolConformanceRef(), None);
29672979
}
29682980

29692981
if (auto func = dyn_cast<clang::FunctionDecl>(clangDecl)) {
@@ -2976,7 +2988,7 @@ static CanSILFunctionType getSILFunctionTypeForClangDecl(
29762988
return getSILFunctionType(TC, TypeExpansionContext::minimal(), origPattern,
29772989
substInterfaceType, extInfoBuilder,
29782990
CFunctionConventions(func), foreignInfo, constant,
2979-
constant, None, ProtocolConformanceRef());
2991+
constant, None, ProtocolConformanceRef(), None);
29802992
}
29812993

29822994
llvm_unreachable("call to unknown kind of C function");
@@ -3004,15 +3016,15 @@ static CanSILFunctionType getSILFunctionTypeForAbstractCFunction(
30043016
return getSILFunctionType(
30053017
TC, TypeExpansionContext::minimal(), origType, substType,
30063018
extInfoBuilder, CFunctionTypeConventions(fnType), ForeignInfo(),
3007-
constant, constant, None, ProtocolConformanceRef());
3019+
constant, constant, None, ProtocolConformanceRef(), None);
30083020
}
30093021
}
30103022

30113023
// TODO: Ought to support captures in block funcs.
30123024
return getSILFunctionType(TC, TypeExpansionContext::minimal(), origType,
30133025
substType, extInfoBuilder,
30143026
DefaultBlockConventions(), ForeignInfo(), constant,
3015-
constant, None, ProtocolConformanceRef());
3027+
constant, None, ProtocolConformanceRef(), None);
30163028
}
30173029

30183030
/// Try to find a clang method declaration for the given function.
@@ -3180,7 +3192,7 @@ static CanSILFunctionType getSILFunctionTypeForObjCSelectorFamily(
31803192
TC, TypeExpansionContext::minimal(), AbstractionPattern(origType),
31813193
substInterfaceType, extInfoBuilder, ObjCSelectorFamilyConventions(family),
31823194
foreignInfo, constant, constant,
3183-
/*requirement subs*/ None, ProtocolConformanceRef());
3195+
/*requirement subs*/ None, ProtocolConformanceRef(), None);
31843196
}
31853197

31863198
static bool isImporterGeneratedAccessor(const clang::Decl *clangDecl,
@@ -3250,10 +3262,23 @@ static CanSILFunctionType getUncachedSILFunctionTypeForConstant(
32503262
}
32513263
}();
32523264

3265+
Optional<SmallBitVector> noImplicitCopyIndices;
3266+
if (constant.hasDecl()) {
3267+
auto decl = constant.getDecl();
3268+
if (auto *funcDecl = dyn_cast<AbstractFunctionDecl>(decl)) {
3269+
noImplicitCopyIndices.emplace(funcDecl->getParameters()->size());
3270+
for (auto p : llvm::enumerate(*funcDecl->getParameters())) {
3271+
if (p.value()->isNoImplicitCopy()) {
3272+
noImplicitCopyIndices->set(p.index());
3273+
}
3274+
}
3275+
}
3276+
}
3277+
32533278
return ::getNativeSILFunctionType(
3254-
TC, context, origType,
3255-
origLoweredInterfaceType, extInfoBuilder, constant, constant, None,
3256-
witnessMethodConformance);
3279+
TC, context, origType, origLoweredInterfaceType, extInfoBuilder,
3280+
constant, constant, None, witnessMethodConformance,
3281+
noImplicitCopyIndices);
32573282
}
32583283

32593284
ForeignInfo foreignInfo;

test/SILGen/noimplicitcopy_attr.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-swift-emit-silgen -enable-experimental-move-only -parse-stdlib -disable-availability-checking %s | %FileCheck %s
2+
// RUN: %target-swift-emit-sil -enable-experimental-move-only -parse-stdlib -disable-availability-checking %s | %FileCheck -check-prefix=CHECK-SIL %s
3+
// RUN: %target-swift-emit-sil -O -enable-experimental-move-only -Xllvm -sil-disable-pass=FunctionSignatureOpts -parse-stdlib -disable-availability-checking %s | %FileCheck -check-prefix=CHECK-SIL %s
4+
5+
public class Klass {}
6+
7+
// CHECK: bb0(%0 : @noImplicitCopy @owned $Klass):
8+
// CHECK-SIL: bb0(%0 : @noImplicitCopy $Klass):
9+
10+
public func arguments(@_noImplicitCopy _ x: Klass) -> Klass {
11+
let y = x
12+
let z = x
13+
return x
14+
}

0 commit comments

Comments
 (0)