/* * Copyright (c) 2021, Ali Mohammad Pur * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include namespace JS::Bytecode { struct PassPipelineExecutable { Executable& executable; Optional>> cfg {}; Optional>> inverted_cfg {}; Optional> exported_blocks {}; }; class Pass { public: Pass() = default; virtual ~Pass() = default; virtual void perform(PassPipelineExecutable&) = 0; void started() { m_timer.start(); } void finished() { m_time_difference = m_timer.elapsed_time(); } u64 elapsed() const { return m_time_difference.to_microseconds(); } protected: Core::ElapsedTimer m_timer; Duration m_time_difference {}; }; class PassManager : public Pass { public: PassManager() = default; ~PassManager() override = default; void add(NonnullOwnPtr pass) { m_passes.append(move(pass)); } template void add(Args&&... args) { m_passes.append(make(forward(args)...)); } void perform(Executable& executable) { PassPipelineExecutable pipeline_executable { executable }; perform(pipeline_executable); } virtual void perform(PassPipelineExecutable& executable) override { started(); for (auto& pass : m_passes) pass->perform(executable); finished(); } private: Vector> m_passes; }; namespace Passes { class GenerateCFG : public Pass { public: GenerateCFG() = default; ~GenerateCFG() override = default; private: virtual void perform(PassPipelineExecutable&) override; }; class MergeBlocks : public Pass { public: MergeBlocks() = default; ~MergeBlocks() override = default; private: virtual void perform(PassPipelineExecutable&) override; }; class PlaceBlocks : public Pass { public: PlaceBlocks() = default; ~PlaceBlocks() override = default; private: virtual void perform(PassPipelineExecutable&) override; }; class UnifySameBlocks : public Pass { public: UnifySameBlocks() = default; ~UnifySameBlocks() override = default; private: virtual void perform(PassPipelineExecutable&) override; }; class DumpCFG : public Pass { public: DumpCFG(FILE* file) : m_file(file) { } ~DumpCFG() override = default; private: virtual void perform(PassPipelineExecutable&) override; FILE* m_file { nullptr }; }; class EliminateLoads : public Pass { public: EliminateLoads() = default; virtual ~EliminateLoads() override = default; private: virtual void perform(PassPipelineExecutable&) override; }; } }