• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 PANDA_LOCATIONS_H
17 #define PANDA_LOCATIONS_H
18 
19 #include "compiler/optimizer/code_generator/target_info.h"
20 #include "compiler/optimizer/ir/constants.h"
21 #include "compiler/optimizer/ir/datatype.h"
22 #include "utils/arena_containers.h"
23 #include "utils/bit_field.h"
24 #include "utils/arch.h"
25 #include "utils/regmask.h"
26 
27 #include <ostream>
28 
29 namespace panda::compiler {
30 class Inst;
31 
32 // NOLINTNEXTLINE:e(cppcoreguidelines-macro-usage)
33 #define LOCATIONS(DEF)            \
34     DEF(INVALID, "?")             \
35     DEF(REGISTER, "r")            \
36     DEF(FP_REGISTER, "vr")        \
37     DEF(IMMEDIATE, "i")           \
38     DEF(STACK, "s")               \
39     DEF(STACK_PARAMETER, "param") \
40     DEF(STACK_ARGUMENT, "arg")
41 
42 class Location {
43 public:
44     enum class Kind : uint8_t {
45 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
46 #define LOCATION_DEF(name, short) name,
47         LOCATIONS(LOCATION_DEF)
48 #undef LOCATION_DEF
49             LAST = STACK_ARGUMENT,
50         COUNT
51     };
52 
Location()53     Location() : Location(Kind::INVALID) {}
54     explicit Location(Kind type, uintptr_t value = 0) : bit_fields_(KindField::Encode(type) | ValueField::Encode(value))
55     {
56         CHECK_LT(value, ValueField::Mask());
57     }
58 
GetName()59     const char *GetName()
60     {
61         static constexpr std::array names = {
62 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
63 #define LOCATION_DEF(name, short_name) short_name,
64             LOCATIONS(LOCATION_DEF)
65 #undef LOCATION_DEF
66         };
67         return names[static_cast<unsigned>(GetKind())];
68     }
69 
70     bool operator==(Location rhs) const
71     {
72         return bit_fields_ == rhs.bit_fields_;
73     }
74 
75     bool operator!=(Location rhs) const
76     {
77         return !(*this == rhs);
78     }
79 
80     bool operator<(Location rhs) const
81     {
82         return bit_fields_ < rhs.bit_fields_;
83     }
84 
IsInvalid()85     bool IsInvalid() const
86     {
87         return GetKind() == Kind::INVALID;
88     }
89 
IsConstant()90     bool IsConstant() const
91     {
92         return GetKind() == Kind::IMMEDIATE;
93     }
94 
IsRegister()95     bool IsRegister() const
96     {
97         return GetKind() == Kind::REGISTER;
98     }
99 
IsFpRegister()100     bool IsFpRegister() const
101     {
102         return GetKind() == Kind::FP_REGISTER;
103     }
104 
IsStack()105     bool IsStack() const
106     {
107         return GetKind() == Kind::STACK;
108     }
109 
IsStackArgument()110     bool IsStackArgument() const
111     {
112         return GetKind() == Kind::STACK_ARGUMENT;
113     }
114 
IsStackParameter()115     bool IsStackParameter() const
116     {
117         return GetKind() == Kind::STACK_PARAMETER;
118     }
119 
IsAnyStack()120     bool IsAnyStack() const
121     {
122         return IsStack() || IsStackArgument() || IsStackParameter();
123     }
124 
IsAnyRegister()125     bool IsAnyRegister() const
126     {
127         return IsRegister() || IsFpRegister();
128     }
129 
IsRegisterValid()130     bool IsRegisterValid() const
131     {
132         ASSERT(IsRegister() || IsFpRegister());
133         return GetValue() != INVALID_REG;
134     }
135 
GetKind()136     Kind GetKind() const
137     {
138         return KindField::Get(bit_fields_);
139     }
140 
GetRegister()141     Register GetRegister() const
142     {
143         ASSERT(IsRegister());
144         ASSERT(GetValue() < RegMask::Size());
145         return GetValue();
146     }
GetFpRegister()147     Register GetFpRegister() const
148     {
149         ASSERT(IsFpRegister());
150         ASSERT(GetValue() < VRegMask::Size());
151         return GetValue();
152     }
153 
IsUnallocatedRegister()154     bool IsUnallocatedRegister() const
155     {
156         return IsAnyRegister() && GetValue() == INVALID_REG;
157     }
158 
IsFixedRegister()159     bool IsFixedRegister() const
160     {
161         return IsAnyRegister() && GetValue() != INVALID_REG;
162     }
163 
GetValue()164     unsigned GetValue() const
165     {
166         return ValueField::Get(bit_fields_);
167     }
168 
MakeRegister(size_t id)169     static Location MakeRegister(size_t id)
170     {
171         return Location(Kind::REGISTER, id);
172     }
173 
MakeFpRegister(size_t id)174     static Location MakeFpRegister(size_t id)
175     {
176         return Location(Kind::FP_REGISTER, id);
177     }
178 
MakeRegister(size_t id,DataType::Type type)179     static Location MakeRegister(size_t id, DataType::Type type)
180     {
181         return DataType::IsFloatType(type) ? MakeFpRegister(id) : MakeRegister(id);
182     }
183 
MakeStackSlot(size_t id)184     static Location MakeStackSlot(size_t id)
185     {
186         return Location(Kind::STACK, id);
187     }
188 
MakeStackArgument(size_t id)189     static Location MakeStackArgument(size_t id)
190     {
191         return Location(Kind::STACK_ARGUMENT, id);
192     }
193 
MakeStackParameter(size_t id)194     static Location MakeStackParameter(size_t id)
195     {
196         return Location(Kind::STACK_PARAMETER, id);
197     }
198 
MakeConstant(size_t value)199     static Location MakeConstant(size_t value)
200     {
201         return Location(Kind::IMMEDIATE, value);
202     }
203 
Invalid()204     static Location Invalid()
205     {
206         return Location();
207     }
208 
RequireRegister()209     static Location RequireRegister()
210     {
211         return Location(Kind::REGISTER, INVALID_REG);
212     }
213 
214     void Dump(std::ostream &stm, Arch arch);
215     std::string ToString(Arch arch);
216 
217 private:
218     uint16_t bit_fields_;
219 
220     using KindField = BitField<Kind, 0, MinimumBitsToStore(Kind::LAST)>;
221     using ValueField =
222         KindField::NextField<uintptr_t, sizeof(bit_fields_) * BITS_PER_BYTE - MinimumBitsToStore(Kind::LAST)>;
223 };
224 
225 static_assert(sizeof(Location) <= sizeof(uint16_t));
226 
227 class LocationsInfo {
228 public:
229     LocationsInfo(ArenaAllocator *allocator, Inst *inst);
230 
GetLocation(size_t index)231     Location GetLocation(size_t index) const
232     {
233         ASSERT(index < locations_.size());
234         return locations_[index];
235     }
236 
GetDstLocation()237     Location GetDstLocation() const
238     {
239         return dst_location_;
240     }
241 
SetLocation(size_t index,Location location)242     void SetLocation(size_t index, Location location)
243     {
244         locations_[index] = location;
245     }
246 
SetDstLocation(Location location)247     void SetDstLocation(Location location)
248     {
249         dst_location_ = location;
250     }
251 
252 private:
253     Span<Location> locations_;
254     Location dst_location_;
255 };
256 }  // namespace panda::compiler
257 
258 #endif  // PANDA_LOCATIONS_H
259