mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
134 lines
4.4 KiB
C++
134 lines
4.4 KiB
C++
#pragma once
|
|
|
|
/*
|
|
* This file is distributed under the MIT License. See LICENSE.md for details.
|
|
*/
|
|
|
|
#include <string>
|
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/PluginLoader.h"
|
|
|
|
#include "revng/Pipes/PipelineManager.h"
|
|
#include "revng/Storage/CLPathOpt.h"
|
|
#include "revng/Support/Error.h"
|
|
|
|
namespace revng::pipes {
|
|
class ToolCLOptions {
|
|
private:
|
|
llvm::cl::list<std::string> InputPipeline;
|
|
InputPathOpt ModelOverride;
|
|
llvm::cl::list<std::string> EnablingFlags;
|
|
llvm::cl::opt<std::string> ExecutionDirectory;
|
|
llvm::cl::alias A1;
|
|
llvm::cl::alias A2;
|
|
|
|
public:
|
|
ToolCLOptions(llvm::cl::OptionCategory &Category) :
|
|
|
|
InputPipeline("P", llvm::cl::desc("<Pipeline>"), llvm::cl::cat(Category)),
|
|
ModelOverride("model",
|
|
llvm::cl::desc("Load the model from a provided file"),
|
|
llvm::cl::cat(Category)),
|
|
EnablingFlags("f",
|
|
llvm::cl::desc("list of pipeline enabling flags"),
|
|
llvm::cl::cat(Category)),
|
|
ExecutionDirectory("resume",
|
|
llvm::cl::desc("Directory from which all containers "
|
|
"will be loaded before everything else "
|
|
"and to which it will be store after "
|
|
"everything else"),
|
|
llvm::cl::cat(Category)),
|
|
A1("l",
|
|
llvm::cl::desc("Alias for --load"),
|
|
llvm::cl::aliasopt(llvm::LoadOpt),
|
|
llvm::cl::cat(Category)),
|
|
A2("m",
|
|
llvm::cl::desc("Alias for --model"),
|
|
llvm::cl::aliasopt(ModelOverride),
|
|
llvm::cl::cat(Category)) {}
|
|
|
|
llvm::Error overrideModel(revng::FilePath ModelOverride,
|
|
PipelineManager &Manager) {
|
|
const auto &Name = ModelGlobalName;
|
|
auto *Model = cantFail(Manager.context().getGlobal<ModelGlobal>(Name));
|
|
return Model->load(ModelOverride);
|
|
}
|
|
|
|
llvm::Expected<revng::pipes::PipelineManager> makeManager() {
|
|
if (llvm::sys::fs::is_regular_file(ExecutionDirectory))
|
|
return revng::createError("--resume points to a file");
|
|
|
|
auto Manager = revng::pipes::PipelineManager::create(InputPipeline,
|
|
EnablingFlags,
|
|
ExecutionDirectory);
|
|
if (not Manager)
|
|
return Manager;
|
|
|
|
auto MaybeModelOverride = ModelOverride.get();
|
|
if (not MaybeModelOverride)
|
|
return MaybeModelOverride.takeError();
|
|
|
|
if (MaybeModelOverride->has_value()) {
|
|
if (auto Error = overrideModel(**MaybeModelOverride, *Manager))
|
|
return Error;
|
|
}
|
|
|
|
return Manager;
|
|
}
|
|
};
|
|
|
|
inline pipeline::Step *getStepOfAnalysis(pipeline::Runner &Runner,
|
|
llvm::StringRef AnalysisName) {
|
|
using namespace pipeline;
|
|
const auto &StepHasAnalysis = [AnalysisName](const Step &Step) {
|
|
return Step.hasAnalysis(AnalysisName);
|
|
};
|
|
auto It = llvm::find_if(Runner, StepHasAnalysis);
|
|
if (It == Runner.end())
|
|
return nullptr;
|
|
return &*It;
|
|
}
|
|
|
|
inline pipeline::TargetInStepSet
|
|
runAnalysisOrAnalysesList(revng::pipes::PipelineManager &Manager,
|
|
llvm::StringRef Name,
|
|
llvm::ExitOnError &AbortOnError) {
|
|
using namespace pipeline;
|
|
using namespace llvm;
|
|
auto &Runner = Manager.getRunner();
|
|
TargetInStepSet InvMap;
|
|
if (Runner.hasAnalysesList(Name)) {
|
|
AnalysesList AL = Runner.getAnalysesList(Name);
|
|
AbortOnError(Manager.runAnalyses(AL, InvMap));
|
|
} else {
|
|
auto *Step = getStepOfAnalysis(Runner, Name);
|
|
if (not Step) {
|
|
AbortOnError(revng::createError("No known analysis named %s, invoke this "
|
|
"command without arguments to see the "
|
|
"list of available analysis",
|
|
Name.data()));
|
|
}
|
|
|
|
auto &Analysis = Step->getAnalysis(Name);
|
|
|
|
ContainerToTargetsMap Map;
|
|
for (const auto &Pair :
|
|
llvm::enumerate(Analysis->getRunningContainersNames())) {
|
|
auto Index = Pair.index();
|
|
const auto &ContainerName = Pair.value();
|
|
for (const auto &Kind : Analysis->getAcceptedKinds(Index)) {
|
|
Map.add(ContainerName, Kind->allTargets(Manager.context()));
|
|
}
|
|
}
|
|
|
|
llvm::StringRef StepName = Step->getName();
|
|
std::string AnalysisName = Name.str();
|
|
AbortOnError(Manager.runAnalysis(AnalysisName, StepName, Map, InvMap));
|
|
}
|
|
|
|
return InvMap;
|
|
}
|
|
|
|
} // namespace revng::pipes
|