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_VREG_H
17#define ES2PANDA_COMPILER_CORE_VREG_H
18
19#include "macros.h"
20
21#include <limits>
22
23namespace ark::es2panda::compiler {
24class VReg final {
25public:
26    using Index = uint32_t;
27    explicit constexpr VReg() noexcept : VReg(INVALID_IDX) {}
28    explicit constexpr VReg(const uint32_t idx) noexcept : idx_(idx) {}
29
30    [[nodiscard]] constexpr Index GetIndex() const noexcept
31    {
32        return idx_;
33    }
34
35    constexpr void SetIndex(const Index idx) noexcept
36    {
37        idx_ = idx;
38    }
39
40    [[nodiscard]] static constexpr VReg Invalid() noexcept
41    {
42        return VReg(INVALID_IDX);
43    }
44
45    [[nodiscard]] static constexpr VReg RegStart() noexcept
46    {
47        return VReg(REG_START);
48    }
49
50    [[nodiscard]] constexpr bool IsInvalid() const noexcept
51    {
52        return idx_ == INVALID_IDX;
53    }
54
55    [[nodiscard]] constexpr bool IsValid(uint32_t limit) const noexcept
56    {
57        return (idx_ >= REG_MAX - limit) && (limit == REG_MAX || !IsParameter());
58    }
59
60    [[nodiscard]] constexpr bool IsParameter() const noexcept
61    {
62        return idx_ >= PARAM_START;
63    }
64
65    constexpr VReg &operator++() noexcept
66    {
67        idx_++;
68        return *this;
69    }
70
71    // NOLINTNEXTLINE(readability-const-return-type)
72    constexpr const VReg operator++(int) noexcept
73    {
74        const auto temp = *this;
75        ++*this;
76        return temp;
77    }
78
79    constexpr VReg &operator--() noexcept
80    {
81        idx_--;
82        return *this;
83    }
84
85    // NOLINTNEXTLINE(readability-const-return-type)
86    constexpr const VReg operator--(int) noexcept
87    {
88        const auto temp = *this;
89        --*this;
90        return temp;
91    }
92
93    [[nodiscard]] constexpr bool operator!=(const VReg other) const noexcept
94    {
95        return !(*this == other);
96    }
97
98    [[nodiscard]] constexpr bool operator==(const VReg other) const noexcept
99    {
100        return idx_ == other.idx_;
101    }
102
103    [[nodiscard]] constexpr bool operator!=(const Index idx) const noexcept
104    {
105        return !(*this == idx);
106    }
107
108    [[nodiscard]] constexpr bool operator==(const Index idx) const noexcept
109    {
110        return idx_ == idx;
111    }
112
113    [[nodiscard]] constexpr VReg operator+(const Index idx) const noexcept
114    {
115        return VReg(idx_ + idx);
116    }
117
118    [[nodiscard]] constexpr VReg operator+(const VReg other) const noexcept
119    {
120        return VReg(idx_ + other.idx_);
121    }
122
123    static constexpr auto REG_START = std::numeric_limits<std::uint16_t>::max();
124    static constexpr auto REG_MAX = REG_START + 1U;
125    static constexpr auto PARAM_START = REG_MAX;
126    static constexpr auto MANDATORY_PARAM_NUM = 3U;
127
128private:
129    static constexpr auto INVALID_IDX = std::numeric_limits<Index>::max();
130
131    Index idx_;
132};
133}  // namespace ark::es2panda::compiler
134
135template <>
136struct std::hash<ark::es2panda::compiler::VReg> {
137    std::size_t operator()(const ark::es2panda::compiler::VReg &vreg) const
138    {
139        return std::hash<ark::es2panda::compiler::VReg::Index> {}(vreg.GetIndex());
140    }
141};
142
143#endif
144