10b57cec5SDimitry Andric //===- ExtractFunction.cpp - Extract a function from Program --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements several methods that are used to extract functions,
100b57cec5SDimitry Andric // loops, or portions of a module from the rest of the module.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "BugDriver.h"
150b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
160b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
170b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
180b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
190b57cec5SDimitry Andric #include "llvm/IR/LegacyPassManager.h"
200b57cec5SDimitry Andric #include "llvm/IR/Module.h"
210b57cec5SDimitry Andric #include "llvm/IR/Verifier.h"
220b57cec5SDimitry Andric #include "llvm/Pass.h"
230b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
240b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
250b57cec5SDimitry Andric #include "llvm/Support/FileUtilities.h"
260b57cec5SDimitry Andric #include "llvm/Support/Path.h"
270b57cec5SDimitry Andric #include "llvm/Support/Signals.h"
280b57cec5SDimitry Andric #include "llvm/Support/ToolOutputFile.h"
290b57cec5SDimitry Andric #include "llvm/Transforms/IPO.h"
300b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h"
310b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h"
320b57cec5SDimitry Andric #include "llvm/Transforms/Utils/CodeExtractor.h"
330b57cec5SDimitry Andric #include <set>
340b57cec5SDimitry Andric using namespace llvm;
350b57cec5SDimitry Andric
360b57cec5SDimitry Andric #define DEBUG_TYPE "bugpoint"
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric namespace llvm {
390b57cec5SDimitry Andric bool DisableSimplifyCFG = false;
400b57cec5SDimitry Andric extern cl::opt<std::string> OutputPrefix;
410b57cec5SDimitry Andric } // End llvm namespace
420b57cec5SDimitry Andric
430b57cec5SDimitry Andric namespace {
440b57cec5SDimitry Andric cl::opt<bool> NoDCE("disable-dce",
450b57cec5SDimitry Andric cl::desc("Do not use the -dce pass to reduce testcases"));
460b57cec5SDimitry Andric cl::opt<bool, true>
470b57cec5SDimitry Andric NoSCFG("disable-simplifycfg", cl::location(DisableSimplifyCFG),
480b57cec5SDimitry Andric cl::desc("Do not use the -simplifycfg pass to reduce testcases"));
490b57cec5SDimitry Andric
globalInitUsesExternalBA(GlobalVariable * GV)500b57cec5SDimitry Andric Function *globalInitUsesExternalBA(GlobalVariable *GV) {
510b57cec5SDimitry Andric if (!GV->hasInitializer())
520b57cec5SDimitry Andric return nullptr;
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric Constant *I = GV->getInitializer();
550b57cec5SDimitry Andric
560b57cec5SDimitry Andric // walk the values used by the initializer
570b57cec5SDimitry Andric // (and recurse into things like ConstantExpr)
580b57cec5SDimitry Andric std::vector<Constant *> Todo;
590b57cec5SDimitry Andric std::set<Constant *> Done;
600b57cec5SDimitry Andric Todo.push_back(I);
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric while (!Todo.empty()) {
630b57cec5SDimitry Andric Constant *V = Todo.back();
640b57cec5SDimitry Andric Todo.pop_back();
650b57cec5SDimitry Andric Done.insert(V);
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric if (BlockAddress *BA = dyn_cast<BlockAddress>(V)) {
680b57cec5SDimitry Andric Function *F = BA->getFunction();
690b57cec5SDimitry Andric if (F->isDeclaration())
700b57cec5SDimitry Andric return F;
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric
730b57cec5SDimitry Andric for (User::op_iterator i = V->op_begin(), e = V->op_end(); i != e; ++i) {
740b57cec5SDimitry Andric Constant *C = dyn_cast<Constant>(*i);
750b57cec5SDimitry Andric if (C && !isa<GlobalValue>(C) && !Done.count(C))
760b57cec5SDimitry Andric Todo.push_back(C);
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric return nullptr;
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric } // end anonymous namespace
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric std::unique_ptr<Module>
deleteInstructionFromProgram(const Instruction * I,unsigned Simplification)840b57cec5SDimitry Andric BugDriver::deleteInstructionFromProgram(const Instruction *I,
850b57cec5SDimitry Andric unsigned Simplification) {
860b57cec5SDimitry Andric // FIXME, use vmap?
870b57cec5SDimitry Andric std::unique_ptr<Module> Clone = CloneModule(*Program);
880b57cec5SDimitry Andric
890b57cec5SDimitry Andric const BasicBlock *PBB = I->getParent();
900b57cec5SDimitry Andric const Function *PF = PBB->getParent();
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric Module::iterator RFI = Clone->begin(); // Get iterator to corresponding fn
930b57cec5SDimitry Andric std::advance(
940b57cec5SDimitry Andric RFI, std::distance(PF->getParent()->begin(), Module::const_iterator(PF)));
950b57cec5SDimitry Andric
960b57cec5SDimitry Andric Function::iterator RBI = RFI->begin(); // Get iterator to corresponding BB
970b57cec5SDimitry Andric std::advance(RBI, std::distance(PF->begin(), Function::const_iterator(PBB)));
980b57cec5SDimitry Andric
990b57cec5SDimitry Andric BasicBlock::iterator RI = RBI->begin(); // Get iterator to corresponding inst
1000b57cec5SDimitry Andric std::advance(RI, std::distance(PBB->begin(), BasicBlock::const_iterator(I)));
1010b57cec5SDimitry Andric Instruction *TheInst = &*RI; // Got the corresponding instruction!
1020b57cec5SDimitry Andric
1030b57cec5SDimitry Andric // If this instruction produces a value, replace any users with null values
1040b57cec5SDimitry Andric if (!TheInst->getType()->isVoidTy())
1050b57cec5SDimitry Andric TheInst->replaceAllUsesWith(Constant::getNullValue(TheInst->getType()));
1060b57cec5SDimitry Andric
1070b57cec5SDimitry Andric // Remove the instruction from the program.
108*bdd1243dSDimitry Andric TheInst->eraseFromParent();
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andric // Spiff up the output a little bit.
1110b57cec5SDimitry Andric std::vector<std::string> Passes;
1120b57cec5SDimitry Andric
1130b57cec5SDimitry Andric /// Can we get rid of the -disable-* options?
1140b57cec5SDimitry Andric if (Simplification > 1 && !NoDCE)
1150b57cec5SDimitry Andric Passes.push_back("dce");
1160b57cec5SDimitry Andric if (Simplification && !DisableSimplifyCFG)
1170b57cec5SDimitry Andric Passes.push_back("simplifycfg"); // Delete dead control flow
1180b57cec5SDimitry Andric
1190b57cec5SDimitry Andric Passes.push_back("verify");
1200b57cec5SDimitry Andric std::unique_ptr<Module> New = runPassesOn(Clone.get(), Passes);
1210b57cec5SDimitry Andric if (!New) {
1220b57cec5SDimitry Andric errs() << "Instruction removal failed. Sorry. :( Please report a bug!\n";
1230b57cec5SDimitry Andric exit(1);
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric return New;
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric
1280b57cec5SDimitry Andric std::unique_ptr<Module>
performFinalCleanups(std::unique_ptr<Module> M,bool MayModifySemantics)1290b57cec5SDimitry Andric BugDriver::performFinalCleanups(std::unique_ptr<Module> M,
1300b57cec5SDimitry Andric bool MayModifySemantics) {
1310b57cec5SDimitry Andric // Make all functions external, so GlobalDCE doesn't delete them...
1320b57cec5SDimitry Andric for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
1330b57cec5SDimitry Andric I->setLinkage(GlobalValue::ExternalLinkage);
1340b57cec5SDimitry Andric
1350b57cec5SDimitry Andric std::vector<std::string> CleanupPasses;
1360b57cec5SDimitry Andric
1370b57cec5SDimitry Andric if (MayModifySemantics)
1380b57cec5SDimitry Andric CleanupPasses.push_back("deadarghaX0r");
1390b57cec5SDimitry Andric else
1400b57cec5SDimitry Andric CleanupPasses.push_back("deadargelim");
1410b57cec5SDimitry Andric
1420b57cec5SDimitry Andric std::unique_ptr<Module> New = runPassesOn(M.get(), CleanupPasses);
1430b57cec5SDimitry Andric if (!New) {
1440b57cec5SDimitry Andric errs() << "Final cleanups failed. Sorry. :( Please report a bug!\n";
1450b57cec5SDimitry Andric return nullptr;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric return New;
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric
extractLoop(Module * M)1500b57cec5SDimitry Andric std::unique_ptr<Module> BugDriver::extractLoop(Module *M) {
1510b57cec5SDimitry Andric std::vector<std::string> LoopExtractPasses;
1520b57cec5SDimitry Andric LoopExtractPasses.push_back("loop-extract-single");
1530b57cec5SDimitry Andric
1540b57cec5SDimitry Andric std::unique_ptr<Module> NewM = runPassesOn(M, LoopExtractPasses);
1550b57cec5SDimitry Andric if (!NewM) {
1560b57cec5SDimitry Andric outs() << "*** Loop extraction failed: ";
1570b57cec5SDimitry Andric EmitProgressBitcode(*M, "loopextraction", true);
1580b57cec5SDimitry Andric outs() << "*** Sorry. :( Please report a bug!\n";
1590b57cec5SDimitry Andric return nullptr;
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andric // Check to see if we created any new functions. If not, no loops were
1630b57cec5SDimitry Andric // extracted and we should return null. Limit the number of loops we extract
1640b57cec5SDimitry Andric // to avoid taking forever.
1650b57cec5SDimitry Andric static unsigned NumExtracted = 32;
1660b57cec5SDimitry Andric if (M->size() == NewM->size() || --NumExtracted == 0) {
1670b57cec5SDimitry Andric return nullptr;
1680b57cec5SDimitry Andric } else {
1690b57cec5SDimitry Andric assert(M->size() < NewM->size() && "Loop extract removed functions?");
1700b57cec5SDimitry Andric Module::iterator MI = NewM->begin();
1710b57cec5SDimitry Andric for (unsigned i = 0, e = M->size(); i != e; ++i)
1720b57cec5SDimitry Andric ++MI;
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric
1750b57cec5SDimitry Andric return NewM;
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric
eliminateAliases(GlobalValue * GV)1780b57cec5SDimitry Andric static void eliminateAliases(GlobalValue *GV) {
1790b57cec5SDimitry Andric // First, check whether a GlobalAlias references this definition.
1800b57cec5SDimitry Andric // GlobalAlias MAY NOT reference declarations.
1810b57cec5SDimitry Andric for (;;) {
1820b57cec5SDimitry Andric // 1. Find aliases
1830b57cec5SDimitry Andric SmallVector<GlobalAlias *, 1> aliases;
1840b57cec5SDimitry Andric Module *M = GV->getParent();
1850b57cec5SDimitry Andric for (Module::alias_iterator I = M->alias_begin(), E = M->alias_end();
1860b57cec5SDimitry Andric I != E; ++I)
1870b57cec5SDimitry Andric if (I->getAliasee()->stripPointerCasts() == GV)
1880b57cec5SDimitry Andric aliases.push_back(&*I);
1890b57cec5SDimitry Andric if (aliases.empty())
1900b57cec5SDimitry Andric break;
1910b57cec5SDimitry Andric // 2. Resolve aliases
1920b57cec5SDimitry Andric for (unsigned i = 0, e = aliases.size(); i < e; ++i) {
1930b57cec5SDimitry Andric aliases[i]->replaceAllUsesWith(aliases[i]->getAliasee());
1940b57cec5SDimitry Andric aliases[i]->eraseFromParent();
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric // 3. Repeat until no more aliases found; there might
1970b57cec5SDimitry Andric // be an alias to an alias...
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric
2010b57cec5SDimitry Andric //
2020b57cec5SDimitry Andric // DeleteGlobalInitializer - "Remove" the global variable by deleting its
2030b57cec5SDimitry Andric // initializer,
2040b57cec5SDimitry Andric // making it external.
2050b57cec5SDimitry Andric //
DeleteGlobalInitializer(GlobalVariable * GV)2060b57cec5SDimitry Andric void llvm::DeleteGlobalInitializer(GlobalVariable *GV) {
2070b57cec5SDimitry Andric eliminateAliases(GV);
2080b57cec5SDimitry Andric GV->setInitializer(nullptr);
2090b57cec5SDimitry Andric GV->setComdat(nullptr);
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric
2120b57cec5SDimitry Andric // DeleteFunctionBody - "Remove" the function by deleting all of its basic
2130b57cec5SDimitry Andric // blocks, making it external.
2140b57cec5SDimitry Andric //
DeleteFunctionBody(Function * F)2150b57cec5SDimitry Andric void llvm::DeleteFunctionBody(Function *F) {
2160b57cec5SDimitry Andric eliminateAliases(F);
2170b57cec5SDimitry Andric // Function declarations can't have comdats.
2180b57cec5SDimitry Andric F->setComdat(nullptr);
2190b57cec5SDimitry Andric
2200b57cec5SDimitry Andric // delete the body of the function...
2210b57cec5SDimitry Andric F->deleteBody();
2220b57cec5SDimitry Andric assert(F->isDeclaration() && "This didn't make the function external!");
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric
2250b57cec5SDimitry Andric /// GetTorInit - Given a list of entries for static ctors/dtors, return them
2260b57cec5SDimitry Andric /// as a constant array.
GetTorInit(std::vector<std::pair<Function *,int>> & TorList)2270b57cec5SDimitry Andric static Constant *GetTorInit(std::vector<std::pair<Function *, int>> &TorList) {
2280b57cec5SDimitry Andric assert(!TorList.empty() && "Don't create empty tor list!");
2290b57cec5SDimitry Andric std::vector<Constant *> ArrayElts;
2300b57cec5SDimitry Andric Type *Int32Ty = Type::getInt32Ty(TorList[0].first->getContext());
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric StructType *STy = StructType::get(Int32Ty, TorList[0].first->getType());
2330b57cec5SDimitry Andric for (unsigned i = 0, e = TorList.size(); i != e; ++i) {
2340b57cec5SDimitry Andric Constant *Elts[] = {ConstantInt::get(Int32Ty, TorList[i].second),
2350b57cec5SDimitry Andric TorList[i].first};
2360b57cec5SDimitry Andric ArrayElts.push_back(ConstantStruct::get(STy, Elts));
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric return ConstantArray::get(
2390b57cec5SDimitry Andric ArrayType::get(ArrayElts[0]->getType(), ArrayElts.size()), ArrayElts);
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric /// SplitStaticCtorDtor - A module was recently split into two parts, M1/M2, and
2430b57cec5SDimitry Andric /// M1 has all of the global variables. If M2 contains any functions that are
2440b57cec5SDimitry Andric /// static ctors/dtors, we need to add an llvm.global_[cd]tors global to M2, and
2450b57cec5SDimitry Andric /// prune appropriate entries out of M1s list.
SplitStaticCtorDtor(const char * GlobalName,Module * M1,Module * M2,ValueToValueMapTy & VMap)2460b57cec5SDimitry Andric static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2,
2470b57cec5SDimitry Andric ValueToValueMapTy &VMap) {
2480b57cec5SDimitry Andric GlobalVariable *GV = M1->getNamedGlobal(GlobalName);
2490b57cec5SDimitry Andric if (!GV || GV->isDeclaration() || GV->hasLocalLinkage() || !GV->use_empty())
2500b57cec5SDimitry Andric return;
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andric std::vector<std::pair<Function *, int>> M1Tors, M2Tors;
2530b57cec5SDimitry Andric ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
2540b57cec5SDimitry Andric if (!InitList)
2550b57cec5SDimitry Andric return;
2560b57cec5SDimitry Andric
2570b57cec5SDimitry Andric for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
2580b57cec5SDimitry Andric if (ConstantStruct *CS =
2590b57cec5SDimitry Andric dyn_cast<ConstantStruct>(InitList->getOperand(i))) {
2600b57cec5SDimitry Andric if (CS->getNumOperands() != 2)
2610b57cec5SDimitry Andric return; // Not array of 2-element structs.
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric if (CS->getOperand(1)->isNullValue())
2640b57cec5SDimitry Andric break; // Found a null terminator, stop here.
2650b57cec5SDimitry Andric
2660b57cec5SDimitry Andric ConstantInt *CI = dyn_cast<ConstantInt>(CS->getOperand(0));
2670b57cec5SDimitry Andric int Priority = CI ? CI->getSExtValue() : 0;
2680b57cec5SDimitry Andric
2690b57cec5SDimitry Andric Constant *FP = CS->getOperand(1);
2700b57cec5SDimitry Andric if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
2710b57cec5SDimitry Andric if (CE->isCast())
2720b57cec5SDimitry Andric FP = CE->getOperand(0);
2730b57cec5SDimitry Andric if (Function *F = dyn_cast<Function>(FP)) {
2740b57cec5SDimitry Andric if (!F->isDeclaration())
2750b57cec5SDimitry Andric M1Tors.push_back(std::make_pair(F, Priority));
2760b57cec5SDimitry Andric else {
2770b57cec5SDimitry Andric // Map to M2's version of the function.
2780b57cec5SDimitry Andric F = cast<Function>(VMap[F]);
2790b57cec5SDimitry Andric M2Tors.push_back(std::make_pair(F, Priority));
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric }
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric
2850b57cec5SDimitry Andric GV->eraseFromParent();
2860b57cec5SDimitry Andric if (!M1Tors.empty()) {
2870b57cec5SDimitry Andric Constant *M1Init = GetTorInit(M1Tors);
2880b57cec5SDimitry Andric new GlobalVariable(*M1, M1Init->getType(), false,
2890b57cec5SDimitry Andric GlobalValue::AppendingLinkage, M1Init, GlobalName);
2900b57cec5SDimitry Andric }
2910b57cec5SDimitry Andric
2920b57cec5SDimitry Andric GV = M2->getNamedGlobal(GlobalName);
2930b57cec5SDimitry Andric assert(GV && "Not a clone of M1?");
2940b57cec5SDimitry Andric assert(GV->use_empty() && "llvm.ctors shouldn't have uses!");
2950b57cec5SDimitry Andric
2960b57cec5SDimitry Andric GV->eraseFromParent();
2970b57cec5SDimitry Andric if (!M2Tors.empty()) {
2980b57cec5SDimitry Andric Constant *M2Init = GetTorInit(M2Tors);
2990b57cec5SDimitry Andric new GlobalVariable(*M2, M2Init->getType(), false,
3000b57cec5SDimitry Andric GlobalValue::AppendingLinkage, M2Init, GlobalName);
3010b57cec5SDimitry Andric }
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric
3040b57cec5SDimitry Andric std::unique_ptr<Module>
SplitFunctionsOutOfModule(Module * M,const std::vector<Function * > & F,ValueToValueMapTy & VMap)3050b57cec5SDimitry Andric llvm::SplitFunctionsOutOfModule(Module *M, const std::vector<Function *> &F,
3060b57cec5SDimitry Andric ValueToValueMapTy &VMap) {
3070b57cec5SDimitry Andric // Make sure functions & globals are all external so that linkage
3080b57cec5SDimitry Andric // between the two modules will work.
3090b57cec5SDimitry Andric for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
3100b57cec5SDimitry Andric I->setLinkage(GlobalValue::ExternalLinkage);
3110b57cec5SDimitry Andric for (Module::global_iterator I = M->global_begin(), E = M->global_end();
3120b57cec5SDimitry Andric I != E; ++I) {
3130b57cec5SDimitry Andric if (I->hasName() && I->getName()[0] == '\01')
3140b57cec5SDimitry Andric I->setName(I->getName().substr(1));
3150b57cec5SDimitry Andric I->setLinkage(GlobalValue::ExternalLinkage);
3160b57cec5SDimitry Andric }
3170b57cec5SDimitry Andric
3180b57cec5SDimitry Andric ValueToValueMapTy NewVMap;
3190b57cec5SDimitry Andric std::unique_ptr<Module> New = CloneModule(*M, NewVMap);
3200b57cec5SDimitry Andric
3210b57cec5SDimitry Andric // Remove the Test functions from the Safe module
3220b57cec5SDimitry Andric std::set<Function *> TestFunctions;
3230b57cec5SDimitry Andric for (unsigned i = 0, e = F.size(); i != e; ++i) {
3240b57cec5SDimitry Andric Function *TNOF = cast<Function>(VMap[F[i]]);
3250b57cec5SDimitry Andric LLVM_DEBUG(errs() << "Removing function ");
3260b57cec5SDimitry Andric LLVM_DEBUG(TNOF->printAsOperand(errs(), false));
3270b57cec5SDimitry Andric LLVM_DEBUG(errs() << "\n");
3280b57cec5SDimitry Andric TestFunctions.insert(cast<Function>(NewVMap[TNOF]));
3290b57cec5SDimitry Andric DeleteFunctionBody(TNOF); // Function is now external in this module!
3300b57cec5SDimitry Andric }
3310b57cec5SDimitry Andric
3320b57cec5SDimitry Andric // Remove the Safe functions from the Test module
3330b57cec5SDimitry Andric for (Function &I : *New)
3340b57cec5SDimitry Andric if (!TestFunctions.count(&I))
3350b57cec5SDimitry Andric DeleteFunctionBody(&I);
3360b57cec5SDimitry Andric
3370b57cec5SDimitry Andric // Try to split the global initializers evenly
3380b57cec5SDimitry Andric for (GlobalVariable &I : M->globals()) {
3390b57cec5SDimitry Andric GlobalVariable *GV = cast<GlobalVariable>(NewVMap[&I]);
3400b57cec5SDimitry Andric if (Function *TestFn = globalInitUsesExternalBA(&I)) {
3410b57cec5SDimitry Andric if (Function *SafeFn = globalInitUsesExternalBA(GV)) {
3420b57cec5SDimitry Andric errs() << "*** Error: when reducing functions, encountered "
3430b57cec5SDimitry Andric "the global '";
3440b57cec5SDimitry Andric GV->printAsOperand(errs(), false);
3450b57cec5SDimitry Andric errs() << "' with an initializer that references blockaddresses "
3460b57cec5SDimitry Andric "from safe function '"
3470b57cec5SDimitry Andric << SafeFn->getName() << "' and from test function '"
3480b57cec5SDimitry Andric << TestFn->getName() << "'.\n";
3490b57cec5SDimitry Andric exit(1);
3500b57cec5SDimitry Andric }
3510b57cec5SDimitry Andric DeleteGlobalInitializer(&I); // Delete the initializer to make it external
3520b57cec5SDimitry Andric } else {
3530b57cec5SDimitry Andric // If we keep it in the safe module, then delete it in the test module
3540b57cec5SDimitry Andric DeleteGlobalInitializer(GV);
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric
3580b57cec5SDimitry Andric // Make sure that there is a global ctor/dtor array in both halves of the
3590b57cec5SDimitry Andric // module if they both have static ctor/dtor functions.
3600b57cec5SDimitry Andric SplitStaticCtorDtor("llvm.global_ctors", M, New.get(), NewVMap);
3610b57cec5SDimitry Andric SplitStaticCtorDtor("llvm.global_dtors", M, New.get(), NewVMap);
3620b57cec5SDimitry Andric
3630b57cec5SDimitry Andric return New;
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric
3660b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
3670b57cec5SDimitry Andric // Basic Block Extraction Code
3680b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
3690b57cec5SDimitry Andric
3700b57cec5SDimitry Andric std::unique_ptr<Module>
extractMappedBlocksFromModule(const std::vector<BasicBlock * > & BBs,Module * M)3710b57cec5SDimitry Andric BugDriver::extractMappedBlocksFromModule(const std::vector<BasicBlock *> &BBs,
3720b57cec5SDimitry Andric Module *M) {
3730b57cec5SDimitry Andric auto Temp = sys::fs::TempFile::create(OutputPrefix + "-extractblocks%%%%%%%");
3740b57cec5SDimitry Andric if (!Temp) {
3750b57cec5SDimitry Andric outs() << "*** Basic Block extraction failed!\n";
3760b57cec5SDimitry Andric errs() << "Error creating temporary file: " << toString(Temp.takeError())
3770b57cec5SDimitry Andric << "\n";
3780b57cec5SDimitry Andric EmitProgressBitcode(*M, "basicblockextractfail", true);
3790b57cec5SDimitry Andric return nullptr;
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric DiscardTemp Discard{*Temp};
3820b57cec5SDimitry Andric
3830b57cec5SDimitry Andric // Extract all of the blocks except the ones in BBs.
3840b57cec5SDimitry Andric SmallVector<BasicBlock *, 32> BlocksToExtract;
3850b57cec5SDimitry Andric for (Function &F : *M)
3860b57cec5SDimitry Andric for (BasicBlock &BB : F)
3870b57cec5SDimitry Andric // Check if this block is going to be extracted.
388e8d8bef9SDimitry Andric if (!llvm::is_contained(BBs, &BB))
3890b57cec5SDimitry Andric BlocksToExtract.push_back(&BB);
3900b57cec5SDimitry Andric
3910b57cec5SDimitry Andric raw_fd_ostream OS(Temp->FD, /*shouldClose*/ false);
3920b57cec5SDimitry Andric for (BasicBlock *BB : BBs) {
3930b57cec5SDimitry Andric // If the BB doesn't have a name, give it one so we have something to key
3940b57cec5SDimitry Andric // off of.
3950b57cec5SDimitry Andric if (!BB->hasName())
3960b57cec5SDimitry Andric BB->setName("tmpbb");
3970b57cec5SDimitry Andric OS << BB->getParent()->getName() << " " << BB->getName() << "\n";
3980b57cec5SDimitry Andric }
3990b57cec5SDimitry Andric OS.flush();
4000b57cec5SDimitry Andric if (OS.has_error()) {
4010b57cec5SDimitry Andric errs() << "Error writing list of blocks to not extract\n";
4020b57cec5SDimitry Andric EmitProgressBitcode(*M, "basicblockextractfail", true);
4030b57cec5SDimitry Andric OS.clear_error();
4040b57cec5SDimitry Andric return nullptr;
4050b57cec5SDimitry Andric }
4060b57cec5SDimitry Andric
4070b57cec5SDimitry Andric std::string uniqueFN = "--extract-blocks-file=";
4080b57cec5SDimitry Andric uniqueFN += Temp->TmpName;
4090b57cec5SDimitry Andric
4100b57cec5SDimitry Andric std::vector<std::string> PI;
4110b57cec5SDimitry Andric PI.push_back("extract-blocks");
4128bcb0991SDimitry Andric std::unique_ptr<Module> Ret = runPassesOn(M, PI, {uniqueFN});
4130b57cec5SDimitry Andric
4140b57cec5SDimitry Andric if (!Ret) {
4150b57cec5SDimitry Andric outs() << "*** Basic Block extraction failed, please report a bug!\n";
4160b57cec5SDimitry Andric EmitProgressBitcode(*M, "basicblockextractfail", true);
4170b57cec5SDimitry Andric }
4180b57cec5SDimitry Andric return Ret;
4190b57cec5SDimitry Andric }
420