mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01: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. llvm-svn: 133940
This commit is contained in:
parent
1ae2ca427b
commit
c1dcf312d1
@ -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
Block a user