forked from OSchip/llvm-project
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. llvm-svn: 133940
This commit is contained in:
parent
0ceb5473a3
commit
a84be6c96b
|
@ -26,11 +26,19 @@ class SubRegIndex {
|
|||
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
|
||||
// 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 AsmName = n;
|
||||
list<string> AltNames = altNames;
|
||||
|
||||
// Aliases - A list of registers that this register overlaps with. A read or
|
||||
// modification of this register can potentially read or modify the aliased
|
||||
|
@ -48,6 +56,10 @@ class Register<string n> {
|
|||
// SubRegs.
|
||||
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
|
||||
// a register in SubRegs and are not inherited. The following formats are
|
||||
// supported:
|
||||
|
@ -92,7 +104,7 @@ class RegisterWithSubRegs<string n, list<Register> subregs> : Register<n> {
|
|||
// registers by register allocators.
|
||||
//
|
||||
class RegisterClass<string namespace, list<ValueType> regTypes, int alignment,
|
||||
dag regList> {
|
||||
dag regList, RegAltNameIndex idx = NoRegAltName> {
|
||||
string Namespace = namespace;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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
|
||||
// dags: (RegClass SubRegIndex, SubRegindex, ...)
|
||||
list<dag> SubRegClasses = [];
|
||||
|
@ -466,6 +483,24 @@ class Operand<ValueType ty> {
|
|||
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 i8imm : Operand<i8>;
|
||||
def i16imm : Operand<i16>;
|
||||
|
|
|
@ -871,6 +871,31 @@ AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI,
|
|||
if (SubOpIdx != -1)
|
||||
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 (ClassInfo *CI = RegisterClassClasses[Rec])
|
||||
return CI;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "CodeGenTarget.h"
|
||||
#include "Record.h"
|
||||
#include "StringToOffsetTable.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include <algorithm>
|
||||
|
@ -458,6 +459,58 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
|||
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) {
|
||||
CodeGenTarget Target(Records);
|
||||
|
@ -465,40 +518,48 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
|
|||
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
|
||||
const std::vector<CodeGenRegister*> &Registers =
|
||||
Target.getRegBank().getRegisters();
|
||||
std::vector<Record*> AltNameIndices = Target.getRegAltNameIndices();
|
||||
bool hasAltNames = AltNameIndices.size() > 1;
|
||||
|
||||
StringToOffsetTable StringTable;
|
||||
O <<
|
||||
"\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
|
||||
"/// from the register set description. This returns the assembler name\n"
|
||||
"/// for the specified register.\n"
|
||||
"const char *" << Target.getName() << ClassName
|
||||
<< "::getRegisterName(unsigned RegNo) {\n"
|
||||
<< " assert(RegNo && RegNo < " << (Registers.size()+1)
|
||||
<< " && \"Invalid register number!\");\n"
|
||||
<< "\n"
|
||||
<< " static const unsigned RegAsmOffset[] = {";
|
||||
for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
|
||||
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"
|
||||
"const char *" << Target.getName() << ClassName << "::";
|
||||
if (hasAltNames)
|
||||
O << "\ngetRegisterName(unsigned RegNo, unsigned AltIdx) {\n";
|
||||
else
|
||||
O << "getRegisterName(unsigned RegNo) {\n";
|
||||
O << " assert(RegNo && RegNo < " << (Registers.size()+1)
|
||||
<< " && \"Invalid register number!\");\n"
|
||||
<< "\n";
|
||||
|
||||
O << " const char *AsmStrs =\n";
|
||||
StringTable.EmitString(O);
|
||||
O << ";\n";
|
||||
if (hasAltNames) {
|
||||
for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i)
|
||||
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";
|
||||
}
|
||||
|
||||
|
@ -936,6 +997,9 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
|
|||
const Record *Rec = RO.getRecord();
|
||||
StringRef ROName = RO.getName();
|
||||
|
||||
|
||||
if (Rec->isSubClassOf("RegisterOperand"))
|
||||
Rec = Rec->getValueAsDef("RegClass");
|
||||
if (Rec->isSubClassOf("RegisterClass")) {
|
||||
Cond = std::string("MI->getOperand(")+llvm::utostr(i)+").isReg()";
|
||||
IAP->addCond(Cond);
|
||||
|
|
|
@ -1242,6 +1242,16 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
|
|||
///
|
||||
static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo,
|
||||
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.
|
||||
if (R->isSubClassOf("RegisterClass")) {
|
||||
assert(ResNo == 0 && "Regclass ref only has one result!");
|
||||
|
@ -1524,6 +1534,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
|
|||
|
||||
if (ResultNode->isSubClassOf("PointerLikeRegClass")) {
|
||||
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") {
|
||||
// Nothing to do.
|
||||
} else {
|
||||
|
@ -1582,6 +1597,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
|
|||
const CodeGenRegisterClass &RC =
|
||||
CDP.getTargetInfo().getRegisterClass(OperandNode);
|
||||
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")) {
|
||||
VT = getValueType(OperandNode->getValueAsDef("Type"));
|
||||
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)>;
|
||||
if (Nodes[i] == Trees[0] && Nodes[i]->isLeaf()) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2211,7 +2232,8 @@ static bool HandleUse(TreePattern *I, TreePatternNode *Pat,
|
|||
if (Pat->getName().empty()) {
|
||||
if (Pat->isLeaf()) {
|
||||
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!");
|
||||
}
|
||||
return false;
|
||||
|
@ -2318,6 +2340,7 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
|
|||
I->error("set destination should be a register!");
|
||||
|
||||
if (Val->getDef()->isSubClassOf("RegisterClass") ||
|
||||
Val->getDef()->isSubClassOf("RegisterOperand") ||
|
||||
Val->getDef()->isSubClassOf("PointerLikeRegClass")) {
|
||||
if (Dest->getName().empty())
|
||||
I->error("set destination must have a name!");
|
||||
|
|
|
@ -69,7 +69,9 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
|
|||
std::string EncoderMethod;
|
||||
unsigned NumOps = 1;
|
||||
DagInit *MIOpInfo = 0;
|
||||
if (Rec->isSubClassOf("Operand")) {
|
||||
if (Rec->isSubClassOf("RegisterOperand")) {
|
||||
PrintMethod = Rec->getValueAsString("PrintMethod");
|
||||
} else if (Rec->isSubClassOf("Operand")) {
|
||||
PrintMethod = Rec->getValueAsString("PrintMethod");
|
||||
// If there is an explicit encoder method, use it.
|
||||
EncoderMethod = Rec->getValueAsString("EncoderMethod");
|
||||
|
@ -415,6 +417,9 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
|
|||
|
||||
// Handle explicit registers.
|
||||
if (ADI && ADI->getDef()->isSubClassOf("Register")) {
|
||||
if (InstOpRec->isSubClassOf("RegisterOperand"))
|
||||
InstOpRec = InstOpRec->getValueAsDef("RegClass");
|
||||
|
||||
if (!InstOpRec->isSubClassOf("RegisterClass"))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -164,6 +164,11 @@ CodeGenRegBank &CodeGenTarget::getRegBank() const {
|
|||
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,
|
||||
/// return it.
|
||||
const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
|
||||
|
|
|
@ -66,7 +66,9 @@ class CodeGenTarget {
|
|||
|
||||
mutable DenseMap<const Record*, CodeGenInstruction*> Instructions;
|
||||
mutable CodeGenRegBank *RegBank;
|
||||
mutable std::vector<Record*> RegAltNameIndices;
|
||||
mutable std::vector<MVT::SimpleValueType> LegalValueTypes;
|
||||
void ReadRegAltNameIndices() const;
|
||||
void ReadInstructions() const;
|
||||
void ReadLegalValueTypes() const;
|
||||
|
||||
|
@ -100,6 +102,11 @@ public:
|
|||
/// return it.
|
||||
const CodeGenRegister *getRegisterByName(StringRef Name) const;
|
||||
|
||||
const std::vector<Record*> &getRegAltNameIndices() const {
|
||||
if (RegAltNameIndices.empty()) ReadRegAltNameIndices();
|
||||
return RegAltNameIndices;
|
||||
}
|
||||
|
||||
const std::vector<CodeGenRegisterClass> &getRegisterClasses() const {
|
||||
return getRegBank().getRegClasses();
|
||||
}
|
||||
|
|
|
@ -224,6 +224,7 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
|
|||
Record *LeafRec = DI->getDef();
|
||||
if (// Handle register references. Nothing to do here, they always match.
|
||||
LeafRec->isSubClassOf("RegisterClass") ||
|
||||
LeafRec->isSubClassOf("RegisterOperand") ||
|
||||
LeafRec->isSubClassOf("PointerLikeRegClass") ||
|
||||
LeafRec->isSubClassOf("SubRegIndex") ||
|
||||
// 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 (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
|
||||
if (DI->getDef()->isSubClassOf("Register")) {
|
||||
Record *Def = DI->getDef();
|
||||
if (Def->isSubClassOf("Register")) {
|
||||
const CodeGenRegister *Reg =
|
||||
CGP.getTargetInfo().getRegBank().getReg(DI->getDef());
|
||||
CGP.getTargetInfo().getRegBank().getReg(Def);
|
||||
AddMatcher(new EmitRegisterMatcher(Reg, N->getType(0)));
|
||||
ResultOps.push_back(NextRecordedOperandNo++);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DI->getDef()->getName() == "zero_reg") {
|
||||
if (Def->getName() == "zero_reg") {
|
||||
AddMatcher(new EmitRegisterMatcher(0, N->getType(0)));
|
||||
ResultOps.push_back(NextRecordedOperandNo++);
|
||||
return;
|
||||
|
@ -595,16 +597,18 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N,
|
|||
|
||||
// Handle a reference to a register class. This is used
|
||||
// in COPY_TO_SUBREG instructions.
|
||||
if (DI->getDef()->isSubClassOf("RegisterClass")) {
|
||||
std::string Value = getQualifiedName(DI->getDef()) + "RegClassID";
|
||||
if (Def->isSubClassOf("RegisterOperand"))
|
||||
Def = Def->getValueAsDef("RegClass");
|
||||
if (Def->isSubClassOf("RegisterClass")) {
|
||||
std::string Value = getQualifiedName(Def) + "RegClassID";
|
||||
AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
|
||||
ResultOps.push_back(NextRecordedOperandNo++);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle a subregister index. This is used for INSERT_SUBREG etc.
|
||||
if (DI->getDef()->isSubClassOf("SubRegIndex")) {
|
||||
std::string Value = getQualifiedName(DI->getDef());
|
||||
if (Def->isSubClassOf("SubRegIndex")) {
|
||||
std::string Value = getQualifiedName(Def);
|
||||
AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
|
||||
ResultOps.push_back(NextRecordedOperandNo++);
|
||||
return;
|
||||
|
|
|
@ -248,6 +248,8 @@ struct OperandsSignature {
|
|||
|
||||
// For now, the only other thing we accept is register operands.
|
||||
const CodeGenRegisterClass *RC = 0;
|
||||
if (OpLeafRec->isSubClassOf("RegisterOperand"))
|
||||
OpLeafRec = OpLeafRec->getValueAsDef("RegClass");
|
||||
if (OpLeafRec->isSubClassOf("RegisterClass"))
|
||||
RC = &Target.getRegisterClass(OpLeafRec);
|
||||
else if (OpLeafRec->isSubClassOf("Register"))
|
||||
|
@ -454,6 +456,8 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
|
|||
std::string SubRegNo;
|
||||
if (Op->getName() != "EXTRACT_SUBREG") {
|
||||
Record *Op0Rec = II.Operands[0].Rec;
|
||||
if (Op0Rec->isSubClassOf("RegisterOperand"))
|
||||
Op0Rec = Op0Rec->getValueAsDef("RegClass");
|
||||
if (!Op0Rec->isSubClassOf("RegisterClass"))
|
||||
continue;
|
||||
DstRC = &Target.getRegisterClass(Op0Rec);
|
||||
|
|
|
@ -1305,8 +1305,10 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI,
|
|||
RecordRecTy *Type = dynamic_cast<RecordRecTy*>(TI->getType());
|
||||
Record *TypeRecord = Type->getRecord();
|
||||
bool isReg = false;
|
||||
if (TypeRecord->isSubClassOf("RegisterOperand"))
|
||||
TypeRecord = TypeRecord->getValueAsDef("RegClass");
|
||||
if (TypeRecord->isSubClassOf("RegisterClass")) {
|
||||
Decoder = "Decode" + Type->getRecord()->getName() + "RegisterClass";
|
||||
Decoder = "Decode" + TypeRecord->getName() + "RegisterClass";
|
||||
isReg = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,10 +43,10 @@ void InstrInfoEmitter::GatherItinClasses() {
|
|||
std::vector<Record*> DefList =
|
||||
Records.getAllDerivedDefinitions("InstrItinClass");
|
||||
std::sort(DefList.begin(), DefList.end(), LessRecord());
|
||||
|
||||
|
||||
for (unsigned i = 0, N = DefList.size(); i < N; i++)
|
||||
ItinClassMap[DefList[i]->getName()] = i;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) {
|
||||
return ItinClassMap[InstRec->getValueAsDef("Itinerary")->getName()];
|
||||
|
@ -59,7 +59,7 @@ unsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) {
|
|||
std::vector<std::string>
|
||||
InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
||||
std::vector<std::string> Result;
|
||||
|
||||
|
||||
for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) {
|
||||
// Handle aggregate operands and normal operands the same way by expanding
|
||||
// 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.
|
||||
DagInit *MIOI = Inst.Operands[i].MIOperandInfo;
|
||||
|
||||
|
||||
if (!MIOI || MIOI->getNumArgs() == 0) {
|
||||
// Single, anonymous, operand.
|
||||
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) {
|
||||
Record *OpR = OperandList[j].Rec;
|
||||
std::string Res;
|
||||
|
||||
|
||||
if (OpR->isSubClassOf("RegisterOperand"))
|
||||
OpR = OpR->getValueAsDef("RegClass");
|
||||
if (OpR->isSubClassOf("RegisterClass"))
|
||||
Res += getQualifiedName(OpR) + "RegClassID, ";
|
||||
else if (OpR->isSubClassOf("PointerLikeRegClass"))
|
||||
|
@ -94,10 +96,10 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
|||
else
|
||||
// -1 means the operand does not have a fixed register class.
|
||||
Res += "-1, ";
|
||||
|
||||
|
||||
// Fill in applicable flags.
|
||||
Res += "0";
|
||||
|
||||
|
||||
// Ptr value whose register class is resolved via callback.
|
||||
if (OpR->isSubClassOf("PointerLikeRegClass"))
|
||||
Res += "|(1<<TOI::LookupPtrRegClass)";
|
||||
|
@ -106,7 +108,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
|||
// was of type PredicateOperand.
|
||||
if (Inst.Operands[i].Rec->isSubClassOf("PredicateOperand"))
|
||||
Res += "|(1<<TOI::Predicate)";
|
||||
|
||||
|
||||
// Optional def operands. Check to see if the original unexpanded operand
|
||||
// was of type OptionalDefOperand.
|
||||
if (Inst.Operands[i].Rec->isSubClassOf("OptionalDefOperand"))
|
||||
|
@ -114,7 +116,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
|||
|
||||
// Fill in constraint info.
|
||||
Res += ", ";
|
||||
|
||||
|
||||
const CGIOperandList::ConstraintInfo &Constraint =
|
||||
Inst.Operands[i].Constraints[j];
|
||||
if (Constraint.isNone())
|
||||
|
@ -126,7 +128,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
|||
Res += "((" + utostr(Constraint.getTiedOperand()) +
|
||||
" << 16) | (1 << TOI::TIED_TO))";
|
||||
}
|
||||
|
||||
|
||||
Result.push_back(Res);
|
||||
}
|
||||
}
|
||||
|
@ -134,12 +136,12 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
|||
return Result;
|
||||
}
|
||||
|
||||
void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
|
||||
void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
|
||||
OperandInfoMapTy &OperandInfoIDs) {
|
||||
// ID #0 is for no operand info.
|
||||
unsigned OperandListNum = 0;
|
||||
OperandInfoIDs[std::vector<std::string>()] = ++OperandListNum;
|
||||
|
||||
|
||||
OS << "\n";
|
||||
const CodeGenTarget &Target = CDP.getTargetInfo();
|
||||
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);
|
||||
unsigned &N = OperandInfoIDs[OperandInfo];
|
||||
if (N != 0) continue;
|
||||
|
||||
|
||||
N = ++OperandListNum;
|
||||
OS << "static const TargetOperandInfo OperandInfo" << N << "[] = { ";
|
||||
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;
|
||||
unsigned BarrierNumber = 0;
|
||||
std::map<Record*, unsigned> BarriersMap;
|
||||
|
||||
|
||||
// Emit all of the instruction's implicit uses and defs.
|
||||
for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
|
||||
E = Target.inst_end(); II != E; ++II) {
|
||||
|
@ -231,10 +233,10 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
|
|||
}
|
||||
|
||||
OperandInfoMapTy OperandInfoIDs;
|
||||
|
||||
|
||||
// Emit all of the operand info records.
|
||||
EmitOperandInfo(OS, OperandInfoIDs);
|
||||
|
||||
|
||||
// Emit all of the TargetInstrDesc records in their ENUM ordering.
|
||||
//
|
||||
OS << "\nstatic const TargetInstrDesc " << TargetName
|
||||
|
|
|
@ -1443,6 +1443,25 @@ Record::getValueAsListOfInts(StringRef FieldName) const {
|
|||
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
|
||||
/// value as a Record, throwing an exception if the field does not exist or if
|
||||
/// the value is not the right type.
|
||||
|
|
|
@ -1368,6 +1368,12 @@ public:
|
|||
///
|
||||
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
|
||||
/// value as a Record, throwing an exception if the field does not exist or if
|
||||
/// the value is not the right type.
|
||||
|
|
|
@ -112,6 +112,18 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
|||
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
|
||||
OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n";
|
||||
// Loop over all of the registers which have sub-registers, emitting the
|
||||
|
|
Loading…
Reference in New Issue