Skip to content

Commit 9b62558

Browse files
committed
[sil] Make copyable_to_moveonlywrapper forwarding like moveonlywrapper_to_copyable.
Specifically this means that rather than always being owned, we now have owned and guaranteed versions of copyable_to_moveonlywrapper. Similar to moveonlywrapper_to_copyable, one chooses which variant one gets by using specific SILBuilder APIs: create{Owned,Guaranteed}CopyableToMoveOnlyWrapperValueInst. It is still forwarding and the rest of the forwarding APIs work as expected except that the forwarding ownership is fixed (and an assertion will result if one attempts to do so). NOTE: It is assumed that trivial operands are always passed to the owned variant.
1 parent 36e1e52 commit 9b62558

File tree

14 files changed

+140
-33
lines changed

14 files changed

+140
-33
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,9 +1291,18 @@ class SILBuilder {
12911291
}
12921292

12931293
CopyableToMoveOnlyWrapperValueInst *
1294-
createCopyableToMoveOnlyWrapperValue(SILLocation loc, SILValue src) {
1294+
createOwnedCopyableToMoveOnlyWrapperValue(SILLocation loc, SILValue src) {
12951295
return insert(new (getModule()) CopyableToMoveOnlyWrapperValueInst(
1296-
getSILDebugLocation(loc), src));
1296+
getSILDebugLocation(loc), src,
1297+
CopyableToMoveOnlyWrapperValueInst::Owned));
1298+
}
1299+
1300+
CopyableToMoveOnlyWrapperValueInst *
1301+
createGuaranteedCopyableToMoveOnlyWrapperValue(SILLocation loc,
1302+
SILValue src) {
1303+
return insert(new (getModule()) CopyableToMoveOnlyWrapperValueInst(
1304+
getSILDebugLocation(loc), src,
1305+
CopyableToMoveOnlyWrapperValueInst::Guaranteed));
12971306
}
12981307

12991308
MoveOnlyWrapperToCopyableValueInst *

include/swift/SIL/SILCloner.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1788,11 +1788,18 @@ void SILCloner<ImplClass>::visitMoveOnlyWrapperToCopyableValueInst(
17881788

17891789
template <typename ImplClass>
17901790
void SILCloner<ImplClass>::visitCopyableToMoveOnlyWrapperValueInst(
1791-
CopyableToMoveOnlyWrapperValueInst *Inst) {
1792-
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
1793-
auto *MVI = getBuilder().createCopyableToMoveOnlyWrapperValue(
1794-
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()));
1795-
recordClonedInstruction(Inst, MVI);
1791+
CopyableToMoveOnlyWrapperValueInst *inst) {
1792+
getBuilder().setCurrentDebugScope(getOpScope(inst->getDebugScope()));
1793+
CopyableToMoveOnlyWrapperValueInst *cvt;
1794+
if (inst->getOwnershipKind() == OwnershipKind::Owned) {
1795+
cvt = getBuilder().createOwnedCopyableToMoveOnlyWrapperValue(
1796+
getOpLocation(inst->getLoc()), getOpValue(inst->getOperand()));
1797+
} else {
1798+
assert(inst->getOwnershipKind() == OwnershipKind::Guaranteed);
1799+
cvt = getBuilder().createGuaranteedCopyableToMoveOnlyWrapperValue(
1800+
getOpLocation(inst->getLoc()), getOpValue(inst->getOperand()));
1801+
}
1802+
recordClonedInstruction(inst, cvt);
17961803
}
17971804

17981805
template <typename ImplClass>

include/swift/SIL/SILInstruction.h

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,6 +1317,7 @@ FirstArgOwnershipForwardingSingleValueInst::classof(SILInstructionKind kind) {
13171317
case SILInstructionKind::InitExistentialRefInst:
13181318
case SILInstructionKind::MarkDependenceInst:
13191319
case SILInstructionKind::MoveOnlyWrapperToCopyableValueInst:
1320+
case SILInstructionKind::CopyableToMoveOnlyWrapperValueInst:
13201321
return true;
13211322
default:
13221323
return false;
@@ -7591,16 +7592,49 @@ class MarkMustCheckInst
75917592
bool isNoImplicitCopy() const { return kind == CheckKind::NoImplicitCopy; }
75927593
};
75937594

7595+
/// Convert from a non-trivial copyable type to an `@moveOnly` wrapper type.
7596+
///
7597+
/// IMPORTANT: Unlike other forwarding instructions, the ownership of
7598+
/// copyable_to_moveonly is not decided by the operand passed in on
7599+
/// construction. Instead in SILBuilder one must select the specific type of
7600+
/// ownership one wishes by using the following APIs:
7601+
///
7602+
/// * SILBuilder::createOwnedCopyableToMoveOnlyWrapperValueInst
7603+
/// * SILBuilder::createGuaranteedCopyableToMoveOnlyWrapperInst
7604+
///
7605+
/// The reason why this instruction was designed in this manner is that a
7606+
/// frontend chooses the ownership form of this instruction based off of the
7607+
/// semantic place that the value is used. Specifically:
7608+
///
7609+
/// 1. When creating a moveOnly wrapped value for an owned argument or a value,
7610+
/// we use the owned variant.
7611+
///
7612+
/// 2. When creating a moveOnly wrapped value from a guaranteed argument, we use
7613+
/// the guaranteed variant.
75947614
class CopyableToMoveOnlyWrapperValueInst
75957615
: public UnaryInstructionBase<
75967616
SILInstructionKind::CopyableToMoveOnlyWrapperValueInst,
7597-
SingleValueInstruction> {
7617+
FirstArgOwnershipForwardingSingleValueInst> {
7618+
public:
7619+
enum InitialKind {
7620+
Guaranteed,
7621+
Owned,
7622+
};
7623+
7624+
private:
75987625
friend class SILBuilder;
75997626

7627+
InitialKind initialKind;
7628+
76007629
CopyableToMoveOnlyWrapperValueInst(SILDebugLocation DebugLoc,
7601-
SILValue operand)
7602-
: UnaryInstructionBase(DebugLoc, operand,
7603-
operand->getType().addingMoveOnlyWrapper()) {}
7630+
SILValue operand, InitialKind kind)
7631+
: UnaryInstructionBase(
7632+
DebugLoc, operand, operand->getType().addingMoveOnlyWrapper(),
7633+
kind == InitialKind::Guaranteed ? OwnershipKind::Guaranteed
7634+
: OwnershipKind::Owned) {}
7635+
7636+
public:
7637+
InitialKind getInitialKind() const { return initialKind; }
76047638
};
76057639

76067640
/// Convert from an @moveOnly wrapper type to the underlying copyable type. Can
@@ -9822,6 +9856,8 @@ OwnershipForwardingMixin::get(SILInstruction *inst) {
98229856
return result;
98239857
if (auto *result = dyn_cast<MoveOnlyWrapperToCopyableValueInst>(inst))
98249858
return result;
9859+
if (auto *result = dyn_cast<CopyableToMoveOnlyWrapperValueInst>(inst))
9860+
return result;
98259861
return nullptr;
98269862
}
98279863

include/swift/SIL/SILNodes.def

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,9 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
474474
SINGLE_VALUE_INST(MarkMustCheckInst, mark_must_check,
475475
SingleValueInstruction, None, DoesNotRelease)
476476
// Convert a $T to $@moveOnly T. This is the method that one uses to convert a
477-
// trivial value to a non-trivial move only value.
477+
// trivial value to a non-trivial move only value. Ownership is fixed at construction by
478+
// frontend to express specific semantics: guaranteed for guaranteed function arguments
479+
// and owned for assignment/owned function arguments.
478480
SINGLE_VALUE_INST(CopyableToMoveOnlyWrapperValueInst, copyable_to_moveonlywrapper,
479481
SingleValueInstruction, None, DoesNotRelease)
480482
// Convert a $@moveOnly T to $T. Ownership is fixed at construction by

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,6 @@ OPERAND_OWNERSHIP(DestroyingConsume, EndCOWMutation)
256256

257257
// TODO: Should this be a forwarding consume.
258258
OPERAND_OWNERSHIP(DestroyingConsume, MoveValue)
259-
OPERAND_OWNERSHIP(DestroyingConsume, CopyableToMoveOnlyWrapperValue)
260259

261260
// Instructions that move an owned value.
262261
OPERAND_OWNERSHIP(ForwardingConsume, InitExistentialValue)
@@ -330,6 +329,7 @@ FORWARDING_OWNERSHIP(DifferentiableFunction)
330329
FORWARDING_OWNERSHIP(LinearFunction)
331330
FORWARDING_OWNERSHIP(MarkMustCheck)
332331
FORWARDING_OWNERSHIP(MoveOnlyWrapperToCopyableValue)
332+
FORWARDING_OWNERSHIP(CopyableToMoveOnlyWrapperValue)
333333
#undef FORWARDING_OWNERSHIP
334334

335335
// Arbitrary value casts are forwarding instructions that are also allowed to

lib/SIL/IR/SILPrinter.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,6 +1916,14 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
19161916

19171917
void visitCopyableToMoveOnlyWrapperValueInst(
19181918
CopyableToMoveOnlyWrapperValueInst *I) {
1919+
switch (I->getInitialKind()) {
1920+
case CopyableToMoveOnlyWrapperValueInst::Owned:
1921+
*this << "[owned] ";
1922+
break;
1923+
case CopyableToMoveOnlyWrapperValueInst::Guaranteed:
1924+
*this << "[guaranteed] ";
1925+
break;
1926+
}
19191927
*this << getIDAndType(I->getOperand());
19201928
}
19211929

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ CONSTANT_OWNERSHIP_INST(Owned, CopyBlockWithoutEscaping)
7575
CONSTANT_OWNERSHIP_INST(Owned, CopyValue)
7676
CONSTANT_OWNERSHIP_INST(Owned, ExplicitCopyValue)
7777
CONSTANT_OWNERSHIP_INST(Owned, MoveValue)
78-
CONSTANT_OWNERSHIP_INST(Owned, CopyableToMoveOnlyWrapperValue)
7978
CONSTANT_OWNERSHIP_INST(Owned, EndCOWMutation)
8079
CONSTANT_OWNERSHIP_INST(Owned, KeyPath)
8180
CONSTANT_OWNERSHIP_INST(Owned, InitExistentialValue)
@@ -277,6 +276,7 @@ FORWARDING_OWNERSHIP_INST(DifferentiableFunction)
277276
FORWARDING_OWNERSHIP_INST(LinearFunction)
278277
FORWARDING_OWNERSHIP_INST(MarkMustCheck)
279278
FORWARDING_OWNERSHIP_INST(MoveOnlyWrapperToCopyableValue)
279+
FORWARDING_OWNERSHIP_INST(CopyableToMoveOnlyWrapperValue)
280280
#undef FORWARDING_OWNERSHIP_INST
281281

282282
ValueOwnershipKind

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3411,13 +3411,34 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
34113411
}
34123412

34133413
case SILInstructionKind::CopyableToMoveOnlyWrapperValueInst: {
3414+
StringRef AttrName;
3415+
if (!parseSILOptional(AttrName, *this)) {
3416+
auto diag = diag::sil_moveonlytocopyable_requires_attribute;
3417+
P.diagnose(InstLoc.getSourceLoc(), diag);
3418+
return true;
3419+
}
3420+
3421+
OwnershipKind OwnershipKind =
3422+
llvm::StringSwitch<ValueOwnershipKind>(AttrName)
3423+
.Case("owned", OwnershipKind::Owned)
3424+
.Case("guaranteed", OwnershipKind::Guaranteed)
3425+
.Default(OwnershipKind::None);
3426+
3427+
if (OwnershipKind == OwnershipKind::None) {
3428+
auto diag = diag::sil_moveonlytocopyable_invalid_attribute;
3429+
P.diagnose(InstLoc.getSourceLoc(), diag, AttrName);
3430+
return true;
3431+
}
3432+
34143433
if (parseTypedValueRef(Val, B))
34153434
return true;
34163435
if (parseSILDebugLocation(InstLoc, B))
34173436
return true;
3418-
3419-
auto *MVI = B.createCopyableToMoveOnlyWrapperValue(InstLoc, Val);
3420-
ResultVal = MVI;
3437+
if (OwnershipKind == OwnershipKind::Owned)
3438+
ResultVal = B.createOwnedCopyableToMoveOnlyWrapperValue(InstLoc, Val);
3439+
else
3440+
ResultVal =
3441+
B.createGuaranteedCopyableToMoveOnlyWrapperValue(InstLoc, Val);
34213442
break;
34223443
}
34233444

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,10 @@ void swift::findGuaranteedReferenceRoots(SILValue value,
897897
if (addAllOperandsToWorklist(mvi)) {
898898
continue;
899899
}
900+
} else if (auto *c = dyn_cast<CopyableToMoveOnlyWrapperValueInst>(inst)) {
901+
if (addAllOperandsToWorklist(c)) {
902+
continue;
903+
}
900904
}
901905
}
902906

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5398,6 +5398,9 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
53985398

53995399
void checkCopyableToMoveOnlyWrapperValueInst(
54005400
CopyableToMoveOnlyWrapperValueInst *cvt) {
5401+
require(!cvt->getOperand()->getType().isTrivial(*cvt->getFunction()),
5402+
"To convert from a trivial value to a move only wrapper value use "
5403+
"TrivialToGuaranteedMoveOnlyWrapperValueInst");
54015404
require(cvt->getOperand()->getType().isObject(),
54025405
"Operand value should be an object");
54035406
require(cvt->getType().isMoveOnlyWrapped(), "Output should be move only");

0 commit comments

Comments
 (0)