Files
2024-09-27 12:07:17 +02:00

145 lines
4.3 KiB
C++

#pragma once
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include <set>
#include "revng/Pipeline/GlobalTupleTreeDiff.h"
#include "revng/Pipeline/Rank.h"
#include "revng/Pipeline/RegisterKind.h"
#include "revng/Support/Assert.h"
namespace pipeline {
class Target;
class Context;
class TargetsList;
class ContainerBase;
class InvalidationEventBase;
class DeadKind;
template<RankSpecialization... T>
inline std::vector<const Rank *>
locationsToRanks(std::tuple<const T &...> Locations) {
std::vector<const Rank *> Return;
std::apply([&](auto &&...Loc) { (Return.push_back(&Loc), ...); }, Locations);
return Return;
}
/// A Kind is used to accumulate objects that logically belongs to the same
/// category.
///
/// As an example, the Kind of Isolated Functions, the Kind of translated
/// binaries.
///
/// A kind refers to a rank which is used by Targets, furthermore a Kind
/// can optionally have a Parent Kind. Again this is used mostly by targets.
///
/// Kinds expose two additional bits of metadata:
/// * DefinedLocations: these are Locations (ranks) which define the locations
/// exposed by the objects of this kind, these assume that all the n keys of the
/// target map to the first n components of the location; if there are trailing
/// components all of them are matched
/// * PreferredKinds: these are other kinds that are suggested when looking for
/// forward references, i.e. Given a location reference in this Kind, which
/// Kinds should I look into to find a definition?
///
/// If you wish to declare a kind to be used in a llvm container, declare a
/// LLVMKind instead.
class Kind : public DynamicHierarchy<Kind> {
private:
RegisterKind Register;
const Rank *TheRank = nullptr;
std::vector<const Rank *> DefinedLocations;
std::vector<const Kind *> PreferredKinds;
public:
template<RankSpecialization BaseRank, typename... T>
requires(RankConvertibleTo<BaseRank, T> and ...)
Kind(llvm::StringRef Name,
const BaseRank &TheRank,
std::tuple<const T &...> Locations,
std::vector<const Kind *> PreferredKinds) :
DynamicHierarchy<Kind>(Name),
Register(*this),
TheRank(&TheRank),
DefinedLocations(locationsToRanks(Locations)),
PreferredKinds(PreferredKinds) {
this->PreferredKinds.push_back(this);
}
template<RankSpecialization BaseRank, typename... T>
requires(RankConvertibleTo<BaseRank, T> and ...)
Kind(llvm::StringRef Name,
Kind &Parent,
const BaseRank &TheRank,
std::tuple<const T &...> Locations,
std::vector<const Kind *> PreferredKinds) :
DynamicHierarchy<Kind>(Name, Parent),
Register(*this),
TheRank(&TheRank),
DefinedLocations(locationsToRanks(Locations)),
PreferredKinds(PreferredKinds) {
this->PreferredKinds.push_back(this);
}
/// Kinds may provide a override for this method. They must return success if
/// ToVerify (which always has this kind as a kind), well formed inside
/// Container (which always contains ToVerify).
virtual llvm::Error verify(const ContainerBase &Container,
const Target &ToVerify) const;
public:
size_t depth() const { return TheRank->depth(); }
const Rank &rank() const { return *TheRank; }
const llvm::ArrayRef<const Kind *> preferredKinds() const {
return PreferredKinds;
}
const llvm::ArrayRef<const Rank *> definedLocations() const {
return DefinedLocations;
}
public:
virtual ~Kind() = default;
virtual void appendAllTargets(const Context &Context,
TargetsList &Out) const = 0;
TargetsList allTargets(const Context &Context) const;
public:
template<RankSpecialization RankDefinitionType>
static Kind &deadKind(const RankDefinitionType &Rank);
};
class SingleElementKind : public Kind {
using Kind::Kind;
void appendAllTargets(const Context &Context,
TargetsList &Out) const override;
};
class DeadKind : public Kind {
public:
template<RankSpecialization BaseRank>
DeadKind(const BaseRank &R) : Kind("Dead", R, {}, {}) {}
void appendAllTargets(const Context &Context,
TargetsList &Out) const override {
revng_abort();
}
};
template<RankSpecialization RankDefinitionType>
inline Kind &Kind::deadKind(const RankDefinitionType &Rank) {
static DeadKind Kind(Rank);
return Kind;
}
} // namespace pipeline