10b57cec5SDimitry Andric //===- Miscompilation.cpp - Debug program miscompilations -----------------===//
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 optimizer and code generation miscompilation debugging
100b57cec5SDimitry Andric // support.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "BugDriver.h"
150b57cec5SDimitry Andric #include "ListReducer.h"
160b57cec5SDimitry Andric #include "ToolRunner.h"
170b57cec5SDimitry Andric #include "llvm/Config/config.h" // for HAVE_LINK_R
180b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
190b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
200b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
210b57cec5SDimitry Andric #include "llvm/IR/Module.h"
220b57cec5SDimitry Andric #include "llvm/IR/Verifier.h"
230b57cec5SDimitry Andric #include "llvm/Linker/Linker.h"
240b57cec5SDimitry Andric #include "llvm/Pass.h"
250b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
260b57cec5SDimitry Andric #include "llvm/Support/FileUtilities.h"
270b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h"
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric using namespace llvm;
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric namespace llvm {
320b57cec5SDimitry Andric extern cl::opt<std::string> OutputPrefix;
330b57cec5SDimitry Andric extern cl::list<std::string> InputArgv;
340b57cec5SDimitry Andric } // end namespace llvm
350b57cec5SDimitry Andric
360b57cec5SDimitry Andric namespace {
370b57cec5SDimitry Andric static llvm::cl::opt<bool> DisableLoopExtraction(
380b57cec5SDimitry Andric "disable-loop-extraction",
390b57cec5SDimitry Andric cl::desc("Don't extract loops when searching for miscompilations"),
400b57cec5SDimitry Andric cl::init(false));
410b57cec5SDimitry Andric static llvm::cl::opt<bool> DisableBlockExtraction(
420b57cec5SDimitry Andric "disable-block-extraction",
430b57cec5SDimitry Andric cl::desc("Don't extract blocks when searching for miscompilations"),
440b57cec5SDimitry Andric cl::init(false));
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric class ReduceMiscompilingPasses : public ListReducer<std::string> {
470b57cec5SDimitry Andric BugDriver &BD;
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric public:
ReduceMiscompilingPasses(BugDriver & bd)500b57cec5SDimitry Andric ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {}
510b57cec5SDimitry Andric
520b57cec5SDimitry Andric Expected<TestResult> doTest(std::vector<std::string> &Prefix,
530b57cec5SDimitry Andric std::vector<std::string> &Suffix) override;
540b57cec5SDimitry Andric };
550b57cec5SDimitry Andric } // end anonymous namespace
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric /// TestResult - After passes have been split into a test group and a control
580b57cec5SDimitry Andric /// group, see if they still break the program.
590b57cec5SDimitry Andric ///
600b57cec5SDimitry Andric Expected<ReduceMiscompilingPasses::TestResult>
doTest(std::vector<std::string> & Prefix,std::vector<std::string> & Suffix)610b57cec5SDimitry Andric ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix,
620b57cec5SDimitry Andric std::vector<std::string> &Suffix) {
630b57cec5SDimitry Andric // First, run the program with just the Suffix passes. If it is still broken
640b57cec5SDimitry Andric // with JUST the kept passes, discard the prefix passes.
650b57cec5SDimitry Andric outs() << "Checking to see if '" << getPassesString(Suffix)
660b57cec5SDimitry Andric << "' compiles correctly: ";
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric std::string BitcodeResult;
690b57cec5SDimitry Andric if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false /*delete*/,
700b57cec5SDimitry Andric true /*quiet*/)) {
710b57cec5SDimitry Andric errs() << " Error running this sequence of passes"
720b57cec5SDimitry Andric << " on the input program!\n";
730b57cec5SDimitry Andric BD.setPassesToRun(Suffix);
740b57cec5SDimitry Andric BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false);
750b57cec5SDimitry Andric // TODO: This should propagate the error instead of exiting.
760b57cec5SDimitry Andric if (Error E = BD.debugOptimizerCrash())
770b57cec5SDimitry Andric exit(1);
780b57cec5SDimitry Andric exit(0);
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric
810b57cec5SDimitry Andric // Check to see if the finished program matches the reference output...
820b57cec5SDimitry Andric Expected<bool> Diff = BD.diffProgram(BD.getProgram(), BitcodeResult, "",
830b57cec5SDimitry Andric true /*delete bitcode*/);
840b57cec5SDimitry Andric if (Error E = Diff.takeError())
850b57cec5SDimitry Andric return std::move(E);
860b57cec5SDimitry Andric if (*Diff) {
870b57cec5SDimitry Andric outs() << " nope.\n";
880b57cec5SDimitry Andric if (Suffix.empty()) {
890b57cec5SDimitry Andric errs() << BD.getToolName() << ": I'm confused: the test fails when "
900b57cec5SDimitry Andric << "no passes are run, nondeterministic program?\n";
910b57cec5SDimitry Andric exit(1);
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric return KeepSuffix; // Miscompilation detected!
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric outs() << " yup.\n"; // No miscompilation!
960b57cec5SDimitry Andric
970b57cec5SDimitry Andric if (Prefix.empty())
980b57cec5SDimitry Andric return NoFailure;
990b57cec5SDimitry Andric
1000b57cec5SDimitry Andric // Next, see if the program is broken if we run the "prefix" passes first,
1010b57cec5SDimitry Andric // then separately run the "kept" passes.
1020b57cec5SDimitry Andric outs() << "Checking to see if '" << getPassesString(Prefix)
1030b57cec5SDimitry Andric << "' compiles correctly: ";
1040b57cec5SDimitry Andric
1050b57cec5SDimitry Andric // If it is not broken with the kept passes, it's possible that the prefix
1060b57cec5SDimitry Andric // passes must be run before the kept passes to break it. If the program
1070b57cec5SDimitry Andric // WORKS after the prefix passes, but then fails if running the prefix AND
1080b57cec5SDimitry Andric // kept passes, we can update our bitcode file to include the result of the
1090b57cec5SDimitry Andric // prefix passes, then discard the prefix passes.
1100b57cec5SDimitry Andric //
1110b57cec5SDimitry Andric if (BD.runPasses(BD.getProgram(), Prefix, BitcodeResult, false /*delete*/,
1120b57cec5SDimitry Andric true /*quiet*/)) {
1130b57cec5SDimitry Andric errs() << " Error running this sequence of passes"
1140b57cec5SDimitry Andric << " on the input program!\n";
1150b57cec5SDimitry Andric BD.setPassesToRun(Prefix);
1160b57cec5SDimitry Andric BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false);
1170b57cec5SDimitry Andric // TODO: This should propagate the error instead of exiting.
1180b57cec5SDimitry Andric if (Error E = BD.debugOptimizerCrash())
1190b57cec5SDimitry Andric exit(1);
1200b57cec5SDimitry Andric exit(0);
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric
1230b57cec5SDimitry Andric // If the prefix maintains the predicate by itself, only keep the prefix!
1240b57cec5SDimitry Andric Diff = BD.diffProgram(BD.getProgram(), BitcodeResult, "", false);
1250b57cec5SDimitry Andric if (Error E = Diff.takeError())
1260b57cec5SDimitry Andric return std::move(E);
1270b57cec5SDimitry Andric if (*Diff) {
1280b57cec5SDimitry Andric outs() << " nope.\n";
1290b57cec5SDimitry Andric sys::fs::remove(BitcodeResult);
1300b57cec5SDimitry Andric return KeepPrefix;
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric outs() << " yup.\n"; // No miscompilation!
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric // Ok, so now we know that the prefix passes work, try running the suffix
1350b57cec5SDimitry Andric // passes on the result of the prefix passes.
1360b57cec5SDimitry Andric //
1370b57cec5SDimitry Andric std::unique_ptr<Module> PrefixOutput =
1380b57cec5SDimitry Andric parseInputFile(BitcodeResult, BD.getContext());
1390b57cec5SDimitry Andric if (!PrefixOutput) {
1400b57cec5SDimitry Andric errs() << BD.getToolName() << ": Error reading bitcode file '"
1410b57cec5SDimitry Andric << BitcodeResult << "'!\n";
1420b57cec5SDimitry Andric exit(1);
1430b57cec5SDimitry Andric }
1440b57cec5SDimitry Andric sys::fs::remove(BitcodeResult);
1450b57cec5SDimitry Andric
1460b57cec5SDimitry Andric // Don't check if there are no passes in the suffix.
1470b57cec5SDimitry Andric if (Suffix.empty())
1480b57cec5SDimitry Andric return NoFailure;
1490b57cec5SDimitry Andric
1500b57cec5SDimitry Andric outs() << "Checking to see if '" << getPassesString(Suffix)
1510b57cec5SDimitry Andric << "' passes compile correctly after the '" << getPassesString(Prefix)
1520b57cec5SDimitry Andric << "' passes: ";
1530b57cec5SDimitry Andric
1540b57cec5SDimitry Andric std::unique_ptr<Module> OriginalInput =
1550b57cec5SDimitry Andric BD.swapProgramIn(std::move(PrefixOutput));
1560b57cec5SDimitry Andric if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false /*delete*/,
1570b57cec5SDimitry Andric true /*quiet*/)) {
1580b57cec5SDimitry Andric errs() << " Error running this sequence of passes"
1590b57cec5SDimitry Andric << " on the input program!\n";
1600b57cec5SDimitry Andric BD.setPassesToRun(Suffix);
1610b57cec5SDimitry Andric BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false);
1620b57cec5SDimitry Andric // TODO: This should propagate the error instead of exiting.
1630b57cec5SDimitry Andric if (Error E = BD.debugOptimizerCrash())
1640b57cec5SDimitry Andric exit(1);
1650b57cec5SDimitry Andric exit(0);
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andric // Run the result...
1690b57cec5SDimitry Andric Diff = BD.diffProgram(BD.getProgram(), BitcodeResult, "",
1700b57cec5SDimitry Andric true /*delete bitcode*/);
1710b57cec5SDimitry Andric if (Error E = Diff.takeError())
1720b57cec5SDimitry Andric return std::move(E);
1730b57cec5SDimitry Andric if (*Diff) {
1740b57cec5SDimitry Andric outs() << " nope.\n";
1750b57cec5SDimitry Andric return KeepSuffix;
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric
1780b57cec5SDimitry Andric // Otherwise, we must not be running the bad pass anymore.
1790b57cec5SDimitry Andric outs() << " yup.\n"; // No miscompilation!
1800b57cec5SDimitry Andric // Restore orig program & free test.
1810b57cec5SDimitry Andric BD.setNewProgram(std::move(OriginalInput));
1820b57cec5SDimitry Andric return NoFailure;
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric
1850b57cec5SDimitry Andric namespace {
1860b57cec5SDimitry Andric class ReduceMiscompilingFunctions : public ListReducer<Function *> {
1870b57cec5SDimitry Andric BugDriver &BD;
1880b57cec5SDimitry Andric Expected<bool> (*TestFn)(BugDriver &, std::unique_ptr<Module>,
1890b57cec5SDimitry Andric std::unique_ptr<Module>);
1900b57cec5SDimitry Andric
1910b57cec5SDimitry Andric public:
ReduceMiscompilingFunctions(BugDriver & bd,Expected<bool> (* F)(BugDriver &,std::unique_ptr<Module>,std::unique_ptr<Module>))1920b57cec5SDimitry Andric ReduceMiscompilingFunctions(BugDriver &bd,
1930b57cec5SDimitry Andric Expected<bool> (*F)(BugDriver &,
1940b57cec5SDimitry Andric std::unique_ptr<Module>,
1950b57cec5SDimitry Andric std::unique_ptr<Module>))
1960b57cec5SDimitry Andric : BD(bd), TestFn(F) {}
1970b57cec5SDimitry Andric
doTest(std::vector<Function * > & Prefix,std::vector<Function * > & Suffix)1980b57cec5SDimitry Andric Expected<TestResult> doTest(std::vector<Function *> &Prefix,
1990b57cec5SDimitry Andric std::vector<Function *> &Suffix) override {
2000b57cec5SDimitry Andric if (!Suffix.empty()) {
2010b57cec5SDimitry Andric Expected<bool> Ret = TestFuncs(Suffix);
2020b57cec5SDimitry Andric if (Error E = Ret.takeError())
2030b57cec5SDimitry Andric return std::move(E);
2040b57cec5SDimitry Andric if (*Ret)
2050b57cec5SDimitry Andric return KeepSuffix;
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric if (!Prefix.empty()) {
2080b57cec5SDimitry Andric Expected<bool> Ret = TestFuncs(Prefix);
2090b57cec5SDimitry Andric if (Error E = Ret.takeError())
2100b57cec5SDimitry Andric return std::move(E);
2110b57cec5SDimitry Andric if (*Ret)
2120b57cec5SDimitry Andric return KeepPrefix;
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric return NoFailure;
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric
2170b57cec5SDimitry Andric Expected<bool> TestFuncs(const std::vector<Function *> &Prefix);
2180b57cec5SDimitry Andric };
2190b57cec5SDimitry Andric } // end anonymous namespace
2200b57cec5SDimitry Andric
2210b57cec5SDimitry Andric /// Given two modules, link them together and run the program, checking to see
2220b57cec5SDimitry Andric /// if the program matches the diff. If there is an error, return NULL. If not,
2230b57cec5SDimitry Andric /// return the merged module. The Broken argument will be set to true if the
2240b57cec5SDimitry Andric /// output is different. If the DeleteInputs argument is set to true then this
2250b57cec5SDimitry Andric /// function deletes both input modules before it returns.
2260b57cec5SDimitry Andric ///
testMergedProgram(const BugDriver & BD,const Module & M1,const Module & M2,bool & Broken)2270b57cec5SDimitry Andric static Expected<std::unique_ptr<Module>> testMergedProgram(const BugDriver &BD,
2280b57cec5SDimitry Andric const Module &M1,
2290b57cec5SDimitry Andric const Module &M2,
2300b57cec5SDimitry Andric bool &Broken) {
2310b57cec5SDimitry Andric // Resulting merge of M1 and M2.
2320b57cec5SDimitry Andric auto Merged = CloneModule(M1);
2330b57cec5SDimitry Andric if (Linker::linkModules(*Merged, CloneModule(M2)))
2340b57cec5SDimitry Andric // TODO: Shouldn't we thread the error up instead of exiting?
2350b57cec5SDimitry Andric exit(1);
2360b57cec5SDimitry Andric
2370b57cec5SDimitry Andric // Execute the program.
2380b57cec5SDimitry Andric Expected<bool> Diff = BD.diffProgram(*Merged, "", "", false);
2390b57cec5SDimitry Andric if (Error E = Diff.takeError())
2400b57cec5SDimitry Andric return std::move(E);
2410b57cec5SDimitry Andric Broken = *Diff;
2420b57cec5SDimitry Andric return std::move(Merged);
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric
2450b57cec5SDimitry Andric /// split functions in a Module into two groups: those that are under
2460b57cec5SDimitry Andric /// consideration for miscompilation vs. those that are not, and test
2470b57cec5SDimitry Andric /// accordingly. Each group of functions becomes a separate Module.
2480b57cec5SDimitry Andric Expected<bool>
TestFuncs(const std::vector<Function * > & Funcs)2490b57cec5SDimitry Andric ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function *> &Funcs) {
2500b57cec5SDimitry Andric // Test to see if the function is misoptimized if we ONLY run it on the
2510b57cec5SDimitry Andric // functions listed in Funcs.
2520b57cec5SDimitry Andric outs() << "Checking to see if the program is misoptimized when "
2530b57cec5SDimitry Andric << (Funcs.size() == 1 ? "this function is" : "these functions are")
2540b57cec5SDimitry Andric << " run through the pass"
2550b57cec5SDimitry Andric << (BD.getPassesToRun().size() == 1 ? "" : "es") << ":";
2560b57cec5SDimitry Andric PrintFunctionList(Funcs);
2570b57cec5SDimitry Andric outs() << '\n';
2580b57cec5SDimitry Andric
2590b57cec5SDimitry Andric // Create a clone for two reasons:
2600b57cec5SDimitry Andric // * If the optimization passes delete any function, the deleted function
2610b57cec5SDimitry Andric // will be in the clone and Funcs will still point to valid memory
2620b57cec5SDimitry Andric // * If the optimization passes use interprocedural information to break
2630b57cec5SDimitry Andric // a function, we want to continue with the original function. Otherwise
2640b57cec5SDimitry Andric // we can conclude that a function triggers the bug when in fact one
2650b57cec5SDimitry Andric // needs a larger set of original functions to do so.
2660b57cec5SDimitry Andric ValueToValueMapTy VMap;
2670b57cec5SDimitry Andric std::unique_ptr<Module> Clone = CloneModule(BD.getProgram(), VMap);
2680b57cec5SDimitry Andric std::unique_ptr<Module> Orig = BD.swapProgramIn(std::move(Clone));
2690b57cec5SDimitry Andric
2700b57cec5SDimitry Andric std::vector<Function *> FuncsOnClone;
2710b57cec5SDimitry Andric for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
2720b57cec5SDimitry Andric Function *F = cast<Function>(VMap[Funcs[i]]);
2730b57cec5SDimitry Andric FuncsOnClone.push_back(F);
2740b57cec5SDimitry Andric }
2750b57cec5SDimitry Andric
2760b57cec5SDimitry Andric // Split the module into the two halves of the program we want.
2770b57cec5SDimitry Andric VMap.clear();
2780b57cec5SDimitry Andric std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap);
2790b57cec5SDimitry Andric std::unique_ptr<Module> ToOptimize =
2800b57cec5SDimitry Andric SplitFunctionsOutOfModule(ToNotOptimize.get(), FuncsOnClone, VMap);
2810b57cec5SDimitry Andric
2820b57cec5SDimitry Andric Expected<bool> Broken =
2830b57cec5SDimitry Andric TestFn(BD, std::move(ToOptimize), std::move(ToNotOptimize));
2840b57cec5SDimitry Andric
2850b57cec5SDimitry Andric BD.setNewProgram(std::move(Orig));
2860b57cec5SDimitry Andric
2870b57cec5SDimitry Andric return Broken;
2880b57cec5SDimitry Andric }
2890b57cec5SDimitry Andric
2900b57cec5SDimitry Andric /// Give anonymous global values names.
DisambiguateGlobalSymbols(Module & M)2910b57cec5SDimitry Andric static void DisambiguateGlobalSymbols(Module &M) {
2920b57cec5SDimitry Andric for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E;
2930b57cec5SDimitry Andric ++I)
2940b57cec5SDimitry Andric if (!I->hasName())
2950b57cec5SDimitry Andric I->setName("anon_global");
2960b57cec5SDimitry Andric for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
2970b57cec5SDimitry Andric if (!I->hasName())
2980b57cec5SDimitry Andric I->setName("anon_fn");
2990b57cec5SDimitry Andric }
3000b57cec5SDimitry Andric
3010b57cec5SDimitry Andric /// Given a reduced list of functions that still exposed the bug, check to see
3020b57cec5SDimitry Andric /// if we can extract the loops in the region without obscuring the bug. If so,
3030b57cec5SDimitry Andric /// it reduces the amount of code identified.
3040b57cec5SDimitry Andric ///
3050b57cec5SDimitry Andric static Expected<bool>
ExtractLoops(BugDriver & BD,Expected<bool> (* TestFn)(BugDriver &,std::unique_ptr<Module>,std::unique_ptr<Module>),std::vector<Function * > & MiscompiledFunctions)3060b57cec5SDimitry Andric ExtractLoops(BugDriver &BD,
3070b57cec5SDimitry Andric Expected<bool> (*TestFn)(BugDriver &, std::unique_ptr<Module>,
3080b57cec5SDimitry Andric std::unique_ptr<Module>),
3090b57cec5SDimitry Andric std::vector<Function *> &MiscompiledFunctions) {
3100b57cec5SDimitry Andric bool MadeChange = false;
31104eeddc0SDimitry Andric while (true) {
3120b57cec5SDimitry Andric if (BugpointIsInterrupted)
3130b57cec5SDimitry Andric return MadeChange;
3140b57cec5SDimitry Andric
3150b57cec5SDimitry Andric ValueToValueMapTy VMap;
3160b57cec5SDimitry Andric std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap);
3170b57cec5SDimitry Andric std::unique_ptr<Module> ToOptimize = SplitFunctionsOutOfModule(
3180b57cec5SDimitry Andric ToNotOptimize.get(), MiscompiledFunctions, VMap);
3190b57cec5SDimitry Andric std::unique_ptr<Module> ToOptimizeLoopExtracted =
3200b57cec5SDimitry Andric BD.extractLoop(ToOptimize.get());
3210b57cec5SDimitry Andric if (!ToOptimizeLoopExtracted)
3220b57cec5SDimitry Andric // If the loop extractor crashed or if there were no extractible loops,
3230b57cec5SDimitry Andric // then this chapter of our odyssey is over with.
3240b57cec5SDimitry Andric return MadeChange;
3250b57cec5SDimitry Andric
3260b57cec5SDimitry Andric errs() << "Extracted a loop from the breaking portion of the program.\n";
3270b57cec5SDimitry Andric
3280b57cec5SDimitry Andric // Bugpoint is intentionally not very trusting of LLVM transformations. In
3290b57cec5SDimitry Andric // particular, we're not going to assume that the loop extractor works, so
3300b57cec5SDimitry Andric // we're going to test the newly loop extracted program to make sure nothing
3310b57cec5SDimitry Andric // has broken. If something broke, then we'll inform the user and stop
3320b57cec5SDimitry Andric // extraction.
3330b57cec5SDimitry Andric AbstractInterpreter *AI = BD.switchToSafeInterpreter();
3340b57cec5SDimitry Andric bool Failure;
3350b57cec5SDimitry Andric Expected<std::unique_ptr<Module>> New = testMergedProgram(
3360b57cec5SDimitry Andric BD, *ToOptimizeLoopExtracted, *ToNotOptimize, Failure);
3370b57cec5SDimitry Andric if (Error E = New.takeError())
3380b57cec5SDimitry Andric return std::move(E);
3390b57cec5SDimitry Andric if (!*New)
3400b57cec5SDimitry Andric return false;
3410b57cec5SDimitry Andric
3420b57cec5SDimitry Andric // Delete the original and set the new program.
3430b57cec5SDimitry Andric std::unique_ptr<Module> Old = BD.swapProgramIn(std::move(*New));
3440b57cec5SDimitry Andric for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
3450b57cec5SDimitry Andric MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]);
3460b57cec5SDimitry Andric
3470b57cec5SDimitry Andric if (Failure) {
3480b57cec5SDimitry Andric BD.switchToInterpreter(AI);
3490b57cec5SDimitry Andric
3500b57cec5SDimitry Andric // Merged program doesn't work anymore!
3510b57cec5SDimitry Andric errs() << " *** ERROR: Loop extraction broke the program. :("
3520b57cec5SDimitry Andric << " Please report a bug!\n";
3530b57cec5SDimitry Andric errs() << " Continuing on with un-loop-extracted version.\n";
3540b57cec5SDimitry Andric
3550b57cec5SDimitry Andric BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-tno.bc",
3560b57cec5SDimitry Andric *ToNotOptimize);
3570b57cec5SDimitry Andric BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to.bc",
3580b57cec5SDimitry Andric *ToOptimize);
3590b57cec5SDimitry Andric BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to-le.bc",
3600b57cec5SDimitry Andric *ToOptimizeLoopExtracted);
3610b57cec5SDimitry Andric
3620b57cec5SDimitry Andric errs() << "Please submit the " << OutputPrefix
3630b57cec5SDimitry Andric << "-loop-extract-fail-*.bc files.\n";
3640b57cec5SDimitry Andric return MadeChange;
3650b57cec5SDimitry Andric }
3660b57cec5SDimitry Andric BD.switchToInterpreter(AI);
3670b57cec5SDimitry Andric
3680b57cec5SDimitry Andric outs() << " Testing after loop extraction:\n";
3690b57cec5SDimitry Andric // Clone modules, the tester function will free them.
3700b57cec5SDimitry Andric std::unique_ptr<Module> TOLEBackup =
3710b57cec5SDimitry Andric CloneModule(*ToOptimizeLoopExtracted, VMap);
3720b57cec5SDimitry Andric std::unique_ptr<Module> TNOBackup = CloneModule(*ToNotOptimize, VMap);
3730b57cec5SDimitry Andric
3740b57cec5SDimitry Andric for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
3750b57cec5SDimitry Andric MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]);
3760b57cec5SDimitry Andric
3770b57cec5SDimitry Andric Expected<bool> Result = TestFn(BD, std::move(ToOptimizeLoopExtracted),
3780b57cec5SDimitry Andric std::move(ToNotOptimize));
3790b57cec5SDimitry Andric if (Error E = Result.takeError())
3800b57cec5SDimitry Andric return std::move(E);
3810b57cec5SDimitry Andric
3820b57cec5SDimitry Andric ToOptimizeLoopExtracted = std::move(TOLEBackup);
3830b57cec5SDimitry Andric ToNotOptimize = std::move(TNOBackup);
3840b57cec5SDimitry Andric
3850b57cec5SDimitry Andric if (!*Result) {
3860b57cec5SDimitry Andric outs() << "*** Loop extraction masked the problem. Undoing.\n";
3870b57cec5SDimitry Andric // If the program is not still broken, then loop extraction did something
3880b57cec5SDimitry Andric // that masked the error. Stop loop extraction now.
3890b57cec5SDimitry Andric
3900b57cec5SDimitry Andric std::vector<std::pair<std::string, FunctionType *>> MisCompFunctions;
3910b57cec5SDimitry Andric for (Function *F : MiscompiledFunctions) {
3925ffd83dbSDimitry Andric MisCompFunctions.emplace_back(std::string(F->getName()),
3935ffd83dbSDimitry Andric F->getFunctionType());
3940b57cec5SDimitry Andric }
3950b57cec5SDimitry Andric
3960b57cec5SDimitry Andric if (Linker::linkModules(*ToNotOptimize,
3970b57cec5SDimitry Andric std::move(ToOptimizeLoopExtracted)))
3980b57cec5SDimitry Andric exit(1);
3990b57cec5SDimitry Andric
4000b57cec5SDimitry Andric MiscompiledFunctions.clear();
4010b57cec5SDimitry Andric for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
4020b57cec5SDimitry Andric Function *NewF = ToNotOptimize->getFunction(MisCompFunctions[i].first);
4030b57cec5SDimitry Andric
4040b57cec5SDimitry Andric assert(NewF && "Function not found??");
4050b57cec5SDimitry Andric MiscompiledFunctions.push_back(NewF);
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric
4080b57cec5SDimitry Andric BD.setNewProgram(std::move(ToNotOptimize));
4090b57cec5SDimitry Andric return MadeChange;
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric
4120b57cec5SDimitry Andric outs() << "*** Loop extraction successful!\n";
4130b57cec5SDimitry Andric
4140b57cec5SDimitry Andric std::vector<std::pair<std::string, FunctionType *>> MisCompFunctions;
4150b57cec5SDimitry Andric for (Module::iterator I = ToOptimizeLoopExtracted->begin(),
4160b57cec5SDimitry Andric E = ToOptimizeLoopExtracted->end();
4170b57cec5SDimitry Andric I != E; ++I)
4180b57cec5SDimitry Andric if (!I->isDeclaration())
4195ffd83dbSDimitry Andric MisCompFunctions.emplace_back(std::string(I->getName()),
4205ffd83dbSDimitry Andric I->getFunctionType());
4210b57cec5SDimitry Andric
4220b57cec5SDimitry Andric // Okay, great! Now we know that we extracted a loop and that loop
4230b57cec5SDimitry Andric // extraction both didn't break the program, and didn't mask the problem.
4240b57cec5SDimitry Andric // Replace the current program with the loop extracted version, and try to
4250b57cec5SDimitry Andric // extract another loop.
4260b57cec5SDimitry Andric if (Linker::linkModules(*ToNotOptimize, std::move(ToOptimizeLoopExtracted)))
4270b57cec5SDimitry Andric exit(1);
4280b57cec5SDimitry Andric
4290b57cec5SDimitry Andric // All of the Function*'s in the MiscompiledFunctions list are in the old
4300b57cec5SDimitry Andric // module. Update this list to include all of the functions in the
4310b57cec5SDimitry Andric // optimized and loop extracted module.
4320b57cec5SDimitry Andric MiscompiledFunctions.clear();
4330b57cec5SDimitry Andric for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
4340b57cec5SDimitry Andric Function *NewF = ToNotOptimize->getFunction(MisCompFunctions[i].first);
4350b57cec5SDimitry Andric
4360b57cec5SDimitry Andric assert(NewF && "Function not found??");
4370b57cec5SDimitry Andric MiscompiledFunctions.push_back(NewF);
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric
4400b57cec5SDimitry Andric BD.setNewProgram(std::move(ToNotOptimize));
4410b57cec5SDimitry Andric MadeChange = true;
4420b57cec5SDimitry Andric }
4430b57cec5SDimitry Andric }
4440b57cec5SDimitry Andric
4450b57cec5SDimitry Andric namespace {
4460b57cec5SDimitry Andric class ReduceMiscompiledBlocks : public ListReducer<BasicBlock *> {
4470b57cec5SDimitry Andric BugDriver &BD;
4480b57cec5SDimitry Andric Expected<bool> (*TestFn)(BugDriver &, std::unique_ptr<Module>,
4490b57cec5SDimitry Andric std::unique_ptr<Module>);
4500b57cec5SDimitry Andric std::vector<Function *> FunctionsBeingTested;
4510b57cec5SDimitry Andric
4520b57cec5SDimitry Andric public:
ReduceMiscompiledBlocks(BugDriver & bd,Expected<bool> (* F)(BugDriver &,std::unique_ptr<Module>,std::unique_ptr<Module>),const std::vector<Function * > & Fns)4530b57cec5SDimitry Andric ReduceMiscompiledBlocks(BugDriver &bd,
4540b57cec5SDimitry Andric Expected<bool> (*F)(BugDriver &,
4550b57cec5SDimitry Andric std::unique_ptr<Module>,
4560b57cec5SDimitry Andric std::unique_ptr<Module>),
4570b57cec5SDimitry Andric const std::vector<Function *> &Fns)
4580b57cec5SDimitry Andric : BD(bd), TestFn(F), FunctionsBeingTested(Fns) {}
4590b57cec5SDimitry Andric
doTest(std::vector<BasicBlock * > & Prefix,std::vector<BasicBlock * > & Suffix)4600b57cec5SDimitry Andric Expected<TestResult> doTest(std::vector<BasicBlock *> &Prefix,
4610b57cec5SDimitry Andric std::vector<BasicBlock *> &Suffix) override {
4620b57cec5SDimitry Andric if (!Suffix.empty()) {
4630b57cec5SDimitry Andric Expected<bool> Ret = TestFuncs(Suffix);
4640b57cec5SDimitry Andric if (Error E = Ret.takeError())
4650b57cec5SDimitry Andric return std::move(E);
4660b57cec5SDimitry Andric if (*Ret)
4670b57cec5SDimitry Andric return KeepSuffix;
4680b57cec5SDimitry Andric }
4690b57cec5SDimitry Andric if (!Prefix.empty()) {
4700b57cec5SDimitry Andric Expected<bool> Ret = TestFuncs(Prefix);
4710b57cec5SDimitry Andric if (Error E = Ret.takeError())
4720b57cec5SDimitry Andric return std::move(E);
4730b57cec5SDimitry Andric if (*Ret)
4740b57cec5SDimitry Andric return KeepPrefix;
4750b57cec5SDimitry Andric }
4760b57cec5SDimitry Andric return NoFailure;
4770b57cec5SDimitry Andric }
4780b57cec5SDimitry Andric
4790b57cec5SDimitry Andric Expected<bool> TestFuncs(const std::vector<BasicBlock *> &BBs);
4800b57cec5SDimitry Andric };
4810b57cec5SDimitry Andric } // end anonymous namespace
4820b57cec5SDimitry Andric
4830b57cec5SDimitry Andric /// TestFuncs - Extract all blocks for the miscompiled functions except for the
4840b57cec5SDimitry Andric /// specified blocks. If the problem still exists, return true.
4850b57cec5SDimitry Andric ///
4860b57cec5SDimitry Andric Expected<bool>
TestFuncs(const std::vector<BasicBlock * > & BBs)4870b57cec5SDimitry Andric ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock *> &BBs) {
4880b57cec5SDimitry Andric // Test to see if the function is misoptimized if we ONLY run it on the
4890b57cec5SDimitry Andric // functions listed in Funcs.
4900b57cec5SDimitry Andric outs() << "Checking to see if the program is misoptimized when all ";
4910b57cec5SDimitry Andric if (!BBs.empty()) {
4920b57cec5SDimitry Andric outs() << "but these " << BBs.size() << " blocks are extracted: ";
4930b57cec5SDimitry Andric for (unsigned i = 0, e = BBs.size() < 10 ? BBs.size() : 10; i != e; ++i)
4940b57cec5SDimitry Andric outs() << BBs[i]->getName() << " ";
4950b57cec5SDimitry Andric if (BBs.size() > 10)
4960b57cec5SDimitry Andric outs() << "...";
4970b57cec5SDimitry Andric } else {
4980b57cec5SDimitry Andric outs() << "blocks are extracted.";
4990b57cec5SDimitry Andric }
5000b57cec5SDimitry Andric outs() << '\n';
5010b57cec5SDimitry Andric
5020b57cec5SDimitry Andric // Split the module into the two halves of the program we want.
5030b57cec5SDimitry Andric ValueToValueMapTy VMap;
5040b57cec5SDimitry Andric std::unique_ptr<Module> Clone = CloneModule(BD.getProgram(), VMap);
5050b57cec5SDimitry Andric std::unique_ptr<Module> Orig = BD.swapProgramIn(std::move(Clone));
5060b57cec5SDimitry Andric std::vector<Function *> FuncsOnClone;
5070b57cec5SDimitry Andric std::vector<BasicBlock *> BBsOnClone;
5080b57cec5SDimitry Andric for (unsigned i = 0, e = FunctionsBeingTested.size(); i != e; ++i) {
5090b57cec5SDimitry Andric Function *F = cast<Function>(VMap[FunctionsBeingTested[i]]);
5100b57cec5SDimitry Andric FuncsOnClone.push_back(F);
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric for (unsigned i = 0, e = BBs.size(); i != e; ++i) {
5130b57cec5SDimitry Andric BasicBlock *BB = cast<BasicBlock>(VMap[BBs[i]]);
5140b57cec5SDimitry Andric BBsOnClone.push_back(BB);
5150b57cec5SDimitry Andric }
5160b57cec5SDimitry Andric VMap.clear();
5170b57cec5SDimitry Andric
5180b57cec5SDimitry Andric std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap);
5190b57cec5SDimitry Andric std::unique_ptr<Module> ToOptimize =
5200b57cec5SDimitry Andric SplitFunctionsOutOfModule(ToNotOptimize.get(), FuncsOnClone, VMap);
5210b57cec5SDimitry Andric
5220b57cec5SDimitry Andric // Try the extraction. If it doesn't work, then the block extractor crashed
5230b57cec5SDimitry Andric // or something, in which case bugpoint can't chase down this possibility.
5240b57cec5SDimitry Andric if (std::unique_ptr<Module> New =
5250b57cec5SDimitry Andric BD.extractMappedBlocksFromModule(BBsOnClone, ToOptimize.get())) {
5260b57cec5SDimitry Andric Expected<bool> Ret = TestFn(BD, std::move(New), std::move(ToNotOptimize));
5270b57cec5SDimitry Andric BD.setNewProgram(std::move(Orig));
5280b57cec5SDimitry Andric return Ret;
5290b57cec5SDimitry Andric }
5300b57cec5SDimitry Andric BD.setNewProgram(std::move(Orig));
5310b57cec5SDimitry Andric return false;
5320b57cec5SDimitry Andric }
5330b57cec5SDimitry Andric
5340b57cec5SDimitry Andric /// Given a reduced list of functions that still expose the bug, extract as many
5350b57cec5SDimitry Andric /// basic blocks from the region as possible without obscuring the bug.
5360b57cec5SDimitry Andric ///
5370b57cec5SDimitry Andric static Expected<bool>
ExtractBlocks(BugDriver & BD,Expected<bool> (* TestFn)(BugDriver &,std::unique_ptr<Module>,std::unique_ptr<Module>),std::vector<Function * > & MiscompiledFunctions)5380b57cec5SDimitry Andric ExtractBlocks(BugDriver &BD,
5390b57cec5SDimitry Andric Expected<bool> (*TestFn)(BugDriver &, std::unique_ptr<Module>,
5400b57cec5SDimitry Andric std::unique_ptr<Module>),
5410b57cec5SDimitry Andric std::vector<Function *> &MiscompiledFunctions) {
5420b57cec5SDimitry Andric if (BugpointIsInterrupted)
5430b57cec5SDimitry Andric return false;
5440b57cec5SDimitry Andric
5450b57cec5SDimitry Andric std::vector<BasicBlock *> Blocks;
5460b57cec5SDimitry Andric for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
5470b57cec5SDimitry Andric for (BasicBlock &BB : *MiscompiledFunctions[i])
5480b57cec5SDimitry Andric Blocks.push_back(&BB);
5490b57cec5SDimitry Andric
5500b57cec5SDimitry Andric // Use the list reducer to identify blocks that can be extracted without
5510b57cec5SDimitry Andric // obscuring the bug. The Blocks list will end up containing blocks that must
5520b57cec5SDimitry Andric // be retained from the original program.
5530b57cec5SDimitry Andric unsigned OldSize = Blocks.size();
5540b57cec5SDimitry Andric
5550b57cec5SDimitry Andric // Check to see if all blocks are extractible first.
5560b57cec5SDimitry Andric Expected<bool> Ret = ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions)
5570b57cec5SDimitry Andric .TestFuncs(std::vector<BasicBlock *>());
5580b57cec5SDimitry Andric if (Error E = Ret.takeError())
5590b57cec5SDimitry Andric return std::move(E);
5600b57cec5SDimitry Andric if (*Ret) {
5610b57cec5SDimitry Andric Blocks.clear();
5620b57cec5SDimitry Andric } else {
5630b57cec5SDimitry Andric Expected<bool> Ret =
5640b57cec5SDimitry Andric ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions)
5650b57cec5SDimitry Andric .reduceList(Blocks);
5660b57cec5SDimitry Andric if (Error E = Ret.takeError())
5670b57cec5SDimitry Andric return std::move(E);
5680b57cec5SDimitry Andric if (Blocks.size() == OldSize)
5690b57cec5SDimitry Andric return false;
5700b57cec5SDimitry Andric }
5710b57cec5SDimitry Andric
5720b57cec5SDimitry Andric ValueToValueMapTy VMap;
5730b57cec5SDimitry Andric std::unique_ptr<Module> ProgClone = CloneModule(BD.getProgram(), VMap);
5740b57cec5SDimitry Andric std::unique_ptr<Module> ToExtract =
5750b57cec5SDimitry Andric SplitFunctionsOutOfModule(ProgClone.get(), MiscompiledFunctions, VMap);
5760b57cec5SDimitry Andric std::unique_ptr<Module> Extracted =
5770b57cec5SDimitry Andric BD.extractMappedBlocksFromModule(Blocks, ToExtract.get());
5780b57cec5SDimitry Andric if (!Extracted) {
5790b57cec5SDimitry Andric // Weird, extraction should have worked.
5800b57cec5SDimitry Andric errs() << "Nondeterministic problem extracting blocks??\n";
5810b57cec5SDimitry Andric return false;
5820b57cec5SDimitry Andric }
5830b57cec5SDimitry Andric
5840b57cec5SDimitry Andric // Otherwise, block extraction succeeded. Link the two program fragments back
5850b57cec5SDimitry Andric // together.
5860b57cec5SDimitry Andric
5870b57cec5SDimitry Andric std::vector<std::pair<std::string, FunctionType *>> MisCompFunctions;
5880b57cec5SDimitry Andric for (Module::iterator I = Extracted->begin(), E = Extracted->end(); I != E;
5890b57cec5SDimitry Andric ++I)
5900b57cec5SDimitry Andric if (!I->isDeclaration())
5915ffd83dbSDimitry Andric MisCompFunctions.emplace_back(std::string(I->getName()),
5925ffd83dbSDimitry Andric I->getFunctionType());
5930b57cec5SDimitry Andric
5940b57cec5SDimitry Andric if (Linker::linkModules(*ProgClone, std::move(Extracted)))
5950b57cec5SDimitry Andric exit(1);
5960b57cec5SDimitry Andric
5970b57cec5SDimitry Andric // Update the list of miscompiled functions.
5980b57cec5SDimitry Andric MiscompiledFunctions.clear();
5990b57cec5SDimitry Andric
6000b57cec5SDimitry Andric for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
6010b57cec5SDimitry Andric Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first);
6020b57cec5SDimitry Andric assert(NewF && "Function not found??");
6030b57cec5SDimitry Andric MiscompiledFunctions.push_back(NewF);
6040b57cec5SDimitry Andric }
6050b57cec5SDimitry Andric
6060b57cec5SDimitry Andric // Set the new program and delete the old one.
6070b57cec5SDimitry Andric BD.setNewProgram(std::move(ProgClone));
6080b57cec5SDimitry Andric
6090b57cec5SDimitry Andric return true;
6100b57cec5SDimitry Andric }
6110b57cec5SDimitry Andric
6120b57cec5SDimitry Andric /// This is a generic driver to narrow down miscompilations, either in an
6130b57cec5SDimitry Andric /// optimization or a code generator.
6140b57cec5SDimitry Andric ///
DebugAMiscompilation(BugDriver & BD,Expected<bool> (* TestFn)(BugDriver &,std::unique_ptr<Module>,std::unique_ptr<Module>))6150b57cec5SDimitry Andric static Expected<std::vector<Function *>> DebugAMiscompilation(
6160b57cec5SDimitry Andric BugDriver &BD,
6170b57cec5SDimitry Andric Expected<bool> (*TestFn)(BugDriver &, std::unique_ptr<Module>,
6180b57cec5SDimitry Andric std::unique_ptr<Module>)) {
6190b57cec5SDimitry Andric // Okay, now that we have reduced the list of passes which are causing the
6200b57cec5SDimitry Andric // failure, see if we can pin down which functions are being
6210b57cec5SDimitry Andric // miscompiled... first build a list of all of the non-external functions in
6220b57cec5SDimitry Andric // the program.
6230b57cec5SDimitry Andric std::vector<Function *> MiscompiledFunctions;
6240b57cec5SDimitry Andric Module &Prog = BD.getProgram();
6250b57cec5SDimitry Andric for (Function &F : Prog)
6260b57cec5SDimitry Andric if (!F.isDeclaration())
6270b57cec5SDimitry Andric MiscompiledFunctions.push_back(&F);
6280b57cec5SDimitry Andric
6290b57cec5SDimitry Andric // Do the reduction...
6300b57cec5SDimitry Andric if (!BugpointIsInterrupted) {
6310b57cec5SDimitry Andric Expected<bool> Ret = ReduceMiscompilingFunctions(BD, TestFn)
6320b57cec5SDimitry Andric .reduceList(MiscompiledFunctions);
6330b57cec5SDimitry Andric if (Error E = Ret.takeError()) {
6340b57cec5SDimitry Andric errs() << "\n***Cannot reduce functions: ";
6350b57cec5SDimitry Andric return std::move(E);
6360b57cec5SDimitry Andric }
6370b57cec5SDimitry Andric }
6380b57cec5SDimitry Andric outs() << "\n*** The following function"
6390b57cec5SDimitry Andric << (MiscompiledFunctions.size() == 1 ? " is" : "s are")
6400b57cec5SDimitry Andric << " being miscompiled: ";
6410b57cec5SDimitry Andric PrintFunctionList(MiscompiledFunctions);
6420b57cec5SDimitry Andric outs() << '\n';
6430b57cec5SDimitry Andric
6440b57cec5SDimitry Andric // See if we can rip any loops out of the miscompiled functions and still
6450b57cec5SDimitry Andric // trigger the problem.
6460b57cec5SDimitry Andric
6470b57cec5SDimitry Andric if (!BugpointIsInterrupted && !DisableLoopExtraction) {
6480b57cec5SDimitry Andric Expected<bool> Ret = ExtractLoops(BD, TestFn, MiscompiledFunctions);
6490b57cec5SDimitry Andric if (Error E = Ret.takeError())
6500b57cec5SDimitry Andric return std::move(E);
6510b57cec5SDimitry Andric if (*Ret) {
6520b57cec5SDimitry Andric // Okay, we extracted some loops and the problem still appears. See if
6530b57cec5SDimitry Andric // we can eliminate some of the created functions from being candidates.
6540b57cec5SDimitry Andric DisambiguateGlobalSymbols(BD.getProgram());
6550b57cec5SDimitry Andric
6560b57cec5SDimitry Andric // Do the reduction...
6570b57cec5SDimitry Andric if (!BugpointIsInterrupted)
6580b57cec5SDimitry Andric Ret = ReduceMiscompilingFunctions(BD, TestFn)
6590b57cec5SDimitry Andric .reduceList(MiscompiledFunctions);
6600b57cec5SDimitry Andric if (Error E = Ret.takeError())
6610b57cec5SDimitry Andric return std::move(E);
6620b57cec5SDimitry Andric
6630b57cec5SDimitry Andric outs() << "\n*** The following function"
6640b57cec5SDimitry Andric << (MiscompiledFunctions.size() == 1 ? " is" : "s are")
6650b57cec5SDimitry Andric << " being miscompiled: ";
6660b57cec5SDimitry Andric PrintFunctionList(MiscompiledFunctions);
6670b57cec5SDimitry Andric outs() << '\n';
6680b57cec5SDimitry Andric }
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric
6710b57cec5SDimitry Andric if (!BugpointIsInterrupted && !DisableBlockExtraction) {
6720b57cec5SDimitry Andric Expected<bool> Ret = ExtractBlocks(BD, TestFn, MiscompiledFunctions);
6730b57cec5SDimitry Andric if (Error E = Ret.takeError())
6740b57cec5SDimitry Andric return std::move(E);
6750b57cec5SDimitry Andric if (*Ret) {
6760b57cec5SDimitry Andric // Okay, we extracted some blocks and the problem still appears. See if
6770b57cec5SDimitry Andric // we can eliminate some of the created functions from being candidates.
6780b57cec5SDimitry Andric DisambiguateGlobalSymbols(BD.getProgram());
6790b57cec5SDimitry Andric
6800b57cec5SDimitry Andric // Do the reduction...
6810b57cec5SDimitry Andric Ret = ReduceMiscompilingFunctions(BD, TestFn)
6820b57cec5SDimitry Andric .reduceList(MiscompiledFunctions);
6830b57cec5SDimitry Andric if (Error E = Ret.takeError())
6840b57cec5SDimitry Andric return std::move(E);
6850b57cec5SDimitry Andric
6860b57cec5SDimitry Andric outs() << "\n*** The following function"
6870b57cec5SDimitry Andric << (MiscompiledFunctions.size() == 1 ? " is" : "s are")
6880b57cec5SDimitry Andric << " being miscompiled: ";
6890b57cec5SDimitry Andric PrintFunctionList(MiscompiledFunctions);
6900b57cec5SDimitry Andric outs() << '\n';
6910b57cec5SDimitry Andric }
6920b57cec5SDimitry Andric }
6930b57cec5SDimitry Andric
6940b57cec5SDimitry Andric return MiscompiledFunctions;
6950b57cec5SDimitry Andric }
6960b57cec5SDimitry Andric
6970b57cec5SDimitry Andric /// This is the predicate function used to check to see if the "Test" portion of
6980b57cec5SDimitry Andric /// the program is misoptimized. If so, return true. In any case, both module
6990b57cec5SDimitry Andric /// arguments are deleted.
7000b57cec5SDimitry Andric ///
TestOptimizer(BugDriver & BD,std::unique_ptr<Module> Test,std::unique_ptr<Module> Safe)7010b57cec5SDimitry Andric static Expected<bool> TestOptimizer(BugDriver &BD, std::unique_ptr<Module> Test,
7020b57cec5SDimitry Andric std::unique_ptr<Module> Safe) {
7030b57cec5SDimitry Andric // Run the optimization passes on ToOptimize, producing a transformed version
7040b57cec5SDimitry Andric // of the functions being tested.
7050b57cec5SDimitry Andric outs() << " Optimizing functions being tested: ";
7060b57cec5SDimitry Andric std::unique_ptr<Module> Optimized =
7070b57cec5SDimitry Andric BD.runPassesOn(Test.get(), BD.getPassesToRun());
7080b57cec5SDimitry Andric if (!Optimized) {
7090b57cec5SDimitry Andric errs() << " Error running this sequence of passes"
7100b57cec5SDimitry Andric << " on the input program!\n";
7110b57cec5SDimitry Andric BD.EmitProgressBitcode(*Test, "pass-error", false);
7120b57cec5SDimitry Andric BD.setNewProgram(std::move(Test));
7130b57cec5SDimitry Andric if (Error E = BD.debugOptimizerCrash())
7140b57cec5SDimitry Andric return std::move(E);
7150b57cec5SDimitry Andric return false;
7160b57cec5SDimitry Andric }
7170b57cec5SDimitry Andric outs() << "done.\n";
7180b57cec5SDimitry Andric
7190b57cec5SDimitry Andric outs() << " Checking to see if the merged program executes correctly: ";
7200b57cec5SDimitry Andric bool Broken;
7210b57cec5SDimitry Andric auto Result = testMergedProgram(BD, *Optimized, *Safe, Broken);
7220b57cec5SDimitry Andric if (Error E = Result.takeError())
7230b57cec5SDimitry Andric return std::move(E);
7240b57cec5SDimitry Andric if (auto New = std::move(*Result)) {
7250b57cec5SDimitry Andric outs() << (Broken ? " nope.\n" : " yup.\n");
7260b57cec5SDimitry Andric // Delete the original and set the new program.
7270b57cec5SDimitry Andric BD.setNewProgram(std::move(New));
7280b57cec5SDimitry Andric }
7290b57cec5SDimitry Andric return Broken;
7300b57cec5SDimitry Andric }
7310b57cec5SDimitry Andric
7320b57cec5SDimitry Andric /// debugMiscompilation - This method is used when the passes selected are not
7330b57cec5SDimitry Andric /// crashing, but the generated output is semantically different from the
7340b57cec5SDimitry Andric /// input.
7350b57cec5SDimitry Andric ///
debugMiscompilation()7360b57cec5SDimitry Andric Error BugDriver::debugMiscompilation() {
7370b57cec5SDimitry Andric // Make sure something was miscompiled...
7380b57cec5SDimitry Andric if (!BugpointIsInterrupted) {
7390b57cec5SDimitry Andric Expected<bool> Result =
7400b57cec5SDimitry Andric ReduceMiscompilingPasses(*this).reduceList(PassesToRun);
7410b57cec5SDimitry Andric if (Error E = Result.takeError())
7420b57cec5SDimitry Andric return E;
7430b57cec5SDimitry Andric if (!*Result)
7440b57cec5SDimitry Andric return make_error<StringError>(
7450b57cec5SDimitry Andric "*** Optimized program matches reference output! No problem"
7460b57cec5SDimitry Andric " detected...\nbugpoint can't help you with your problem!\n",
7470b57cec5SDimitry Andric inconvertibleErrorCode());
7480b57cec5SDimitry Andric }
7490b57cec5SDimitry Andric
7500b57cec5SDimitry Andric outs() << "\n*** Found miscompiling pass"
7510b57cec5SDimitry Andric << (getPassesToRun().size() == 1 ? "" : "es") << ": "
7520b57cec5SDimitry Andric << getPassesString(getPassesToRun()) << '\n';
7530b57cec5SDimitry Andric EmitProgressBitcode(*Program, "passinput");
7540b57cec5SDimitry Andric
7550b57cec5SDimitry Andric Expected<std::vector<Function *>> MiscompiledFunctions =
7560b57cec5SDimitry Andric DebugAMiscompilation(*this, TestOptimizer);
7570b57cec5SDimitry Andric if (Error E = MiscompiledFunctions.takeError())
7580b57cec5SDimitry Andric return E;
7590b57cec5SDimitry Andric
7600b57cec5SDimitry Andric // Output a bunch of bitcode files for the user...
7610b57cec5SDimitry Andric outs() << "Outputting reduced bitcode files which expose the problem:\n";
7620b57cec5SDimitry Andric ValueToValueMapTy VMap;
7630b57cec5SDimitry Andric Module *ToNotOptimize = CloneModule(getProgram(), VMap).release();
7640b57cec5SDimitry Andric Module *ToOptimize =
7650b57cec5SDimitry Andric SplitFunctionsOutOfModule(ToNotOptimize, *MiscompiledFunctions, VMap)
7660b57cec5SDimitry Andric .release();
7670b57cec5SDimitry Andric
7680b57cec5SDimitry Andric outs() << " Non-optimized portion: ";
7690b57cec5SDimitry Andric EmitProgressBitcode(*ToNotOptimize, "tonotoptimize", true);
7700b57cec5SDimitry Andric delete ToNotOptimize; // Delete hacked module.
7710b57cec5SDimitry Andric
7720b57cec5SDimitry Andric outs() << " Portion that is input to optimizer: ";
7730b57cec5SDimitry Andric EmitProgressBitcode(*ToOptimize, "tooptimize");
7740b57cec5SDimitry Andric delete ToOptimize; // Delete hacked module.
7750b57cec5SDimitry Andric
7760b57cec5SDimitry Andric return Error::success();
7770b57cec5SDimitry Andric }
7780b57cec5SDimitry Andric
7790b57cec5SDimitry Andric /// Get the specified modules ready for code generator testing.
7800b57cec5SDimitry Andric ///
7810b57cec5SDimitry Andric static std::unique_ptr<Module>
CleanupAndPrepareModules(BugDriver & BD,std::unique_ptr<Module> Test,Module * Safe)7820b57cec5SDimitry Andric CleanupAndPrepareModules(BugDriver &BD, std::unique_ptr<Module> Test,
7830b57cec5SDimitry Andric Module *Safe) {
7840b57cec5SDimitry Andric // Clean up the modules, removing extra cruft that we don't need anymore...
7850b57cec5SDimitry Andric Test = BD.performFinalCleanups(std::move(Test));
7860b57cec5SDimitry Andric
7870b57cec5SDimitry Andric // If we are executing the JIT, we have several nasty issues to take care of.
7880b57cec5SDimitry Andric if (!BD.isExecutingJIT())
7890b57cec5SDimitry Andric return Test;
7900b57cec5SDimitry Andric
7910b57cec5SDimitry Andric // First, if the main function is in the Safe module, we must add a stub to
7920b57cec5SDimitry Andric // the Test module to call into it. Thus, we create a new function `main'
7930b57cec5SDimitry Andric // which just calls the old one.
7940b57cec5SDimitry Andric if (Function *oldMain = Safe->getFunction("main"))
7950b57cec5SDimitry Andric if (!oldMain->isDeclaration()) {
7960b57cec5SDimitry Andric // Rename it
7970b57cec5SDimitry Andric oldMain->setName("llvm_bugpoint_old_main");
7980b57cec5SDimitry Andric // Create a NEW `main' function with same type in the test module.
7990b57cec5SDimitry Andric Function *newMain =
8000b57cec5SDimitry Andric Function::Create(oldMain->getFunctionType(),
8010b57cec5SDimitry Andric GlobalValue::ExternalLinkage, "main", Test.get());
8020b57cec5SDimitry Andric // Create an `oldmain' prototype in the test module, which will
8030b57cec5SDimitry Andric // corresponds to the real main function in the same module.
8040b57cec5SDimitry Andric Function *oldMainProto = Function::Create(oldMain->getFunctionType(),
8050b57cec5SDimitry Andric GlobalValue::ExternalLinkage,
8060b57cec5SDimitry Andric oldMain->getName(), Test.get());
8070b57cec5SDimitry Andric // Set up and remember the argument list for the main function.
8080b57cec5SDimitry Andric std::vector<Value *> args;
8090b57cec5SDimitry Andric for (Function::arg_iterator I = newMain->arg_begin(),
8100b57cec5SDimitry Andric E = newMain->arg_end(),
8110b57cec5SDimitry Andric OI = oldMain->arg_begin();
8120b57cec5SDimitry Andric I != E; ++I, ++OI) {
8130b57cec5SDimitry Andric I->setName(OI->getName()); // Copy argument names from oldMain
8140b57cec5SDimitry Andric args.push_back(&*I);
8150b57cec5SDimitry Andric }
8160b57cec5SDimitry Andric
8170b57cec5SDimitry Andric // Call the old main function and return its result
8180b57cec5SDimitry Andric BasicBlock *BB = BasicBlock::Create(Safe->getContext(), "entry", newMain);
8190b57cec5SDimitry Andric CallInst *call = CallInst::Create(oldMainProto, args, "", BB);
8200b57cec5SDimitry Andric
8210b57cec5SDimitry Andric // If the type of old function wasn't void, return value of call
8220b57cec5SDimitry Andric ReturnInst::Create(Safe->getContext(), call, BB);
8230b57cec5SDimitry Andric }
8240b57cec5SDimitry Andric
8250b57cec5SDimitry Andric // The second nasty issue we must deal with in the JIT is that the Safe
8260b57cec5SDimitry Andric // module cannot directly reference any functions defined in the test
8270b57cec5SDimitry Andric // module. Instead, we use a JIT API call to dynamically resolve the
8280b57cec5SDimitry Andric // symbol.
8290b57cec5SDimitry Andric
8300b57cec5SDimitry Andric // Add the resolver to the Safe module.
8310b57cec5SDimitry Andric // Prototype: void *getPointerToNamedFunction(const char* Name)
8320b57cec5SDimitry Andric FunctionCallee resolverFunc = Safe->getOrInsertFunction(
8335f757f3fSDimitry Andric "getPointerToNamedFunction", PointerType::getUnqual(Safe->getContext()),
8345f757f3fSDimitry Andric PointerType::getUnqual(Safe->getContext()));
8350b57cec5SDimitry Andric
8360b57cec5SDimitry Andric // Use the function we just added to get addresses of functions we need.
8370b57cec5SDimitry Andric for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) {
8380b57cec5SDimitry Andric if (F->isDeclaration() && !F->use_empty() &&
8390b57cec5SDimitry Andric &*F != resolverFunc.getCallee() &&
8400b57cec5SDimitry Andric !F->isIntrinsic() /* ignore intrinsics */) {
8410b57cec5SDimitry Andric Function *TestFn = Test->getFunction(F->getName());
8420b57cec5SDimitry Andric
8430b57cec5SDimitry Andric // Don't forward functions which are external in the test module too.
8440b57cec5SDimitry Andric if (TestFn && !TestFn->isDeclaration()) {
8450b57cec5SDimitry Andric // 1. Add a string constant with its name to the global file
8460b57cec5SDimitry Andric Constant *InitArray =
8470b57cec5SDimitry Andric ConstantDataArray::getString(F->getContext(), F->getName());
8480b57cec5SDimitry Andric GlobalVariable *funcName = new GlobalVariable(
8490b57cec5SDimitry Andric *Safe, InitArray->getType(), true /*isConstant*/,
8500b57cec5SDimitry Andric GlobalValue::InternalLinkage, InitArray, F->getName() + "_name");
8510b57cec5SDimitry Andric
8520b57cec5SDimitry Andric // 2. Use `GetElementPtr *funcName, 0, 0' to convert the string to an
8530b57cec5SDimitry Andric // sbyte* so it matches the signature of the resolver function.
8540b57cec5SDimitry Andric
8550b57cec5SDimitry Andric // GetElementPtr *funcName, ulong 0, ulong 0
8560b57cec5SDimitry Andric std::vector<Constant *> GEPargs(
8570b57cec5SDimitry Andric 2, Constant::getNullValue(Type::getInt32Ty(F->getContext())));
8580b57cec5SDimitry Andric Value *GEP = ConstantExpr::getGetElementPtr(InitArray->getType(),
8590b57cec5SDimitry Andric funcName, GEPargs);
8600b57cec5SDimitry Andric std::vector<Value *> ResolverArgs;
8610b57cec5SDimitry Andric ResolverArgs.push_back(GEP);
8620b57cec5SDimitry Andric
8630b57cec5SDimitry Andric // Rewrite uses of F in global initializers, etc. to uses of a wrapper
8640b57cec5SDimitry Andric // function that dynamically resolves the calls to F via our JIT API
8650b57cec5SDimitry Andric if (!F->use_empty()) {
8660b57cec5SDimitry Andric // Create a new global to hold the cached function pointer.
8670b57cec5SDimitry Andric Constant *NullPtr = ConstantPointerNull::get(F->getType());
8680b57cec5SDimitry Andric GlobalVariable *Cache = new GlobalVariable(
8690b57cec5SDimitry Andric *F->getParent(), F->getType(), false,
8700b57cec5SDimitry Andric GlobalValue::InternalLinkage, NullPtr, F->getName() + ".fpcache");
8710b57cec5SDimitry Andric
8720b57cec5SDimitry Andric // Construct a new stub function that will re-route calls to F
8730b57cec5SDimitry Andric FunctionType *FuncTy = F->getFunctionType();
8740b57cec5SDimitry Andric Function *FuncWrapper =
8750b57cec5SDimitry Andric Function::Create(FuncTy, GlobalValue::InternalLinkage,
8760b57cec5SDimitry Andric F->getName() + "_wrapper", F->getParent());
8770b57cec5SDimitry Andric BasicBlock *EntryBB =
8780b57cec5SDimitry Andric BasicBlock::Create(F->getContext(), "entry", FuncWrapper);
8790b57cec5SDimitry Andric BasicBlock *DoCallBB =
8800b57cec5SDimitry Andric BasicBlock::Create(F->getContext(), "usecache", FuncWrapper);
8810b57cec5SDimitry Andric BasicBlock *LookupBB =
8820b57cec5SDimitry Andric BasicBlock::Create(F->getContext(), "lookupfp", FuncWrapper);
8830b57cec5SDimitry Andric
8840b57cec5SDimitry Andric // Check to see if we already looked up the value.
8850b57cec5SDimitry Andric Value *CachedVal =
8860b57cec5SDimitry Andric new LoadInst(F->getType(), Cache, "fpcache", EntryBB);
887*0fca6ea1SDimitry Andric Value *IsNull = new ICmpInst(EntryBB, ICmpInst::ICMP_EQ, CachedVal,
8880b57cec5SDimitry Andric NullPtr, "isNull");
8890b57cec5SDimitry Andric BranchInst::Create(LookupBB, DoCallBB, IsNull, EntryBB);
8900b57cec5SDimitry Andric
8910b57cec5SDimitry Andric // Resolve the call to function F via the JIT API:
8920b57cec5SDimitry Andric //
8930b57cec5SDimitry Andric // call resolver(GetElementPtr...)
8940b57cec5SDimitry Andric CallInst *Resolver = CallInst::Create(resolverFunc, ResolverArgs,
8950b57cec5SDimitry Andric "resolver", LookupBB);
8960b57cec5SDimitry Andric
8970b57cec5SDimitry Andric // Cast the result from the resolver to correctly-typed function.
8980b57cec5SDimitry Andric CastInst *CastedResolver = new BitCastInst(
8990b57cec5SDimitry Andric Resolver, PointerType::getUnqual(F->getFunctionType()),
9000b57cec5SDimitry Andric "resolverCast", LookupBB);
9010b57cec5SDimitry Andric
9020b57cec5SDimitry Andric // Save the value in our cache.
9030b57cec5SDimitry Andric new StoreInst(CastedResolver, Cache, LookupBB);
9040b57cec5SDimitry Andric BranchInst::Create(DoCallBB, LookupBB);
9050b57cec5SDimitry Andric
9060b57cec5SDimitry Andric PHINode *FuncPtr =
9070b57cec5SDimitry Andric PHINode::Create(NullPtr->getType(), 2, "fp", DoCallBB);
9080b57cec5SDimitry Andric FuncPtr->addIncoming(CastedResolver, LookupBB);
9090b57cec5SDimitry Andric FuncPtr->addIncoming(CachedVal, EntryBB);
9100b57cec5SDimitry Andric
9110b57cec5SDimitry Andric // Save the argument list.
9120b57cec5SDimitry Andric std::vector<Value *> Args;
9130b57cec5SDimitry Andric for (Argument &A : FuncWrapper->args())
9140b57cec5SDimitry Andric Args.push_back(&A);
9150b57cec5SDimitry Andric
9160b57cec5SDimitry Andric // Pass on the arguments to the real function, return its result
9170b57cec5SDimitry Andric if (F->getReturnType()->isVoidTy()) {
9180b57cec5SDimitry Andric CallInst::Create(FuncTy, FuncPtr, Args, "", DoCallBB);
9190b57cec5SDimitry Andric ReturnInst::Create(F->getContext(), DoCallBB);
9200b57cec5SDimitry Andric } else {
9210b57cec5SDimitry Andric CallInst *Call =
9220b57cec5SDimitry Andric CallInst::Create(FuncTy, FuncPtr, Args, "retval", DoCallBB);
9230b57cec5SDimitry Andric ReturnInst::Create(F->getContext(), Call, DoCallBB);
9240b57cec5SDimitry Andric }
9250b57cec5SDimitry Andric
9260b57cec5SDimitry Andric // Use the wrapper function instead of the old function
9270b57cec5SDimitry Andric F->replaceAllUsesWith(FuncWrapper);
9280b57cec5SDimitry Andric }
9290b57cec5SDimitry Andric }
9300b57cec5SDimitry Andric }
9310b57cec5SDimitry Andric }
9320b57cec5SDimitry Andric
9330b57cec5SDimitry Andric if (verifyModule(*Test) || verifyModule(*Safe)) {
9340b57cec5SDimitry Andric errs() << "Bugpoint has a bug, which corrupted a module!!\n";
9350b57cec5SDimitry Andric abort();
9360b57cec5SDimitry Andric }
9370b57cec5SDimitry Andric
9380b57cec5SDimitry Andric return Test;
9390b57cec5SDimitry Andric }
9400b57cec5SDimitry Andric
9410b57cec5SDimitry Andric /// This is the predicate function used to check to see if the "Test" portion of
9420b57cec5SDimitry Andric /// the program is miscompiled by the code generator under test. If so, return
9430b57cec5SDimitry Andric /// true. In any case, both module arguments are deleted.
9440b57cec5SDimitry Andric ///
TestCodeGenerator(BugDriver & BD,std::unique_ptr<Module> Test,std::unique_ptr<Module> Safe)9450b57cec5SDimitry Andric static Expected<bool> TestCodeGenerator(BugDriver &BD,
9460b57cec5SDimitry Andric std::unique_ptr<Module> Test,
9470b57cec5SDimitry Andric std::unique_ptr<Module> Safe) {
9480b57cec5SDimitry Andric Test = CleanupAndPrepareModules(BD, std::move(Test), Safe.get());
9490b57cec5SDimitry Andric
9500b57cec5SDimitry Andric SmallString<128> TestModuleBC;
9510b57cec5SDimitry Andric int TestModuleFD;
9520b57cec5SDimitry Andric std::error_code EC = sys::fs::createTemporaryFile("bugpoint.test", "bc",
9530b57cec5SDimitry Andric TestModuleFD, TestModuleBC);
9540b57cec5SDimitry Andric if (EC) {
9550b57cec5SDimitry Andric errs() << BD.getToolName()
9560b57cec5SDimitry Andric << "Error making unique filename: " << EC.message() << "\n";
9570b57cec5SDimitry Andric exit(1);
9580b57cec5SDimitry Andric }
9597a6dacacSDimitry Andric if (BD.writeProgramToFile(std::string(TestModuleBC), TestModuleFD, *Test)) {
9600b57cec5SDimitry Andric errs() << "Error writing bitcode to `" << TestModuleBC.str()
9610b57cec5SDimitry Andric << "'\nExiting.";
9620b57cec5SDimitry Andric exit(1);
9630b57cec5SDimitry Andric }
9640b57cec5SDimitry Andric
9650b57cec5SDimitry Andric FileRemover TestModuleBCRemover(TestModuleBC.str(), !SaveTemps);
9660b57cec5SDimitry Andric
9670b57cec5SDimitry Andric // Make the shared library
9680b57cec5SDimitry Andric SmallString<128> SafeModuleBC;
9690b57cec5SDimitry Andric int SafeModuleFD;
9700b57cec5SDimitry Andric EC = sys::fs::createTemporaryFile("bugpoint.safe", "bc", SafeModuleFD,
9710b57cec5SDimitry Andric SafeModuleBC);
9720b57cec5SDimitry Andric if (EC) {
9730b57cec5SDimitry Andric errs() << BD.getToolName()
9740b57cec5SDimitry Andric << "Error making unique filename: " << EC.message() << "\n";
9750b57cec5SDimitry Andric exit(1);
9760b57cec5SDimitry Andric }
9770b57cec5SDimitry Andric
9787a6dacacSDimitry Andric if (BD.writeProgramToFile(std::string(SafeModuleBC), SafeModuleFD, *Safe)) {
9790b57cec5SDimitry Andric errs() << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting.";
9800b57cec5SDimitry Andric exit(1);
9810b57cec5SDimitry Andric }
9820b57cec5SDimitry Andric
9830b57cec5SDimitry Andric FileRemover SafeModuleBCRemover(SafeModuleBC.str(), !SaveTemps);
9840b57cec5SDimitry Andric
9850b57cec5SDimitry Andric Expected<std::string> SharedObject =
9867a6dacacSDimitry Andric BD.compileSharedObject(std::string(SafeModuleBC));
9870b57cec5SDimitry Andric if (Error E = SharedObject.takeError())
9880b57cec5SDimitry Andric return std::move(E);
9890b57cec5SDimitry Andric
9900b57cec5SDimitry Andric FileRemover SharedObjectRemover(*SharedObject, !SaveTemps);
9910b57cec5SDimitry Andric
9920b57cec5SDimitry Andric // Run the code generator on the `Test' code, loading the shared library.
9930b57cec5SDimitry Andric // The function returns whether or not the new output differs from reference.
9945ffd83dbSDimitry Andric Expected<bool> Result = BD.diffProgram(
9957a6dacacSDimitry Andric BD.getProgram(), std::string(TestModuleBC), *SharedObject, false);
9960b57cec5SDimitry Andric if (Error E = Result.takeError())
9970b57cec5SDimitry Andric return std::move(E);
9980b57cec5SDimitry Andric
9990b57cec5SDimitry Andric if (*Result)
10000b57cec5SDimitry Andric errs() << ": still failing!\n";
10010b57cec5SDimitry Andric else
10020b57cec5SDimitry Andric errs() << ": didn't fail.\n";
10030b57cec5SDimitry Andric
10040b57cec5SDimitry Andric return Result;
10050b57cec5SDimitry Andric }
10060b57cec5SDimitry Andric
10070b57cec5SDimitry Andric /// debugCodeGenerator - debug errors in LLC, LLI, or CBE.
10080b57cec5SDimitry Andric ///
debugCodeGenerator()10090b57cec5SDimitry Andric Error BugDriver::debugCodeGenerator() {
10100b57cec5SDimitry Andric if ((void *)SafeInterpreter == (void *)Interpreter) {
10110b57cec5SDimitry Andric Expected<std::string> Result =
10120b57cec5SDimitry Andric executeProgramSafely(*Program, "bugpoint.safe.out");
10130b57cec5SDimitry Andric if (Result) {
10140b57cec5SDimitry Andric outs() << "\n*** The \"safe\" i.e. 'known good' backend cannot match "
10150b57cec5SDimitry Andric << "the reference diff. This may be due to a\n front-end "
10160b57cec5SDimitry Andric << "bug or a bug in the original program, but this can also "
10170b57cec5SDimitry Andric << "happen if bugpoint isn't running the program with the "
10180b57cec5SDimitry Andric << "right flags or input.\n I left the result of executing "
10190b57cec5SDimitry Andric << "the program with the \"safe\" backend in this file for "
10200b57cec5SDimitry Andric << "you: '" << *Result << "'.\n";
10210b57cec5SDimitry Andric }
10220b57cec5SDimitry Andric return Error::success();
10230b57cec5SDimitry Andric }
10240b57cec5SDimitry Andric
10250b57cec5SDimitry Andric DisambiguateGlobalSymbols(*Program);
10260b57cec5SDimitry Andric
10270b57cec5SDimitry Andric Expected<std::vector<Function *>> Funcs =
10280b57cec5SDimitry Andric DebugAMiscompilation(*this, TestCodeGenerator);
10290b57cec5SDimitry Andric if (Error E = Funcs.takeError())
10300b57cec5SDimitry Andric return E;
10310b57cec5SDimitry Andric
10320b57cec5SDimitry Andric // Split the module into the two halves of the program we want.
10330b57cec5SDimitry Andric ValueToValueMapTy VMap;
10340b57cec5SDimitry Andric std::unique_ptr<Module> ToNotCodeGen = CloneModule(getProgram(), VMap);
10350b57cec5SDimitry Andric std::unique_ptr<Module> ToCodeGen =
10360b57cec5SDimitry Andric SplitFunctionsOutOfModule(ToNotCodeGen.get(), *Funcs, VMap);
10370b57cec5SDimitry Andric
10380b57cec5SDimitry Andric // Condition the modules
10390b57cec5SDimitry Andric ToCodeGen =
10400b57cec5SDimitry Andric CleanupAndPrepareModules(*this, std::move(ToCodeGen), ToNotCodeGen.get());
10410b57cec5SDimitry Andric
10420b57cec5SDimitry Andric SmallString<128> TestModuleBC;
10430b57cec5SDimitry Andric int TestModuleFD;
10440b57cec5SDimitry Andric std::error_code EC = sys::fs::createTemporaryFile("bugpoint.test", "bc",
10450b57cec5SDimitry Andric TestModuleFD, TestModuleBC);
10460b57cec5SDimitry Andric if (EC) {
10470b57cec5SDimitry Andric errs() << getToolName() << "Error making unique filename: " << EC.message()
10480b57cec5SDimitry Andric << "\n";
10490b57cec5SDimitry Andric exit(1);
10500b57cec5SDimitry Andric }
10510b57cec5SDimitry Andric
10527a6dacacSDimitry Andric if (writeProgramToFile(std::string(TestModuleBC), TestModuleFD, *ToCodeGen)) {
10530b57cec5SDimitry Andric errs() << "Error writing bitcode to `" << TestModuleBC << "'\nExiting.";
10540b57cec5SDimitry Andric exit(1);
10550b57cec5SDimitry Andric }
10560b57cec5SDimitry Andric
10570b57cec5SDimitry Andric // Make the shared library
10580b57cec5SDimitry Andric SmallString<128> SafeModuleBC;
10590b57cec5SDimitry Andric int SafeModuleFD;
10600b57cec5SDimitry Andric EC = sys::fs::createTemporaryFile("bugpoint.safe", "bc", SafeModuleFD,
10610b57cec5SDimitry Andric SafeModuleBC);
10620b57cec5SDimitry Andric if (EC) {
10630b57cec5SDimitry Andric errs() << getToolName() << "Error making unique filename: " << EC.message()
10640b57cec5SDimitry Andric << "\n";
10650b57cec5SDimitry Andric exit(1);
10660b57cec5SDimitry Andric }
10670b57cec5SDimitry Andric
10687a6dacacSDimitry Andric if (writeProgramToFile(std::string(SafeModuleBC), SafeModuleFD,
10695ffd83dbSDimitry Andric *ToNotCodeGen)) {
10700b57cec5SDimitry Andric errs() << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting.";
10710b57cec5SDimitry Andric exit(1);
10720b57cec5SDimitry Andric }
10735ffd83dbSDimitry Andric Expected<std::string> SharedObject =
10747a6dacacSDimitry Andric compileSharedObject(std::string(SafeModuleBC));
10750b57cec5SDimitry Andric if (Error E = SharedObject.takeError())
10760b57cec5SDimitry Andric return E;
10770b57cec5SDimitry Andric
10780b57cec5SDimitry Andric outs() << "You can reproduce the problem with the command line: \n";
10790b57cec5SDimitry Andric if (isExecutingJIT()) {
10800b57cec5SDimitry Andric outs() << " lli -load " << *SharedObject << " " << TestModuleBC;
10810b57cec5SDimitry Andric } else {
10820b57cec5SDimitry Andric outs() << " llc " << TestModuleBC << " -o " << TestModuleBC << ".s\n";
10830b57cec5SDimitry Andric outs() << " cc " << *SharedObject << " " << TestModuleBC.str() << ".s -o "
10840b57cec5SDimitry Andric << TestModuleBC << ".exe\n";
10850b57cec5SDimitry Andric outs() << " ./" << TestModuleBC << ".exe";
10860b57cec5SDimitry Andric }
10870b57cec5SDimitry Andric for (unsigned i = 0, e = InputArgv.size(); i != e; ++i)
10880b57cec5SDimitry Andric outs() << " " << InputArgv[i];
10890b57cec5SDimitry Andric outs() << '\n';
10900b57cec5SDimitry Andric outs() << "The shared object was created with:\n llc -march=c "
10910b57cec5SDimitry Andric << SafeModuleBC.str() << " -o temporary.c\n"
10920b57cec5SDimitry Andric << " cc -xc temporary.c -O2 -o " << *SharedObject;
10930b57cec5SDimitry Andric if (TargetTriple.getArch() == Triple::sparc)
10940b57cec5SDimitry Andric outs() << " -G"; // Compile a shared library, `-G' for Sparc
10950b57cec5SDimitry Andric else
10960b57cec5SDimitry Andric outs() << " -fPIC -shared"; // `-shared' for Linux/X86, maybe others
10970b57cec5SDimitry Andric
10980b57cec5SDimitry Andric outs() << " -fno-strict-aliasing\n";
10990b57cec5SDimitry Andric
11000b57cec5SDimitry Andric return Error::success();
11010b57cec5SDimitry Andric }
1102