//===- MC/MCRegisterInfo.cpp - Target Register Description ----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements MCRegisterInfo functions.
//
//===----------------------------------------------------------------------===//

#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <cassert>
#include <cstdint>

using namespace llvm;

namespace {
/// MCRegAliasIterator enumerates all registers aliasing Reg.  This iterator
/// does not guarantee any ordering or that entries are unique.
class MCRegAliasIteratorImpl {
private:
  MCRegister Reg;
  const MCRegisterInfo *MCRI;

  MCRegUnitIterator RI;
  MCRegUnitRootIterator RRI;
  MCSuperRegIterator SI;

public:
  MCRegAliasIteratorImpl(MCRegister Reg, const MCRegisterInfo *MCRI)
      : Reg(Reg), MCRI(MCRI) {

    // Initialize the iterators.
    for (RI = MCRegUnitIterator(Reg, MCRI); RI.isValid(); ++RI) {
      for (RRI = MCRegUnitRootIterator(*RI, MCRI); RRI.isValid(); ++RRI) {
        for (SI = MCSuperRegIterator(*RRI, MCRI, true); SI.isValid(); ++SI) {
          if (Reg != *SI)
            return;
        }
      }
    }
  }

  bool isValid() const { return RI.isValid(); }

  MCRegister operator*() const {
    assert(SI.isValid() && "Cannot dereference an invalid iterator.");
    return *SI;
  }

  void advance() {
    // Assuming SI is valid.
    ++SI;
    if (SI.isValid())
      return;

    ++RRI;
    if (RRI.isValid()) {
      SI = MCSuperRegIterator(*RRI, MCRI, true);
      return;
    }

    ++RI;
    if (RI.isValid()) {
      RRI = MCRegUnitRootIterator(*RI, MCRI);
      SI = MCSuperRegIterator(*RRI, MCRI, true);
    }
  }

  MCRegAliasIteratorImpl &operator++() {
    assert(isValid() && "Cannot move off the end of the list.");
    do
      advance();
    while (isValid() && *SI == Reg);
    return *this;
  }
};
} // namespace

ArrayRef<MCPhysReg> MCRegisterInfo::getCachedAliasesOf(MCRegister R) const {
  auto &Aliases = RegAliasesCache[R.id()];
  if (!Aliases.empty())
    return Aliases;

  for (MCRegAliasIteratorImpl It(R, this); It.isValid(); ++It)
    Aliases.push_back((*It).id());

  sort(Aliases);
  Aliases.erase(unique(Aliases), Aliases.end());
  assert(!llvm::is_contained(Aliases, R) &&
         "MCRegAliasIteratorImpl includes Self!");

  // Always put "self" at the end, so the iterator can choose to ignore it.
  // For registers without aliases, it also serves as a sentinel value that
  // tells us to not recompute the alias set.
  Aliases.push_back(R.id());
  Aliases.shrink_to_fit();
  return Aliases;
}

MCRegister
MCRegisterInfo::getMatchingSuperReg(MCRegister Reg, unsigned SubIdx,
                                    const MCRegisterClass *RC) const {
  for (MCPhysReg Super : superregs(Reg))
    if (RC->contains(Super) && Reg == getSubReg(Super, SubIdx))
      return Super;
  return 0;
}

MCRegister MCRegisterInfo::getSubReg(MCRegister Reg, unsigned Idx) const {
  assert(Idx && Idx < getNumSubRegIndices() &&
         "This is not a subregister index");
  // Get a pointer to the corresponding SubRegIndices list. This list has the
  // name of each sub-register in the same order as MCSubRegIterator.
  const uint16_t *SRI = SubRegIndices + get(Reg).SubRegIndices;
  for (MCPhysReg Sub : subregs(Reg)) {
    if (*SRI == Idx)
      return Sub;
    ++SRI;
  }
  return 0;
}

unsigned MCRegisterInfo::getSubRegIndex(MCRegister Reg,
                                        MCRegister SubReg) const {
  assert(SubReg && SubReg < getNumRegs() && "This is not a register");
  // Get a pointer to the corresponding SubRegIndices list. This list has the
  // name of each sub-register in the same order as MCSubRegIterator.
  const uint16_t *SRI = SubRegIndices + get(Reg).SubRegIndices;
  for (MCPhysReg Sub : subregs(Reg)) {
    if (Sub == SubReg)
      return *SRI;
    ++SRI;
  }
  return 0;
}

int64_t MCRegisterInfo::getDwarfRegNum(MCRegister Reg, bool isEH) const {
  const DwarfLLVMRegPair *M = isEH ? EHL2DwarfRegs : L2DwarfRegs;
  unsigned Size = isEH ? EHL2DwarfRegsSize : L2DwarfRegsSize;

  if (!M)
    return -1;
  DwarfLLVMRegPair Key = {Reg.id(), 0};
  const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key);
  if (I == M + Size || I->FromReg != Reg)
    return -1;
  // Consumers need to be able to detect -1 and -2, but at various points
  // the numbers move between unsigned and signed representations, as well as
  // between 32- and 64-bit representations. We need to convert first to int
  // before int64_t for proper sign handling.
  return int64_t(int(I->ToReg));
}

std::optional<MCRegister> MCRegisterInfo::getLLVMRegNum(uint64_t RegNum,
                                                        bool isEH) const {
  const DwarfLLVMRegPair *M = isEH ? EHDwarf2LRegs : Dwarf2LRegs;
  unsigned Size = isEH ? EHDwarf2LRegsSize : Dwarf2LRegsSize;

  if (!M)
    return std::nullopt;
  DwarfLLVMRegPair Key = {unsigned(RegNum), 0};
  const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key);
  if (I != M + Size && I->FromReg == RegNum)
    return MCRegister::from(I->ToReg);
  return std::nullopt;
}

int64_t MCRegisterInfo::getDwarfRegNumFromDwarfEHRegNum(uint64_t RegNum) const {
  // On ELF platforms, DWARF EH register numbers are the same as DWARF
  // other register numbers.  On Darwin x86, they differ and so need to be
  // mapped.  The .cfi_* directives accept integer literals as well as
  // register names and should generate exactly what the assembly code
  // asked for, so there might be DWARF/EH register numbers that don't have
  // a corresponding LLVM register number at all.  So if we can't map the
  // EH register number to an LLVM register number, assume it's just a
  // valid DWARF register number as is.
  if (std::optional<MCRegister> LRegNum = getLLVMRegNum(RegNum, true)) {
    int DwarfRegNum = getDwarfRegNum(*LRegNum, false);
    if (DwarfRegNum == -1)
      return RegNum;
    else
      return DwarfRegNum;
  }
  return RegNum;
}

int MCRegisterInfo::getSEHRegNum(MCRegister Reg) const {
  const auto I = L2SEHRegs.find(Reg);
  if (I == L2SEHRegs.end())
    return (int)Reg.id();
  return I->second;
}

int MCRegisterInfo::getCodeViewRegNum(MCRegister Reg) const {
  if (L2CVRegs.empty())
    report_fatal_error("target does not implement codeview register mapping");
  const auto I = L2CVRegs.find(Reg);
  if (I == L2CVRegs.end())
    report_fatal_error("unknown codeview register " + (Reg.id() < getNumRegs()
                                                           ? getName(Reg)
                                                           : Twine(Reg.id())));
  return I->second;
}

bool MCRegisterInfo::regsOverlap(MCRegister RegA, MCRegister RegB) const {
  // Regunits are numerically ordered. Find a common unit.
  auto RangeA = regunits(RegA);
  MCRegUnitIterator IA = RangeA.begin(), EA = RangeA.end();
  auto RangeB = regunits(RegB);
  MCRegUnitIterator IB = RangeB.begin(), EB = RangeB.end();
  do {
    if (*IA == *IB)
      return true;
  } while (*IA < *IB ? ++IA != EA : ++IB != EB);
  return false;
}

bool MCRegisterInfo::isArtificialRegUnit(MCRegUnit Unit) const {
  for (MCRegUnitRootIterator Root(Unit, this); Root.isValid(); ++Root)
    if (isArtificial(*Root))
      return true;
  return false;
}
