xref: /freebsd/contrib/llvm-project/llvm/lib/IR/PassRegistry.cpp (revision 753f127f3ace09432b2baeffd71a308760641a62)
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