1321369Sdim//===- MC/MCRegisterInfo.cpp - Target Register Description ----------------===//
2239310Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6239310Sdim//
7239310Sdim//===----------------------------------------------------------------------===//
8239310Sdim//
9239310Sdim// This file implements MCRegisterInfo functions.
10239310Sdim//
11239310Sdim//===----------------------------------------------------------------------===//
12239310Sdim
13239310Sdim#include "llvm/MC/MCRegisterInfo.h"
14321369Sdim#include "llvm/ADT/DenseMap.h"
15344779Sdim#include "llvm/ADT/Twine.h"
16321369Sdim#include "llvm/Support/ErrorHandling.h"
17321369Sdim#include <algorithm>
18321369Sdim#include <cassert>
19321369Sdim#include <cstdint>
20239310Sdim
21239310Sdimusing namespace llvm;
22239310Sdim
23360784SdimMCRegister
24360784SdimMCRegisterInfo::getMatchingSuperReg(MCRegister Reg, unsigned SubIdx,
25360784Sdim                                    const MCRegisterClass *RC) const {
26239310Sdim  for (MCSuperRegIterator Supers(Reg, this); Supers.isValid(); ++Supers)
27239310Sdim    if (RC->contains(*Supers) && Reg == getSubReg(*Supers, SubIdx))
28239310Sdim      return *Supers;
29239310Sdim  return 0;
30239310Sdim}
31239310Sdim
32360784SdimMCRegister MCRegisterInfo::getSubReg(MCRegister Reg, unsigned Idx) const {
33243830Sdim  assert(Idx && Idx < getNumSubRegIndices() &&
34243830Sdim         "This is not a subregister index");
35239310Sdim  // Get a pointer to the corresponding SubRegIndices list. This list has the
36239310Sdim  // name of each sub-register in the same order as MCSubRegIterator.
37239310Sdim  const uint16_t *SRI = SubRegIndices + get(Reg).SubRegIndices;
38239310Sdim  for (MCSubRegIterator Subs(Reg, this); Subs.isValid(); ++Subs, ++SRI)
39239310Sdim    if (*SRI == Idx)
40239310Sdim      return *Subs;
41239310Sdim  return 0;
42239310Sdim}
43239310Sdim
44360784Sdimunsigned MCRegisterInfo::getSubRegIndex(MCRegister Reg,
45360784Sdim                                        MCRegister SubReg) const {
46243830Sdim  assert(SubReg && SubReg < getNumRegs() && "This is not a register");
47239310Sdim  // Get a pointer to the corresponding SubRegIndices list. This list has the
48239310Sdim  // name of each sub-register in the same order as MCSubRegIterator.
49239310Sdim  const uint16_t *SRI = SubRegIndices + get(Reg).SubRegIndices;
50239310Sdim  for (MCSubRegIterator Subs(Reg, this); Subs.isValid(); ++Subs, ++SRI)
51239310Sdim    if (*Subs == SubReg)
52239310Sdim      return *SRI;
53239310Sdim  return 0;
54239310Sdim}
55239310Sdim
56261991Sdimunsigned MCRegisterInfo::getSubRegIdxSize(unsigned Idx) const {
57261991Sdim  assert(Idx && Idx < getNumSubRegIndices() &&
58261991Sdim         "This is not a subregister index");
59261991Sdim  return SubRegIdxRanges[Idx].Size;
60261991Sdim}
61261991Sdim
62261991Sdimunsigned MCRegisterInfo::getSubRegIdxOffset(unsigned Idx) const {
63261991Sdim  assert(Idx && Idx < getNumSubRegIndices() &&
64261991Sdim         "This is not a subregister index");
65261991Sdim  return SubRegIdxRanges[Idx].Offset;
66261991Sdim}
67261991Sdim
68360784Sdimint MCRegisterInfo::getDwarfRegNum(MCRegister RegNum, bool isEH) const {
69239310Sdim  const DwarfLLVMRegPair *M = isEH ? EHL2DwarfRegs : L2DwarfRegs;
70239310Sdim  unsigned Size = isEH ? EHL2DwarfRegsSize : L2DwarfRegsSize;
71239310Sdim
72314564Sdim  if (!M)
73314564Sdim    return -1;
74239310Sdim  DwarfLLVMRegPair Key = { RegNum, 0 };
75239310Sdim  const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key);
76239310Sdim  if (I == M+Size || I->FromReg != RegNum)
77239310Sdim    return -1;
78239310Sdim  return I->ToReg;
79239310Sdim}
80239310Sdim
81360784SdimOptional<unsigned> MCRegisterInfo::getLLVMRegNum(unsigned RegNum,
82360784Sdim                                                 bool isEH) const {
83239310Sdim  const DwarfLLVMRegPair *M = isEH ? EHDwarf2LRegs : Dwarf2LRegs;
84239310Sdim  unsigned Size = isEH ? EHDwarf2LRegsSize : Dwarf2LRegsSize;
85239310Sdim
86314564Sdim  if (!M)
87360784Sdim    return None;
88239310Sdim  DwarfLLVMRegPair Key = { RegNum, 0 };
89239310Sdim  const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key);
90360784Sdim  if (I != M + Size && I->FromReg == RegNum)
91360784Sdim    return I->ToReg;
92360784Sdim  return None;
93239310Sdim}
94239310Sdim
95327952Sdimint MCRegisterInfo::getDwarfRegNumFromDwarfEHRegNum(unsigned RegNum) const {
96327952Sdim  // On ELF platforms, DWARF EH register numbers are the same as DWARF
97327952Sdim  // other register numbers.  On Darwin x86, they differ and so need to be
98327952Sdim  // mapped.  The .cfi_* directives accept integer literals as well as
99327952Sdim  // register names and should generate exactly what the assembly code
100327952Sdim  // asked for, so there might be DWARF/EH register numbers that don't have
101327952Sdim  // a corresponding LLVM register number at all.  So if we can't map the
102327952Sdim  // EH register number to an LLVM register number, assume it's just a
103327952Sdim  // valid DWARF register number as is.
104360784Sdim  if (Optional<unsigned> LRegNum = getLLVMRegNum(RegNum, true))
105360784Sdim    return getDwarfRegNum(*LRegNum, false);
106327952Sdim  return RegNum;
107327952Sdim}
108327952Sdim
109360784Sdimint MCRegisterInfo::getSEHRegNum(MCRegister RegNum) const {
110360784Sdim  const DenseMap<MCRegister, int>::const_iterator I = L2SEHRegs.find(RegNum);
111239310Sdim  if (I == L2SEHRegs.end()) return (int)RegNum;
112239310Sdim  return I->second;
113239310Sdim}
114309124Sdim
115360784Sdimint MCRegisterInfo::getCodeViewRegNum(MCRegister RegNum) const {
116309124Sdim  if (L2CVRegs.empty())
117309124Sdim    report_fatal_error("target does not implement codeview register mapping");
118360784Sdim  const DenseMap<MCRegister, int>::const_iterator I = L2CVRegs.find(RegNum);
119309124Sdim  if (I == L2CVRegs.end())
120344779Sdim    report_fatal_error("unknown codeview register " + (RegNum < getNumRegs()
121344779Sdim                                                           ? getName(RegNum)
122344779Sdim                                                           : Twine(RegNum)));
123309124Sdim  return I->second;
124309124Sdim}
125