mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-09 11:25:55 +00:00
Add support for alternative register names, useful for instructions whose operands are logically equivalent to existing registers, but happen to be printed specially. For example, an instruciton that prints d0[0] instead of s0.
Patch by Jim Grosbach. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133940 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -26,11 +26,19 @@ class SubRegIndex {
|
|||||||
string Namespace = "";
|
string Namespace = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegAltNameIndex - The alternate name set to use for register operands of
|
||||||
|
// this register class when printing.
|
||||||
|
class RegAltNameIndex {
|
||||||
|
string Namespace = "";
|
||||||
|
}
|
||||||
|
def NoRegAltName : RegAltNameIndex;
|
||||||
|
|
||||||
// Register - You should define one instance of this class for each register
|
// Register - You should define one instance of this class for each register
|
||||||
// in the target machine. String n will become the "name" of the register.
|
// in the target machine. String n will become the "name" of the register.
|
||||||
class Register<string n> {
|
class Register<string n, list<string> altNames = []> {
|
||||||
string Namespace = "";
|
string Namespace = "";
|
||||||
string AsmName = n;
|
string AsmName = n;
|
||||||
|
list<string> AltNames = altNames;
|
||||||
|
|
||||||
// Aliases - A list of registers that this register overlaps with. A read or
|
// Aliases - A list of registers that this register overlaps with. A read or
|
||||||
// modification of this register can potentially read or modify the aliased
|
// modification of this register can potentially read or modify the aliased
|
||||||
@@ -48,6 +56,10 @@ class Register<string n> {
|
|||||||
// SubRegs.
|
// SubRegs.
|
||||||
list<SubRegIndex> SubRegIndices = [];
|
list<SubRegIndex> SubRegIndices = [];
|
||||||
|
|
||||||
|
// RegAltNameIndices - The alternate name indices which are valid for this
|
||||||
|
// register.
|
||||||
|
list<RegAltNameIndex> RegAltNameIndices = [];
|
||||||
|
|
||||||
// CompositeIndices - Specify subreg indices that don't correspond directly to
|
// CompositeIndices - Specify subreg indices that don't correspond directly to
|
||||||
// a register in SubRegs and are not inherited. The following formats are
|
// a register in SubRegs and are not inherited. The following formats are
|
||||||
// supported:
|
// supported:
|
||||||
@@ -92,7 +104,7 @@ class RegisterWithSubRegs<string n, list<Register> subregs> : Register<n> {
|
|||||||
// registers by register allocators.
|
// registers by register allocators.
|
||||||
//
|
//
|
||||||
class RegisterClass<string namespace, list<ValueType> regTypes, int alignment,
|
class RegisterClass<string namespace, list<ValueType> regTypes, int alignment,
|
||||||
dag regList> {
|
dag regList, RegAltNameIndex idx = NoRegAltName> {
|
||||||
string Namespace = namespace;
|
string Namespace = namespace;
|
||||||
|
|
||||||
// RegType - Specify the list ValueType of the registers in this register
|
// RegType - Specify the list ValueType of the registers in this register
|
||||||
@@ -124,6 +136,11 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment,
|
|||||||
//
|
//
|
||||||
dag MemberList = regList;
|
dag MemberList = regList;
|
||||||
|
|
||||||
|
// AltNameIndex - The alternate register name to use when printing operands
|
||||||
|
// of this register class. Every register in the register class must have
|
||||||
|
// a valid alternate name for the given index.
|
||||||
|
RegAltNameIndex altNameIndex = idx;
|
||||||
|
|
||||||
// SubRegClasses - Specify the register class of subregisters as a list of
|
// SubRegClasses - Specify the register class of subregisters as a list of
|
||||||
// dags: (RegClass SubRegIndex, SubRegindex, ...)
|
// dags: (RegClass SubRegIndex, SubRegindex, ...)
|
||||||
list<dag> SubRegClasses = [];
|
list<dag> SubRegClasses = [];
|
||||||
@@ -466,6 +483,24 @@ class Operand<ValueType ty> {
|
|||||||
AsmOperandClass ParserMatchClass = ImmAsmOperand;
|
AsmOperandClass ParserMatchClass = ImmAsmOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RegisterOperand<RegisterClass regclass, string pm = "printOperand"> {
|
||||||
|
// RegClass - The register class of the operand.
|
||||||
|
RegisterClass RegClass = regclass;
|
||||||
|
// PrintMethod - The target method to call to print register operands of
|
||||||
|
// this type. The method normally will just use an alt-name index to look
|
||||||
|
// up the name to print. Default to the generic printOperand().
|
||||||
|
string PrintMethod = pm;
|
||||||
|
// ParserMatchClass - The "match class" that operands of this type fit
|
||||||
|
// in. Match classes are used to define the order in which instructions are
|
||||||
|
// match, to ensure that which instructions gets matched is deterministic.
|
||||||
|
//
|
||||||
|
// The target specific parser must be able to classify an parsed operand into
|
||||||
|
// a unique class, which does not partially overlap with any other classes. It
|
||||||
|
// can match a subset of some other class, in which case the AsmOperandClass
|
||||||
|
// should declare the other operand as one of its super classes.
|
||||||
|
AsmOperandClass ParserMatchClass;
|
||||||
|
}
|
||||||
|
|
||||||
def i1imm : Operand<i1>;
|
def i1imm : Operand<i1>;
|
||||||
def i8imm : Operand<i8>;
|
def i8imm : Operand<i8>;
|
||||||
def i16imm : Operand<i16>;
|
def i16imm : Operand<i16>;
|
||||||
|
@@ -871,6 +871,31 @@ AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI,
|
|||||||
if (SubOpIdx != -1)
|
if (SubOpIdx != -1)
|
||||||
Rec = dynamic_cast<DefInit*>(OI.MIOperandInfo->getArg(SubOpIdx))->getDef();
|
Rec = dynamic_cast<DefInit*>(OI.MIOperandInfo->getArg(SubOpIdx))->getDef();
|
||||||
|
|
||||||
|
if (Rec->isSubClassOf("RegisterOperand")) {
|
||||||
|
// RegisterOperand may have an associated ParserMatchClass. If it does,
|
||||||
|
// use it, else just fall back to the underlying register class.
|
||||||
|
const RecordVal *R = Rec->getValue("ParserMatchClass");
|
||||||
|
if (R == 0 || R->getValue() == 0)
|
||||||
|
throw "Record `" + Rec->getName() +
|
||||||
|
"' does not have a ParserMatchClass!\n";
|
||||||
|
|
||||||
|
if (DefInit *DI= dynamic_cast<DefInit*>(R->getValue())) {
|
||||||
|
Record *MatchClass = DI->getDef();
|
||||||
|
if (ClassInfo *CI = AsmOperandClasses[MatchClass])
|
||||||
|
return CI;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No custom match class. Just use the register class.
|
||||||
|
Record *ClassRec = Rec->getValueAsDef("RegClass");
|
||||||
|
if (!ClassRec)
|
||||||
|
throw TGError(Rec->getLoc(), "RegisterOperand `" + Rec->getName() +
|
||||||
|
"' has no associated register class!\n");
|
||||||
|
if (ClassInfo *CI = RegisterClassClasses[ClassRec])
|
||||||
|
return CI;
|
||||||
|
throw TGError(Rec->getLoc(), "register class has no class info!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (Rec->isSubClassOf("RegisterClass")) {
|
if (Rec->isSubClassOf("RegisterClass")) {
|
||||||
if (ClassInfo *CI = RegisterClassClasses[Rec])
|
if (ClassInfo *CI = RegisterClassClasses[Rec])
|
||||||
return CI;
|
return CI;
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#include "CodeGenTarget.h"
|
#include "CodeGenTarget.h"
|
||||||
#include "Record.h"
|
#include "Record.h"
|
||||||
#include "StringToOffsetTable.h"
|
#include "StringToOffsetTable.h"
|
||||||
|
#include "llvm/ADT/Twine.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/MathExtras.h"
|
#include "llvm/Support/MathExtras.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -458,6 +459,58 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
|||||||
O << "}\n";
|
O << "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
emitRegisterNameString(raw_ostream &O, StringRef AltName,
|
||||||
|
const std::vector<CodeGenRegister*> &Registers) {
|
||||||
|
StringToOffsetTable StringTable;
|
||||||
|
O << " static const unsigned RegAsmOffset" << AltName << "[] = {\n ";
|
||||||
|
for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
|
||||||
|
const CodeGenRegister &Reg = *Registers[i];
|
||||||
|
|
||||||
|
StringRef AsmName;
|
||||||
|
// "NoRegAltName" is special. We don't need to do a lookup for that,
|
||||||
|
// as it's just a reference to the default register name.
|
||||||
|
if (AltName == "" || AltName == "NoRegAltName") {
|
||||||
|
AsmName = Reg.TheDef->getValueAsString("AsmName");
|
||||||
|
if (AsmName.empty())
|
||||||
|
AsmName = Reg.getName();
|
||||||
|
} else {
|
||||||
|
// Make sure the register has an alternate name for this index.
|
||||||
|
std::vector<Record*> AltNameList =
|
||||||
|
Reg.TheDef->getValueAsListOfDefs("RegAltNameIndices");
|
||||||
|
unsigned Idx = 0, e;
|
||||||
|
for (e = AltNameList.size();
|
||||||
|
Idx < e && (AltNameList[Idx]->getName() != AltName);
|
||||||
|
++Idx)
|
||||||
|
;
|
||||||
|
// If the register has an alternate name for this index, use it.
|
||||||
|
// Otherwise, leave it empty as an error flag.
|
||||||
|
if (Idx < e) {
|
||||||
|
std::vector<std::string> AltNames =
|
||||||
|
Reg.TheDef->getValueAsListOfStrings("AltNames");
|
||||||
|
if (AltNames.size() <= Idx)
|
||||||
|
throw TGError(Reg.TheDef->getLoc(),
|
||||||
|
(Twine("Register definition missing alt name for '") +
|
||||||
|
AltName + "'.").str());
|
||||||
|
AsmName = AltNames[Idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
O << StringTable.GetOrAddStringOffset(AsmName);
|
||||||
|
if (((i + 1) % 14) == 0)
|
||||||
|
O << ",\n ";
|
||||||
|
else
|
||||||
|
O << ", ";
|
||||||
|
|
||||||
|
}
|
||||||
|
O << "0\n"
|
||||||
|
<< " };\n"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
O << " const char *AsmStrs" << AltName << " =\n";
|
||||||
|
StringTable.EmitString(O);
|
||||||
|
O << ";\n";
|
||||||
|
}
|
||||||
|
|
||||||
void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
|
void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
|
||||||
CodeGenTarget Target(Records);
|
CodeGenTarget Target(Records);
|
||||||
@@ -465,40 +518,48 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
|
|||||||
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
|
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
|
||||||
const std::vector<CodeGenRegister*> &Registers =
|
const std::vector<CodeGenRegister*> &Registers =
|
||||||
Target.getRegBank().getRegisters();
|
Target.getRegBank().getRegisters();
|
||||||
|
std::vector<Record*> AltNameIndices = Target.getRegAltNameIndices();
|
||||||
|
bool hasAltNames = AltNameIndices.size() > 1;
|
||||||
|
|
||||||
StringToOffsetTable StringTable;
|
|
||||||
O <<
|
O <<
|
||||||
"\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
|
"\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
|
||||||
"/// from the register set description. This returns the assembler name\n"
|
"/// from the register set description. This returns the assembler name\n"
|
||||||
"/// for the specified register.\n"
|
"/// for the specified register.\n"
|
||||||
"const char *" << Target.getName() << ClassName
|
"const char *" << Target.getName() << ClassName << "::";
|
||||||
<< "::getRegisterName(unsigned RegNo) {\n"
|
if (hasAltNames)
|
||||||
<< " assert(RegNo && RegNo < " << (Registers.size()+1)
|
O << "\ngetRegisterName(unsigned RegNo, unsigned AltIdx) {\n";
|
||||||
<< " && \"Invalid register number!\");\n"
|
else
|
||||||
<< "\n"
|
O << "getRegisterName(unsigned RegNo) {\n";
|
||||||
<< " static const unsigned RegAsmOffset[] = {";
|
O << " assert(RegNo && RegNo < " << (Registers.size()+1)
|
||||||
for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
|
<< " && \"Invalid register number!\");\n"
|
||||||
const CodeGenRegister &Reg = *Registers[i];
|
|
||||||
|
|
||||||
std::string AsmName = Reg.TheDef->getValueAsString("AsmName");
|
|
||||||
if (AsmName.empty())
|
|
||||||
AsmName = Reg.getName();
|
|
||||||
|
|
||||||
|
|
||||||
if ((i % 14) == 0)
|
|
||||||
O << "\n ";
|
|
||||||
|
|
||||||
O << StringTable.GetOrAddStringOffset(AsmName) << ", ";
|
|
||||||
}
|
|
||||||
O << "0\n"
|
|
||||||
<< " };\n"
|
|
||||||
<< "\n";
|
<< "\n";
|
||||||
|
|
||||||
O << " const char *AsmStrs =\n";
|
if (hasAltNames) {
|
||||||
StringTable.EmitString(O);
|
for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i)
|
||||||
O << ";\n";
|
emitRegisterNameString(O, AltNameIndices[i]->getName(), Registers);
|
||||||
|
} else
|
||||||
|
emitRegisterNameString(O, "", Registers);
|
||||||
|
|
||||||
O << " return AsmStrs+RegAsmOffset[RegNo-1];\n"
|
if (hasAltNames) {
|
||||||
|
O << " const unsigned *RegAsmOffset;\n"
|
||||||
|
<< " const char *AsmStrs;\n"
|
||||||
|
<< " switch(AltIdx) {\n"
|
||||||
|
<< " default: assert(0 && \"Invalid register alt name index!\");\n";
|
||||||
|
for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i) {
|
||||||
|
StringRef Namespace = AltNameIndices[1]->getValueAsString("Namespace");
|
||||||
|
StringRef AltName(AltNameIndices[i]->getName());
|
||||||
|
O << " case " << Namespace << "::" << AltName
|
||||||
|
<< ":\n"
|
||||||
|
<< " AsmStrs = AsmStrs" << AltName << ";\n"
|
||||||
|
<< " RegAsmOffset = RegAsmOffset" << AltName << ";\n"
|
||||||
|
<< " break;\n";
|
||||||
|
}
|
||||||
|
O << "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n"
|
||||||
|
<< " \"Invalid alt name index for register!\");\n"
|
||||||
|
<< " return AsmStrs+RegAsmOffset[RegNo-1];\n"
|
||||||
<< "}\n";
|
<< "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -936,6 +997,9 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
|
|||||||
const Record *Rec = RO.getRecord();
|
const Record *Rec = RO.getRecord();
|
||||||
StringRef ROName = RO.getName();
|
StringRef ROName = RO.getName();
|
||||||
|
|
||||||
|
|
||||||
|
if (Rec->isSubClassOf("RegisterOperand"))
|
||||||
|
Rec = Rec->getValueAsDef("RegClass");
|
||||||
if (Rec->isSubClassOf("RegisterClass")) {
|
if (Rec->isSubClassOf("RegisterClass")) {
|
||||||
Cond = std::string("MI->getOperand(")+llvm::utostr(i)+").isReg()";
|
Cond = std::string("MI->getOperand(")+llvm::utostr(i)+").isReg()";
|
||||||
IAP->addCond(Cond);
|
IAP->addCond(Cond);
|
||||||
|
@@ -1242,6 +1242,16 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
|
|||||||
///
|
///
|
||||||
static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo,
|
static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo,
|
||||||
bool NotRegisters, TreePattern &TP) {
|
bool NotRegisters, TreePattern &TP) {
|
||||||
|
// Check to see if this is a register operand.
|
||||||
|
if (R->isSubClassOf("RegisterOperand")) {
|
||||||
|
assert(ResNo == 0 && "Regoperand ref only has one result!");
|
||||||
|
if (NotRegisters)
|
||||||
|
return EEVT::TypeSet(); // Unknown.
|
||||||
|
Record *RegClass = R->getValueAsDef("RegClass");
|
||||||
|
const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
|
||||||
|
return EEVT::TypeSet(T.getRegisterClass(RegClass).getValueTypes());
|
||||||
|
}
|
||||||
|
|
||||||
// Check to see if this is a register or a register class.
|
// Check to see if this is a register or a register class.
|
||||||
if (R->isSubClassOf("RegisterClass")) {
|
if (R->isSubClassOf("RegisterClass")) {
|
||||||
assert(ResNo == 0 && "Regclass ref only has one result!");
|
assert(ResNo == 0 && "Regclass ref only has one result!");
|
||||||
@@ -1524,6 +1534,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
|
|||||||
|
|
||||||
if (ResultNode->isSubClassOf("PointerLikeRegClass")) {
|
if (ResultNode->isSubClassOf("PointerLikeRegClass")) {
|
||||||
MadeChange |= UpdateNodeType(ResNo, MVT::iPTR, TP);
|
MadeChange |= UpdateNodeType(ResNo, MVT::iPTR, TP);
|
||||||
|
} else if (ResultNode->isSubClassOf("RegisterOperand")) {
|
||||||
|
Record *RegClass = ResultNode->getValueAsDef("RegClass");
|
||||||
|
const CodeGenRegisterClass &RC =
|
||||||
|
CDP.getTargetInfo().getRegisterClass(RegClass);
|
||||||
|
MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP);
|
||||||
} else if (ResultNode->getName() == "unknown") {
|
} else if (ResultNode->getName() == "unknown") {
|
||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
} else {
|
} else {
|
||||||
@@ -1582,6 +1597,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
|
|||||||
const CodeGenRegisterClass &RC =
|
const CodeGenRegisterClass &RC =
|
||||||
CDP.getTargetInfo().getRegisterClass(OperandNode);
|
CDP.getTargetInfo().getRegisterClass(OperandNode);
|
||||||
MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP);
|
MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP);
|
||||||
|
} else if (OperandNode->isSubClassOf("RegisterOperand")) {
|
||||||
|
Record *RegClass = OperandNode->getValueAsDef("RegClass");
|
||||||
|
const CodeGenRegisterClass &RC =
|
||||||
|
CDP.getTargetInfo().getRegisterClass(RegClass);
|
||||||
|
MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP);
|
||||||
} else if (OperandNode->isSubClassOf("Operand")) {
|
} else if (OperandNode->isSubClassOf("Operand")) {
|
||||||
VT = getValueType(OperandNode->getValueAsDef("Type"));
|
VT = getValueType(OperandNode->getValueAsDef("Type"));
|
||||||
MadeChange |= Child->UpdateNodeType(ChildResNo, VT, TP);
|
MadeChange |= Child->UpdateNodeType(ChildResNo, VT, TP);
|
||||||
@@ -1928,7 +1948,8 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) {
|
|||||||
// def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>;
|
// def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>;
|
||||||
if (Nodes[i] == Trees[0] && Nodes[i]->isLeaf()) {
|
if (Nodes[i] == Trees[0] && Nodes[i]->isLeaf()) {
|
||||||
DefInit *DI = dynamic_cast<DefInit*>(Nodes[i]->getLeafValue());
|
DefInit *DI = dynamic_cast<DefInit*>(Nodes[i]->getLeafValue());
|
||||||
if (DI && DI->getDef()->isSubClassOf("RegisterClass"))
|
if (DI && (DI->getDef()->isSubClassOf("RegisterClass") ||
|
||||||
|
DI->getDef()->isSubClassOf("RegisterOperand")))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2211,7 +2232,8 @@ static bool HandleUse(TreePattern *I, TreePatternNode *Pat,
|
|||||||
if (Pat->getName().empty()) {
|
if (Pat->getName().empty()) {
|
||||||
if (Pat->isLeaf()) {
|
if (Pat->isLeaf()) {
|
||||||
DefInit *DI = dynamic_cast<DefInit*>(Pat->getLeafValue());
|
DefInit *DI = dynamic_cast<DefInit*>(Pat->getLeafValue());
|
||||||
if (DI && DI->getDef()->isSubClassOf("RegisterClass"))
|
if (DI && (DI->getDef()->isSubClassOf("RegisterClass") ||
|
||||||
|
DI->getDef()->isSubClassOf("RegisterOperand")))
|
||||||
I->error("Input " + DI->getDef()->getName() + " must be named!");
|
I->error("Input " + DI->getDef()->getName() + " must be named!");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -2318,6 +2340,7 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
|
|||||||
I->error("set destination should be a register!");
|
I->error("set destination should be a register!");
|
||||||
|
|
||||||
if (Val->getDef()->isSubClassOf("RegisterClass") ||
|
if (Val->getDef()->isSubClassOf("RegisterClass") ||
|
||||||
|
Val->getDef()->isSubClassOf("RegisterOperand") ||
|
||||||
Val->getDef()->isSubClassOf("PointerLikeRegClass")) {
|
Val->getDef()->isSubClassOf("PointerLikeRegClass")) {
|
||||||
if (Dest->getName().empty())
|
if (Dest->getName().empty())
|
||||||
I->error("set destination must have a name!");
|
I->error("set destination must have a name!");
|
||||||
|
@@ -69,7 +69,9 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
|
|||||||
std::string EncoderMethod;
|
std::string EncoderMethod;
|
||||||
unsigned NumOps = 1;
|
unsigned NumOps = 1;
|
||||||
DagInit *MIOpInfo = 0;
|
DagInit *MIOpInfo = 0;
|
||||||
if (Rec->isSubClassOf("Operand")) {
|
if (Rec->isSubClassOf("RegisterOperand")) {
|
||||||
|
PrintMethod = Rec->getValueAsString("PrintMethod");
|
||||||
|
} else if (Rec->isSubClassOf("Operand")) {
|
||||||
PrintMethod = Rec->getValueAsString("PrintMethod");
|
PrintMethod = Rec->getValueAsString("PrintMethod");
|
||||||
// If there is an explicit encoder method, use it.
|
// If there is an explicit encoder method, use it.
|
||||||
EncoderMethod = Rec->getValueAsString("EncoderMethod");
|
EncoderMethod = Rec->getValueAsString("EncoderMethod");
|
||||||
@@ -415,6 +417,9 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
|
|||||||
|
|
||||||
// Handle explicit registers.
|
// Handle explicit registers.
|
||||||
if (ADI && ADI->getDef()->isSubClassOf("Register")) {
|
if (ADI && ADI->getDef()->isSubClassOf("Register")) {
|
||||||
|
if (InstOpRec->isSubClassOf("RegisterOperand"))
|
||||||
|
InstOpRec = InstOpRec->getValueAsDef("RegClass");
|
||||||
|
|
||||||
if (!InstOpRec->isSubClassOf("RegisterClass"))
|
if (!InstOpRec->isSubClassOf("RegisterClass"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@@ -164,6 +164,11 @@ CodeGenRegBank &CodeGenTarget::getRegBank() const {
|
|||||||
return *RegBank;
|
return *RegBank;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CodeGenTarget::ReadRegAltNameIndices() const {
|
||||||
|
RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex");
|
||||||
|
std::sort(RegAltNameIndices.begin(), RegAltNameIndices.end(), LessRecord());
|
||||||
|
}
|
||||||
|
|
||||||
/// getRegisterByName - If there is a register with the specific AsmName,
|
/// getRegisterByName - If there is a register with the specific AsmName,
|
||||||
/// return it.
|
/// return it.
|
||||||
const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
|
const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
|
||||||
|
@@ -66,7 +66,9 @@ class CodeGenTarget {
|
|||||||
|
|
||||||
mutable DenseMap<const Record*, CodeGenInstruction*> Instructions;
|
mutable DenseMap<const Record*, CodeGenInstruction*> Instructions;
|
||||||
mutable CodeGenRegBank *RegBank;
|
mutable CodeGenRegBank *RegBank;
|
||||||
|
mutable std::vector<Record*> RegAltNameIndices;
|
||||||
mutable std::vector<MVT::SimpleValueType> LegalValueTypes;
|
mutable std::vector<MVT::SimpleValueType> LegalValueTypes;
|
||||||
|
void ReadRegAltNameIndices() const;
|
||||||
void ReadInstructions() const;
|
void ReadInstructions() const;
|
||||||
void ReadLegalValueTypes() const;
|
void ReadLegalValueTypes() const;
|
||||||
|
|
||||||
@@ -100,6 +102,11 @@ public:
|
|||||||
/// return it.
|
/// return it.
|
||||||
const CodeGenRegister *getRegisterByName(StringRef Name) const;
|
const CodeGenRegister *getRegisterByName(StringRef Name) const;
|
||||||
|
|
||||||
|
const std::vector<Record*> &getRegAltNameIndices() const {
|
||||||
|
if (RegAltNameIndices.empty()) ReadRegAltNameIndices();
|
||||||
|
return RegAltNameIndices;
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<CodeGenRegisterClass> &getRegisterClasses() const {
|
const std::vector<CodeGenRegisterClass> &getRegisterClasses() const {
|
||||||
return getRegBank().getRegClasses();
|
return getRegBank().getRegClasses();
|
||||||
}
|
}
|
||||||
|
@@ -224,6 +224,7 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
|
|||||||
Record *LeafRec = DI->getDef();
|
Record *LeafRec = DI->getDef();
|
||||||
if (// Handle register references. Nothing to do here, they always match.
|
if (// Handle register references. Nothing to do here, they always match.
|
||||||
LeafRec->isSubClassOf("RegisterClass") ||
|
LeafRec->isSubClassOf("RegisterClass") ||
|
||||||
|
LeafRec->isSubClassOf("RegisterOperand") ||
|
||||||
LeafRec->isSubClassOf("PointerLikeRegClass") ||
|
LeafRec->isSubClassOf("PointerLikeRegClass") ||
|
||||||
LeafRec->isSubClassOf("SubRegIndex") ||
|
LeafRec->isSubClassOf("SubRegIndex") ||
|
||||||
// Place holder for SRCVALUE nodes. Nothing to do here.
|
// Place holder for SRCVALUE nodes. Nothing to do here.
|
||||||
@@ -579,15 +580,16 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N,
|
|||||||
|
|
||||||
// If this is an explicit register reference, handle it.
|
// If this is an explicit register reference, handle it.
|
||||||
if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
|
if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
|
||||||
if (DI->getDef()->isSubClassOf("Register")) {
|
Record *Def = DI->getDef();
|
||||||
|
if (Def->isSubClassOf("Register")) {
|
||||||
const CodeGenRegister *Reg =
|
const CodeGenRegister *Reg =
|
||||||
CGP.getTargetInfo().getRegBank().getReg(DI->getDef());
|
CGP.getTargetInfo().getRegBank().getReg(Def);
|
||||||
AddMatcher(new EmitRegisterMatcher(Reg, N->getType(0)));
|
AddMatcher(new EmitRegisterMatcher(Reg, N->getType(0)));
|
||||||
ResultOps.push_back(NextRecordedOperandNo++);
|
ResultOps.push_back(NextRecordedOperandNo++);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DI->getDef()->getName() == "zero_reg") {
|
if (Def->getName() == "zero_reg") {
|
||||||
AddMatcher(new EmitRegisterMatcher(0, N->getType(0)));
|
AddMatcher(new EmitRegisterMatcher(0, N->getType(0)));
|
||||||
ResultOps.push_back(NextRecordedOperandNo++);
|
ResultOps.push_back(NextRecordedOperandNo++);
|
||||||
return;
|
return;
|
||||||
@@ -595,16 +597,18 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N,
|
|||||||
|
|
||||||
// Handle a reference to a register class. This is used
|
// Handle a reference to a register class. This is used
|
||||||
// in COPY_TO_SUBREG instructions.
|
// in COPY_TO_SUBREG instructions.
|
||||||
if (DI->getDef()->isSubClassOf("RegisterClass")) {
|
if (Def->isSubClassOf("RegisterOperand"))
|
||||||
std::string Value = getQualifiedName(DI->getDef()) + "RegClassID";
|
Def = Def->getValueAsDef("RegClass");
|
||||||
|
if (Def->isSubClassOf("RegisterClass")) {
|
||||||
|
std::string Value = getQualifiedName(Def) + "RegClassID";
|
||||||
AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
|
AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
|
||||||
ResultOps.push_back(NextRecordedOperandNo++);
|
ResultOps.push_back(NextRecordedOperandNo++);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle a subregister index. This is used for INSERT_SUBREG etc.
|
// Handle a subregister index. This is used for INSERT_SUBREG etc.
|
||||||
if (DI->getDef()->isSubClassOf("SubRegIndex")) {
|
if (Def->isSubClassOf("SubRegIndex")) {
|
||||||
std::string Value = getQualifiedName(DI->getDef());
|
std::string Value = getQualifiedName(Def);
|
||||||
AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
|
AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
|
||||||
ResultOps.push_back(NextRecordedOperandNo++);
|
ResultOps.push_back(NextRecordedOperandNo++);
|
||||||
return;
|
return;
|
||||||
|
@@ -248,6 +248,8 @@ struct OperandsSignature {
|
|||||||
|
|
||||||
// For now, the only other thing we accept is register operands.
|
// For now, the only other thing we accept is register operands.
|
||||||
const CodeGenRegisterClass *RC = 0;
|
const CodeGenRegisterClass *RC = 0;
|
||||||
|
if (OpLeafRec->isSubClassOf("RegisterOperand"))
|
||||||
|
OpLeafRec = OpLeafRec->getValueAsDef("RegClass");
|
||||||
if (OpLeafRec->isSubClassOf("RegisterClass"))
|
if (OpLeafRec->isSubClassOf("RegisterClass"))
|
||||||
RC = &Target.getRegisterClass(OpLeafRec);
|
RC = &Target.getRegisterClass(OpLeafRec);
|
||||||
else if (OpLeafRec->isSubClassOf("Register"))
|
else if (OpLeafRec->isSubClassOf("Register"))
|
||||||
@@ -454,6 +456,8 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
|
|||||||
std::string SubRegNo;
|
std::string SubRegNo;
|
||||||
if (Op->getName() != "EXTRACT_SUBREG") {
|
if (Op->getName() != "EXTRACT_SUBREG") {
|
||||||
Record *Op0Rec = II.Operands[0].Rec;
|
Record *Op0Rec = II.Operands[0].Rec;
|
||||||
|
if (Op0Rec->isSubClassOf("RegisterOperand"))
|
||||||
|
Op0Rec = Op0Rec->getValueAsDef("RegClass");
|
||||||
if (!Op0Rec->isSubClassOf("RegisterClass"))
|
if (!Op0Rec->isSubClassOf("RegisterClass"))
|
||||||
continue;
|
continue;
|
||||||
DstRC = &Target.getRegisterClass(Op0Rec);
|
DstRC = &Target.getRegisterClass(Op0Rec);
|
||||||
|
@@ -1305,8 +1305,10 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI,
|
|||||||
RecordRecTy *Type = dynamic_cast<RecordRecTy*>(TI->getType());
|
RecordRecTy *Type = dynamic_cast<RecordRecTy*>(TI->getType());
|
||||||
Record *TypeRecord = Type->getRecord();
|
Record *TypeRecord = Type->getRecord();
|
||||||
bool isReg = false;
|
bool isReg = false;
|
||||||
|
if (TypeRecord->isSubClassOf("RegisterOperand"))
|
||||||
|
TypeRecord = TypeRecord->getValueAsDef("RegClass");
|
||||||
if (TypeRecord->isSubClassOf("RegisterClass")) {
|
if (TypeRecord->isSubClassOf("RegisterClass")) {
|
||||||
Decoder = "Decode" + Type->getRecord()->getName() + "RegisterClass";
|
Decoder = "Decode" + TypeRecord->getName() + "RegisterClass";
|
||||||
isReg = true;
|
isReg = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -43,10 +43,10 @@ void InstrInfoEmitter::GatherItinClasses() {
|
|||||||
std::vector<Record*> DefList =
|
std::vector<Record*> DefList =
|
||||||
Records.getAllDerivedDefinitions("InstrItinClass");
|
Records.getAllDerivedDefinitions("InstrItinClass");
|
||||||
std::sort(DefList.begin(), DefList.end(), LessRecord());
|
std::sort(DefList.begin(), DefList.end(), LessRecord());
|
||||||
|
|
||||||
for (unsigned i = 0, N = DefList.size(); i < N; i++)
|
for (unsigned i = 0, N = DefList.size(); i < N; i++)
|
||||||
ItinClassMap[DefList[i]->getName()] = i;
|
ItinClassMap[DefList[i]->getName()] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) {
|
unsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) {
|
||||||
return ItinClassMap[InstRec->getValueAsDef("Itinerary")->getName()];
|
return ItinClassMap[InstRec->getValueAsDef("Itinerary")->getName()];
|
||||||
@@ -59,7 +59,7 @@ unsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) {
|
|||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
||||||
std::vector<std::string> Result;
|
std::vector<std::string> Result;
|
||||||
|
|
||||||
for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) {
|
||||||
// Handle aggregate operands and normal operands the same way by expanding
|
// Handle aggregate operands and normal operands the same way by expanding
|
||||||
// either case into a list of operands for this op.
|
// either case into a list of operands for this op.
|
||||||
@@ -70,7 +70,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
|||||||
// operand, which has a single operand, but no declared class for the
|
// operand, which has a single operand, but no declared class for the
|
||||||
// operand.
|
// operand.
|
||||||
DagInit *MIOI = Inst.Operands[i].MIOperandInfo;
|
DagInit *MIOI = Inst.Operands[i].MIOperandInfo;
|
||||||
|
|
||||||
if (!MIOI || MIOI->getNumArgs() == 0) {
|
if (!MIOI || MIOI->getNumArgs() == 0) {
|
||||||
// Single, anonymous, operand.
|
// Single, anonymous, operand.
|
||||||
OperandList.push_back(Inst.Operands[i]);
|
OperandList.push_back(Inst.Operands[i]);
|
||||||
@@ -86,7 +86,9 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
|||||||
for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {
|
for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {
|
||||||
Record *OpR = OperandList[j].Rec;
|
Record *OpR = OperandList[j].Rec;
|
||||||
std::string Res;
|
std::string Res;
|
||||||
|
|
||||||
|
if (OpR->isSubClassOf("RegisterOperand"))
|
||||||
|
OpR = OpR->getValueAsDef("RegClass");
|
||||||
if (OpR->isSubClassOf("RegisterClass"))
|
if (OpR->isSubClassOf("RegisterClass"))
|
||||||
Res += getQualifiedName(OpR) + "RegClassID, ";
|
Res += getQualifiedName(OpR) + "RegClassID, ";
|
||||||
else if (OpR->isSubClassOf("PointerLikeRegClass"))
|
else if (OpR->isSubClassOf("PointerLikeRegClass"))
|
||||||
@@ -94,10 +96,10 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
|||||||
else
|
else
|
||||||
// -1 means the operand does not have a fixed register class.
|
// -1 means the operand does not have a fixed register class.
|
||||||
Res += "-1, ";
|
Res += "-1, ";
|
||||||
|
|
||||||
// Fill in applicable flags.
|
// Fill in applicable flags.
|
||||||
Res += "0";
|
Res += "0";
|
||||||
|
|
||||||
// Ptr value whose register class is resolved via callback.
|
// Ptr value whose register class is resolved via callback.
|
||||||
if (OpR->isSubClassOf("PointerLikeRegClass"))
|
if (OpR->isSubClassOf("PointerLikeRegClass"))
|
||||||
Res += "|(1<<TOI::LookupPtrRegClass)";
|
Res += "|(1<<TOI::LookupPtrRegClass)";
|
||||||
@@ -106,7 +108,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
|||||||
// was of type PredicateOperand.
|
// was of type PredicateOperand.
|
||||||
if (Inst.Operands[i].Rec->isSubClassOf("PredicateOperand"))
|
if (Inst.Operands[i].Rec->isSubClassOf("PredicateOperand"))
|
||||||
Res += "|(1<<TOI::Predicate)";
|
Res += "|(1<<TOI::Predicate)";
|
||||||
|
|
||||||
// Optional def operands. Check to see if the original unexpanded operand
|
// Optional def operands. Check to see if the original unexpanded operand
|
||||||
// was of type OptionalDefOperand.
|
// was of type OptionalDefOperand.
|
||||||
if (Inst.Operands[i].Rec->isSubClassOf("OptionalDefOperand"))
|
if (Inst.Operands[i].Rec->isSubClassOf("OptionalDefOperand"))
|
||||||
@@ -114,7 +116,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
|||||||
|
|
||||||
// Fill in constraint info.
|
// Fill in constraint info.
|
||||||
Res += ", ";
|
Res += ", ";
|
||||||
|
|
||||||
const CGIOperandList::ConstraintInfo &Constraint =
|
const CGIOperandList::ConstraintInfo &Constraint =
|
||||||
Inst.Operands[i].Constraints[j];
|
Inst.Operands[i].Constraints[j];
|
||||||
if (Constraint.isNone())
|
if (Constraint.isNone())
|
||||||
@@ -126,7 +128,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
|||||||
Res += "((" + utostr(Constraint.getTiedOperand()) +
|
Res += "((" + utostr(Constraint.getTiedOperand()) +
|
||||||
" << 16) | (1 << TOI::TIED_TO))";
|
" << 16) | (1 << TOI::TIED_TO))";
|
||||||
}
|
}
|
||||||
|
|
||||||
Result.push_back(Res);
|
Result.push_back(Res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,12 +136,12 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
|
void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
|
||||||
OperandInfoMapTy &OperandInfoIDs) {
|
OperandInfoMapTy &OperandInfoIDs) {
|
||||||
// ID #0 is for no operand info.
|
// ID #0 is for no operand info.
|
||||||
unsigned OperandListNum = 0;
|
unsigned OperandListNum = 0;
|
||||||
OperandInfoIDs[std::vector<std::string>()] = ++OperandListNum;
|
OperandInfoIDs[std::vector<std::string>()] = ++OperandListNum;
|
||||||
|
|
||||||
OS << "\n";
|
OS << "\n";
|
||||||
const CodeGenTarget &Target = CDP.getTargetInfo();
|
const CodeGenTarget &Target = CDP.getTargetInfo();
|
||||||
for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
|
for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
|
||||||
@@ -147,7 +149,7 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
|
|||||||
std::vector<std::string> OperandInfo = GetOperandInfo(**II);
|
std::vector<std::string> OperandInfo = GetOperandInfo(**II);
|
||||||
unsigned &N = OperandInfoIDs[OperandInfo];
|
unsigned &N = OperandInfoIDs[OperandInfo];
|
||||||
if (N != 0) continue;
|
if (N != 0) continue;
|
||||||
|
|
||||||
N = ++OperandListNum;
|
N = ++OperandListNum;
|
||||||
OS << "static const TargetOperandInfo OperandInfo" << N << "[] = { ";
|
OS << "static const TargetOperandInfo OperandInfo" << N << "[] = { ";
|
||||||
for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i)
|
for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i)
|
||||||
@@ -205,7 +207,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
|
|||||||
std::map<std::vector<Record*>, unsigned> EmittedBarriers;
|
std::map<std::vector<Record*>, unsigned> EmittedBarriers;
|
||||||
unsigned BarrierNumber = 0;
|
unsigned BarrierNumber = 0;
|
||||||
std::map<Record*, unsigned> BarriersMap;
|
std::map<Record*, unsigned> BarriersMap;
|
||||||
|
|
||||||
// Emit all of the instruction's implicit uses and defs.
|
// Emit all of the instruction's implicit uses and defs.
|
||||||
for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
|
for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
|
||||||
E = Target.inst_end(); II != E; ++II) {
|
E = Target.inst_end(); II != E; ++II) {
|
||||||
@@ -231,10 +233,10 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OperandInfoMapTy OperandInfoIDs;
|
OperandInfoMapTy OperandInfoIDs;
|
||||||
|
|
||||||
// Emit all of the operand info records.
|
// Emit all of the operand info records.
|
||||||
EmitOperandInfo(OS, OperandInfoIDs);
|
EmitOperandInfo(OS, OperandInfoIDs);
|
||||||
|
|
||||||
// Emit all of the TargetInstrDesc records in their ENUM ordering.
|
// Emit all of the TargetInstrDesc records in their ENUM ordering.
|
||||||
//
|
//
|
||||||
OS << "\nstatic const TargetInstrDesc " << TargetName
|
OS << "\nstatic const TargetInstrDesc " << TargetName
|
||||||
|
@@ -1443,6 +1443,25 @@ Record::getValueAsListOfInts(StringRef FieldName) const {
|
|||||||
return Ints;
|
return Ints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getValueAsListOfStrings - This method looks up the specified field and
|
||||||
|
/// returns its value as a vector of strings, throwing an exception if the
|
||||||
|
/// field does not exist or if the value is not the right type.
|
||||||
|
///
|
||||||
|
std::vector<std::string>
|
||||||
|
Record::getValueAsListOfStrings(StringRef FieldName) const {
|
||||||
|
ListInit *List = getValueAsListInit(FieldName);
|
||||||
|
std::vector<std::string> Strings;
|
||||||
|
for (unsigned i = 0; i < List->getSize(); i++) {
|
||||||
|
if (StringInit *II = dynamic_cast<StringInit*>(List->getElement(i))) {
|
||||||
|
Strings.push_back(II->getValue());
|
||||||
|
} else {
|
||||||
|
throw "Record `" + getName() + "', field `" + FieldName.str() +
|
||||||
|
"' does not have a list of strings initializer!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Strings;
|
||||||
|
}
|
||||||
|
|
||||||
/// getValueAsDef - This method looks up the specified field and returns its
|
/// getValueAsDef - This method looks up the specified field and returns its
|
||||||
/// value as a Record, throwing an exception if the field does not exist or if
|
/// value as a Record, throwing an exception if the field does not exist or if
|
||||||
/// the value is not the right type.
|
/// the value is not the right type.
|
||||||
|
@@ -1368,6 +1368,12 @@ public:
|
|||||||
///
|
///
|
||||||
std::vector<int64_t> getValueAsListOfInts(StringRef FieldName) const;
|
std::vector<int64_t> getValueAsListOfInts(StringRef FieldName) const;
|
||||||
|
|
||||||
|
/// getValueAsListOfStrings - This method looks up the specified field and
|
||||||
|
/// returns its value as a vector of strings, throwing an exception if the
|
||||||
|
/// field does not exist or if the value is not the right type.
|
||||||
|
///
|
||||||
|
std::vector<std::string> getValueAsListOfStrings(StringRef FieldName) const;
|
||||||
|
|
||||||
/// getValueAsDef - This method looks up the specified field and returns its
|
/// getValueAsDef - This method looks up the specified field and returns its
|
||||||
/// value as a Record, throwing an exception if the field does not exist or if
|
/// value as a Record, throwing an exception if the field does not exist or if
|
||||||
/// the value is not the right type.
|
/// the value is not the right type.
|
||||||
|
@@ -112,6 +112,18 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
|||||||
OS << "0 };\n";
|
OS << "0 };\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<Record*> RegAltNameIndices = Target.getRegAltNameIndices();
|
||||||
|
// If the only definition is the default NoRegAltName, we don't need to
|
||||||
|
// emit anything.
|
||||||
|
if (RegAltNameIndices.size() > 1) {
|
||||||
|
OS << "\n// Register alternate name indices\n";
|
||||||
|
OS << "enum {\n";
|
||||||
|
for (unsigned i = 0, e = RegAltNameIndices.size(); i != e; ++i)
|
||||||
|
OS << " " << RegAltNameIndices[i]->getName() << ",\t// " << i << "\n";
|
||||||
|
OS << " NUM_TARGET_REG_ALT_NAMES = " << RegAltNameIndices.size() << "\n";
|
||||||
|
OS << "};\n";
|
||||||
|
}
|
||||||
|
|
||||||
// Emit the empty sub-registers list
|
// Emit the empty sub-registers list
|
||||||
OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n";
|
OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n";
|
||||||
// Loop over all of the registers which have sub-registers, emitting the
|
// Loop over all of the registers which have sub-registers, emitting the
|
||||||
|
Reference in New Issue
Block a user