// SPDX-License-Identifier: GPL-3.0-or-later #ifndef RCC_IR_PASSINSTRUMENTATION_H #define RCC_IR_PASSINSTRUMENTATION_H #include "rcc/CodeGen/MachineFunctionAnalysisManager.h" #include #include #include #include #include #include #include #include namespace rcc { class CompilationUnit; class MachineFunction; struct MachinePassResult; struct CompilationUnitPassResult; 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; }; struct MachineActionID final { std::string Pass; std::string Rule; MachineFunctionStableID Function; MachineInstrStableID Instruction; [[nodiscard]] std::string toString() const; friend bool operator==(const MachineActionID &, const MachineActionID &) = default; }; struct MachineActionEvent final { MachineActionID ID; std::uint64_t Cost = 0; bool Accepted = false; friend bool operator==(const MachineActionEvent &, const MachineActionEvent &) = default; }; class MachinePassInstrumentation final { public: using BeforeCallback = std::function; using AfterCallback = std::function; using FailureCallback = std::function; using BeforeAnalysisCallback = std::function; using AfterAnalysisCallback = std::function; using AnalysisFailureCallback = std::function; using IRPrintCallback = std::function; using ChangeCallback = std::function; using ActionFilter = std::function; using BeforeUnitCallback = std::function; using AfterUnitCallback = std::function; using UnitFailureCallback = std::function; using BeforeUnitAnalysisCallback = std::function; using AfterUnitAnalysisCallback = std::function; using UnitAnalysisFailureCallback = std::function; 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 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 statistics() const; [[nodiscard]] std::vector actionEvents() const; [[nodiscard]] bool requiresSerialFunctionExecution() const; [[nodiscard]] Expected requestAction(std::string_view Pass, std::string_view Rule, const MachineFunction &Function, MachineInstrStableID Instruction, std::uint64_t Cost); [[nodiscard]] Expected requestAction(std::string_view Pass, std::string_view Rule, const MachineFunction &Function, std::nullptr_t, std::uint64_t Cost); private: 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; 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 beforeAnalysis(std::string_view Name, const CompilationUnit &Unit) const; void afterAnalysis(std::string_view Name, const CompilationUnit &Unit, bool CacheHit, std::uint64_t Nanoseconds) const; void analysisFailure(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 Before; std::vector After; std::vector Failure; std::vector BeforeAnalysis; std::vector AfterAnalysis; std::vector AnalysisFailure; std::vector IRPrint; std::vector Change; ActionFilter Filter; std::optional PerFunctionFuel; std::unordered_map ConsumedFuel; std::vector ActionEvents; std::vector BeforeUnit; std::vector AfterUnit; std::vector UnitFailure; std::vector BeforeUnitAnalysis; std::vector AfterUnitAnalysis; std::vector UnitAnalysisFailure; mutable std::unordered_map Statistics; template friend struct AnalysisManagerInstrumentation; template friend struct PassManagerCallbacks; }; } // namespace rcc #endif // RCC_IR_PASSINSTRUMENTATION_H