diff --git a/include/swift/SIL/SILModule.h b/include/swift/SIL/SILModule.h index 81a526c98f0..13764eee1c8 100644 --- a/include/swift/SIL/SILModule.h +++ b/include/swift/SIL/SILModule.h @@ -113,6 +113,7 @@ private: /// Lookup table for SIL functions. This needs to be declared before \p /// functions so that the destructor of \p functions is called first. llvm::StringMap FunctionTable; + llvm::StringMap ZombieFunctionTable; /// The list of SILFunctions in the module. FunctionListType functions; @@ -226,6 +227,11 @@ public: /// Erase a function from the module. void eraseFunction(SILFunction *F); + /// Specialization can cause a function that was erased before by dead function + /// elimination to become alive again. If this happens we need to remove it + /// from the list of zombies. + void removeFromZombieList(StringRef Name); + /// Erase a global SIL variable from the module. void eraseGlobalVariable(SILGlobalVariable *G); diff --git a/lib/SIL/SILFunction.cpp b/lib/SIL/SILFunction.cpp index 30ad2ac6504..13ab46e708b 100644 --- a/lib/SIL/SILFunction.cpp +++ b/lib/SIL/SILFunction.cpp @@ -95,6 +95,8 @@ SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage, else Module.functions.push_back(this); + Module.removeFromZombieList(Name); + // Set our BB list to have this function as its parent. This enables us to // splice efficiently basic blocks in between functions. BlockList.Parent = this; diff --git a/lib/SIL/SILModule.cpp b/lib/SIL/SILModule.cpp index 5c73a6285ca..e29637e0226 100644 --- a/lib/SIL/SILModule.cpp +++ b/lib/SIL/SILModule.cpp @@ -512,6 +512,13 @@ void SILModule::invalidateSILLoaderCaches() { getSILLoader()->invalidateCaches(); } +void SILModule::removeFromZombieList(StringRef Name) { + if (auto *Zombie = ZombieFunctionTable.lookup(Name)) { + ZombieFunctionTable.erase(Name); + zombieFunctions.remove(Zombie); + } +} + /// Erase a function from the module. void SILModule::eraseFunction(SILFunction *F) { @@ -529,6 +536,7 @@ void SILModule::eraseFunction(SILFunction *F) { // or vtable stub generation. So we move it into the zombie list. getFunctionList().remove(F); zombieFunctions.push_back(F); + ZombieFunctionTable[copiedName] = F; F->setZombie(); // This opens dead-function-removal opportunities for called functions.