#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/Module.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Atomic.h"
#include "llvm/System/Mutex.h"
#include "llvm/System/Threading.h"
#include <algorithm>
#include <map>
#include <set>
using namespace llvm;
Pass::~Pass() {
delete Resolver;
}
ModulePass::~ModulePass() { }
PassManagerType ModulePass::getPotentialPassManagerType() const {
return PMT_ModulePassManager;
}
bool Pass::mustPreserveAnalysisID(const PassInfo *AnalysisID) const {
return Resolver->getAnalysisIfAvailable(AnalysisID, true) != 0;
}
void Pass::dumpPassStructure(unsigned Offset) {
dbgs().indent(Offset*2) << getPassName() << "\n";
}
const char *Pass::getPassName() const {
if (const PassInfo *PI = getPassInfo())
return PI->getPassName();
return "Unnamed pass: implement Pass::getPassName()";
}
void Pass::preparePassManager(PMStack &) {
}
PassManagerType Pass::getPotentialPassManagerType() const {
return PMT_Unknown;
}
void Pass::getAnalysisUsage(AnalysisUsage &) const {
}
void Pass::releaseMemory() {
}
void Pass::verifyAnalysis() const {
}
void Pass::print(raw_ostream &O,const Module*) const {
O << "Pass::print not implemented for pass: '" << getPassName() << "'!\n";
}
void Pass::dump() const {
print(dbgs(), 0);
}
ImmutablePass::~ImmutablePass() { }
void ImmutablePass::initializePass() {
}
bool FunctionPass::runOnModule(Module &M) {
bool Changed = doInitialization(M);
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
if (!I->isDeclaration()) Changed |= runOnFunction(*I);
return Changed | doFinalization(M);
}
bool FunctionPass::run(Function &F) {
if (F.isDeclaration()) return false;
bool Changed = doInitialization(*F.getParent());
Changed |= runOnFunction(F);
return Changed | doFinalization(*F.getParent());
}
bool FunctionPass::doInitialization(Module &) {
return false;
}
bool FunctionPass::doFinalization(Module &) {
return false;
}
PassManagerType FunctionPass::getPotentialPassManagerType() const {
return PMT_FunctionPassManager;
}
bool BasicBlockPass::runOnFunction(Function &F) {
bool Changed = doInitialization(F);
for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
Changed |= runOnBasicBlock(*I);
return Changed | doFinalization(F);
}
bool BasicBlockPass::doInitialization(Module &) {
return false;
}
bool BasicBlockPass::doInitialization(Function &) {
return false;
}
bool BasicBlockPass::doFinalization(Function &) {
return false;
}
bool BasicBlockPass::doFinalization(Module &) {
return false;
}
PassManagerType BasicBlockPass::getPotentialPassManagerType() const {
return PMT_BasicBlockPassManager;
}
namespace {
class PassRegistrar {
mutable sys::SmartMutex<true> Lock;
typedef std::map<intptr_t, const PassInfo*> MapType;
MapType PassInfoMap;
typedef StringMap<const PassInfo*> StringMapType;
StringMapType PassInfoStringMap;
struct AnalysisGroupInfo {
std::set<const PassInfo *> Implementations;
};
std::map<const PassInfo *, AnalysisGroupInfo> AnalysisGroupInfoMap;
public:
const PassInfo *GetPassInfo(intptr_t TI) const {
sys::SmartScopedLock<true> Guard(Lock);
MapType::const_iterator I = PassInfoMap.find(TI);
return I != PassInfoMap.end() ? I->second : 0;
}
const PassInfo *GetPassInfo(StringRef Arg) const {
sys::SmartScopedLock<true> Guard(Lock);
StringMapType::const_iterator I = PassInfoStringMap.find(Arg);
return I != PassInfoStringMap.end() ? I->second : 0;
}
void RegisterPass(const PassInfo &PI) {
sys::SmartScopedLock<true> Guard(Lock);
bool Inserted =
PassInfoMap.insert(std::make_pair(PI.getTypeInfo(),&PI)).second;
assert(Inserted && "Pass registered multiple times!"); Inserted=Inserted;
PassInfoStringMap[PI.getPassArgument()] = &PI;
}
void UnregisterPass(const PassInfo &PI) {
sys::SmartScopedLock<true> Guard(Lock);
MapType::iterator I = PassInfoMap.find(PI.getTypeInfo());
assert(I != PassInfoMap.end() && "Pass registered but not in map!");
PassInfoMap.erase(I);
PassInfoStringMap.erase(PI.getPassArgument());
}
void EnumerateWith(PassRegistrationListener *L) {
sys::SmartScopedLock<true> Guard(Lock);
for (MapType::const_iterator I = PassInfoMap.begin(),
E = PassInfoMap.end(); I != E; ++I)
L->passEnumerate(I->second);
}
void RegisterAnalysisGroup(PassInfo *InterfaceInfo,
const PassInfo *ImplementationInfo,
bool isDefault) {
sys::SmartScopedLock<true> Guard(Lock);
AnalysisGroupInfo &AGI = AnalysisGroupInfoMap[InterfaceInfo];
assert(AGI.Implementations.count(ImplementationInfo) == 0 &&
"Cannot add a pass to the same analysis group more than once!");
AGI.Implementations.insert(ImplementationInfo);
if (isDefault) {
assert(InterfaceInfo->getNormalCtor() == 0 &&
"Default implementation for analysis group already specified!");
assert(ImplementationInfo->getNormalCtor() &&
"Cannot specify pass as default if it does not have a default ctor");
InterfaceInfo->setNormalCtor(ImplementationInfo->getNormalCtor());
}
}
};
}
static std::vector<PassRegistrationListener*> *Listeners = 0;
static sys::SmartMutex<true> ListenersLock;
static PassRegistrar *getPassRegistrar() {
static PassRegistrar *PassRegistrarObj = 0;
PassRegistrar* tmp = PassRegistrarObj;
if (llvm_is_multithreaded()) {
sys::MemoryFence();
if (!tmp) {
llvm_acquire_global_lock();
tmp = PassRegistrarObj;
if (!tmp) {
tmp = new PassRegistrar();
sys::MemoryFence();
PassRegistrarObj = tmp;
}
llvm_release_global_lock();
}
} else if (!tmp) {
PassRegistrarObj = new PassRegistrar();
}
return PassRegistrarObj;
}
const PassInfo *Pass::getPassInfo() const {
return lookupPassInfo(PassID);
}
const PassInfo *Pass::lookupPassInfo(intptr_t TI) {
return getPassRegistrar()->GetPassInfo(TI);
}
const PassInfo *Pass::lookupPassInfo(StringRef Arg) {
return getPassRegistrar()->GetPassInfo(Arg);
}
void PassInfo::registerPass() {
getPassRegistrar()->RegisterPass(*this);
sys::SmartScopedLock<true> Lock(ListenersLock);
if (Listeners)
for (std::vector<PassRegistrationListener*>::iterator
I = Listeners->begin(), E = Listeners->end(); I != E; ++I)
(*I)->passRegistered(this);
}
void PassInfo::unregisterPass() {
getPassRegistrar()->UnregisterPass(*this);
}
RegisterAGBase::RegisterAGBase(const char *Name, intptr_t InterfaceID,
intptr_t PassID, bool isDefault)
: PassInfo(Name, InterfaceID) {
PassInfo *InterfaceInfo =
const_cast<PassInfo*>(Pass::lookupPassInfo(InterfaceID));
if (InterfaceInfo == 0) {
registerPass();
InterfaceInfo = this;
}
assert(isAnalysisGroup() &&
"Trying to join an analysis group that is a normal pass!");
if (PassID) {
const PassInfo *ImplementationInfo = Pass::lookupPassInfo(PassID);
assert(ImplementationInfo &&
"Must register pass before adding to AnalysisGroup!");
PassInfo *IIPI = const_cast<PassInfo*>(ImplementationInfo);
IIPI->addInterfaceImplemented(InterfaceInfo);
getPassRegistrar()->RegisterAnalysisGroup(InterfaceInfo, IIPI, isDefault);
}
}
PassRegistrationListener::PassRegistrationListener() {
sys::SmartScopedLock<true> Lock(ListenersLock);
if (!Listeners) Listeners = new std::vector<PassRegistrationListener*>();
Listeners->push_back(this);
}
PassRegistrationListener::~PassRegistrationListener() {
sys::SmartScopedLock<true> Lock(ListenersLock);
std::vector<PassRegistrationListener*>::iterator I =
std::find(Listeners->begin(), Listeners->end(), this);
assert(Listeners && I != Listeners->end() &&
"PassRegistrationListener not registered!");
Listeners->erase(I);
if (Listeners->empty()) {
delete Listeners;
Listeners = 0;
}
}
void PassRegistrationListener::enumeratePasses() {
getPassRegistrar()->EnumerateWith(this);
}
PassNameParser::~PassNameParser() {}
namespace {
struct GetCFGOnlyPasses : public PassRegistrationListener {
typedef AnalysisUsage::VectorType VectorType;
VectorType &CFGOnlyList;
GetCFGOnlyPasses(VectorType &L) : CFGOnlyList(L) {}
void passEnumerate(const PassInfo *P) {
if (P->isCFGOnlyPass())
CFGOnlyList.push_back(P);
}
};
}
void AnalysisUsage::setPreservesCFG() {
GetCFGOnlyPasses(Preserved).enumeratePasses();
}