//===- Miscompilation.cpp - Debug program miscompilations -----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements optimizer and code generation miscompilation debugging
// support.
//
//===----------------------------------------------------------------------===//
#include "BugDriver.h"
#include "ListReducer.h"
#include "ToolRunner.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Linker.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Config/config.h" // for HAVE_LINK_R
using namespace llvm;
namespace llvm {
extern cl::opt<std::string> OutputPrefix;
extern cl::list<std::string> InputArgv;
}
namespace {
static llvm::cl::opt<bool>
DisableLoopExtraction("disable-loop-extraction",
cl::desc("Don't extract loops when searching for miscompilations"),
cl::init(false));
static llvm::cl::opt<bool>
DisableBlockExtraction("disable-block-extraction",
cl::desc("Don't extract blocks when searching for miscompilations"),
cl::init(false));
class ReduceMiscompilingPasses : public ListReducer<std::string> {
BugDriver &BD;
public:
ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {}
virtual TestResult doTest(std::vector<std::string> &Prefix,
std::vector<std::string> &Suffix,
std::string &Error);
};
}
/// TestResult - After passes have been split into a test group and a control
/// group, see if they still break the program.
///
ReduceMiscompilingPasses::TestResult
ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix,
std::vector<std::string> &Suffix,
std::string &Error) {
// First, run the program with just the Suffix passes. If it is still broken
// with JUST the kept passes, discard the prefix passes.
outs() << "Checking to see if '" << getPassesString(Suffix)
<< "' compiles correctly: ";
std::string BitcodeResult;
if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false/*delete*/,
true/*quiet*/)) {
errs() << " Error running this sequence of passes"
<< " on the input program!\n";
BD.setPassesToRun(Suffix);
BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false);
exit(BD.debugOptimizerCrash());
}
// Check to see if the finished program matches the reference output...
bool Diff = BD.diffProgram(BD.getProgram(), BitcodeResult, "",
true /*delete bitcode*/, &Error);
if (!Error.empty())
return InternalError;
if (Diff) {
outs() << " nope.\n";
if (Suffix.empty()) {
errs() << BD.getToolName() << ": I'm confused: the test fails when "
<< "no passes are run, nondeterministic program?\n";
exit(1);
}
return KeepSuffix; // Miscompilation detected!
}
outs() << " yup.\n"; // No miscompilation!
if (Prefix.empty()) return NoFailure;
// Next, see if the program is broken if we run the "prefix" passes first,
// then separately run the "kept" passes.
outs() << "Checking to see if '" << getPassesString(Prefix)
<< "' compiles correctly: ";
// If it is not broken with the kept passes, it's possible that the prefix
// passes must be run before the kept passes to break it. If the program
// WORKS after the prefix passes, but then fails if running the prefix AND
// kept passes, we can update our bitcode file to include the result of the
// prefix passes, then discard the prefix passes.
//
if (BD.runPasses(BD.getProgram(), Prefix, BitcodeResult, false/*delete*/,
true/*quiet*/)) {
errs() << " Error running this sequence of passes"
<< " on the input pr