| //===- TestPasses.cpp - "buggy" passes used to test bugpoint --------------===// |
| // |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file contains "buggy" passes that are used to test bugpoint, to check |
| // that it is narrowing down testcases correctly. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/IR/BasicBlock.h" |
| #include "llvm/IR/Constant.h" |
| #include "llvm/IR/InstIterator.h" |
| #include "llvm/IR/InstVisitor.h" |
| #include "llvm/IR/Instructions.h" |
| #include "llvm/IR/Type.h" |
| #include "llvm/Pass.h" |
| |
| #include "llvm/IR/PatternMatch.h" |
| using namespace llvm::PatternMatch; |
| using namespace llvm; |
| |
| namespace { |
| /// CrashOnCalls - This pass is used to test bugpoint. It intentionally |
| /// crashes on any call instructions. |
| class CrashOnCalls : public FunctionPass { |
| public: |
| static char ID; // Pass ID, replacement for typeid |
| CrashOnCalls() : FunctionPass(ID) {} |
| |
| private: |
| void getAnalysisUsage(AnalysisUsage &AU) const override { |
| AU.setPreservesAll(); |
| } |
| |
| bool runOnFunction(Function &F) override { |
| for (auto &BB : F) |
| for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) |
| if (isa<CallInst>(*I)) |
| abort(); |
| |
| return false; |
| } |
| }; |
| } |
| |
| char CrashOnCalls::ID = 0; |
| static RegisterPass<CrashOnCalls> |
| X("bugpoint-crashcalls", |
| "BugPoint Test Pass - Intentionally crash on CallInsts"); |
| |
| namespace { |
| /// DeleteCalls - This pass is used to test bugpoint. It intentionally |
| /// deletes some call instructions, "misoptimizing" the program. |
| class DeleteCalls : public FunctionPass { |
| public: |
| static char ID; // Pass ID, replacement for typeid |
| DeleteCalls() : FunctionPass(ID) {} |
| |
| private: |
| bool runOnFunction(Function &F) override { |
| for (auto &BB : F) |
| for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) |
| if (CallInst *CI = dyn_cast<CallInst>(I)) { |
| if (!CI->use_empty()) |
| CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); |
| CI->eraseFromParent(); |
| break; |
| } |
| return false; |
| } |
| }; |
| } |
| |
| char DeleteCalls::ID = 0; |
| static RegisterPass<DeleteCalls> |
| Y("bugpoint-deletecalls", |
| "BugPoint Test Pass - Intentionally 'misoptimize' CallInsts"); |
| |
| namespace { |
| /// CrashOnDeclFunc - This pass is used to test bugpoint. It intentionally |
| /// crashes if the module has an undefined function (ie a function that is |
| /// defined in an external module). |
| class CrashOnDeclFunc : public ModulePass { |
| public: |
| static char ID; // Pass ID, replacement for typeid |
| CrashOnDeclFunc() : ModulePass(ID) {} |
| |
| private: |
| bool runOnModule(Module &M) override { |
| for (auto &F : M.functions()) { |
| if (F.isDeclaration()) |
| abort(); |
| } |
| return false; |
| } |
| }; |
| } |
| |
| char CrashOnDeclFunc::ID = 0; |
| static RegisterPass<CrashOnDeclFunc> |
| Z("bugpoint-crash-decl-funcs", |
| "BugPoint Test Pass - Intentionally crash on declared functions"); |
| |
| namespace { |
| /// CrashOnOneCU - This pass is used to test bugpoint. It intentionally |
| /// crashes if the Module has two or more compile units |
| class CrashOnTooManyCUs : public ModulePass { |
| public: |
| static char ID; |
| CrashOnTooManyCUs() : ModulePass(ID) {} |
| |
| private: |
| bool runOnModule(Module &M) override { |
| NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu"); |
| if (!CU_Nodes) |
| return false; |
| if (CU_Nodes->getNumOperands() >= 2) |
| abort(); |
| return false; |
| } |
| }; |
| } |
| |
| char CrashOnTooManyCUs::ID = 0; |
| static RegisterPass<CrashOnTooManyCUs> |
| A("bugpoint-crash-too-many-cus", |
| "BugPoint Test Pass - Intentionally crash on too many CUs"); |
| |
| namespace { |
| class CrashOnFunctionAttribute : public FunctionPass { |
| public: |
| static char ID; // Pass ID, replacement for typeid |
| CrashOnFunctionAttribute() : FunctionPass(ID) {} |
| |
| private: |
| void getAnalysisUsage(AnalysisUsage &AU) const override { |
| AU.setPreservesAll(); |
| } |
| |
| bool runOnFunction(Function &F) override { |
| AttributeSet A = F.getAttributes().getFnAttrs(); |
| if (A.hasAttribute("bugpoint-crash")) |
| abort(); |
| return false; |
| } |
| }; |
| } // namespace |
| |
| char CrashOnFunctionAttribute::ID = 0; |
| static RegisterPass<CrashOnFunctionAttribute> |
| B("bugpoint-crashfuncattr", "BugPoint Test Pass - Intentionally crash on " |
| "function attribute 'bugpoint-crash'"); |
| |
| namespace { |
| class CrashOnMetadata : public FunctionPass { |
| public: |
| static char ID; // Pass ID, replacement for typeid |
| CrashOnMetadata() : FunctionPass(ID) {} |
| |
| private: |
| void getAnalysisUsage(AnalysisUsage &AU) const override { |
| AU.setPreservesAll(); |
| } |
| |
| // Crash on fabs calls with fpmath metdata and an fadd as argument. This |
| // ensures the fadd instruction sticks around and we can check that the |
| // metadata there is dropped correctly. |
| bool runOnFunction(Function &F) override { |
| for (Instruction &I : instructions(F)) |
| if (match(&I, m_FAbs(m_FAdd(m_Value(), m_Value()))) && |
| I.hasMetadata("fpmath")) |
| abort(); |
| return false; |
| } |
| }; |
| } // namespace |
| |
| char CrashOnMetadata::ID = 0; |
| static RegisterPass<CrashOnMetadata> |
| C("bugpoint-crashmetadata", |
| "BugPoint Test Pass - Intentionally crash on " |
| "fabs calls with fpmath metadata and an fadd as argument"); |