1*9880d681SAndroid Build Coastguard Worker //===- PassRegistry.cpp - Pass Registration Implementation ----------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements the PassRegistry, with which passes are registered on
11*9880d681SAndroid Build Coastguard Worker // initialization, and supports the PassManager in dependency resolution.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker #include "llvm/PassRegistry.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/PassSupport.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ManagedStatic.h"
18*9880d681SAndroid Build Coastguard Worker
19*9880d681SAndroid Build Coastguard Worker using namespace llvm;
20*9880d681SAndroid Build Coastguard Worker
21*9880d681SAndroid Build Coastguard Worker // FIXME: We use ManagedStatic to erase the pass registrar on shutdown.
22*9880d681SAndroid Build Coastguard Worker // Unfortunately, passes are registered with static ctors, and having
23*9880d681SAndroid Build Coastguard Worker // llvm_shutdown clear this map prevents successful resurrection after
24*9880d681SAndroid Build Coastguard Worker // llvm_shutdown is run. Ideally we should find a solution so that we don't
25*9880d681SAndroid Build Coastguard Worker // leak the map, AND can still resurrect after shutdown.
26*9880d681SAndroid Build Coastguard Worker static ManagedStatic<PassRegistry> PassRegistryObj;
getPassRegistry()27*9880d681SAndroid Build Coastguard Worker PassRegistry *PassRegistry::getPassRegistry() {
28*9880d681SAndroid Build Coastguard Worker return &*PassRegistryObj;
29*9880d681SAndroid Build Coastguard Worker }
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
32*9880d681SAndroid Build Coastguard Worker // Accessors
33*9880d681SAndroid Build Coastguard Worker //
34*9880d681SAndroid Build Coastguard Worker
~PassRegistry()35*9880d681SAndroid Build Coastguard Worker PassRegistry::~PassRegistry() {}
36*9880d681SAndroid Build Coastguard Worker
getPassInfo(const void * TI) const37*9880d681SAndroid Build Coastguard Worker const PassInfo *PassRegistry::getPassInfo(const void *TI) const {
38*9880d681SAndroid Build Coastguard Worker sys::SmartScopedReader<true> Guard(Lock);
39*9880d681SAndroid Build Coastguard Worker MapType::const_iterator I = PassInfoMap.find(TI);
40*9880d681SAndroid Build Coastguard Worker return I != PassInfoMap.end() ? I->second : nullptr;
41*9880d681SAndroid Build Coastguard Worker }
42*9880d681SAndroid Build Coastguard Worker
getPassInfo(StringRef Arg) const43*9880d681SAndroid Build Coastguard Worker const PassInfo *PassRegistry::getPassInfo(StringRef Arg) const {
44*9880d681SAndroid Build Coastguard Worker sys::SmartScopedReader<true> Guard(Lock);
45*9880d681SAndroid Build Coastguard Worker StringMapType::const_iterator I = PassInfoStringMap.find(Arg);
46*9880d681SAndroid Build Coastguard Worker return I != PassInfoStringMap.end() ? I->second : nullptr;
47*9880d681SAndroid Build Coastguard Worker }
48*9880d681SAndroid Build Coastguard Worker
49*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
50*9880d681SAndroid Build Coastguard Worker // Pass Registration mechanism
51*9880d681SAndroid Build Coastguard Worker //
52*9880d681SAndroid Build Coastguard Worker
registerPass(const PassInfo & PI,bool ShouldFree)53*9880d681SAndroid Build Coastguard Worker void PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) {
54*9880d681SAndroid Build Coastguard Worker sys::SmartScopedWriter<true> Guard(Lock);
55*9880d681SAndroid Build Coastguard Worker bool Inserted =
56*9880d681SAndroid Build Coastguard Worker PassInfoMap.insert(std::make_pair(PI.getTypeInfo(), &PI)).second;
57*9880d681SAndroid Build Coastguard Worker assert(Inserted && "Pass registered multiple times!");
58*9880d681SAndroid Build Coastguard Worker (void)Inserted;
59*9880d681SAndroid Build Coastguard Worker PassInfoStringMap[PI.getPassArgument()] = &PI;
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker // Notify any listeners.
62*9880d681SAndroid Build Coastguard Worker for (auto *Listener : Listeners)
63*9880d681SAndroid Build Coastguard Worker Listener->passRegistered(&PI);
64*9880d681SAndroid Build Coastguard Worker
65*9880d681SAndroid Build Coastguard Worker if (ShouldFree)
66*9880d681SAndroid Build Coastguard Worker ToFree.push_back(std::unique_ptr<const PassInfo>(&PI));
67*9880d681SAndroid Build Coastguard Worker }
68*9880d681SAndroid Build Coastguard Worker
enumerateWith(PassRegistrationListener * L)69*9880d681SAndroid Build Coastguard Worker void PassRegistry::enumerateWith(PassRegistrationListener *L) {
70*9880d681SAndroid Build Coastguard Worker sys::SmartScopedReader<true> Guard(Lock);
71*9880d681SAndroid Build Coastguard Worker for (auto PassInfoPair : PassInfoMap)
72*9880d681SAndroid Build Coastguard Worker L->passEnumerate(PassInfoPair.second);
73*9880d681SAndroid Build Coastguard Worker }
74*9880d681SAndroid Build Coastguard Worker
75*9880d681SAndroid Build Coastguard Worker /// Analysis Group Mechanisms.
registerAnalysisGroup(const void * InterfaceID,const void * PassID,PassInfo & Registeree,bool isDefault,bool ShouldFree)76*9880d681SAndroid Build Coastguard Worker void PassRegistry::registerAnalysisGroup(const void *InterfaceID,
77*9880d681SAndroid Build Coastguard Worker const void *PassID,
78*9880d681SAndroid Build Coastguard Worker PassInfo &Registeree, bool isDefault,
79*9880d681SAndroid Build Coastguard Worker bool ShouldFree) {
80*9880d681SAndroid Build Coastguard Worker PassInfo *InterfaceInfo = const_cast<PassInfo *>(getPassInfo(InterfaceID));
81*9880d681SAndroid Build Coastguard Worker if (!InterfaceInfo) {
82*9880d681SAndroid Build Coastguard Worker // First reference to Interface, register it now.
83*9880d681SAndroid Build Coastguard Worker registerPass(Registeree);
84*9880d681SAndroid Build Coastguard Worker InterfaceInfo = &Registeree;
85*9880d681SAndroid Build Coastguard Worker }
86*9880d681SAndroid Build Coastguard Worker assert(Registeree.isAnalysisGroup() &&
87*9880d681SAndroid Build Coastguard Worker "Trying to join an analysis group that is a normal pass!");
88*9880d681SAndroid Build Coastguard Worker
89*9880d681SAndroid Build Coastguard Worker if (PassID) {
90*9880d681SAndroid Build Coastguard Worker PassInfo *ImplementationInfo = const_cast<PassInfo *>(getPassInfo(PassID));
91*9880d681SAndroid Build Coastguard Worker assert(ImplementationInfo &&
92*9880d681SAndroid Build Coastguard Worker "Must register pass before adding to AnalysisGroup!");
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker sys::SmartScopedWriter<true> Guard(Lock);
95*9880d681SAndroid Build Coastguard Worker
96*9880d681SAndroid Build Coastguard Worker // Make sure we keep track of the fact that the implementation implements
97*9880d681SAndroid Build Coastguard Worker // the interface.
98*9880d681SAndroid Build Coastguard Worker ImplementationInfo->addInterfaceImplemented(InterfaceInfo);
99*9880d681SAndroid Build Coastguard Worker
100*9880d681SAndroid Build Coastguard Worker if (isDefault) {
101*9880d681SAndroid Build Coastguard Worker assert(InterfaceInfo->getNormalCtor() == nullptr &&
102*9880d681SAndroid Build Coastguard Worker "Default implementation for analysis group already specified!");
103*9880d681SAndroid Build Coastguard Worker assert(
104*9880d681SAndroid Build Coastguard Worker ImplementationInfo->getNormalCtor() &&
105*9880d681SAndroid Build Coastguard Worker "Cannot specify pass as default if it does not have a default ctor");
106*9880d681SAndroid Build Coastguard Worker InterfaceInfo->setNormalCtor(ImplementationInfo->getNormalCtor());
107*9880d681SAndroid Build Coastguard Worker InterfaceInfo->setTargetMachineCtor(
108*9880d681SAndroid Build Coastguard Worker ImplementationInfo->getTargetMachineCtor());
109*9880d681SAndroid Build Coastguard Worker }
110*9880d681SAndroid Build Coastguard Worker }
111*9880d681SAndroid Build Coastguard Worker
112*9880d681SAndroid Build Coastguard Worker if (ShouldFree)
113*9880d681SAndroid Build Coastguard Worker ToFree.push_back(std::unique_ptr<const PassInfo>(&Registeree));
114*9880d681SAndroid Build Coastguard Worker }
115*9880d681SAndroid Build Coastguard Worker
addRegistrationListener(PassRegistrationListener * L)116*9880d681SAndroid Build Coastguard Worker void PassRegistry::addRegistrationListener(PassRegistrationListener *L) {
117*9880d681SAndroid Build Coastguard Worker sys::SmartScopedWriter<true> Guard(Lock);
118*9880d681SAndroid Build Coastguard Worker Listeners.push_back(L);
119*9880d681SAndroid Build Coastguard Worker }
120*9880d681SAndroid Build Coastguard Worker
removeRegistrationListener(PassRegistrationListener * L)121*9880d681SAndroid Build Coastguard Worker void PassRegistry::removeRegistrationListener(PassRegistrationListener *L) {
122*9880d681SAndroid Build Coastguard Worker sys::SmartScopedWriter<true> Guard(Lock);
123*9880d681SAndroid Build Coastguard Worker
124*9880d681SAndroid Build Coastguard Worker auto I = std::find(Listeners.begin(), Listeners.end(), L);
125*9880d681SAndroid Build Coastguard Worker Listeners.erase(I);
126*9880d681SAndroid Build Coastguard Worker }
127