Skip to content

Commit 18e8fea

Browse files
committed
SILGen: Kill OpaqueValueState and clean up code for opening existentials
OpaqueValueState used to store a SILValue, so back then the IsConsumable flag was meaningful. But now we can just check if the ManagedValue has a cleanup or not. Also, we were passing around an opened ArchetypeType for no good reason.
1 parent 3daf1c1 commit 18e8fea

File tree

6 files changed

+49
-138
lines changed

6 files changed

+49
-138
lines changed

lib/SILGen/SILGenBridging.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -703,11 +703,11 @@ static ManagedValue emitNativeToCBridgedNonoptionalValue(SILGenFunction &SGF,
703703

704704
FormalEvaluationScope scope(SGF);
705705

706-
auto openedExistential = SGF.emitOpenExistential(
707-
loc, v, openedType, SGF.getLoweredType(openedType),
706+
v = SGF.emitOpenExistential(
707+
loc, v, SGF.getLoweredType(openedType),
708708
AccessKind::Read);
709+
v = v.ensurePlusOne(SGF, loc);
709710

710-
v = SGF.manageOpaqueValue(openedExistential, loc, SGFContext());
711711
nativeType = openedType;
712712
}
713713

lib/SILGen/SILGenConvert.cpp

Lines changed: 15 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -923,27 +923,20 @@ ManagedValue SILGenFunction::emitProtocolMetatypeToObject(SILLocation loc,
923923
return emitManagedRValueWithCleanup(value);
924924
}
925925

926-
SILGenFunction::OpaqueValueState
926+
ManagedValue
927927
SILGenFunction::emitOpenExistential(
928928
SILLocation loc,
929929
ManagedValue existentialValue,
930-
ArchetypeType *openedArchetype,
931930
SILType loweredOpenedType,
932931
AccessKind accessKind) {
933932
assert(isInFormalEvaluationScope());
934933

935-
// Open the existential value into the opened archetype value.
936-
bool isUnique = true;
937-
bool canConsume;
938-
ManagedValue archetypeMV;
939-
940934
SILType existentialType = existentialValue.getType();
941935
switch (existentialType.getPreferredExistentialRepresentation(SGM.M)) {
942936
case ExistentialRepresentation::Opaque: {
943937
// With CoW existentials we can't consume the boxed value inside of
944938
// the existential. (We could only do so after a uniqueness check on
945939
// the box holding the value).
946-
canConsume = false;
947940
if (existentialType.isAddress()) {
948941
OpenedExistentialAccess allowedAccess =
949942
getOpenedExistentialAccessFor(accessKind);
@@ -956,28 +949,20 @@ SILGenFunction::emitOpenExistential(
956949
SILValue archetypeValue =
957950
B.createOpenExistentialAddr(loc, existentialValue.getValue(),
958951
loweredOpenedType, allowedAccess);
959-
archetypeMV = ManagedValue::forUnmanaged(archetypeValue);
952+
return ManagedValue::forUnmanaged(archetypeValue);
960953
} else {
961954
// borrow the existential and return an unmanaged opened value.
962-
archetypeMV = getBuilder().createOpenExistentialValue(
955+
return B.createOpenExistentialValue(
963956
loc, existentialValue, loweredOpenedType);
964957
}
965-
break;
966958
}
967959
case ExistentialRepresentation::Metatype:
968960
assert(existentialType.isObject());
969-
archetypeMV = B.createOpenExistentialMetatype(
961+
return B.createOpenExistentialMetatype(
970962
loc, existentialValue, loweredOpenedType);
971-
// Metatypes are always trivial. Consuming would be a no-op.
972-
canConsume = false;
973-
break;
974-
case ExistentialRepresentation::Class: {
963+
case ExistentialRepresentation::Class:
975964
assert(existentialType.isObject());
976-
archetypeMV =
977-
B.createOpenExistentialRef(loc, existentialValue, loweredOpenedType);
978-
canConsume = archetypeMV.hasCleanup();
979-
break;
980-
}
965+
return B.createOpenExistentialRef(loc, existentialValue, loweredOpenedType);
981966
case ExistentialRepresentation::Boxed:
982967
if (existentialType.isAddress()) {
983968
existentialValue = emitLoad(loc, existentialValue.getValue(),
@@ -989,67 +974,43 @@ SILGenFunction::emitOpenExistential(
989974
existentialType = existentialValue.getType();
990975
assert(existentialType.isObject());
991976
if (loweredOpenedType.isAddress()) {
992-
archetypeMV = ManagedValue::forUnmanaged(
977+
return ManagedValue::forUnmanaged(
993978
B.createOpenExistentialBox(loc, existentialValue.getValue(),
994979
loweredOpenedType));
995980
} else {
996981
assert(!silConv.useLoweredAddresses());
997-
archetypeMV = getBuilder().createOpenExistentialBoxValue(
982+
return B.createOpenExistentialBoxValue(
998983
loc, existentialValue, loweredOpenedType);
999984
}
1000-
// NB: Don't forward the cleanup, because consuming a boxed value won't
1001-
// consume the box reference.
1002-
// The boxed value can't be assumed to be uniquely referenced.
1003-
// We can never consume it.
1004-
// TODO: We could use isUniquelyReferenced to shorten the duration of
1005-
// the box to the point that the opaque value is copied out.
1006-
isUnique = false;
1007-
canConsume = false;
1008-
break;
1009985
case ExistentialRepresentation::None:
1010986
llvm_unreachable("not existential");
1011987
}
1012-
1013-
assert(!canConsume || isUnique); (void) isUnique;
1014-
1015-
return SILGenFunction::OpaqueValueState{
1016-
archetypeMV,
1017-
/*isConsumable*/ canConsume,
1018-
/*hasBeenConsumed*/ false
1019-
};
1020988
}
1021989

1022-
ManagedValue SILGenFunction::manageOpaqueValue(OpaqueValueState &entry,
990+
ManagedValue SILGenFunction::manageOpaqueValue(ManagedValue value,
1023991
SILLocation loc,
1024992
SGFContext C) {
1025993
// If the opaque value is consumable, we can just return the
1026994
// value with a cleanup. There is no need to retain it separately.
1027-
if (entry.IsConsumable) {
1028-
assert(!entry.HasBeenConsumed
1029-
&& "Uniquely-referenced opaque value already consumed");
1030-
entry.HasBeenConsumed = true;
1031-
return entry.Value;
1032-
}
1033-
1034-
assert(!entry.Value.hasCleanup());
995+
if (value.hasCleanup())
996+
return value;
1035997

1036998
// If the context wants a +0 value, guaranteed or immediate, we can
1037999
// give it to them, because OpenExistential emission guarantees the
10381000
// value.
1039-
if (C.isGuaranteedPlusZeroOk()) {
1040-
return entry.Value;
1041-
}
1001+
if (C.isGuaranteedPlusZeroOk())
1002+
return value;
10421003

10431004
// If the context has an initialization a buffer, copy there instead
10441005
// of making a temporary allocation.
10451006
if (auto I = C.getEmitInto()) {
1046-
I->copyOrInitValueInto(*this, loc, entry.Value, /*init*/ false);
1007+
I->copyOrInitValueInto(*this, loc, value, /*init*/ false);
10471008
I->finishInitialization(*this);
10481009
return ManagedValue::forInContext();
10491010
}
10501011

10511012
// Otherwise, copy the value into a temporary.
1052-
return entry.Value.copyUnmanaged(*this, loc);
1013+
return value.copyUnmanaged(*this, loc);
10531014
}
10541015

10551016
ManagedValue SILGenFunction::emitConvertedRValue(Expr *E,

lib/SILGen/SILGenExpr.cpp

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2436,15 +2436,11 @@ emitKeyPathRValueBase(SILGenFunction &subSGF,
24362436

24372437
baseType = opened->getCanonicalType();
24382438
auto openedOpaqueValue = subSGF.emitOpenExistential(loc, paramSubstValue,
2439-
opened, subSGF.getLoweredType(baseType),
2439+
subSGF.getLoweredType(baseType),
24402440
AccessKind::Read);
24412441
// Maybe we could peephole this if we know the property load can borrow the
24422442
// base value…
2443-
if (!openedOpaqueValue.IsConsumable) {
2444-
paramSubstValue = openedOpaqueValue.Value.copyUnmanaged(subSGF, loc);
2445-
} else {
2446-
paramSubstValue = openedOpaqueValue.Value;
2447-
}
2443+
paramSubstValue = openedOpaqueValue.ensurePlusOne(subSGF, loc);
24482444
}
24492445

24502446
// Upcast a class instance to the property's declared type if necessary.
@@ -4830,14 +4826,14 @@ void SILGenFunction::emitOpenExistentialExprImpl(
48304826
SGFContext::AllowGuaranteedPlusZero);
48314827

48324828
Type opaqueValueType = E->getOpaqueValue()->getType()->getRValueType();
4833-
auto state = emitOpenExistential(
4834-
E, existentialValue, E->getOpenedArchetype(),
4829+
auto payload = emitOpenExistential(
4830+
E, existentialValue,
48354831
getLoweredType(opaqueValueType),
48364832
AccessKind::Read);
48374833

48384834
// Register the opaque value for the projected existential.
48394835
SILGenFunction::OpaqueValueRAII opaqueValueRAII(
4840-
*this, E->getOpaqueValue(), state);
4836+
*this, E->getOpaqueValue(), payload);
48414837

48424838
emitSubExpr(E->getSubExpr());
48434839
}
@@ -4867,13 +4863,9 @@ RValue RValueEmitter::visitMakeTemporarilyEscapableExpr(
48674863
auto visitSubExpr = [&](ManagedValue escapingClosure,
48684864
bool isClosureConsumable) -> RValue {
48694865
// Bind the opaque value to the escaping function.
4870-
SILGenFunction::OpaqueValueState opaqueValue{
4871-
escapingClosure,
4872-
/*consumable*/ isClosureConsumable,
4873-
/*hasBeenConsumed*/ false,
4874-
};
4866+
assert(isClosureConsumable == escapingClosure.hasCleanup());
48754867
SILGenFunction::OpaqueValueRAII pushOpaqueValue(SGF, E->getOpaqueValue(),
4876-
opaqueValue);
4868+
escapingClosure);
48774869

48784870
// Emit the guarded expression.
48794871
return visit(E->getSubExpr(), C);
@@ -4907,8 +4899,8 @@ RValue RValueEmitter::visitMakeTemporarilyEscapableExpr(
49074899

49084900
RValue RValueEmitter::visitOpaqueValueExpr(OpaqueValueExpr *E, SGFContext C) {
49094901
assert(SGF.OpaqueValues.count(E) && "Didn't bind OpaqueValueExpr");
4910-
auto &entry = SGF.OpaqueValues[E];
4911-
return RValue(SGF, E, SGF.manageOpaqueValue(entry, E, C));
4902+
auto value = SGF.OpaqueValues[E];
4903+
return RValue(SGF, E, SGF.manageOpaqueValue(value, E, C));
49124904
}
49134905

49144906
ProtocolDecl *SILGenFunction::getPointerProtocol() {

lib/SILGen/SILGenFunction.h

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -971,28 +971,19 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
971971
CanType inputTy,
972972
SILType resultTy);
973973

974-
struct OpaqueValueState {
975-
ManagedValue Value;
976-
bool IsConsumable;
977-
bool HasBeenConsumed;
978-
};
979-
980-
ManagedValue manageOpaqueValue(OpaqueValueState &entry,
974+
ManagedValue manageOpaqueValue(ManagedValue value,
981975
SILLocation loc,
982976
SGFContext C);
983977

984978
/// Open up the given existential value and project its payload.
985979
///
986980
/// \param existentialValue The existential value.
987-
/// \param openedArchetype The opened existential archetype.
988981
/// \param loweredOpenedType The lowered type of the projection, which in
989982
/// practice will be the openedArchetype, possibly wrapped in a metatype.
990-
OpaqueValueState
991-
emitOpenExistential(SILLocation loc,
992-
ManagedValue existentialValue,
993-
ArchetypeType *openedArchetype,
994-
SILType loweredOpenedType,
995-
AccessKind accessKind);
983+
ManagedValue emitOpenExistential(SILLocation loc,
984+
ManagedValue existentialValue,
985+
SILType loweredOpenedType,
986+
AccessKind accessKind);
996987

997988
/// Wrap the given value in an existential container.
998989
///
@@ -1544,9 +1535,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
15441535
emitOpenExistentialExprImpl(e, emitSubExpr);
15451536
}
15461537

1547-
/// Mapping from active opaque value expressions to their values,
1548-
/// along with a bit for each indicating whether it has been consumed yet.
1549-
llvm::SmallDenseMap<OpaqueValueExpr *, OpaqueValueState>
1538+
/// Mapping from active opaque value expressions to their values.
1539+
llvm::SmallDenseMap<OpaqueValueExpr *, ManagedValue>
15501540
OpaqueValues;
15511541

15521542
/// A mapping from opaque value expressions to the open-existential
@@ -1568,11 +1558,11 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
15681558

15691559
public:
15701560
OpaqueValueRAII(SILGenFunction &self, OpaqueValueExpr *opaqueValue,
1571-
OpaqueValueState state)
1561+
ManagedValue value)
15721562
: Self(self), OpaqueValue(opaqueValue) {
15731563
assert(Self.OpaqueValues.count(OpaqueValue) == 0 &&
15741564
"Opaque value already has a binding");
1575-
Self.OpaqueValues[OpaqueValue] = state;
1565+
Self.OpaqueValues[OpaqueValue] = value;
15761566
}
15771567

15781568
~OpaqueValueRAII();

lib/SILGen/SILGenLValue.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2731,14 +2731,11 @@ LValue SILGenLValue::visitOpaqueValueExpr(OpaqueValueExpr *e,
27312731
}
27322732

27332733
assert(SGF.OpaqueValues.count(e) && "Didn't bind OpaqueValueExpr");
2734-
2735-
auto &entry = SGF.OpaqueValues.find(e)->second;
2736-
assert(!entry.HasBeenConsumed && "opaque value already consumed");
2737-
entry.HasBeenConsumed = true;
2734+
auto value = SGF.OpaqueValues[e];
27382735

27392736
RegularLocation loc(e);
27402737
LValue lv;
2741-
lv.add<ValueComponent>(entry.Value.formalAccessBorrow(SGF, loc), None,
2738+
lv.add<ValueComponent>(value.formalAccessBorrow(SGF, loc), None,
27422739
getValueTypeData(SGF, accessKind, e));
27432740
return lv;
27442741
}

lib/SILGen/SILGenPoly.cpp

Lines changed: 11 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,6 @@ collectExistentialConformances(ModuleDecl *M, CanType fromType, CanType toType)
182182
return M->getASTContext().AllocateCopy(conformances);
183183
}
184184

185-
static ArchetypeType *getOpenedArchetype(CanType openedType) {
186-
while (auto metatypeTy = dyn_cast<MetatypeType>(openedType))
187-
openedType = metatypeTy.getInstanceType();
188-
return cast<ArchetypeType>(openedType);
189-
}
190-
191185
static ManagedValue emitTransformExistential(SILGenFunction &SGF,
192186
SILLocation loc,
193187
ManagedValue input,
@@ -198,17 +192,11 @@ static ManagedValue emitTransformExistential(SILGenFunction &SGF,
198192

199193
FormalEvaluationScope scope(SGF);
200194

201-
SILGenFunction::OpaqueValueState state;
202-
ArchetypeType *openedArchetype = nullptr;
203-
204195
if (inputType->isAnyExistentialType()) {
205196
CanType openedType = OpenedArchetypeType::getAny(inputType);
206197
SILType loweredOpenedType = SGF.getLoweredType(openedType);
207198

208-
// Unwrap zero or more metatype levels
209-
openedArchetype = getOpenedArchetype(openedType);
210-
211-
state = SGF.emitOpenExistential(loc, input, openedArchetype,
199+
input = SGF.emitOpenExistential(loc, input,
212200
loweredOpenedType, AccessKind::Read);
213201
inputType = openedType;
214202
}
@@ -235,20 +223,12 @@ static ManagedValue emitTransformExistential(SILGenFunction &SGF,
235223
AbstractionPattern opaque = AbstractionPattern::getOpaque();
236224
const TypeLowering &concreteTL = SGF.getTypeLowering(opaque, inputType);
237225
const TypeLowering &expectedTL = SGF.getTypeLowering(outputType);
238-
input = SGF.emitExistentialErasure(
226+
return SGF.emitExistentialErasure(
239227
loc, inputType, concreteTL, expectedTL,
240228
conformances, ctxt,
241229
[&](SGFContext C) -> ManagedValue {
242-
if (openedArchetype)
243-
return SGF.manageOpaqueValue(state, loc, C);
244-
if (input.isPlusOne(SGF))
245-
return input;
246-
if (C.isGuaranteedPlusZeroOk())
247-
return input;
248-
return input.copyUnmanaged(SGF, loc);
230+
return SGF.manageOpaqueValue(input, loc, C);
249231
});
250-
251-
return input;
252232
}
253233

254234
/// Apply this transformation to an arbitrary value.
@@ -593,15 +573,12 @@ ManagedValue Transform::transform(ManagedValue v,
593573
CanType openedType = OpenedArchetypeType::getAny(inputSubstType);
594574
SILType loweredOpenedType = SGF.getLoweredType(openedType);
595575

596-
// Unwrap zero or more metatype levels
597-
auto openedArchetype = getOpenedArchetype(openedType);
598-
599576
FormalEvaluationScope scope(SGF);
600577

601-
auto state = SGF.emitOpenExistential(Loc, v, openedArchetype,
602-
loweredOpenedType,
603-
AccessKind::Read);
604-
auto payload = SGF.manageOpaqueValue(state, Loc, SGFContext());
578+
auto payload = SGF.emitOpenExistential(Loc, v,
579+
loweredOpenedType,
580+
AccessKind::Read);
581+
payload = payload.ensurePlusOne(SGF, Loc);
605582
return transform(payload,
606583
AbstractionPattern::getOpaque(),
607584
openedType,
@@ -3745,17 +3722,11 @@ emitOpenExistentialInSelfConformance(SILGenFunction &SGF, SILLocation loc,
37453722
SILDeclRef witness,
37463723
SubstitutionMap subs, ManagedValue value,
37473724
SILParameterInfo destParameter) {
3748-
auto typeAndConf = getSelfTypeAndConformanceForWitness(witness, subs);
3749-
auto archetype = typeAndConf.first->castTo<ArchetypeType>();
3750-
assert(archetype->isOpenedExistential());
3751-
37523725
auto openedTy = destParameter.getSILStorageType();
3753-
auto state = SGF.emitOpenExistential(loc, value, archetype, openedTy,
3754-
destParameter.isIndirectMutating()
3755-
? AccessKind::ReadWrite
3756-
: AccessKind::Read);
3757-
3758-
return state.Value;
3726+
return SGF.emitOpenExistential(loc, value, openedTy,
3727+
destParameter.isIndirectMutating()
3728+
? AccessKind::ReadWrite
3729+
: AccessKind::Read);
37593730
}
37603731

37613732
void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,

0 commit comments

Comments
 (0)