173a6bdd9SChris Lattner //===- ExtractFunction.cpp - Extract a function from Program --------------===//
273a6bdd9SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609344dcfSJohn Criswell //
709344dcfSJohn Criswell //===----------------------------------------------------------------------===//
809344dcfSJohn Criswell //
9fd72bed3SChris Lattner // This file implements several methods that are used to extract functions,
10fd72bed3SChris Lattner // loops, or portions of a module from the rest of the module.
1173a6bdd9SChris Lattner //
1273a6bdd9SChris Lattner //===----------------------------------------------------------------------===//
1373a6bdd9SChris Lattner 
1473a6bdd9SChris Lattner #include "BugDriver.h"
159fb823bbSChandler Carruth #include "llvm/IR/Constants.h"
169fb823bbSChandler Carruth #include "llvm/IR/DataLayout.h"
179fb823bbSChandler Carruth #include "llvm/IR/DerivedTypes.h"
189fb823bbSChandler Carruth #include "llvm/IR/LLVMContext.h"
1930d69c2eSChandler Carruth #include "llvm/IR/LegacyPassManager.h"
209fb823bbSChandler Carruth #include "llvm/IR/Module.h"
215ad5f15cSChandler Carruth #include "llvm/IR/Verifier.h"
22ef432703SBrian Gaeke #include "llvm/Pass.h"
234d88a1c2SChandler Carruth #include "llvm/Support/CommandLine.h"
244d88a1c2SChandler Carruth #include "llvm/Support/Debug.h"
254d88a1c2SChandler Carruth #include "llvm/Support/FileUtilities.h"
264d88a1c2SChandler Carruth #include "llvm/Support/Path.h"
274d88a1c2SChandler Carruth #include "llvm/Support/Signals.h"
284d88a1c2SChandler Carruth #include "llvm/Support/ToolOutputFile.h"
2973a6bdd9SChris Lattner #include "llvm/Transforms/IPO.h"
300eb5ce94SChris Lattner #include "llvm/Transforms/Scalar.h"
3173a6bdd9SChris Lattner #include "llvm/Transforms/Utils/Cloning.h"
320fde0015SChandler Carruth #include "llvm/Transforms/Utils/CodeExtractor.h"
333838243dSChris Lattner #include <set>
343f1ad878SChris Lattner using namespace llvm;
35960707c3SBrian Gaeke 
36e96dd897SChandler Carruth #define DEBUG_TYPE "bugpoint"
37e96dd897SChandler Carruth 
38960707c3SBrian Gaeke namespace llvm {
39d1e2aaefSChris Lattner bool DisableSimplifyCFG = false;
40a53337f7SDaniel Dunbar extern cl::opt<std::string> OutputPrefix;
41960707c3SBrian Gaeke } // End llvm namespace
42960707c3SBrian Gaeke 
438d8de422SChris Lattner namespace {
448d0a0811SJustin Bogner cl::opt<bool> NoDCE("disable-dce",
458d8de422SChris Lattner                     cl::desc("Do not use the -dce pass to reduce testcases"));
46d1e2aaefSChris Lattner cl::opt<bool, true>
47d1e2aaefSChris Lattner     NoSCFG("disable-simplifycfg", cl::location(DisableSimplifyCFG),
488d8de422SChris Lattner            cl::desc("Do not use the -simplifycfg pass to reduce testcases"));
499f18ea84SEli Friedman 
globalInitUsesExternalBA(GlobalVariable * GV)509f18ea84SEli Friedman Function *globalInitUsesExternalBA(GlobalVariable *GV) {
519f18ea84SEli Friedman   if (!GV->hasInitializer())
52e6cb63e4SCraig Topper     return nullptr;
539f18ea84SEli Friedman 
549f18ea84SEli Friedman   Constant *I = GV->getInitializer();
559f18ea84SEli Friedman 
569f18ea84SEli Friedman   // walk the values used by the initializer
579f18ea84SEli Friedman   // (and recurse into things like ConstantExpr)
589f18ea84SEli Friedman   std::vector<Constant *> Todo;
599f18ea84SEli Friedman   std::set<Constant *> Done;
609f18ea84SEli Friedman   Todo.push_back(I);
619f18ea84SEli Friedman 
629f18ea84SEli Friedman   while (!Todo.empty()) {
639f18ea84SEli Friedman     Constant *V = Todo.back();
649f18ea84SEli Friedman     Todo.pop_back();
659f18ea84SEli Friedman     Done.insert(V);
669f18ea84SEli Friedman 
679f18ea84SEli Friedman     if (BlockAddress *BA = dyn_cast<BlockAddress>(V)) {
689f18ea84SEli Friedman       Function *F = BA->getFunction();
699f18ea84SEli Friedman       if (F->isDeclaration())
709f18ea84SEli Friedman         return F;
718d8de422SChris Lattner     }
7273a6bdd9SChris Lattner 
739f18ea84SEli Friedman     for (User::op_iterator i = V->op_begin(), e = V->op_end(); i != e; ++i) {
749f18ea84SEli Friedman       Constant *C = dyn_cast<Constant>(*i);
759f18ea84SEli Friedman       if (C && !isa<GlobalValue>(C) && !Done.count(C))
769f18ea84SEli Friedman         Todo.push_back(C);
779f18ea84SEli Friedman     }
789f18ea84SEli Friedman   }
79e6cb63e4SCraig Topper   return nullptr;
809f18ea84SEli Friedman }
819f18ea84SEli Friedman } // end anonymous namespace
829f18ea84SEli Friedman 
8328b351a5SRafael Espindola std::unique_ptr<Module>
deleteInstructionFromProgram(const Instruction * I,unsigned Simplification)8428b351a5SRafael Espindola BugDriver::deleteInstructionFromProgram(const Instruction *I,
85d1e241a4SRafael Espindola                                         unsigned Simplification) {
86d1e241a4SRafael Espindola   // FIXME, use vmap?
8771867532SRafael Espindola   std::unique_ptr<Module> Clone = CloneModule(*Program);
880eb5ce94SChris Lattner 
89b943b6b0SChris Lattner   const BasicBlock *PBB = I->getParent();
90b943b6b0SChris Lattner   const Function *PF = PBB->getParent();
910eb5ce94SChris Lattner 
92d1e241a4SRafael Espindola   Module::iterator RFI = Clone->begin(); // Get iterator to corresponding fn
938d0a0811SJustin Bogner   std::advance(
948d0a0811SJustin Bogner       RFI, std::distance(PF->getParent()->begin(), Module::const_iterator(PF)));
950eb5ce94SChris Lattner 
960eb5ce94SChris Lattner   Function::iterator RBI = RFI->begin(); // Get iterator to corresponding BB
97b943b6b0SChris Lattner   std::advance(RBI, std::distance(PF->begin(), Function::const_iterator(PBB)));
980eb5ce94SChris Lattner 
990eb5ce94SChris Lattner   BasicBlock::iterator RI = RBI->begin(); // Get iterator to corresponding inst
100b943b6b0SChris Lattner   std::advance(RI, std::distance(PBB->begin(), BasicBlock::const_iterator(I)));
101306d16e0SDuncan P. N. Exon Smith   Instruction *TheInst = &*RI; // Got the corresponding instruction!
1020eb5ce94SChris Lattner 
1030eb5ce94SChris Lattner   // If this instruction produces a value, replace any users with null values
10434a2249fSDan Gohman   if (!TheInst->getType()->isVoidTy())
1055a1acd99SOwen Anderson     TheInst->replaceAllUsesWith(Constant::getNullValue(TheInst->getType()));
1060eb5ce94SChris Lattner 
1070eb5ce94SChris Lattner   // Remove the instruction from the program.
108b943b6b0SChris Lattner   TheInst->getParent()->getInstList().erase(TheInst);
1090eb5ce94SChris Lattner 
11010c0469bSChris Lattner   // Spiff up the output a little bit.
111d1e241a4SRafael Espindola   std::vector<std::string> Passes;
112f3e8f97dSChris Lattner 
113d1e241a4SRafael Espindola   /// Can we get rid of the -disable-* options?
1148d8de422SChris Lattner   if (Simplification > 1 && !NoDCE)
115d1e241a4SRafael Espindola     Passes.push_back("dce");
116d1e2aaefSChris Lattner   if (Simplification && !DisableSimplifyCFG)
117d1e241a4SRafael Espindola     Passes.push_back("simplifycfg"); // Delete dead control flow
11844ffd7c3SChris Lattner 
119d1e241a4SRafael Espindola   Passes.push_back("verify");
120e84e7675SVedant Kumar   std::unique_ptr<Module> New = runPassesOn(Clone.get(), Passes);
121d1e241a4SRafael Espindola   if (!New) {
122d1e241a4SRafael Espindola     errs() << "Instruction removal failed.  Sorry. :(  Please report a bug!\n";
123d1e241a4SRafael Espindola     exit(1);
124d1e241a4SRafael Espindola   }
125d1e241a4SRafael Espindola   return New;
1260eb5ce94SChris Lattner }
127514c02ebSChris Lattner 
12828b351a5SRafael Espindola std::unique_ptr<Module>
performFinalCleanups(std::unique_ptr<Module> M,bool MayModifySemantics)129b71251caSRafael Espindola BugDriver::performFinalCleanups(std::unique_ptr<Module> M,
130b71251caSRafael Espindola                                 bool MayModifySemantics) {
1312b3ab562SChris Lattner   // Make all functions external, so GlobalDCE doesn't delete them...
1322b3ab562SChris Lattner   for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
1332b3ab562SChris Lattner     I->setLinkage(GlobalValue::ExternalLinkage);
1342b3ab562SChris Lattner 
13533e81a82SRafael Espindola   std::vector<std::string> CleanupPasses;
13633e81a82SRafael Espindola   CleanupPasses.push_back("globaldce");
1373f1ad878SChris Lattner 
1383f1ad878SChris Lattner   if (MayModifySemantics)
13933e81a82SRafael Espindola     CleanupPasses.push_back("deadarghaX0r");
1403f1ad878SChris Lattner   else
14133e81a82SRafael Espindola     CleanupPasses.push_back("deadargelim");
1422920100eSChris Lattner 
143b71251caSRafael Espindola   std::unique_ptr<Module> New = runPassesOn(M.get(), CleanupPasses);
144e6cb63e4SCraig Topper   if (!New) {
145d8db3760SDan Gohman     errs() << "Final cleanups failed.  Sorry. :(  Please report a bug!\n";
14628b351a5SRafael Espindola     return nullptr;
1476ce2d033SChris Lattner   }
1486ce2d033SChris Lattner   return New;
149514c02ebSChris Lattner }
150567543f0SChris Lattner 
extractLoop(Module * M)15128b351a5SRafael Espindola std::unique_ptr<Module> BugDriver::extractLoop(Module *M) {
15233e81a82SRafael Espindola   std::vector<std::string> LoopExtractPasses;
15333e81a82SRafael Espindola   LoopExtractPasses.push_back("loop-extract-single");
1543fe96bc9SChris Lattner 
15528b351a5SRafael Espindola   std::unique_ptr<Module> NewM = runPassesOn(M, LoopExtractPasses);
156e6cb63e4SCraig Topper   if (!NewM) {
157ee05152cSDan Gohman     outs() << "*** Loop extraction failed: ";
158f6074ed9SRafael Espindola     EmitProgressBitcode(*M, "loopextraction", true);
159ee05152cSDan Gohman     outs() << "*** Sorry. :(  Please report a bug!\n";
160e6cb63e4SCraig Topper     return nullptr;
1613fe96bc9SChris Lattner   }
1623fe96bc9SChris Lattner 
1633fe96bc9SChris Lattner   // Check to see if we created any new functions.  If not, no loops were
1648cb483b3SChris Lattner   // extracted and we should return null.  Limit the number of loops we extract
1658cb483b3SChris Lattner   // to avoid taking forever.
1668cb483b3SChris Lattner   static unsigned NumExtracted = 32;
167d308797cSChris Lattner   if (M->size() == NewM->size() || --NumExtracted == 0) {
168e6cb63e4SCraig Topper     return nullptr;
169d308797cSChris Lattner   } else {
170d308797cSChris Lattner     assert(M->size() < NewM->size() && "Loop extract removed functions?");
171d308797cSChris Lattner     Module::iterator MI = NewM->begin();
172d308797cSChris Lattner     for (unsigned i = 0, e = M->size(); i != e; ++i)
173d308797cSChris Lattner       ++MI;
1743fe96bc9SChris Lattner   }
1753fe96bc9SChris Lattner 
1763fe96bc9SChris Lattner   return NewM;
1773fe96bc9SChris Lattner }
1783fe96bc9SChris Lattner 
eliminateAliases(GlobalValue * GV)17928ad2b47SHal Finkel static void eliminateAliases(GlobalValue *GV) {
18028ad2b47SHal Finkel   // First, check whether a GlobalAlias references this definition.
18128ad2b47SHal Finkel   // GlobalAlias MAY NOT reference declarations.
18228ad2b47SHal Finkel   for (;;) {
18328ad2b47SHal Finkel     // 1. Find aliases
18428ad2b47SHal Finkel     SmallVector<GlobalAlias *, 1> aliases;
18528ad2b47SHal Finkel     Module *M = GV->getParent();
1868d0a0811SJustin Bogner     for (Module::alias_iterator I = M->alias_begin(), E = M->alias_end();
1878d0a0811SJustin Bogner          I != E; ++I)
18828ad2b47SHal Finkel       if (I->getAliasee()->stripPointerCasts() == GV)
18928ad2b47SHal Finkel         aliases.push_back(&*I);
19028ad2b47SHal Finkel     if (aliases.empty())
19128ad2b47SHal Finkel       break;
19228ad2b47SHal Finkel     // 2. Resolve aliases
19328ad2b47SHal Finkel     for (unsigned i = 0, e = aliases.size(); i < e; ++i) {
19428ad2b47SHal Finkel       aliases[i]->replaceAllUsesWith(aliases[i]->getAliasee());
19528ad2b47SHal Finkel       aliases[i]->eraseFromParent();
19628ad2b47SHal Finkel     }
19728ad2b47SHal Finkel     // 3. Repeat until no more aliases found; there might
19828ad2b47SHal Finkel     // be an alias to an alias...
19928ad2b47SHal Finkel   }
20028ad2b47SHal Finkel }
20128ad2b47SHal Finkel 
20228ad2b47SHal Finkel //
2038d0a0811SJustin Bogner // DeleteGlobalInitializer - "Remove" the global variable by deleting its
2048d0a0811SJustin Bogner // initializer,
20528ad2b47SHal Finkel // making it external.
20628ad2b47SHal Finkel //
DeleteGlobalInitializer(GlobalVariable * GV)20728ad2b47SHal Finkel void llvm::DeleteGlobalInitializer(GlobalVariable *GV) {
20828ad2b47SHal Finkel   eliminateAliases(GV);
20928ad2b47SHal Finkel   GV->setInitializer(nullptr);
21055379ab8SHal Finkel   GV->setComdat(nullptr);
21128ad2b47SHal Finkel }
2123fe96bc9SChris Lattner 
213567543f0SChris Lattner // DeleteFunctionBody - "Remove" the function by deleting all of its basic
214567543f0SChris Lattner // blocks, making it external.
215567543f0SChris Lattner //
DeleteFunctionBody(Function * F)216567543f0SChris Lattner void llvm::DeleteFunctionBody(Function *F) {
21728ad2b47SHal Finkel   eliminateAliases(F);
2182a445cf7SJustin Lebar   // Function declarations can't have comdats.
2192a445cf7SJustin Lebar   F->setComdat(nullptr);
22028ad2b47SHal Finkel 
221567543f0SChris Lattner   // delete the body of the function...
222567543f0SChris Lattner   F->deleteBody();
2235301e7c6SReid Spencer   assert(F->isDeclaration() && "This didn't make the function external!");
224567543f0SChris Lattner }
225567543f0SChris Lattner 
226fdb533a1SChris Lattner /// GetTorInit - Given a list of entries for static ctors/dtors, return them
227fdb533a1SChris Lattner /// as a constant array.
GetTorInit(std::vector<std::pair<Function *,int>> & TorList)228fdb533a1SChris Lattner static Constant *GetTorInit(std::vector<std::pair<Function *, int>> &TorList) {
229fdb533a1SChris Lattner   assert(!TorList.empty() && "Don't create empty tor list!");
230fdb533a1SChris Lattner   std::vector<Constant *> ArrayElts;
231b804a2b7SJay Foad   Type *Int32Ty = Type::getInt32Ty(TorList[0].first->getContext());
232cc19efaaSChris Lattner 
233e38003f8SSerge Guelton   StructType *STy = StructType::get(Int32Ty, TorList[0].first->getType());
234fdb533a1SChris Lattner   for (unsigned i = 0, e = TorList.size(); i != e; ++i) {
2358d0a0811SJustin Bogner     Constant *Elts[] = {ConstantInt::get(Int32Ty, TorList[i].second),
2368d0a0811SJustin Bogner                         TorList[i].first};
237cc19efaaSChris Lattner     ArrayElts.push_back(ConstantStruct::get(STy, Elts));
238fdb533a1SChris Lattner   }
2398d0a0811SJustin Bogner   return ConstantArray::get(
2408d0a0811SJustin Bogner       ArrayType::get(ArrayElts[0]->getType(), ArrayElts.size()), ArrayElts);
241fdb533a1SChris Lattner }
242fdb533a1SChris Lattner 
243fdb533a1SChris Lattner /// SplitStaticCtorDtor - A module was recently split into two parts, M1/M2, and
244fdb533a1SChris Lattner /// M1 has all of the global variables.  If M2 contains any functions that are
245fdb533a1SChris Lattner /// static ctors/dtors, we need to add an llvm.global_[cd]tors global to M2, and
246fdb533a1SChris Lattner /// prune appropriate entries out of M1s list.
SplitStaticCtorDtor(const char * GlobalName,Module * M1,Module * M2,ValueToValueMapTy & VMap)247956ae9dcSDan Gohman static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2,
248229e38f0SRafael Espindola                                 ValueToValueMapTy &VMap) {
249fdb533a1SChris Lattner   GlobalVariable *GV = M1->getNamedGlobal(GlobalName);
2508d0a0811SJustin Bogner   if (!GV || GV->isDeclaration() || GV->hasLocalLinkage() || !GV->use_empty())
2518d0a0811SJustin Bogner     return;
252fdb533a1SChris Lattner 
253fdb533a1SChris Lattner   std::vector<std::pair<Function *, int>> M1Tors, M2Tors;
254fdb533a1SChris Lattner   ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
2558d0a0811SJustin Bogner   if (!InitList)
2568d0a0811SJustin Bogner     return;
257fdb533a1SChris Lattner 
258fdb533a1SChris Lattner   for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
2598d0a0811SJustin Bogner     if (ConstantStruct *CS =
2608d0a0811SJustin Bogner             dyn_cast<ConstantStruct>(InitList->getOperand(i))) {
2618d0a0811SJustin Bogner       if (CS->getNumOperands() != 2)
2628d0a0811SJustin Bogner         return; // Not array of 2-element structs.
263fdb533a1SChris Lattner 
264fdb533a1SChris Lattner       if (CS->getOperand(1)->isNullValue())
265fdb533a1SChris Lattner         break; // Found a null terminator, stop here.
266fdb533a1SChris Lattner 
267e0fc4dfcSReid Spencer       ConstantInt *CI = dyn_cast<ConstantInt>(CS->getOperand(0));
268e0fc4dfcSReid Spencer       int Priority = CI ? CI->getSExtValue() : 0;
269fdb533a1SChris Lattner 
270fdb533a1SChris Lattner       Constant *FP = CS->getOperand(1);
271fdb533a1SChris Lattner       if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
2726c38f0bbSReid Spencer         if (CE->isCast())
273fdb533a1SChris Lattner           FP = CE->getOperand(0);
274fdb533a1SChris Lattner       if (Function *F = dyn_cast<Function>(FP)) {
2755301e7c6SReid Spencer         if (!F->isDeclaration())
276fdb533a1SChris Lattner           M1Tors.push_back(std::make_pair(F, Priority));
277fdb533a1SChris Lattner         else {
278fdb533a1SChris Lattner           // Map to M2's version of the function.
2790dc3c2d3SDevang Patel           F = cast<Function>(VMap[F]);
280fdb533a1SChris Lattner           M2Tors.push_back(std::make_pair(F, Priority));
281fdb533a1SChris Lattner         }
282fdb533a1SChris Lattner       }
283fdb533a1SChris Lattner     }
284fdb533a1SChris Lattner   }
285fdb533a1SChris Lattner 
286fdb533a1SChris Lattner   GV->eraseFromParent();
287fdb533a1SChris Lattner   if (!M1Tors.empty()) {
288fdb533a1SChris Lattner     Constant *M1Init = GetTorInit(M1Tors);
289b17f3294SOwen Anderson     new GlobalVariable(*M1, M1Init->getType(), false,
2908d0a0811SJustin Bogner                        GlobalValue::AppendingLinkage, M1Init, GlobalName);
291fdb533a1SChris Lattner   }
292fdb533a1SChris Lattner 
293fdb533a1SChris Lattner   GV = M2->getNamedGlobal(GlobalName);
294fdb533a1SChris Lattner   assert(GV && "Not a clone of M1?");
295fdb533a1SChris Lattner   assert(GV->use_empty() && "llvm.ctors shouldn't have uses!");
296fdb533a1SChris Lattner 
297fdb533a1SChris Lattner   GV->eraseFromParent();
298fdb533a1SChris Lattner   if (!M2Tors.empty()) {
299fdb533a1SChris Lattner     Constant *M2Init = GetTorInit(M2Tors);
300b17f3294SOwen Anderson     new GlobalVariable(*M2, M2Init->getType(), false,
3018d0a0811SJustin Bogner                        GlobalValue::AppendingLinkage, M2Init, GlobalName);
302fdb533a1SChris Lattner   }
303fdb533a1SChris Lattner }
304fdb533a1SChris Lattner 
30550102c29SRafael Espindola std::unique_ptr<Module>
SplitFunctionsOutOfModule(Module * M,const std::vector<Function * > & F,ValueToValueMapTy & VMap)30650102c29SRafael Espindola llvm::SplitFunctionsOutOfModule(Module *M, const std::vector<Function *> &F,
307229e38f0SRafael Espindola                                 ValueToValueMapTy &VMap) {
308567543f0SChris Lattner   // Make sure functions & globals are all external so that linkage
309567543f0SChris Lattner   // between the two modules will work.
310567543f0SChris Lattner   for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
311567543f0SChris Lattner     I->setLinkage(GlobalValue::ExternalLinkage);
312fdb533a1SChris Lattner   for (Module::global_iterator I = M->global_begin(), E = M->global_end();
313c76bacbfSOwen Anderson        I != E; ++I) {
314d786b51eSDaniel Dunbar     if (I->hasName() && I->getName()[0] == '\01')
315d786b51eSDaniel Dunbar       I->setName(I->getName().substr(1));
316567543f0SChris Lattner     I->setLinkage(GlobalValue::ExternalLinkage);
317c76bacbfSOwen Anderson   }
318567543f0SChris Lattner 
319229e38f0SRafael Espindola   ValueToValueMapTy NewVMap;
32071867532SRafael Espindola   std::unique_ptr<Module> New = CloneModule(*M, NewVMap);
321567543f0SChris Lattner 
3227275b02eSChris Lattner   // Remove the Test functions from the Safe module
323956ae9dcSDan Gohman   std::set<Function *> TestFunctions;
324567543f0SChris Lattner   for (unsigned i = 0, e = F.size(); i != e; ++i) {
3250dc3c2d3SDevang Patel     Function *TNOF = cast<Function>(VMap[F[i]]);
326d34e60caSNicola Zaghen     LLVM_DEBUG(errs() << "Removing function ");
327d34e60caSNicola Zaghen     LLVM_DEBUG(TNOF->printAsOperand(errs(), false));
328d34e60caSNicola Zaghen     LLVM_DEBUG(errs() << "\n");
3290dc3c2d3SDevang Patel     TestFunctions.insert(cast<Function>(NewVMap[TNOF]));
3307275b02eSChris Lattner     DeleteFunctionBody(TNOF); // Function is now external in this module!
331567543f0SChris Lattner   }
332567543f0SChris Lattner 
3337275b02eSChris Lattner   // Remove the Safe functions from the Test module
334306d16e0SDuncan P. N. Exon Smith   for (Function &I : *New)
335306d16e0SDuncan P. N. Exon Smith     if (!TestFunctions.count(&I))
336306d16e0SDuncan P. N. Exon Smith       DeleteFunctionBody(&I);
337fdb533a1SChris Lattner 
3389f18ea84SEli Friedman   // Try to split the global initializers evenly
339306d16e0SDuncan P. N. Exon Smith   for (GlobalVariable &I : M->globals()) {
340306d16e0SDuncan P. N. Exon Smith     GlobalVariable *GV = cast<GlobalVariable>(NewVMap[&I]);
341306d16e0SDuncan P. N. Exon Smith     if (Function *TestFn = globalInitUsesExternalBA(&I)) {
3429f18ea84SEli Friedman       if (Function *SafeFn = globalInitUsesExternalBA(GV)) {
3439f18ea84SEli Friedman         errs() << "*** Error: when reducing functions, encountered "
3449f18ea84SEli Friedman                   "the global '";
345d48cdbf0SChandler Carruth         GV->printAsOperand(errs(), false);
3469f18ea84SEli Friedman         errs() << "' with an initializer that references blockaddresses "
3478d0a0811SJustin Bogner                   "from safe function '"
3488d0a0811SJustin Bogner                << SafeFn->getName() << "' and from test function '"
3498d0a0811SJustin Bogner                << TestFn->getName() << "'.\n";
3509f18ea84SEli Friedman         exit(1);
3519f18ea84SEli Friedman       }
35228ad2b47SHal Finkel       DeleteGlobalInitializer(&I); // Delete the initializer to make it external
3539f18ea84SEli Friedman     } else {
3549f18ea84SEli Friedman       // If we keep it in the safe module, then delete it in the test module
35528ad2b47SHal Finkel       DeleteGlobalInitializer(GV);
3569f18ea84SEli Friedman     }
3579f18ea84SEli Friedman   }
3589f18ea84SEli Friedman 
359fdb533a1SChris Lattner   // Make sure that there is a global ctor/dtor array in both halves of the
360fdb533a1SChris Lattner   // module if they both have static ctor/dtor functions.
36150102c29SRafael Espindola   SplitStaticCtorDtor("llvm.global_ctors", M, New.get(), NewVMap);
36250102c29SRafael Espindola   SplitStaticCtorDtor("llvm.global_dtors", M, New.get(), NewVMap);
363fdb533a1SChris Lattner 
364567543f0SChris Lattner   return New;
365567543f0SChris Lattner }
366a060b10eSChris Lattner 
367a060b10eSChris Lattner //===----------------------------------------------------------------------===//
368a060b10eSChris Lattner // Basic Block Extraction Code
369a060b10eSChris Lattner //===----------------------------------------------------------------------===//
370a060b10eSChris Lattner 
37128b351a5SRafael Espindola std::unique_ptr<Module>
extractMappedBlocksFromModule(const std::vector<BasicBlock * > & BBs,Module * M)37228b351a5SRafael Espindola BugDriver::extractMappedBlocksFromModule(const std::vector<BasicBlock *> &BBs,
373a060b10eSChris Lattner                                          Module *M) {
3748010bf0aSRafael Espindola   auto Temp = sys::fs::TempFile::create(OutputPrefix + "-extractblocks%%%%%%%");
3758010bf0aSRafael Espindola   if (!Temp) {
376ee05152cSDan Gohman     outs() << "*** Basic Block extraction failed!\n";
3778010bf0aSRafael Espindola     errs() << "Error creating temporary file: " << toString(Temp.takeError())
3788010bf0aSRafael Espindola            << "\n";
379f6074ed9SRafael Espindola     EmitProgressBitcode(*M, "basicblockextractfail", true);
380e6cb63e4SCraig Topper     return nullptr;
381c6243020SNick Lewycky   }
3828010bf0aSRafael Espindola   DiscardTemp Discard{*Temp};
383c6243020SNick Lewycky 
384dc40be75SVolkan Keles   // Extract all of the blocks except the ones in BBs.
385dc40be75SVolkan Keles   SmallVector<BasicBlock *, 32> BlocksToExtract;
386dc40be75SVolkan Keles   for (Function &F : *M)
387dc40be75SVolkan Keles     for (BasicBlock &BB : F)
388dc40be75SVolkan Keles       // Check if this block is going to be extracted.
389*902cbcd5SKazu Hirata       if (!llvm::is_contained(BBs, &BB))
390dc40be75SVolkan Keles         BlocksToExtract.push_back(&BB);
391dc40be75SVolkan Keles 
3928010bf0aSRafael Espindola   raw_fd_ostream OS(Temp->FD, /*shouldClose*/ false);
393dc40be75SVolkan Keles   for (BasicBlock *BB : BBs) {
39497879424SChris Lattner     // If the BB doesn't have a name, give it one so we have something to key
39597879424SChris Lattner     // off of.
3968d0a0811SJustin Bogner     if (!BB->hasName())
3978d0a0811SJustin Bogner       BB->setName("tmpbb");
3988010bf0aSRafael Espindola     OS << BB->getParent()->getName() << " " << BB->getName() << "\n";
399c6243020SNick Lewycky   }
4008010bf0aSRafael Espindola   OS.flush();
4018010bf0aSRafael Espindola   if (OS.has_error()) {
4027e936eeeSRafael Espindola     errs() << "Error writing list of blocks to not extract\n";
403f6074ed9SRafael Espindola     EmitProgressBitcode(*M, "basicblockextractfail", true);
4048010bf0aSRafael Espindola     OS.clear_error();
405e6cb63e4SCraig Topper     return nullptr;
4068525fe71SDan Gohman   }
407c6243020SNick Lewycky 
4087e936eeeSRafael Espindola   std::string uniqueFN = "--extract-blocks-file=";
4098010bf0aSRafael Espindola   uniqueFN += Temp->TmpName;
410c6243020SNick Lewycky 
41133e81a82SRafael Espindola   std::vector<std::string> PI;
41233e81a82SRafael Espindola   PI.push_back("extract-blocks");
413f341f801SFlorian Hahn   std::unique_ptr<Module> Ret = runPassesOn(M, PI, {uniqueFN});
414c6243020SNick Lewycky 
415e6cb63e4SCraig Topper   if (!Ret) {
416ee05152cSDan Gohman     outs() << "*** Basic Block extraction failed, please report a bug!\n";
417f6074ed9SRafael Espindola     EmitProgressBitcode(*M, "basicblockextractfail", true);
418af32dfa0SChris Lattner   }
419a060b10eSChris Lattner   return Ret;
420a060b10eSChris Lattner }
421