llvm-project/llvm/tools/llvm-reduce/TestRunner.cpp

116 lines
4.0 KiB
C++

//===-- TestRunner.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "TestRunner.h"
#include "ReducerWorkItem.h"
#include "deltas/Utils.h"
#include "llvm/Analysis/ModuleSummaryAnalysis.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
using namespace llvm;
TestRunner::TestRunner(StringRef TestName,
const std::vector<std::string> &TestArgs,
std::unique_ptr<ReducerWorkItem> Program,
std::unique_ptr<TargetMachine> TM, const char *ToolName,
StringRef OutputName, bool InputIsBitcode,
bool OutputBitcode)
: TestName(TestName), ToolName(ToolName), TestArgs(TestArgs),
Program(std::move(Program)), TM(std::move(TM)),
OutputFilename(OutputName), InputIsBitcode(InputIsBitcode),
EmitBitcode(OutputBitcode) {
assert(this->Program && "Initialized with null program?");
}
/// Runs the interestingness test, passes file to be tested as first argument
/// and other specified test arguments after that.
int TestRunner::run(StringRef Filename) const {
std::vector<StringRef> ProgramArgs;
ProgramArgs.push_back(TestName);
for (const auto &Arg : TestArgs)
ProgramArgs.push_back(Arg);
ProgramArgs.push_back(Filename);
std::string ErrMsg;
SmallVector<std::optional<StringRef>, 3> Redirects;
std::optional<StringRef> Empty = StringRef();
if (!Verbose) {
for (int i = 0; i < 3; ++i)
Redirects.push_back(Empty);
}
int Result = sys::ExecuteAndWait(
TestName, ProgramArgs, /*Env=*/std::nullopt, Redirects,
/*SecondsToWait=*/0, /*MemoryLimit=*/0, &ErrMsg);
if (Result < 0) {
Error E = make_error<StringError>("Error running interesting-ness test: " +
ErrMsg,
inconvertibleErrorCode());
errs() << toString(std::move(E));
exit(1);
}
return !Result;
}
void TestRunner::setProgram(std::unique_ptr<ReducerWorkItem> P) {
assert(P && "Setting null program?");
Program = std::move(P);
}
void writeBitcode(ReducerWorkItem &M, raw_ostream &OutStream) {
if (M.LTOInfo && M.LTOInfo->IsThinLTO && M.LTOInfo->EnableSplitLTOUnit) {
PassBuilder PB;
LoopAnalysisManager LAM;
FunctionAnalysisManager FAM;
CGSCCAnalysisManager CGAM;
ModuleAnalysisManager MAM;
PB.registerModuleAnalyses(MAM);
PB.registerCGSCCAnalyses(CGAM);
PB.registerFunctionAnalyses(FAM);
PB.registerLoopAnalyses(LAM);
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
ModulePassManager MPM;
MPM.addPass(ThinLTOBitcodeWriterPass(OutStream, nullptr));
MPM.run(*M.M, MAM);
} else {
std::unique_ptr<ModuleSummaryIndex> Index;
if (M.LTOInfo && M.LTOInfo->HasSummary) {
ProfileSummaryInfo PSI(M);
Index = std::make_unique<ModuleSummaryIndex>(
buildModuleSummaryIndex(M, nullptr, &PSI));
}
WriteBitcodeToFile(M, OutStream, Index.get());
}
}
void TestRunner::writeOutput(StringRef Message) {
std::error_code EC;
raw_fd_ostream Out(OutputFilename, EC,
EmitBitcode && !Program->isMIR() ? sys::fs::OF_None
: sys::fs::OF_Text);
if (EC) {
errs() << "Error opening output file: " << EC.message() << "!\n";
exit(1);
}
// Requesting bitcode emission with mir is nonsense, so just ignore it.
if (EmitBitcode && !Program->isMIR())
writeBitcode(*Program, Out);
else
Program->print(Out, /*AnnotationWriter=*/nullptr);
errs() << Message << OutputFilename << '\n';
}