10b57cec5SDimitry Andric //===- PassRegistry.cpp - Pass Registration Implementation ----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the PassRegistry, with which passes are registered on
100b57cec5SDimitry Andric // initialization, and supports the PassManager in dependency resolution.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "llvm/PassRegistry.h"
150b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
165ffd83dbSDimitry Andric #include "llvm/Pass.h"
170b57cec5SDimitry Andric #include "llvm/PassInfo.h"
180b57cec5SDimitry Andric #include <cassert>
190b57cec5SDimitry Andric #include <memory>
200b57cec5SDimitry Andric #include <utility>
210b57cec5SDimitry Andric
220b57cec5SDimitry Andric using namespace llvm;
230b57cec5SDimitry Andric
getPassRegistry()240b57cec5SDimitry Andric PassRegistry *PassRegistry::getPassRegistry() {
25*753f127fSDimitry Andric static PassRegistry PassRegistryObj;
26*753f127fSDimitry Andric return &PassRegistryObj;
270b57cec5SDimitry Andric }
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
300b57cec5SDimitry Andric // Accessors
310b57cec5SDimitry Andric //
320b57cec5SDimitry Andric
330b57cec5SDimitry Andric PassRegistry::~PassRegistry() = default;
340b57cec5SDimitry Andric
getPassInfo(const void * TI) const350b57cec5SDimitry Andric const PassInfo *PassRegistry::getPassInfo(const void *TI) const {
360b57cec5SDimitry Andric sys::SmartScopedReader<true> Guard(Lock);
37e8d8bef9SDimitry Andric return PassInfoMap.lookup(TI);
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric
getPassInfo(StringRef Arg) const400b57cec5SDimitry Andric const PassInfo *PassRegistry::getPassInfo(StringRef Arg) const {
410b57cec5SDimitry Andric sys::SmartScopedReader<true> Guard(Lock);
42e8d8bef9SDimitry Andric return PassInfoStringMap.lookup(Arg);
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric
450b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
460b57cec5SDimitry Andric // Pass Registration mechanism
470b57cec5SDimitry Andric //
480b57cec5SDimitry Andric
registerPass(const PassInfo & PI,bool ShouldFree)490b57cec5SDimitry Andric void PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) {
500b57cec5SDimitry Andric sys::SmartScopedWriter<true> Guard(Lock);
510b57cec5SDimitry Andric bool Inserted =
520b57cec5SDimitry Andric PassInfoMap.insert(std::make_pair(PI.getTypeInfo(), &PI)).second;
530b57cec5SDimitry Andric assert(Inserted && "Pass registered multiple times!");
540b57cec5SDimitry Andric (void)Inserted;
550b57cec5SDimitry Andric PassInfoStringMap[PI.getPassArgument()] = &PI;
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric // Notify any listeners.
580b57cec5SDimitry Andric for (auto *Listener : Listeners)
590b57cec5SDimitry Andric Listener->passRegistered(&PI);
600b57cec5SDimitry Andric
610b57cec5SDimitry Andric if (ShouldFree)
620b57cec5SDimitry Andric ToFree.push_back(std::unique_ptr<const PassInfo>(&PI));
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric
enumerateWith(PassRegistrationListener * L)650b57cec5SDimitry Andric void PassRegistry::enumerateWith(PassRegistrationListener *L) {
660b57cec5SDimitry Andric sys::SmartScopedReader<true> Guard(Lock);
670b57cec5SDimitry Andric for (auto PassInfoPair : PassInfoMap)
680b57cec5SDimitry Andric L->passEnumerate(PassInfoPair.second);
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric /// Analysis Group Mechanisms.
registerAnalysisGroup(const void * InterfaceID,const void * PassID,PassInfo & Registeree,bool isDefault,bool ShouldFree)720b57cec5SDimitry Andric void PassRegistry::registerAnalysisGroup(const void *InterfaceID,
730b57cec5SDimitry Andric const void *PassID,
740b57cec5SDimitry Andric PassInfo &Registeree, bool isDefault,
750b57cec5SDimitry Andric bool ShouldFree) {
760b57cec5SDimitry Andric PassInfo *InterfaceInfo = const_cast<PassInfo *>(getPassInfo(InterfaceID));
770b57cec5SDimitry Andric if (!InterfaceInfo) {
780b57cec5SDimitry Andric // First reference to Interface, register it now.
790b57cec5SDimitry Andric registerPass(Registeree);
800b57cec5SDimitry Andric InterfaceInfo = &Registeree;
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric assert(Registeree.isAnalysisGroup() &&
830b57cec5SDimitry Andric "Trying to join an analysis group that is a normal pass!");
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric if (PassID) {
860b57cec5SDimitry Andric PassInfo *ImplementationInfo = const_cast<PassInfo *>(getPassInfo(PassID));
870b57cec5SDimitry Andric assert(ImplementationInfo &&
880b57cec5SDimitry Andric "Must register pass before adding to AnalysisGroup!");
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric sys::SmartScopedWriter<true> Guard(Lock);
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric // Make sure we keep track of the fact that the implementation implements
930b57cec5SDimitry Andric // the interface.
940b57cec5SDimitry Andric ImplementationInfo->addInterfaceImplemented(InterfaceInfo);
950b57cec5SDimitry Andric
960b57cec5SDimitry Andric if (isDefault) {
970b57cec5SDimitry Andric assert(InterfaceInfo->getNormalCtor() == nullptr &&
980b57cec5SDimitry Andric "Default implementation for analysis group already specified!");
990b57cec5SDimitry Andric assert(
1000b57cec5SDimitry Andric ImplementationInfo->getNormalCtor() &&
1010b57cec5SDimitry Andric "Cannot specify pass as default if it does not have a default ctor");
1020b57cec5SDimitry Andric InterfaceInfo->setNormalCtor(ImplementationInfo->getNormalCtor());
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric
1060b57cec5SDimitry Andric if (ShouldFree)
1070b57cec5SDimitry Andric ToFree.push_back(std::unique_ptr<const PassInfo>(&Registeree));
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric
addRegistrationListener(PassRegistrationListener * L)1100b57cec5SDimitry Andric void PassRegistry::addRegistrationListener(PassRegistrationListener *L) {
1110b57cec5SDimitry Andric sys::SmartScopedWriter<true> Guard(Lock);
1120b57cec5SDimitry Andric Listeners.push_back(L);
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric
removeRegistrationListener(PassRegistrationListener * L)1150b57cec5SDimitry Andric void PassRegistry::removeRegistrationListener(PassRegistrationListener *L) {
1160b57cec5SDimitry Andric sys::SmartScopedWriter<true> Guard(Lock);
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andric auto I = llvm::find(Listeners, L);
1190b57cec5SDimitry Andric Listeners.erase(I);
1200b57cec5SDimitry Andric }
121