Skip to content

Commit 6a24087

Browse files
authored
Merge pull request #59611 from gottesmm/moveonly-rebase
[no-implicit-copy] Update SILGen/move checker to work with new patterns from copyable_to_moveonly and friends.
2 parents b09b385 + 3088fe1 commit 6a24087

18 files changed

+1861
-81
lines changed

include/swift/SIL/SILValue.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,19 @@ class ValueBase : public SILNode, public SILAllocated<ValueBase> {
558558

559559
bool isLexical() const;
560560

561+
/// Unsafely eliminate moveonly from this value's type. Returns true if the
562+
/// value's underlying type was move only and thus was changed. Returns false
563+
/// otherwise.
564+
///
565+
/// NOTE: Please do not use this directly! It is only meant to be used by the
566+
/// optimizer pass: SILMoveOnlyTypeEliminator.
567+
bool unsafelyEliminateMoveOnlyWrapper() {
568+
if (!Type.isMoveOnlyWrapped())
569+
return false;
570+
Type = Type.removingMoveOnlyWrapper();
571+
return true;
572+
}
573+
561574
static bool classof(SILNodePointer node) {
562575
return node->getKind() >= SILNodeKind::First_ValueBase &&
563576
node->getKind() <= SILNodeKind::Last_ValueBase;

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,10 @@ PASS(MoveOnlyChecker, "sil-move-only-checker",
440440
PASS(MoveKillsCopyableValuesChecker, "sil-move-kills-copyable-values-checker",
441441
"Pass that checks that any copyable (non-move only) value that is passed "
442442
"to _move do not have any uses later than the _move")
443+
PASS(TrivialMoveOnlyTypeEliminator, "sil-trivial-move-only-type-eliminator",
444+
"Pass that rewrites SIL to remove move only types from values of trivial type")
445+
PASS(MoveOnlyTypeEliminator, "sil-move-only-type-eliminator",
446+
"Pass that rewrites SIL to remove move only types from all values")
443447
PASS(LexicalLifetimeEliminator, "sil-lexical-lifetime-eliminator",
444448
"Pass that removes lexical lifetime markers from borrows and alloc stack")
445449
PASS(MoveKillsCopyableAddressesChecker, "sil-move-kills-copyable-addresses-checker",

lib/SILGen/SILGenApply.cpp

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1786,8 +1786,33 @@ static void emitRawApply(SILGenFunction &SGF,
17861786

17871787
// Gather the arguments.
17881788
for (auto i : indices(args)) {
1789-
auto argValue = (inputParams[i].isConsumed() ? args[i].forward(SGF)
1790-
: args[i].getValue());
1789+
SILValue argValue;
1790+
if (inputParams[i].isConsumed()) {
1791+
argValue = args[i].forward(SGF);
1792+
if (argValue->getType().isMoveOnlyWrapped()) {
1793+
argValue =
1794+
SGF.B.createOwnedMoveOnlyWrapperToCopyableValue(loc, argValue);
1795+
}
1796+
} else {
1797+
ManagedValue arg = args[i];
1798+
1799+
// Move only is not represented in the Swift level type system, so if we
1800+
// have a move only value, convert it to a non-move only value. The
1801+
// move/is no escape checkers will ensure that it is legal to do this or
1802+
// will error. At this point we just want to make sure that the emitted
1803+
// types line up.
1804+
if (arg.getType().isMoveOnlyWrapped()) {
1805+
// We need to borrow so that we can convert from $@moveOnly T -> $T. Use
1806+
// a formal access borrow to ensure that we have tight scopes like we do
1807+
// when we borrow fn.
1808+
if (!arg.isPlusZero())
1809+
arg = arg.formalAccessBorrow(SGF, loc);
1810+
arg = SGF.B.createGuaranteedMoveOnlyWrapperToCopyableValue(loc, arg);
1811+
}
1812+
1813+
argValue = arg.getValue();
1814+
}
1815+
17911816
#ifndef NDEBUG
17921817
auto inputTy =
17931818
substFnConv.getSILType(inputParams[i], SGF.getTypeExpansionContext());
@@ -3059,6 +3084,18 @@ class ArgEmitter {
30593084

30603085
// If it's not already in memory, put it there.
30613086
if (!result.getType().isAddress()) {
3087+
// If we have a move only wrapped type, we need to unwrap before we
3088+
// materialize. We will forward as appropriate so it will show up as a
3089+
// consuming use or a guaranteed use as appropriate.
3090+
if (result.getType().isMoveOnlyWrapped()) {
3091+
if (result.isPlusOne(SGF)) {
3092+
result =
3093+
SGF.B.createOwnedMoveOnlyWrapperToCopyableValue(loc, result);
3094+
} else {
3095+
result = SGF.B.createGuaranteedMoveOnlyWrapperToCopyableValue(
3096+
loc, result);
3097+
}
3098+
}
30623099
result = result.materialize(SGF, loc);
30633100
}
30643101

lib/SILGen/SILGenBuilder.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "SILGenBuilder.h"
1414
#include "ArgumentSource.h"
15+
#include "Cleanup.h"
1516
#include "RValue.h"
1617
#include "SILGenFunction.h"
1718
#include "Scope.h"
@@ -450,6 +451,9 @@ static ManagedValue createInputFunctionArgument(SILGenBuilder &B, SILType type,
450451
case SILArgumentConvention::Direct_Unowned:
451452
// Unowned parameters are only guaranteed at the instant of the call, so we
452453
// must retain them even if we're in a context that can accept a +0 value.
454+
//
455+
// NOTE: If we have a trivial value, the copy will do nothing, so this is
456+
// just a convenient way to avoid writing conditional code.
453457
return ManagedValue::forUnmanaged(arg).copy(SGF, loc);
454458

455459
case SILArgumentConvention::Direct_Owned:
@@ -882,3 +886,38 @@ ManagedValue SILGenBuilder::createMarkDependence(SILLocation loc,
882886
base.forward(getSILGenFunction()));
883887
return cloner.clone(mdi);
884888
}
889+
890+
ManagedValue SILGenBuilder::createBeginBorrow(SILLocation loc,
891+
ManagedValue value,
892+
bool isLexical) {
893+
auto *newValue =
894+
SILBuilder::createBeginBorrow(loc, value.getValue(), isLexical);
895+
SGF.emitManagedBorrowedRValueWithCleanup(newValue);
896+
return ManagedValue::forUnmanaged(newValue);
897+
}
898+
899+
ManagedValue SILGenBuilder::createMoveValue(SILLocation loc,
900+
ManagedValue value) {
901+
assert(value.isPlusOne(SGF) && "Must be +1 to be moved!");
902+
CleanupCloner cloner(*this, value);
903+
auto *mdi = createMoveValue(loc, value.forward(getSILGenFunction()));
904+
return cloner.clone(mdi);
905+
}
906+
907+
ManagedValue
908+
SILGenBuilder::createOwnedMoveOnlyWrapperToCopyableValue(SILLocation loc,
909+
ManagedValue value) {
910+
assert(value.isPlusOne(SGF) && "Argument must be at +1!");
911+
CleanupCloner cloner(*this, value);
912+
auto *mdi = createOwnedMoveOnlyWrapperToCopyableValue(
913+
loc, value.forward(getSILGenFunction()));
914+
return cloner.clone(mdi);
915+
}
916+
917+
ManagedValue SILGenBuilder::createGuaranteedMoveOnlyWrapperToCopyableValue(
918+
SILLocation loc, ManagedValue value) {
919+
auto *mdi =
920+
createGuaranteedMoveOnlyWrapperToCopyableValue(loc, value.getValue());
921+
assert(mdi->getOperand()->getType().isObject() && "Expected an object?!");
922+
return ManagedValue::forUnmanaged(mdi);
923+
}

lib/SILGen/SILGenBuilder.h

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@
2626
#include "JumpDest.h"
2727
#include "ManagedValue.h"
2828
#include "RValue.h"
29-
#include "swift/SIL/SILBuilder.h"
3029
#include "swift/Basic/ProfileCounter.h"
30+
#include "swift/SIL/SILBuilder.h"
31+
#include "swift/SIL/SILLocation.h"
3132

3233
namespace swift {
3334
namespace Lowering {
@@ -362,7 +363,19 @@ class SILGenBuilder : public SILBuilder {
362363
BranchInst *createBranch(SILLocation Loc, SILBasicBlock *TargetBlock,
363364
ArrayRef<ManagedValue> Args);
364365

365-
using SILBuilder::createReturn;
366+
ReturnInst *createReturn(SILLocation Loc, SILValue ReturnValue) {
367+
// If we have a move only type as our "result type", convert it back to
368+
// being a copyable type. Move only types are never returned today and we
369+
// will rely on the SIL level move only and no escape checker to validate
370+
// that this is a correct usage. So just make the types line up.
371+
if (ReturnValue->getType().isMoveOnlyWrapped()) {
372+
auto cvtLoc = RegularLocation::getAutoGeneratedLocation();
373+
ReturnValue =
374+
createOwnedMoveOnlyWrapperToCopyableValue(cvtLoc, ReturnValue);
375+
}
376+
return SILBuilder::createReturn(Loc, ReturnValue);
377+
}
378+
366379
ReturnInst *createReturn(SILLocation Loc, ManagedValue ReturnValue);
367380

368381
ReturnInst *createReturn(SILLocation Loc, SILValue ReturnValue,
@@ -385,6 +398,22 @@ class SILGenBuilder : public SILBuilder {
385398
using SILBuilder::createMarkDependence;
386399
ManagedValue createMarkDependence(SILLocation loc, ManagedValue value,
387400
ManagedValue base);
401+
402+
using SILBuilder::createBeginBorrow;
403+
ManagedValue createBeginBorrow(SILLocation loc, ManagedValue value,
404+
bool isLexical = false);
405+
406+
using SILBuilder::createMoveValue;
407+
ManagedValue createMoveValue(SILLocation loc, ManagedValue value);
408+
409+
using SILBuilder::createOwnedMoveOnlyWrapperToCopyableValue;
410+
ManagedValue createOwnedMoveOnlyWrapperToCopyableValue(SILLocation loc,
411+
ManagedValue value);
412+
413+
using SILBuilder::createGuaranteedMoveOnlyWrapperToCopyableValue;
414+
ManagedValue
415+
createGuaranteedMoveOnlyWrapperToCopyableValue(SILLocation loc,
416+
ManagedValue value);
388417
};
389418

390419
} // namespace Lowering

0 commit comments

Comments
 (0)