Skip to content

Commit a46019f

Browse files
committed
[SIL] Ensure __owned arguments are @owned.
No matter what the default is, an __owned argument should end up being @owned in SIL. Currently this is... hard to test, since arguments are owned by default. Part of rdar://problem/34668110.
1 parent e307e54 commit a46019f

File tree

2 files changed

+96
-61
lines changed

2 files changed

+96
-61
lines changed

lib/SIL/SILFunctionType.cpp

Lines changed: 80 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,42 @@ class Conventions {
268268
getIndirectSelfParameter(const AbstractionPattern &type) const = 0;
269269
virtual ParameterConvention
270270
getDirectSelfParameter(const AbstractionPattern &type) const = 0;
271+
272+
// Helpers that branch based on a value ownership.
273+
ParameterConvention getIndirect(ValueOwnership ownership, bool forSelf,
274+
unsigned index,
275+
const AbstractionPattern &type,
276+
const TypeLowering &substTL) const {
277+
switch (ownership) {
278+
case ValueOwnership::Default:
279+
if (forSelf)
280+
return getIndirectSelfParameter(type);
281+
return getIndirectParameter(index, type, substTL);
282+
case ValueOwnership::InOut:
283+
return ParameterConvention::Indirect_Inout;
284+
case ValueOwnership::Shared:
285+
return ParameterConvention::Indirect_In_Guaranteed;
286+
case ValueOwnership::Owned:
287+
return ParameterConvention::Indirect_In;
288+
}
289+
}
290+
291+
ParameterConvention getDirect(ValueOwnership ownership, bool forSelf,
292+
unsigned index, const AbstractionPattern &type,
293+
const TypeLowering &substTL) const {
294+
switch (ownership) {
295+
case ValueOwnership::Default:
296+
if (forSelf)
297+
return getDirectSelfParameter(type);
298+
return getDirectParameter(index, type, substTL);
299+
case ValueOwnership::InOut:
300+
return ParameterConvention::Indirect_Inout;
301+
case ValueOwnership::Shared:
302+
return ParameterConvention::Direct_Guaranteed;
303+
case ValueOwnership::Owned:
304+
return ParameterConvention::Direct_Owned;
305+
}
306+
}
271307
};
272308

273309
/// A visitor for breaking down formal result types into a SILResultInfo
@@ -523,40 +559,6 @@ class DestructureInputs {
523559
}
524560
}
525561

526-
void visitSharedType(AbstractionPattern origType, CanType substType,
527-
SILFunctionTypeRepresentation rep) {
528-
NextOrigParamIndex++;
529-
530-
auto &substTL =
531-
M.Types.getTypeLowering(origType, substType);
532-
ParameterConvention convention;
533-
if (origType.getAs<InOutType>()) {
534-
convention = ParameterConvention::Indirect_Inout;
535-
} else if (isa<TupleType>(substType) && !origType.isTypeParameter()) {
536-
// Do not lower tuples @guaranteed. This can create conflicts with
537-
// substitutions for witness thunks e.g. we take $*(T, T)
538-
// @in_guaranteed and try to substitute it for $*T.
539-
return visit(origType, substType);
540-
} else if (isFormallyPassedIndirectly(origType, substType, substTL)) {
541-
if (rep == SILFunctionTypeRepresentation::WitnessMethod)
542-
convention = ParameterConvention::Indirect_In_Guaranteed;
543-
else
544-
convention = Convs.getIndirectSelfParameter(origType);
545-
assert(isIndirectFormalParameter(convention));
546-
547-
} else if (substTL.isTrivial()) {
548-
convention = ParameterConvention::Direct_Unowned;
549-
} else {
550-
convention = Convs.getDirectSelfParameter(origType);
551-
assert(!isIndirectFormalParameter(convention));
552-
}
553-
554-
auto loweredType = substTL.getLoweredType().getSwiftRValueType();
555-
Inputs.push_back(SILParameterInfo(loweredType, convention));
556-
557-
maybeAddForeignParameters();
558-
}
559-
560562
/// This is a special entry point that allows destructure inputs to handle
561563
/// self correctly.
562564
void visitTopLevelParams(AbstractionPattern origType,
@@ -565,11 +567,15 @@ class DestructureInputs {
565567
unsigned numEltTypes = params.size();
566568
unsigned numNonSelfParams = numEltTypes - 1;
567569

570+
auto silRepresentation = extInfo.getSILRepresentation();
571+
568572
// We have to declare this out here so that the lambda scope lasts for
569573
// the duration of the loop below.
570574
auto handleForeignSelf = [&] {
571-
visit(origType.getTupleElementType(numNonSelfParams),
572-
params[numNonSelfParams].getType());
575+
// This is a "self", but it's not a Swift self, we handle it differently.
576+
visit(ValueOwnership::Default,
577+
/*forSelf=*/false, origType.getTupleElementType(numNonSelfParams),
578+
params[numNonSelfParams].getType(), silRepresentation);
573579
};
574580

575581
// If we have a foreign-self, install handleSelf as the handler.
@@ -587,7 +593,8 @@ class DestructureInputs {
587593
// to substitute.
588594
if (params.empty()) {
589595
if (origType.isTypeParameter())
590-
visit(origType, M.getASTContext().TheEmptyTupleType);
596+
visit(ValueOwnership::Default, /*forSelf=*/false, origType,
597+
M.getASTContext().TheEmptyTupleType, silRepresentation);
591598
return;
592599
}
593600

@@ -599,25 +606,18 @@ class DestructureInputs {
599606
// If the abstraction pattern is opaque, and the tuple type is
600607
// materializable -- if it doesn't contain an l-value type -- then it's
601608
// a valid target for substitution and we should not expand it.
602-
auto silExtInfo = extInfo.getSILRepresentation();
603609
if (!tty || (pattern.isTypeParameter() && !tty->hasInOutElement())) {
604-
if (paramFlags.isShared()) {
605-
visitSharedType(pattern, ty, silExtInfo);
606-
} else {
607-
visit(pattern, ty);
608-
}
610+
visit(paramFlags.getValueOwnership(), /*forSelf=*/false, pattern, ty,
611+
silRepresentation);
609612
return;
610613
}
611614

612615
for (auto i : indices(tty.getElementTypes())) {
613616
auto patternEltTy = pattern.getTupleElementType(i);
614617
auto trueEltTy = tty.getElementType(i);
615618
auto flags = tty->getElement(i).getParameterFlags();
616-
if (flags.isShared()) {
617-
visitSharedType(patternEltTy, trueEltTy, silExtInfo);
618-
} else {
619-
visit(patternEltTy, trueEltTy);
620-
}
619+
visit(flags.getValueOwnership(), /*forSelf=*/false, patternEltTy,
620+
trueEltTy, silRepresentation);
621621
}
622622
};
623623

@@ -647,25 +647,41 @@ class DestructureInputs {
647647
// Process the self parameter. Note that we implicitly drop self
648648
// if this is a static foreign-self import.
649649
if (!Foreign.Self.isImportAsMember()) {
650-
visitSharedType(origType.getTupleElementType(numNonSelfParams),
651-
params[numNonSelfParams].getType(),
652-
extInfo.getSILRepresentation());
650+
visit(ValueOwnership::Default, /*forSelf=*/true,
651+
origType.getTupleElementType(numNonSelfParams),
652+
params[numNonSelfParams].getType(), silRepresentation);
653653
}
654654

655655
// Clear the foreign-self handler for safety.
656656
HandleForeignSelf.reset();
657657
}
658658

659-
void visit(AbstractionPattern origType, CanType substType) {
660-
// Expand tuples.
659+
void visit(ValueOwnership ownership, bool forSelf,
660+
AbstractionPattern origType, CanType substType,
661+
SILFunctionTypeRepresentation rep) {
662+
// Tuples get handled specially, in some cases:
661663
CanTupleType substTupleTy = dyn_cast<TupleType>(substType);
662664
if (substTupleTy && !origType.isTypeParameter()) {
663665
assert(origType.getNumTupleElements() == substTupleTy->getNumElements());
664-
for (auto i : indices(substTupleTy.getElementTypes())) {
665-
visit(origType.getTupleElementType(i),
666-
substTupleTy.getElementType(i));
666+
switch (ownership) {
667+
case ValueOwnership::Default:
668+
case ValueOwnership::Owned:
669+
// Expand the tuple.
670+
for (auto i : indices(substTupleTy.getElementTypes())) {
671+
visit(ownership, forSelf, origType.getTupleElementType(i),
672+
substTupleTy.getElementType(i), rep);
673+
}
674+
return;
675+
case ValueOwnership::Shared:
676+
// Do not lower tuples @guaranteed. This can create conflicts with
677+
// substitutions for witness thunks e.g. we take $*(T, T)
678+
// @in_guaranteed and try to substitute it for $*T.
679+
return visit(ValueOwnership::Default, forSelf, origType, substType,
680+
rep);
681+
case ValueOwnership::InOut:
682+
// handled below
683+
break;
667684
}
668-
return;
669685
}
670686

671687
unsigned origParamIndex = NextOrigParamIndex++;
@@ -676,14 +692,17 @@ class DestructureInputs {
676692
assert(origType.isTypeParameter() || origType.getAs<InOutType>());
677693
convention = ParameterConvention::Indirect_Inout;
678694
} else if (isFormallyPassedIndirectly(origType, substType, substTL)) {
679-
convention = Convs.getIndirectParameter(origParamIndex,
680-
origType, substTL);
695+
if (forSelf && rep == SILFunctionTypeRepresentation::WitnessMethod)
696+
convention = ParameterConvention::Indirect_In_Guaranteed;
697+
else
698+
convention = Convs.getIndirect(ownership, forSelf, origParamIndex,
699+
origType, substTL);
681700
assert(isIndirectFormalParameter(convention));
682701
} else if (substTL.isTrivial()) {
683702
convention = ParameterConvention::Direct_Unowned;
684703
} else {
685-
convention = Convs.getDirectParameter(origParamIndex, origType,
686-
substTL);
704+
convention = Convs.getDirect(ownership, forSelf, origParamIndex, origType,
705+
substTL);
687706
assert(!isIndirectFormalParameter(convention));
688707
}
689708
auto loweredType = substTL.getLoweredType().getSwiftRValueType();

test/SILGen/owned.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen %s -disable-objc-attr-requires-foundation-module -enable-sil-ownership -enable-guaranteed-normal-arguments | %FileCheck %s
2+
3+
// see shared.swift for thunks/conversions between __shared and __owned.
4+
5+
class RefAggregate {}
6+
struct ValueAggregate { let x = RefAggregate() }
7+
8+
// CHECK-LABEL: sil hidden @$S5owned0A10_arguments7trivial5value3refySin_AA14ValueAggregateVnAA03RefG0CntF : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> () {
9+
func owned_arguments(trivial : __owned Int, value : __owned ValueAggregate, ref : __owned RefAggregate) {}
10+
11+
struct Foo {
12+
var x: ValueAggregate
13+
14+
// CHECK-LABEL: sil hidden @$S5owned3FooV20methodOwnedArguments7trivial5value3refySin_AA14ValueAggregateVnAA03RefJ0CntF : $@convention(method) (Int, @owned ValueAggregate, @owned RefAggregate, @guaranteed Foo) -> () {
15+
func methodOwnedArguments(trivial : __owned Int, value : __owned ValueAggregate, ref : __owned RefAggregate) {}
16+
}

0 commit comments

Comments
 (0)