// SPDX-License-Identifier: GPL-3.0-or-later #ifndef RCC_CODEGEN_MACHINEPASSINSTRUMENTATION_H #define RCC_CODEGEN_MACHINEPASSINSTRUMENTATION_H #include "rcc/CodeGen/MachineFunctionAnalysisManager.h" #include "rcc/IR/PassInstrumentation.h" #include #include #include #include #include #include #include #include namespace rcc { class CompilationUnit; class MachineFunction; struct MachinePassResult; struct CompilationUnitPassResult; 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 { using FunctionCallbackRegistry = PassInstrumentationCallbacks; using UnitCallbackRegistry = PassInstrumentationCallbacks; public: using BeforeCallback = FunctionCallbackRegistry::BeforeCallback; using AfterCallback = FunctionCallbackRegistry::AfterCallback; using FailureCallback = FunctionCallbackRegistry::FailureCallback; using BeforeAnalysisCallback = FunctionCallbackRegistry::BeforeAnalysisCallback; using AfterAnalysisCallback = FunctionCallbackRegistry::AfterAnalysisCallback; using AnalysisFailureCallback = FunctionCallbackRegistry::AnalysisFailureCallback; using IRPrintCallback = std::function; using ChangeCallback = std::function; using ActionFilter = std::function; using BeforeUnitCallback = UnitCallbackRegistry::BeforeCallback; using AfterUnitCallback = UnitCallbackRegistry::AfterCallback; using UnitFailureCallback = UnitCallbackRegistry::FailureCallback; using BeforeUnitAnalysisCallback = UnitCallbackRegistry::BeforeAnalysisCallback; using AfterUnitAnalysisCallback = UnitCallbackRegistry::AfterAnalysisCallback; using UnitAnalysisFailureCallback = UnitCallbackRegistry::AnalysisFailureCallback; 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; FunctionCallbackRegistry FunctionCallbacks; UnitCallbackRegistry UnitCallbacks; mutable std::mutex Mutex; mutable std::mutex ActionMutex; std::vector IRPrint; std::vector Change; ActionFilter Filter; std::optional PerFunctionFuel; std::unordered_map ConsumedFuel; std::vector ActionEvents; mutable std::unordered_map Statistics; template friend struct AnalysisManagerInstrumentation; template friend struct PassManagerCallbacks; }; } // namespace rcc #endif // RCC_CODEGEN_MACHINEPASSINSTRUMENTATION_H