//===- 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(*I)) abort(); return false; } }; } char CrashOnCalls::ID = 0; static RegisterPass 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(I)) { if (!CI->use_empty()) CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); CI->getParent()->getInstList().erase(CI); break; } return false; } }; } char DeleteCalls::ID = 0; static RegisterPass 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 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 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().getFnAttributes(); if (A.hasAttribute("bugpoint-crash")) abort(); return false; } }; } // namespace char CrashOnFunctionAttribute::ID = 0; static RegisterPass 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 C("bugpoint-crashmetadata", "BugPoint Test Pass - Intentionally crash on " "fabs calls with fpmath metadata and an fadd as argument");