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