[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

@@ -226,14 +226,8 @@ private:
/// The stage of processing this module is at.
SILStage Stage;
/// The callback used by the SILLoader.
std::unique_ptr<SerializationCallback> Callback;
// Callbacks registered by the SIL optimizer to run on each deserialized
// function body. This is intentionally a stateless type because the
// ModuleDecl and SILFunction should be sufficient context.
using SILFunctionBodyCallback = void (*)(ModuleDecl *, SILFunction *F);
SmallVector<SILFunctionBodyCallback, 0> DeserializationCallbacks;
/// The set of deserialization notification handlers.
DeserializationNotificationHandlerSet deserializationNotificationHandlers;
/// The SILLoader used when linking functions into this module.
///
@@ -283,10 +277,19 @@ public:
~SILModule();
/// Add a callback for each newly deserialized SIL function body.
void registerDeserializationCallback(SILFunctionBodyCallback callBack);
void registerDeserializationNotificationHandler(
std::unique_ptr<DeserializationNotificationHandler> &&handler);
/// Return set of registered deserialization callbacks.
ArrayRef<SILFunctionBodyCallback> getDeserializationCallbacks();
/// Return the set of registered deserialization callbacks.
DeserializationNotificationHandlerSet::range
getDeserializationHandlers() const {
return deserializationNotificationHandlers.getRange();
}
void removeDeserializationNotificationHandler(
DeserializationNotificationHandler *handler) {
deserializationNotificationHandlers.erase(handler);
}
/// Add a delete notification handler \p Handler to the module context.
void registerDeleteNotificationHandler(DeleteNotificationHandler* Handler);