Skip to content

Commit 3c1e8bb

Browse files
authored
Merge pull request #60201 from gottesmm/pr-85df238aa56ab50a2caf47e27e7be0fbcdc0fea1
[silgen] Simplify some logic by refactoring code into some helper methods
2 parents d9969ad + c2e13f4 commit 3c1e8bb

File tree

2 files changed

+152
-120
lines changed

2 files changed

+152
-120
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);

lib/SILGen/SILGenProlog.cpp

Lines changed: 82 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,87 @@ struct ArgumentInitHelper {
256256
return argEmitter.visit(canTy, origTy);
257257
}
258258

259+
SILValue updateArgumentValueForBinding(ManagedValue argrv, SILLocation loc,
260+
ParamDecl *pd, SILValue value,
261+
const SILDebugVariable &varinfo) {
262+
// If we do not need to support lexical lifetimes, just return value as the
263+
// updated value.
264+
if (!SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule()))
265+
return value;
266+
267+
bool isNoImplicitCopy = false;
268+
if (auto *arg = dyn_cast<SILFunctionArgument>(value))
269+
isNoImplicitCopy = arg->isNoImplicitCopy();
270+
271+
// If we have a no implicit copy argument and the argument is trivial,
272+
// we need to use copyable to move only to convert it to its move only
273+
// form.
274+
if (!isNoImplicitCopy) {
275+
if (!value->getType().isMoveOnly()) {
276+
if (value->getOwnershipKind() == OwnershipKind::Owned) {
277+
value =
278+
SILValue(SGF.B.createBeginBorrow(loc, value, /*isLexical*/ true));
279+
SGF.Cleanups.pushCleanup<EndBorrowCleanup>(value);
280+
}
281+
return value;
282+
}
283+
284+
// At this point, we have a move only type.
285+
if (value->getOwnershipKind() == OwnershipKind::Owned) {
286+
value = SGF.B.createMoveValue(loc, argrv.forward(SGF),
287+
/*isLexical*/ true);
288+
value = SGF.B.createMarkMustCheckInst(
289+
loc, value, MarkMustCheckInst::CheckKind::NoImplicitCopy);
290+
SGF.emitManagedRValueWithCleanup(value);
291+
return value;
292+
}
293+
294+
assert(value->getOwnershipKind() == OwnershipKind::Guaranteed);
295+
value = SGF.B.createCopyValue(loc, value);
296+
value = SGF.B.createMarkMustCheckInst(
297+
loc, value, MarkMustCheckInst::CheckKind::NoCopy);
298+
SGF.emitManagedRValueWithCleanup(value);
299+
return value;
300+
}
301+
302+
if (value->getType().isTrivial(SGF.F)) {
303+
value = SGF.B.createOwnedCopyableToMoveOnlyWrapperValue(loc, value);
304+
value = SGF.B.createMoveValue(loc, value, true /*is lexical*/);
305+
306+
// If our argument was owned, we use no implicit copy. Otherwise, we
307+
// use no copy.
308+
auto kind = MarkMustCheckInst::CheckKind::NoCopy;
309+
if (pd->isOwned())
310+
kind = MarkMustCheckInst::CheckKind::NoImplicitCopy;
311+
value = SGF.B.createMarkMustCheckInst(loc, value, kind);
312+
SGF.emitManagedRValueWithCleanup(value);
313+
return value;
314+
}
315+
316+
if (value->getOwnershipKind() == OwnershipKind::Guaranteed) {
317+
value = SGF.B.createGuaranteedCopyableToMoveOnlyWrapperValue(loc, value);
318+
value = SGF.B.createCopyValue(loc, value);
319+
value = SGF.B.createMarkMustCheckInst(
320+
loc, value, MarkMustCheckInst::CheckKind::NoCopy);
321+
SGF.emitManagedRValueWithCleanup(value);
322+
return value;
323+
}
324+
325+
if (value->getOwnershipKind() == OwnershipKind::Owned) {
326+
// If we have an owned value, forward it into the mark_must_check to
327+
// avoid an extra destroy_value.
328+
value = SGF.B.createOwnedCopyableToMoveOnlyWrapperValue(
329+
loc, argrv.forward(SGF));
330+
value = SGF.B.createMoveValue(loc, value, true /*is lexical*/);
331+
value = SGF.B.createMarkMustCheckInst(
332+
loc, value, MarkMustCheckInst::CheckKind::NoImplicitCopy);
333+
SGF.emitManagedRValueWithCleanup(value);
334+
return value;
335+
}
336+
337+
return value;
338+
}
339+
259340
/// Create a SILArgument and store its value into the given Initialization,
260341
/// if not null.
261342
void makeArgumentIntoBinding(Type ty, SILBasicBlock *parent, ParamDecl *pd) {
@@ -276,66 +357,7 @@ struct ArgumentInitHelper {
276357
SILValue value = argrv.getValue();
277358
SILDebugVariable varinfo(pd->isImmutable(), ArgNo);
278359
if (!argrv.getType().isAddress()) {
279-
if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(
280-
SGF.getModule())) {
281-
bool isNoImplicitCopy = false;
282-
if (auto *arg = dyn_cast<SILFunctionArgument>(value))
283-
isNoImplicitCopy = arg->isNoImplicitCopy();
284-
285-
// If we have a no implicit copy argument and the argument is trivial,
286-
// we need to use copyable to move only to convert it to its move only
287-
// form.
288-
if (isNoImplicitCopy) {
289-
if (value->getType().isTrivial(SGF.F)) {
290-
value = SGF.B.createOwnedCopyableToMoveOnlyWrapperValue(loc, value);
291-
value = SGF.B.createMoveValue(loc, value, true /*is lexical*/);
292-
293-
// If our argument was owned, we use no implicit copy. Otherwise, we
294-
// use no copy.
295-
auto kind = MarkMustCheckInst::CheckKind::NoCopy;
296-
if (pd->isOwned())
297-
kind = MarkMustCheckInst::CheckKind::NoImplicitCopy;
298-
value = SGF.B.createMarkMustCheckInst(loc, value, kind);
299-
SGF.emitManagedRValueWithCleanup(value);
300-
} else if (value->getOwnershipKind() == OwnershipKind::Guaranteed) {
301-
value = SGF.B.createGuaranteedCopyableToMoveOnlyWrapperValue(loc,
302-
value);
303-
value = SGF.B.createCopyValue(loc, value);
304-
value = SGF.B.createMarkMustCheckInst(
305-
loc, value, MarkMustCheckInst::CheckKind::NoCopy);
306-
SGF.emitManagedRValueWithCleanup(value);
307-
} else if (value->getOwnershipKind() == OwnershipKind::Owned) {
308-
// If we have an owned value, forward it into the mark_must_check to
309-
// avoid an extra destroy_value.
310-
value = SGF.B.createOwnedCopyableToMoveOnlyWrapperValue(
311-
loc, argrv.forward(SGF));
312-
value = SGF.B.createMoveValue(loc, value, true /*is lexical*/);
313-
value = SGF.B.createMarkMustCheckInst(
314-
loc, value, MarkMustCheckInst::CheckKind::NoImplicitCopy);
315-
SGF.emitManagedRValueWithCleanup(value);
316-
}
317-
} else if (value->getType().isMoveOnly()) {
318-
if (value->getOwnershipKind() == OwnershipKind::Owned) {
319-
value = SGF.B.createMoveValue(loc, argrv.forward(SGF),
320-
/*isLexical*/ true);
321-
value = SGF.B.createMarkMustCheckInst(
322-
loc, value, MarkMustCheckInst::CheckKind::NoImplicitCopy);
323-
SGF.emitManagedRValueWithCleanup(value);
324-
} else {
325-
assert(value->getOwnershipKind() == OwnershipKind::Guaranteed);
326-
value = SGF.B.createCopyValue(loc, value);
327-
value = SGF.B.createMarkMustCheckInst(
328-
loc, value, MarkMustCheckInst::CheckKind::NoCopy);
329-
SGF.emitManagedRValueWithCleanup(value);
330-
}
331-
} else {
332-
if (value->getOwnershipKind() == OwnershipKind::Owned) {
333-
value = SILValue(
334-
SGF.B.createBeginBorrow(loc, value, /*isLexical*/ true));
335-
SGF.Cleanups.pushCleanup<EndBorrowCleanup>(value);
336-
}
337-
}
338-
}
360+
value = updateArgumentValueForBinding(argrv, loc, pd, value, varinfo);
339361
SGF.B.createDebugValue(loc, value, varinfo);
340362
} else {
341363
if (auto *allocStack = dyn_cast<AllocStackInst>(value)) {

0 commit comments

Comments
 (0)