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