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 |
33 | CrashOnCalls() : FunctionPass(ID) {} |
34 | |
35 | private: |
36 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
37 | AU.setPreservesAll(); |
38 | } |
39 | |
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>(Val: *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 |
62 | DeleteCalls() : FunctionPass(ID) {} |
63 | |
64 | private: |
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>(Val&: I)) { |
69 | if (!CI->use_empty()) |
70 | CI->replaceAllUsesWith(V: Constant::getNullValue(Ty: CI->getType())); |
71 | CI->eraseFromParent(); |
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 |
91 | CrashOnDeclFunc() : ModulePass(ID) {} |
92 | |
93 | private: |
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; |
115 | CrashOnTooManyCUs() : ModulePass(ID) {} |
116 | |
117 | private: |
118 | bool runOnModule(Module &M) override { |
119 | NamedMDNode *CU_Nodes = M.getNamedMetadata(Name: "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 |
138 | CrashOnFunctionAttribute() : FunctionPass(ID) {} |
139 | |
140 | private: |
141 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
142 | AU.setPreservesAll(); |
143 | } |
144 | |
145 | bool runOnFunction(Function &F) override { |
146 | AttributeSet A = F.getAttributes().getFnAttrs(); |
147 | if (A.hasAttribute(Kind: "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 |
163 | CrashOnMetadata() : FunctionPass(ID) {} |
164 | |
165 | private: |
166 | 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. |
173 | bool runOnFunction(Function &F) override { |
174 | for (Instruction &I : instructions(F)) |
175 | if (match(V: &I, P: m_FAbs(Op0: m_FAdd(L: m_Value(), R: m_Value()))) && |
176 | I.hasMetadata(Kind: "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 | |