/* * Copyright (c) 2021, Ali Mohammad Pur * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #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() { gettimeofday(&m_start_time, nullptr); } void finished() { struct timeval end_time { 0, 0 }; gettimeofday(&end_time, nullptr); time_t interval_s = end_time.tv_sec - m_start_time.tv_sec; suseconds_t interval_us = end_time.tv_usec; if (interval_us < m_start_time.tv_usec) { interval_s -= 1; interval_us += 1000000; } interval_us -= m_start_time.tv_usec; m_time_difference = interval_s * 1000000 + interval_us; } u64 elapsed() const { return m_time_difference; } protected: struct timeval m_start_time { 0, 0 }; u64 m_time_difference { 0 }; }; 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: NonnullOwnPtrVector 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 }; }; } }