bool operator<(DwarfLLVMRegPair RHS) const { return FromReg < RHS.FromReg; }
};
+
+ /// SubRegCoveredBits - Emitted by tablegen: bit range covered by a subreg
+ /// index, -1 in any being invalid.
+ struct SubRegCoveredBits {
+ uint16_t Offset;
+ uint16_t Size;
+ };
private:
const MCRegisterDesc *Desc; // Pointer to the descriptor array
unsigned NumRegs; // Number of entries in the array
const char *RegStrings; // Pointer to the string table.
const uint16_t *SubRegIndices; // Pointer to the subreg lookup
// array.
+ const SubRegCoveredBits *SubRegIdxRanges; // Pointer to the subreg covered
+ // bit ranges array.
unsigned NumSubRegIndices; // Number of subreg indices.
const uint16_t *RegEncodingTable; // Pointer to array of register
// encodings.
const char *Strings,
const uint16_t *SubIndices,
unsigned NumIndices,
+ const SubRegCoveredBits *SubIdxRanges,
const uint16_t *RET) {
Desc = D;
NumRegs = NR;
NumRegUnits = NRU;
SubRegIndices = SubIndices;
NumSubRegIndices = NumIndices;
+ SubRegIdxRanges = SubIdxRanges;
RegEncodingTable = RET;
}
/// otherwise.
unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const;
+ /// \brief Get the bit range covered by a given sub-register index.
+ /// In some cases, for instance non-contiguous synthesized indices,
+ /// there is no meaningful bit range to get, so return true if \p Offset
+ /// and \p Size were set.
+ bool getSubRegIdxCoveredBits(unsigned Idx,
+ unsigned &Offset, unsigned &Size) const;
+
/// \brief Return the human-readable symbolic target-specific name for the
/// specified physical register.
const char *getName(unsigned RegNo) const {
class RegisterClass; // Forward def
// SubRegIndex - Use instances of SubRegIndex to identify subregisters.
-class SubRegIndex<list<SubRegIndex> comps = []> {
+class SubRegIndex<int size = -1, int offset = 0> {
string Namespace = "";
+ // Size - Size (in bits) of the sub-registers represented by this index.
+ int Size = size;
+
+ // Offset - Offset of the first bit that is part of this sub-register index.
+ int Offset = offset;
+
// ComposedOf - A list of two SubRegIndex instances, [A, B].
// This indicates that this SubRegIndex is the result of composing A and B.
- list<SubRegIndex> ComposedOf = comps;
+ // See ComposedSubRegIndex.
+ list<SubRegIndex> ComposedOf = [];
// CoveringSubRegIndices - A list of two or more sub-register indexes that
// cover this sub-register.
list<SubRegIndex> CoveringSubRegIndices = [];
}
+// ComposedSubRegIndex - A sub-register that is the result of composing A and B.
+// Offset is set to the sum of A and B's Offsets. Size is set to B's Size.
+class ComposedSubRegIndex<SubRegIndex A, SubRegIndex B>
+ : SubRegIndex<B.Size, -1> {
+ // See SubRegIndex.
+ let ComposedOf = [A, B];
+}
+
// RegAltNameIndex - The alternate name set to use for register operands of
// this register class when printing.
class RegAltNameIndex {
return 0;
}
+bool MCRegisterInfo::getSubRegIdxCoveredBits(unsigned Idx, unsigned &Offset,
+ unsigned &Size) const {
+ assert(Idx && Idx < getNumSubRegIndices() &&
+ "This is not a subregister index");
+ // Get a pointer to the corresponding SubRegIdxRanges struct.
+ const SubRegCoveredBits *Bits = &SubRegIdxRanges[Idx];
+ if (Bits->Offset == (uint16_t)-1 || Bits->Size == (uint16_t)-1)
+ return false;
+ Offset = Bits->Offset;
+ Size = Bits->Size;
+ return true;
+}
+
int MCRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
const DwarfLLVMRegPair *M = isEH ? EHL2DwarfRegs : L2DwarfRegs;
unsigned Size = isEH ? EHL2DwarfRegsSize : L2DwarfRegsSize;
// Subregister indices.
let Namespace = "ARM" in {
-def qqsub_0 : SubRegIndex;
-def qqsub_1 : SubRegIndex;
+def qqsub_0 : SubRegIndex<256>;
+def qqsub_1 : SubRegIndex<256, 256>;
// Note: Code depends on these having consecutive numbers.
-def qsub_0 : SubRegIndex;
-def qsub_1 : SubRegIndex;
-def qsub_2 : SubRegIndex<[qqsub_1, qsub_0]>;
-def qsub_3 : SubRegIndex<[qqsub_1, qsub_1]>;
-
-def dsub_0 : SubRegIndex;
-def dsub_1 : SubRegIndex;
-def dsub_2 : SubRegIndex<[qsub_1, dsub_0]>;
-def dsub_3 : SubRegIndex<[qsub_1, dsub_1]>;
-def dsub_4 : SubRegIndex<[qsub_2, dsub_0]>;
-def dsub_5 : SubRegIndex<[qsub_2, dsub_1]>;
-def dsub_6 : SubRegIndex<[qsub_3, dsub_0]>;
-def dsub_7 : SubRegIndex<[qsub_3, dsub_1]>;
-
-def ssub_0 : SubRegIndex;
-def ssub_1 : SubRegIndex;
-def ssub_2 : SubRegIndex<[dsub_1, ssub_0]>;
-def ssub_3 : SubRegIndex<[dsub_1, ssub_1]>;
-
-def gsub_0 : SubRegIndex;
-def gsub_1 : SubRegIndex;
+def qsub_0 : SubRegIndex<128>;
+def qsub_1 : SubRegIndex<128, 128>;
+def qsub_2 : ComposedSubRegIndex<qqsub_1, qsub_0>;
+def qsub_3 : ComposedSubRegIndex<qqsub_1, qsub_1>;
+
+def dsub_0 : SubRegIndex<64>;
+def dsub_1 : SubRegIndex<64, 64>;
+def dsub_2 : ComposedSubRegIndex<qsub_1, dsub_0>;
+def dsub_3 : ComposedSubRegIndex<qsub_1, dsub_1>;
+def dsub_4 : ComposedSubRegIndex<qsub_2, dsub_0>;
+def dsub_5 : ComposedSubRegIndex<qsub_2, dsub_1>;
+def dsub_6 : ComposedSubRegIndex<qsub_3, dsub_0>;
+def dsub_7 : ComposedSubRegIndex<qsub_3, dsub_1>;
+
+def ssub_0 : SubRegIndex<32>;
+def ssub_1 : SubRegIndex<32, 32>;
+def ssub_2 : ComposedSubRegIndex<dsub_1, ssub_0>;
+def ssub_3 : ComposedSubRegIndex<dsub_1, ssub_1>;
+
+def gsub_0 : SubRegIndex<32>;
+def gsub_1 : SubRegIndex<32, 32>;
// Let TableGen synthesize the remaining 12 ssub_* indices.
// We don't need to name them.
}
def subreg_32bit : SubRegIndex; // could also be known as "subreg_high32"
def subreg_high : SubRegIndex;
def subreg_low : SubRegIndex;
-def subreg_low32 : SubRegIndex<[subreg_low, subreg_32bit]>;
+def subreg_low32 : ComposedSubRegIndex<subreg_low, subreg_32bit>;
}
// Define a register class that contains values of type TYPE and an
// Subregister indices.
let Namespace = "X86" in {
- def sub_8bit : SubRegIndex;
- def sub_8bit_hi : SubRegIndex;
- def sub_16bit : SubRegIndex;
- def sub_32bit : SubRegIndex;
- def sub_xmm : SubRegIndex;
+ def sub_8bit : SubRegIndex<8>;
+ def sub_8bit_hi : SubRegIndex<8, 8>;
+ def sub_16bit : SubRegIndex<16>;
+ def sub_32bit : SubRegIndex<32>;
+ def sub_xmm : SubRegIndex<64>;
}
//===----------------------------------------------------------------------===//
Name = R->getName();
if (R->getValue("Namespace"))
Namespace = R->getValueAsString("Namespace");
+ Size = R->getValueAsInt("Size");
+ Offset = R->getValueAsInt("Offset");
}
CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace,
unsigned Enum)
- : TheDef(0), Name(N), Namespace(Nspace), EnumValue(Enum),
- LaneMask(0), AllSuperRegsCovered(true) {
+ : TheDef(0), Name(N), Namespace(Nspace), Size(-1), Offset(-1),
+ EnumValue(Enum), LaneMask(0), AllSuperRegsCovered(true) {
}
std::string CodeGenSubRegIndex::getQualifiedName() const {
if (!Parts.empty()) {
if (Parts.size() < 2)
PrintFatalError(TheDef->getLoc(),
- "CoveredBySubRegs must have two or more entries");
+ "CoveredBySubRegs must have two or more entries");
SmallVector<CodeGenSubRegIndex*, 8> IdxParts;
for (unsigned i = 0, e = Parts.size(); i != e; ++i)
IdxParts.push_back(RegBank.getSubRegIdx(Parts[i]));
Record *const TheDef;
std::string Name;
std::string Namespace;
+ uint16_t Size;
+ uint16_t Offset;
public:
const unsigned EnumValue;
const std::string &getName() const { return Name; }
const std::string &getNamespace() const { return Namespace; }
std::string getQualifiedName() const;
+ uint16_t getSize() const { return Size; }
+ uint16_t getOffset() const { return Offset; }
// Order CodeGenSubRegIndex pointers by EnumValue.
struct Less {
assert(A && B);
std::pair<CompMap::iterator, bool> Ins =
Composed.insert(std::make_pair(A, B));
+ // Synthetic subreg indices that aren't contiguous (for instance ARM
+ // register tuples) don't have a bit range, so it's OK to let
+ // B->Offset == -1. For the other cases, accumulate the offset and set
+ // the size here. Only do so if there is no offset yet though.
+ if ((Offset != (uint16_t)-1 && A->Offset != (uint16_t)-1) &&
+ (B->Offset == (uint16_t)-1)) {
+ B->Offset = Offset + A->Offset;
+ B->Size = A->Size;
+ }
return (Ins.second || Ins.first->second == B) ? 0 : Ins.first->second;
}
const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters();
+ ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices();
// The lists of sub-registers and super-registers go in the same array. That
// allows us to share suffixes.
typedef std::vector<const CodeGenRegister*> RegVec;
SubRegIdxSeqs.emit(OS, printSubRegIndex);
OS << "};\n\n";
+ // Emit the table of sub-register index sizes.
+ OS << "extern const MCRegisterInfo::SubRegCoveredBits "
+ << TargetName << "SubRegIdxRanges[] = {\n";
+ OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n";
+ for (ArrayRef<CodeGenSubRegIndex*>::const_iterator
+ SRI = SubRegIndices.begin(), SRE = SubRegIndices.end();
+ SRI != SRE; ++SRI) {
+ OS << " { " << (*SRI)->getOffset() << ", "
+ << (*SRI)->getSize()
+ << " },\t// " << (*SRI)->getName() << "\n";
+ }
+ OS << "};\n\n";
+
// Emit the string table.
RegStrings.layout();
OS << "extern const char " << TargetName << "RegStrings[] = {\n";
OS << "};\n\n";
- ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices();
-
EmitRegMappingTables(OS, Regs, false);
// Emit Reg encoding table
<< TargetName << "RegStrings, "
<< TargetName << "SubRegIdxLists, "
<< (SubRegIndices.size() + 1) << ",\n"
+ << TargetName << "SubRegIdxRanges, "
<< " " << TargetName << "RegEncodingTable);\n\n";
EmitRegMapping(OS, Regs, false);
OS << "extern const char " << TargetName << "RegStrings[];\n";
OS << "extern const uint16_t " << TargetName << "RegUnitRoots[][2];\n";
OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n";
+ OS << "extern const MCRegisterInfo::SubRegCoveredBits "
+ << TargetName << "SubRegIdxRanges[];\n";
OS << "extern const uint16_t " << TargetName << "RegEncodingTable[];\n";
EmitRegMappingTables(OS, Regs, true);
<< " " << TargetName << "RegStrings,\n"
<< " " << TargetName << "SubRegIdxLists,\n"
<< " " << SubRegIndices.size() + 1 << ",\n"
+ << " " << TargetName << "SubRegIdxRanges,\n"
<< " " << TargetName << "RegEncodingTable);\n\n";
EmitRegMapping(OS, Regs, true);