Skip to content

Commit a32c5b3

Browse files
committed
[silgen] Refactor out a helper method from LetValueInitialization::bindValue.
Specifically, I refactored out the logic around setting up the value in the case of having lexical lifetimes/no implicit copy into the method LetValueInitialization::getValueForLexicalLifetimeBinding. This logic was taking over bindValue and was making the logic hard to follow. Additionally this allows me to take advantage of return value/early exits to make the actual logic in getValueForLexicalLifetimeBinding easier to reason about. NFC.
1 parent b044958 commit a32c5b3

File tree

1 file changed

+70
-60
lines changed

1 file changed

+70
-60
lines changed

lib/SILGen/SILGenDecl.cpp

Lines changed: 70 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,74 @@ class LetValueInitialization : public Initialization {
552552
SplitCleanups);
553553
}
554554

555+
/// This is a helper method for bindValue that handles any changes to the
556+
/// value needed for lexical lifetime or no implicit copy purposes.
557+
SILValue getValueForLexicalLifetimeBinding(SILGenFunction &SGF,
558+
SILLocation PrologueLoc,
559+
SILValue value, bool wasPlusOne) {
560+
// If we have none...
561+
if (value->getOwnershipKind() == OwnershipKind::None) {
562+
// ... and we don't have a no implicit copy trivial type, just return
563+
// value.
564+
if (!SGF.getASTContext().LangOpts.Features.count(Feature::MoveOnly) ||
565+
!vd->getAttrs().hasAttribute<NoImplicitCopyAttr>() ||
566+
!value->getType().isTrivial(SGF.F))
567+
return value;
568+
569+
// Otherwise, we have a no implicit copy trivial type, so wrap it in the
570+
// move only wrapper and mark it as needing checking by the move cherk.
571+
value =
572+
SGF.B.createOwnedCopyableToMoveOnlyWrapperValue(PrologueLoc, value);
573+
value = SGF.B.createMoveValue(PrologueLoc, value, /*isLexical*/ true);
574+
return SGF.B.createMarkMustCheckInst(
575+
PrologueLoc, value, MarkMustCheckInst::CheckKind::NoImplicitCopy);
576+
}
577+
578+
// Then if we don't have move only, just perform a lexical borrow.
579+
if (!SGF.getASTContext().LangOpts.Features.count(Feature::MoveOnly))
580+
return SGF.B.createBeginBorrow(PrologueLoc, value, /*isLexical*/ true);
581+
582+
// Otherwise, we need to perform some additional processing. First, if we
583+
// have an owned moveonly value that had a cleanup, then create a move_value
584+
// that acts as a consuming use of the value. The reason why we want this is
585+
// even if we are only performing a borrow for our lexical lifetime, we want
586+
// to ensure that our defs see this initialization as consuming this value.
587+
if (value->getOwnershipKind() == OwnershipKind::Owned) {
588+
assert(wasPlusOne);
589+
// NOTE: If our type is trivial when not wrapped in a
590+
// SILMoveOnlyWrappedType, this will return a trivial value. We rely
591+
// on the checker to determine if this is an acceptable use of the
592+
// value.
593+
if (value->getType().isMoveOnly()) {
594+
if (value->getType().isMoveOnlyWrapped()) {
595+
value = SGF.B.createOwnedMoveOnlyWrapperToCopyableValue(PrologueLoc,
596+
value);
597+
} else {
598+
// Change this to be lexical and get rid of borrow scope?
599+
value = SGF.B.createMoveValue(PrologueLoc, value);
600+
}
601+
}
602+
}
603+
604+
// If we still have a trivial thing, just return that.
605+
if (value->getType().isTrivial(SGF.F))
606+
return value;
607+
608+
// Otherwise, if we do not have a no implicit copy variable, just do a
609+
// borrow lexical.
610+
if (!vd->getAttrs().hasAttribute<NoImplicitCopyAttr>())
611+
return SGF.B.createBeginBorrow(PrologueLoc, value, /*isLexical*/ true);
612+
613+
// If we have a no implicit copy lexical, emit the instruction stream so
614+
// that the move checker knows to check this variable.
615+
value = SGF.B.createBeginBorrow(PrologueLoc, value,
616+
/*isLexical*/ true);
617+
value = SGF.B.createCopyValue(PrologueLoc, value);
618+
value = SGF.B.createOwnedCopyableToMoveOnlyWrapperValue(PrologueLoc, value);
619+
return SGF.B.createMarkMustCheckInst(
620+
PrologueLoc, value, MarkMustCheckInst::CheckKind::NoImplicitCopy);
621+
}
622+
555623
void bindValue(SILValue value, SILGenFunction &SGF, bool wasPlusOne) {
556624
assert(!SGF.VarLocs.count(vd) && "Already emitted this vardecl?");
557625
// If we're binding an address to this let value, then we can use it as an
@@ -562,66 +630,8 @@ class LetValueInitialization : public Initialization {
562630
SILLocation PrologueLoc(vd);
563631

564632
if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule())) {
565-
if (value->getOwnershipKind() != OwnershipKind::None) {
566-
if (!SGF.getASTContext().LangOpts.Features.count(Feature::MoveOnly)) {
567-
value =
568-
SGF.B.createBeginBorrow(PrologueLoc, value, /*isLexical*/ true);
569-
} else {
570-
// If we have an owned moveonly value that had a cleanup, then create
571-
// a move_value that acts as a consuming use of the value. The reason
572-
// why we want this is even if we are only performing a borrow for our
573-
// lexical lifetime, we want to ensure that our defs see this
574-
// initialization as consuming this value.
575-
if (value->getOwnershipKind() == OwnershipKind::Owned) {
576-
assert(wasPlusOne);
577-
// NOTE: If our type is trivial when not wrapped in a
578-
// SILMoveOnlyWrappedType, this will return a trivial value. We rely
579-
// on the checker to determine if this is an acceptable use of the
580-
// value.
581-
if (value->getType().isMoveOnly()) {
582-
if (value->getType().isMoveOnlyWrapped()) {
583-
value = SGF.B.createOwnedMoveOnlyWrapperToCopyableValue(
584-
PrologueLoc, value);
585-
} else {
586-
// Change this to be lexical and get rid of borrow scope?
587-
value = SGF.B.createMoveValue(PrologueLoc, value);
588-
}
589-
}
590-
}
591-
592-
// If we still have a non-trivial thing, emit code that will need to
593-
// be cleaned up. If we are now trivial, we do not need to cleanup
594-
// anything.
595-
if (!value->getType().isTrivial(SGF.F)) {
596-
if (vd->getAttrs().hasAttribute<NoImplicitCopyAttr>()) {
597-
value = SGF.B.createBeginBorrow(PrologueLoc, value,
598-
/*isLexical*/ true);
599-
value = SGF.B.createCopyValue(PrologueLoc, value);
600-
value = SGF.B.createOwnedCopyableToMoveOnlyWrapperValue(
601-
PrologueLoc, value);
602-
value = SGF.B.createMarkMustCheckInst(
603-
PrologueLoc, value,
604-
MarkMustCheckInst::CheckKind::NoImplicitCopy);
605-
} else {
606-
value = SGF.B.createBeginBorrow(PrologueLoc, value,
607-
/*isLexical*/ true);
608-
}
609-
}
610-
}
611-
} else {
612-
if (SGF.getASTContext().LangOpts.Features.count(Feature::MoveOnly) &&
613-
vd->getAttrs().hasAttribute<NoImplicitCopyAttr>() &&
614-
value->getType().isTrivial(SGF.F)) {
615-
// We are abusing this. This should be a separate instruction just for
616-
// converting from copyable trivial to move only. I am abusing it
617-
// here by using it multiple times in different ways.
618-
value = SGF.B.createOwnedCopyableToMoveOnlyWrapperValue(PrologueLoc,
619-
value);
620-
value = SGF.B.createMoveValue(PrologueLoc, value, /*isLexical*/ true);
621-
value = SGF.B.createMarkMustCheckInst(
622-
PrologueLoc, value, MarkMustCheckInst::CheckKind::NoImplicitCopy);
623-
}
624-
}
633+
value = getValueForLexicalLifetimeBinding(SGF, PrologueLoc, value,
634+
wasPlusOne);
625635
}
626636

627637
SGF.VarLocs[vd] = SILGenFunction::VarLoc::get(value);

0 commit comments

Comments
 (0)