//===- AliasDebugger.cpp - Simple Alias Analysis Use Checker --------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This simple pass checks alias analysis users to ensure that if they // create a new value, they do not query AA without informing it of the value. // It acts as a shim over any other AA pass you want. // // Yes keeping track of every value in the program is expensive, but this is // a debugging pass. // //===----------------------------------------------------------------------===// #include "llvm/Analysis/Passes.h" #include "llvm/Module.h" #include "llvm/Pass.h" #include "llvm/Instructions.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Support/Compiler.h" #include using namespace llvm; namespace { class VISIBILITY_HIDDEN AliasDebugger : public ModulePass, public AliasAnalysis { //What we do is simple. Keep track of every value the AA could //know about, and verify that queries are one of those. //A query to a value that didn't exist when the AA was created //means someone forgot to update the AA when creating new values std::set Vals; public: static char ID; // Class identification, replacement for typeinfo AliasDebugger() : ModulePass((intptr_t)&ID) {} bool runOnModule(Module &M) { InitializeAliasAnalysis(this); // set up super class for(Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) Vals.insert(&*I); for(Module::iterator I = M.begin(), E = M.end(); I != E; ++I){ Vals.insert(&*I); if(!I->isDeclaration()) { for (Function::arg_iterator AI = I->arg_begin(), AE = I->arg_end(); AI != AE; ++AI) Vals.insert(&*AI); for (Function::const_iterator FI = I->begin(), FE = I->end(); FI != FE; ++FI) for (BasicBlock::const_iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) Vals.insert(&*BI); } } return false; } virtual void getAnalysisUsage(AnalysisUsage &AU) const { AliasAnalysis::getAnalysisUsage(AU); AU.setPreservesAll(); // Does not transform code } //------------------------------------------------ // Implement the AliasAnalysis API // AliasResult alias(const Value *V1, unsigned V1Size, const Value *V2, unsigned V2Size) { assert(Vals.find(V1) != Vals.end() && "Never seen value in AA before"); assert(Vals.find(V2) != Vals.end() && "Never seen value in AA before"); return AliasAnalysis::alias(V1, V1Size, V2, V2Size); } ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size) { assert(Vals.find(P) != Vals.end() && "Never seen value in AA before"); return AliasAnalysis::getModRefInfo(CS, P, Size); } ModRefResult getModRefInfo(CallSite CS1, CallSite CS2) { return AliasAnalysis::getModRefInfo(CS1,CS2); } void getMustAliases(Value *P, std::vector &RetVals) { assert(Vals.find(P) != Vals.end() && "Never seen value in AA before"); return AliasAnalysis::getMustAliases(P, RetVals); } bool pointsToConstantMemory(const Value *P) { assert(Vals.find(P) != Vals.end() && "Never seen value in AA before"); return AliasAnalysis::pointsToConstantMemory(P); } /// getModRefBehavior - Return the behavior of the specified function if /// called from the specified call site. The call site may be null in which /// case the most generic behavior of this function should be returned. virtual ModRefBehavior getModRefBehavior(Function *F, CallSite CS, std::vector *Info) { assert(Vals.find(F) != Vals.end() && "Never seen value in AA before"); return AliasAnalysis::getModRefBehavior(F, CS, Info); } virtual void deleteValue(Value *V) { assert(Vals.find(V) != Vals.end() && "Never seen value in AA before"); AliasAnalysis::deleteValue(V); } virtual void copyValue(Value *From, Value *To) { Vals.insert(To); AliasAnalysis::copyValue(From, To); } }; char AliasDebugger::ID = 0; RegisterPass X("debug-aa", "AA use debugger", true, true); RegisterAnalysisGroup Y(X); } Pass *llvm::createAliasDebugger() { return new AliasDebugger(); }