1 //===- TestPasses.cpp - "buggy" passes used to test bugpoint --------------===// 2 // 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains "buggy" passes that are used to test bugpoint, to check 11 // that it is narrowing down testcases correctly. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/IR/BasicBlock.h" 16 #include "llvm/IR/Constant.h" 17 #include "llvm/IR/InstIterator.h" 18 #include "llvm/IR/InstVisitor.h" 19 #include "llvm/IR/Instructions.h" 20 #include "llvm/IR/Type.h" 21 #include "llvm/Pass.h" 22 23 #include "llvm/IR/PatternMatch.h" 24 using namespace llvm::PatternMatch; 25 using namespace llvm; 26 27 namespace { 28 /// CrashOnCalls - This pass is used to test bugpoint. It intentionally 29 /// crashes on any call instructions. 30 class CrashOnCalls : public FunctionPass { 31 public: 32 static char ID; // Pass ID, replacement for typeid CrashOnCalls()33 CrashOnCalls() : FunctionPass(ID) {} 34 35 private: getAnalysisUsage(AnalysisUsage & AU) const36 void getAnalysisUsage(AnalysisUsage &AU) const override { 37 AU.setPreservesAll(); 38 } 39 runOnFunction(Function & F)40 bool runOnFunction(Function &F) override { 41 for (auto &BB : F) 42 for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) 43 if (isa<CallInst>(*I)) 44 abort(); 45 46 return false; 47 } 48 }; 49 } 50 51 char CrashOnCalls::ID = 0; 52 static RegisterPass<CrashOnCalls> 53 X("bugpoint-crashcalls", 54 "BugPoint Test Pass - Intentionally crash on CallInsts"); 55 56 namespace { 57 /// DeleteCalls - This pass is used to test bugpoint. It intentionally 58 /// deletes some call instructions, "misoptimizing" the program. 59 class DeleteCalls : public FunctionPass { 60 public: 61 static char ID; // Pass ID, replacement for typeid DeleteCalls()62 DeleteCalls() : FunctionPass(ID) {} 63 64 private: runOnFunction(Function & F)65 bool runOnFunction(Function &F) override { 66 for (auto &BB : F) 67 for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) 68 if (CallInst *CI = dyn_cast<CallInst>(I)) { 69 if (!CI->use_empty()) 70 CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); 71 CI->getParent()->getInstList().erase(CI); 72 break; 73 } 74 return false; 75 } 76 }; 77 } 78 79 char DeleteCalls::ID = 0; 80 static RegisterPass<DeleteCalls> 81 Y("bugpoint-deletecalls", 82 "BugPoint Test Pass - Intentionally 'misoptimize' CallInsts"); 83 84 namespace { 85 /// CrashOnDeclFunc - This pass is used to test bugpoint. It intentionally 86 /// crashes if the module has an undefined function (ie a function that is 87 /// defined in an external module). 88 class CrashOnDeclFunc : public ModulePass { 89 public: 90 static char ID; // Pass ID, replacement for typeid CrashOnDeclFunc()91 CrashOnDeclFunc() : ModulePass(ID) {} 92 93 private: runOnModule(Module & M)94 bool runOnModule(Module &M) override { 95 for (auto &F : M.functions()) { 96 if (F.isDeclaration()) 97 abort(); 98 } 99 return false; 100 } 101 }; 102 } 103 104 char CrashOnDeclFunc::ID = 0; 105 static RegisterPass<CrashOnDeclFunc> 106 Z("bugpoint-crash-decl-funcs", 107 "BugPoint Test Pass - Intentionally crash on declared functions"); 108 109 namespace { 110 /// CrashOnOneCU - This pass is used to test bugpoint. It intentionally 111 /// crashes if the Module has two or more compile units 112 class CrashOnTooManyCUs : public ModulePass { 113 public: 114 static char ID; CrashOnTooManyCUs()115 CrashOnTooManyCUs() : ModulePass(ID) {} 116 117 private: runOnModule(Module & M)118 bool runOnModule(Module &M) override { 119 NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu"); 120 if (!CU_Nodes) 121 return false; 122 if (CU_Nodes->getNumOperands() >= 2) 123 abort(); 124 return false; 125 } 126 }; 127 } 128 129 char CrashOnTooManyCUs::ID = 0; 130 static RegisterPass<CrashOnTooManyCUs> 131 A("bugpoint-crash-too-many-cus", 132 "BugPoint Test Pass - Intentionally crash on too many CUs"); 133 134 namespace { 135 class CrashOnFunctionAttribute : public FunctionPass { 136 public: 137 static char ID; // Pass ID, replacement for typeid CrashOnFunctionAttribute()138 CrashOnFunctionAttribute() : FunctionPass(ID) {} 139 140 private: getAnalysisUsage(AnalysisUsage & AU) const141 void getAnalysisUsage(AnalysisUsage &AU) const override { 142 AU.setPreservesAll(); 143 } 144 runOnFunction(Function & F)145 bool runOnFunction(Function &F) override { 146 AttributeSet A = F.getAttributes().getFnAttributes(); 147 if (A.hasAttribute("bugpoint-crash")) 148 abort(); 149 return false; 150 } 151 }; 152 } // namespace 153 154 char CrashOnFunctionAttribute::ID = 0; 155 static RegisterPass<CrashOnFunctionAttribute> 156 B("bugpoint-crashfuncattr", "BugPoint Test Pass - Intentionally crash on " 157 "function attribute 'bugpoint-crash'"); 158 159 namespace { 160 class CrashOnMetadata : public FunctionPass { 161 public: 162 static char ID; // Pass ID, replacement for typeid CrashOnMetadata()163 CrashOnMetadata() : FunctionPass(ID) {} 164 165 private: getAnalysisUsage(AnalysisUsage & AU) const166 void getAnalysisUsage(AnalysisUsage &AU) const override { 167 AU.setPreservesAll(); 168 } 169 170 // Crash on fabs calls with fpmath metdata and an fadd as argument. This 171 // ensures the fadd instruction sticks around and we can check that the 172 // metadata there is dropped correctly. runOnFunction(Function & F)173 bool runOnFunction(Function &F) override { 174 for (Instruction &I : instructions(F)) 175 if (match(&I, m_FAbs(m_FAdd(m_Value(), m_Value()))) && 176 I.hasMetadata("fpmath")) 177 abort(); 178 return false; 179 } 180 }; 181 } // namespace 182 183 char CrashOnMetadata::ID = 0; 184 static RegisterPass<CrashOnMetadata> 185 C("bugpoint-crashmetadata", 186 "BugPoint Test Pass - Intentionally crash on " 187 "fabs calls with fpmath metadata and an fadd as argument"); 188