16bb1caddSDimitry Andric //===- ExtractFunction.cpp - Extract a function from Program --------------===//
26bb1caddSDimitry Andric //
36bb1caddSDimitry Andric //                     The LLVM Compiler Infrastructure
46bb1caddSDimitry Andric //
56bb1caddSDimitry Andric // This file is distributed under the University of Illinois Open Source
66bb1caddSDimitry Andric // License. See LICENSE.TXT for details.
76bb1caddSDimitry Andric //
86bb1caddSDimitry Andric //===----------------------------------------------------------------------===//
96bb1caddSDimitry Andric //
106bb1caddSDimitry Andric // This file implements several methods that are used to extract functions,
116bb1caddSDimitry Andric // loops, or portions of a module from the rest of the module.
126bb1caddSDimitry Andric //
136bb1caddSDimitry Andric //===----------------------------------------------------------------------===//
146bb1caddSDimitry Andric 
156bb1caddSDimitry Andric #include "BugDriver.h"
16139f7f9bSDimitry Andric #include "llvm/IR/Constants.h"
17139f7f9bSDimitry Andric #include "llvm/IR/DataLayout.h"
18139f7f9bSDimitry Andric #include "llvm/IR/DerivedTypes.h"
19139f7f9bSDimitry Andric #include "llvm/IR/LLVMContext.h"
20ff0cc061SDimitry Andric #include "llvm/IR/LegacyPassManager.h"
21139f7f9bSDimitry Andric #include "llvm/IR/Module.h"
2291bc56edSDimitry Andric #include "llvm/IR/Verifier.h"
23139f7f9bSDimitry Andric #include "llvm/Pass.h"
24139f7f9bSDimitry Andric #include "llvm/Support/CommandLine.h"
25139f7f9bSDimitry Andric #include "llvm/Support/Debug.h"
26139f7f9bSDimitry Andric #include "llvm/Support/FileUtilities.h"
27139f7f9bSDimitry Andric #include "llvm/Support/Path.h"
28139f7f9bSDimitry Andric #include "llvm/Support/Signals.h"
29139f7f9bSDimitry Andric #include "llvm/Support/ToolOutputFile.h"
306bb1caddSDimitry Andric #include "llvm/Transforms/IPO.h"
316bb1caddSDimitry Andric #include "llvm/Transforms/Scalar.h"
326bb1caddSDimitry Andric #include "llvm/Transforms/Utils/Cloning.h"
337ae0e2c9SDimitry Andric #include "llvm/Transforms/Utils/CodeExtractor.h"
346bb1caddSDimitry Andric #include <set>
356bb1caddSDimitry Andric using namespace llvm;
366bb1caddSDimitry Andric 
3791bc56edSDimitry Andric #define DEBUG_TYPE "bugpoint"
3891bc56edSDimitry Andric 
396bb1caddSDimitry Andric namespace llvm {
406bb1caddSDimitry Andric bool DisableSimplifyCFG = false;
416bb1caddSDimitry Andric extern cl::opt<std::string> OutputPrefix;
426bb1caddSDimitry Andric } // End llvm namespace
436bb1caddSDimitry Andric 
446bb1caddSDimitry Andric namespace {
45d88c1a5aSDimitry Andric cl::opt<bool> NoDCE("disable-dce",
466bb1caddSDimitry Andric                     cl::desc("Do not use the -dce pass to reduce testcases"));
476bb1caddSDimitry Andric cl::opt<bool, true>
486bb1caddSDimitry Andric     NoSCFG("disable-simplifycfg", cl::location(DisableSimplifyCFG),
496bb1caddSDimitry Andric            cl::desc("Do not use the -simplifycfg pass to reduce testcases"));
50dff0c46cSDimitry Andric 
globalInitUsesExternalBA(GlobalVariable * GV)51dff0c46cSDimitry Andric Function *globalInitUsesExternalBA(GlobalVariable *GV) {
52dff0c46cSDimitry Andric   if (!GV->hasInitializer())
5391bc56edSDimitry Andric     return nullptr;
54dff0c46cSDimitry Andric 
55dff0c46cSDimitry Andric   Constant *I = GV->getInitializer();
56dff0c46cSDimitry Andric 
57dff0c46cSDimitry Andric   // walk the values used by the initializer
58dff0c46cSDimitry Andric   // (and recurse into things like ConstantExpr)
59dff0c46cSDimitry Andric   std::vector<Constant *> Todo;
60dff0c46cSDimitry Andric   std::set<Constant *> Done;
61dff0c46cSDimitry Andric   Todo.push_back(I);
62dff0c46cSDimitry Andric 
63dff0c46cSDimitry Andric   while (!Todo.empty()) {
64dff0c46cSDimitry Andric     Constant *V = Todo.back();
65dff0c46cSDimitry Andric     Todo.pop_back();
66dff0c46cSDimitry Andric     Done.insert(V);
67dff0c46cSDimitry Andric 
68dff0c46cSDimitry Andric     if (BlockAddress *BA = dyn_cast<BlockAddress>(V)) {
69dff0c46cSDimitry Andric       Function *F = BA->getFunction();
70dff0c46cSDimitry Andric       if (F->isDeclaration())
71dff0c46cSDimitry Andric         return F;
726bb1caddSDimitry Andric     }
736bb1caddSDimitry Andric 
74dff0c46cSDimitry Andric     for (User::op_iterator i = V->op_begin(), e = V->op_end(); i != e; ++i) {
75dff0c46cSDimitry Andric       Constant *C = dyn_cast<Constant>(*i);
76dff0c46cSDimitry Andric       if (C && !isa<GlobalValue>(C) && !Done.count(C))
77dff0c46cSDimitry Andric         Todo.push_back(C);
78dff0c46cSDimitry Andric     }
79dff0c46cSDimitry Andric   }
8091bc56edSDimitry Andric   return nullptr;
81dff0c46cSDimitry Andric }
82dff0c46cSDimitry Andric } // end anonymous namespace
83dff0c46cSDimitry Andric 
8439d628a0SDimitry Andric std::unique_ptr<Module>
deleteInstructionFromProgram(const Instruction * I,unsigned Simplification)8539d628a0SDimitry Andric BugDriver::deleteInstructionFromProgram(const Instruction *I,
866bb1caddSDimitry Andric                                         unsigned Simplification) {
876bb1caddSDimitry Andric   // FIXME, use vmap?
88*4ba319b5SDimitry Andric   std::unique_ptr<Module> Clone = CloneModule(*Program);
896bb1caddSDimitry Andric 
906bb1caddSDimitry Andric   const BasicBlock *PBB = I->getParent();
916bb1caddSDimitry Andric   const Function *PF = PBB->getParent();
926bb1caddSDimitry Andric 
936bb1caddSDimitry Andric   Module::iterator RFI = Clone->begin(); // Get iterator to corresponding fn
94d88c1a5aSDimitry Andric   std::advance(
95d88c1a5aSDimitry Andric       RFI, std::distance(PF->getParent()->begin(), Module::const_iterator(PF)));
966bb1caddSDimitry Andric 
976bb1caddSDimitry Andric   Function::iterator RBI = RFI->begin(); // Get iterator to corresponding BB
986bb1caddSDimitry Andric   std::advance(RBI, std::distance(PF->begin(), Function::const_iterator(PBB)));
996bb1caddSDimitry Andric 
1006bb1caddSDimitry Andric   BasicBlock::iterator RI = RBI->begin(); // Get iterator to corresponding inst
1016bb1caddSDimitry Andric   std::advance(RI, std::distance(PBB->begin(), BasicBlock::const_iterator(I)));
1027d523365SDimitry Andric   Instruction *TheInst = &*RI; // Got the corresponding instruction!
1036bb1caddSDimitry Andric 
1046bb1caddSDimitry Andric   // If this instruction produces a value, replace any users with null values
1056bb1caddSDimitry Andric   if (!TheInst->getType()->isVoidTy())
1066bb1caddSDimitry Andric     TheInst->replaceAllUsesWith(Constant::getNullValue(TheInst->getType()));
1076bb1caddSDimitry Andric 
1086bb1caddSDimitry Andric   // Remove the instruction from the program.
1096bb1caddSDimitry Andric   TheInst->getParent()->getInstList().erase(TheInst);
1106bb1caddSDimitry Andric 
1116bb1caddSDimitry Andric   // Spiff up the output a little bit.
1126bb1caddSDimitry Andric   std::vector<std::string> Passes;
1136bb1caddSDimitry Andric 
1146bb1caddSDimitry Andric   /// Can we get rid of the -disable-* options?
1156bb1caddSDimitry Andric   if (Simplification > 1 && !NoDCE)
1166bb1caddSDimitry Andric     Passes.push_back("dce");
1176bb1caddSDimitry Andric   if (Simplification && !DisableSimplifyCFG)
1186bb1caddSDimitry Andric     Passes.push_back("simplifycfg"); // Delete dead control flow
1196bb1caddSDimitry Andric 
1206bb1caddSDimitry Andric   Passes.push_back("verify");
121*4ba319b5SDimitry Andric   std::unique_ptr<Module> New = runPassesOn(Clone.get(), Passes);
1226bb1caddSDimitry Andric   if (!New) {
1236bb1caddSDimitry Andric     errs() << "Instruction removal failed.  Sorry. :(  Please report a bug!\n";
1246bb1caddSDimitry Andric     exit(1);
1256bb1caddSDimitry Andric   }
1266bb1caddSDimitry Andric   return New;
1276bb1caddSDimitry Andric }
1286bb1caddSDimitry Andric 
12939d628a0SDimitry Andric std::unique_ptr<Module>
performFinalCleanups(std::unique_ptr<Module> M,bool MayModifySemantics)130*4ba319b5SDimitry Andric BugDriver::performFinalCleanups(std::unique_ptr<Module> M,
131*4ba319b5SDimitry Andric                                 bool MayModifySemantics) {
1326bb1caddSDimitry Andric   // Make all functions external, so GlobalDCE doesn't delete them...
1336bb1caddSDimitry Andric   for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
1346bb1caddSDimitry Andric     I->setLinkage(GlobalValue::ExternalLinkage);
1356bb1caddSDimitry Andric 
1366bb1caddSDimitry Andric   std::vector<std::string> CleanupPasses;
1376bb1caddSDimitry Andric   CleanupPasses.push_back("globaldce");
1386bb1caddSDimitry Andric 
1396bb1caddSDimitry Andric   if (MayModifySemantics)
1406bb1caddSDimitry Andric     CleanupPasses.push_back("deadarghaX0r");
1416bb1caddSDimitry Andric   else
1426bb1caddSDimitry Andric     CleanupPasses.push_back("deadargelim");
1436bb1caddSDimitry Andric 
144*4ba319b5SDimitry Andric   std::unique_ptr<Module> New = runPassesOn(M.get(), CleanupPasses);
14591bc56edSDimitry Andric   if (!New) {
1466bb1caddSDimitry Andric     errs() << "Final cleanups failed.  Sorry. :(  Please report a bug!\n";
14739d628a0SDimitry Andric     return nullptr;
1486bb1caddSDimitry Andric   }
1496bb1caddSDimitry Andric   return New;
1506bb1caddSDimitry Andric }
1516bb1caddSDimitry Andric 
extractLoop(Module * M)15239d628a0SDimitry Andric std::unique_ptr<Module> BugDriver::extractLoop(Module *M) {
1536bb1caddSDimitry Andric   std::vector<std::string> LoopExtractPasses;
1546bb1caddSDimitry Andric   LoopExtractPasses.push_back("loop-extract-single");
1556bb1caddSDimitry Andric 
15639d628a0SDimitry Andric   std::unique_ptr<Module> NewM = runPassesOn(M, LoopExtractPasses);
15791bc56edSDimitry Andric   if (!NewM) {
1586bb1caddSDimitry Andric     outs() << "*** Loop extraction failed: ";
159*4ba319b5SDimitry Andric     EmitProgressBitcode(*M, "loopextraction", true);
1606bb1caddSDimitry Andric     outs() << "*** Sorry. :(  Please report a bug!\n";
16191bc56edSDimitry Andric     return nullptr;
1626bb1caddSDimitry Andric   }
1636bb1caddSDimitry Andric 
1646bb1caddSDimitry Andric   // Check to see if we created any new functions.  If not, no loops were
1656bb1caddSDimitry Andric   // extracted and we should return null.  Limit the number of loops we extract
1666bb1caddSDimitry Andric   // to avoid taking forever.
1676bb1caddSDimitry Andric   static unsigned NumExtracted = 32;
1686bb1caddSDimitry Andric   if (M->size() == NewM->size() || --NumExtracted == 0) {
16991bc56edSDimitry Andric     return nullptr;
1706bb1caddSDimitry Andric   } else {
1716bb1caddSDimitry Andric     assert(M->size() < NewM->size() && "Loop extract removed functions?");
1726bb1caddSDimitry Andric     Module::iterator MI = NewM->begin();
1736bb1caddSDimitry Andric     for (unsigned i = 0, e = M->size(); i != e; ++i)
1746bb1caddSDimitry Andric       ++MI;
1756bb1caddSDimitry Andric   }
1766bb1caddSDimitry Andric 
1776bb1caddSDimitry Andric   return NewM;
1786bb1caddSDimitry Andric }
1796bb1caddSDimitry Andric 
eliminateAliases(GlobalValue * GV)1807d523365SDimitry Andric static void eliminateAliases(GlobalValue *GV) {
1817d523365SDimitry Andric   // First, check whether a GlobalAlias references this definition.
1827d523365SDimitry Andric   // GlobalAlias MAY NOT reference declarations.
1837d523365SDimitry Andric   for (;;) {
1847d523365SDimitry Andric     // 1. Find aliases
1857d523365SDimitry Andric     SmallVector<GlobalAlias *, 1> aliases;
1867d523365SDimitry Andric     Module *M = GV->getParent();
187d88c1a5aSDimitry Andric     for (Module::alias_iterator I = M->alias_begin(), E = M->alias_end();
188d88c1a5aSDimitry Andric          I != E; ++I)
1897d523365SDimitry Andric       if (I->getAliasee()->stripPointerCasts() == GV)
1907d523365SDimitry Andric         aliases.push_back(&*I);
1917d523365SDimitry Andric     if (aliases.empty())
1927d523365SDimitry Andric       break;
1937d523365SDimitry Andric     // 2. Resolve aliases
1947d523365SDimitry Andric     for (unsigned i = 0, e = aliases.size(); i < e; ++i) {
1957d523365SDimitry Andric       aliases[i]->replaceAllUsesWith(aliases[i]->getAliasee());
1967d523365SDimitry Andric       aliases[i]->eraseFromParent();
1977d523365SDimitry Andric     }
1987d523365SDimitry Andric     // 3. Repeat until no more aliases found; there might
1997d523365SDimitry Andric     // be an alias to an alias...
2007d523365SDimitry Andric   }
2017d523365SDimitry Andric }
2027d523365SDimitry Andric 
2037d523365SDimitry Andric //
204d88c1a5aSDimitry Andric // DeleteGlobalInitializer - "Remove" the global variable by deleting its
205d88c1a5aSDimitry Andric // initializer,
2067d523365SDimitry Andric // making it external.
2077d523365SDimitry Andric //
DeleteGlobalInitializer(GlobalVariable * GV)2087d523365SDimitry Andric void llvm::DeleteGlobalInitializer(GlobalVariable *GV) {
2097d523365SDimitry Andric   eliminateAliases(GV);
2107d523365SDimitry Andric   GV->setInitializer(nullptr);
2117a7e6055SDimitry Andric   GV->setComdat(nullptr);
2127d523365SDimitry Andric }
2136bb1caddSDimitry Andric 
2146bb1caddSDimitry Andric // DeleteFunctionBody - "Remove" the function by deleting all of its basic
2156bb1caddSDimitry Andric // blocks, making it external.
2166bb1caddSDimitry Andric //
DeleteFunctionBody(Function * F)2176bb1caddSDimitry Andric void llvm::DeleteFunctionBody(Function *F) {
2187d523365SDimitry Andric   eliminateAliases(F);
2193ca95b02SDimitry Andric   // Function declarations can't have comdats.
2203ca95b02SDimitry Andric   F->setComdat(nullptr);
2217d523365SDimitry Andric 
2226bb1caddSDimitry Andric   // delete the body of the function...
2236bb1caddSDimitry Andric   F->deleteBody();
2246bb1caddSDimitry Andric   assert(F->isDeclaration() && "This didn't make the function external!");
2256bb1caddSDimitry Andric }
2266bb1caddSDimitry Andric 
2276bb1caddSDimitry Andric /// GetTorInit - Given a list of entries for static ctors/dtors, return them
2286bb1caddSDimitry Andric /// as a constant array.
GetTorInit(std::vector<std::pair<Function *,int>> & TorList)2296bb1caddSDimitry Andric static Constant *GetTorInit(std::vector<std::pair<Function *, int>> &TorList) {
2306bb1caddSDimitry Andric   assert(!TorList.empty() && "Don't create empty tor list!");
2316bb1caddSDimitry Andric   std::vector<Constant *> ArrayElts;
2326bb1caddSDimitry Andric   Type *Int32Ty = Type::getInt32Ty(TorList[0].first->getContext());
2336bb1caddSDimitry Andric 
2345517e702SDimitry Andric   StructType *STy = StructType::get(Int32Ty, TorList[0].first->getType());
2356bb1caddSDimitry Andric   for (unsigned i = 0, e = TorList.size(); i != e; ++i) {
236d88c1a5aSDimitry Andric     Constant *Elts[] = {ConstantInt::get(Int32Ty, TorList[i].second),
237d88c1a5aSDimitry Andric                         TorList[i].first};
2386bb1caddSDimitry Andric     ArrayElts.push_back(ConstantStruct::get(STy, Elts));
2396bb1caddSDimitry Andric   }
240d88c1a5aSDimitry Andric   return ConstantArray::get(
241d88c1a5aSDimitry Andric       ArrayType::get(ArrayElts[0]->getType(), ArrayElts.size()), ArrayElts);
2426bb1caddSDimitry Andric }
2436bb1caddSDimitry Andric 
2446bb1caddSDimitry Andric /// SplitStaticCtorDtor - A module was recently split into two parts, M1/M2, and
2456bb1caddSDimitry Andric /// M1 has all of the global variables.  If M2 contains any functions that are
2466bb1caddSDimitry Andric /// static ctors/dtors, we need to add an llvm.global_[cd]tors global to M2, and
2476bb1caddSDimitry Andric /// prune appropriate entries out of M1s list.
SplitStaticCtorDtor(const char * GlobalName,Module * M1,Module * M2,ValueToValueMapTy & VMap)2486bb1caddSDimitry Andric static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2,
2496bb1caddSDimitry Andric                                 ValueToValueMapTy &VMap) {
2506bb1caddSDimitry Andric   GlobalVariable *GV = M1->getNamedGlobal(GlobalName);
251d88c1a5aSDimitry Andric   if (!GV || GV->isDeclaration() || GV->hasLocalLinkage() || !GV->use_empty())
252d88c1a5aSDimitry Andric     return;
2536bb1caddSDimitry Andric 
2546bb1caddSDimitry Andric   std::vector<std::pair<Function *, int>> M1Tors, M2Tors;
2556bb1caddSDimitry Andric   ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
256d88c1a5aSDimitry Andric   if (!InitList)
257d88c1a5aSDimitry Andric     return;
2586bb1caddSDimitry Andric 
2596bb1caddSDimitry Andric   for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
260d88c1a5aSDimitry Andric     if (ConstantStruct *CS =
261d88c1a5aSDimitry Andric             dyn_cast<ConstantStruct>(InitList->getOperand(i))) {
262d88c1a5aSDimitry Andric       if (CS->getNumOperands() != 2)
263d88c1a5aSDimitry Andric         return; // Not array of 2-element structs.
2646bb1caddSDimitry Andric 
2656bb1caddSDimitry Andric       if (CS->getOperand(1)->isNullValue())
2666bb1caddSDimitry Andric         break; // Found a null terminator, stop here.
2676bb1caddSDimitry Andric 
2686bb1caddSDimitry Andric       ConstantInt *CI = dyn_cast<ConstantInt>(CS->getOperand(0));
2696bb1caddSDimitry Andric       int Priority = CI ? CI->getSExtValue() : 0;
2706bb1caddSDimitry Andric 
2716bb1caddSDimitry Andric       Constant *FP = CS->getOperand(1);
2726bb1caddSDimitry Andric       if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
2736bb1caddSDimitry Andric         if (CE->isCast())
2746bb1caddSDimitry Andric           FP = CE->getOperand(0);
2756bb1caddSDimitry Andric       if (Function *F = dyn_cast<Function>(FP)) {
2766bb1caddSDimitry Andric         if (!F->isDeclaration())
2776bb1caddSDimitry Andric           M1Tors.push_back(std::make_pair(F, Priority));
2786bb1caddSDimitry Andric         else {
2796bb1caddSDimitry Andric           // Map to M2's version of the function.
2806bb1caddSDimitry Andric           F = cast<Function>(VMap[F]);
2816bb1caddSDimitry Andric           M2Tors.push_back(std::make_pair(F, Priority));
2826bb1caddSDimitry Andric         }
2836bb1caddSDimitry Andric       }
2846bb1caddSDimitry Andric     }
2856bb1caddSDimitry Andric   }
2866bb1caddSDimitry Andric 
2876bb1caddSDimitry Andric   GV->eraseFromParent();
2886bb1caddSDimitry Andric   if (!M1Tors.empty()) {
2896bb1caddSDimitry Andric     Constant *M1Init = GetTorInit(M1Tors);
2906bb1caddSDimitry Andric     new GlobalVariable(*M1, M1Init->getType(), false,
291d88c1a5aSDimitry Andric                        GlobalValue::AppendingLinkage, M1Init, GlobalName);
2926bb1caddSDimitry Andric   }
2936bb1caddSDimitry Andric 
2946bb1caddSDimitry Andric   GV = M2->getNamedGlobal(GlobalName);
2956bb1caddSDimitry Andric   assert(GV && "Not a clone of M1?");
2966bb1caddSDimitry Andric   assert(GV->use_empty() && "llvm.ctors shouldn't have uses!");
2976bb1caddSDimitry Andric 
2986bb1caddSDimitry Andric   GV->eraseFromParent();
2996bb1caddSDimitry Andric   if (!M2Tors.empty()) {
3006bb1caddSDimitry Andric     Constant *M2Init = GetTorInit(M2Tors);
3016bb1caddSDimitry Andric     new GlobalVariable(*M2, M2Init->getType(), false,
302d88c1a5aSDimitry Andric                        GlobalValue::AppendingLinkage, M2Init, GlobalName);
3036bb1caddSDimitry Andric   }
3046bb1caddSDimitry Andric }
3056bb1caddSDimitry Andric 
3067d523365SDimitry Andric std::unique_ptr<Module>
SplitFunctionsOutOfModule(Module * M,const std::vector<Function * > & F,ValueToValueMapTy & VMap)3077d523365SDimitry Andric llvm::SplitFunctionsOutOfModule(Module *M, const std::vector<Function *> &F,
3086bb1caddSDimitry Andric                                 ValueToValueMapTy &VMap) {
3096bb1caddSDimitry Andric   // Make sure functions & globals are all external so that linkage
3106bb1caddSDimitry Andric   // between the two modules will work.
3116bb1caddSDimitry Andric   for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
3126bb1caddSDimitry Andric     I->setLinkage(GlobalValue::ExternalLinkage);
3136bb1caddSDimitry Andric   for (Module::global_iterator I = M->global_begin(), E = M->global_end();
3146bb1caddSDimitry Andric        I != E; ++I) {
3156bb1caddSDimitry Andric     if (I->hasName() && I->getName()[0] == '\01')
3166bb1caddSDimitry Andric       I->setName(I->getName().substr(1));
3176bb1caddSDimitry Andric     I->setLinkage(GlobalValue::ExternalLinkage);
3186bb1caddSDimitry Andric   }
3196bb1caddSDimitry Andric 
3206bb1caddSDimitry Andric   ValueToValueMapTy NewVMap;
321*4ba319b5SDimitry Andric   std::unique_ptr<Module> New = CloneModule(*M, NewVMap);
3226bb1caddSDimitry Andric 
3236bb1caddSDimitry Andric   // Remove the Test functions from the Safe module
3246bb1caddSDimitry Andric   std::set<Function *> TestFunctions;
3256bb1caddSDimitry Andric   for (unsigned i = 0, e = F.size(); i != e; ++i) {
3266bb1caddSDimitry Andric     Function *TNOF = cast<Function>(VMap[F[i]]);
327*4ba319b5SDimitry Andric     LLVM_DEBUG(errs() << "Removing function ");
328*4ba319b5SDimitry Andric     LLVM_DEBUG(TNOF->printAsOperand(errs(), false));
329*4ba319b5SDimitry Andric     LLVM_DEBUG(errs() << "\n");
3306bb1caddSDimitry Andric     TestFunctions.insert(cast<Function>(NewVMap[TNOF]));
3316bb1caddSDimitry Andric     DeleteFunctionBody(TNOF); // Function is now external in this module!
3326bb1caddSDimitry Andric   }
3336bb1caddSDimitry Andric 
3346bb1caddSDimitry Andric   // Remove the Safe functions from the Test module
3357d523365SDimitry Andric   for (Function &I : *New)
3367d523365SDimitry Andric     if (!TestFunctions.count(&I))
3377d523365SDimitry Andric       DeleteFunctionBody(&I);
3386bb1caddSDimitry Andric 
339dff0c46cSDimitry Andric   // Try to split the global initializers evenly
3407d523365SDimitry Andric   for (GlobalVariable &I : M->globals()) {
3417d523365SDimitry Andric     GlobalVariable *GV = cast<GlobalVariable>(NewVMap[&I]);
3427d523365SDimitry Andric     if (Function *TestFn = globalInitUsesExternalBA(&I)) {
343dff0c46cSDimitry Andric       if (Function *SafeFn = globalInitUsesExternalBA(GV)) {
344dff0c46cSDimitry Andric         errs() << "*** Error: when reducing functions, encountered "
345dff0c46cSDimitry Andric                   "the global '";
34691bc56edSDimitry Andric         GV->printAsOperand(errs(), false);
347dff0c46cSDimitry Andric         errs() << "' with an initializer that references blockaddresses "
348d88c1a5aSDimitry Andric                   "from safe function '"
349d88c1a5aSDimitry Andric                << SafeFn->getName() << "' and from test function '"
350d88c1a5aSDimitry Andric                << TestFn->getName() << "'.\n";
351dff0c46cSDimitry Andric         exit(1);
352dff0c46cSDimitry Andric       }
3537d523365SDimitry Andric       DeleteGlobalInitializer(&I); // Delete the initializer to make it external
354dff0c46cSDimitry Andric     } else {
355dff0c46cSDimitry Andric       // If we keep it in the safe module, then delete it in the test module
3567d523365SDimitry Andric       DeleteGlobalInitializer(GV);
357dff0c46cSDimitry Andric     }
358dff0c46cSDimitry Andric   }
359dff0c46cSDimitry Andric 
3606bb1caddSDimitry Andric   // Make sure that there is a global ctor/dtor array in both halves of the
3616bb1caddSDimitry Andric   // module if they both have static ctor/dtor functions.
3627d523365SDimitry Andric   SplitStaticCtorDtor("llvm.global_ctors", M, New.get(), NewVMap);
3637d523365SDimitry Andric   SplitStaticCtorDtor("llvm.global_dtors", M, New.get(), NewVMap);
3646bb1caddSDimitry Andric 
3656bb1caddSDimitry Andric   return New;
3666bb1caddSDimitry Andric }
3676bb1caddSDimitry Andric 
3686bb1caddSDimitry Andric //===----------------------------------------------------------------------===//
3696bb1caddSDimitry Andric // Basic Block Extraction Code
3706bb1caddSDimitry Andric //===----------------------------------------------------------------------===//
3716bb1caddSDimitry Andric 
37239d628a0SDimitry Andric std::unique_ptr<Module>
extractMappedBlocksFromModule(const std::vector<BasicBlock * > & BBs,Module * M)37339d628a0SDimitry Andric BugDriver::extractMappedBlocksFromModule(const std::vector<BasicBlock *> &BBs,
3746bb1caddSDimitry Andric                                          Module *M) {
3752cab237bSDimitry Andric   auto Temp = sys::fs::TempFile::create(OutputPrefix + "-extractblocks%%%%%%%");
3762cab237bSDimitry Andric   if (!Temp) {
3776bb1caddSDimitry Andric     outs() << "*** Basic Block extraction failed!\n";
3782cab237bSDimitry Andric     errs() << "Error creating temporary file: " << toString(Temp.takeError())
3792cab237bSDimitry Andric            << "\n";
380*4ba319b5SDimitry Andric     EmitProgressBitcode(*M, "basicblockextractfail", true);
38191bc56edSDimitry Andric     return nullptr;
3826bb1caddSDimitry Andric   }
3832cab237bSDimitry Andric   DiscardTemp Discard{*Temp};
3846bb1caddSDimitry Andric 
385*4ba319b5SDimitry Andric   // Extract all of the blocks except the ones in BBs.
386*4ba319b5SDimitry Andric   SmallVector<BasicBlock *, 32> BlocksToExtract;
387*4ba319b5SDimitry Andric   for (Function &F : *M)
388*4ba319b5SDimitry Andric     for (BasicBlock &BB : F)
389*4ba319b5SDimitry Andric       // Check if this block is going to be extracted.
390*4ba319b5SDimitry Andric       if (std::find(BBs.begin(), BBs.end(), &BB) == BBs.end())
391*4ba319b5SDimitry Andric         BlocksToExtract.push_back(&BB);
392*4ba319b5SDimitry Andric 
3932cab237bSDimitry Andric   raw_fd_ostream OS(Temp->FD, /*shouldClose*/ false);
394*4ba319b5SDimitry Andric   for (BasicBlock *BB : BBs) {
3956bb1caddSDimitry Andric     // If the BB doesn't have a name, give it one so we have something to key
3966bb1caddSDimitry Andric     // off of.
397d88c1a5aSDimitry Andric     if (!BB->hasName())
398d88c1a5aSDimitry Andric       BB->setName("tmpbb");
3992cab237bSDimitry Andric     OS << BB->getParent()->getName() << " " << BB->getName() << "\n";
4006bb1caddSDimitry Andric   }
4012cab237bSDimitry Andric   OS.flush();
4022cab237bSDimitry Andric   if (OS.has_error()) {
403f785676fSDimitry Andric     errs() << "Error writing list of blocks to not extract\n";
404*4ba319b5SDimitry Andric     EmitProgressBitcode(*M, "basicblockextractfail", true);
4052cab237bSDimitry Andric     OS.clear_error();
40691bc56edSDimitry Andric     return nullptr;
4076bb1caddSDimitry Andric   }
4086bb1caddSDimitry Andric 
409f785676fSDimitry Andric   std::string uniqueFN = "--extract-blocks-file=";
4102cab237bSDimitry Andric   uniqueFN += Temp->TmpName;
4116bb1caddSDimitry Andric   const char *ExtraArg = uniqueFN.c_str();
4126bb1caddSDimitry Andric 
4136bb1caddSDimitry Andric   std::vector<std::string> PI;
4146bb1caddSDimitry Andric   PI.push_back("extract-blocks");
4153ca95b02SDimitry Andric   std::unique_ptr<Module> Ret = runPassesOn(M, PI, 1, &ExtraArg);
4166bb1caddSDimitry Andric 
41791bc56edSDimitry Andric   if (!Ret) {
4186bb1caddSDimitry Andric     outs() << "*** Basic Block extraction failed, please report a bug!\n";
419*4ba319b5SDimitry Andric     EmitProgressBitcode(*M, "basicblockextractfail", true);
4206bb1caddSDimitry Andric   }
4216bb1caddSDimitry Andric   return Ret;
4226bb1caddSDimitry Andric }
423