// SPDX-License-Identifier: GPL-3.0-or-later #ifndef RCC_IR_PASSINSTRUMENTATION_H #define RCC_IR_PASSINSTRUMENTATION_H #include "rcc/Support/Error.h" #include #include #include #include #include #include namespace rcc { enum class InstrumentationPhase : std::uint8_t { Before, After, }; template class PassInstrumentationCallbacks 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; void addBeforeCallback(BeforeCallback Callback) { addCallback(Before, std::move(Callback)); } void addAfterCallback(AfterCallback Callback) { addCallback(After, std::move(Callback)); } void addFailureCallback(FailureCallback Callback) { addCallback(Failure, std::move(Callback)); } void addBeforeAnalysisCallback(BeforeAnalysisCallback Callback) { addCallback(BeforeAnalysis, std::move(Callback)); } void addAfterAnalysisCallback(AfterAnalysisCallback Callback) { addCallback(AfterAnalysis, std::move(Callback)); } void addAnalysisFailureCallback(AnalysisFailureCallback Callback) { addCallback(AnalysisFailure, std::move(Callback)); } void runBefore(std::string_view Name, const IRUnitT &Unit) const { for (const BeforeCallback &Callback : snapshot(Before)) Callback(Name, Unit); } void runAfter(std::string_view Name, const IRUnitT &Unit, const PassResultT &Result) const { for (const AfterCallback &Callback : snapshot(After)) Callback(Name, Unit, Result); } void runFailure(std::string_view Name, const IRUnitT &Unit, const Error &FailureValue) const { for (const FailureCallback &Callback : snapshot(Failure)) Callback(Name, Unit, FailureValue); } void runBeforeAnalysis(std::string_view Name, const IRUnitT &Unit) const { for (const BeforeAnalysisCallback &Callback : snapshot(BeforeAnalysis)) Callback(Name, Unit); } void runAfterAnalysis(std::string_view Name, const IRUnitT &Unit, bool CacheHit, std::uint64_t Nanoseconds) const { for (const AfterAnalysisCallback &Callback : snapshot(AfterAnalysis)) Callback(Name, Unit, CacheHit, Nanoseconds); } void runAnalysisFailure(std::string_view Name, const IRUnitT &Unit, const Error &FailureValue) const { for (const AnalysisFailureCallback &Callback : snapshot(AnalysisFailure)) Callback(Name, Unit, FailureValue); } [[nodiscard]] bool empty() const { std::scoped_lock Lock(Mutex); return Before.empty() && After.empty() && Failure.empty() && BeforeAnalysis.empty() && AfterAnalysis.empty() && AnalysisFailure.empty(); } private: template void addCallback(std::vector &Callbacks, CallbackT Callback) { if (!Callback) return; std::scoped_lock Lock(Mutex); Callbacks.push_back(std::move(Callback)); } template [[nodiscard]] std::vector snapshot(const std::vector &Callbacks) const { std::scoped_lock Lock(Mutex); return Callbacks; } mutable std::mutex Mutex; std::vector Before; std::vector After; std::vector Failure; std::vector BeforeAnalysis; std::vector AfterAnalysis; std::vector AnalysisFailure; }; } // namespace rcc #endif // RCC_IR_PASSINSTRUMENTATION_H