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