SILModule: track opened archetypes per function.

In theory we could map opened archetypes per module because opened archetypes _should_ be unique across the module.
But currently in some rare cases SILGen re-uses the same opened archetype in multiple functions.
The fix is to add the SILFunction to the map's key.
That also requires that we update the map whenever instructions are moved from one function to another.

This fixes a compiler crash.

rdar://76916931
This commit is contained in:
Erik Eckstein
2021-04-23 14:13:26 +02:00
parent 619226b480
commit eecb9fa975
8 changed files with 118 additions and 28 deletions

View File

@@ -724,8 +724,9 @@ void SILModule::registerDeserializationNotificationHandler(
deserializationNotificationHandlers.add(std::move(handler));
}
SILValue SILModule::getOpenedArchetypeDef(CanArchetypeType archetype) {
SILValue &def = openedArchetypeDefs[archetype];
SILValue SILModule::getOpenedArchetypeDef(CanArchetypeType archetype,
SILFunction *inFunction) {
SILValue &def = openedArchetypeDefs[{archetype, inFunction}];
if (!def) {
numUnresolvedOpenedArchetypes++;
def = ::new PlaceholderValue(SILType::getPrimitiveAddressType(archetype));
@@ -741,7 +742,7 @@ bool SILModule::hasUnresolvedOpenedArchetypeDefinitions() {
void SILModule::notifyAddedInstruction(SILInstruction *inst) {
if (auto *svi = dyn_cast<SingleValueInstruction>(inst)) {
if (CanArchetypeType archeTy = svi->getOpenedArchetype()) {
SILValue &val = openedArchetypeDefs[archeTy];
SILValue &val = openedArchetypeDefs[{archeTy, inst->getFunction()}];
if (val) {
if (!isa<PlaceholderValue>(val)) {
// Print a useful error message (and not just abort with an assert).
@@ -765,6 +766,19 @@ void SILModule::notifyAddedInstruction(SILInstruction *inst) {
}
}
void SILModule::notifyMovedInstruction(SILInstruction *inst,
SILFunction *fromFunction) {
if (auto *svi = dyn_cast<SingleValueInstruction>(inst)) {
if (CanArchetypeType archeTy = svi->getOpenedArchetype()) {
OpenedArchetypeKey key = {archeTy, fromFunction};
assert(openedArchetypeDefs.lookup(key) == svi &&
"archetype def was not registered");
openedArchetypeDefs.erase(key);
openedArchetypeDefs[{archeTy, svi->getFunction()}] = svi;
}
}
}
void SILModule::registerDeleteNotificationHandler(
DeleteNotificationHandler *handler) {
// Ask the handler (that can be an analysis, a pass, or some other data
@@ -783,9 +797,10 @@ void SILModule::notifyDeleteHandlers(SILNode *node) {
// Update openedArchetypeDefs.
if (auto *svi = dyn_cast<SingleValueInstruction>(node)) {
if (CanArchetypeType archeTy = svi->getOpenedArchetype()) {
assert(openedArchetypeDefs.lookup(archeTy) == svi &&
OpenedArchetypeKey key = {archeTy, svi->getFunction()};
assert(openedArchetypeDefs.lookup(key) == svi &&
"archetype def was not registered");
openedArchetypeDefs.erase(archeTy);
openedArchetypeDefs.erase(key);
}
}