Add pipeline invalidation

Replace the stub implementation of invalidation with the proper
implementation. A ReadPathCache is added to each global so that it can
keep tracks of what target are associated to which read paths.
This commit is contained in:
Massimo Fioravanti
2023-06-27 15:28:25 +02:00
parent e5347b2910
commit c276a439b5
79 changed files with 1328 additions and 383 deletions
+1 -1
View File
@@ -57,7 +57,7 @@ public:
private:
T Content;
mutable AccessTracker Exact;
mutable AccessTracker Exact = AccessTracker(false);
mutable std::vector<TrackingSet> NonExisting;
mutable std::vector<llvm::BitVector> Existing;
+1 -1
View File
@@ -36,7 +36,7 @@ public:
pipeline::InputPreservation::Preserve) };
}
void run(pipeline::Context &Ctx,
void run(pipeline::ExecutionContext &Ctx,
const BinaryFileContainer &SourceBinary,
pipeline::LLVMContainer &Output);
+2 -1
View File
@@ -27,7 +27,8 @@ public:
pipeline::InputPreservation::Preserve) };
}
void run(const pipeline::Context &Ctx, pipeline::LLVMContainer &TargetsList);
void run(const pipeline::ExecutionContext &Ctx,
pipeline::LLVMContainer &TargetsList);
void print(const pipeline::Context &Ctx,
llvm::raw_ostream &OS,
@@ -24,7 +24,7 @@ public:
};
public:
llvm::Error run(pipeline::Context &Context,
llvm::Error run(pipeline::ExecutionContext &Context,
const BinaryFileContainer &SourceBinary);
};
@@ -25,7 +25,7 @@ public:
std::vector<std::vector<pipeline::Kind *>> AcceptedKinds = {};
public:
void run(pipeline::Context &Context);
void run(pipeline::ExecutionContext &Context);
};
} // namespace revng::pipes
+61 -1
View File
@@ -21,8 +21,54 @@ inline Logger<> ModelVerifyLogger("model-verify");
namespace model {
class Type;
class Identifier;
class VerifyHelper {
private:
template<typename TrackableTupleTree>
class TrackingSuspender {
private:
VerifyHelper *TheContext;
std::optional<TrackGuard<TrackableTupleTree>> Guard;
public:
TrackingSuspender(TrackingSuspender &&Other) :
TheContext(Other.TheContext), Guard(std::move(Other.Guard)) {}
TrackingSuspender &operator=(TrackingSuspender &Other) {
if (this == Other)
return *this;
onDestruction();
TheContext = Other.TheContext;
Guard = std::move(Other.Guard);
return *this;
}
TrackingSuspender(const TrackingSuspender &Other) = delete;
TrackingSuspender &operator=(const TrackingSuspender &Other) = delete;
public:
TrackingSuspender(VerifyHelper &Context,
const TrackableTupleTree &Trackable) :
TheContext(&Context), Guard(std::nullopt) {
revng_assert(TheContext != nullptr);
if (not Context.hasPushedTracking()) {
Context.setPushedTracking();
Guard = TrackGuard<TrackableTupleTree>(Trackable);
}
}
public:
~TrackingSuspender() { onDestruction(); }
private:
void onDestruction() {
if (Guard.has_value()) {
TheContext->setPushedTracking(false);
Guard = std::nullopt;
}
}
};
friend class VerifyHelper;
private:
std::set<const model::Type *> VerifiedCache;
std::map<const model::Type *, uint64_t> SizeCache;
@@ -30,6 +76,7 @@ private:
std::set<const model::Type *> InProgress;
bool AssertOnFail = false;
std::map<model::Identifier, std::string> GlobalSymbols;
bool HasPushedTracking = false;
// TODO: This is a hack for now, but the methods, when the Model does not
// verify, should return an llvm::Error with the error message found by this.
@@ -41,6 +88,19 @@ public:
~VerifyHelper() { revng_assert(InProgress.size() == 0); }
private:
bool hasPushedTracking() const { return HasPushedTracking; }
void setPushedTracking(bool HasPushed = true) {
HasPushedTracking = HasPushed;
}
public:
template<typename T>
TrackingSuspender<T> suspendTracking(const T &Trackable) {
return TrackingSuspender<T>(*this, Trackable);
}
public:
void setVerified(const model::Type *T) {
revng_assert(not isVerified(T));
+1 -1
View File
@@ -74,7 +74,7 @@ public:
Invokable.print(Ctx, OS, Indentation);
}
llvm::Error run(Context &Ctx,
llvm::Error run(ExecutionContext &Ctx,
ContainerSet &Containers,
const llvm::StringMap<std::string> &ExtraArgs) override {
return Invokable.run(Ctx, Containers, ExtraArgs);
+12 -1
View File
@@ -17,6 +17,7 @@
#include "revng/Pipeline/Container.h"
#include "revng/Pipeline/ContainerSet.h"
#include "revng/Pipeline/ExecutionContext.h"
#include "revng/Pipeline/Global.h"
#include "revng/Pipeline/GlobalsMap.h"
#include "revng/Pipeline/KindsRegistry.h"
@@ -126,6 +127,16 @@ public:
public:
llvm::Error store(const revng::DirectoryPath &Path) const;
llvm::Error load(const revng::DirectoryPath &Path);
};
public:
void collectReadFields(const TargetInContainer &Target,
llvm::StringMap<PathTargetBimap> &Out) const {
Globals.collectReadFields(Target, Out);
}
void clearAndResume() const { Globals.clearAndResume(); }
void pushReadFields() const { Globals.pushReadFields(); }
void popReadFields() const { Globals.popReadFields(); }
void stopTracking() const { Globals.stopTracking(); }
};
} // namespace pipeline
+1 -1
View File
@@ -21,7 +21,7 @@ public:
}
public:
void run(const Context &, const Source &S, Destination &T) { T = S; }
void run(const ExecutionContext &, const Source &S, Destination &T) { T = S; }
};
} // namespace pipeline
+92
View File
@@ -0,0 +1,92 @@
#pragma once
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include "llvm/ADT/StringRef.h"
namespace pipeline {
class Context;
class Target;
class ContainerBase;
class Step;
struct PipeWrapper;
// A execution context is created and passed to each invocation of a pipe. It
// provides a reference to the pipeline::Context, as well as carrying around
// information about what is the state of the pipeline while the pipe is being
// executed, such as what is the current step.
//
// The execution context is the intended way of letting the pipeline know when a
// target is created, so that it may keep track of what paths inside pipeline
// globals have been read to produce such target and thus it can be invalidated
// when of element of the global indicated by such paths changes.
//
// We will not explain here how exactly the pipeline achieve this, but as a
// mental model what is happening is that every access to any field of the model
// is instrumented. When a ExecutionContext is created, or a when it commits (at
// the end of the call, just after the commit happens), the entire tracking
// state of the global is reset, and from that moment forward each time a
// variable is accessed it is marked as being accessed.
//
// When commit with arguments Target and Container is inovked, the following
// MUST be true:
// * Target must be == to the last target that has been created in Container
// * no field of any global can be read in betweet the last target being created
// and Target being committed.
// * Target cannot be erased by Container after commit has been invoked.
// * No field of a global, directly or indirectly, can be read to produce a
// target that is not the next Target to be committed. (that is, you can't
// read fields to produce target X but then produce Y, commit Y, produce X,
// commit X, unless you use pop and push to save and restore the state of read
// fields).
//
// Less formally, you must produce and commit a target at the time.
//
// Example:
//
// void SomePipeProducingFunctions(const ExecutionContext& Ctx, SomeContainer&
// Container) {
// ...
// for (auto& Function : Container)
// {
// ...
// Ctx.getContext().pushReadFields();
// Ctx.commit(Container, Target(Function.metaadress()));
// Ctx.getContext().popReadFields();
// }
// }
//
class ExecutionContext {
private:
Context *TheContext = nullptr;
Step *CurrentStep = nullptr;
PipeWrapper *Pipe = nullptr;
// false when running on a analysis
bool RunningOnPipe = true;
void commit(const Target &Target, llvm::StringRef ContainerName);
public:
~ExecutionContext();
public:
ExecutionContext(Context &TheContext, Step &Step, PipeWrapper *Pipe);
public:
void commit(const ContainerBase &Container, const Target &Target);
void commitUniqueTarget(const ContainerBase &Container);
void clearAndResumeTracking();
public:
const Context &getContext() const { return *TheContext; }
Context &getContext() { return *TheContext; }
public:
const Step &getStep() const { return *CurrentStep; }
Step &getStep() { return *CurrentStep; }
};
} // namespace pipeline
+1 -1
View File
@@ -176,7 +176,7 @@ public:
return Contract;
}
void run(const Context &, LLVMContainer &Container);
void run(const ExecutionContext &, LLVMContainer &Container);
void addPass(const PureLLVMPassWrapper &Pass) {
Passes.emplace_back(Pass.clone());
+46 -2
View File
@@ -13,8 +13,10 @@
#include "llvm/Support/raw_ostream.h"
#include "revng/Pipeline/GlobalTupleTreeDiff.h"
#include "revng/Pipeline/PathTargetBimap.h"
#include "revng/Storage/Path.h"
#include "revng/Support/YAMLTraits.h"
#include "revng/TupleTree/Tracking.h"
#include "revng/TupleTree/TupleTreeDiff.h"
namespace pipeline {
@@ -57,6 +59,18 @@ public:
virtual llvm::Error store(const revng::FilePath &Path) const;
virtual llvm::Error load(const revng::FilePath &Path);
virtual std::optional<TupleTreePath>
deserializePath(llvm::StringRef Serialized) const = 0;
virtual std::optional<std::string>
serializePath(const TupleTreePath &Path) const = 0;
virtual void collectReadFields(const TargetInContainer &Target,
PathTargetBimap &Out) = 0;
virtual void clearAndResume() const = 0;
virtual void pushReadFields() const = 0;
virtual void popReadFields() const = 0;
virtual void stopTracking() const = 0;
};
template<TupleTreeCompatibleAndVerifiable Object>
@@ -124,7 +138,10 @@ public:
llvm::Expected<GlobalTupleTreeDiff>
deserializeDiff(const llvm::MemoryBuffer &Buffer) override {
return ::deserialize<TupleTreeDiff<Object>>(Buffer.getBuffer());
auto MaybeDiff = ::deserialize<TupleTreeDiff<Object>>(Buffer.getBuffer());
if (not MaybeDiff)
return MaybeDiff.takeError();
return GlobalTupleTreeDiff(std::move(*MaybeDiff), getName());
}
bool verify() const override { return Value->verify(); }
@@ -132,7 +149,7 @@ public:
GlobalTupleTreeDiff diff(const Global &Other) const override {
const TupleTreeGlobal &Casted = llvm::cast<TupleTreeGlobal>(Other);
auto Diff = ::diff(*Value, *Casted.Value);
return GlobalTupleTreeDiff(std::move(Diff));
return GlobalTupleTreeDiff(std::move(Diff), getName());
}
llvm::Error applyDiff(const llvm::MemoryBuffer &Diff) override {
@@ -159,6 +176,33 @@ public:
const TupleTree<Object> &get() const { return Value; }
TupleTree<Object> &get() { return Value; }
std::optional<TupleTreePath>
deserializePath(llvm::StringRef Serialized) const override {
return stringAsPath<Object>(Serialized);
}
std::optional<std::string>
serializePath(const TupleTreePath &Path) const override {
return pathAsString<Object>(Path);
}
void collectReadFields(const TargetInContainer &Target,
PathTargetBimap &Out) override {
const TupleTree<Object> &AsConst = Value;
ReadFields Results = revng::Tracking::collect(*AsConst);
for (const TupleTreePath &Result : Results.Read)
Out.insert(Target, Result);
for (const TupleTreePath &Result : Results.ExactVectors)
Out.insert(Target, Result);
}
void clearAndResume() const override {
revng::Tracking::clearAndResume(*Value);
}
void pushReadFields() const override { revng::Tracking::push(*Value); }
void popReadFields() const override { revng::Tracking::pop(*Value); }
void stopTracking() const override { revng::Tracking::stop(*Value); }
};
} // namespace pipeline
+32 -7
View File
@@ -12,14 +12,26 @@ namespace pipeline {
class GlobalTupleTreeDiffBase {
private:
char *ID;
llvm::StringRef GlobalName;
public:
virtual ~GlobalTupleTreeDiffBase() = default;
GlobalTupleTreeDiffBase(char *ID, llvm::StringRef GlobalName) :
ID(ID), GlobalName(GlobalName) {}
public:
virtual void serialize(llvm::raw_ostream &OS) const = 0;
virtual ~GlobalTupleTreeDiffBase() = default;
public:
virtual std::unique_ptr<GlobalTupleTreeDiffBase> clone() const = 0;
virtual bool isEmpty() const = 0;
GlobalTupleTreeDiffBase(char *ID) : ID(ID) {}
public:
const char *getID() const { return ID; }
public:
virtual bool isEmpty() const = 0;
llvm::StringRef getGlobalName() const { return GlobalName; }
virtual llvm::SmallVector<const TupleTreePath *, 4> getPaths() const = 0;
};
template<TupleTreeCompatible T>
@@ -33,8 +45,8 @@ private:
}
public:
GlobalTupleTreeDiffImpl(TupleTreeDiff<T> Diff) :
GlobalTupleTreeDiffBase(getID()), Diff(std::move(Diff)) {}
GlobalTupleTreeDiffImpl(TupleTreeDiff<T> Diff, llvm::StringRef GlobalName) :
GlobalTupleTreeDiffBase(getID(), GlobalName), Diff(std::move(Diff)) {}
~GlobalTupleTreeDiffImpl() override = default;
@@ -55,6 +67,14 @@ public:
TupleTreeDiff<T> &getDiff() { return Diff; }
const TupleTreeDiff<T> &getDiff() const { return Diff; }
llvm::SmallVector<const TupleTreePath *, 4> getPaths() const override {
llvm::SmallVector<const TupleTreePath *, 4> ToReturn;
for (const Change<T> &Entry : Diff.Changes) {
ToReturn.emplace_back(&Entry.Path);
}
return ToReturn;
}
};
class GlobalTupleTreeDiff {
@@ -63,8 +83,8 @@ private:
public:
template<TupleTreeCompatible T>
GlobalTupleTreeDiff(TupleTreeDiff<T> Diff) :
Diff(new GlobalTupleTreeDiffImpl<T>(std::move(Diff))) {}
GlobalTupleTreeDiff(TupleTreeDiff<T> Diff, llvm::StringRef GlobalName) :
Diff(new GlobalTupleTreeDiffImpl<T>(std::move(Diff), GlobalName)) {}
GlobalTupleTreeDiff(GlobalTupleTreeDiff &&) = default;
GlobalTupleTreeDiff &operator=(GlobalTupleTreeDiff &&) = default;
@@ -101,7 +121,12 @@ public:
return &Casted->getDiff();
}
llvm::SmallVector<const TupleTreePath *, 4> getPaths() const {
return Diff->getPaths();
}
bool isEmpty() const { return Diff.get()->isEmpty(); }
llvm::StringRef getGlobalName() const { return Diff->getGlobalName(); }
};
using DiffMap = llvm::StringMap<GlobalTupleTreeDiff>;
+23 -9
View File
@@ -132,15 +132,6 @@ public:
size_t size() const { return Map.size(); }
std::vector<llvm::StringRef> getGlobalNames() const {
std::vector<llvm::StringRef> ToReturn;
for (const auto &Global : Map)
ToReturn.push_back(Global.first);
return ToReturn;
}
public:
GlobalsMap() = default;
~GlobalsMap() = default;
@@ -162,5 +153,28 @@ public:
return *this;
}
void collectReadFields(const TargetInContainer &Target,
llvm::StringMap<PathTargetBimap> &Out) const {
for (const auto &Global : Map) {
Global.second->collectReadFields(Target, Out[Global.first]);
}
}
void clearAndResume() const {
for (const auto &Global : Map)
Global.second->clearAndResume();
}
void pushReadFields() const {
for (const auto &Global : Map)
Global.second->pushReadFields();
}
void popReadFields() const {
for (const auto &Global : Map)
Global.second->popReadFields();
}
void stopTracking() const {
for (const auto &Global : Map)
Global.second->stopTracking();
}
};
} // namespace pipeline
+9 -9
View File
@@ -23,7 +23,7 @@
#include "revng/Pipeline/CLOption.h"
#include "revng/Pipeline/Container.h"
#include "revng/Pipeline/ContainerSet.h"
#include "revng/Pipeline/Context.h"
#include "revng/Pipeline/ExecutionContext.h"
#include "revng/Pipeline/Option.h"
#include "revng/Pipeline/Target.h"
#include "revng/Support/Assert.h"
@@ -63,9 +63,9 @@ concept ReturnsError = invokableTypeReturnsError<Invokable>();
///
/// * It must have a static constexpr field named Name that is a string
/// describing its name. Mostly used for debug purposes.
/// * a RetT run(T...) method where the first argument must be a Context& or
/// const Context&, arguments after the first must be K& or const K& where
/// K is derived from a container.
/// * a RetT run(T...) method where the first argument must be a
/// ExecutionContext& or const ExecutionContext&, arguments after the first
/// must be K& or const K& where K is derived from a container.
///
/// Options after the last container can be of any type, but for each of
/// them there must exists an entry in a constexpr tuple named Options that
@@ -74,8 +74,8 @@ concept ReturnsError = invokableTypeReturnsError<Invokable>();
/// RetT can either be llvm::Error or void, if it is void then the invokable
/// never fails.
///
template<typename InvokableType, typename FirstRunArg, typename... Rest>
concept Invokable = convertible_to<Context &, std::remove_cv_t<FirstRunArg>>
template<typename InvokableType, typename First, typename... Rest>
concept Invokable = convertible_to<ExecutionContext &, std::remove_cv_t<First>>
and HasName<InvokableType>;
namespace detail {
@@ -325,7 +325,7 @@ createCLOptions(llvm::cl::OptionCategory *Category = nullptr) {
/// Invokes the F member function on the Pipe Pipe passing as nth argument the
/// container with the name equal to the nth element of ArgsNames.
template<typename InvokableType, typename ContextT, typename... Args>
auto invokePipeFunction(Context &Ctx,
auto invokePipeFunction(ExecutionContext &Ctx,
InvokableType &Pipe,
auto (InvokableType::*F)(ContextT &, Args...),
ContainerSet &Containers,
@@ -371,7 +371,7 @@ concept Printable = requires(InvokableType Pipe) {
class InvokableWrapperBase {
public:
virtual llvm::Error run(Context &Ctx,
virtual llvm::Error run(ExecutionContext &Ctx,
ContainerSet &Containers,
const llvm::StringMap<std::string> &Options = {}) = 0;
virtual ~InvokableWrapperBase() = default;
@@ -412,7 +412,7 @@ public:
std::string getName() const override { return InvokableType::Name; }
public:
llvm::Error run(Context &Ctx,
llvm::Error run(ExecutionContext &Ctx,
ContainerSet &Containers,
const llvm::StringMap<std::string> &OptionArgs) override {
if constexpr (invokableTypeReturnsError<InvokableType>()) {
-4
View File
@@ -108,10 +108,6 @@ public:
public:
virtual ~Kind() = default;
virtual void getInvalidations(const Context &Ctx,
pipeline::TargetsList &ToRemove,
const GlobalTupleTreeDiff &Diff) const {}
virtual void appendAllTargets(const Context &Ctx, TargetsList &Out) const = 0;
TargetsList allTargets(const Context &Ctx) const;
+120
View File
@@ -0,0 +1,120 @@
#pragma once
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include <string>
#include <tuple>
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/YAMLTraits.h"
#include "revng/Pipeline/Target.h"
#include "revng/TupleTree/TupleTreePath.h"
namespace pipeline {
class Context;
class TargetInContainer {
private:
Target Content;
std::string ContainerName;
public:
TargetInContainer(const Target &Target, const std::string &ContainerName) :
Content(Target), ContainerName(ContainerName) {}
const Target &getTarget() const { return Content; }
llvm::StringRef getContainerName() const {
return llvm::StringRef(ContainerName);
}
Target &getTarget() { return Content; }
std::string &getContainerName() { return ContainerName; }
bool operator==(const TargetInContainer &) const = default;
bool operator!=(const TargetInContainer &) const = default;
bool operator<(const TargetInContainer &Other) const {
const auto &LHS = std::tie(Content, ContainerName);
return LHS < std::tie(Other.Content, Other.ContainerName);
}
};
/// A PathTargetBimap is a many to many relationship between a TupleTreePaths
/// and TargetInContainer. It can be queried both ways, so from a target and a
/// container you can get the list of tuple tree paths that contribuited to that
/// target in that container, and from a tuple tree path you can know all the
/// targets that have been created reading the field pointed by that path.
class PathTargetBimap {
private:
using MapType = std::map<TupleTreePath, std::set<TargetInContainer>>;
using ReverseMapType = std::map<TargetInContainer,
std::vector<TupleTreePath>>;
MapType Map;
// When we will instrument the entire pipeline there will not be any longer a
// need to have a reverse map, since it will only be inspected at load time of
// the pipeline.
ReverseMapType ReverseMap;
public:
explicit PathTargetBimap() : Map() {}
public:
auto begin() { return Map.begin(); }
auto end() { return Map.end(); }
auto begin() const { return Map.begin(); }
auto end() const { return Map.end(); }
public:
auto find(const TupleTreePath &Path) const { return Map.find(Path); }
public:
void merge(PathTargetBimap &&Other) {
for (auto &Entry : Other.Map)
for (auto &Target : Entry.second)
insert(std::move(Target), std::move(Entry.first));
}
public:
void clear() { Map = MapType(); }
void insert(const TargetInContainer &TargetInContainer,
const TupleTreePath &Path) {
Map[Path].insert(TargetInContainer);
ReverseMap[TargetInContainer].push_back(Path);
}
void insert(const Target &Target,
const std::string &ContainerName,
const TupleTreePath &Path) {
TargetInContainer Located(Target, ContainerName);
insert(Located, Path);
}
void remove(const TargetsList &List, llvm::StringRef ContainerName) {
for (auto &Target : List) {
TargetInContainer ToErase(Target, ContainerName.str());
auto Iter = ReverseMap.find(ToErase);
if (Iter == ReverseMap.end())
continue;
for (auto &Path : Iter->second) {
Map.at(Path).erase(ToErase);
}
ReverseMap.erase(Iter);
}
}
public:
bool contains(const TargetInContainer &Target) const {
return ReverseMap.find(Target) != ReverseMap.end();
}
};
} // namespace pipeline
+93 -3
View File
@@ -20,8 +20,8 @@
#include "revng/ADT/STLExtras.h"
#include "revng/Pipeline/Container.h"
#include "revng/Pipeline/ContainerSet.h"
#include "revng/Pipeline/Context.h"
#include "revng/Pipeline/Contract.h"
#include "revng/Pipeline/ExecutionContext.h"
#include "revng/Pipeline/Invokable.h"
#include "revng/Pipeline/Target.h"
#include "revng/Support/Debug.h"
@@ -54,6 +54,8 @@ constexpr bool checkPipe(auto (C::*)(First, Rest...))
template<typename PipeType>
class PipeWrapperImpl;
// TODO: Rename, there are 3 layers of wrappers around a pipe and they are
// getting confusing
class PipeWrapperBase : public InvokableWrapperBase {
public:
template<typename PipeType>
@@ -173,7 +175,7 @@ public:
Invokable.print(Ctx, OS, Indentation);
}
llvm::Error run(Context &Ctx,
llvm::Error run(ExecutionContext &Ctx,
ContainerSet &Containers,
const llvm::StringMap<std::string> &ExtraArgs) override {
return Invokable.run(Ctx, Containers, ExtraArgs);
@@ -198,6 +200,94 @@ public:
} // namespace detail
using PipeWrapper = InvokableWrapper<detail::PipeWrapperBase>;
// Due to invokable wrapper not being controllable by this file we need to have
// a extra wrapper that carries along the invalidation metadata too.
struct PipeWrapper {
class InvalidationMetadata {
private:
llvm::StringMap<PathTargetBimap> PathCache;
public:
void registerTargetsDependingOn(const Context &Ctx,
llvm::StringRef GlobalName,
const TupleTreePath &Path,
ContainerToTargetsMap &Out) const {
if (auto Iter = PathCache.find(GlobalName); Iter != PathCache.end()) {
auto &Bimap = Iter->second;
auto It = Bimap.find(Path);
if (It == Bimap.end())
return;
for (const auto &Entry : It->second)
Out.add(Entry.getContainerName(), Entry.getTarget());
}
}
void remove(const ContainerToTargetsMap &Map) {
for (auto &Pair : Map) {
auto Iter = PathCache.find(Pair.first());
if (Iter == PathCache.end())
continue;
Iter->second.remove(Pair.second, Pair.first());
}
}
bool contains(llvm::StringRef GlobalName,
const TargetInContainer &Target) const {
if (auto Iter = PathCache.find(GlobalName); Iter != PathCache.end())
return Iter->second.contains(Target);
return false;
}
const llvm::StringMap<PathTargetBimap> &getPathCache() const {
return PathCache;
}
llvm::StringMap<PathTargetBimap> &getPathCache() { return PathCache; }
const PathTargetBimap &getPathCache(llvm::StringRef GlobalName) const {
revng_assert(PathCache.find(GlobalName) != PathCache.end());
return PathCache.find(GlobalName)->second;
}
PathTargetBimap &getPathCache(llvm::StringRef GlobalName) {
return PathCache[GlobalName];
}
};
public:
using WrapperType = InvokableWrapper<detail::PipeWrapperBase>;
WrapperType Pipe;
InvalidationMetadata InvalidationMetadata;
template<typename PipeType>
static PipeWrapper
make(PipeType Pipe, std::vector<std::string> RunningContainersNames) {
return WrapperType::make<PipeType>(Pipe, std::move(RunningContainersNames));
}
template<typename PipeType>
static PipeWrapper make(std::vector<std::string> RunningContainersNames) {
return WrapperType::make<PipeType>(std::move(RunningContainersNames));
}
PipeWrapper(const InvokableWrapper<detail::PipeWrapperBase> &Other) :
Pipe(Other) {}
PipeWrapper(const PipeWrapper &Other,
std::vector<std::string> RunningContainersNames) :
Pipe(Other.Pipe, RunningContainersNames) {}
template<typename PipeType, typename... ContainerNames>
static PipeWrapper bind(ContainerNames &&...Names) {
return WrapperType::bind<PipeType, ContainerNames...>(Names...);
}
template<typename PipeType, typename... ContainerNames>
static PipeWrapper bind(PipeType &&E, ContainerNames &&...Names) {
return WrapperType::bind<PipeType, ContainerNames...>(E, Names...);
}
};
} // namespace pipeline
+11 -9
View File
@@ -73,9 +73,9 @@ public:
const KindsRegistry &getKindsRegistry() const;
llvm::Error apply(const GlobalTupleTreeDiff &Diff,
pipeline::InvalidationMap &Map);
pipeline::TargetInStepSet &Map);
void getDiffInvalidations(const GlobalTupleTreeDiff &Diff,
pipeline::InvalidationMap &Out) const;
pipeline::TargetInStepSet &Out) const;
public:
Step &operator[](llvm::StringRef Name) { return getStep(Name); }
@@ -127,11 +127,11 @@ public:
/// every step will be registered in the returned invalidation map. The
/// propagations will not be calculated.
llvm::Error getInvalidations(const Target &Target,
pipeline::InvalidationMap &Invalidations) const;
pipeline::TargetInStepSet &Invalidations) const;
/// Deduces and register in the invalidation map all the targets that have
/// been produced starting from targets already presents in the map.
llvm::Error getInvalidations(pipeline::InvalidationMap &Invalidated) const;
llvm::Error getInvalidations(pipeline::TargetInStepSet &Invalidated) const;
public:
template<typename... PipeWrappers>
@@ -141,12 +141,14 @@ public:
PipeWrappers &&...Wrappers) {
IsContainerFactoriesRegistryFinalized = true;
if (PreviousStepName.empty())
return addStep(Step(StepName.str(),
return addStep(Step(*TheContext,
StepName.str(),
Component.str(),
ContainerFactoriesRegistry.createEmpty(),
std::forward<PipeWrappers>(Wrappers)...));
else
return addStep(Step(StepName.str(),
return addStep(Step(*TheContext,
StepName.str(),
Component.str(),
ContainerFactoriesRegistry.createEmpty(),
operator[](PreviousStepName),
@@ -173,12 +175,12 @@ public:
runAnalysis(llvm::StringRef AnalysisName,
llvm::StringRef StepName,
const ContainerToTargetsMap &Targets,
pipeline::InvalidationMap &InvalidationsMap,
pipeline::TargetInStepSet &InvalidationsMap,
const llvm::StringMap<std::string> &Options = {});
llvm::Expected<DiffMap>
runAnalyses(const AnalysesList &List,
pipeline::InvalidationMap &InvalidationsMap,
pipeline::TargetInStepSet &InvalidationsMap,
const llvm::StringMap<std::string> &Options = {});
void addContainerFactory(llvm::StringRef Name, ContainerFactory Entry) {
@@ -203,7 +205,7 @@ public:
/// Remove the provided target from all containers in all the steps, as well
/// as all all their transitive dependencies
llvm::Error invalidate(const Target &Target);
llvm::Error invalidate(const pipeline::InvalidationMap &Invalidations);
llvm::Error invalidate(const pipeline::TargetInStepSet &Invalidations);
public:
llvm::Error store(const revng::DirectoryPath &DirPath) const;
+49 -16
View File
@@ -69,10 +69,12 @@ private:
Step *PreviousStep;
ArtifactsInfo Artifacts;
AnalysisMapType AnalysisMap;
Context *Ctx;
public:
template<typename... PipeWrapperTypes>
Step(std::string Name,
Step(Context &Ctx,
std::string Name,
std::string Component,
ContainerSet Containers,
PipeWrapperTypes &&...PipeWrappers) :
@@ -80,10 +82,12 @@ public:
Component(std::move(Component)),
Containers(std::move(Containers)),
Pipes({ std::forward<PipeWrapperTypes>(PipeWrappers)... }),
PreviousStep(nullptr) {}
PreviousStep(nullptr),
Ctx(&Ctx) {}
template<typename... PipeWrapperTypes>
Step(std::string Name,
Step(Context &Ctx,
std::string Name,
std::string Component,
ContainerSet Containers,
Step &PreviousStep,
@@ -92,7 +96,40 @@ public:
Component(std::move(Component)),
Containers(std::move(Containers)),
Pipes({ std::forward<PipeWrapperTypes>(PipeWrappers)... }),
PreviousStep(&PreviousStep) {}
PreviousStep(&PreviousStep),
Ctx(&Ctx) {}
public:
// TODO: drop the Out parameter pattern if favour of coorutines in the whole
// codebase.
void registerTargetsDependingOn(llvm::StringRef GlobalName,
const TupleTreePath &Path,
TargetInStepSet &Out) const {
for (const PipeWrapper &Pipe : Pipes) {
Pipe.InvalidationMetadata.registerTargetsDependingOn(*Ctx,
GlobalName,
Path,
Out[getName()]);
}
}
bool invalidationMetadataContains(llvm::StringRef GlobalName,
const TargetInContainer &Target) const {
for (const PipeWrapper &Pipe : Pipes) {
if (Pipe.InvalidationMetadata.contains(GlobalName, Target))
return false;
}
return true;
}
private:
llvm::Error loadInvalidationMetadataImpl(const revng::DirectoryPath &Path,
ContainerSet::value_type &Pair);
private:
llvm::Error loadInvalidationMetadata(const revng::DirectoryPath &Path);
llvm::Error storeInvalidationMetadata(const revng::DirectoryPath &Path) const;
public:
void addAnalysis(llvm::StringRef Name, AnalysisWrapper Analysis) {
@@ -164,7 +201,7 @@ public:
return nullptr;
}
auto &ContainerName = Artifacts.Container;
const std::string &ContainerName = Artifacts.Container;
if (Containers.isContainerRegistered(ContainerName)) {
Containers[ContainerName];
return &*Containers.find(ContainerName);
@@ -196,27 +233,24 @@ public:
public:
llvm::Error runAnalysis(llvm::StringRef AnalysisName,
Context &Ctx,
const ContainerToTargetsMap &Targets,
const llvm::StringMap<std::string> &ExtraArgs = {});
/// Executes all the pipes of this step, merges the results in the final
/// containers and returns the containers filtered according to the request.
ContainerSet run(Context &Ctx, ContainerSet &&Targets);
ContainerSet run(ContainerSet &&Targets);
/// Returns the set of goals that are already contained in the backing
/// containers of this step, furthermore adds to the container ToLoad those
/// that were not present.
ContainerToTargetsMap
analyzeGoals(const Context &Ctx,
const ContainerToTargetsMap &RequiredGoals) const;
analyzeGoals(const ContainerToTargetsMap &RequiredGoals) const;
llvm::Error checkPrecondition(const Context &Ctx) const;
llvm::Error checkPrecondition() const;
/// Returns the predicted state of the Input containers status after the
/// execution of all the pipes in this step.
ContainerToTargetsMap deduceResults(const Context &Ctx,
ContainerToTargetsMap Input) const;
ContainerToTargetsMap deduceResults(ContainerToTargetsMap Input) const;
public:
void addPipe(PipeWrapper Wrapper) { Pipes.push_back(std::move(Wrapper)); }
@@ -237,8 +271,8 @@ public:
indent(OS, Indentation + 1);
OS << "Pipes: \n";
for (const auto &Pipe : Pipes)
Pipe.dump(OS, Indentation + 2);
for (const PipeWrapper &Pipe : Pipes)
Pipe.Pipe.dump(OS, Indentation + 2);
indent(OS, Indentation + 1);
OS << " containers: \n";
@@ -256,8 +290,7 @@ private:
void removeSatisfiedGoals(ContainerToTargetsMap &Targets,
ContainerToTargetsMap &ToLoad) const;
void explainExecutedPipe(const Context &Ctx,
const InvokableWrapperBase &Wrapper,
void explainExecutedPipe(const InvokableWrapperBase &Wrapper,
size_t Indentation = 0) const;
void explainStartStep(const ContainerToTargetsMap &Wrapper,
size_t Indentation = 0) const;
+2 -2
View File
@@ -391,14 +391,14 @@ private:
}
};
using InvalidationMap = llvm::StringMap<ContainerToTargetsMap>;
using TargetInStepSet = llvm::StringMap<ContainerToTargetsMap>;
llvm::Error parseTarget(const Context &Ctx,
ContainerToTargetsMap &CurrentStatus,
llvm::StringRef AsString,
const KindsRegistry &Dict);
inline void merge(InvalidationMap &Map, const InvalidationMap &Other) {
inline void merge(TargetInStepSet &Map, const TargetInStepSet &Other) {
for (const auto &Entry : Other) {
if (auto Iter = Map.find(Entry.first()); Iter != Map.end()) {
Iter->second.merge(Entry.second);
@@ -52,7 +52,7 @@ typedef const pipeline::TargetsList rp_targets_list;
typedef const pipeline::Step::AnalysisValueType rp_analysis;
typedef const pipeline::DiffMap rp_diff_map;
typedef llvm::StringMap<std::string> rp_string_map;
typedef pipeline::InvalidationMap rp_invalidations;
typedef pipeline::TargetInStepSet rp_invalidations;
typedef llvm::SmallVector<char, 0> rp_buffer;
typedef pipeline::ContainerToTargetsMap rp_container_targets_map;
typedef const pipeline::AnalysesList rp_analyses_list;
+24
View File
@@ -0,0 +1,24 @@
#pragma once
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include <tuple>
#include <vector>
#include "revng/Pipeline/Kind.h"
#include "revng/Pipeline/Option.h"
namespace revng::pipes {
struct ApplyDiffAnalysis {
static constexpr auto Name = "Apply";
constexpr static std::tuple Options = { pipeline::Option("diff-path", "") };
std::vector<std::vector<pipeline::Kind *>> AcceptedKinds = {};
llvm::Error run(pipeline::ExecutionContext &Ctx, std::string DiffLocation);
};
} // namespace revng::pipes
+4 -4
View File
@@ -32,7 +32,7 @@ struct ApplyDiffAnalysis {
std::vector<std::vector<pipeline::Kind *>> AcceptedKinds = {};
llvm::Error run(pipeline::Context &Ctx,
llvm::Error run(pipeline::ExecutionContext &Ctx,
std::string DiffGlobalName,
std::string DiffContent);
};
@@ -46,7 +46,7 @@ struct VerifyDiffAnalysis {
std::vector<std::vector<pipeline::Kind *>> AcceptedKinds = {};
llvm::Error run(pipeline::Context &Ctx,
llvm::Error run(pipeline::ExecutionContext &Ctx,
std::string DiffGlobalNane,
std::string DiffContent);
};
@@ -61,7 +61,7 @@ struct SetGlobalAnalysis {
std::vector<std::vector<pipeline::Kind *>> AcceptedKinds = {};
llvm::Error run(pipeline::Context &Ctx,
llvm::Error run(pipeline::ExecutionContext &Ctx,
std::string SetGlobalNane,
std::string GlobalContent);
};
@@ -75,7 +75,7 @@ struct VerifyGlobalAnalysis {
std::vector<std::vector<pipeline::Kind *>> AcceptedKinds = {};
llvm::Error run(pipeline::Context &Ctx,
llvm::Error run(pipeline::ExecutionContext &Ctx,
std::string SetGlobalNane,
std::string GlobalContent);
};
@@ -18,9 +18,10 @@ namespace revng::pipes {
template<typename... Passes>
class LLVMAnalysisImplementation {
public:
void run(const pipeline::Context &Ctx, pipeline::LLVMContainer &Container) {
void run(const pipeline::ExecutionContext &Ctx,
pipeline::LLVMContainer &Container) {
llvm::legacy::PassManager Manager;
registerPasses(Ctx, Manager);
registerPasses(Ctx.getContext(), Manager);
Manager.run(Container.getModule());
}
+9
View File
@@ -30,6 +30,11 @@ getModelFromContext(const pipeline::Context &Ctx) {
return Model->get();
}
inline const TupleTree<model::Binary> &
getModelFromContext(const pipeline::ExecutionContext &Ctx) {
return getModelFromContext(Ctx.getContext());
}
inline TupleTree<model::Binary> &
getWritableModelFromContext(pipeline::Context &Ctx) {
using Wrapper = ModelGlobal;
@@ -38,4 +43,8 @@ getWritableModelFromContext(pipeline::Context &Ctx) {
return Model->get();
}
inline TupleTree<model::Binary> &
getWritableModelFromContext(pipeline::ExecutionContext &Ctx) {
return getWritableModelFromContext(Ctx.getContext());
}
} // namespace revng
+5 -5
View File
@@ -105,7 +105,7 @@ public:
const pipeline::Step::AnalysisValueType &
getAnalysis(const pipeline::AnalysisReference &Reference) const;
llvm::Expected<pipeline::InvalidationMap>
llvm::Expected<pipeline::TargetInStepSet>
deserializeContainer(pipeline::Step &Step,
llvm::StringRef ContainerName,
const llvm::MemoryBuffer &Buffer);
@@ -140,8 +140,8 @@ public:
return produceAllPossibleTargets(true);
}
llvm::Expected<pipeline::InvalidationMap> invalidateAllPossibleTargets();
llvm::Expected<pipeline::InvalidationMap>
llvm::Expected<pipeline::TargetInStepSet> invalidateAllPossibleTargets();
llvm::Expected<pipeline::TargetInStepSet>
invalidateFromDiff(const llvm::StringRef Name,
const pipeline::GlobalTupleTreeDiff &Diff);
@@ -171,7 +171,7 @@ public:
llvm::Expected<pipeline::DiffMap>
runAnalyses(const pipeline::AnalysesList &List,
pipeline::InvalidationMap &Map,
pipeline::TargetInStepSet &Map,
const llvm::StringMap<std::string> &Options = {},
llvm::raw_ostream *DiagnosticLog = nullptr);
@@ -179,7 +179,7 @@ public:
runAnalysis(llvm::StringRef AnalysisName,
llvm::StringRef StepName,
const pipeline::ContainerToTargetsMap &Targets,
pipeline::InvalidationMap &Map,
pipeline::TargetInStepSet &Map,
const llvm::StringMap<std::string> &Options = {},
llvm::raw_ostream *DiagnosticLog = nullptr);
-5
View File
@@ -25,11 +25,6 @@ public:
void appendAllTargets(const pipeline::Context &Ctx,
pipeline::TargetsList &Out) const override;
void
getInvalidations(const pipeline::Context &Ctx,
pipeline::TargetsList &ToRemove,
const pipeline::GlobalTupleTreeDiff &Base) const override;
};
class IsolatedRootKind : public pipeline::LLVMKind {
+6 -6
View File
@@ -23,6 +23,9 @@ private:
// It is on the heap to avoid Initialization Order Fiasco
std::unique_ptr<llvm::SmallVector<TaggedFunctionKind *>> Children = nullptr;
// we have a redundant extra list of children here that would be a subset of
// that present in kind because kinds are not upcastable, and so we would not
// be able to know which one we care about without a second list.
void registerChild(TaggedFunctionKind *Child) {
if (Children == nullptr)
Children = std::make_unique<llvm::SmallVector<TaggedFunctionKind *>>();
@@ -42,16 +45,13 @@ public:
TaggedFunctionKind &Parent,
const BaseRank &Rank,
const FunctionTags::Tag &Tag) :
pipeline::LLVMKind(Name, Parent, Rank), Tag(&Tag) {}
pipeline::LLVMKind(Name, Parent, Rank), Tag(&Tag) {
Parent.registerChild(this);
}
std::optional<pipeline::Target>
symbolToTarget(const llvm::Function &Symbol) const override;
void
getInvalidations(const pipeline::Context &Ctx,
pipeline::TargetsList &ToRemove,
const pipeline::GlobalTupleTreeDiff &Diff) const override;
void appendAllTargets(const pipeline::Context &Ctx,
pipeline::TargetsList &Out) const override;
};
+1 -3
View File
@@ -40,9 +40,7 @@ public:
A1("l",
llvm::cl::desc("Alias for --load"),
llvm::cl::aliasopt(llvm::LoadOpt),
llvm::cl::cat(Category))
{}
llvm::cl::cat(Category)) {}
llvm::Error overrideModel(revng::FilePath ModelOverride,
PipelineManager &Manager) {
+2 -2
View File
@@ -28,7 +28,7 @@ public:
std::array<pipeline::ContractGroup, 1> getContract() const {
return { pipeline::ContractGroup(kinds::Root, 0, kinds::Object, 1) };
}
void run(const pipeline::Context &,
void run(const pipeline::ExecutionContext &,
pipeline::LLVMContainer &TargetsList,
ObjectFileContainer &TargetBinary);
@@ -53,7 +53,7 @@ public:
pipeline::Contract IsolatedPart(kinds::Isolated, 0, kinds::Object, 1);
return { pipeline::ContractGroup({ RootPart, IsolatedPart }) };
}
void run(const pipeline::Context &,
void run(const pipeline::ExecutionContext &,
pipeline::LLVMContainer &TargetsList,
ObjectFileContainer &TargetBinary);
@@ -37,7 +37,7 @@ public:
return { pipeline::ContractGroup({ BinaryPart, ObjectPart }) };
}
void run(const pipeline::Context &Ctx,
void run(const pipeline::ExecutionContext &Ctx,
BinaryFileContainer &InputBinary,
ObjectFileContainer &ObjectFile,
TranslatedFileContainer &OutputBinary);
+12 -3
View File
@@ -16,15 +16,23 @@ namespace revng {
///
class AccessTracker {
private:
uint8_t Counter = 0;
std::uint8_t Counter = 0;
bool IsTracking;
public:
AccessTracker(bool StartsActive) { IsTracking = StartsActive; }
public:
bool operator==(const AccessTracker &Other) const = default;
bool operator!=(const AccessTracker &Other) const = default;
void clear() { Counter &= ~0x1; }
void access() { Counter |= 0x1; }
public:
void clear() {
Counter &= ~0x1;
IsTracking = true;
}
void access() { Counter |= (0x1 & IsTracking); }
void push() {
revng_assert(llvm::countLeadingZeros(Counter) != 0,
"More than 8 pushes have been performed");
@@ -34,6 +42,7 @@ public:
bool front() const { return (Counter & 0x1) == 0; }
bool peak() const { return Counter & 0x1; }
bool isSet() const { return Counter; }
void stopTracking() { IsTracking = false; }
};
} // namespace revng
+12 -8
View File
@@ -20,6 +20,10 @@
/// The field Read is the set of paths of fields that were accessed.
/// The exact vectors contains the paths of all vectors that were marked as
/// requiring being identical.
///
/// We divide into read and exact vectors because when we will introduce the
/// cold start invalidation based on the hash, the hash will be different
/// depending if they are just read or if they are vectors required to be exact.
struct ReadFields {
std::set<TupleTreePath> Read;
std::set<TupleTreePath> ExactVectors;
@@ -85,8 +89,9 @@ private:
if constexpr (I < std::tuple_size_v<T>) {
Stack.push_back(size_t(I));
if (LHS.template getTracker<I>().isSet())
if (LHS.template getTracker<I>().isSet()) {
Info.Read.insert(Stack);
}
collectImpl<M>(LHS.template untrackedGet<I>(), Stack, Info);
Stack.pop_back();
@@ -114,7 +119,8 @@ private:
if (TrackingResult.Exact)
Info.ExactVectors.insert(Stack);
for (auto &Key : TrackingResult.InspectedKeys) {
using KeyType = std::remove_cv_t<typename T::key_type>;
for (KeyType Key : TrackingResult.InspectedKeys) {
Stack.push_back(Key);
Info.Read.insert(Stack);
Stack.pop_back();
@@ -122,10 +128,7 @@ private:
for (auto &LHSElement : LHS.Content) {
using value_type = typename T::value_type;
if constexpr (TupleSizeCompatible<value_type>)
Stack.push_back(LHSElement.untrackedKey());
else
Stack.push_back(KeyedObjectTraits<value_type>::key(LHSElement));
Stack.push_back(KeyedObjectTraits<value_type>::key(LHSElement));
collectImpl<M>(LHSElement, Stack, Info);
Stack.pop_back();
@@ -175,14 +178,16 @@ private:
public:
template<typename M>
static ReadFields collect(const M &LHS) {
stop(LHS);
TupleTreePath Stack;
ReadFields Info;
collectImpl<M>(LHS, Stack, Info);
clearAndResume(LHS);
return Info;
}
template<typename M>
static void clear(const M &LHS) {
static void clearAndResume(const M &LHS) {
visitTuple<M, ClearVisitor>(LHS);
}
@@ -201,5 +206,4 @@ public:
visitTuple<M, StopTrackingVisitor>(LHS);
}
};
} // namespace revng
+53
View File
@@ -25,11 +25,59 @@
#include "revng/Support/Assert.h"
#include "revng/Support/Debug.h"
#include "revng/Support/YAMLTraits.h"
#include "revng/TupleTree/Tracking.h"
#include "revng/TupleTree/TupleTreeCompatible.h"
#include "revng/TupleTree/TupleTreePath.h"
#include "revng/TupleTree/TupleTreeReference.h"
#include "revng/TupleTree/Visits.h"
template<typename T>
concept HasTracking = requires(T _) { T::HasTracking; };
template<typename T>
struct TrackGuard {
const T *TrackedObject;
public:
TrackGuard(const T &TrackedObject) : TrackedObject(&TrackedObject) {
// Since the model classes may have been generated either with or without
// tracking, a trackguard should do nothing if the concept returns false.
if constexpr (HasTracking<T>)
revng::Tracking::push(*this->TrackedObject);
}
TrackGuard(const TrackGuard &Other) = delete;
TrackGuard &operator=(const TrackGuard &Other) = delete;
TrackGuard(TrackGuard &&Other) {
TrackedObject = Other.TrackedObject;
Other.TrackedObject = nullptr;
}
TrackGuard &operator=(TrackGuard &&Other) {
if (this == &Other) {
return *this;
}
onDestruction();
TrackedObject = Other.TrackedObject;
Other.TrackedObject = nullptr;
return *this;
}
~TrackGuard() { onDestruction(); }
private:
void onDestruction() {
if constexpr (HasTracking<T>) {
if (TrackedObject != nullptr) {
revng::Tracking::pop(*TrackedObject);
}
}
TrackedObject = nullptr;
}
};
template<TupleTreeCompatible T>
class TupleTree {
private:
@@ -169,6 +217,7 @@ public:
private:
void initializeUncachedReferences() {
TrackGuard Guard(*Root);
visitReferences([this](auto &Element) {
Element.Root = Root.get();
Element.evictCachedTarget();
@@ -178,17 +227,20 @@ private:
public:
void initializeReferences() {
TrackGuard Guard(*Root);
revng_assert(not AllReferencesAreCached);
visitReferences([this](auto &Element) { Element.Root = Root.get(); });
}
void cacheReferences() {
TrackGuard Guard(*Root);
if (not AllReferencesAreCached)
visitReferencesInternal([](auto &Element) { Element.cacheTarget(); });
AllReferencesAreCached = true;
}
void evictCachedReferences() {
TrackGuard Guard(*Root);
if (AllReferencesAreCached)
visitReferencesInternal([](auto &E) { E.evictCachedTarget(); });
AllReferencesAreCached = false;
@@ -251,6 +303,7 @@ public:
private:
bool verifyReferences(bool Assert) const {
TrackGuard Guard(*Root);
bool Result = true;
visitReferences([&Result,
+1 -1
View File
@@ -41,7 +41,7 @@ public:
}
public:
void run(pipeline::Context &Context,
void run(pipeline::ExecutionContext &Context,
const BinaryFileContainer &SourceBinary,
const pipeline::LLVMContainer &TargetsList,
FunctionAssemblyStringMap &OutputAssembly);
+1 -1
View File
@@ -63,7 +63,7 @@ public:
}
public:
void run(pipeline::Context &Context,
void run(pipeline::ExecutionContext &Context,
const pipeline::LLVMContainer &TargetsList,
CrossRelationsFileContainer &OutputFile);
+1 -1
View File
@@ -30,7 +30,7 @@ public:
}
public:
void run(pipeline::Context &Context,
void run(pipeline::ExecutionContext &Context,
const FunctionAssemblyStringMap &Input,
FunctionAssemblyPTMLStringMap &Output);
+1 -1
View File
@@ -30,7 +30,7 @@ public:
}
public:
void run(pipeline::Context &Context,
void run(pipeline::ExecutionContext &Context,
const CrossRelationsFileContainer &InputFile,
CallGraphSVGFileContainer &OutputFile);
@@ -39,7 +39,7 @@ public:
}
public:
void run(pipeline::Context &Context,
void run(pipeline::ExecutionContext &Context,
const pipeline::LLVMContainer &TargetList,
const CrossRelationsFileContainer &InputFile,
CallGraphSliceSVGStringMap &Output);
+1 -1
View File
@@ -58,7 +58,7 @@ public:
}
public:
void run(pipeline::Context &Context,
void run(pipeline::ExecutionContext &Context,
const FunctionAssemblyStringMap &Input,
FunctionControlFlowStringMap &Output);
@@ -165,7 +165,7 @@ public:
};
std::vector<std::vector<pipeline::Kind *>> AcceptedKinds = {};
void run(pipeline::Context &Context,
void run(pipeline::ExecutionContext &Context,
std::string TargetABI,
std::string Mode,
std::string ABIConfidence) {
@@ -20,7 +20,7 @@ public:
std::vector<std::vector<pipeline::Kind *>> AcceptedKinds = {};
void run(pipeline::Context &Context) {
void run(pipeline::ExecutionContext &Context) {
auto &Model = revng::getWritableModelFromContext(Context);
model::VerifyHelper VH;
+2 -1
View File
@@ -99,7 +99,8 @@ public:
Implementation.print(Ctx, OS, ContainerNames);
}
void run(const pipeline::Context &Ctx, pipeline::LLVMContainer &Container) {
void run(const pipeline::ExecutionContext &Ctx,
pipeline::LLVMContainer &Container) {
Implementation.run(Ctx, Container);
}
};
+2 -1
View File
@@ -358,7 +358,8 @@ MaterializedValue JumpTargetManager::readFromPointer(MetaAddress LoadAddress,
uint64_t Addend = Relocation.Addend();
auto RelocationSize = model::RelocationType::getSize(Relocation.Type());
if (LoadAddress == Relocation.Address() and LoadSize == RelocationSize) {
revng_assert(not StringRef(Function.name()).contains('\0'));
// TODO: add this to model verify
revng_assert(not StringRef(Function.OriginalName()).contains('\0'));
Result = MaterializedValue::fromSymbol(Function.OriginalName(),
NewAPInt(Addend));
++MatchCount;
+5 -3
View File
@@ -26,9 +26,9 @@ using namespace llvm;
using namespace pipeline;
using namespace ::revng::pipes;
void Lift::run(Context &Ctx,
void Lift::run(ExecutionContext &Ctx,
const BinaryFileContainer &SourceBinary,
LLVMContainer &TargetsList) {
LLVMContainer &Output) {
if (not SourceBinary.exists())
return;
@@ -43,7 +43,9 @@ void Lift::run(Context &Ctx,
PM.add(new LoadModelWrapperPass(Model));
PM.add(new LoadBinaryWrapperPass(Buffer->getBuffer()));
PM.add(new LiftPass);
PM.run(TargetsList.getModule());
PM.run(Output.getModule());
Ctx.commitUniqueTarget(Output);
}
llvm::Error Lift::checkPrecondition(const pipeline::Context &Ctx) const {
+2 -2
View File
@@ -81,12 +81,12 @@ void LinkSupport::print(const pipeline::Context &Ctx,
<< Names[0] << "\n";
}
void revng::pipes::LinkSupport::run(const Context &Ctx,
void revng::pipes::LinkSupport::run(const ExecutionContext &Ctx,
LLVMContainer &TargetsList) {
if (TargetsList.enumerate().empty())
return;
std::string SupportPath = getSupportPath(Ctx);
std::string SupportPath = getSupportPath(Ctx.getContext());
llvm::SMDiagnostic Err;
auto Module = llvm::parseIRFile(SupportPath,
+25
View File
@@ -5,9 +5,12 @@
//
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DOTGraphTraits.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/raw_os_ostream.h"
#include "revng/ADT/GenericGraph.h"
@@ -15,6 +18,7 @@
#include "revng/Model/TypeSystemPrinter.h"
#include "revng/Model/VerifyHelper.h"
#include "revng/Support/OverflowSafeInt.h"
#include "revng/TupleTree/Tracking.h"
using namespace llvm;
@@ -78,6 +82,7 @@ bool Binary::verifyTypes(bool Assert) const {
}
bool Binary::verifyTypes(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
// All types on their own should verify
std::set<Identifier> Names;
for (auto &Type : Types()) {
@@ -95,10 +100,13 @@ bool Binary::verifyTypes(VerifyHelper &VH) const {
}
void Binary::dump() const {
TrackGuard Guard(*this);
serialize(dbg, *this);
}
void Binary::dumpTypeGraph(const char *Path) const {
TrackGuard Guard(*this);
std::error_code EC;
llvm::raw_fd_ostream Out(Path, EC);
if (EC)
@@ -109,6 +117,7 @@ void Binary::dumpTypeGraph(const char *Path) const {
}
std::string Binary::toString() const {
TrackGuard Guard(*this);
std::string S;
llvm::raw_string_ostream OS(S);
serialize(OS, *this);
@@ -152,6 +161,8 @@ bool VerifyHelper::registerGlobalSymbol(const model::Identifier &Name,
static bool verifyGlobalNamespace(VerifyHelper &VH,
const model::Binary &Model) {
auto Guard = VH.suspendTracking(Model);
// Namespacing rules:
//
// 1. each struct/union induces a namespace for its field names;
@@ -197,6 +208,8 @@ static bool verifyGlobalNamespace(VerifyHelper &VH,
bool Binary::verify(VerifyHelper &VH) const {
// First of all, verify the global namespace: we need to fully populate it
// before we can verify namespaces with smaller scopes
auto Guard = VH.suspendTracking(*this);
if (not verifyGlobalNamespace(VH, *this))
return VH.fail();
@@ -282,6 +295,8 @@ bool Relocation::verify(bool Assert) const {
}
bool Relocation::verify(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
if (Type() == model::RelocationType::Invalid)
return VH.fail("Invalid relocation", *this);
@@ -298,6 +313,7 @@ bool Section::verify(bool Assert) const {
}
bool Section::verify(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
auto EndAddress = StartAddress() + Size();
if (not EndAddress.isValid())
return VH.fail("Computing the end address leads to overflow");
@@ -318,6 +334,7 @@ Identifier Segment::name() const {
}
void Segment::dump() const {
TrackGuard Guard(*this);
serialize(dbg, *this);
}
@@ -331,6 +348,7 @@ bool Segment::verify(bool Assert) const {
}
bool Segment::verify(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
using OverflowSafeInt = OverflowSafeInt<uint64_t>;
if (FileSize() > VirtualSize())
@@ -394,10 +412,12 @@ bool Segment::verify(VerifyHelper &VH) const {
}
void Function::dump() const {
TrackGuard Guard(*this);
serialize(dbg, *this);
}
void Function::dumpTypeGraph(const char *Path) const {
TrackGuard Guard(*this);
std::error_code EC;
llvm::raw_fd_ostream Out(Path, EC);
if (EC)
@@ -417,6 +437,7 @@ bool Function::verify(bool Assert) const {
}
bool Function::verify(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
if (not Entry().isValid())
return VH.fail("Invalid Entry", *this);
@@ -459,6 +480,7 @@ bool Function::verify(VerifyHelper &VH) const {
}
void DynamicFunction::dump() const {
TrackGuard Guard(*this);
serialize(dbg, *this);
}
@@ -472,6 +494,7 @@ bool DynamicFunction::verify(bool Assert) const {
}
bool DynamicFunction::verify(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
// Ensure we have a name
if (OriginalName().size() == 0)
return VH.fail("Dynamic functions must have a OriginalName", *this);
@@ -501,6 +524,7 @@ bool DynamicFunction::verify(VerifyHelper &VH) const {
}
void CallSitePrototype::dump() const {
TrackGuard Guard(*this);
serialize(dbg, *this);
}
@@ -514,6 +538,7 @@ bool CallSitePrototype::verify(bool Assert) const {
}
bool CallSitePrototype::verify(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
if (Prototype().empty() or not Prototype().isValid())
return VH.fail("Invalid prototype");
@@ -16,7 +16,7 @@
using namespace revng::pipes;
llvm::Error ImportBinaryAnalysis::run(pipeline::Context &Context,
llvm::Error ImportBinaryAnalysis::run(pipeline::ExecutionContext &Context,
const BinaryFileContainer &SourceBinary) {
if (not SourceBinary.exists())
return llvm::Error::success();
+1 -1
View File
@@ -46,7 +46,7 @@ public:
std::vector<std::vector<pipeline::Kind *>> AcceptedKinds;
public:
llvm::Error run(pipeline::Context &Context) {
llvm::Error run(pipeline::ExecutionContext &Context) {
std::vector<std::unique_ptr<WellKnownModel>> WellKnownModels;
std::map<WellKnownFunctionKey,
std::pair<WellKnownModel *, model::Function *>>
+1 -1
View File
@@ -13,7 +13,7 @@
namespace revng::pipes {
void AddPrimitiveTypesAnalysis::run(pipeline::Context &Context) {
void AddPrimitiveTypesAnalysis::run(pipeline::ExecutionContext &Context) {
model::addPrimitiveTypes(getWritableModelFromContext(Context));
}
+32
View File
@@ -11,6 +11,7 @@
#include <type_traits>
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/MathExtras.h"
@@ -343,6 +344,7 @@ Identifier model::Type::name() const {
}
void Qualifier::dump() const {
TrackGuard Guard(*this);
serialize(dbg, *this);
}
@@ -356,6 +358,8 @@ bool Qualifier::verify(bool Assert) const {
}
bool Qualifier::verify(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
switch (Kind()) {
case QualifierKind::Invalid:
return VH.fail("Invalid qualifier found", *this);
@@ -597,6 +601,7 @@ PrimitiveType::PrimitiveType(uint64_t ID) :
}
void EnumEntry::dump() const {
TrackGuard Guard(*this);
serialize(dbg, *this);
}
@@ -625,6 +630,7 @@ std::optional<uint64_t> QualifiedType::trySize() const {
RecursiveCoroutine<std::optional<uint64_t>>
QualifiedType::size(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
std::optional<uint64_t> MaybeSize = rc_recur trySize(VH);
revng_check(MaybeSize);
if (*MaybeSize == 0)
@@ -635,6 +641,7 @@ QualifiedType::size(VerifyHelper &VH) const {
RecursiveCoroutine<std::optional<uint64_t>>
QualifiedType::trySize(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
// This code assumes that the QualifiedType QT is well formed.
auto QIt = Qualifiers().begin();
auto QEnd = Qualifiers().end();
@@ -832,6 +839,7 @@ std::optional<uint64_t> Type::trySize() const {
}
std::optional<uint64_t> Type::size(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
std::optional<uint64_t> MaybeSize = trySize(VH);
revng_check(MaybeSize);
if (*MaybeSize == 0)
@@ -846,6 +854,7 @@ std::optional<uint64_t> Type::size(VerifyHelper &VH) const {
// to its little brother as well.
RecursiveCoroutine<std::optional<uint64_t>>
Type::trySize(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
auto MaybeSize = VH.size(this);
if (MaybeSize)
rc_return MaybeSize;
@@ -923,6 +932,7 @@ Type::trySize(VerifyHelper &VH) const {
static RecursiveCoroutine<bool> verifyImpl(VerifyHelper &VH,
const PrimitiveType *T) {
auto Guard = VH.suspendTracking(*T);
revng_assert(T->Kind() == TypeKind::PrimitiveType);
if (not T->CustomName().empty() or not T->OriginalName().empty())
@@ -973,6 +983,8 @@ bool Identifier::verify(VerifyHelper &VH) const {
static RecursiveCoroutine<bool> verifyImpl(VerifyHelper &VH,
const EnumType *T) {
auto Guard = VH.suspendTracking(*T);
if (T->Kind() != TypeKind::EnumType or T->Entries().empty()
or not T->CustomName().verify(VH))
rc_return VH.fail();
@@ -1002,6 +1014,7 @@ static RecursiveCoroutine<bool> verifyImpl(VerifyHelper &VH,
static RecursiveCoroutine<bool> verifyImpl(VerifyHelper &VH,
const TypedefType *T) {
auto Guard = VH.suspendTracking(*T);
rc_return VH.maybeFail(T->CustomName().verify(VH)
and T->Kind() == TypeKind::TypedefType
and rc_recur T->UnderlyingType().verify(VH));
@@ -1042,6 +1055,8 @@ bool model::QualifiedType::isScalar() const {
static RecursiveCoroutine<bool> verifyImpl(VerifyHelper &VH,
const StructType *T) {
auto Guard = VH.suspendTracking(*T);
using namespace llvm;
revng_assert(T->Kind() == TypeKind::StructType);
@@ -1118,6 +1133,7 @@ static RecursiveCoroutine<bool> verifyImpl(VerifyHelper &VH,
static RecursiveCoroutine<bool> verifyImpl(VerifyHelper &VH,
const UnionType *T) {
auto Guard = VH.suspendTracking(*T);
revng_assert(T->Kind() == TypeKind::UnionType);
if (not T->CustomName().verify(VH))
@@ -1163,6 +1179,8 @@ static RecursiveCoroutine<bool> verifyImpl(VerifyHelper &VH,
static RecursiveCoroutine<bool> verifyImpl(VerifyHelper &VH,
const CABIFunctionType *T) {
auto Guard = VH.suspendTracking(*T);
if (not T->CustomName().verify(VH) or T->Kind() != TypeKind::CABIFunctionType
or not rc_recur T->ReturnType().verify(VH))
rc_return VH.fail();
@@ -1269,6 +1287,8 @@ bool Type::verify(bool Assert) const {
}
RecursiveCoroutine<bool> Type::verify(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
if (VH.isVerified(this))
rc_return true;
@@ -1326,6 +1346,7 @@ RecursiveCoroutine<bool> Type::verify(VerifyHelper &VH) const {
}
void QualifiedType::dump() const {
TrackGuard Guard(*this);
serialize(dbg, *this);
}
@@ -1339,6 +1360,8 @@ bool QualifiedType::verify(bool Assert) const {
}
RecursiveCoroutine<bool> QualifiedType::verify(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
if (not UnqualifiedType().isValid())
rc_return VH.fail("Underlying type is invalid", *this);
@@ -1423,6 +1446,7 @@ verifyTypedRegisterCommon(const T &TypedRegister, VerifyHelper &VH) {
}
void TypedRegister::dump() const {
TrackGuard Guard(*this);
serialize(dbg, *this);
}
@@ -1436,10 +1460,12 @@ bool TypedRegister::verify(bool Assert) const {
}
RecursiveCoroutine<bool> TypedRegister::verify(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
rc_return verifyTypedRegisterCommon(this, VH);
}
void NamedTypedRegister::dump() const {
TrackGuard Guard(*this);
serialize(dbg, *this);
}
@@ -1453,6 +1479,7 @@ bool NamedTypedRegister::verify(bool Assert) const {
}
RecursiveCoroutine<bool> NamedTypedRegister::verify(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
// Ensure the name is valid
if (not CustomName().verify(VH))
rc_return VH.fail();
@@ -1470,6 +1497,7 @@ bool StructField::verify(bool Assert) const {
}
RecursiveCoroutine<bool> StructField::verify(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
if (not rc_recur Type().verify(VH))
rc_return VH.fail("Aggregate field type is not valid");
@@ -1491,6 +1519,8 @@ bool UnionField::verify(bool Assert) const {
}
RecursiveCoroutine<bool> UnionField::verify(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
if (not rc_recur Type().verify(VH))
rc_return VH.fail("Aggregate field type is not valid");
@@ -1503,6 +1533,7 @@ RecursiveCoroutine<bool> UnionField::verify(VerifyHelper &VH) const {
}
void Argument::dump() const {
TrackGuard Guard(*this);
serialize(dbg, *this);
}
@@ -1516,6 +1547,7 @@ bool Argument::verify(bool Assert) const {
}
RecursiveCoroutine<bool> Argument::verify(VerifyHelper &VH) const {
auto Guard = VH.suspendTracking(*this);
rc_return VH.maybeFail(CustomName().verify(VH)
and rc_recur Type().verify(VH));
}
+1
View File
@@ -18,6 +18,7 @@ revng_add_library_internal(
RegisterKind.cpp
Registry.cpp
Step.cpp
ExecutionContext.cpp
Target.cpp
Global.cpp
GlobalsMap.cpp)
+55
View File
@@ -0,0 +1,55 @@
/// \file ExecutionContext.cpp
/// \brief
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include "revng/Pipeline/Context.h"
#include "revng/Pipeline/ExecutionContext.h"
#include "revng/Pipeline/Step.h"
#include "revng/Pipeline/Target.h"
using namespace pipeline;
ExecutionContext::ExecutionContext(Context &Ctx,
Step &Step,
PipeWrapper *Pipe) :
TheContext(&Ctx),
CurrentStep(&Step),
Pipe(Pipe),
RunningOnPipe(Pipe != nullptr) {
// pipe is null when execution a analysis. We could just provide a context to
// analyses, for the sake of uniformity we pass a execution context to them
// too.
if (RunningOnPipe)
getContext().clearAndResume();
}
pipeline::ExecutionContext::~ExecutionContext() {
if (RunningOnPipe)
getContext().stopTracking();
}
void ExecutionContext::commit(const Target &Target,
llvm::StringRef ContainerName) {
revng_assert(Pipe != nullptr);
TargetInContainer ToCollect(Target, ContainerName.str());
getContext().collectReadFields(ToCollect,
Pipe->InvalidationMetadata.getPathCache());
}
void ExecutionContext::clearAndResumeTracking() {
getContext().clearAndResume();
}
void ExecutionContext::commitUniqueTarget(const ContainerBase &Container) {
auto Enumeration = Container.enumerate();
revng_check(Enumeration.size() == 1);
commit(Enumeration[0], Container.name());
}
void ExecutionContext::commit(const ContainerBase &Container,
const Target &Target) {
commit(Target, Container.name());
}
+1 -1
View File
@@ -29,7 +29,7 @@ std::unique_ptr<LLVMPassWrapperBase> PureLLVMPassWrapper::clone() const {
return std::make_unique<PureLLVMPassWrapper>(*this);
}
void GenericLLVMPipe::run(const Context &, LLVMContainer &Container) {
void GenericLLVMPipe::run(const ExecutionContext &, LLVMContainer &Container) {
llvm::legacy::PassManager Manager;
for (const auto &Element : Passes)
Element->registerPasses(Manager);
+1 -1
View File
@@ -148,7 +148,7 @@ Loader::parseInvocation(Step &Step,
continue;
const auto &RoleName = ReadOnlyNames.find(ContainerName)->second;
if (Pipe->isContainerArgumentConst(Index))
if (Pipe.Pipe->isContainerArgumentConst(Index))
continue;
if (PipelineContext->hasRegisteredReadOnlyContainer(ContainerName)) {
+60 -57
View File
@@ -40,11 +40,11 @@ static Error getObjectives(Runner &Runner,
const ContainerToTargetsMap &Targets,
std::vector<PipelineExecutionEntry> &ToExec) {
ContainerToTargetsMap ToLoad = Targets;
auto *CurrentStep = &(Runner[EndingStepName]);
Step *CurrentStep = &(Runner[EndingStepName]);
while (CurrentStep != nullptr and not ToLoad.empty()) {
ContainerToTargetsMap Output = ToLoad;
ToLoad = CurrentStep->analyzeGoals(Runner.getContext(), ToLoad);
ToLoad = CurrentStep->analyzeGoals(ToLoad);
ToExec.emplace_back(*CurrentStep, Output, ToLoad);
CurrentStep = CurrentStep->hasPredecessor() ?
&CurrentStep->getPredecessor() :
@@ -82,7 +82,7 @@ static void explainPipeline(const ContainerToTargetsMap &Targets,
for (size_t I = Requirements.size(); I != 0; I--) {
StringRef StepName = Requirements[I - 1].ToExecute->getName();
const auto &TargetsNeeded = Requirements[I - 1].Input;
const ContainerToTargetsMap &TargetsNeeded = Requirements[I - 1].Input;
indent(ExplanationLogger, 1);
ExplanationLogger << StepName << ":\n";
@@ -92,9 +92,9 @@ static void explainPipeline(const ContainerToTargetsMap &Targets,
ExplanationLogger << DoLog;
}
Error Runner::getInvalidations(InvalidationMap &Invalidated) const {
Error Runner::getInvalidations(TargetInStepSet &Invalidated) const {
for (const auto &NextS : *this) {
for (const Step &NextS : *this) {
if (not NextS.hasPredecessor())
continue;
@@ -104,7 +104,7 @@ Error Runner::getInvalidations(InvalidationMap &Invalidated) const {
ContainerToTargetsMap &Outputs = Invalidated[NextS.getName()];
auto Deduced = NextS.deduceResults(getContext(), Inputs);
ContainerToTargetsMap Deduced = NextS.deduceResults(Inputs);
NextS.containers().intersect(Deduced);
Outputs.merge(Deduced);
}
@@ -121,8 +121,8 @@ Step &Runner::addStep(Step &&NewStep) {
}
llvm::Error Runner::getInvalidations(const Target &Target,
InvalidationMap &Invalidations) const {
for (const auto &Step : *this)
TargetInStepSet &Invalidations) const {
for (const Step &Step : *this)
for (const auto &Container : Step.containers()) {
if (Container.second == nullptr)
continue;
@@ -131,7 +131,7 @@ llvm::Error Runner::getInvalidations(const Target &Target,
Invalidations[Step.getName()].add(Container.first(), Target);
}
}
if (auto Error = getInvalidations(Invalidations); !!Error)
if (llvm::Error Error = getInvalidations(Invalidations); !!Error)
return Error;
return llvm::Error::success();
@@ -139,7 +139,7 @@ llvm::Error Runner::getInvalidations(const Target &Target,
Error Runner::invalidate(const Target &Target) {
llvm::StringMap<ContainerToTargetsMap> Invalidations;
if (auto Error = getInvalidations(Target, Invalidations); !!Error)
if (llvm::Error Error = getInvalidations(Target, Invalidations); !!Error)
return Error;
return invalidate(Invalidations);
}
@@ -192,7 +192,7 @@ Error Runner::store(const revng::DirectoryPath &DirPath) const {
return Error;
for (const auto &StepName : Steps.keys()) {
if (auto Error = storeStepToDisk(StepName, DirPath); !!Error) {
if (llvm::Error Error = storeStepToDisk(StepName, DirPath); !!Error) {
return Error;
}
}
@@ -240,10 +240,10 @@ llvm::Expected<DiffMap>
Runner::runAnalysis(llvm::StringRef AnalysisName,
llvm::StringRef StepName,
const ContainerToTargetsMap &Targets,
InvalidationMap &InvalidationsMap,
TargetInStepSet &InvalidationsMap,
const llvm::StringMap<std::string> &Options) {
auto Before = getContext().getGlobals();
GlobalsMap Before = getContext().getGlobals();
auto MaybeStep = Steps.find(StepName);
@@ -255,23 +255,22 @@ Runner::runAnalysis(llvm::StringRef AnalysisName,
Task T(3, "Analysis execution");
T.advance("Produce step " + StepName, true);
if (auto Error = run(StepName, Targets))
if (llvm::Error Error = run(StepName, Targets))
return std::move(Error);
T.advance("Run analysis", true);
if (auto Error = MaybeStep->second.runAnalysis(AnalysisName,
*TheContext,
Targets,
Options);
if (llvm::Error Error = MaybeStep->second.runAnalysis(AnalysisName,
Targets,
Options);
Error) {
return std::move(Error);
}
T.advance("Apply diff produced by the analysis", true);
auto &After = getContext().getGlobals();
auto Map = Before.diff(After);
const GlobalsMap &After = getContext().getGlobals();
DiffMap Map = Before.diff(After);
for (const auto &GlobalNameDiffPair : Map)
if (auto Error = apply(GlobalNameDiffPair.second, InvalidationsMap))
if (llvm::Error Error = apply(GlobalNameDiffPair.second, InvalidationsMap))
return std::move(Error);
return std::move(Map);
@@ -280,17 +279,18 @@ Runner::runAnalysis(llvm::StringRef AnalysisName,
/// Run all analysis in reverse post order (that is: parents first),
llvm::Expected<DiffMap>
Runner::runAnalyses(const AnalysesList &List,
InvalidationMap &InvalidationsMap,
TargetInStepSet &InvalidationsMap,
const llvm::StringMap<std::string> &Options) {
auto Before = getContext().getGlobals();
GlobalsMap Before = getContext().getGlobals();
Task T(List.size() + 1, "Analysis list " + List.getName());
for (const AnalysisReference &Ref : List) {
T.advance(Ref.getAnalysisName(), true);
const auto &Step = getStep(Ref.getStepName());
const auto &Analysis = Step.getAnalysis(Ref.getAnalysisName());
const Step &Step = getStep(Ref.getStepName());
const AnalysisWrapper &Analysis = Step.getAnalysis(Ref.getAnalysisName());
ContainerToTargetsMap Map;
const auto &Containers = Analysis->getRunningContainersNames();
const std::vector<std::string>
&Containers = Analysis->getRunningContainersNames();
for (size_t I = 0; I < Containers.size(); I++) {
for (const Kind *K : Analysis->getAcceptedKinds(I)) {
Map.add(Containers[I], TargetsList::allTargets(getContext(), *K));
@@ -307,7 +307,7 @@ Runner::runAnalyses(const AnalysesList &List,
}
T.advance("Computing analysis list diff", true);
auto &After = getContext().getGlobals();
const GlobalsMap &After = getContext().getGlobals();
return Before.diff(After);
}
@@ -315,7 +315,7 @@ Error Runner::run(const State &ToProduce) {
Task T(ToProduce.size(), "Multi-step pipeline run");
for (const auto &Request : ToProduce) {
T.advance(Request.first(), true);
if (auto Error = run(Request.first(), Request.second))
if (llvm::Error Error = run(Request.first(), Request.second))
return Error;
}
@@ -327,7 +327,8 @@ Error Runner::run(llvm::StringRef EndingStepName,
vector<PipelineExecutionEntry> ToExec;
if (auto Error = getObjectives(*this, EndingStepName, Targets, ToExec); Error)
if (llvm::Error Error = getObjectives(*this, EndingStepName, Targets, ToExec);
Error)
return Error;
explainPipeline(Targets, ToExec);
@@ -335,9 +336,9 @@ Error Runner::run(llvm::StringRef EndingStepName,
if (ToExec.size() <= 1)
return Error::success();
for (auto &StepGoalsPairs : llvm::drop_begin(ToExec)) {
auto &Step = *StepGoalsPairs.ToExecute;
if (auto Error = Step.checkPrecondition(getContext()); Error)
for (PipelineExecutionEntry &StepGoalsPairs : llvm::drop_begin(ToExec)) {
Step &Step = *StepGoalsPairs.ToExecute;
if (llvm::Error Error = Step.checkPrecondition(); Error)
return llvm::make_error<AnnotatedError>(std::move(Error),
"While scheduling step "
+ Step.getName() + ":");
@@ -351,16 +352,16 @@ Error Runner::run(llvm::StringRef EndingStepName,
Task T2(3, "Run step");
T2.advance("Clone and filter input containers", true);
auto &Parent = Step->getPredecessor();
auto CurrentContainer = Parent.containers().cloneFiltered(Input);
::Step &Parent = Step->getPredecessor();
ContainerSet CurrentContainer = Parent.containers().cloneFiltered(Input);
// Run the step
T2.advance("Run the step", true);
Step->run(*TheContext, std::move(CurrentContainer));
Step->run(std::move(CurrentContainer));
T2.advance("Extract the requested targets", true);
if (VerifyLog.isEnabled()) {
auto Produced = Step->containers().cloneFiltered(PredictedOutput);
ContainerSet Produced = Step->containers().cloneFiltered(PredictedOutput);
revng_check(Produced.enumerate().contains(PredictedOutput),
"predicted output was not fully contained in actually "
"produced");
@@ -381,11 +382,11 @@ Error Runner::run(llvm::StringRef EndingStepName,
return Error::success();
}
Error Runner::invalidate(const InvalidationMap &Invalidations) {
Error Runner::invalidate(const TargetInStepSet &Invalidations) {
for (const auto &Step : Invalidations) {
const auto &StepName = Step.first();
const auto &ToRemove = Step.second;
if (auto Error = operator[](StepName).invalidate(ToRemove); Error)
llvm::StringRef StepName = Step.first();
const ContainerToTargetsMap &ToRemove = Step.second;
if (llvm::Error Error = operator[](StepName).invalidate(ToRemove); Error)
return Error;
}
return Error::success();
@@ -406,7 +407,7 @@ void Runner::deduceAllPossibleTargets(State &Out) const {
continue;
const Step &Step = NextStep.getPredecessor();
auto Result = NextStep.deduceResults(getContext(), Out[Step.getName()]);
auto Result = NextStep.deduceResults(Out[Step.getName()]);
Out[NextStep.getName()].merge(std::move(Result));
}
}
@@ -415,36 +416,38 @@ const KindsRegistry &Runner::getKindsRegistry() const {
}
void Runner::getDiffInvalidations(const GlobalTupleTreeDiff &Diff,
InvalidationMap &Map) const {
// the custom write invalidation rules do not know what is the current
// content of each container, so first we overestimate the targets to be
// invalidated, and then we do the intersection between the overestimated one
// and those that do exists.
TargetsList OverestimatedTargets;
for (const Kind &Kind : getKindsRegistry())
Kind.getInvalidations(getContext(), OverestimatedTargets, Diff);
TargetInStepSet &Map) const {
for (const auto &Step : llvm::drop_begin(*this)) {
for (const Step &Step : llvm::drop_begin(*this)) {
auto &StepInvalidations = Map[Step.getName()];
for (const auto &Container : Step.containers()) {
if (not Container.second)
continue;
const TargetsList &ExisitingTargets = Container.second->enumerate();
TargetsList NewTargets;
for (const auto &Target : OverestimatedTargets)
if (ExisitingTargets.contains(Target))
NewTargets.emplace_back(Target);
const TargetsList &ExistingTargets = Container.second->enumerate();
// for all targets that are not cached anywhere, mark them to be deleated
// every time, since we must be conservative
for (const Target &Target : ExistingTargets) {
StepInvalidations[Container.first()] = NewTargets;
TargetInContainer ToFind(Target, Container.first().str());
if (Step.invalidationMetadataContains(Diff.getGlobalName(), ToFind))
continue;
StepInvalidations[Container.first()].push_back(Target);
}
}
for (const TupleTreePath *Path : Diff.getPaths()) {
Step.registerTargetsDependingOn(Diff.getGlobalName(), *Path, Map);
}
}
}
llvm::Error Runner::apply(const GlobalTupleTreeDiff &Diff,
InvalidationMap &Map) {
TargetInStepSet &Map) {
getDiffInvalidations(Diff, Map);
if (auto Error = getInvalidations(Map); Error)
return Error;
return invalidate(Map);
}
+325 -33
View File
@@ -24,15 +24,201 @@ using namespace llvm;
using namespace std;
using namespace pipeline;
namespace pipeline {
class TargetInPipe {
public:
std::string SerializedTarget;
std::string PipeName;
llvm::Expected<llvm::SmallVector<TargetInContainer, 2>>
deserialize(const Context &Ctx, llvm::StringRef ContainerName) const;
static TargetInPipe fromTargetInContainer(const TargetInContainer &Target,
llvm::StringRef PipeName);
bool operator<(const TargetInPipe &Other) const {
const auto &Tied = std::tie(SerializedTarget, PipeName);
return Tied < std::tie(Other.SerializedTarget, Other.PipeName);
}
};
class ContainerInvalidationMetadata {
public:
using ValueType = std::pair<pipeline::TargetInPipe, std::vector<std::string>>;
using Vector = std::vector<ValueType>;
Vector Data;
void merge(ContainerInvalidationMetadata &&Other) {
for (ValueType &Entry : Other.Data)
Data.emplace_back(std::move(Entry));
}
public:
llvm::Expected<PathTargetBimap>
deserialize(const Context &Ctx,
const Global &Primitives,
llvm::StringRef PipeName,
llvm::StringRef ContainerName) const;
static ContainerInvalidationMetadata serialize(const PathTargetBimap &Map,
const Global &Primitives,
llvm::StringRef PipeName,
llvm::StringRef ContainerName);
};
class NamedPathTargetBimapVector {
public:
std::string GlobalName;
ContainerInvalidationMetadata Map;
};
} // namespace pipeline
LLVM_YAML_IS_SEQUENCE_VECTOR(ContainerInvalidationMetadata::ValueType);
namespace llvm {
namespace yaml {
// YAML traits for TargetInContainer
template<>
struct MappingTraits<pipeline::TargetInPipe> {
static void mapping(IO &IO, pipeline::TargetInPipe &TargetInContainer) {
IO.mapRequired("Target", TargetInContainer.SerializedTarget);
IO.mapRequired("PipeName", TargetInContainer.PipeName);
}
};
template<>
struct MappingTraits<pipeline::ContainerInvalidationMetadata> {
static void mapping(IO &Io,
pipeline::ContainerInvalidationMetadata &TargetMap) {
Io.mapRequired("Map", TargetMap.Data);
}
};
template<>
struct MappingTraits<ContainerInvalidationMetadata::Vector::value_type> {
static void
mapping(IO &Io,
pipeline::ContainerInvalidationMetadata::Vector::value_type
&TargetMap) {
Io.mapRequired("Target", TargetMap.first.SerializedTarget);
Io.mapRequired("PipeName", TargetMap.first.PipeName);
Io.mapRequired("ReadPaths", TargetMap.second);
}
};
} // namespace yaml
} // namespace llvm
LLVM_YAML_IS_SEQUENCE_VECTOR(pipeline::NamedPathTargetBimapVector);
namespace llvm {
namespace yaml {
template<>
struct MappingTraits<pipeline::NamedPathTargetBimapVector> {
static void mapping(IO &Io, pipeline::NamedPathTargetBimapVector &TargetMap) {
Io.mapRequired("GlobalName", TargetMap.GlobalName);
Io.mapRequired("Map", TargetMap.Map.Data);
}
};
} // namespace yaml
} // namespace llvm
llvm::Expected<llvm::SmallVector<TargetInContainer, 2>>
TargetInPipe::deserialize(const Context &Ctx,
llvm::StringRef ContainerName) const {
TargetsList Targets;
llvm::Error Error = parseTarget(Ctx,
SerializedTarget,
Ctx.getKindsRegistry(),
Targets);
if (Error)
return std::move(Error);
llvm::SmallVector<TargetInContainer, 2> Return;
for (const Target &Target : Targets) {
Return.emplace_back(std::move(Target), ContainerName.str());
}
return Return;
}
TargetInPipe
TargetInPipe::fromTargetInContainer(const TargetInContainer &Target,
llvm::StringRef PipeName) {
TargetInPipe ToReturn;
ToReturn.PipeName = PipeName;
ToReturn.SerializedTarget = Target.getTarget().serialize();
return ToReturn;
}
ContainerInvalidationMetadata
ContainerInvalidationMetadata::serialize(const PathTargetBimap &Map,
const Global &Global,
llvm::StringRef PipeName,
llvm::StringRef ContainerName) {
ContainerInvalidationMetadata ToSerialize;
std::map<pipeline::TargetInPipe, std::vector<std::string>> TemporaryMap;
for (const auto &Content : Map) {
for (const TargetInContainer &Entry : Content.second) {
if (Entry.getContainerName() != ContainerName)
continue;
std::optional<std::string> AsString = Global.serializePath(Content.first);
revng_check(AsString.has_value());
TemporaryMap[TargetInPipe::fromTargetInContainer(Entry, PipeName)]
.push_back(*AsString);
}
}
for (const auto &Content : TemporaryMap) {
std::pair ToEmplace{ Content.first, Content.second };
ToSerialize.Data.emplace_back(std::move(ToEmplace));
}
return ToSerialize;
}
llvm::Expected<PathTargetBimap>
ContainerInvalidationMetadata::deserialize(const Context &Ctx,
const Global &Global,
llvm::StringRef PipeName,
llvm::StringRef ContainerName)
const {
PathTargetBimap ToReturn;
for (const ValueType &Entry : Data) {
if (Entry.first.PipeName != PipeName)
continue;
llvm::Expected<SmallVector<TargetInContainer>>
MaybeTarget = Entry.first.deserialize(Ctx, ContainerName);
if (not MaybeTarget)
return MaybeTarget.takeError();
for (auto &SerializedPath : Entry.second) {
std::optional<TupleTreePath>
MaybeParsedPath = Global.deserializePath(SerializedPath);
if (not MaybeParsedPath)
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"could not parse " + SerializedPath);
for (const TargetInContainer &Path : *MaybeTarget)
ToReturn.insert(std::move(Path), std::move(*MaybeParsedPath));
}
}
return ToReturn;
}
ContainerToTargetsMap
Step::analyzeGoals(const Context &Ctx,
const ContainerToTargetsMap &RequiredGoals) const {
Step::analyzeGoals(const ContainerToTargetsMap &RequiredGoals) const {
ContainerToTargetsMap AlreadyAvailable;
ContainerToTargetsMap Targets = RequiredGoals;
removeSatisfiedGoals(Targets, AlreadyAvailable);
for (const auto &Pipe : llvm::make_range(Pipes.rbegin(), Pipes.rend())) {
Targets = Pipe->getRequirements(Ctx, Targets);
for (const PipeWrapper &Pipe :
llvm::make_range(Pipes.rbegin(), Pipes.rend())) {
Targets = Pipe.Pipe->getRequirements(*Ctx, Targets);
}
return Targets;
@@ -60,13 +246,12 @@ void Step::explainEndStep(const ContainerToTargetsMap &Targets,
ExplanationLogger << DoLog;
}
void Step::explainExecutedPipe(const Context &Ctx,
const InvokableWrapperBase &Wrapper,
void Step::explainExecutedPipe(const InvokableWrapperBase &Wrapper,
size_t Indentation) const {
ExplanationLogger << "RUN " << Wrapper.getName();
ExplanationLogger << "(";
auto Vec = Wrapper.getRunningContainersNames();
std::vector<std::string> Vec = Wrapper.getRunningContainersNames();
if (not Vec.empty()) {
for (size_t I = 0; I < Vec.size() - 1; I++) {
ExplanationLogger << Vec[I];
@@ -80,49 +265,50 @@ void Step::explainExecutedPipe(const Context &Ctx,
ExplanationLogger << DoLog;
auto CommandStream = CommandLogger.getAsLLVMStream();
Wrapper.print(Ctx, *CommandStream, Indentation);
Wrapper.print(*Ctx, *CommandStream, Indentation);
CommandStream->flush();
CommandLogger << DoLog;
}
ContainerSet Step::run(Context &Ctx, ContainerSet &&Input) {
auto InputEnumeration = Input.enumerate();
ContainerSet Step::run(ContainerSet &&Input) {
ContainerToTargetsMap InputEnumeration = Input.enumerate();
explainStartStep(InputEnumeration);
Task T(Pipes.size() + 1, "Step " + getName());
for (PipeWrapper &Pipe : Pipes) {
T.advance(Pipe->getName(), false);
explainExecutedPipe(Ctx, *Pipe);
cantFail(Pipe->run(Ctx, Input));
T.advance(Pipe.Pipe->getName(), false);
explainExecutedPipe(*Pipe.Pipe);
ExecutionContext Context(*Ctx, *this, &Pipe);
cantFail(Pipe.Pipe->run(Context, Input));
llvm::cantFail(Input.verify());
}
T.advance("Merging back", true);
explainEndStep(Input.enumerate());
Containers.mergeBack(std::move(Input));
InputEnumeration = deduceResults(Ctx, InputEnumeration);
auto Cloned = Containers.cloneFiltered(InputEnumeration);
InputEnumeration = deduceResults(InputEnumeration);
ContainerSet Cloned = Containers.cloneFiltered(InputEnumeration);
return Cloned;
}
llvm::Error Step::runAnalysis(llvm::StringRef AnalysisName,
Context &Ctx,
const ContainerToTargetsMap &Targets,
const llvm::StringMap<std::string> &ExtraArgs) {
auto Stream = ExplanationLogger.getAsLLVMStream();
ContainerToTargetsMap Map = Containers.enumerate();
auto CollapsedTargets = Targets;
ContainerToTargetsMap CollapsedTargets = Targets;
revng_assert(Map.contains(CollapsedTargets),
"An analysis was requested, but not all targets are available");
auto &TheAnalysis = getAnalysis(AnalysisName);
AnalysisWrapper &TheAnalysis = getAnalysis(AnalysisName);
explainExecutedPipe(Ctx, *TheAnalysis);
explainExecutedPipe(*TheAnalysis);
auto Cloned = Containers.cloneFiltered(Targets);
return TheAnalysis->run(Ctx, Cloned, ExtraArgs);
ContainerSet Cloned = Containers.cloneFiltered(Targets);
ExecutionContext ExecutionCtx(*Ctx, *this, nullptr);
return TheAnalysis->run(ExecutionCtx, Cloned, ExtraArgs);
}
void Step::removeSatisfiedGoals(TargetsList &RequiredInputs,
@@ -144,8 +330,8 @@ void Step::removeSatisfiedGoals(ContainerToTargetsMap &Targets,
ContainerToTargetsMap &ToLoad) const {
for (auto &RequiredInputsFromContainer : Targets) {
llvm::StringRef ContainerName = RequiredInputsFromContainer.first();
auto &RequiredInputs = RequiredInputsFromContainer.second;
auto &ToLoadFromCurrentContainer = ToLoad[ContainerName];
TargetsList &RequiredInputs = RequiredInputsFromContainer.second;
TargetsList &ToLoadFromCurrentContainer = ToLoad[ContainerName];
if (Containers.contains(ContainerName))
removeSatisfiedGoals(RequiredInputs,
Containers.at(ContainerName),
@@ -153,31 +339,137 @@ void Step::removeSatisfiedGoals(ContainerToTargetsMap &Targets,
}
}
ContainerToTargetsMap Step::deduceResults(const Context &Ctx,
ContainerToTargetsMap Input) const {
for (const auto &Pipe : Pipes)
Input = Pipe->deduceResults(Ctx, Input);
ContainerToTargetsMap Step::deduceResults(ContainerToTargetsMap Input) const {
for (const PipeWrapper &Pipe : Pipes)
Input = Pipe.Pipe->deduceResults(*Ctx, Input);
return Input;
}
Error Step::invalidate(const ContainerToTargetsMap &ToRemove) {
for (auto &Pipe : Pipes) {
Pipe.InvalidationMetadata.remove(ToRemove);
}
return containers().remove(ToRemove);
}
Error Step::store(const revng::DirectoryPath &DirPath) const {
return Containers.store(DirPath);
if (auto Error = Containers.store(DirPath))
return Error;
return storeInvalidationMetadata(DirPath);
}
Error Step::checkPrecondition(const Context &Ctx) const {
for (const auto &Pipe : Pipes) {
if (auto Error = Pipe->checkPrecondition(Ctx); Error)
Error Step::checkPrecondition() const {
for (const PipeWrapper &Pipe : Pipes) {
if (llvm::Error Error = Pipe.Pipe->checkPrecondition(*Ctx); Error)
return llvm::make_error<AnnotatedError>(std::move(Error),
"While scheduling pipe "
+ Pipe->getName() + ":");
+ Pipe.Pipe->getName() + ":");
}
return llvm::Error::success();
}
Error Step::load(const revng::DirectoryPath &DirPath) {
return Containers.load(DirPath);
auto MaybeBool = DirPath.exists();
if (not MaybeBool)
return MaybeBool.takeError();
if (not MaybeBool.get())
return llvm::Error::success();
if (auto Error = Containers.load(DirPath))
return Error;
return loadInvalidationMetadata(DirPath);
}
llvm::Error
Step::loadInvalidationMetadataImpl(const revng::DirectoryPath &Path,
ContainerSet::value_type &Container) {
auto FilePath = Path.getFile(Container.first().str() + ".cache");
auto MaybeBool = FilePath.exists();
if (not MaybeBool)
return MaybeBool.takeError();
if (not MaybeBool.get())
return llvm::Error::success();
auto File = FilePath.getReadableFile();
if (not File)
return File.takeError();
using Type = llvm::SmallVector<NamedPathTargetBimapVector, 2>;
auto Parsed = ::deserialize<Type>(File.get()->buffer().getBuffer());
if (not Parsed)
return Parsed.takeError();
for (PipeWrapper &Pipe : Pipes) {
for (NamedPathTargetBimapVector &Entry : *Parsed) {
Global *Global = llvm::cantFail(Ctx->getGlobals().get(Entry.GlobalName));
auto Parsed(Entry.Map.deserialize(*Ctx,
*Global,
Pipe.Pipe->getName(),
Container.first()));
if (not Parsed)
return Parsed.takeError();
Pipe.InvalidationMetadata.getPathCache(Global->getName())
.merge(std::move(*Parsed));
}
}
return llvm::Error::success();
}
llvm::Error Step::loadInvalidationMetadata(const revng::DirectoryPath &Path) {
for (PipeWrapper &Pipe : Pipes) {
Pipe.InvalidationMetadata = {};
}
for (auto &Container : Containers) {
if (llvm::Error Error = loadInvalidationMetadataImpl(Path, Container))
return Error;
}
return llvm::Error::success();
}
llvm::Error
Step::storeInvalidationMetadata(const revng::DirectoryPath &Path) const {
for (auto &Container : Containers) {
if (Container.second == nullptr)
continue;
using Type = llvm::SmallVector<NamedPathTargetBimapVector, 2>;
Type ToStore = {};
for (const Global *Global : Ctx->getGlobals()) {
NamedPathTargetBimapVector Entry;
Entry.GlobalName = Global->getName();
for (const PipeWrapper &Pipe : Pipes) {
auto &PathCache = Pipe.InvalidationMetadata.getPathCache();
if (PathCache.count(Entry.GlobalName) == 0)
continue;
using MetadataType = ContainerInvalidationMetadata;
auto Serialize = MetadataType::serialize;
MetadataType Serialized = Serialize(Pipe.InvalidationMetadata
.getPathCache(Entry.GlobalName),
*Global,
Pipe.Pipe->getName(),
Container.first());
Entry.Map.merge(std::move(Serialized));
}
ToStore.emplace_back(std::move(Entry));
}
auto File = Path.getFile(Container.first().str() + ".cache")
.getWritableFile();
if (not File)
return File.takeError();
::serialize(File->get()->os(), ToStore);
if (auto Error = File->get()->commit())
return Error;
}
return llvm::Error::success();
}
+36
View File
@@ -0,0 +1,36 @@
/// \file ApplyDiffAnalysis.cpp
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include "llvm/Support/Error.h"
#include "revng/Pipeline/Context.h"
#include "revng/Pipeline/RegisterAnalysis.h"
#include "revng/Pipes/ApplyDiffAnalysis.h"
#include "revng/Pipes/ModelGlobal.h"
#include "revng/Support/YAMLTraits.h"
#include "revng/TupleTree/TupleTreeDiff.h"
namespace revng::pipes {
llvm::Error ApplyDiffAnalysis::run(pipeline::ExecutionContext &Ctx,
std::string DiffLocation) {
if (DiffLocation == "")
return llvm::Error::success();
auto &Model = getWritableModelFromContext(Ctx);
using DiffT = TupleTreeDiff<model::Binary>;
auto MaybeDiff = deserializeFileOrSTDIN<DiffT>(DiffLocation);
if (!MaybeDiff)
return MaybeDiff.takeError();
return MaybeDiff->apply(Model);
}
static pipeline::RegisterAnalysis<ApplyDiffAnalysis> X;
} // namespace revng::pipes
+10 -9
View File
@@ -16,7 +16,7 @@
namespace revng::pipes {
template<bool commit>
static llvm::Error applyDiffImpl(pipeline::Context &Ctx,
static llvm::Error applyDiffImpl(pipeline::ExecutionContext &Ctx,
std::string DiffGlobalName,
std::string DiffContent) {
if (DiffGlobalName.empty()) {
@@ -27,7 +27,7 @@ static llvm::Error applyDiffImpl(pipeline::Context &Ctx,
std::unique_ptr<llvm::MemoryBuffer>
Buffer = llvm::MemoryBuffer::getMemBuffer(DiffContent);
auto GlobalOrError = Ctx.getGlobals().get(DiffGlobalName);
auto GlobalOrError = Ctx.getContext().getGlobals().get(DiffGlobalName);
if (not GlobalOrError)
return GlobalOrError.takeError();
@@ -54,20 +54,20 @@ static llvm::Error applyDiffImpl(pipeline::Context &Ctx,
return llvm::Error::success();
}
llvm::Error ApplyDiffAnalysis::run(pipeline::Context &Ctx,
llvm::Error ApplyDiffAnalysis::run(pipeline::ExecutionContext &Ctx,
std::string DiffGlobalName,
std::string DiffContent) {
return applyDiffImpl<true>(Ctx, DiffGlobalName, DiffContent);
}
llvm::Error VerifyDiffAnalysis::run(pipeline::Context &Ctx,
llvm::Error VerifyDiffAnalysis::run(pipeline::ExecutionContext &Ctx,
std::string DiffGlobalName,
std::string DiffContent) {
return applyDiffImpl<false>(Ctx, DiffGlobalName, DiffContent);
}
template<bool commit>
inline llvm::Error setGlobalImpl(pipeline::Context &Ctx,
inline llvm::Error setGlobalImpl(pipeline::ExecutionContext &Ctx,
std::string SetGlobalName,
std::string GlobalContent) {
if (SetGlobalName.empty()) {
@@ -78,7 +78,8 @@ inline llvm::Error setGlobalImpl(pipeline::Context &Ctx,
std::unique_ptr<llvm::MemoryBuffer>
Buffer = llvm::MemoryBuffer::getMemBuffer(GlobalContent);
auto MaybeNewGlobal = Ctx.getGlobals().createNew(SetGlobalName, *Buffer);
auto MaybeNewGlobal = Ctx.getContext().getGlobals().createNew(SetGlobalName,
*Buffer);
if (not MaybeNewGlobal)
return MaybeNewGlobal.takeError();
@@ -89,7 +90,7 @@ inline llvm::Error setGlobalImpl(pipeline::Context &Ctx,
}
if constexpr (commit) {
auto GlobalOrError = Ctx.getGlobals().get(SetGlobalName);
auto GlobalOrError = Ctx.getContext().getGlobals().get(SetGlobalName);
if (not GlobalOrError)
return GlobalOrError.takeError();
@@ -99,13 +100,13 @@ inline llvm::Error setGlobalImpl(pipeline::Context &Ctx,
return llvm::Error::success();
}
llvm::Error SetGlobalAnalysis::run(pipeline::Context &Ctx,
llvm::Error SetGlobalAnalysis::run(pipeline::ExecutionContext &Ctx,
std::string SetGlobalName,
std::string GlobalContent) {
return setGlobalImpl<true>(Ctx, SetGlobalName, GlobalContent);
}
llvm::Error VerifyGlobalAnalysis::run(pipeline::Context &Ctx,
llvm::Error VerifyGlobalAnalysis::run(pipeline::ExecutionContext &Ctx,
std::string SetGlobalName,
std::string GlobalContent) {
return setGlobalImpl<false>(Ctx, SetGlobalName, GlobalContent);
+9 -19
View File
@@ -272,7 +272,7 @@ llvm::Error PipelineManager::storeStepToDisk(llvm::StringRef StepName) {
return StorageClient->commit();
}
llvm::Expected<InvalidationMap>
llvm::Expected<TargetInStepSet>
PipelineManager::deserializeContainer(pipeline::Step &Step,
llvm::StringRef ContainerName,
const llvm::MemoryBuffer &Buffer) {
@@ -318,9 +318,9 @@ PipelineManager::store(llvm::ArrayRef<std::string> StoresOverrides) {
return llvm::Error::success();
}
llvm::Expected<InvalidationMap>
llvm::Expected<TargetInStepSet>
PipelineManager::invalidateAllPossibleTargets() {
InvalidationMap ResultMap;
TargetInStepSet ResultMap;
auto Stream = ExplanationLogger.getAsLLVMStream();
recalculateAllPossibleTargets();
@@ -346,7 +346,7 @@ PipelineManager::invalidateAllPossibleTargets() {
*Stream << Step.first() << "/" << Container.first() << "/";
Target.dump(*Stream);
InvalidationMap Map;
TargetInStepSet Map;
Map[Step.first()][Container.first()].push_back(Target);
if (auto Error = Runner->getInvalidations(Map); Error)
return std::move(Error);
@@ -403,7 +403,7 @@ PipelineManager::getAnalysis(const AnalysisReference &Reference) const {
llvm::Expected<DiffMap>
PipelineManager::runAnalyses(const pipeline::AnalysesList &List,
InvalidationMap &Map,
TargetInStepSet &Map,
const llvm::StringMap<std::string> &Options,
llvm::raw_ostream *DiagnosticLog) {
auto Result = Runner->runAnalyses(List, Map, Options);
@@ -411,11 +411,7 @@ PipelineManager::runAnalyses(const pipeline::AnalysesList &List,
if (not Result)
return Result.takeError();
// TODO: to remove once invalidations are working
if (auto Invalidations = invalidateAllPossibleTargets(); !!Invalidations)
Map = Invalidations.get();
else
return Invalidations.takeError();
recalculateAllPossibleTargets();
PipelineContext->bumpCommitIndex();
return Result;
@@ -425,7 +421,7 @@ llvm::Expected<DiffMap>
PipelineManager::runAnalysis(llvm::StringRef AnalysisName,
llvm::StringRef StepName,
const ContainerToTargetsMap &Targets,
InvalidationMap &Map,
TargetInStepSet &Map,
const llvm::StringMap<std::string> &Options,
llvm::raw_ostream *DiagnosticLog) {
auto Result = Runner->runAnalysis(AnalysisName,
@@ -438,20 +434,14 @@ PipelineManager::runAnalysis(llvm::StringRef AnalysisName,
recalculateAllPossibleTargets();
// TODO: to remove once invalidations are working
if (auto Invalidations = invalidateAllPossibleTargets(); !!Invalidations)
Map = Invalidations.get();
else
return Invalidations.takeError();
PipelineContext->bumpCommitIndex();
return Result;
}
llvm::Expected<InvalidationMap>
llvm::Expected<TargetInStepSet>
PipelineManager::invalidateFromDiff(const llvm::StringRef Name,
const pipeline::GlobalTupleTreeDiff &Diff) {
InvalidationMap Map;
TargetInStepSet Map;
if (auto ApplyError = getRunner().apply(Diff, Map); !!ApplyError)
return std::move(ApplyError);
-21
View File
@@ -42,27 +42,6 @@ IsolatedRootKind::symbolToTarget(const llvm::Function &Symbol) const {
return std::nullopt;
}
void RootKind::getInvalidations(const Context &Ctx,
TargetsList &ToRemove,
const GlobalTupleTreeDiff &Base) const {
const auto *Diff = Base.getAs<model::Binary>();
if (not Diff)
return;
const TupleTreePath ToCheck = *stringAsPath<model::Binary>("/ExtraCodeAddre"
"ss"
"es");
bool RootChanged = llvm::any_of(Diff->Changes, [&ToCheck](const auto &Entry) {
const auto &[Path, Old, New] = Entry;
return ToCheck.isPrefixOf(Path);
});
if (RootChanged)
ToRemove.emplace_back(*this);
}
void RootKind::appendAllTargets(const Context &Ctx, TargetsList &Out) const {
Out.push_back(Target(*this));
}
-14
View File
@@ -39,20 +39,6 @@ TaggedFunctionKind::symbolToTarget(const llvm::Function &Symbol) const {
return pipeline::Target({ Address.toString() }, *this);
}
using TaggedFK = TaggedFunctionKind;
void TaggedFK::getInvalidations(const Context &Ctx,
TargetsList &ToRemove,
const GlobalTupleTreeDiff &Diff) const {
const auto &CurrentModel = getModelFromContext(Ctx);
if (not Ctx.containsReadOnlyContainer(BinaryCrossRelationsRole))
return;
const auto *ModelDiff = Diff.getAs<model::Binary>();
if (not ModelDiff)
return;
}
void TaggedFunctionKind::appendAllTargets(const pipeline::Context &Ctx,
pipeline::TargetsList &Out) const {
const auto &Model = getModelFromContext(Ctx);
+4 -4
View File
@@ -143,16 +143,16 @@ static void compileModuleRunImpl(const Context &Ctx,
fs::setPermissions(*TargetBinary.path(), Permissions);
}
void CompileModule::run(const Context &Ctx,
void CompileModule::run(const ExecutionContext &Ctx,
LLVMContainer &Module,
ObjectFileContainer &TargetBinary) {
compileModuleRunImpl(Ctx, Module, TargetBinary);
compileModuleRunImpl(Ctx.getContext(), Module, TargetBinary);
}
void CompileIsolatedModule::run(const Context &Ctx,
void CompileIsolatedModule::run(const ExecutionContext &Ctx,
LLVMContainer &Module,
ObjectFileContainer &TargetBinary) {
compileModuleRunImpl(Ctx, Module, TargetBinary);
compileModuleRunImpl(Ctx.getContext(), Module, TargetBinary);
}
static RegisterPipe<CompileModule> E2;
+1 -1
View File
@@ -17,7 +17,7 @@ using namespace llvm::sys;
using namespace pipeline;
using namespace ::revng::pipes;
void LinkForTranslation::run(const Context &Ctx,
void LinkForTranslation::run(const ExecutionContext &Ctx,
BinaryFileContainer &InputBinary,
ObjectFileContainer &ObjectFile,
TranslatedFileContainer &OutputBinary) {
+2 -2
View File
@@ -256,13 +256,13 @@ public:
pipeline::InputPreservation::Preserve);
return { pipeline::ContractGroup({ FunctionsContract, BinaryContract }) };
}
void run(const pipeline::Context &Ctx,
void run(pipeline::ExecutionContext &Ctx,
const BinaryFileContainer &SourceBinary,
const pipeline::LLVMContainer &Module,
HexDumpFileContainer &Output) {
pipeline::TargetsList Enumeration = Module.enumerate();
if (not Enumeration.contains(kinds::Isolated.allTargets(Ctx)))
if (not Enumeration.contains(kinds::Isolated.allTargets(Ctx.getContext())))
return;
if (not SourceBinary.exists())
+2 -2
View File
@@ -24,7 +24,7 @@ using ptml::PTMLBuilder;
namespace revng::pipes {
void ProcessAssembly::run(pipeline::Context &Context,
void ProcessAssembly::run(pipeline::ExecutionContext &Context,
const BinaryFileContainer &SourceBinary,
const pipeline::LLVMContainer &TargetList,
FunctionAssemblyStringMap &Output) {
@@ -65,7 +65,7 @@ void ProcessAssembly::print(const pipeline::Context &,
OS << "[this is a pure pipe, no command exists for its invocation]\n";
}
void YieldAssembly::run(pipeline::Context &Context,
void YieldAssembly::run(pipeline::ExecutionContext &Context,
const FunctionAssemblyStringMap &Input,
FunctionAssemblyPTMLStringMap &Output) {
// Access the model
+1 -1
View File
@@ -16,7 +16,7 @@ using ptml::PTMLBuilder;
namespace revng::pipes {
void YieldControlFlow::run(pipeline::Context &Context,
void YieldControlFlow::run(pipeline::ExecutionContext &Context,
const FunctionAssemblyStringMap &Input,
FunctionControlFlowStringMap &Output) {
// Access the model
+3 -3
View File
@@ -24,7 +24,7 @@ using ptml::PTMLBuilder;
namespace revng::pipes {
void ProcessCallGraph::run(pipeline::Context &Context,
void ProcessCallGraph::run(pipeline::ExecutionContext &Context,
const pipeline::LLVMContainer &TargetList,
CrossRelationsFileContainer &OutputFile) {
// Access the model
@@ -51,7 +51,7 @@ void ProcessCallGraph::print(const pipeline::Context &,
OS << "[this is a pure pipe, no command exists for its invocation]\n";
}
void YieldCallGraph::run(pipeline::Context &Context,
void YieldCallGraph::run(pipeline::ExecutionContext &Context,
const CrossRelationsFileContainer &Relations,
CallGraphSVGFileContainer &Output) {
// Access the model
@@ -71,7 +71,7 @@ void YieldCallGraph::print(const pipeline::Context &,
OS << "[this is a pure pipe, no command exists for its invocation]\n";
}
void YieldCallGraphSlice::run(pipeline::Context &Context,
void YieldCallGraphSlice::run(pipeline::ExecutionContext &Context,
const pipeline::LLVMContainer &TargetList,
const CrossRelationsFileContainer &Relations,
CallGraphSliceSVGStringMap &Output) {
@@ -39,6 +39,7 @@ struct /*= struct | fullname =*/
{
/** if emit_tracking -**/
friend struct revng::Tracking;
inline static constexpr bool HasTracking = true;
/**- endif **/
/** if struct.inherits **/
@@ -57,7 +58,7 @@ private:
static_assert(Yamlizable</*= field | field_type =*/>);
/**- if emit_tracking **/
mutable revng::AccessTracker /*= field.name =*/Tracker;
mutable revng::AccessTracker /*= field.name =*/Tracker = revng::AccessTracker(false);
/** endif -**/
public:
+1
View File
@@ -4,6 +4,7 @@
#
set -euo pipefail
set -x
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
-16
View File
@@ -314,22 +314,6 @@ target_link_libraries(test_pipeline revngUnitTestHelpers revngPipeline
revng_add_test(NAME test_pipeline COMMAND test_pipeline)
set_tests_properties(test_pipeline PROPERTIES LABELS "unit")
#
# test_diff_invalidation_event
#
revng_add_test_executable(test_diff_invalidation_event
"${SRC}/DiffInvalidationEvent.cpp")
target_compile_definitions(test_diff_invalidation_event
PRIVATE "BOOST_TEST_DYN_LINK=1")
target_include_directories(test_diff_invalidation_event
PRIVATE "${CMAKE_SOURCE_DIR}")
target_link_libraries(test_diff_invalidation_event revngUnitTestHelpers
revngPipes Boost::unit_test_framework ${LLVM_LIBRARIES})
revng_add_test(NAME test_diff_invalidation_event COMMAND
test_diff_invalidation_event)
set_tests_properties(test_diff_invalidation_event PROPERTIES LABELS "unit")
#
# test_pipeline_c
#
-38
View File
@@ -1,38 +0,0 @@
/// \file DiffInvalidationEvent.cpp
/// Tests for C API of revng-pipeline.
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include "revng/Model/Binary.h"
#include "revng/Pipes/Kinds.h"
#include "revng/Support/MetaAddress.h"
#define BOOST_TEST_MODULE PipelineC
bool init_unit_test();
#include "boost/test/unit_test.hpp"
#include "revng/UnitTestHelpers/UnitTestHelpers.h"
using namespace revng::kinds;
using namespace pipeline;
BOOST_AUTO_TEST_SUITE(ModelInvalidationDiffSuite)
BOOST_AUTO_TEST_CASE(RootInvalidationTest) {
model::Binary Empty;
model::Binary New;
Context Ctx;
MetaAddress Address(0x1000, MetaAddressType::Code_aarch64);
New.ExtraCodeAddresses().insert(Address);
TargetsList ToRemove;
GlobalTupleTreeDiff Event(diff(Empty, New));
Root.getInvalidations(Ctx, ToRemove, Event);
BOOST_TEST(ToRemove.size() == 1);
BOOST_TEST(&ToRemove.front().getKind() == &Root);
}
BOOST_AUTO_TEST_SUITE_END()
+6 -6
View File
@@ -343,7 +343,7 @@ BOOST_AUTO_TEST_CASE(CollectReadFieldsShouldCompile) {
BOOST_AUTO_TEST_CASE(TrackingResetterShouldCompile) {
model::Binary Model;
revng::Tracking::clear(Model);
revng::Tracking::clearAndResume(Model);
}
BOOST_AUTO_TEST_CASE(TrackingPushAndPopperShouldCompile) {
@@ -356,7 +356,7 @@ BOOST_AUTO_TEST_CASE(CollectReadFieldsShouldBeEmptyAtFirst) {
model::Binary Model;
auto MetaAddress = MetaAddress::fromPC(llvm::Triple::ArchType::x86_64, 0);
Model.Segments().insert(Segment(MetaAddress, 1000));
revng::Tracking::clear(Model);
revng::Tracking::clearAndResume(Model);
auto Collected = revng::Tracking::collect(Model);
BOOST_TEST(Collected.Read.size() == 0);
@@ -367,7 +367,7 @@ BOOST_AUTO_TEST_CASE(CollectReadFieldsShouldCollectSegments) {
const auto MetaAddress = MetaAddress::fromPC(llvm::Triple::ArchType::x86_64,
0);
Model.Segments().insert(Segment(MetaAddress, 1000));
revng::Tracking::clear(Model);
revng::Tracking::clearAndResume(Model);
const auto &ConstModel = Model;
ConstModel.Segments().at(Segment::Key(MetaAddress, 1000)).StartAddress();
@@ -389,7 +389,7 @@ BOOST_AUTO_TEST_CASE(CollectReadFieldsShouldCollectNotFoundSegments) {
model::Binary Model;
const auto MetaAddress = MetaAddress::fromPC(llvm::Triple::ArchType::x86_64,
0);
revng::Tracking::clear(Model);
revng::Tracking::clearAndResume(Model);
const auto &ConstModel = Model;
ConstModel.Segments().tryGet(Segment::Key(MetaAddress, 1000));
@@ -407,7 +407,7 @@ BOOST_AUTO_TEST_CASE(CollectReadFieldsShouldCollectAllSegments) {
const auto MetaAddress = MetaAddress::fromPC(llvm::Triple::ArchType::x86_64,
0);
Model.Segments().insert(Segment(MetaAddress, 1000));
revng::Tracking::clear(Model);
revng::Tracking::clearAndResume(Model);
const auto &ConstModel = Model;
ConstModel.Segments().begin();
@@ -428,7 +428,7 @@ BOOST_AUTO_TEST_CASE(QualifiersInsideAVectorAreNotVisited) {
const auto MetaAddress = MetaAddress::fromPC(llvm::Triple::ArchType::x86_64,
0);
Type.Qualifiers().push_back(Qualifier());
revng::Tracking::clear(Type);
revng::Tracking::clearAndResume(Type);
const auto &ConstType = Type;
ConstType.Qualifiers().at(0).Size();
+24 -13
View File
@@ -243,7 +243,9 @@ public:
};
}
void run(const Context &, const MapContainer &Source, MapContainer &Target) {
void run(const ExecutionContext &,
const MapContainer &Source,
MapContainer &Target) {
Source.enumerate().dump();
auto SrcCopy = Source;
for (const auto &Element : SrcCopy.getMap())
@@ -260,10 +262,12 @@ public:
BOOST_AUTO_TEST_CASE(PipeCanBeWrapper) {
Context Ctx;
Step FakeStep(Ctx, "dc", "", {});
ExecutionContext ExecutionCtx(Ctx, FakeStep, nullptr);
MapContainer Map("RandomName");
Map.get({ {}, RootKind }) = 1;
TestPipe Enf;
Enf.run(Ctx, Map, Map);
Enf.run(ExecutionCtx, Map, Map);
BOOST_TEST(Map.get({ {}, RootKind2 }) == 1);
}
@@ -453,7 +457,8 @@ BOOST_AUTO_TEST_CASE(StepCanCloneAndRun) {
ContainerSet Containers;
auto Factory = getMapFactoryContainer();
Containers.add(CName, Factory, Factory("dont_care"));
Step Step("first_step",
Step Step(Ctx,
"first_step",
"",
std::move(Containers),
PipeWrapper::bind<TestPipe>(CName, CName));
@@ -465,7 +470,7 @@ BOOST_AUTO_TEST_CASE(StepCanCloneAndRun) {
auto Factory2 = getMapFactoryContainer();
Containers.add(CName, Factory, Factory("dont_care"));
cast<MapContainer>(Containers[CName]).get(Target({}, RootKind)) = 1;
auto Result = Step.run(Ctx, std::move(Containers));
auto Result = Step.run(std::move(Containers));
auto &Cont = cast<MapContainer>(Result.at(CName));
BOOST_TEST(Cont.get(Target({}, RootKind2)) == 1);
@@ -477,7 +482,8 @@ BOOST_AUTO_TEST_CASE(PipelineCanBeManuallyExectued) {
Context Ctx;
Runner Pip(Ctx);
Pip.addStep(Step("first_step",
Pip.addStep(Step(Ctx,
"first_step",
"",
Registry.createEmpty(),
PipeWrapper::bind<TestPipe>(CName, CName)));
@@ -486,7 +492,7 @@ BOOST_AUTO_TEST_CASE(PipelineCanBeManuallyExectued) {
auto &C1 = Containers.getOrCreate<MapContainer>(CName);
C1.get(Target(RootKind)) = 1;
auto Res = Pip["first_step"].run(Ctx, std::move(Containers));
auto Res = Pip["first_step"].run(std::move(Containers));
BOOST_TEST(cast<MapContainer>(Res.at(CName)).get(Target(RootKind2)) == 1);
const auto &StartingContainer = Pip["first_step"]
.containers()
@@ -505,14 +511,15 @@ BOOST_AUTO_TEST_CASE(SingleElementPipelineCanBeRunned) {
auto &C1 = cast<MapContainer>(Content[CName]);
C1.get(Target(RootKind)) = 1;
Step StepToAdd("first_step", "", std::move(Content));
Step StepToAdd(Ctx, "first_step", "", std::move(Content));
Pip.addStep(std::move(StepToAdd));
ContainerSet &BCI = Pip["first_step"].containers();
BOOST_TEST(cast<MapContainer>(BCI.at(CName)).get(Target(RootKind)) == 1);
ContainerSet Containers2;
Containers2.add(CName, Factory, make_unique<MapContainer>("dont_care"));
Pip.addStep(Step("End",
Pip.addStep(Step(Ctx,
"End",
"",
std::move(Containers2),
Pip["first_step"],
@@ -536,7 +543,8 @@ public:
};
}
void run(Context &, const MapContainer &Source, MapContainer &Target) {
void
run(ExecutionContext &, const MapContainer &Source, MapContainer &Target) {
for (const auto &Element : Source.getMap()) {
if (&Element.first.getKind() != &RootKind)
@@ -565,7 +573,8 @@ public:
InputPreservation::Preserve) };
}
void run(Context &, const MapContainer &Source, MapContainer &Target) {
void
run(ExecutionContext &, const MapContainer &Source, MapContainer &Target) {
for (const auto &Element : Source.getMap())
if (&Element.first.getKind() == &FunctionKind)
Target.get(Element.first) = Element.second;
@@ -1289,7 +1298,7 @@ BOOST_AUTO_TEST_CASE(MultiStepInvalidationTest) {
BOOST_TEST(C2End.get(ToProduce) == 1);
pipeline::InvalidationMap Invalidations;
pipeline::TargetInStepSet Invalidations;
Invalidations[Name][CName].push_back(T);
// C2End.enumerate().dump();
@@ -1322,7 +1331,7 @@ public:
std::vector<std::vector<pipeline::Kind *>> AcceptedKinds = { { &RootKind } };
void run(const Context &Ctx,
void run(const ExecutionContext &Ctx,
const MapContainer &Cont,
int First,
std::string Second,
@@ -1337,11 +1346,13 @@ BOOST_AUTO_TEST_CASE(PipeOptions) {
RegisterAnalysis<ArgumentTestAnalysis> Dummy;
pipeline::AnalysisWrapperImpl W(ArgumentTestAnalysis(), { "container_name" });
Context Ctx;
Step FakeStep(Ctx, "dc", "", {});
ExecutionContext ExecutionCtx(Ctx, FakeStep, nullptr);
ContainerSet Set;
auto Factory = ContainerFactory::create<MapContainer>();
Set.add("container_name", Factory);
Set["container_name"];
if (auto Error = W.run(Ctx, Set, {}); Error)
if (auto Error = W.run(ExecutionCtx, Set, {}); Error)
BOOST_FAIL("unreachable");
}
+5 -4
View File
@@ -133,7 +133,7 @@ static void runAnalysis(Runner &Pipeline, llvm::StringRef Target) {
auto [AnalysisName, Rest2] = Rest.split("/");
ContainerToTargetsMap ToProduce;
InvalidationMap Map;
TargetInStepSet Map;
AbortOnError(parseTarget(Pipeline.getContext(), ToProduce, Rest2, Registry));
AbortOnError(Pipeline.runAnalysis(AnalysisName, Step, ToProduce, Map));
}
@@ -183,11 +183,12 @@ int main(int argc, char *argv[]) {
auto Diff = AbortOnError(deserializeFileOrSTDIN<Type>(ApplyModelDiff));
auto &Runner = Manager.getRunner();
InvalidationMap Map;
AbortOnError(Runner.apply(GlobalTupleTreeDiff(std::move(Diff)), Map));
TargetInStepSet Map;
GlobalTupleTreeDiff GlobalDiff(std::move(Diff), ModelGlobalName);
AbortOnError(Runner.apply(GlobalDiff, Map));
}
InvalidationMap InvMap;
TargetInStepSet InvMap;
for (auto &AnalysesListName : AnalysesLists) {
if (!Manager.getRunner().hasAnalysesList(AnalysesListName)) {
AbortOnError(createStringError(inconvertibleErrorCode(),
+1 -1
View File
@@ -121,7 +121,7 @@ int main(int argc, char *argv[]) {
auto &InputContainer = Manager.getRunner().begin()->containers()["input"];
AbortOnError(InputContainer.load(FilePath::fromLocalStorage(Arguments[1])));
InvalidationMap InvMap;
TargetInStepSet InvMap;
if (Manager.getRunner().hasAnalysesList(Arguments[0])) {
AnalysesList AL = Manager.getRunner().getAnalysesList(Arguments[0]);
AbortOnError(Manager.runAnalyses(AL, InvMap));
+1 -1
View File
@@ -85,7 +85,7 @@ int main(int argc, char *argv[]) {
auto &InputContainer = Manager.getRunner().begin()->containers()["input"];
AbortOnError(InputContainer.load(FilePath::fromLocalStorage(Arguments[1])));
InvalidationMap InvMap;
TargetInStepSet InvMap;
for (auto &AnalysesListName : AnalysesLists) {
if (!Manager.getRunner().hasAnalysesList(AnalysesListName)) {
AbortOnError(createStringError(inconvertibleErrorCode(),
+6 -6
View File
@@ -49,8 +49,8 @@ static ToolCLOptions BaseOptions(MainCategory);
static ExitOnError AbortOnError;
static InvalidationMap getInvalidationMap(Runner &Pipeline) {
InvalidationMap Invalidations;
static TargetInStepSet getTargetInStepSet(Runner &Pipeline) {
TargetInStepSet Invalidations;
const auto &Registry = Pipeline.getKindsRegistry();
for (llvm::StringRef Target : Targets) {
@@ -63,8 +63,8 @@ static InvalidationMap getInvalidationMap(Runner &Pipeline) {
return Invalidations;
}
static void dumpInvalidationMap(llvm::raw_ostream &OS,
const InvalidationMap &Map) {
static void dumpTargetInStepSet(llvm::raw_ostream &OS,
const TargetInStepSet &Map) {
for (const auto &Pair : Map) {
OS << Pair.first();
Pair.second.dump(OS, 1);
@@ -78,11 +78,11 @@ int main(int argc, char *argv[]) {
auto Manager = AbortOnError(BaseOptions.makeManager());
auto Map = getInvalidationMap(Manager.getRunner());
auto Map = getTargetInStepSet(Manager.getRunner());
AbortOnError(Manager.getRunner().getInvalidations(Map));
if (DumpPredictedRemovals) {
dumpInvalidationMap(llvm::outs(), Map);
dumpTargetInStepSet(llvm::outs(), Map);
return EXIT_SUCCESS;
}