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