/// SplitFunctionsOutOfModule - Given a module and a list of functions in the /// module, split the functions OUT of the specified module, and place them in /// the new module. Module * llvm::SplitFunctionsOutOfModule(Module *M, const std::vector<Function*> &F, DenseMap<const Value*, Value*> &ValueMap) { // Make sure functions & globals are all external so that linkage // between the two modules will work. for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) I->setLinkage(GlobalValue::ExternalLinkage); for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) { if (I->hasName() && I->getName()[0] == '\01') I->setName(I->getName().substr(1)); I->setLinkage(GlobalValue::ExternalLinkage); } DenseMap<const Value*, Value*> NewValueMap; Module *New = CloneModule(M, NewValueMap); // Make sure global initializers exist only in the safe module (CBE->.so) for (Module::global_iterator I = New->global_begin(), E = New->global_end(); I != E; ++I) I->setInitializer(0); // Delete the initializer to make it external // Remove the Test functions from the Safe module std::set<Function *> TestFunctions; for (unsigned i = 0, e = F.size(); i != e; ++i) { Function *TNOF = cast<Function>(ValueMap[F[i]]); DEBUG(errs() << "Removing function "); DEBUG(WriteAsOperand(errs(), TNOF, false)); DEBUG(errs() << "\n"); TestFunctions.insert(cast<Function>(NewValueMap[TNOF])); DeleteFunctionBody(TNOF); // Function is now external in this module! } // Remove the Safe functions from the Test module for (Module::iterator I = New->begin(), E = New->end(); I != E; ++I) if (!TestFunctions.count(I)) DeleteFunctionBody(I); // Make sure that there is a global ctor/dtor array in both halves of the // module if they both have static ctor/dtor functions. SplitStaticCtorDtor("llvm.global_ctors", M, New, NewValueMap); SplitStaticCtorDtor("llvm.global_dtors", M, New, NewValueMap); return New; }
bool StripExternals::runOnModule(Module &M) { bool Changed = false; for (Module::iterator I = M.begin(); I != M.end(); ) { if (I->hasAvailableExternallyLinkage()) { assert(!I->isDeclaration()&&"Declarations can't be available_externally"); Changed = true; ++NumFunctions; if (I->use_empty()) { DEBUG(errs() << "Deleting function: " << *I); Module::iterator todelete = I; ++I; todelete->eraseFromParent(); continue; } else { I->deleteBody(); DEBUG(errs() << "Deleted function body: " << *I); } } ++I; } for (Module::global_iterator I = M.global_begin(); I != M.global_end(); ) { if (I->hasAvailableExternallyLinkage()) { assert(!I->isDeclaration()&&"Declarations can't be available_externally"); Changed = true; ++NumVariables; if (I->use_empty()) { DEBUG(errs() << "Deleting global: " << *I); Module::global_iterator todelete = I; ++I; todelete->eraseFromParent(); continue; } else { I->setInitializer(0); I->setLinkage(GlobalValue::ExternalLinkage); DEBUG(errs() << "Deleted initializer: " << *I); } } ++I; } return Changed; }
bool ReduceCrashingGlobalVariables::TestGlobalVariables( std::vector<GlobalVariable*> &GVs) { // Clone the program to try hacking it apart... ValueMap<const Value*, Value*> VMap; Module *M = CloneModule(BD.getProgram(), VMap); // Convert list to set for fast lookup... std::set<GlobalVariable*> GVSet; for (unsigned i = 0, e = GVs.size(); i != e; ++i) { GlobalVariable* CMGV = cast<GlobalVariable>(VMap[GVs[i]]); assert(CMGV && "Global Variable not in module?!"); GVSet.insert(CMGV); } outs() << "Checking for crash with only these global variables: "; PrintGlobalVariableList(GVs); outs() << ": "; // Loop over and delete any global variables which we aren't supposed to be // playing with... for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) if (I->hasInitializer() && !GVSet.count(I)) { I->setInitializer(0); I->setLinkage(GlobalValue::ExternalLinkage); } // Try running the hacked up program... if (TestFn(BD, M)) { BD.setNewProgram(M); // It crashed, keep the trimmed version... // Make sure to use global variable pointers that point into the now-current // module. GVs.assign(GVSet.begin(), GVSet.end()); return true; } delete M; return false; }
static int runCompilePasses(Module *ModuleRef, unsigned ModuleIndex, ThreadedFunctionQueue *FuncQueue, const Triple &TheTriple, TargetMachine &Target, StringRef ProgramName, raw_pwrite_stream &OS){ PNaClABIErrorReporter ABIErrorReporter; if (SplitModuleCount > 1 || ExternalizeAll) { // Add function and global names, and give them external linkage. // This relies on LLVM's consistent auto-generation of names, we could // maybe do our own in case something changes there. for (Function &F : *ModuleRef) { if (!F.hasName()) F.setName("Function"); if (F.hasInternalLinkage()) F.setLinkage(GlobalValue::ExternalLinkage); } for (Module::global_iterator GI = ModuleRef->global_begin(), GE = ModuleRef->global_end(); GI != GE; ++GI) { if (!GI->hasName()) GI->setName("Global"); if (GI->hasInternalLinkage()) GI->setLinkage(GlobalValue::ExternalLinkage); } if (ModuleIndex > 0) { // Remove the initializers for all global variables, turning them into // declarations. for (Module::global_iterator GI = ModuleRef->global_begin(), GE = ModuleRef->global_end(); GI != GE; ++GI) { assert(GI->hasInitializer() && "Global variable missing initializer"); Constant *Init = GI->getInitializer(); GI->setInitializer(nullptr); if (Init->getNumUses() == 0) Init->destroyConstant(); } } } // Make all non-weak symbols hidden for better code. We cannot do // this for weak symbols. The linker complains when some weak // symbols are not resolved. for (Function &F : *ModuleRef) { if (!F.isWeakForLinker() && !F.hasLocalLinkage()) F.setVisibility(GlobalValue::HiddenVisibility); } for (Module::global_iterator GI = ModuleRef->global_begin(), GE = ModuleRef->global_end(); GI != GE; ++GI) { if (!GI->isWeakForLinker() && !GI->hasLocalLinkage()) GI->setVisibility(GlobalValue::HiddenVisibility); } // Build up all of the passes that we want to do to the module. std::unique_ptr<legacy::PassManagerBase> PM; if (LazyBitcode) PM.reset(new legacy::FunctionPassManager(ModuleRef)); else PM.reset(new legacy::PassManager()); // Add the target data from the target machine, if it exists, or the module. if (const DataLayout *DL = Target.getDataLayout()) ModuleRef->setDataLayout(*DL); // For conformance with llc, we let the user disable LLVM IR verification with // -disable-verify. Unlike llc, when LLVM IR verification is enabled we only // run it once, before PNaCl ABI verification. if (!NoVerify) PM->add(createVerifierPass()); // Add the ABI verifier pass before the analysis and code emission passes. if (PNaClABIVerify) PM->add(createPNaClABIVerifyFunctionsPass(&ABIErrorReporter)); // Add the intrinsic resolution pass. It assumes ABI-conformant code. PM->add(createResolvePNaClIntrinsicsPass()); // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfoImpl TLII(TheTriple); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (DisableSimplifyLibCalls) TLII.disableAllFunctions(); PM->add(new TargetLibraryInfoWrapperPass(TLII)); // Allow subsequent passes and the backend to better optimize instructions // that were simplified for PNaCl's ABI. This pass uses the TargetLibraryInfo // above. PM->add(createBackendCanonicalizePass()); // Ask the target to add backend passes as necessary. We explicitly ask it // not to add the verifier pass because we added it earlier. if (Target.addPassesToEmitFile(*PM, OS, FileType, /* DisableVerify */ true)) { errs() << ProgramName << ": target does not support generation of this file type!\n"; return 1; } if (LazyBitcode) { auto FPM = static_cast<legacy::FunctionPassManager *>(PM.get()); FPM->doInitialization(); unsigned FuncIndex = 0; switch (SplitModuleSched) { case SplitModuleStatic: for (Function &F : *ModuleRef) { if (FuncQueue->GrabFunctionStatic(FuncIndex, ModuleIndex)) { FPM->run(F); CheckABIVerifyErrors(ABIErrorReporter, "Function " + F.getName()); F.Dematerialize(); } ++FuncIndex; } break; case SplitModuleDynamic: unsigned ChunkSize = 0; unsigned NumFunctions = FuncQueue->Size(); Module::iterator I = ModuleRef->begin(); while (FuncIndex < NumFunctions) { ChunkSize = FuncQueue->RecommendedChunkSize(); unsigned NextIndex; bool grabbed = FuncQueue->GrabFunctionDynamic(FuncIndex, ChunkSize, NextIndex); if (grabbed) { while (FuncIndex < NextIndex) { if (!I->isMaterializable() && I->isDeclaration()) { ++I; continue; } FPM->run(*I); CheckABIVerifyErrors(ABIErrorReporter, "Function " + I->getName()); I->Dematerialize(); ++FuncIndex; ++I; } } else { while (FuncIndex < NextIndex) { if (!I->isMaterializable() && I->isDeclaration()) { ++I; continue; } ++FuncIndex; ++I; } } } break; } FPM->doFinalization(); } else static_cast<legacy::PassManager *>(PM.get())->run(*ModuleRef); return 0; }
/// DebugACrash - Given a predicate that determines whether a component crashes /// on a program, try to destructively reduce the program while still keeping /// the predicate true. static bool DebugACrash(BugDriver &BD, bool (*TestFn)(const BugDriver &, Module *), std::string &Error) { // See if we can get away with nuking some of the global variable initializers // in the program... if (!NoGlobalRM && BD.getProgram()->global_begin() != BD.getProgram()->global_end()) { // Now try to reduce the number of global variable initializers in the // module to something small. Module *M = CloneModule(BD.getProgram()); bool DeletedInit = false; for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) if (I->hasInitializer()) { I->setInitializer(nullptr); I->setLinkage(GlobalValue::ExternalLinkage); DeletedInit = true; } if (!DeletedInit) { delete M; // No change made... } else { // See if the program still causes a crash... outs() << "\nChecking to see if we can delete global inits: "; if (TestFn(BD, M)) { // Still crashes? BD.setNewProgram(M); outs() << "\n*** Able to remove all global initializers!\n"; } else { // No longer crashes? outs() << " - Removing all global inits hides problem!\n"; delete M; std::vector<GlobalVariable*> GVs; for (Module::global_iterator I = BD.getProgram()->global_begin(), E = BD.getProgram()->global_end(); I != E; ++I) if (I->hasInitializer()) GVs.push_back(&*I); if (GVs.size() > 1 && !BugpointIsInterrupted) { outs() << "\n*** Attempting to reduce the number of global " << "variables in the testcase\n"; unsigned OldSize = GVs.size(); ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs, Error); if (!Error.empty()) return true; if (GVs.size() < OldSize) BD.EmitProgressBitcode(BD.getProgram(), "reduced-global-variables"); } } } } // Now try to reduce the number of functions in the module to something small. std::vector<Function*> Functions; for (Function &F : *BD.getProgram()) if (!F.isDeclaration()) Functions.push_back(&F); if (Functions.size() > 1 && !BugpointIsInterrupted) { outs() << "\n*** Attempting to reduce the number of functions " "in the testcase\n"; unsigned OldSize = Functions.size(); ReduceCrashingFunctions(BD, TestFn).reduceList(Functions, Error); if (Functions.size() < OldSize) BD.EmitProgressBitcode(BD.getProgram(), "reduced-function"); } // Attempt to delete entire basic blocks at a time to speed up // convergence... this actually works by setting the terminator of the blocks // to a return instruction then running simplifycfg, which can potentially // shrinks the code dramatically quickly // if (!DisableSimplifyCFG && !BugpointIsInterrupted) { std::vector<const BasicBlock*> Blocks; for (Function &F : *BD.getProgram()) for (BasicBlock &BB : F) Blocks.push_back(&BB); unsigned OldSize = Blocks.size(); ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks, Error); if (Blocks.size() < OldSize) BD.EmitProgressBitcode(BD.getProgram(), "reduced-blocks"); } // Attempt to delete instructions using bisection. This should help out nasty // cases with large basic blocks where the problem is at one end. if (!BugpointIsInterrupted) { std::vector<const Instruction*> Insts; for (const Function &F : *BD.getProgram()) for (const BasicBlock &BB : F) for (const Instruction &I : BB) if (!isa<TerminatorInst>(&I)) Insts.push_back(&I); ReduceCrashingInstructions(BD, TestFn).reduceList(Insts, Error); } // FIXME: This should use the list reducer to converge faster by deleting // larger chunks of instructions at a time! unsigned Simplification = 2; do { if (BugpointIsInterrupted) break; --Simplification; outs() << "\n*** Attempting to reduce testcase by deleting instruc" << "tions: Simplification Level #" << Simplification << '\n'; // Now that we have deleted the functions that are unnecessary for the // program, try to remove instructions that are not necessary to cause the // crash. To do this, we loop through all of the instructions in the // remaining functions, deleting them (replacing any values produced with // nulls), and then running ADCE and SimplifyCFG. If the transformed input // still triggers failure, keep deleting until we cannot trigger failure // anymore. // unsigned InstructionsToSkipBeforeDeleting = 0; TryAgain: // Loop over all of the (non-terminator) instructions remaining in the // function, attempting to delete them. unsigned CurInstructionNum = 0; for (Module::const_iterator FI = BD.getProgram()->begin(), E = BD.getProgram()->end(); FI != E; ++FI) if (!FI->isDeclaration()) for (Function::const_iterator BI = FI->begin(), E = FI->end(); BI != E; ++BI) for (BasicBlock::const_iterator I = BI->begin(), E = --BI->end(); I != E; ++I, ++CurInstructionNum) { if (InstructionsToSkipBeforeDeleting) { --InstructionsToSkipBeforeDeleting; } else { if (BugpointIsInterrupted) goto ExitLoops; if (isa<LandingPadInst>(I)) continue; outs() << "Checking instruction: " << *I; std::unique_ptr<Module> M = BD.deleteInstructionFromProgram(&*I, Simplification); // Find out if the pass still crashes on this pass... if (TestFn(BD, M.get())) { // Yup, it does, we delete the old module, and continue trying // to reduce the testcase... BD.setNewProgram(M.release()); InstructionsToSkipBeforeDeleting = CurInstructionNum; goto TryAgain; // I wish I had a multi-level break here! } } } if (InstructionsToSkipBeforeDeleting) { InstructionsToSkipBeforeDeleting = 0; goto TryAgain; } } while (Simplification); ExitLoops: // Try to clean up the testcase by running funcresolve and globaldce... if (!BugpointIsInterrupted) { outs() << "\n*** Attempting to perform final cleanups: "; Module *M = CloneModule(BD.getProgram()); M = BD.performFinalCleanups(M, true).release(); // Find out if the pass still crashes on the cleaned up program... if (TestFn(BD, M)) { BD.setNewProgram(M); // Yup, it does, keep the reduced version... } else { delete M; } } BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplified"); return false; }
/// SplitFunctionsOutOfModule - Given a module and a list of functions in the /// module, split the functions OUT of the specified module, and place them in /// the new module. Module * llvm::SplitFunctionsOutOfModule(Module *M, const std::vector<Function*> &F, ValueToValueMapTy &VMap) { // Make sure functions & globals are all external so that linkage // between the two modules will work. for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) I->setLinkage(GlobalValue::ExternalLinkage); for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) { if (I->hasName() && I->getName()[0] == '\01') I->setName(I->getName().substr(1)); I->setLinkage(GlobalValue::ExternalLinkage); } ValueToValueMapTy NewVMap; Module *New = CloneModule(M, NewVMap); // Remove the Test functions from the Safe module std::set<Function *> TestFunctions; for (unsigned i = 0, e = F.size(); i != e; ++i) { Function *TNOF = cast<Function>(VMap[F[i]]); DEBUG(errs() << "Removing function "); DEBUG(WriteAsOperand(errs(), TNOF, false)); DEBUG(errs() << "\n"); TestFunctions.insert(cast<Function>(NewVMap[TNOF])); DeleteFunctionBody(TNOF); // Function is now external in this module! } // Remove the Safe functions from the Test module for (Module::iterator I = New->begin(), E = New->end(); I != E; ++I) if (!TestFunctions.count(I)) DeleteFunctionBody(I); // Try to split the global initializers evenly for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) { GlobalVariable *GV = cast<GlobalVariable>(NewVMap[I]); if (Function *TestFn = globalInitUsesExternalBA(I)) { if (Function *SafeFn = globalInitUsesExternalBA(GV)) { errs() << "*** Error: when reducing functions, encountered " "the global '"; WriteAsOperand(errs(), GV, false); errs() << "' with an initializer that references blockaddresses " "from safe function '" << SafeFn->getName() << "' and from test function '" << TestFn->getName() << "'.\n"; exit(1); } I->setInitializer(0); // Delete the initializer to make it external } else { // If we keep it in the safe module, then delete it in the test module GV->setInitializer(0); } } // Make sure that there is a global ctor/dtor array in both halves of the // module if they both have static ctor/dtor functions. SplitStaticCtorDtor("llvm.global_ctors", M, New, NewVMap); SplitStaticCtorDtor("llvm.global_dtors", M, New, NewVMap); return New; }
bool GlobalDCE::runOnModule(Module &M) { bool Changed = false; // Loop over the module, adding globals which are obviously necessary. for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { Changed |= RemoveUnusedGlobalValue(*I); // Functions with external linkage are needed if they have a body if (!I->isDiscardableIfUnused() && !I->isDeclaration() && !I->hasAvailableExternallyLinkage()) GlobalIsNeeded(I); } for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { Changed |= RemoveUnusedGlobalValue(*I); // Externally visible & appending globals are needed, if they have an // initializer. if (!I->isDiscardableIfUnused() && !I->isDeclaration() && !I->hasAvailableExternallyLinkage()) GlobalIsNeeded(I); } for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) { Changed |= RemoveUnusedGlobalValue(*I); // Externally visible aliases are needed. if (!I->isDiscardableIfUnused()) GlobalIsNeeded(I); } // Now that all globals which are needed are in the AliveGlobals set, we loop // through the program, deleting those which are not alive. // // The first pass is to drop initializers of global variables which are dead. std::vector<GlobalVariable*> DeadGlobalVars; // Keep track of dead globals for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) if (!AliveGlobals.count(I)) { DeadGlobalVars.push_back(I); // Keep track of dead globals I->setInitializer(0); } // The second pass drops the bodies of functions which are dead... std::vector<Function*> DeadFunctions; for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (!AliveGlobals.count(I)) { DeadFunctions.push_back(I); // Keep track of dead globals if (!I->isDeclaration()) I->deleteBody(); } // The third pass drops targets of aliases which are dead... std::vector<GlobalAlias*> DeadAliases; for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) if (!AliveGlobals.count(I)) { DeadAliases.push_back(I); I->setAliasee(0); } if (!DeadFunctions.empty()) { // Now that all interferences have been dropped, delete the actual objects // themselves. for (unsigned i = 0, e = DeadFunctions.size(); i != e; ++i) { RemoveUnusedGlobalValue(*DeadFunctions[i]); M.getFunctionList().erase(DeadFunctions[i]); } NumFunctions += DeadFunctions.size(); Changed = true; } if (!DeadGlobalVars.empty()) { for (unsigned i = 0, e = DeadGlobalVars.size(); i != e; ++i) { RemoveUnusedGlobalValue(*DeadGlobalVars[i]); M.getGlobalList().erase(DeadGlobalVars[i]); } NumVariables += DeadGlobalVars.size(); Changed = true; } // Now delete any dead aliases. if (!DeadAliases.empty()) { for (unsigned i = 0, e = DeadAliases.size(); i != e; ++i) { RemoveUnusedGlobalValue(*DeadAliases[i]); M.getAliasList().erase(DeadAliases[i]); } NumAliases += DeadAliases.size(); Changed = true; } // Make sure that all memory is released AliveGlobals.clear(); return Changed; }