1ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson//===- PassRegistry.cpp - Pass Registration Implementation ----------------===//
2ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson//
3ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson//                     The LLVM Compiler Infrastructure
4ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson//
5ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson// This file is distributed under the University of Illinois Open Source
6ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson// License. See LICENSE.TXT for details.
7ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson//
8ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson//===----------------------------------------------------------------------===//
9ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson//
10ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson// This file implements the PassRegistry, with which passes are registered on
11ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson// initialization, and supports the PassManager in dependency resolution.
12ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson//
13ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson//===----------------------------------------------------------------------===//
14ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson
15ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson#include "llvm/PassRegistry.h"
160b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Function.h"
17d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/PassSupport.h"
18d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/Compiler.h"
19d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/ManagedStatic.h"
2040488cf13973dc5364f017c1a403fe93e6c46d6fChad Rosier#include "llvm/Support/RWMutex.h"
216bcd3a02653c45b87094577517547b7eb9f76395Owen Anderson#include <vector>
22aac07eaeef0b29690f18061abc148a2608cd77deOwen Anderson
23539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Andersonusing namespace llvm;
24539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Anderson
25381f17ee7c07b5a80d7dcdeae3d62e497902ef85Owen Anderson// FIXME: We use ManagedStatic to erase the pass registrar on shutdown.
26aac07eaeef0b29690f18061abc148a2608cd77deOwen Anderson// Unfortunately, passes are registered with static ctors, and having
277a2bdde0a0eebcd2125055e0eacaca040f0b766cChris Lattner// llvm_shutdown clear this map prevents successful resurrection after
28aac07eaeef0b29690f18061abc148a2608cd77deOwen Anderson// llvm_shutdown is run.  Ideally we should find a solution so that we don't
29aac07eaeef0b29690f18061abc148a2608cd77deOwen Anderson// leak the map, AND can still resurrect after shutdown.
30381f17ee7c07b5a80d7dcdeae3d62e497902ef85Owen Andersonstatic ManagedStatic<PassRegistry> PassRegistryObj;
31381f17ee7c07b5a80d7dcdeae3d62e497902ef85Owen AndersonPassRegistry *PassRegistry::getPassRegistry() {
32381f17ee7c07b5a80d7dcdeae3d62e497902ef85Owen Anderson  return &*PassRegistryObj;
33aac07eaeef0b29690f18061abc148a2608cd77deOwen Anderson}
34ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson
356bcd3a02653c45b87094577517547b7eb9f76395Owen Anderson//===----------------------------------------------------------------------===//
366bcd3a02653c45b87094577517547b7eb9f76395Owen Anderson// Accessors
376bcd3a02653c45b87094577517547b7eb9f76395Owen Anderson//
386bcd3a02653c45b87094577517547b7eb9f76395Owen Anderson
39381f17ee7c07b5a80d7dcdeae3d62e497902ef85Owen AndersonPassRegistry::~PassRegistry() {
40381f17ee7c07b5a80d7dcdeae3d62e497902ef85Owen Anderson}
41381f17ee7c07b5a80d7dcdeae3d62e497902ef85Owen Anderson
4290c579de5a383cee278acc3f7e7b9d0a656e6a35Owen Andersonconst PassInfo *PassRegistry::getPassInfo(const void *TI) const {
43cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  sys::SmartScopedReader<true> Guard(Lock);
44cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  MapType::const_iterator I = PassInfoMap.find(TI);
45cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return I != PassInfoMap.end() ? I->second : nullptr;
46ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson}
47ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson
48ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Andersonconst PassInfo *PassRegistry::getPassInfo(StringRef Arg) const {
49cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  sys::SmartScopedReader<true> Guard(Lock);
50cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  StringMapType::const_iterator I = PassInfoStringMap.find(Arg);
51cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return I != PassInfoStringMap.end() ? I->second : nullptr;
52ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson}
53ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson
54539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Anderson//===----------------------------------------------------------------------===//
55539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Anderson// Pass Registration mechanism
56539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Anderson//
57539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Anderson
5875f6df283f726c289b240fe8c5f2f42cdfff5d5fOwen Andersonvoid PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) {
59cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  sys::SmartScopedWriter<true> Guard(Lock);
60ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson  bool Inserted =
61cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    PassInfoMap.insert(std::make_pair(PI.getTypeInfo(),&PI)).second;
627008f1e9ab3e455955bac764282b62d51b5ae523Jakob Stoklund Olesen  assert(Inserted && "Pass registered multiple times!");
637008f1e9ab3e455955bac764282b62d51b5ae523Jakob Stoklund Olesen  (void)Inserted;
64cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  PassInfoStringMap[PI.getPassArgument()] = &PI;
65539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Anderson
66539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Anderson  // Notify any listeners.
67539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Anderson  for (std::vector<PassRegistrationListener*>::iterator
68cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines       I = Listeners.begin(), E = Listeners.end(); I != E; ++I)
69539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Anderson    (*I)->passRegistered(&PI);
7075f6df283f726c289b240fe8c5f2f42cdfff5d5fOwen Anderson
71cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (ShouldFree) ToFree.push_back(std::unique_ptr<const PassInfo>(&PI));
72ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson}
73ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson
74ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Andersonvoid PassRegistry::unregisterPass(const PassInfo &PI) {
75cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  sys::SmartScopedWriter<true> Guard(Lock);
76cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  MapType::iterator I = PassInfoMap.find(PI.getTypeInfo());
77cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  assert(I != PassInfoMap.end() && "Pass registered but not in map!");
78ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson
79ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson  // Remove pass from the map.
80cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  PassInfoMap.erase(I);
81cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  PassInfoStringMap.erase(PI.getPassArgument());
82ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson}
83ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson
84ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Andersonvoid PassRegistry::enumerateWith(PassRegistrationListener *L) {
85cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  sys::SmartScopedReader<true> Guard(Lock);
86cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  for (auto I = PassInfoMap.begin(), E = PassInfoMap.end(); I != E; ++I)
87ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson    L->passEnumerate(I->second);
88ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson}
89ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson
90ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson
91ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson/// Analysis Group Mechanisms.
9290c579de5a383cee278acc3f7e7b9d0a656e6a35Owen Andersonvoid PassRegistry::registerAnalysisGroup(const void *InterfaceID,
9390c579de5a383cee278acc3f7e7b9d0a656e6a35Owen Anderson                                         const void *PassID,
949650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson                                         PassInfo& Registeree,
9575f6df283f726c289b240fe8c5f2f42cdfff5d5fOwen Anderson                                         bool isDefault,
9675f6df283f726c289b240fe8c5f2f42cdfff5d5fOwen Anderson                                         bool ShouldFree) {
979650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson  PassInfo *InterfaceInfo =  const_cast<PassInfo*>(getPassInfo(InterfaceID));
98dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (!InterfaceInfo) {
999650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson    // First reference to Interface, register it now.
1009650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson    registerPass(Registeree);
1019650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson    InterfaceInfo = &Registeree;
1029650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson  }
1039650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson  assert(Registeree.isAnalysisGroup() &&
1049650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson         "Trying to join an analysis group that is a normal pass!");
1059650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson
1069650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson  if (PassID) {
1079650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson    PassInfo *ImplementationInfo = const_cast<PassInfo*>(getPassInfo(PassID));
1089650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson    assert(ImplementationInfo &&
1099650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson           "Must register pass before adding to AnalysisGroup!");
1109650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson
111cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    sys::SmartScopedWriter<true> Guard(Lock);
1121e3e6362c8def5abcbc9a89c02619a0912177f7eOwen Anderson
1139650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson    // Make sure we keep track of the fact that the implementation implements
1149650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson    // the interface.
1159650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson    ImplementationInfo->addInterfaceImplemented(InterfaceInfo);
1169650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson
117cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    AnalysisGroupInfo &AGI = AnalysisGroupInfoMap[InterfaceInfo];
1189650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson    assert(AGI.Implementations.count(ImplementationInfo) == 0 &&
1199650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson           "Cannot add a pass to the same analysis group more than once!");
1209650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson    AGI.Implementations.insert(ImplementationInfo);
1219650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson    if (isDefault) {
122dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      assert(InterfaceInfo->getNormalCtor() == nullptr &&
1239650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson             "Default implementation for analysis group already specified!");
1249650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson      assert(ImplementationInfo->getNormalCtor() &&
1259650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson           "Cannot specify pass as default if it does not have a default ctor");
1269650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson      InterfaceInfo->setNormalCtor(ImplementationInfo->getNormalCtor());
12736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      InterfaceInfo->setTargetMachineCtor(
12836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          ImplementationInfo->getTargetMachineCtor());
1299650983b9a30804d3479aeffb2a7f8bdb6b33942Owen Anderson    }
130ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson  }
13175f6df283f726c289b240fe8c5f2f42cdfff5d5fOwen Anderson
132dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (ShouldFree)
133cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    ToFree.push_back(std::unique_ptr<const PassInfo>(&Registeree));
134ee9886ed3dfac7b4459c9cb5bf8845b27e241792Owen Anderson}
135539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Anderson
136539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Andersonvoid PassRegistry::addRegistrationListener(PassRegistrationListener *L) {
137cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  sys::SmartScopedWriter<true> Guard(Lock);
138cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  Listeners.push_back(L);
139539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Anderson}
140539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Anderson
141539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Andersonvoid PassRegistry::removeRegistrationListener(PassRegistrationListener *L) {
142cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  sys::SmartScopedWriter<true> Guard(Lock);
143381f17ee7c07b5a80d7dcdeae3d62e497902ef85Owen Anderson
144cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  auto I = std::find(Listeners.begin(), Listeners.end(), L);
145cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  Listeners.erase(I);
146539673579ec79b75a95ef9daefc6a8b2fc8552f5Owen Anderson}
147