mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-01 16:33:37 +01:00
e0801b07e0
target machine from those that are only needed by codegen. The goal is to sink the essential target description into MC layer so we can start building MC based tools without needing to link in the entire codegen. First step is to refactor TargetRegisterInfo. This patch added a base class MCRegisterInfo which TargetRegisterInfo is derived from. Changed TableGen to separate register description from the rest of the stuff. llvm-svn: 133782
719 lines
26 KiB
C++
719 lines
26 KiB
C++
//===- RegisterInfoEmitter.cpp - Generate a Register File Desc. -*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This tablegen backend is responsible for emitting a description of a target
|
|
// register file for a code generator. It uses instances of the Register,
|
|
// RegisterAliases, and RegisterClass classes to gather this information.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "RegisterInfoEmitter.h"
|
|
#include "CodeGenTarget.h"
|
|
#include "CodeGenRegisters.h"
|
|
#include "Record.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/Support/Format.h"
|
|
#include <algorithm>
|
|
#include <set>
|
|
using namespace llvm;
|
|
|
|
// runEnums - Print out enum values for all of the registers.
|
|
void RegisterInfoEmitter::runEnums(raw_ostream &OS) {
|
|
CodeGenTarget Target(Records);
|
|
CodeGenRegBank &Bank = Target.getRegBank();
|
|
const std::vector<CodeGenRegister*> &Registers = Bank.getRegisters();
|
|
|
|
std::string Namespace = Registers[0]->TheDef->getValueAsString("Namespace");
|
|
|
|
EmitSourceFileHeader("Target Register Enum Values", OS);
|
|
OS << "namespace llvm {\n\n";
|
|
|
|
if (!Namespace.empty())
|
|
OS << "namespace " << Namespace << " {\n";
|
|
OS << "enum {\n NoRegister,\n";
|
|
|
|
for (unsigned i = 0, e = Registers.size(); i != e; ++i)
|
|
OS << " " << Registers[i]->getName() << " = " <<
|
|
Registers[i]->EnumValue << ",\n";
|
|
assert(Registers.size() == Registers[Registers.size()-1]->EnumValue &&
|
|
"Register enum value mismatch!");
|
|
OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n";
|
|
OS << "};\n";
|
|
if (!Namespace.empty())
|
|
OS << "}\n";
|
|
|
|
const std::vector<Record*> &SubRegIndices = Bank.getSubRegIndices();
|
|
if (!SubRegIndices.empty()) {
|
|
OS << "\n// Subregister indices\n";
|
|
Namespace = SubRegIndices[0]->getValueAsString("Namespace");
|
|
if (!Namespace.empty())
|
|
OS << "namespace " << Namespace << " {\n";
|
|
OS << "enum {\n NoSubRegister,\n";
|
|
for (unsigned i = 0, e = Bank.getNumNamedIndices(); i != e; ++i)
|
|
OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n";
|
|
OS << " NUM_TARGET_NAMED_SUBREGS = " << SubRegIndices.size()+1 << "\n";
|
|
OS << "};\n";
|
|
if (!Namespace.empty())
|
|
OS << "}\n";
|
|
}
|
|
OS << "} // End llvm namespace \n";
|
|
}
|
|
|
|
void RegisterInfoEmitter::runHeader(raw_ostream &OS) {
|
|
EmitSourceFileHeader("Register Information Header Fragment", OS);
|
|
CodeGenTarget Target(Records);
|
|
const std::string &TargetName = Target.getName();
|
|
std::string ClassName = TargetName + "GenRegisterInfo";
|
|
|
|
OS << "#include \"llvm/Target/TargetRegisterInfo.h\"\n";
|
|
OS << "#include <string>\n\n";
|
|
|
|
OS << "namespace llvm {\n\n";
|
|
|
|
OS << "struct " << ClassName << " : public TargetRegisterInfo {\n"
|
|
<< " explicit " << ClassName
|
|
<< "(const TargetRegisterDesc *D, const TargetRegisterInfoDesc *ID, "
|
|
<< "int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n"
|
|
<< " virtual int getDwarfRegNumFull(unsigned RegNum, "
|
|
<< "unsigned Flavour) const;\n"
|
|
<< " virtual int getLLVMRegNumFull(unsigned DwarfRegNum, "
|
|
<< "unsigned Flavour) const;\n"
|
|
<< " virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const = 0;\n"
|
|
<< " virtual bool needsStackRealignment(const MachineFunction &) const\n"
|
|
<< " { return false; }\n"
|
|
<< " unsigned getSubReg(unsigned RegNo, unsigned Index) const;\n"
|
|
<< " unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const;\n"
|
|
<< " unsigned composeSubRegIndices(unsigned, unsigned) const;\n"
|
|
<< "};\n\n";
|
|
|
|
const std::vector<CodeGenRegisterClass> &RegisterClasses =
|
|
Target.getRegisterClasses();
|
|
|
|
if (!RegisterClasses.empty()) {
|
|
OS << "namespace " << RegisterClasses[0].Namespace
|
|
<< " { // Register classes\n";
|
|
|
|
OS << " enum {\n";
|
|
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
|
|
if (i) OS << ",\n";
|
|
OS << " " << RegisterClasses[i].getName() << "RegClassID";
|
|
OS << " = " << i;
|
|
}
|
|
OS << "\n };\n\n";
|
|
|
|
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
|
|
const CodeGenRegisterClass &RC = RegisterClasses[i];
|
|
const std::string &Name = RC.getName();
|
|
|
|
// Output the register class definition.
|
|
OS << " struct " << Name << "Class : public TargetRegisterClass {\n"
|
|
<< " " << Name << "Class();\n";
|
|
if (!RC.AltOrderSelect.empty())
|
|
OS << " ArrayRef<unsigned> "
|
|
"getRawAllocationOrder(const MachineFunction&) const;\n";
|
|
OS << " };\n";
|
|
|
|
// Output the extern for the instance.
|
|
OS << " extern " << Name << "Class\t" << Name << "RegClass;\n";
|
|
// Output the extern for the pointer to the instance (should remove).
|
|
OS << " static TargetRegisterClass * const "<< Name <<"RegisterClass = &"
|
|
<< Name << "RegClass;\n";
|
|
}
|
|
OS << "} // end of namespace " << TargetName << "\n\n";
|
|
}
|
|
OS << "} // End llvm namespace \n";
|
|
}
|
|
|
|
typedef std::pair<unsigned, unsigned> UUPair;
|
|
typedef std::vector<UUPair> UUVector;
|
|
|
|
//
|
|
// RegisterInfoEmitter::run - Main register file description emitter.
|
|
//
|
|
void RegisterInfoEmitter::run(raw_ostream &OS) {
|
|
CodeGenTarget Target(Records);
|
|
CodeGenRegBank &RegBank = Target.getRegBank();
|
|
RegBank.computeDerivedInfo();
|
|
|
|
EmitSourceFileHeader("Register Information Source Fragment", OS);
|
|
|
|
OS << "namespace llvm {\n\n";
|
|
|
|
// Start out by emitting each of the register classes.
|
|
const std::vector<CodeGenRegisterClass> &RegisterClasses =
|
|
Target.getRegisterClasses();
|
|
|
|
// Collect all registers belonging to any allocatable class.
|
|
std::set<Record*> AllocatableRegs;
|
|
|
|
// Loop over all of the register classes... emitting each one.
|
|
OS << "namespace { // Register classes...\n";
|
|
|
|
// Emit the register enum value arrays for each RegisterClass
|
|
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
|
|
const CodeGenRegisterClass &RC = RegisterClasses[rc];
|
|
ArrayRef<Record*> Order = RC.getOrder();
|
|
|
|
// Collect allocatable registers.
|
|
if (RC.Allocatable)
|
|
AllocatableRegs.insert(Order.begin(), Order.end());
|
|
|
|
// Give the register class a legal C name if it's anonymous.
|
|
std::string Name = RC.getName();
|
|
|
|
// Emit the register list now.
|
|
OS << " // " << Name << " Register Class...\n"
|
|
<< " static const unsigned " << Name
|
|
<< "[] = {\n ";
|
|
for (unsigned i = 0, e = Order.size(); i != e; ++i) {
|
|
Record *Reg = Order[i];
|
|
OS << getQualifiedName(Reg) << ", ";
|
|
}
|
|
OS << "\n };\n\n";
|
|
}
|
|
|
|
// Emit the ValueType arrays for each RegisterClass
|
|
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
|
|
const CodeGenRegisterClass &RC = RegisterClasses[rc];
|
|
|
|
// Give the register class a legal C name if it's anonymous.
|
|
std::string Name = RC.getName() + "VTs";
|
|
|
|
// Emit the register list now.
|
|
OS << " // " << Name
|
|
<< " Register Class Value Types...\n"
|
|
<< " static const EVT " << Name
|
|
<< "[] = {\n ";
|
|
for (unsigned i = 0, e = RC.VTs.size(); i != e; ++i)
|
|
OS << getEnumName(RC.VTs[i]) << ", ";
|
|
OS << "MVT::Other\n };\n\n";
|
|
}
|
|
OS << "} // end anonymous namespace\n\n";
|
|
|
|
// Now that all of the structs have been emitted, emit the instances.
|
|
if (!RegisterClasses.empty()) {
|
|
OS << "namespace " << RegisterClasses[0].Namespace
|
|
<< " { // Register class instances\n";
|
|
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i)
|
|
OS << " " << RegisterClasses[i].getName() << "Class\t"
|
|
<< RegisterClasses[i].getName() << "RegClass;\n";
|
|
|
|
std::map<unsigned, std::set<unsigned> > SuperClassMap;
|
|
std::map<unsigned, std::set<unsigned> > SuperRegClassMap;
|
|
OS << "\n";
|
|
|
|
unsigned NumSubRegIndices = RegBank.getSubRegIndices().size();
|
|
|
|
if (NumSubRegIndices) {
|
|
// Emit the sub-register classes for each RegisterClass
|
|
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
|
|
const CodeGenRegisterClass &RC = RegisterClasses[rc];
|
|
std::vector<Record*> SRC(NumSubRegIndices);
|
|
for (DenseMap<Record*,Record*>::const_iterator
|
|
i = RC.SubRegClasses.begin(),
|
|
e = RC.SubRegClasses.end(); i != e; ++i) {
|
|
// Build SRC array.
|
|
unsigned idx = RegBank.getSubRegIndexNo(i->first);
|
|
SRC.at(idx-1) = i->second;
|
|
|
|
// Find the register class number of i->second for SuperRegClassMap.
|
|
for (unsigned rc2 = 0, e2 = RegisterClasses.size(); rc2 != e2; ++rc2) {
|
|
const CodeGenRegisterClass &RC2 = RegisterClasses[rc2];
|
|
if (RC2.TheDef == i->second) {
|
|
SuperRegClassMap[rc2].insert(rc);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Give the register class a legal C name if it's anonymous.
|
|
std::string Name = RC.TheDef->getName();
|
|
|
|
OS << " // " << Name
|
|
<< " Sub-register Classes...\n"
|
|
<< " static const TargetRegisterClass* const "
|
|
<< Name << "SubRegClasses[] = {\n ";
|
|
|
|
for (unsigned idx = 0; idx != NumSubRegIndices; ++idx) {
|
|
if (idx)
|
|
OS << ", ";
|
|
if (SRC[idx])
|
|
OS << "&" << getQualifiedName(SRC[idx]) << "RegClass";
|
|
else
|
|
OS << "0";
|
|
}
|
|
OS << "\n };\n\n";
|
|
}
|
|
|
|
// Emit the super-register classes for each RegisterClass
|
|
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
|
|
const CodeGenRegisterClass &RC = RegisterClasses[rc];
|
|
|
|
// Give the register class a legal C name if it's anonymous.
|
|
std::string Name = RC.TheDef->getName();
|
|
|
|
OS << " // " << Name
|
|
<< " Super-register Classes...\n"
|
|
<< " static const TargetRegisterClass* const "
|
|
<< Name << "SuperRegClasses[] = {\n ";
|
|
|
|
bool Empty = true;
|
|
std::map<unsigned, std::set<unsigned> >::iterator I =
|
|
SuperRegClassMap.find(rc);
|
|
if (I != SuperRegClassMap.end()) {
|
|
for (std::set<unsigned>::iterator II = I->second.begin(),
|
|
EE = I->second.end(); II != EE; ++II) {
|
|
const CodeGenRegisterClass &RC2 = RegisterClasses[*II];
|
|
if (!Empty)
|
|
OS << ", ";
|
|
OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
|
|
Empty = false;
|
|
}
|
|
}
|
|
|
|
OS << (!Empty ? ", " : "") << "NULL";
|
|
OS << "\n };\n\n";
|
|
}
|
|
} else {
|
|
// No subregindices in this target
|
|
OS << " static const TargetRegisterClass* const "
|
|
<< "NullRegClasses[] = { NULL };\n\n";
|
|
}
|
|
|
|
// Emit the sub-classes array for each RegisterClass
|
|
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
|
|
const CodeGenRegisterClass &RC = RegisterClasses[rc];
|
|
|
|
// Give the register class a legal C name if it's anonymous.
|
|
std::string Name = RC.TheDef->getName();
|
|
|
|
OS << " // " << Name
|
|
<< " Register Class sub-classes...\n"
|
|
<< " static const TargetRegisterClass* const "
|
|
<< Name << "Subclasses[] = {\n ";
|
|
|
|
bool Empty = true;
|
|
for (unsigned rc2 = 0, e2 = RegisterClasses.size(); rc2 != e2; ++rc2) {
|
|
const CodeGenRegisterClass &RC2 = RegisterClasses[rc2];
|
|
|
|
// Sub-classes are used to determine if a virtual register can be used
|
|
// as an instruction operand, or if it must be copied first.
|
|
if (rc == rc2 || !RC.hasSubClass(&RC2)) continue;
|
|
|
|
if (!Empty) OS << ", ";
|
|
OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
|
|
Empty = false;
|
|
|
|
std::map<unsigned, std::set<unsigned> >::iterator SCMI =
|
|
SuperClassMap.find(rc2);
|
|
if (SCMI == SuperClassMap.end()) {
|
|
SuperClassMap.insert(std::make_pair(rc2, std::set<unsigned>()));
|
|
SCMI = SuperClassMap.find(rc2);
|
|
}
|
|
SCMI->second.insert(rc);
|
|
}
|
|
|
|
OS << (!Empty ? ", " : "") << "NULL";
|
|
OS << "\n };\n\n";
|
|
}
|
|
|
|
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
|
|
const CodeGenRegisterClass &RC = RegisterClasses[rc];
|
|
|
|
// Give the register class a legal C name if it's anonymous.
|
|
std::string Name = RC.TheDef->getName();
|
|
|
|
OS << " // " << Name
|
|
<< " Register Class super-classes...\n"
|
|
<< " static const TargetRegisterClass* const "
|
|
<< Name << "Superclasses[] = {\n ";
|
|
|
|
bool Empty = true;
|
|
std::map<unsigned, std::set<unsigned> >::iterator I =
|
|
SuperClassMap.find(rc);
|
|
if (I != SuperClassMap.end()) {
|
|
for (std::set<unsigned>::iterator II = I->second.begin(),
|
|
EE = I->second.end(); II != EE; ++II) {
|
|
const CodeGenRegisterClass &RC2 = RegisterClasses[*II];
|
|
if (!Empty) OS << ", ";
|
|
OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
|
|
Empty = false;
|
|
}
|
|
}
|
|
|
|
OS << (!Empty ? ", " : "") << "NULL";
|
|
OS << "\n };\n\n";
|
|
}
|
|
|
|
// Emit methods.
|
|
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
|
|
const CodeGenRegisterClass &RC = RegisterClasses[i];
|
|
OS << RC.getName() << "Class::" << RC.getName()
|
|
<< "Class() : TargetRegisterClass("
|
|
<< RC.getName() + "RegClassID" << ", "
|
|
<< '\"' << RC.getName() << "\", "
|
|
<< RC.getName() + "VTs" << ", "
|
|
<< RC.getName() + "Subclasses" << ", "
|
|
<< RC.getName() + "Superclasses" << ", "
|
|
<< (NumSubRegIndices ? RC.getName() + "Sub" : std::string("Null"))
|
|
<< "RegClasses, "
|
|
<< (NumSubRegIndices ? RC.getName() + "Super" : std::string("Null"))
|
|
<< "RegClasses, "
|
|
<< RC.SpillSize/8 << ", "
|
|
<< RC.SpillAlignment/8 << ", "
|
|
<< RC.CopyCost << ", "
|
|
<< RC.Allocatable << ", "
|
|
<< RC.getName() << ", " << RC.getName() << " + "
|
|
<< RC.getOrder().size()
|
|
<< ") {}\n";
|
|
if (!RC.AltOrderSelect.empty()) {
|
|
OS << "\nstatic inline unsigned " << RC.getName()
|
|
<< "AltOrderSelect(const MachineFunction &MF) {"
|
|
<< RC.AltOrderSelect << "}\n\nArrayRef<unsigned> "
|
|
<< RC.getName() << "Class::"
|
|
<< "getRawAllocationOrder(const MachineFunction &MF) const {\n";
|
|
for (unsigned oi = 1 , oe = RC.getNumOrders(); oi != oe; ++oi) {
|
|
ArrayRef<Record*> Elems = RC.getOrder(oi);
|
|
OS << " static const unsigned AltOrder" << oi << "[] = {";
|
|
for (unsigned elem = 0; elem != Elems.size(); ++elem)
|
|
OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]);
|
|
OS << " };\n";
|
|
}
|
|
OS << " static const ArrayRef<unsigned> Order[] = {\n"
|
|
<< " ArrayRef<unsigned>(" << RC.getName();
|
|
for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi)
|
|
OS << "),\n ArrayRef<unsigned>(AltOrder" << oi;
|
|
OS << ")\n };\n const unsigned Select = " << RC.getName()
|
|
<< "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders()
|
|
<< ");\n return Order[Select];\n}\n";
|
|
}
|
|
}
|
|
|
|
OS << "}\n";
|
|
}
|
|
|
|
OS << "\nnamespace {\n";
|
|
OS << " const TargetRegisterClass* const RegisterClasses[] = {\n";
|
|
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i)
|
|
OS << " &" << getQualifiedName(RegisterClasses[i].TheDef)
|
|
<< "RegClass,\n";
|
|
OS << " };\n";
|
|
|
|
// Emit extra information about registers.
|
|
OS << "\n static const TargetRegisterInfoDesc "
|
|
<< Target.getName() << "RegInfoDesc[] = "
|
|
<< "{ // Extra Descriptors\n";
|
|
OS << " { 0, 0 },\n";
|
|
|
|
const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters();
|
|
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
|
|
const CodeGenRegister &Reg = *Regs[i];
|
|
OS << " { ";
|
|
OS << Reg.CostPerUse << ", "
|
|
<< int(AllocatableRegs.count(Reg.TheDef)) << " },\n";
|
|
}
|
|
OS << " };\n"; // End of register descriptors...
|
|
|
|
|
|
// Calculate the mapping of subregister+index pairs to physical registers.
|
|
// This will also create further anonymous indexes.
|
|
unsigned NamedIndices = RegBank.getNumNamedIndices();
|
|
|
|
// Emit SubRegIndex names, skipping 0
|
|
const std::vector<Record*> &SubRegIndices = RegBank.getSubRegIndices();
|
|
OS << "\n const char *const SubRegIndexTable[] = { \"";
|
|
for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) {
|
|
OS << SubRegIndices[i]->getName();
|
|
if (i+1 != e)
|
|
OS << "\", \"";
|
|
}
|
|
OS << "\" };\n\n";
|
|
|
|
// Emit names of the anonymus subreg indexes.
|
|
if (SubRegIndices.size() > NamedIndices) {
|
|
OS << " enum {";
|
|
for (unsigned i = NamedIndices, e = SubRegIndices.size(); i != e; ++i) {
|
|
OS << "\n " << SubRegIndices[i]->getName() << " = " << i+1;
|
|
if (i+1 != e)
|
|
OS << ',';
|
|
}
|
|
OS << "\n };\n\n";
|
|
}
|
|
OS << "}\n\n"; // End of anonymous namespace...
|
|
|
|
std::string ClassName = Target.getName() + "GenRegisterInfo";
|
|
|
|
// Emit the subregister + index mapping function based on the information
|
|
// calculated above.
|
|
OS << "unsigned " << ClassName
|
|
<< "::getSubReg(unsigned RegNo, unsigned Index) const {\n"
|
|
<< " switch (RegNo) {\n"
|
|
<< " default:\n return 0;\n";
|
|
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
|
|
const CodeGenRegister::SubRegMap &SRM = Regs[i]->getSubRegs();
|
|
if (SRM.empty())
|
|
continue;
|
|
OS << " case " << getQualifiedName(Regs[i]->TheDef) << ":\n";
|
|
OS << " switch (Index) {\n";
|
|
OS << " default: return 0;\n";
|
|
for (CodeGenRegister::SubRegMap::const_iterator ii = SRM.begin(),
|
|
ie = SRM.end(); ii != ie; ++ii)
|
|
OS << " case " << getQualifiedName(ii->first)
|
|
<< ": return " << getQualifiedName(ii->second->TheDef) << ";\n";
|
|
OS << " };\n" << " break;\n";
|
|
}
|
|
OS << " };\n";
|
|
OS << " return 0;\n";
|
|
OS << "}\n\n";
|
|
|
|
OS << "unsigned " << ClassName
|
|
<< "::getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const {\n"
|
|
<< " switch (RegNo) {\n"
|
|
<< " default:\n return 0;\n";
|
|
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
|
|
const CodeGenRegister::SubRegMap &SRM = Regs[i]->getSubRegs();
|
|
if (SRM.empty())
|
|
continue;
|
|
OS << " case " << getQualifiedName(Regs[i]->TheDef) << ":\n";
|
|
for (CodeGenRegister::SubRegMap::const_iterator ii = SRM.begin(),
|
|
ie = SRM.end(); ii != ie; ++ii)
|
|
OS << " if (SubRegNo == " << getQualifiedName(ii->second->TheDef)
|
|
<< ") return " << getQualifiedName(ii->first) << ";\n";
|
|
OS << " return 0;\n";
|
|
}
|
|
OS << " };\n";
|
|
OS << " return 0;\n";
|
|
OS << "}\n\n";
|
|
|
|
// Emit composeSubRegIndices
|
|
OS << "unsigned " << ClassName
|
|
<< "::composeSubRegIndices(unsigned IdxA, unsigned IdxB) const {\n"
|
|
<< " switch (IdxA) {\n"
|
|
<< " default:\n return IdxB;\n";
|
|
for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) {
|
|
bool Open = false;
|
|
for (unsigned j = 0; j != e; ++j) {
|
|
if (Record *Comp = RegBank.getCompositeSubRegIndex(SubRegIndices[i],
|
|
SubRegIndices[j])) {
|
|
if (!Open) {
|
|
OS << " case " << getQualifiedName(SubRegIndices[i])
|
|
<< ": switch(IdxB) {\n default: return IdxB;\n";
|
|
Open = true;
|
|
}
|
|
OS << " case " << getQualifiedName(SubRegIndices[j])
|
|
<< ": return " << getQualifiedName(Comp) << ";\n";
|
|
}
|
|
}
|
|
if (Open)
|
|
OS << " }\n";
|
|
}
|
|
OS << " }\n}\n\n";
|
|
|
|
// Emit the constructor of the class...
|
|
OS << ClassName << "::" << ClassName
|
|
<< "(const TargetRegisterDesc *D, const TargetRegisterInfoDesc *ID, "
|
|
<< "int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n"
|
|
<< " : TargetRegisterInfo(ID"
|
|
<< ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n"
|
|
<< " SubRegIndexTable,\n"
|
|
<< " CallFrameSetupOpcode, CallFrameDestroyOpcode) {\n"
|
|
<< " InitMCRegisterInfo(D, " << Regs.size()+1 << ");\n"
|
|
<< "}\n\n";
|
|
|
|
// Collect all information about dwarf register numbers
|
|
typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy;
|
|
DwarfRegNumsMapTy DwarfRegNums;
|
|
|
|
// First, just pull all provided information to the map
|
|
unsigned maxLength = 0;
|
|
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
|
|
Record *Reg = Regs[i]->TheDef;
|
|
std::vector<int64_t> RegNums = Reg->getValueAsListOfInts("DwarfNumbers");
|
|
maxLength = std::max((size_t)maxLength, RegNums.size());
|
|
if (DwarfRegNums.count(Reg))
|
|
errs() << "Warning: DWARF numbers for register " << getQualifiedName(Reg)
|
|
<< "specified multiple times\n";
|
|
DwarfRegNums[Reg] = RegNums;
|
|
}
|
|
|
|
// Now we know maximal length of number list. Append -1's, where needed
|
|
for (DwarfRegNumsMapTy::iterator
|
|
I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I)
|
|
for (unsigned i = I->second.size(), e = maxLength; i != e; ++i)
|
|
I->second.push_back(-1);
|
|
|
|
// Emit reverse information about the dwarf register numbers.
|
|
OS << "int " << ClassName << "::getLLVMRegNumFull(unsigned DwarfRegNum, "
|
|
<< "unsigned Flavour) const {\n"
|
|
<< " switch (Flavour) {\n"
|
|
<< " default:\n"
|
|
<< " assert(0 && \"Unknown DWARF flavour\");\n"
|
|
<< " return -1;\n";
|
|
|
|
for (unsigned i = 0, e = maxLength; i != e; ++i) {
|
|
OS << " case " << i << ":\n"
|
|
<< " switch (DwarfRegNum) {\n"
|
|
<< " default:\n"
|
|
<< " assert(0 && \"Invalid DwarfRegNum\");\n"
|
|
<< " return -1;\n";
|
|
|
|
for (DwarfRegNumsMapTy::iterator
|
|
I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
|
|
int DwarfRegNo = I->second[i];
|
|
if (DwarfRegNo >= 0)
|
|
OS << " case " << DwarfRegNo << ":\n"
|
|
<< " return " << getQualifiedName(I->first) << ";\n";
|
|
}
|
|
OS << " };\n";
|
|
}
|
|
|
|
OS << " };\n}\n\n";
|
|
|
|
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
|
|
Record *Reg = Regs[i]->TheDef;
|
|
const RecordVal *V = Reg->getValue("DwarfAlias");
|
|
if (!V || !V->getValue())
|
|
continue;
|
|
|
|
DefInit *DI = dynamic_cast<DefInit*>(V->getValue());
|
|
Record *Alias = DI->getDef();
|
|
DwarfRegNums[Reg] = DwarfRegNums[Alias];
|
|
}
|
|
|
|
// Emit information about the dwarf register numbers.
|
|
OS << "int " << ClassName << "::getDwarfRegNumFull(unsigned RegNum, "
|
|
<< "unsigned Flavour) const {\n"
|
|
<< " switch (Flavour) {\n"
|
|
<< " default:\n"
|
|
<< " assert(0 && \"Unknown DWARF flavour\");\n"
|
|
<< " return -1;\n";
|
|
|
|
for (unsigned i = 0, e = maxLength; i != e; ++i) {
|
|
OS << " case " << i << ":\n"
|
|
<< " switch (RegNum) {\n"
|
|
<< " default:\n"
|
|
<< " assert(0 && \"Invalid RegNum\");\n"
|
|
<< " return -1;\n";
|
|
|
|
// Sort by name to get a stable order.
|
|
|
|
|
|
for (DwarfRegNumsMapTy::iterator
|
|
I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
|
|
int RegNo = I->second[i];
|
|
OS << " case " << getQualifiedName(I->first) << ":\n"
|
|
<< " return " << RegNo << ";\n";
|
|
}
|
|
OS << " };\n";
|
|
}
|
|
|
|
OS << " };\n}\n\n";
|
|
|
|
OS << "} // End llvm namespace \n";
|
|
}
|
|
|
|
void RegisterInfoEmitter::runDesc(raw_ostream &OS) {
|
|
CodeGenTarget Target(Records);
|
|
CodeGenRegBank &RegBank = Target.getRegBank();
|
|
RegBank.computeDerivedInfo();
|
|
std::map<const CodeGenRegister*, CodeGenRegister::Set> Overlaps;
|
|
RegBank.computeOverlaps(Overlaps);
|
|
|
|
OS << "namespace llvm {\n\n";
|
|
|
|
const std::string &TargetName = Target.getName();
|
|
std::string ClassName = TargetName + "GenMCRegisterInfo";
|
|
OS << "struct " << ClassName << " : public MCRegisterInfo {\n"
|
|
<< " explicit " << ClassName << "(const TargetRegisterDesc *D);\n";
|
|
OS << "};\n";
|
|
|
|
OS << "\nnamespace {\n";
|
|
|
|
const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters();
|
|
|
|
// Emit an overlap list for all registers.
|
|
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
|
|
const CodeGenRegister *Reg = Regs[i];
|
|
const CodeGenRegister::Set &O = Overlaps[Reg];
|
|
// Move Reg to the front so TRI::getAliasSet can share the list.
|
|
OS << " const unsigned " << Reg->getName() << "_Overlaps[] = { "
|
|
<< getQualifiedName(Reg->TheDef) << ", ";
|
|
for (CodeGenRegister::Set::const_iterator I = O.begin(), E = O.end();
|
|
I != E; ++I)
|
|
if (*I != Reg)
|
|
OS << getQualifiedName((*I)->TheDef) << ", ";
|
|
OS << "0 };\n";
|
|
}
|
|
|
|
// Emit the empty sub-registers list
|
|
OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n";
|
|
// Loop over all of the registers which have sub-registers, emitting the
|
|
// sub-registers list to memory.
|
|
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
|
|
const CodeGenRegister &Reg = *Regs[i];
|
|
if (Reg.getSubRegs().empty())
|
|
continue;
|
|
// getSubRegs() orders by SubRegIndex. We want a topological order.
|
|
SetVector<CodeGenRegister*> SR;
|
|
Reg.addSubRegsPreOrder(SR);
|
|
OS << " const unsigned " << Reg.getName() << "_SubRegsSet[] = { ";
|
|
for (unsigned j = 0, je = SR.size(); j != je; ++j)
|
|
OS << getQualifiedName(SR[j]->TheDef) << ", ";
|
|
OS << "0 };\n";
|
|
}
|
|
|
|
// Emit the empty super-registers list
|
|
OS << " const unsigned Empty_SuperRegsSet[] = { 0 };\n";
|
|
// Loop over all of the registers which have super-registers, emitting the
|
|
// super-registers list to memory.
|
|
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
|
|
const CodeGenRegister &Reg = *Regs[i];
|
|
const CodeGenRegister::SuperRegList &SR = Reg.getSuperRegs();
|
|
if (SR.empty())
|
|
continue;
|
|
OS << " const unsigned " << Reg.getName() << "_SuperRegsSet[] = { ";
|
|
for (unsigned j = 0, je = SR.size(); j != je; ++j)
|
|
OS << getQualifiedName(SR[j]->TheDef) << ", ";
|
|
OS << "0 };\n";
|
|
}
|
|
|
|
OS << "\n const TargetRegisterDesc " << TargetName
|
|
<< "RegDesc[] = { // Descriptors\n";
|
|
OS << " { \"NOREG\",\t0,\t0,\t0 },\n";
|
|
|
|
// Now that register alias and sub-registers sets have been emitted, emit the
|
|
// register descriptors now.
|
|
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
|
|
const CodeGenRegister &Reg = *Regs[i];
|
|
OS << " { \"";
|
|
OS << Reg.getName() << "\",\t" << Reg.getName() << "_Overlaps,\t";
|
|
if (!Reg.getSubRegs().empty())
|
|
OS << Reg.getName() << "_SubRegsSet,\t";
|
|
else
|
|
OS << "Empty_SubRegsSet,\t";
|
|
if (!Reg.getSuperRegs().empty())
|
|
OS << Reg.getName() << "_SuperRegsSet";
|
|
else
|
|
OS << "Empty_SuperRegsSet";
|
|
OS << " },\n";
|
|
}
|
|
OS << " };\n"; // End of register descriptors...
|
|
|
|
OS << "}\n\n"; // End of anonymous namespace...
|
|
|
|
// MCRegisterInfo initialization routine.
|
|
OS << "void " << "Init" << TargetName
|
|
<< "MCRegisterInfo(MCRegisterInfo *RI) {\n";
|
|
OS << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, "
|
|
<< Regs.size()+1 << ");\n}\n\n";
|
|
|
|
OS << "} // End llvm namespace \n";
|
|
}
|