aboutsummaryrefslogtreecommitdiff
path: root/backend/include/rcc/CodeGen/MachinePass.h
diff options
context:
space:
mode:
Diffstat (limited to 'backend/include/rcc/CodeGen/MachinePass.h')
-rw-r--r--backend/include/rcc/CodeGen/MachinePass.h655
1 files changed, 655 insertions, 0 deletions
diff --git a/backend/include/rcc/CodeGen/MachinePass.h b/backend/include/rcc/CodeGen/MachinePass.h
new file mode 100644
index 0000000..66e3b6b
--- /dev/null
+++ b/backend/include/rcc/CodeGen/MachinePass.h
@@ -0,0 +1,655 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_CODEGEN_MACHINEPASS_H
+#define RCC_CODEGEN_MACHINEPASS_H
+
+#include "rcc/CodeGen/InstructionDescriptor.h"
+#include "rcc/CodeGen/MachineFunctionProperties.h"
+#include "rcc/Support/Error.h"
+
+#include <concepts>
+#include <cstddef>
+#include <cstdint>
+#include <functional>
+#include <initializer_list>
+#include <memory>
+#include <mutex>
+#include <optional>
+#include <span>
+#include <string>
+#include <string_view>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+namespace rcc {
+
+class CompilationUnit;
+class MachineFunction;
+class MachineVerifier;
+class TargetDescription;
+
+using AnalysisID = const void *;
+
+enum class MachinePassChange : std::uint32_t {
+ None = 0,
+ Instructions = 1U << 0U,
+ Operands = 1U << 1U,
+ Registers = 1U << 2U,
+ CFG = 1U << 3U,
+ BlockLayout = 1U << 4U,
+ Frame = 1U << 5U,
+ ConstantPool = 1U << 6U,
+ JumpTable = 1U << 7U,
+ TargetState = 1U << 8U,
+};
+
+class MachinePassChanges final {
+public:
+ constexpr MachinePassChanges() noexcept = default;
+ constexpr MachinePassChanges(std::initializer_list<MachinePassChange> Changes) noexcept {
+ for (const MachinePassChange Change : Changes)
+ add(Change);
+ }
+
+ [[nodiscard]] static constexpr MachinePassChanges all() noexcept {
+ return fromRaw((1U << 9U) - 1U);
+ }
+
+ [[nodiscard]] static constexpr MachinePassChanges fromRaw(std::uint32_t Bits) noexcept {
+ MachinePassChanges Result;
+ Result.Bits = Bits & rawMask();
+ return Result;
+ }
+
+ constexpr void add(MachinePassChange Change) noexcept {
+ Bits |= static_cast<std::uint32_t>(Change);
+ }
+
+ [[nodiscard]] constexpr bool has(MachinePassChange Change) const noexcept {
+ return (Bits & static_cast<std::uint32_t>(Change)) != 0;
+ }
+
+ [[nodiscard]] constexpr bool contains(MachinePassChanges Other) const noexcept {
+ return (Bits & Other.Bits) == Other.Bits;
+ }
+
+ [[nodiscard]] constexpr bool intersects(MachinePassChanges Other) const noexcept {
+ return (Bits & Other.Bits) != 0;
+ }
+
+ [[nodiscard]] constexpr bool empty() const noexcept {
+ return Bits == 0;
+ }
+
+ [[nodiscard]] constexpr std::uint32_t rawValue() const noexcept {
+ return Bits;
+ }
+
+ friend constexpr bool operator==(MachinePassChanges Left,
+ MachinePassChanges Right) noexcept = default;
+
+private:
+ [[nodiscard]] static constexpr std::uint32_t rawMask() noexcept {
+ return (1U << 9U) - 1U;
+ }
+
+ std::uint32_t Bits = 0;
+};
+
+class PreservedAnalyses final {
+public:
+ [[nodiscard]] static PreservedAnalyses all() noexcept {
+ PreservedAnalyses Result;
+ Result.PreserveAll = true;
+ return Result;
+ }
+
+ [[nodiscard]] static PreservedAnalyses none() noexcept {
+ return {};
+ }
+
+ void preserve(AnalysisID ID) {
+ if (ID != nullptr)
+ Preserved.insert(ID);
+ }
+
+ template <typename AnalysisT> void preserve() {
+ preserve(analysisID<AnalysisT>());
+ }
+
+ [[nodiscard]] bool preserves(AnalysisID ID) const noexcept {
+ return PreserveAll || (ID != nullptr && Preserved.contains(ID));
+ }
+
+ [[nodiscard]] bool preservesAll() const noexcept {
+ return PreserveAll;
+ }
+
+ template <typename AnalysisT> [[nodiscard]] static AnalysisID analysisID() noexcept {
+ static const std::uint8_t Token = 0;
+ return &Token;
+ }
+
+private:
+ bool PreserveAll = false;
+ std::unordered_set<AnalysisID> Preserved;
+};
+
+enum class PassThreadSafety : std::uint8_t {
+ NotThreadSafe,
+ ThreadSafe,
+};
+
+struct PassParameter final {
+ std::string Name;
+ std::string Description;
+ std::optional<std::string> DefaultValue;
+ bool Required = false;
+};
+
+struct MachinePassRegistrationMetadata {
+ std::vector<PassParameter> Parameters;
+ PassThreadSafety ThreadSafety = PassThreadSafety::NotThreadSafe;
+ MachinePassChanges DeclaredChanges = MachinePassChanges::all();
+};
+
+struct MachinePassContract final : MachinePassRegistrationMetadata {
+ std::string Name;
+ MachineFunctionProperties Requires;
+ MachineFunctionProperties Sets;
+ MachineFunctionProperties Clears;
+ std::vector<AnalysisID> RequiredAnalyses;
+ std::optional<PipelineStage> VerificationStage;
+};
+
+struct MachinePassResult final {
+ bool Changed = false;
+ MachinePassChanges Changes;
+ PreservedAnalyses Preserved = PreservedAnalyses::none();
+};
+
+struct CompilationUnitPassContract final {
+ std::string Name;
+ std::vector<AnalysisID> RequiredAnalyses;
+ std::vector<PassParameter> Parameters;
+ MachinePassChanges DeclaredChanges = MachinePassChanges::all();
+};
+
+struct CompilationUnitPassResult final {
+ bool Changed = false;
+ MachinePassChanges Changes;
+ PreservedAnalyses PreservedUnitAnalyses = PreservedAnalyses::none();
+ PreservedAnalyses PreservedFunctionAnalyses = PreservedAnalyses::none();
+};
+
+struct MachineAnalysisRegistration final {
+ AnalysisID ID = nullptr;
+ std::string Name;
+ std::vector<AnalysisID> Dependencies;
+ MachinePassChanges InvalidatedBy = MachinePassChanges::all();
+ PassThreadSafety ThreadSafety = PassThreadSafety::NotThreadSafe;
+};
+
+struct CompilationUnitAnalysisRegistration final {
+ AnalysisID ID = nullptr;
+ std::string Name;
+ std::vector<AnalysisID> Dependencies;
+ MachinePassChanges InvalidatedBy = MachinePassChanges::all();
+};
+
+class MachinePassInstrumentation;
+
+class MachineAnalysisManager final {
+public:
+ MachineAnalysisManager() = default;
+ MachineAnalysisManager(const MachineAnalysisManager &) = delete;
+ MachineAnalysisManager &operator=(const MachineAnalysisManager &) = delete;
+ MachineAnalysisManager(MachineAnalysisManager &&) = delete;
+ MachineAnalysisManager &operator=(MachineAnalysisManager &&) = delete;
+ ~MachineAnalysisManager() = default;
+
+ template <typename AnalysisT> [[nodiscard]] static AnalysisID id() noexcept {
+ return PreservedAnalyses::analysisID<AnalysisT>();
+ }
+
+ template <typename AnalysisT>
+ [[nodiscard]] Expected<void> registerAnalysis(MachineAnalysisRegistration Registration = {}) {
+ using ResultT = typename AnalysisT::Result;
+ if (Registration.ID == nullptr)
+ Registration.ID = id<AnalysisT>();
+ if (Registration.Name.empty()) {
+ if constexpr (requires {
+ { AnalysisT::name() } -> std::convertible_to<std::string_view>;
+ }) {
+ Registration.Name = std::string(AnalysisT::name());
+ } else {
+ Registration.Name = "unnamed-machine-analysis";
+ }
+ }
+
+ ErasedRunner Runner = [](MachineFunction &Function, const TargetDescription &Target,
+ MachineAnalysisManager &Manager) -> Expected<std::shared_ptr<void>> {
+ auto Computed = AnalysisT::run(Function, Target, Manager);
+ if (!Computed)
+ return std::unexpected(Computed.error());
+ return std::shared_ptr<void>(new ResultT(std::move(*Computed)),
+ [](void *Value) { delete static_cast<ResultT *>(Value); });
+ };
+ ErasedInvalidator Invalidator = [](void *Value, const MachineFunction &Function,
+ const PreservedAnalyses &Preserved) -> bool {
+ if constexpr (requires(ResultT &Result, const MachineFunction &InputFunction,
+ const PreservedAnalyses &Analyses) {
+ { Result.invalidate(InputFunction, Analyses) } -> std::convertible_to<bool>;
+ }) {
+ return static_cast<ResultT *>(Value)->invalidate(Function, Preserved);
+ }
+ return true;
+ };
+ return registerAnalysisImpl(std::move(Registration), std::move(Runner), std::move(Invalidator));
+ }
+
+ template <typename AnalysisT>
+ [[nodiscard]] Expected<typename AnalysisT::Result *> getResult(MachineFunction &Function,
+ const TargetDescription &Target) {
+ const AnalysisID Key = id<AnalysisT>();
+ if (!isRegistered(Key)) {
+ auto Registered = registerAnalysis<AnalysisT>();
+ if (!Registered)
+ return std::unexpected(Registered.error());
+ }
+ auto Result = getResultImpl(Key, Function, Target);
+ if (!Result)
+ return std::unexpected(Result.error());
+ return static_cast<typename AnalysisT::Result *>(*Result);
+ }
+
+ void invalidate(MachineFunction &Function, const PreservedAnalyses &Preserved,
+ MachinePassChanges Changes) noexcept;
+ void invalidate(MachineFunction &Function, const PreservedAnalyses &Preserved) noexcept {
+ invalidate(Function, Preserved, MachinePassChanges::all());
+ }
+ [[nodiscard]] bool hasCached(const MachineFunction &Function, AnalysisID ID) const noexcept;
+ [[nodiscard]] bool isRegistered(AnalysisID ID) const noexcept;
+ [[nodiscard]] std::size_t cachedResultCount(const MachineFunction &Function) const noexcept;
+ void clear(MachineFunction &Function) noexcept;
+ void clearAll() noexcept;
+
+ [[nodiscard]] Expected<std::unique_ptr<MachineAnalysisManager>> forkEmpty() const;
+ [[nodiscard]] Expected<bool>
+ requestAction(std::string_view Action, const MachineFunction &Function, std::uint64_t Cost = 1);
+
+private:
+ using ErasedRunner = std::function<Expected<std::shared_ptr<void>>(
+ MachineFunction &, const TargetDescription &, MachineAnalysisManager &)>;
+ using ErasedInvalidator =
+ std::function<bool(void *, const MachineFunction &, const PreservedAnalyses &)>;
+
+ struct RegisteredAnalysis final {
+ MachineAnalysisRegistration Info;
+ ErasedRunner Runner;
+ ErasedInvalidator Invalidator;
+ };
+
+ struct CacheEntry final {
+ std::shared_ptr<void> Value;
+ AnalysisID ID = nullptr;
+ };
+
+ [[nodiscard]] Expected<void> registerAnalysisImpl(MachineAnalysisRegistration Registration,
+ ErasedRunner Runner,
+ ErasedInvalidator Invalidator);
+ [[nodiscard]] Expected<void *> getResultImpl(AnalysisID ID, MachineFunction &Function,
+ const TargetDescription &Target);
+ [[nodiscard]] Expected<void> materializeDependencies(const RegisteredAnalysis &Registration,
+ MachineFunction &Function,
+ const TargetDescription &Target);
+ [[nodiscard]] Expected<void>
+ validateParallelRequirements(std::span<const AnalysisID> RequiredAnalyses) const;
+ void setInstrumentation(MachinePassInstrumentation *NewInstrumentation) noexcept {
+ Instrumentation = NewInstrumentation;
+ }
+
+ std::unordered_map<AnalysisID, RegisteredAnalysis> Registry;
+ std::unordered_map<MachineFunction *, std::unordered_map<AnalysisID, CacheEntry>> Cache;
+ std::unordered_map<MachineFunction *, std::vector<AnalysisID>> ActiveComputations;
+ MachinePassInstrumentation *Instrumentation = nullptr;
+
+ friend class MachinePassManager;
+ friend class CompilationUnitPassManager;
+ friend Expected<void> registerStage8MachineAnalyses(MachineAnalysisManager &Analyses);
+};
+
+class CompilationUnitAnalysisManager final {
+public:
+ CompilationUnitAnalysisManager() = default;
+ CompilationUnitAnalysisManager(const CompilationUnitAnalysisManager &) = delete;
+ CompilationUnitAnalysisManager &operator=(const CompilationUnitAnalysisManager &) = delete;
+ CompilationUnitAnalysisManager(CompilationUnitAnalysisManager &&) = delete;
+ CompilationUnitAnalysisManager &operator=(CompilationUnitAnalysisManager &&) = delete;
+ ~CompilationUnitAnalysisManager() = default;
+
+ template <typename AnalysisT> [[nodiscard]] static AnalysisID id() noexcept {
+ return PreservedAnalyses::analysisID<AnalysisT>();
+ }
+
+ template <typename AnalysisT>
+ [[nodiscard]] Expected<void>
+ registerAnalysis(CompilationUnitAnalysisRegistration Registration = {}) {
+ using ResultT = typename AnalysisT::Result;
+ if (Registration.ID == nullptr)
+ Registration.ID = id<AnalysisT>();
+ if (Registration.Name.empty()) {
+ if constexpr (requires {
+ { AnalysisT::name() } -> std::convertible_to<std::string_view>;
+ }) {
+ Registration.Name = std::string(AnalysisT::name());
+ } else {
+ Registration.Name = "unnamed-compilation-unit-analysis";
+ }
+ }
+
+ ErasedRunner Runner =
+ [](CompilationUnit &Unit, const TargetDescription &Target,
+ CompilationUnitAnalysisManager &Manager) -> Expected<std::shared_ptr<void>> {
+ auto Computed = AnalysisT::run(Unit, Target, Manager);
+ if (!Computed)
+ return std::unexpected(Computed.error());
+ return std::shared_ptr<void>(new ResultT(std::move(*Computed)),
+ [](void *Value) { delete static_cast<ResultT *>(Value); });
+ };
+ ErasedInvalidator Invalidator = [](void *Value, const CompilationUnit &Unit,
+ const PreservedAnalyses &Preserved) -> bool {
+ if constexpr (requires(ResultT &Result, const CompilationUnit &InputUnit,
+ const PreservedAnalyses &Analyses) {
+ { Result.invalidate(InputUnit, Analyses) } -> std::convertible_to<bool>;
+ }) {
+ return static_cast<ResultT *>(Value)->invalidate(Unit, Preserved);
+ }
+ return true;
+ };
+ return registerAnalysisImpl(std::move(Registration), std::move(Runner), std::move(Invalidator));
+ }
+
+ template <typename AnalysisT>
+ [[nodiscard]] Expected<typename AnalysisT::Result *> getResult(CompilationUnit &Unit,
+ const TargetDescription &Target) {
+ const AnalysisID Key = id<AnalysisT>();
+ if (!isRegistered(Key)) {
+ auto Registered = registerAnalysis<AnalysisT>();
+ if (!Registered)
+ return std::unexpected(Registered.error());
+ }
+ auto Result = getResultImpl(Key, Unit, Target);
+ if (!Result)
+ return std::unexpected(Result.error());
+ return static_cast<typename AnalysisT::Result *>(*Result);
+ }
+
+ void invalidate(CompilationUnit &Unit, const PreservedAnalyses &Preserved,
+ MachinePassChanges Changes) noexcept;
+ [[nodiscard]] bool hasCached(const CompilationUnit &Unit, AnalysisID ID) const noexcept;
+ [[nodiscard]] bool isRegistered(AnalysisID ID) const noexcept;
+ void clear(CompilationUnit &Unit) noexcept;
+ void clearAll() noexcept;
+
+private:
+ using ErasedRunner = std::function<Expected<std::shared_ptr<void>>(
+ CompilationUnit &, const TargetDescription &, CompilationUnitAnalysisManager &)>;
+ using ErasedInvalidator =
+ std::function<bool(void *, const CompilationUnit &, const PreservedAnalyses &)>;
+
+ struct RegisteredAnalysis final {
+ CompilationUnitAnalysisRegistration Info;
+ ErasedRunner Runner;
+ ErasedInvalidator Invalidator;
+ };
+
+ struct CacheEntry final {
+ std::shared_ptr<void> Value;
+ AnalysisID ID = nullptr;
+ };
+
+ [[nodiscard]] Expected<void>
+ registerAnalysisImpl(CompilationUnitAnalysisRegistration Registration, ErasedRunner Runner,
+ ErasedInvalidator Invalidator);
+ [[nodiscard]] Expected<void *> getResultImpl(AnalysisID ID, CompilationUnit &Unit,
+ const TargetDescription &Target);
+ [[nodiscard]] Expected<void> materializeDependencies(const RegisteredAnalysis &Registration,
+ CompilationUnit &Unit,
+ const TargetDescription &Target);
+ void setInstrumentation(MachinePassInstrumentation *NewInstrumentation) noexcept {
+ Instrumentation = NewInstrumentation;
+ }
+
+ std::unordered_map<AnalysisID, RegisteredAnalysis> Registry;
+ std::unordered_map<CompilationUnit *, std::unordered_map<AnalysisID, CacheEntry>> Cache;
+ std::unordered_map<CompilationUnit *, std::vector<AnalysisID>> ActiveComputations;
+ MachinePassInstrumentation *Instrumentation = nullptr;
+
+ friend class CompilationUnitPassManager;
+};
+
+class MachineFunctionPass {
+public:
+ MachineFunctionPass() = default;
+ MachineFunctionPass(const MachineFunctionPass &) = delete;
+ MachineFunctionPass &operator=(const MachineFunctionPass &) = delete;
+ virtual ~MachineFunctionPass() = default;
+
+ [[nodiscard]] virtual const MachinePassContract &contract() const noexcept = 0;
+ [[nodiscard]] virtual Expected<MachinePassResult> run(MachineFunction &Function,
+ const TargetDescription &Target,
+ MachineAnalysisManager &Analyses) = 0;
+};
+
+class CompilationUnitPass {
+public:
+ CompilationUnitPass() = default;
+ CompilationUnitPass(const CompilationUnitPass &) = delete;
+ CompilationUnitPass &operator=(const CompilationUnitPass &) = delete;
+ virtual ~CompilationUnitPass() = default;
+
+ [[nodiscard]] virtual const CompilationUnitPassContract &contract() const noexcept = 0;
+ [[nodiscard]] virtual Expected<CompilationUnitPassResult>
+ run(CompilationUnit &Unit, const TargetDescription &Target,
+ CompilationUnitAnalysisManager &UnitAnalyses, MachineAnalysisManager &FunctionAnalyses) = 0;
+};
+
+enum class InstrumentationPhase : std::uint8_t {
+ Before,
+ After,
+};
+
+struct InstrumentationStatistic final {
+ std::string Name;
+ bool IsAnalysis = false;
+ std::uint64_t Invocations = 0;
+ std::uint64_t CacheHits = 0;
+ std::uint64_t Changes = 0;
+ std::uint64_t Failures = 0;
+ std::uint64_t TotalNanoseconds = 0;
+};
+
+class MachinePassInstrumentation final {
+public:
+ using BeforeCallback = std::function<void(std::string_view, const MachineFunction &)>;
+ using AfterCallback =
+ std::function<void(std::string_view, const MachineFunction &, const MachinePassResult &)>;
+ using FailureCallback =
+ std::function<void(std::string_view, const MachineFunction &, const Error &)>;
+ using BeforeAnalysisCallback = std::function<void(std::string_view, const MachineFunction &)>;
+ using AfterAnalysisCallback =
+ std::function<void(std::string_view, const MachineFunction &, bool, std::uint64_t)>;
+ using AnalysisFailureCallback =
+ std::function<void(std::string_view, const MachineFunction &, const Error &)>;
+ using IRPrintCallback =
+ std::function<void(InstrumentationPhase, std::string_view, const MachineFunction &)>;
+ using ChangeCallback =
+ std::function<void(std::string_view, const MachineFunction &, MachinePassChanges, bool)>;
+ using ActionFilter =
+ std::function<bool(std::string_view, const MachineFunction &, std::uint64_t)>;
+
+ using BeforeUnitCallback = std::function<void(std::string_view, const CompilationUnit &)>;
+ using AfterUnitCallback = std::function<void(std::string_view, const CompilationUnit &,
+ const CompilationUnitPassResult &)>;
+ using UnitFailureCallback =
+ std::function<void(std::string_view, const CompilationUnit &, const Error &)>;
+ using BeforeUnitAnalysisCallback = std::function<void(std::string_view, const CompilationUnit &)>;
+ using AfterUnitAnalysisCallback =
+ std::function<void(std::string_view, const CompilationUnit &, bool, std::uint64_t)>;
+ using UnitAnalysisFailureCallback =
+ std::function<void(std::string_view, const CompilationUnit &, const Error &)>;
+
+ void addBeforeCallback(BeforeCallback Callback);
+ void addAfterCallback(AfterCallback Callback);
+ void addFailureCallback(FailureCallback Callback);
+ void addBeforeAnalysisCallback(BeforeAnalysisCallback Callback);
+ void addAfterAnalysisCallback(AfterAnalysisCallback Callback);
+ void addAnalysisFailureCallback(AnalysisFailureCallback Callback);
+ void addIRPrintCallback(IRPrintCallback Callback);
+ void addChangeCallback(ChangeCallback Callback);
+ void setActionFilter(ActionFilter Filter);
+ void setPerFunctionFuel(std::optional<std::uint64_t> Fuel);
+
+ void addBeforeUnitCallback(BeforeUnitCallback Callback);
+ void addAfterUnitCallback(AfterUnitCallback Callback);
+ void addUnitFailureCallback(UnitFailureCallback Callback);
+ void addBeforeUnitAnalysisCallback(BeforeUnitAnalysisCallback Callback);
+ void addAfterUnitAnalysisCallback(AfterUnitAnalysisCallback Callback);
+ void addUnitAnalysisFailureCallback(UnitAnalysisFailureCallback Callback);
+
+ [[nodiscard]] std::vector<InstrumentationStatistic> statistics() const;
+ void clearStatistics();
+
+private:
+ struct BufferedEvents final {
+ const TargetDescription *Target = nullptr;
+ std::vector<std::function<void()>> Events;
+ };
+
+ [[nodiscard]] bool bufferFunctionEvent(const MachineFunction &Function,
+ std::function<void(const MachineFunction &)> Replay) const;
+ void beginBuffering(BufferedEvents &Buffer, const TargetDescription &Target) const noexcept;
+ void endBuffering() const noexcept;
+ void replayBufferedEvents(BufferedEvents &Buffer) const;
+
+ void before(std::string_view Name, const MachineFunction &Function) const;
+ void after(std::string_view Name, const MachineFunction &Function,
+ const MachinePassResult &Result, std::uint64_t Nanoseconds) const;
+ void failure(std::string_view Name, const MachineFunction &Function, const Error &ErrorValue,
+ std::uint64_t Nanoseconds = 0) const;
+ void beforeAnalysis(std::string_view Name, const MachineFunction &Function) const;
+ void afterAnalysis(std::string_view Name, const MachineFunction &Function, bool CacheHit,
+ std::uint64_t Nanoseconds) const;
+ void analysisFailure(std::string_view Name, const MachineFunction &Function,
+ const Error &ErrorValue, std::uint64_t Nanoseconds) const;
+ void change(std::string_view Name, const MachineFunction &Function, MachinePassChanges Changes,
+ bool FingerprintChanged) const;
+ [[nodiscard]] Expected<bool> requestAction(std::string_view Action,
+ const MachineFunction &Function, std::uint64_t Cost);
+
+ void beforeUnit(std::string_view Name, const CompilationUnit &Unit) const;
+ void afterUnit(std::string_view Name, const CompilationUnit &Unit,
+ const CompilationUnitPassResult &Result, std::uint64_t Nanoseconds) const;
+ void unitFailure(std::string_view Name, const CompilationUnit &Unit, const Error &ErrorValue,
+ std::uint64_t Nanoseconds = 0) const;
+ void beforeUnitAnalysis(std::string_view Name, const CompilationUnit &Unit) const;
+ void afterUnitAnalysis(std::string_view Name, const CompilationUnit &Unit, bool CacheHit,
+ std::uint64_t Nanoseconds) const;
+ void unitAnalysisFailure(std::string_view Name, const CompilationUnit &Unit,
+ const Error &ErrorValue, std::uint64_t Nanoseconds) const;
+
+ [[nodiscard]] InstrumentationStatistic &statistic(std::string_view Name, bool IsAnalysis) const;
+
+ mutable std::mutex Mutex;
+ mutable std::mutex ActionMutex;
+ std::vector<BeforeCallback> Before;
+ std::vector<AfterCallback> After;
+ std::vector<FailureCallback> Failure;
+ std::vector<BeforeAnalysisCallback> BeforeAnalysis;
+ std::vector<AfterAnalysisCallback> AfterAnalysis;
+ std::vector<AnalysisFailureCallback> AnalysisFailure;
+ std::vector<IRPrintCallback> IRPrint;
+ std::vector<ChangeCallback> Change;
+ ActionFilter Filter;
+ std::optional<std::uint64_t> PerFunctionFuel;
+ std::unordered_map<std::uint64_t, std::uint64_t> ConsumedFuel;
+
+ std::vector<BeforeUnitCallback> BeforeUnit;
+ std::vector<AfterUnitCallback> AfterUnit;
+ std::vector<UnitFailureCallback> UnitFailure;
+ std::vector<BeforeUnitAnalysisCallback> BeforeUnitAnalysis;
+ std::vector<AfterUnitAnalysisCallback> AfterUnitAnalysis;
+ std::vector<UnitAnalysisFailureCallback> UnitAnalysisFailure;
+ mutable std::unordered_map<std::string, InstrumentationStatistic> Statistics;
+
+ static thread_local BufferedEvents *ActiveBuffer;
+
+ friend class CompilationUnitAnalysisManager;
+ friend class CompilationUnitPassManager;
+ friend class MachineAnalysisManager;
+ friend class MachinePassManager;
+};
+
+struct MachinePassManagerOptions final {
+ bool VerifyBefore = true;
+ bool VerifyEach = true;
+ bool DetectUnreportedChanges = false;
+};
+
+class MachinePassManager final {
+public:
+ explicit MachinePassManager(MachinePassManagerOptions Options = {}) : Options(Options) {}
+
+ MachinePassManager(const MachinePassManager &) = delete;
+ MachinePassManager &operator=(const MachinePassManager &) = delete;
+
+ [[nodiscard]] Expected<void> addPass(std::unique_ptr<MachineFunctionPass> Pass);
+ [[nodiscard]] Expected<void> run(MachineFunction &Function, const TargetDescription &Target,
+ MachineAnalysisManager &Analyses,
+ MachinePassInstrumentation *Instrumentation = nullptr) const;
+ [[nodiscard]] Expected<void>
+ runFunctions(CompilationUnit &Unit, const TargetDescription &Target,
+ const MachineAnalysisManager &AnalysisPrototype, std::size_t ThreadCount,
+ MachinePassInstrumentation *Instrumentation = nullptr) const;
+
+ [[nodiscard]] std::size_t size() const noexcept {
+ return Passes.size();
+ }
+
+private:
+ [[nodiscard]] Expected<void> validateContract(const MachinePassContract &Contract) const;
+
+ MachinePassManagerOptions Options;
+ std::vector<std::unique_ptr<MachineFunctionPass>> Passes;
+};
+
+struct CompilationUnitPassManagerOptions final {
+ bool VerifyBefore = true;
+ bool VerifyEach = true;
+};
+
+class CompilationUnitPassManager final {
+public:
+ explicit CompilationUnitPassManager(CompilationUnitPassManagerOptions Options = {})
+ : Options(Options) {}
+
+ CompilationUnitPassManager(const CompilationUnitPassManager &) = delete;
+ CompilationUnitPassManager &operator=(const CompilationUnitPassManager &) = delete;
+
+ [[nodiscard]] Expected<void> addPass(std::unique_ptr<CompilationUnitPass> Pass);
+ [[nodiscard]] Expected<void> run(CompilationUnit &Unit, const TargetDescription &Target,
+ CompilationUnitAnalysisManager &UnitAnalyses,
+ MachineAnalysisManager &FunctionAnalyses,
+ MachinePassInstrumentation *Instrumentation = nullptr) const;
+
+private:
+ CompilationUnitPassManagerOptions Options;
+ std::vector<std::unique_ptr<CompilationUnitPass>> Passes;
+};
+
+} // namespace rcc
+
+#endif // RCC_CODEGEN_MACHINEPASS_H