1b1994897Sopenharmony_ci/**
2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License.
5b1994897Sopenharmony_ci * You may obtain a copy of the License at
6b1994897Sopenharmony_ci *
7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8b1994897Sopenharmony_ci *
9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and
13b1994897Sopenharmony_ci * limitations under the License.
14b1994897Sopenharmony_ci */
15b1994897Sopenharmony_ci
16b1994897Sopenharmony_ci#ifndef COMPILER_OPTIMIZER_IR_LOCATIONS_H
17b1994897Sopenharmony_ci#define COMPILER_OPTIMIZER_IR_LOCATIONS_H
18b1994897Sopenharmony_ci
19b1994897Sopenharmony_ci#include "compiler/optimizer/ir/constants.h"
20b1994897Sopenharmony_ci#include "compiler/optimizer/ir/datatype.h"
21b1994897Sopenharmony_ci#include "utils/arena_containers.h"
22b1994897Sopenharmony_ci#include "utils/bit_field.h"
23b1994897Sopenharmony_ci#include "utils/arch.h"
24b1994897Sopenharmony_ci#include "utils/regmask.h"
25b1994897Sopenharmony_ci
26b1994897Sopenharmony_ci#include <ostream>
27b1994897Sopenharmony_ci
28b1994897Sopenharmony_cinamespace panda::compiler {
29b1994897Sopenharmony_ciclass Inst;
30b1994897Sopenharmony_ci
31b1994897Sopenharmony_ci// NOLINTNEXTLINE:e(cppcoreguidelines-macro-usage)
32b1994897Sopenharmony_ci#define LOCATIONS(DEF)            \
33b1994897Sopenharmony_ci    DEF(INVALID, "?")             \
34b1994897Sopenharmony_ci    DEF(REGISTER, "r")            \
35b1994897Sopenharmony_ci    DEF(FP_REGISTER, "vr")        \
36b1994897Sopenharmony_ci    DEF(IMMEDIATE, "i")           \
37b1994897Sopenharmony_ci    DEF(STACK, "s")               \
38b1994897Sopenharmony_ci    DEF(STACK_PARAMETER, "param") \
39b1994897Sopenharmony_ci    DEF(STACK_ARGUMENT, "arg")
40b1994897Sopenharmony_ci
41b1994897Sopenharmony_ciclass Location {
42b1994897Sopenharmony_cipublic:
43b1994897Sopenharmony_ci    enum class Kind : uint8_t {
44b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
45b1994897Sopenharmony_ci#define LOCATION_DEF(name, short) name,
46b1994897Sopenharmony_ci        LOCATIONS(LOCATION_DEF)
47b1994897Sopenharmony_ci#undef LOCATION_DEF
48b1994897Sopenharmony_ci            LAST = STACK_ARGUMENT,
49b1994897Sopenharmony_ci        COUNT
50b1994897Sopenharmony_ci    };
51b1994897Sopenharmony_ci
52b1994897Sopenharmony_ci    Location() : Location(Kind::INVALID) {}
53b1994897Sopenharmony_ci    explicit Location(Kind type, uintptr_t value = 0) : bit_fields_(KindField::Encode(type) | ValueField::Encode(value))
54b1994897Sopenharmony_ci    {
55b1994897Sopenharmony_ci        CHECK_LT(value, ValueField::Mask());
56b1994897Sopenharmony_ci    }
57b1994897Sopenharmony_ci
58b1994897Sopenharmony_ci    const char *GetName()
59b1994897Sopenharmony_ci    {
60b1994897Sopenharmony_ci        static constexpr std::array names = {
61b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
62b1994897Sopenharmony_ci#define LOCATION_DEF(name, short_name) short_name,
63b1994897Sopenharmony_ci            LOCATIONS(LOCATION_DEF)
64b1994897Sopenharmony_ci#undef LOCATION_DEF
65b1994897Sopenharmony_ci        };
66b1994897Sopenharmony_ci        return names[static_cast<unsigned>(GetKind())];
67b1994897Sopenharmony_ci    }
68b1994897Sopenharmony_ci
69b1994897Sopenharmony_ci    bool operator==(Location rhs) const
70b1994897Sopenharmony_ci    {
71b1994897Sopenharmony_ci        return bit_fields_ == rhs.bit_fields_;
72b1994897Sopenharmony_ci    }
73b1994897Sopenharmony_ci
74b1994897Sopenharmony_ci    bool operator!=(Location rhs) const
75b1994897Sopenharmony_ci    {
76b1994897Sopenharmony_ci        return !(*this == rhs);
77b1994897Sopenharmony_ci    }
78b1994897Sopenharmony_ci
79b1994897Sopenharmony_ci    bool operator<(Location rhs) const
80b1994897Sopenharmony_ci    {
81b1994897Sopenharmony_ci        return bit_fields_ < rhs.bit_fields_;
82b1994897Sopenharmony_ci    }
83b1994897Sopenharmony_ci
84b1994897Sopenharmony_ci    bool IsInvalid() const
85b1994897Sopenharmony_ci    {
86b1994897Sopenharmony_ci        return GetKind() == Kind::INVALID;
87b1994897Sopenharmony_ci    }
88b1994897Sopenharmony_ci
89b1994897Sopenharmony_ci    bool IsConstant() const
90b1994897Sopenharmony_ci    {
91b1994897Sopenharmony_ci        return GetKind() == Kind::IMMEDIATE;
92b1994897Sopenharmony_ci    }
93b1994897Sopenharmony_ci
94b1994897Sopenharmony_ci    bool IsRegister() const
95b1994897Sopenharmony_ci    {
96b1994897Sopenharmony_ci        return GetKind() == Kind::REGISTER;
97b1994897Sopenharmony_ci    }
98b1994897Sopenharmony_ci
99b1994897Sopenharmony_ci    bool IsFpRegister() const
100b1994897Sopenharmony_ci    {
101b1994897Sopenharmony_ci        return GetKind() == Kind::FP_REGISTER;
102b1994897Sopenharmony_ci    }
103b1994897Sopenharmony_ci
104b1994897Sopenharmony_ci    bool IsStack() const
105b1994897Sopenharmony_ci    {
106b1994897Sopenharmony_ci        return GetKind() == Kind::STACK;
107b1994897Sopenharmony_ci    }
108b1994897Sopenharmony_ci
109b1994897Sopenharmony_ci    bool IsStackArgument() const
110b1994897Sopenharmony_ci    {
111b1994897Sopenharmony_ci        return GetKind() == Kind::STACK_ARGUMENT;
112b1994897Sopenharmony_ci    }
113b1994897Sopenharmony_ci
114b1994897Sopenharmony_ci    bool IsStackParameter() const
115b1994897Sopenharmony_ci    {
116b1994897Sopenharmony_ci        return GetKind() == Kind::STACK_PARAMETER;
117b1994897Sopenharmony_ci    }
118b1994897Sopenharmony_ci
119b1994897Sopenharmony_ci    bool IsAnyStack() const
120b1994897Sopenharmony_ci    {
121b1994897Sopenharmony_ci        return IsStack() || IsStackArgument() || IsStackParameter();
122b1994897Sopenharmony_ci    }
123b1994897Sopenharmony_ci
124b1994897Sopenharmony_ci    bool IsAnyRegister() const
125b1994897Sopenharmony_ci    {
126b1994897Sopenharmony_ci        return IsRegister() || IsFpRegister();
127b1994897Sopenharmony_ci    }
128b1994897Sopenharmony_ci
129b1994897Sopenharmony_ci    bool IsRegisterValid() const
130b1994897Sopenharmony_ci    {
131b1994897Sopenharmony_ci        ASSERT(IsRegister() || IsFpRegister());
132b1994897Sopenharmony_ci        return GetValue() != INVALID_REG;
133b1994897Sopenharmony_ci    }
134b1994897Sopenharmony_ci
135b1994897Sopenharmony_ci    Kind GetKind() const
136b1994897Sopenharmony_ci    {
137b1994897Sopenharmony_ci        return KindField::Get(bit_fields_);
138b1994897Sopenharmony_ci    }
139b1994897Sopenharmony_ci
140b1994897Sopenharmony_ci    Register GetRegister() const
141b1994897Sopenharmony_ci    {
142b1994897Sopenharmony_ci        ASSERT(IsRegister());
143b1994897Sopenharmony_ci        ASSERT(GetValue() < RegMask::Size());
144b1994897Sopenharmony_ci        return GetValue();
145b1994897Sopenharmony_ci    }
146b1994897Sopenharmony_ci    Register GetFpRegister() const
147b1994897Sopenharmony_ci    {
148b1994897Sopenharmony_ci        ASSERT(IsFpRegister());
149b1994897Sopenharmony_ci        ASSERT(GetValue() < VRegMask::Size());
150b1994897Sopenharmony_ci        return GetValue();
151b1994897Sopenharmony_ci    }
152b1994897Sopenharmony_ci
153b1994897Sopenharmony_ci    bool IsUnallocatedRegister() const
154b1994897Sopenharmony_ci    {
155b1994897Sopenharmony_ci        return IsAnyRegister() && GetValue() == INVALID_REG;
156b1994897Sopenharmony_ci    }
157b1994897Sopenharmony_ci
158b1994897Sopenharmony_ci    bool IsFixedRegister() const
159b1994897Sopenharmony_ci    {
160b1994897Sopenharmony_ci        return IsAnyRegister() && GetValue() != INVALID_REG;
161b1994897Sopenharmony_ci    }
162b1994897Sopenharmony_ci
163b1994897Sopenharmony_ci    unsigned GetValue() const
164b1994897Sopenharmony_ci    {
165b1994897Sopenharmony_ci        return ValueField::Get(bit_fields_);
166b1994897Sopenharmony_ci    }
167b1994897Sopenharmony_ci
168b1994897Sopenharmony_ci    static Location MakeRegister(size_t id)
169b1994897Sopenharmony_ci    {
170b1994897Sopenharmony_ci        return Location(Kind::REGISTER, id);
171b1994897Sopenharmony_ci    }
172b1994897Sopenharmony_ci
173b1994897Sopenharmony_ci    static Location MakeFpRegister(size_t id)
174b1994897Sopenharmony_ci    {
175b1994897Sopenharmony_ci        return Location(Kind::FP_REGISTER, id);
176b1994897Sopenharmony_ci    }
177b1994897Sopenharmony_ci
178b1994897Sopenharmony_ci    static Location MakeRegister(size_t id, DataType::Type type)
179b1994897Sopenharmony_ci    {
180b1994897Sopenharmony_ci        return DataType::IsFloatType(type) ? MakeFpRegister(id) : MakeRegister(id);
181b1994897Sopenharmony_ci    }
182b1994897Sopenharmony_ci
183b1994897Sopenharmony_ci    static Location MakeStackSlot(size_t id)
184b1994897Sopenharmony_ci    {
185b1994897Sopenharmony_ci        return Location(Kind::STACK, id);
186b1994897Sopenharmony_ci    }
187b1994897Sopenharmony_ci
188b1994897Sopenharmony_ci    static Location MakeStackArgument(size_t id)
189b1994897Sopenharmony_ci    {
190b1994897Sopenharmony_ci        return Location(Kind::STACK_ARGUMENT, id);
191b1994897Sopenharmony_ci    }
192b1994897Sopenharmony_ci
193b1994897Sopenharmony_ci    static Location MakeStackParameter(size_t id)
194b1994897Sopenharmony_ci    {
195b1994897Sopenharmony_ci        return Location(Kind::STACK_PARAMETER, id);
196b1994897Sopenharmony_ci    }
197b1994897Sopenharmony_ci
198b1994897Sopenharmony_ci    static Location MakeConstant(size_t value)
199b1994897Sopenharmony_ci    {
200b1994897Sopenharmony_ci        return Location(Kind::IMMEDIATE, value);
201b1994897Sopenharmony_ci    }
202b1994897Sopenharmony_ci
203b1994897Sopenharmony_ci    static Location Invalid()
204b1994897Sopenharmony_ci    {
205b1994897Sopenharmony_ci        return Location();
206b1994897Sopenharmony_ci    }
207b1994897Sopenharmony_ci
208b1994897Sopenharmony_ci    static Location RequireRegister()
209b1994897Sopenharmony_ci    {
210b1994897Sopenharmony_ci        return Location(Kind::REGISTER, INVALID_REG);
211b1994897Sopenharmony_ci    }
212b1994897Sopenharmony_ci
213b1994897Sopenharmony_ci    void Dump(std::ostream &stm, Arch arch);
214b1994897Sopenharmony_ci    std::string ToString(Arch arch);
215b1994897Sopenharmony_ci
216b1994897Sopenharmony_ciprivate:
217b1994897Sopenharmony_ci#ifdef IR_FOR_LIBARK_DEFECT_SCAN_AUX
218b1994897Sopenharmony_ci    uint32_t bit_fields_;
219b1994897Sopenharmony_ci#else
220b1994897Sopenharmony_ci    uint16_t bit_fields_;
221b1994897Sopenharmony_ci#endif
222b1994897Sopenharmony_ci
223b1994897Sopenharmony_ci    using KindField = BitField<Kind, 0, MinimumBitsToStore(Kind::LAST)>;
224b1994897Sopenharmony_ci    using ValueField =
225b1994897Sopenharmony_ci        KindField::NextField<uintptr_t, sizeof(bit_fields_) * BITS_PER_BYTE - MinimumBitsToStore(Kind::LAST)>;
226b1994897Sopenharmony_ci};
227b1994897Sopenharmony_ci
228b1994897Sopenharmony_ci#ifndef IR_FOR_LIBARK_DEFECT_SCAN_AUX
229b1994897Sopenharmony_cistatic_assert(sizeof(Location) <= sizeof(uint16_t));
230b1994897Sopenharmony_ci#endif
231b1994897Sopenharmony_ci
232b1994897Sopenharmony_ciclass LocationsInfo {
233b1994897Sopenharmony_cipublic:
234b1994897Sopenharmony_ci    LocationsInfo(ArenaAllocator *allocator, Inst *inst);
235b1994897Sopenharmony_ci
236b1994897Sopenharmony_ci    Location GetLocation(size_t index) const
237b1994897Sopenharmony_ci    {
238b1994897Sopenharmony_ci        ASSERT(index < locations_.size());
239b1994897Sopenharmony_ci        return locations_[index];
240b1994897Sopenharmony_ci    }
241b1994897Sopenharmony_ci
242b1994897Sopenharmony_ci    Location GetDstLocation() const
243b1994897Sopenharmony_ci    {
244b1994897Sopenharmony_ci        return dst_location_;
245b1994897Sopenharmony_ci    }
246b1994897Sopenharmony_ci
247b1994897Sopenharmony_ci    void SetLocation(size_t index, Location location)
248b1994897Sopenharmony_ci    {
249b1994897Sopenharmony_ci        locations_[index] = location;
250b1994897Sopenharmony_ci    }
251b1994897Sopenharmony_ci
252b1994897Sopenharmony_ci    void SetDstLocation(Location location)
253b1994897Sopenharmony_ci    {
254b1994897Sopenharmony_ci        dst_location_ = location;
255b1994897Sopenharmony_ci    }
256b1994897Sopenharmony_ci
257b1994897Sopenharmony_ciprivate:
258b1994897Sopenharmony_ci    Span<Location> locations_;
259b1994897Sopenharmony_ci    Location dst_location_;
260b1994897Sopenharmony_ci};
261b1994897Sopenharmony_ci}  // namespace panda::compiler
262b1994897Sopenharmony_ci
263b1994897Sopenharmony_ci#endif  // COMPILER_OPTIMIZER_IR_LOCATIONS_H
264