1//===- ExtractFunction.cpp - Extract a function from Program --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements several methods that are used to extract functions,
10// loops, or portions of a module from the rest of the module.
11//
12//===----------------------------------------------------------------------===//
13
14#include "BugDriver.h"
15#include "llvm/IR/Constants.h"
16#include "llvm/IR/DataLayout.h"
17#include "llvm/IR/DerivedTypes.h"
18#include "llvm/IR/LLVMContext.h"
19#include "llvm/IR/LegacyPassManager.h"
20#include "llvm/IR/Module.h"
21#include "llvm/IR/Verifier.h"
22#include "llvm/Pass.h"
23#include "llvm/Support/CommandLine.h"
24#include "llvm/Support/Debug.h"
25#include "llvm/Support/FileUtilities.h"
26#include "llvm/Support/Path.h"
27#include "llvm/Support/Signals.h"
28#include "llvm/Support/ToolOutputFile.h"
29#include "llvm/Transforms/IPO.h"
30#include "llvm/Transforms/Scalar.h"
31#include "llvm/Transforms/Utils/Cloning.h"
32#include "llvm/Transforms/Utils/CodeExtractor.h"
33#include <set>
34using namespace llvm;
35
36#define DEBUG_TYPE "bugpoint"
37
38bool llvm::DisableSimplifyCFG = false;
39
40static cl::opt<bool>
41 NoDCE("disable-dce",
42 cl::desc("Do not use the -dce pass to reduce testcases"));
43static cl::opt<bool, true>
44 NoSCFG("disable-simplifycfg", cl::location(L&: DisableSimplifyCFG),
45 cl::desc("Do not use the -simplifycfg pass to reduce testcases"));
46
47static Function *globalInitUsesExternalBA(GlobalVariable *GV) {
48 if (!GV->hasInitializer())
49 return nullptr;
50
51 Constant *I = GV->getInitializer();
52
53 // walk the values used by the initializer
54 // (and recurse into things like ConstantExpr)
55 std::vector<Constant *> Todo;
56 std::set<Constant *> Done;
57 Todo.push_back(x: I);
58
59 while (!Todo.empty()) {
60 Constant *V = Todo.back();
61 Todo.pop_back();
62 Done.insert(x: V);
63
64 if (BlockAddress *BA = dyn_cast<BlockAddress>(Val: V)) {
65 Function *F = BA->getFunction();
66 if (F->isDeclaration())
67 return F;
68 }
69
70 for (User::op_iterator i = V->op_begin(), e = V->op_end(); i != e; ++i) {
71 Constant *C = dyn_cast<Constant>(Val&: *i);
72 if (C && !isa<GlobalValue>(Val: C) && !Done.count(x: C))
73 Todo.push_back(x: C);
74 }
75 }
76 return nullptr;
77}
78
79std::unique_ptr<Module>
80BugDriver::deleteInstructionFromProgram(const Instruction *I,
81 unsigned Simplification) {
82 // FIXME, use vmap?
83 std::unique_ptr<Module> Clone = CloneModule(M: *Program);
84
85 const BasicBlock *PBB = I->getParent();
86 const Function *PF = PBB->getParent();
87
88 Module::iterator RFI = Clone->begin(); // Get iterator to corresponding fn
89 std::advance(
90 i&: RFI, n: std::distance(first: PF->getParent()->begin(), last: Module::const_iterator(PF)));
91
92 Function::iterator RBI = RFI->begin(); // Get iterator to corresponding BB
93 std::advance(i&: RBI, n: std::distance(first: PF->begin(), last: Function::const_iterator(PBB)));
94
95 BasicBlock::iterator RI = RBI->begin(); // Get iterator to corresponding inst
96 std::advance(i&: RI, n: std::distance(first: PBB->begin(), last: BasicBlock::const_iterator(I)));
97 Instruction *TheInst = &*RI; // Got the corresponding instruction!
98
99 // If this instruction produces a value, replace any users with null values
100 if (!TheInst->getType()->isVoidTy())
101 TheInst->replaceAllUsesWith(V: Constant::getNullValue(Ty: TheInst->getType()));
102
103 // Remove the instruction from the program.
104 TheInst->eraseFromParent();
105
106 // Spiff up the output a little bit.
107 std::vector<std::string> Passes;
108
109 /// Can we get rid of the -disable-* options?
110 if (Simplification > 1 && !NoDCE)
111 Passes.push_back(x: "dce");
112 if (Simplification && !DisableSimplifyCFG)
113 Passes.push_back(x: "simplifycfg"); // Delete dead control flow
114
115 Passes.push_back(x: "verify");
116 std::unique_ptr<Module> New = runPassesOn(M: Clone.get(), Passes);
117 if (!New) {
118 errs() << "Instruction removal failed. Sorry. :( Please report a bug!\n";
119 exit(status: 1);
120 }
121 return New;
122}
123
124std::unique_ptr<Module>
125BugDriver::performFinalCleanups(std::unique_ptr<Module> M,
126 bool MayModifySemantics) {
127 // Make all functions external, so GlobalDCE doesn't delete them...
128 for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
129 I->setLinkage(GlobalValue::ExternalLinkage);
130
131 std::vector<std::string> CleanupPasses;
132
133 if (MayModifySemantics)
134 CleanupPasses.push_back(x: "deadarghaX0r");
135 else
136 CleanupPasses.push_back(x: "deadargelim");
137
138 std::unique_ptr<Module> New = runPassesOn(M: M.get(), Passes: CleanupPasses);
139 if (!New) {
140 errs() << "Final cleanups failed. Sorry. :( Please report a bug!\n";
141 return nullptr;
142 }
143 return New;
144}
145
146std::unique_ptr<Module> BugDriver::extractLoop(Module *M) {
147 std::vector<std::string> LoopExtractPasses;
148 LoopExtractPasses.push_back(x: "loop-extract-single");
149
150 std::unique_ptr<Module> NewM = runPassesOn(M, Passes: LoopExtractPasses);
151 if (!NewM) {
152 outs() << "*** Loop extraction failed: ";
153 emitProgressBitcode(M: *M, ID: "loopextraction", NoFlyer: true);
154 outs() << "*** Sorry. :( Please report a bug!\n";
155 return nullptr;
156 }
157
158 // Check to see if we created any new functions. If not, no loops were
159 // extracted and we should return null. Limit the number of loops we extract
160 // to avoid taking forever.
161 static unsigned NumExtracted = 32;
162 if (M->size() == NewM->size() || --NumExtracted == 0) {
163 return nullptr;
164 } else {
165 assert(M->size() < NewM->size() && "Loop extract removed functions?");
166 Module::iterator MI = NewM->begin();
167 for (unsigned i = 0, e = M->size(); i != e; ++i)
168 ++MI;
169 }
170
171 return NewM;
172}
173
174static void eliminateAliases(GlobalValue *GV) {
175 // First, check whether a GlobalAlias references this definition.
176 // GlobalAlias MAY NOT reference declarations.
177 for (;;) {
178 // 1. Find aliases
179 SmallVector<GlobalAlias *, 1> aliases;
180 Module *M = GV->getParent();
181 for (Module::alias_iterator I = M->alias_begin(), E = M->alias_end();
182 I != E; ++I)
183 if (I->getAliasee()->stripPointerCasts() == GV)
184 aliases.push_back(Elt: &*I);
185 if (aliases.empty())
186 break;
187 // 2. Resolve aliases
188 for (unsigned i = 0, e = aliases.size(); i < e; ++i) {
189 aliases[i]->replaceAllUsesWith(V: aliases[i]->getAliasee());
190 aliases[i]->eraseFromParent();
191 }
192 // 3. Repeat until no more aliases found; there might
193 // be an alias to an alias...
194 }
195}
196
197// "Remove" the global variable by deleting its initializer, making it external.
198void llvm::deleteGlobalInitializer(GlobalVariable *GV) {
199 eliminateAliases(GV);
200 GV->setInitializer(nullptr);
201 GV->setComdat(nullptr);
202}
203
204// "Remove" the function by deleting all of its basic blocks, making it
205// external.
206void llvm::deleteFunctionBody(Function *F) {
207 eliminateAliases(GV: F);
208 // Function declarations can't have comdats.
209 F->setComdat(nullptr);
210
211 // delete the body of the function...
212 F->deleteBody();
213 assert(F->isDeclaration() && "This didn't make the function external!");
214}
215
216/// getTorInit - Given a list of entries for static ctors/dtors, return them
217/// as a constant array.
218static Constant *getTorInit(std::vector<std::pair<Function *, int>> &TorList) {
219 assert(!TorList.empty() && "Don't create empty tor list!");
220 std::vector<Constant *> ArrayElts;
221 Type *Int32Ty = Type::getInt32Ty(C&: TorList[0].first->getContext());
222
223 StructType *STy = StructType::get(elt1: Int32Ty, elts: TorList[0].first->getType());
224 for (unsigned i = 0, e = TorList.size(); i != e; ++i) {
225 Constant *Elts[] = {ConstantInt::get(Ty: Int32Ty, V: TorList[i].second),
226 TorList[i].first};
227 ArrayElts.push_back(x: ConstantStruct::get(T: STy, V: Elts));
228 }
229 return ConstantArray::get(
230 T: ArrayType::get(ElementType: ArrayElts[0]->getType(), NumElements: ArrayElts.size()), V: ArrayElts);
231}
232
233/// splitStaticCtorDtor - A module was recently split into two parts, M1/M2, and
234/// M1 has all of the global variables. If M2 contains any functions that are
235/// static ctors/dtors, we need to add an llvm.global_[cd]tors global to M2, and
236/// prune appropriate entries out of M1s list.
237static void splitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2,
238 ValueToValueMapTy &VMap) {
239 GlobalVariable *GV = M1->getNamedGlobal(Name: GlobalName);
240 if (!GV || GV->isDeclaration() || GV->hasLocalLinkage() || !GV->use_empty())
241 return;
242
243 std::vector<std::pair<Function *, int>> M1Tors, M2Tors;
244 ConstantArray *InitList = dyn_cast<ConstantArray>(Val: GV->getInitializer());
245 if (!InitList)
246 return;
247
248 for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
249 if (ConstantStruct *CS =
250 dyn_cast<ConstantStruct>(Val: InitList->getOperand(i_nocapture: i))) {
251 if (CS->getNumOperands() != 2)
252 return; // Not array of 2-element structs.
253
254 if (CS->getOperand(i_nocapture: 1)->isNullValue())
255 break; // Found a null terminator, stop here.
256
257 ConstantInt *CI = dyn_cast<ConstantInt>(Val: CS->getOperand(i_nocapture: 0));
258 int Priority = CI ? CI->getSExtValue() : 0;
259
260 Constant *FP = CS->getOperand(i_nocapture: 1);
261 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Val: FP))
262 if (CE->isCast())
263 FP = CE->getOperand(i_nocapture: 0);
264 if (Function *F = dyn_cast<Function>(Val: FP)) {
265 if (!F->isDeclaration())
266 M1Tors.push_back(x: std::make_pair(x&: F, y&: Priority));
267 else {
268 // Map to M2's version of the function.
269 F = cast<Function>(Val&: VMap[F]);
270 M2Tors.push_back(x: std::make_pair(x&: F, y&: Priority));
271 }
272 }
273 }
274 }
275
276 GV->eraseFromParent();
277 if (!M1Tors.empty()) {
278 Constant *M1Init = getTorInit(TorList&: M1Tors);
279 new GlobalVariable(*M1, M1Init->getType(), false,
280 GlobalValue::AppendingLinkage, M1Init, GlobalName);
281 }
282
283 GV = M2->getNamedGlobal(Name: GlobalName);
284 assert(GV && "Not a clone of M1?");
285 assert(GV->use_empty() && "llvm.ctors shouldn't have uses!");
286
287 GV->eraseFromParent();
288 if (!M2Tors.empty()) {
289 Constant *M2Init = getTorInit(TorList&: M2Tors);
290 new GlobalVariable(*M2, M2Init->getType(), false,
291 GlobalValue::AppendingLinkage, M2Init, GlobalName);
292 }
293}
294
295std::unique_ptr<Module>
296llvm::splitFunctionsOutOfModule(Module *M, const std::vector<Function *> &F,
297 ValueToValueMapTy &VMap) {
298 // Make sure functions & globals are all external so that linkage
299 // between the two modules will work.
300 for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
301 I->setLinkage(GlobalValue::ExternalLinkage);
302 for (Module::global_iterator I = M->global_begin(), E = M->global_end();
303 I != E; ++I) {
304 if (I->hasName() && I->getName()[0] == '\01')
305 I->setName(I->getName().substr(Start: 1));
306 I->setLinkage(GlobalValue::ExternalLinkage);
307 }
308
309 ValueToValueMapTy NewVMap;
310 std::unique_ptr<Module> New = CloneModule(M: *M, VMap&: NewVMap);
311
312 // Remove the Test functions from the Safe module
313 std::set<Function *> TestFunctions;
314 for (unsigned i = 0, e = F.size(); i != e; ++i) {
315 Function *TNOF = cast<Function>(Val&: VMap[F[i]]);
316 LLVM_DEBUG(errs() << "Removing function ");
317 LLVM_DEBUG(TNOF->printAsOperand(errs(), false));
318 LLVM_DEBUG(errs() << "\n");
319 TestFunctions.insert(x: cast<Function>(Val&: NewVMap[TNOF]));
320 deleteFunctionBody(F: TNOF); // Function is now external in this module!
321 }
322
323 // Remove the Safe functions from the Test module
324 for (Function &I : *New)
325 if (!TestFunctions.count(x: &I))
326 deleteFunctionBody(F: &I);
327
328 // Try to split the global initializers evenly
329 for (GlobalVariable &I : M->globals()) {
330 GlobalVariable *GV = cast<GlobalVariable>(Val&: NewVMap[&I]);
331 if (Function *TestFn = globalInitUsesExternalBA(GV: &I)) {
332 if (Function *SafeFn = globalInitUsesExternalBA(GV)) {
333 errs() << "*** Error: when reducing functions, encountered "
334 "the global '";
335 GV->printAsOperand(O&: errs(), PrintType: false);
336 errs() << "' with an initializer that references blockaddresses "
337 "from safe function '"
338 << SafeFn->getName() << "' and from test function '"
339 << TestFn->getName() << "'.\n";
340 exit(status: 1);
341 }
342 deleteGlobalInitializer(GV: &I); // Delete the initializer to make it external
343 } else {
344 // If we keep it in the safe module, then delete it in the test module
345 deleteGlobalInitializer(GV);
346 }
347 }
348
349 // Make sure that there is a global ctor/dtor array in both halves of the
350 // module if they both have static ctor/dtor functions.
351 splitStaticCtorDtor(GlobalName: "llvm.global_ctors", M1: M, M2: New.get(), VMap&: NewVMap);
352 splitStaticCtorDtor(GlobalName: "llvm.global_dtors", M1: M, M2: New.get(), VMap&: NewVMap);
353
354 return New;
355}
356
357//===----------------------------------------------------------------------===//
358// Basic Block Extraction Code
359//===----------------------------------------------------------------------===//
360
361std::unique_ptr<Module>
362BugDriver::extractMappedBlocksFromModule(const std::vector<BasicBlock *> &BBs,
363 Module *M) {
364 auto Temp = sys::fs::TempFile::create(Model: OutputPrefix + "-extractblocks%%%%%%%");
365 if (!Temp) {
366 outs() << "*** Basic Block extraction failed!\n";
367 errs() << "Error creating temporary file: " << toString(E: Temp.takeError())
368 << "\n";
369 emitProgressBitcode(M: *M, ID: "basicblockextractfail", NoFlyer: true);
370 return nullptr;
371 }
372 DiscardTemp Discard{.File: *Temp};
373
374 // Extract all of the blocks except the ones in BBs.
375 SmallVector<BasicBlock *, 32> BlocksToExtract;
376 for (Function &F : *M)
377 for (BasicBlock &BB : F)
378 // Check if this block is going to be extracted.
379 if (!llvm::is_contained(Range: BBs, Element: &BB))
380 BlocksToExtract.push_back(Elt: &BB);
381
382 raw_fd_ostream OS(Temp->FD, /*shouldClose*/ false);
383 for (BasicBlock *BB : BBs) {
384 // If the BB doesn't have a name, give it one so we have something to key
385 // off of.
386 if (!BB->hasName())
387 BB->setName("tmpbb");
388 OS << BB->getParent()->getName() << " " << BB->getName() << "\n";
389 }
390 OS.flush();
391 if (OS.has_error()) {
392 errs() << "Error writing list of blocks to not extract\n";
393 emitProgressBitcode(M: *M, ID: "basicblockextractfail", NoFlyer: true);
394 OS.clear_error();
395 return nullptr;
396 }
397
398 std::string uniqueFN = "--extract-blocks-file=";
399 uniqueFN += Temp->TmpName;
400
401 std::vector<std::string> PI;
402 PI.push_back(x: "extract-blocks");
403 std::unique_ptr<Module> Ret = runPassesOn(M, Passes: PI, ExtraArgs: {uniqueFN});
404
405 if (!Ret) {
406 outs() << "*** Basic Block extraction failed, please report a bug!\n";
407 emitProgressBitcode(M: *M, ID: "basicblockextractfail", NoFlyer: true);
408 }
409 return Ret;
410}
411