diff options
author | Arthur Eubanks <aeubanks@google.com> | 2020-09-02 21:54:27 -0700 |
---|---|---|
committer | Arthur Eubanks <aeubanks@google.com> | 2020-09-03 13:03:44 -0700 |
commit | c9771391ce05e5cba00e29017fd6c39157df3f3c (patch) | |
tree | 7d9eba4672be9a7012cbed37785735e62281f4e4 /llvm/lib/Analysis/Lint.cpp | |
parent | b53243e19496ae59ae1ce457a40e3ea610011fd1 (diff) | |
download | llvm-c9771391ce05e5cba00e29017fd6c39157df3f3c.zip llvm-c9771391ce05e5cba00e29017fd6c39157df3f3c.tar.gz llvm-c9771391ce05e5cba00e29017fd6c39157df3f3c.tar.bz2 |
[NewPM][Lint] Port -lint to NewPM
This also changes -lint from an analysis to a pass. It's similar to
-verify, and that is a normal pass, and lives in llvm/IR.
Reviewed By: ychen
Differential Revision: https://reviews.llvm.org/D87057
Diffstat (limited to 'llvm/lib/Analysis/Lint.cpp')
-rw-r--r-- | llvm/lib/Analysis/Lint.cpp | 304 |
1 files changed, 164 insertions, 140 deletions
diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp index 4a159d6..04e04a8 100644 --- a/llvm/lib/Analysis/Lint.cpp +++ b/llvm/lib/Analysis/Lint.cpp @@ -63,6 +63,7 @@ #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" #include "llvm/InitializePasses.h" @@ -80,134 +81,102 @@ using namespace llvm; namespace { - namespace MemRef { - static const unsigned Read = 1; - static const unsigned Write = 2; - static const unsigned Callee = 4; - static const unsigned Branchee = 8; - } // end namespace MemRef - - class Lint : public FunctionPass, public InstVisitor<Lint> { - friend class InstVisitor<Lint>; - - void visitFunction(Function &F); - - void visitCallBase(CallBase &CB); - void visitMemoryReference(Instruction &I, Value *Ptr, uint64_t Size, - MaybeAlign Alignment, Type *Ty, unsigned Flags); - void visitEHBeginCatch(IntrinsicInst *II); - void visitEHEndCatch(IntrinsicInst *II); - - void visitReturnInst(ReturnInst &I); - void visitLoadInst(LoadInst &I); - void visitStoreInst(StoreInst &I); - void visitXor(BinaryOperator &I); - void visitSub(BinaryOperator &I); - void visitLShr(BinaryOperator &I); - void visitAShr(BinaryOperator &I); - void visitShl(BinaryOperator &I); - void visitSDiv(BinaryOperator &I); - void visitUDiv(BinaryOperator &I); - void visitSRem(BinaryOperator &I); - void visitURem(BinaryOperator &I); - void visitAllocaInst(AllocaInst &I); - void visitVAArgInst(VAArgInst &I); - void visitIndirectBrInst(IndirectBrInst &I); - void visitExtractElementInst(ExtractElementInst &I); - void visitInsertElementInst(InsertElementInst &I); - void visitUnreachableInst(UnreachableInst &I); - - Value *findValue(Value *V, bool OffsetOk) const; - Value *findValueImpl(Value *V, bool OffsetOk, - SmallPtrSetImpl<Value *> &Visited) const; - - public: - Module *Mod; - const DataLayout *DL; - AliasAnalysis *AA; - AssumptionCache *AC; - DominatorTree *DT; - TargetLibraryInfo *TLI; - - std::string Messages; - raw_string_ostream MessagesStr; - - static char ID; // Pass identification, replacement for typeid - Lint() : FunctionPass(ID), MessagesStr(Messages) { - initializeLintPass(*PassRegistry::getPassRegistry()); - } - - bool runOnFunction(Function &F) override; - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - AU.addRequired<AAResultsWrapperPass>(); - AU.addRequired<AssumptionCacheTracker>(); - AU.addRequired<TargetLibraryInfoWrapperPass>(); - AU.addRequired<DominatorTreeWrapperPass>(); - } - void print(raw_ostream &O, const Module *M) const override {} - - void WriteValues(ArrayRef<const Value *> Vs) { - for (const Value *V : Vs) { - if (!V) - continue; - if (isa<Instruction>(V)) { - MessagesStr << *V << '\n'; - } else { - V->printAsOperand(MessagesStr, true, Mod); - MessagesStr << '\n'; - } +namespace MemRef { +static const unsigned Read = 1; +static const unsigned Write = 2; +static const unsigned Callee = 4; +static const unsigned Branchee = 8; +} // end namespace MemRef + +class Lint : public InstVisitor<Lint> { + friend class InstVisitor<Lint>; + + void visitFunction(Function &F); + + void visitCallBase(CallBase &CB); + void visitMemoryReference(Instruction &I, Value *Ptr, uint64_t Size, + MaybeAlign Alignment, Type *Ty, unsigned Flags); + void visitEHBeginCatch(IntrinsicInst *II); + void visitEHEndCatch(IntrinsicInst *II); + + void visitReturnInst(ReturnInst &I); + void visitLoadInst(LoadInst &I); + void visitStoreInst(StoreInst &I); + void visitXor(BinaryOperator &I); + void visitSub(BinaryOperator &I); + void visitLShr(BinaryOperator &I); + void visitAShr(BinaryOperator &I); + void visitShl(BinaryOperator &I); + void visitSDiv(BinaryOperator &I); + void visitUDiv(BinaryOperator &I); + void visitSRem(BinaryOperator &I); + void visitURem(BinaryOperator &I); + void visitAllocaInst(AllocaInst &I); + void visitVAArgInst(VAArgInst &I); + void visitIndirectBrInst(IndirectBrInst &I); + void visitExtractElementInst(ExtractElementInst &I); + void visitInsertElementInst(InsertElementInst &I); + void visitUnreachableInst(UnreachableInst &I); + + Value *findValue(Value *V, bool OffsetOk) const; + Value *findValueImpl(Value *V, bool OffsetOk, + SmallPtrSetImpl<Value *> &Visited) const; + +public: + Module *Mod; + const DataLayout *DL; + AliasAnalysis *AA; + AssumptionCache *AC; + DominatorTree *DT; + TargetLibraryInfo *TLI; + + std::string Messages; + raw_string_ostream MessagesStr; + + Lint(Module *Mod, const DataLayout *DL, AliasAnalysis *AA, + AssumptionCache *AC, DominatorTree *DT, TargetLibraryInfo *TLI) + : Mod(Mod), DL(DL), AA(AA), AC(AC), DT(DT), TLI(TLI), + MessagesStr(Messages) {} + + void WriteValues(ArrayRef<const Value *> Vs) { + for (const Value *V : Vs) { + if (!V) + continue; + if (isa<Instruction>(V)) { + MessagesStr << *V << '\n'; + } else { + V->printAsOperand(MessagesStr, true, Mod); + MessagesStr << '\n'; } } + } - /// A check failed, so printout out the condition and the message. - /// - /// This provides a nice place to put a breakpoint if you want to see why - /// something is not correct. - void CheckFailed(const Twine &Message) { MessagesStr << Message << '\n'; } - - /// A check failed (with values to print). - /// - /// This calls the Message-only version so that the above is easier to set - /// a breakpoint on. - template <typename T1, typename... Ts> - void CheckFailed(const Twine &Message, const T1 &V1, const Ts &...Vs) { - CheckFailed(Message); - WriteValues({V1, Vs...}); - } - }; + /// A check failed, so printout out the condition and the message. + /// + /// This provides a nice place to put a breakpoint if you want to see why + /// something is not correct. + void CheckFailed(const Twine &Message) { MessagesStr << Message << '\n'; } + + /// A check failed (with values to print). + /// + /// This calls the Message-only version so that the above is easier to set + /// a breakpoint on. + template <typename T1, typename... Ts> + void CheckFailed(const Twine &Message, const T1 &V1, const Ts &... Vs) { + CheckFailed(Message); + WriteValues({V1, Vs...}); + } +}; } // end anonymous namespace -char Lint::ID = 0; -INITIALIZE_PASS_BEGIN(Lint, "lint", "Statically lint-checks LLVM IR", - false, true) -INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) -INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) -INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) -INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) -INITIALIZE_PASS_END(Lint, "lint", "Statically lint-checks LLVM IR", - false, true) - // Assert - We know that cond should be true, if not print an error message. -#define Assert(C, ...) \ - do { if (!(C)) { CheckFailed(__VA_ARGS__); return; } } while (false) - -// Lint::run - This is the main Analysis entry point for a -// function. -// -bool Lint::runOnFunction(Function &F) { - Mod = F.getParent(); - DL = &F.getParent()->getDataLayout(); - AA = &getAnalysis<AAResultsWrapperPass>().getAAResults(); - AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); - DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); - TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F); - visit(F); - dbgs() << MessagesStr.str(); - Messages.clear(); - return false; -} +#define Assert(C, ...) \ + do { \ + if (!(C)) { \ + CheckFailed(__VA_ARGS__); \ + return; \ + } \ + } while (false) void Lint::visitFunction(Function &F) { // This isn't undefined behavior, it's just a little unusual, and it's a @@ -281,8 +250,7 @@ void Lint::visitCallBase(CallBase &I) { // Check that an sret argument points to valid memory. if (Formal->hasStructRetAttr() && Actual->getType()->isPointerTy()) { - Type *Ty = - cast<PointerType>(Formal->getType())->getElementType(); + Type *Ty = cast<PointerType>(Formal->getType())->getElementType(); visitMemoryReference(I, Actual, DL->getTypeStoreSize(Ty), DL->getABITypeAlign(Ty), Ty, MemRef::Read | MemRef::Write); @@ -309,12 +277,12 @@ void Lint::visitCallBase(CallBase &I) { } } - if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I)) switch (II->getIntrinsicID()) { - default: break; + default: + break; - // TODO: Check more intrinsics + // TODO: Check more intrinsics case Intrinsic::memcpy: { MemCpyInst *MCI = cast<MemCpyInst>(&I); @@ -553,7 +521,8 @@ static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, VectorType *VecTy = dyn_cast<VectorType>(V->getType()); if (!VecTy) { - KnownBits Known = computeKnownBits(V, DL, 0, AC, dyn_cast<Instruction>(V), DT); + KnownBits Known = + computeKnownBits(V, DL, 0, AC, dyn_cast<Instruction>(V), DT); return Known.isZero(); } @@ -682,11 +651,13 @@ Value *Lint::findValueImpl(Value *V, bool OffsetOk, if (!VisitedBlocks.insert(BB).second) break; if (Value *U = - FindAvailableLoadedValue(L, BB, BBI, DefMaxInstsToScan, AA)) + FindAvailableLoadedValue(L, BB, BBI, DefMaxInstsToScan, AA)) return findValueImpl(U, OffsetOk, Visited); - if (BBI != BB->begin()) break; + if (BBI != BB->begin()) + break; BB = BB->getUniquePredecessor(); - if (!BB) break; + if (!BB) + break; BBI = BB->end(); } } else if (PHINode *PN = dyn_cast<PHINode>(V)) { @@ -696,8 +667,8 @@ Value *Lint::findValueImpl(Value *V, bool OffsetOk, if (CI->isNoopCast(*DL)) return findValueImpl(CI->getOperand(0), OffsetOk, Visited); } else if (ExtractValueInst *Ex = dyn_cast<ExtractValueInst>(V)) { - if (Value *W = FindInsertedValue(Ex->getAggregateOperand(), - Ex->getIndices())) + if (Value *W = + FindInsertedValue(Ex->getAggregateOperand(), Ex->getIndices())) if (W != V) return findValueImpl(W, OffsetOk, Visited); } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) { @@ -728,22 +699,75 @@ Value *Lint::findValueImpl(Value *V, bool OffsetOk, return V; } +PreservedAnalyses LintPass::run(Function &F, FunctionAnalysisManager &AM) { + auto *Mod = F.getParent(); + auto *DL = &F.getParent()->getDataLayout(); + auto *AA = &AM.getResult<AAManager>(F); + auto *AC = &AM.getResult<AssumptionAnalysis>(F); + auto *DT = &AM.getResult<DominatorTreeAnalysis>(F); + auto *TLI = &AM.getResult<TargetLibraryAnalysis>(F); + Lint L(Mod, DL, AA, AC, DT, TLI); + L.visit(F); + dbgs() << L.MessagesStr.str(); + return PreservedAnalyses::all(); +} + +class LintLegacyPass : public FunctionPass { +public: + static char ID; // Pass identification, replacement for typeid + LintLegacyPass() : FunctionPass(ID) { + initializeLintLegacyPassPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + AU.addRequired<AAResultsWrapperPass>(); + AU.addRequired<AssumptionCacheTracker>(); + AU.addRequired<TargetLibraryInfoWrapperPass>(); + AU.addRequired<DominatorTreeWrapperPass>(); + } + void print(raw_ostream &O, const Module *M) const override {} +}; + +char LintLegacyPass::ID = 0; +INITIALIZE_PASS_BEGIN(LintLegacyPass, "lint", "Statically lint-checks LLVM IR", + false, true) +INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) +INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) +INITIALIZE_PASS_END(LintLegacyPass, "lint", "Statically lint-checks LLVM IR", + false, true) + +bool LintLegacyPass::runOnFunction(Function &F) { + auto *Mod = F.getParent(); + auto *DL = &F.getParent()->getDataLayout(); + auto *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults(); + auto *AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); + auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); + auto *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F); + Lint L(Mod, DL, AA, AC, DT, TLI); + L.visit(F); + dbgs() << L.MessagesStr.str(); + return false; +} + //===----------------------------------------------------------------------===// // Implement the public interfaces to this file... //===----------------------------------------------------------------------===// -FunctionPass *llvm::createLintPass() { - return new Lint(); -} +FunctionPass *llvm::createLintLegacyPassPass() { return new LintLegacyPass(); } /// lintFunction - Check a function for errors, printing messages on stderr. /// void llvm::lintFunction(const Function &f) { - Function &F = const_cast<Function&>(f); + Function &F = const_cast<Function &>(f); assert(!F.isDeclaration() && "Cannot lint external functions"); legacy::FunctionPassManager FPM(F.getParent()); - Lint *V = new Lint(); + auto *V = new LintLegacyPass(); FPM.add(V); FPM.run(F); } @@ -752,7 +776,7 @@ void llvm::lintFunction(const Function &f) { /// void llvm::lintModule(const Module &M) { legacy::PassManager PM; - Lint *V = new Lint(); + auto *V = new LintLegacyPass(); PM.add(V); - PM.run(const_cast<Module&>(M)); + PM.run(const_cast<Module &>(M)); } |