1/*
2 * Copyright (c) 2021 - 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef ES2PANDA_COMPILER_CORE_REG_SPILLER_H
17#define ES2PANDA_COMPILER_CORE_REG_SPILLER_H
18
19#include "ir/irnode.h"
20#include "compiler/core/regScope.h"
21
22namespace ark::es2panda::ir {
23class AstNode;
24}  // namespace ark::es2panda::ir
25
26namespace ark::es2panda::compiler {
27class CodeGen;
28
29class RegSpiller {
30protected:
31    class SpillInfo final {
32    public:
33        constexpr explicit SpillInfo(VReg originReg, VReg spillReg) noexcept;
34
35        [[nodiscard]] constexpr VReg OriginReg() const noexcept;
36        [[nodiscard]] constexpr VReg SpillReg() const noexcept;
37        [[nodiscard]] constexpr SpillInfo Reversed() const noexcept;
38
39    private:
40        VReg originReg_ {VReg::Invalid()};
41        VReg spillReg_ {VReg::Invalid()};
42    };
43
44public:
45    explicit RegSpiller() = default;
46    NO_COPY_SEMANTIC(RegSpiller);
47    NO_MOVE_SEMANTIC(RegSpiller);
48    virtual ~RegSpiller() = default;
49
50    [[nodiscard]] virtual RegScope Start(CodeGen &cg) = 0;
51    [[nodiscard]] virtual SpillInfo Restore() = 0;
52    [[nodiscard]] virtual bool Restored() const = 0;
53    [[nodiscard]] virtual IRNode *MoveReg(const ir::AstNode *node, VReg vd, VReg vs, bool spillMov) = 0;
54    virtual void Finalize() noexcept = 0;
55
56    [[nodiscard]] CodeGen *GetCodeGen() const noexcept;
57    [[nodiscard]] std::pair<SpillInfo, const checker::Type *> New() noexcept;
58    void Adjust(const std::unordered_set<VReg> &regs) noexcept;
59
60protected:
61    void SetCodeGen(CodeGen &cg) noexcept;
62    std::uint32_t SpillIndex() const noexcept;
63    std::uint32_t &SpillIndex() noexcept;
64
65private:
66    CodeGen *cg_ {};
67    std::uint32_t spillIndex_ {0};
68};
69
70class DynamicRegSpiller final : public RegSpiller {
71public:
72    explicit DynamicRegSpiller() = default;
73    NO_COPY_SEMANTIC(DynamicRegSpiller);
74    NO_MOVE_SEMANTIC(DynamicRegSpiller);
75    ~DynamicRegSpiller() override = default;
76
77    [[nodiscard]] RegScope Start(CodeGen &cg) override;
78    [[nodiscard]] SpillInfo Restore() override;
79    [[nodiscard]] bool Restored() const override;
80    [[nodiscard]] IRNode *MoveReg(const ir::AstNode *node, VReg vd, VReg vs, bool spillMov) override;
81    void Finalize() noexcept override;
82
83private:
84    std::uint32_t regEnd_ {0};
85};
86
87class StaticRegSpiller final : public RegSpiller {
88public:
89    explicit StaticRegSpiller() = default;
90    NO_COPY_SEMANTIC(StaticRegSpiller);
91    NO_MOVE_SEMANTIC(StaticRegSpiller);
92    ~StaticRegSpiller() override = default;
93
94    [[nodiscard]] RegScope Start(CodeGen &cg) override;
95    [[nodiscard]] SpillInfo Restore() override;
96    [[nodiscard]] bool Restored() const override;
97    [[nodiscard]] IRNode *MoveReg(const ir::AstNode *node, VReg vd, VReg vs, bool spillMov) override;
98    void Finalize() noexcept override;
99
100private:
101    std::vector<SpillInfo> spills_ {};
102};
103
104constexpr RegSpiller::SpillInfo::SpillInfo(const VReg originReg, const VReg spillReg) noexcept
105    : originReg_(originReg), spillReg_(spillReg)
106{
107}
108
109constexpr VReg RegSpiller::SpillInfo::OriginReg() const noexcept
110{
111    return originReg_;
112}
113
114constexpr VReg RegSpiller::SpillInfo::SpillReg() const noexcept
115{
116    return spillReg_;
117}
118
119constexpr RegSpiller::SpillInfo RegSpiller::SpillInfo::Reversed() const noexcept
120{
121    return SpillInfo {spillReg_, originReg_};
122}
123
124}  // namespace ark::es2panda::compiler
125
126#endif
127