Skip to content

Commit ff30221

Browse files
committed
[OpaqueValues] Fix closure handling.
Rewrote and tested all currently emittable variations of closure handling for opaque values.
1 parent dade867 commit ff30221

File tree

3 files changed

+451
-22
lines changed

3 files changed

+451
-22
lines changed

lib/SILGen/SILGenFunction.cpp

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -650,15 +650,46 @@ void SILGenFunction::emitCaptures(SILLocation loc,
650650

651651
// Get an address value for a SILValue if it is address only in an type
652652
// expansion context without opaque archetype substitution.
653-
auto getAddressValue = [&](SILValue entryValue, bool forceCopy) -> SILValue {
654-
if (SGM.M.useLoweredAddresses()
655-
&& SGM.Types
656-
.getTypeLowering(
657-
valueType,
658-
TypeExpansionContext::noOpaqueTypeArchetypesSubstitution(
659-
expansion.getResilienceExpansion()))
660-
.isAddressOnly()
661-
&& !entryValue->getType().isAddress()) {
653+
auto getAddressValue = [&](SILValue entryValue, bool forceCopy,
654+
bool forLValue) -> SILValue {
655+
if (!SGM.M.useLoweredAddresses() && !forLValue && !isPack) {
656+
// In opaque values mode, addresses aren't used except by lvalues.
657+
auto &lowering = getTypeLowering(entryValue->getType());
658+
if (entryValue->getType().isAddress()) {
659+
// If the value is currently an address, load it, copying if needed.
660+
if (lowering.isTrivial()) {
661+
SILValue result = lowering.emitLoad(
662+
B, loc, entryValue, LoadOwnershipQualifier::Trivial);
663+
return result;
664+
}
665+
if (forceCopy) {
666+
SILValue result =
667+
lowering.emitLoadOfCopy(B, loc, entryValue, IsNotTake);
668+
enterDestroyCleanup(result);
669+
return result;
670+
} else {
671+
auto load = B.createLoadBorrow(
672+
loc, ManagedValue::forBorrowedRValue(entryValue))
673+
.getValue();
674+
return load;
675+
}
676+
} else {
677+
// Otherwise, just return it, copying if needed.
678+
if (forceCopy && !lowering.isTrivial()) {
679+
auto result = B.emitCopyValueOperation(loc, entryValue);
680+
// enterDestroyCleanup(result);
681+
return result;
682+
}
683+
return entryValue;
684+
}
685+
} else if (SGM.M.useLoweredAddresses() &&
686+
SGM.Types
687+
.getTypeLowering(
688+
valueType, TypeExpansionContext::
689+
noOpaqueTypeArchetypesSubstitution(
690+
expansion.getResilienceExpansion()))
691+
.isAddressOnly() &&
692+
!entryValue->getType().isAddress()) {
662693

663694
assert(!isPack);
664695

@@ -684,7 +715,6 @@ void SILGenFunction::emitCaptures(SILLocation loc,
684715
if (!forceCopy)
685716
enterDestroyCleanup(addr);
686717
return addr;
687-
688718
} else if (forceCopy) {
689719
// We cannot pass a valid SILDebugVariable while creating the temp here
690720
// See rdar://60425582
@@ -755,26 +785,38 @@ void SILGenFunction::emitCaptures(SILLocation loc,
755785
if (canGuarantee) {
756786
// No-escaping stored declarations are captured as the
757787
// address of the value.
758-
auto addr = getAddressValue(val, /*forceCopy=*/false);
759-
capturedArgs.push_back(ManagedValue::forBorrowedRValue(addr));
760-
}
761-
else if (!silConv.useLoweredAddresses()) {
762-
capturedArgs.push_back(B.copyOwnedObjectRValue(
763-
loc, val, ManagedValue::ScopeKind::Lexical));
788+
auto addr =
789+
getAddressValue(val, /*forceCopy=*/false, /*forLValue=*/false);
790+
capturedArgs.push_back(
791+
addr->getOwnershipKind() == OwnershipKind::Owned
792+
? ManagedValue::forOwnedRValue(addr, CleanupHandle::invalid())
793+
: ManagedValue::forBorrowedRValue(addr));
764794
} else {
765-
auto addr = getAddressValue(val, /*forceCopy=*/true);
795+
auto addr =
796+
getAddressValue(val, /*forceCopy=*/true, /*forLValue=*/false);
797+
if (!useLoweredAddresses()) {
798+
auto &lowering = getTypeLowering(addr->getType());
799+
auto rvalue =
800+
lowering.isTrivial()
801+
? ManagedValue::forObjectRValueWithoutOwnership(addr)
802+
: ManagedValue::forOwnedRValue(addr,
803+
CleanupHandle::invalid());
804+
capturedArgs.push_back(rvalue);
805+
break;
806+
}
766807
// If our address is move only wrapped, unwrap it.
767808
if (addr->getType().isMoveOnlyWrapped()) {
768809
addr = B.createMoveOnlyWrapperToCopyableAddr(loc, addr);
769810
}
770-
capturedArgs.push_back(ManagedValue::forLValue(addr));
811+
capturedArgs.push_back(ManagedValue::forOwnedAddressRValue(
812+
addr, CleanupHandle::invalid()));
771813
}
772814
break;
773815
}
774816
case CaptureKind::StorageAddress: {
775817
assert(!isPack);
776818

777-
auto addr = getAddressValue(val, /*forceCopy=*/false);
819+
auto addr = getAddressValue(val, /*forceCopy=*/false, /*forLValue=*/true);
778820

779821
// No-escaping stored declarations are captured as the
780822
// address of the value.

lib/SILGen/SILGenProlog.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,12 +1130,13 @@ static void emitCaptureArguments(SILGenFunction &SGF,
11301130
LLVM_FALLTHROUGH;
11311131

11321132
case CaptureKind::Immutable: {
1133+
auto argIndex = SGF.F.begin()->getNumArguments();
11331134
// Non-escaping stored decls are captured as the address of the value.
1134-
auto argConv = SGF.F.getConventions().getSILArgumentConvention(
1135-
SGF.F.begin()->getNumArguments());
1135+
auto argConv = SGF.F.getConventions().getSILArgumentConvention(argIndex);
11361136
bool isInOut = (argConv == SILArgumentConvention::Indirect_Inout ||
11371137
argConv == SILArgumentConvention::Indirect_InoutAliasable);
1138-
if (isInOut || SGF.SGM.M.useLoweredAddresses()) {
1138+
auto param = SGF.F.getConventions().getParamInfoForSILArg(argIndex);
1139+
if (SGF.F.getConventions().isSILIndirect(param)) {
11391140
ty = ty.getAddressType();
11401141
}
11411142
auto *fArg = SGF.F.begin()->createFunctionArgument(ty, VD);

0 commit comments

Comments
 (0)