Skip to content

Commit 37f2bc1

Browse files
committed
DI: Add non-working code for handling value_metatype when used on an address-only type
1 parent 7f2b01c commit 37f2bc1

File tree

3 files changed

+56
-26
lines changed

3 files changed

+56
-26
lines changed

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,10 @@ collectDelegatingInitUses(const DIMemoryObjectInfo &TheMemory,
14091409
Kind = DIUseKind::LoadForTypeOfSelf;
14101410
}
14111411
}
1412+
// value_metatype may also use the 'self' value directly, if it has an
1413+
// address-only type.
1414+
if (isa<ValueMetatypeInst>(User))
1415+
Kind = DIUseKind::TypeOfSelf;
14121416

14131417
// We can safely handle anything else as an escape. They should all happen
14141418
// after self.init is invoked.

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.h

+3
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,9 @@ enum DIUseKind {
281281
/// This instruction is a load that's only used to answer a `type(of: self)`
282282
/// question.
283283
LoadForTypeOfSelf,
284+
285+
/// This instruction is a value_metatype on the address of 'self'.
286+
TypeOfSelf
284287
};
285288

286289
/// This struct represents a single classified access to the memory object

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

+49-26
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ namespace {
460460
void handleStoreUse(unsigned UseID);
461461
void handleLoadUse(const DIMemoryUse &Use);
462462
void handleLoadForTypeOfSelfUse(DIMemoryUse &Use);
463+
void handleTypeOfSelfUse(DIMemoryUse &Use);
463464
void handleInOutUse(const DIMemoryUse &Use);
464465
void handleEscapeUse(const DIMemoryUse &Use);
465466

@@ -530,6 +531,7 @@ LifetimeChecker::LifetimeChecker(const DIMemoryObjectInfo &TheMemory,
530531
switch (Use.Kind) {
531532
case DIUseKind::Load:
532533
case DIUseKind::LoadForTypeOfSelf:
534+
case DIUseKind::TypeOfSelf:
533535
case DIUseKind::Escape:
534536
continue;
535537
case DIUseKind::Assign:
@@ -787,6 +789,9 @@ void LifetimeChecker::doIt() {
787789
case DIUseKind::LoadForTypeOfSelf:
788790
handleLoadForTypeOfSelfUse(Use);
789791
break;
792+
case DIUseKind::TypeOfSelf:
793+
handleTypeOfSelfUse(Use);
794+
break;
790795
}
791796
}
792797

@@ -835,6 +840,35 @@ void LifetimeChecker::handleLoadUse(const DIMemoryUse &Use) {
835840
return handleLoadUseFailure(Use, IsSuperInitComplete, FailedSelfUse);
836841
}
837842

843+
static void replaceValueMetatypeInstWithMetatypeArgument(
844+
ValueMetatypeInst *valueMetatype) {
845+
SILValue metatypeArgument = valueMetatype->getFunction()->getSelfArgument();
846+
847+
// SILFunction parameter types never have a DynamicSelfType, since it only
848+
// makes sense in the context of a given method's body. Since the
849+
// value_metatype instruction might produce a DynamicSelfType we have to
850+
// cast the metatype argument.
851+
//
852+
// FIXME: Semantically, we're "opening" the class metatype here to produce
853+
// the "opened" DynamicSelfType. Ideally it would be modeled as an opened
854+
// archetype associated with the original metatype or class instance value,
855+
// instead of as a "global" type.
856+
auto metatypeSelfType = metatypeArgument->getType()
857+
.castTo<MetatypeType>().getInstanceType();
858+
auto valueSelfType = valueMetatype->getType()
859+
.castTo<MetatypeType>().getInstanceType();
860+
if (metatypeSelfType != valueSelfType) {
861+
assert(metatypeSelfType ==
862+
cast<DynamicSelfType>(valueSelfType).getSelfType());
863+
864+
SILBuilderWithScope B(valueMetatype);
865+
metatypeArgument = B.createUncheckedTrivialBitCast(
866+
valueMetatype->getLoc(), metatypeArgument,
867+
valueMetatype->getType());
868+
}
869+
replaceAllSimplifiedUsesAndErase(valueMetatype, metatypeArgument);
870+
}
871+
838872
void LifetimeChecker::handleLoadForTypeOfSelfUse(DIMemoryUse &Use) {
839873
bool IsSuperInitComplete, FailedSelfUse;
840874
// If the value is not definitively initialized, replace the
@@ -849,32 +883,7 @@ void LifetimeChecker::handleLoadForTypeOfSelfUse(DIMemoryUse &Use) {
849883
if (valueMetatype)
850884
break;
851885
}
852-
assert(valueMetatype);
853-
SILValue metatypeArgument = load->getFunction()->getSelfArgument();
854-
855-
// SILFunction parameter types never have a DynamicSelfType, since it only
856-
// makes sense in the context of a given method's body. Since the
857-
// value_metatype instruction might produce a DynamicSelfType we have to
858-
// cast the metatype argument.
859-
//
860-
// FIXME: Semantically, we're "opening" the class metatype here to produce
861-
// the "opened" DynamicSelfType. Ideally it would be modeled as an opened
862-
// archetype associated with the original metatype or class instance value,
863-
// instead of as a "global" type.
864-
auto metatypeSelfType = metatypeArgument->getType()
865-
.castTo<MetatypeType>().getInstanceType();
866-
auto valueSelfType = valueMetatype->getType()
867-
.castTo<MetatypeType>().getInstanceType();
868-
if (metatypeSelfType != valueSelfType) {
869-
assert(metatypeSelfType ==
870-
cast<DynamicSelfType>(valueSelfType).getSelfType());
871-
872-
SILBuilderWithScope B(valueMetatype);
873-
metatypeArgument = B.createUncheckedTrivialBitCast(
874-
valueMetatype->getLoc(), metatypeArgument,
875-
valueMetatype->getType());
876-
}
877-
replaceAllSimplifiedUsesAndErase(valueMetatype, metatypeArgument);
886+
replaceValueMetatypeInstWithMetatypeArgument(valueMetatype);
878887

879888
// Dead loads for type-of-self must be removed.
880889
// Otherwise it's a violation of memory lifetime.
@@ -889,6 +898,20 @@ void LifetimeChecker::handleLoadForTypeOfSelfUse(DIMemoryUse &Use) {
889898
}
890899
}
891900

901+
void LifetimeChecker::handleTypeOfSelfUse(DIMemoryUse &Use) {
902+
bool IsSuperInitComplete, FailedSelfUse;
903+
// If the value is not definitively initialized, replace the
904+
// value_metatype instruction with the metatype argument that was passed into
905+
// the initializer.
906+
if (!isInitializedAtUse(Use, &IsSuperInitComplete, &FailedSelfUse)) {
907+
auto *valueMetatype = cast<ValueMetatypeInst>(Use.Inst);
908+
replaceValueMetatypeInstWithMetatypeArgument(valueMetatype);
909+
910+
// Clear the Inst pointer just to be sure to avoid use-after-free.
911+
Use.Inst = nullptr;
912+
}
913+
}
914+
892915
void LifetimeChecker::emitSelfConsumedDiagnostic(SILInstruction *Inst) {
893916
if (!shouldEmitError(Inst))
894917
return;

0 commit comments

Comments
 (0)