1249259Sdim//===- PassRegistry.cpp - Pass Registration Implementation ----------------===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim// This file implements the PassRegistry, with which passes are registered on
11249259Sdim// initialization, and supports the PassManager in dependency resolution.
12249259Sdim//
13249259Sdim//===----------------------------------------------------------------------===//
14249259Sdim
15249259Sdim#include "llvm/PassRegistry.h"
16249259Sdim#include "llvm/ADT/DenseMap.h"
17249259Sdim#include "llvm/ADT/SmallPtrSet.h"
18249259Sdim#include "llvm/ADT/StringMap.h"
19249259Sdim#include "llvm/IR/Function.h"
20249259Sdim#include "llvm/PassSupport.h"
21249259Sdim#include "llvm/Support/Compiler.h"
22249259Sdim#include "llvm/Support/ManagedStatic.h"
23249259Sdim#include "llvm/Support/Mutex.h"
24263509Sdim#include "llvm/Support/RWMutex.h"
25249259Sdim#include <vector>
26249259Sdim
27249259Sdimusing namespace llvm;
28249259Sdim
29249259Sdim// FIXME: We use ManagedStatic to erase the pass registrar on shutdown.
30249259Sdim// Unfortunately, passes are registered with static ctors, and having
31249259Sdim// llvm_shutdown clear this map prevents successful resurrection after
32249259Sdim// llvm_shutdown is run.  Ideally we should find a solution so that we don't
33249259Sdim// leak the map, AND can still resurrect after shutdown.
34249259Sdimstatic ManagedStatic<PassRegistry> PassRegistryObj;
35249259SdimPassRegistry *PassRegistry::getPassRegistry() {
36249259Sdim  return &*PassRegistryObj;
37249259Sdim}
38249259Sdim
39263509Sdimstatic ManagedStatic<sys::SmartRWMutex<true> > Lock;
40249259Sdim
41249259Sdim//===----------------------------------------------------------------------===//
42249259Sdim// PassRegistryImpl
43249259Sdim//
44249259Sdim
45249259Sdimnamespace {
46249259Sdimstruct PassRegistryImpl {
47249259Sdim  /// PassInfoMap - Keep track of the PassInfo object for each registered pass.
48249259Sdim  typedef DenseMap<const void*, const PassInfo*> MapType;
49249259Sdim  MapType PassInfoMap;
50249259Sdim
51249259Sdim  typedef StringMap<const PassInfo*> StringMapType;
52249259Sdim  StringMapType PassInfoStringMap;
53249259Sdim
54249259Sdim  /// AnalysisGroupInfo - Keep track of information for each analysis group.
55249259Sdim  struct AnalysisGroupInfo {
56249259Sdim    SmallPtrSet<const PassInfo *, 8> Implementations;
57249259Sdim  };
58249259Sdim  DenseMap<const PassInfo*, AnalysisGroupInfo> AnalysisGroupInfoMap;
59249259Sdim
60249259Sdim  std::vector<const PassInfo*> ToFree;
61249259Sdim  std::vector<PassRegistrationListener*> Listeners;
62249259Sdim};
63249259Sdim} // end anonymous namespace
64249259Sdim
65249259Sdimvoid *PassRegistry::getImpl() const {
66249259Sdim  if (!pImpl)
67249259Sdim    pImpl = new PassRegistryImpl();
68249259Sdim  return pImpl;
69249259Sdim}
70249259Sdim
71249259Sdim//===----------------------------------------------------------------------===//
72249259Sdim// Accessors
73249259Sdim//
74249259Sdim
75249259SdimPassRegistry::~PassRegistry() {
76263509Sdim  sys::SmartScopedWriter<true> Guard(*Lock);
77249259Sdim  PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(pImpl);
78249259Sdim
79249259Sdim  for (std::vector<const PassInfo*>::iterator I = Impl->ToFree.begin(),
80249259Sdim       E = Impl->ToFree.end(); I != E; ++I)
81249259Sdim    delete *I;
82249259Sdim
83249259Sdim  delete Impl;
84249259Sdim  pImpl = 0;
85249259Sdim}
86249259Sdim
87249259Sdimconst PassInfo *PassRegistry::getPassInfo(const void *TI) const {
88263509Sdim  sys::SmartScopedReader<true> Guard(*Lock);
89249259Sdim  PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl());
90249259Sdim  PassRegistryImpl::MapType::const_iterator I = Impl->PassInfoMap.find(TI);
91249259Sdim  return I != Impl->PassInfoMap.end() ? I->second : 0;
92249259Sdim}
93249259Sdim
94249259Sdimconst PassInfo *PassRegistry::getPassInfo(StringRef Arg) const {
95263509Sdim  sys::SmartScopedReader<true> Guard(*Lock);
96249259Sdim  PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl());
97249259Sdim  PassRegistryImpl::StringMapType::const_iterator
98249259Sdim    I = Impl->PassInfoStringMap.find(Arg);
99249259Sdim  return I != Impl->PassInfoStringMap.end() ? I->second : 0;
100249259Sdim}
101249259Sdim
102249259Sdim//===----------------------------------------------------------------------===//
103249259Sdim// Pass Registration mechanism
104249259Sdim//
105249259Sdim
106249259Sdimvoid PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) {
107263509Sdim  sys::SmartScopedWriter<true> Guard(*Lock);
108249259Sdim  PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl());
109249259Sdim  bool Inserted =
110249259Sdim    Impl->PassInfoMap.insert(std::make_pair(PI.getTypeInfo(),&PI)).second;
111249259Sdim  assert(Inserted && "Pass registered multiple times!");
112249259Sdim  (void)Inserted;
113249259Sdim  Impl->PassInfoStringMap[PI.getPassArgument()] = &PI;
114249259Sdim
115249259Sdim  // Notify any listeners.
116249259Sdim  for (std::vector<PassRegistrationListener*>::iterator
117249259Sdim       I = Impl->Listeners.begin(), E = Impl->Listeners.end(); I != E; ++I)
118249259Sdim    (*I)->passRegistered(&PI);
119249259Sdim
120249259Sdim  if (ShouldFree) Impl->ToFree.push_back(&PI);
121249259Sdim}
122249259Sdim
123249259Sdimvoid PassRegistry::unregisterPass(const PassInfo &PI) {
124263509Sdim  sys::SmartScopedWriter<true> Guard(*Lock);
125249259Sdim  PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl());
126249259Sdim  PassRegistryImpl::MapType::iterator I =
127249259Sdim    Impl->PassInfoMap.find(PI.getTypeInfo());
128249259Sdim  assert(I != Impl->PassInfoMap.end() && "Pass registered but not in map!");
129249259Sdim
130249259Sdim  // Remove pass from the map.
131249259Sdim  Impl->PassInfoMap.erase(I);
132249259Sdim  Impl->PassInfoStringMap.erase(PI.getPassArgument());
133249259Sdim}
134249259Sdim
135249259Sdimvoid PassRegistry::enumerateWith(PassRegistrationListener *L) {
136263509Sdim  sys::SmartScopedReader<true> Guard(*Lock);
137249259Sdim  PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl());
138249259Sdim  for (PassRegistryImpl::MapType::const_iterator I = Impl->PassInfoMap.begin(),
139249259Sdim       E = Impl->PassInfoMap.end(); I != E; ++I)
140249259Sdim    L->passEnumerate(I->second);
141249259Sdim}
142249259Sdim
143249259Sdim
144249259Sdim/// Analysis Group Mechanisms.
145249259Sdimvoid PassRegistry::registerAnalysisGroup(const void *InterfaceID,
146249259Sdim                                         const void *PassID,
147249259Sdim                                         PassInfo& Registeree,
148249259Sdim                                         bool isDefault,
149249259Sdim                                         bool ShouldFree) {
150249259Sdim  PassInfo *InterfaceInfo =  const_cast<PassInfo*>(getPassInfo(InterfaceID));
151249259Sdim  if (InterfaceInfo == 0) {
152249259Sdim    // First reference to Interface, register it now.
153249259Sdim    registerPass(Registeree);
154249259Sdim    InterfaceInfo = &Registeree;
155249259Sdim  }
156249259Sdim  assert(Registeree.isAnalysisGroup() &&
157249259Sdim         "Trying to join an analysis group that is a normal pass!");
158249259Sdim
159249259Sdim  if (PassID) {
160249259Sdim    PassInfo *ImplementationInfo = const_cast<PassInfo*>(getPassInfo(PassID));
161249259Sdim    assert(ImplementationInfo &&
162249259Sdim           "Must register pass before adding to AnalysisGroup!");
163249259Sdim
164263509Sdim    sys::SmartScopedWriter<true> Guard(*Lock);
165249259Sdim
166249259Sdim    // Make sure we keep track of the fact that the implementation implements
167249259Sdim    // the interface.
168249259Sdim    ImplementationInfo->addInterfaceImplemented(InterfaceInfo);
169249259Sdim
170249259Sdim    PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl());
171249259Sdim    PassRegistryImpl::AnalysisGroupInfo &AGI =
172249259Sdim      Impl->AnalysisGroupInfoMap[InterfaceInfo];
173249259Sdim    assert(AGI.Implementations.count(ImplementationInfo) == 0 &&
174249259Sdim           "Cannot add a pass to the same analysis group more than once!");
175249259Sdim    AGI.Implementations.insert(ImplementationInfo);
176249259Sdim    if (isDefault) {
177249259Sdim      assert(InterfaceInfo->getNormalCtor() == 0 &&
178249259Sdim             "Default implementation for analysis group already specified!");
179249259Sdim      assert(ImplementationInfo->getNormalCtor() &&
180249259Sdim           "Cannot specify pass as default if it does not have a default ctor");
181249259Sdim      InterfaceInfo->setNormalCtor(ImplementationInfo->getNormalCtor());
182249259Sdim    }
183249259Sdim  }
184249259Sdim
185249259Sdim  PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl());
186249259Sdim  if (ShouldFree) Impl->ToFree.push_back(&Registeree);
187249259Sdim}
188249259Sdim
189249259Sdimvoid PassRegistry::addRegistrationListener(PassRegistrationListener *L) {
190263509Sdim  sys::SmartScopedWriter<true> Guard(*Lock);
191249259Sdim  PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl());
192249259Sdim  Impl->Listeners.push_back(L);
193249259Sdim}
194249259Sdim
195249259Sdimvoid PassRegistry::removeRegistrationListener(PassRegistrationListener *L) {
196263509Sdim  sys::SmartScopedWriter<true> Guard(*Lock);
197249259Sdim
198249259Sdim  // NOTE: This is necessary, because removeRegistrationListener() can be called
199249259Sdim  // as part of the llvm_shutdown sequence.  Since we have no control over the
200249259Sdim  // order of that sequence, we need to gracefully handle the case where the
201249259Sdim  // PassRegistry is destructed before the object that triggers this call.
202249259Sdim  if (!pImpl) return;
203249259Sdim
204249259Sdim  PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl());
205249259Sdim  std::vector<PassRegistrationListener*>::iterator I =
206249259Sdim    std::find(Impl->Listeners.begin(), Impl->Listeners.end(), L);
207249259Sdim  assert(I != Impl->Listeners.end() &&
208249259Sdim         "PassRegistrationListener not registered!");
209249259Sdim  Impl->Listeners.erase(I);
210249259Sdim}
211