[sil-optimizer] Centralize how we send out serialization notifications.

Previously SILModule contained two different pathways for the deserializer to
send notifications that it had created functions:

1. A list of function pointers that were called when a function's body was
deserialized. This was added recently so that access enforcement elimination is
run on newly deserialized SIL code if we have already eliminated access
enforcement from the module.

2. SILModule::SerializationCallback. This is an implementation of the full
callback interface and is used by the SILModule to update linkage and other
sorts of book keeping.

To fix the pass manager notification infrastructure, I need to be able to send
notifications to a SILPassManager when deserializing. I also need to be able to
eliminate these callbacks when a SILPassManager is destroyed. These requirements
are incompatible with the current two implementations since: (2) is an
implementation detail of SILModule and (1) only notifies on function bodies
being deserialized instead of the creation of new declarations (what the caller
analysis wants).

Rather than adding a third group of callbacks, this commit refactors the
infrastructure in such a way that all of these use cases can use one
implementation. This is done by:

1. Lifting the interface of SerializedSILLoader::Callback into a base
notification protocol for deserialization called
DeserializationNotificationHandlerBase and its base no-op implementation into an
implementation of the aforementioned protocol:
DeserializationNotificationHandler.

2. Changing SILModule::SerializationCallback to implement
DeserializationNotificationHandler.

3. Creating a class called FunctionBodyDeserializationNotificationHandler that
takes in a function pointer and uses that to just override the
didDeserializeFunctionBody. This eliminates the need for the specific function
body deserialization list.

4. Replacing the state associated with the two other pathways with a single
DeserializationNotificationHandlerSet class that contains a set of
DeserializationNotificationHandler and chains notifications to them. This set
implements DeserializationNotificationHandlerBase so we know that its
implementation will always be in sync with DeserializationNotificationHandler.

rdar://42301529
This commit is contained in:
Michael Gottesman
2018-08-13 10:24:20 -07:00
parent cd7415025e
commit 872bf40e17
10 changed files with 352 additions and 105 deletions

View File

@@ -11,28 +11,30 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "sil-module"
#include "swift/Serialization/SerializedSILLoader.h"
#include "swift/SIL/SILModule.h"
#include "Linker.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/SIL/FormalLinkage.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILModule.h"
#include "swift/Strings.h"
#include "Linker.h"
#include "swift/SIL/SILVisitor.h"
#include "swift/SIL/SILValue.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/SIL/FormalLinkage.h"
#include "swift/SIL/Notifications.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILValue.h"
#include "swift/SIL/SILVisitor.h"
#include "swift/Serialization/SerializedSILLoader.h"
#include "swift/Strings.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/YAMLTraits.h"
#include <functional>
using namespace swift;
using namespace Lowering;
class SILModule::SerializationCallback : public SerializedSILLoader::Callback {
class SILModule::SerializationCallback final
: public DeserializationNotificationHandler {
void didDeserialize(ModuleDecl *M, SILFunction *fn) override {
updateLinkage(fn);
}
@@ -83,19 +85,21 @@ class SILModule::SerializationCallback : public SerializedSILLoader::Callback {
}
}
void didDeserializeFunctionBody(ModuleDecl *M, SILFunction *fn) override {
// Callbacks are currently applied in the order they are registered.
for (auto callBack : fn->getModule().getDeserializationCallbacks())
callBack(M, fn);
StringRef getName() const override {
return "SILModule::SerializationCallback";
}
};
SILModule::SILModule(ModuleDecl *SwiftModule, SILOptions &Options,
const DeclContext *associatedDC, bool wholeModule)
: TheSwiftModule(SwiftModule), AssociatedDeclContext(associatedDC),
Stage(SILStage::Raw), Callback(new SILModule::SerializationCallback()),
wholeModule(wholeModule), Options(Options), serialized(false),
SerializeSILAction(), Types(*this) {}
Stage(SILStage::Raw), wholeModule(wholeModule), Options(Options),
serialized(false), SerializeSILAction(), Types(*this) {
// We always add the base SILModule serialization callback.
std::unique_ptr<DeserializationNotificationHandler> callback(
new SILModule::SerializationCallback());
deserializationNotificationHandlers.add(std::move(callback));
}
SILModule::~SILModule() {
// Decrement ref count for each SILGlobalVariable with static initializers.
@@ -469,8 +473,8 @@ SILVTable *SILModule::lookUpVTable(const ClassDecl *C) {
SerializedSILLoader *SILModule::getSILLoader() {
// If the SILLoader is null, create it.
if (!SILLoader)
SILLoader = SerializedSILLoader::create(getASTContext(), this,
Callback.get());
SILLoader = SerializedSILLoader::create(
getASTContext(), this, &deserializationNotificationHandlers);
// Return the SerializedSILLoader.
return SILLoader.get();
}
@@ -569,25 +573,17 @@ lookUpFunctionInVTable(ClassDecl *Class, SILDeclRef Member) {
return nullptr;
}
void SILModule::registerDeserializationCallback(
SILFunctionBodyCallback callBack) {
if (std::find(DeserializationCallbacks.begin(),
DeserializationCallbacks.end(), callBack)
== DeserializationCallbacks.end())
DeserializationCallbacks.push_back(callBack);
void SILModule::registerDeserializationNotificationHandler(
std::unique_ptr<DeserializationNotificationHandler> &&handler) {
deserializationNotificationHandlers.add(std::move(handler));
}
ArrayRef<SILModule::SILFunctionBodyCallback>
SILModule::getDeserializationCallbacks() {
return DeserializationCallbacks;
}
void SILModule::
registerDeleteNotificationHandler(DeleteNotificationHandler* Handler) {
void SILModule::registerDeleteNotificationHandler(
DeleteNotificationHandler *handler) {
// Ask the handler (that can be an analysis, a pass, or some other data
// structure) if it wants to receive delete notifications.
if (Handler->needsNotifications()) {
NotificationHandlers.insert(Handler);
if (handler->needsNotifications()) {
NotificationHandlers.insert(handler);
}
}