forked from OSchip/llvm-project
llvm-mc/AsmParser: Define match classes in the .td file.
-2 FIXMEs. llvm-svn: 78523
This commit is contained in:
parent
3239f020eb
commit
c32aa060bd
|
@ -286,6 +286,17 @@ class Operand<ValueType ty> {
|
||||||
string PrintMethod = "printOperand";
|
string PrintMethod = "printOperand";
|
||||||
string AsmOperandLowerMethod = ?;
|
string AsmOperandLowerMethod = ?;
|
||||||
dag MIOperandInfo = (ops);
|
dag MIOperandInfo = (ops);
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
string ParserMatchClass = "Imm";
|
||||||
|
|
||||||
|
// ParserMatchSuperClass - The enclosing super class for this operand (if
|
||||||
|
// any). This operand *must* be a subset of the valid operands for the super
|
||||||
|
// class; i.e., the match predicate for this super class must return true
|
||||||
|
// for all instances of this class.
|
||||||
|
string ParserMatchSuperClass = ?;
|
||||||
}
|
}
|
||||||
|
|
||||||
def i1imm : Operand<i1>;
|
def i1imm : Operand<i1>;
|
||||||
|
|
|
@ -173,6 +173,7 @@ def ptr_rc_nosp : PointerLikeRegClass<1>;
|
||||||
class X86MemOperand<string printMethod> : Operand<iPTR> {
|
class X86MemOperand<string printMethod> : Operand<iPTR> {
|
||||||
let PrintMethod = printMethod;
|
let PrintMethod = printMethod;
|
||||||
let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, i8imm);
|
let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, i8imm);
|
||||||
|
let ParserMatchClass = "Mem";
|
||||||
}
|
}
|
||||||
|
|
||||||
def i8mem : X86MemOperand<"printi8mem">;
|
def i8mem : X86MemOperand<"printi8mem">;
|
||||||
|
@ -192,11 +193,13 @@ def f256mem : X86MemOperand<"printf256mem">;
|
||||||
def i8mem_NOREX : Operand<i64> {
|
def i8mem_NOREX : Operand<i64> {
|
||||||
let PrintMethod = "printi8mem";
|
let PrintMethod = "printi8mem";
|
||||||
let MIOperandInfo = (ops GR64_NOREX, i8imm, GR64_NOREX_NOSP, i32imm, i8imm);
|
let MIOperandInfo = (ops GR64_NOREX, i8imm, GR64_NOREX_NOSP, i32imm, i8imm);
|
||||||
|
let ParserMatchClass = "Mem";
|
||||||
}
|
}
|
||||||
|
|
||||||
def lea32mem : Operand<i32> {
|
def lea32mem : Operand<i32> {
|
||||||
let PrintMethod = "printlea32mem";
|
let PrintMethod = "printlea32mem";
|
||||||
let MIOperandInfo = (ops GR32, i8imm, GR32_NOSP, i32imm);
|
let MIOperandInfo = (ops GR32, i8imm, GR32_NOSP, i32imm);
|
||||||
|
let ParserMatchClass = "Mem";
|
||||||
}
|
}
|
||||||
|
|
||||||
def SSECC : Operand<i8> {
|
def SSECC : Operand<i8> {
|
||||||
|
|
|
@ -278,6 +278,7 @@ namespace {
|
||||||
/// class of operands which can be matched.
|
/// class of operands which can be matched.
|
||||||
struct ClassInfo {
|
struct ClassInfo {
|
||||||
enum ClassInfoKind {
|
enum ClassInfoKind {
|
||||||
|
Invalid = 0, ///< Invalid kind, for use as a sentinel value.
|
||||||
Token, ///< The class for a particular token.
|
Token, ///< The class for a particular token.
|
||||||
Register, ///< A register class.
|
Register, ///< A register class.
|
||||||
UserClass0 ///< The (first) user defined class, subsequent user defined
|
UserClass0 ///< The (first) user defined class, subsequent user defined
|
||||||
|
@ -288,9 +289,12 @@ struct ClassInfo {
|
||||||
/// N) for the Nth user defined class.
|
/// N) for the Nth user defined class.
|
||||||
unsigned Kind;
|
unsigned Kind;
|
||||||
|
|
||||||
/// Name - The class name, suitable for use as an enum.
|
/// Name - The full class name, suitable for use in an enum.
|
||||||
std::string Name;
|
std::string Name;
|
||||||
|
|
||||||
|
/// ClassName - The unadorned generic name for this class (e.g., Token).
|
||||||
|
std::string ClassName;
|
||||||
|
|
||||||
/// ValueName - The name of the value this class represents; for a token this
|
/// ValueName - The name of the value this class represents; for a token this
|
||||||
/// is the literal token string, for an operand it is the TableGen class (or
|
/// is the literal token string, for an operand it is the TableGen class (or
|
||||||
/// empty if this is a derived class).
|
/// empty if this is a derived class).
|
||||||
|
@ -311,6 +315,8 @@ struct ClassInfo {
|
||||||
return Kind < RHS.Kind;
|
return Kind < RHS.Kind;
|
||||||
|
|
||||||
switch (Kind) {
|
switch (Kind) {
|
||||||
|
case Invalid:
|
||||||
|
assert(0 && "Invalid kind!");
|
||||||
case Token:
|
case Token:
|
||||||
// Tokens are always comparable.
|
// Tokens are always comparable.
|
||||||
//
|
//
|
||||||
|
@ -412,10 +418,17 @@ private:
|
||||||
/// constructed.
|
/// constructed.
|
||||||
std::map<std::string, ClassInfo*> OperandClasses;
|
std::map<std::string, ClassInfo*> OperandClasses;
|
||||||
|
|
||||||
|
/// Map of user class names to kind value.
|
||||||
|
std::map<std::string, unsigned> UserClasses;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// getTokenClass - Lookup or create the class for the given token.
|
/// getTokenClass - Lookup or create the class for the given token.
|
||||||
ClassInfo *getTokenClass(const StringRef &Token);
|
ClassInfo *getTokenClass(const StringRef &Token);
|
||||||
|
|
||||||
|
/// getUserClassKind - Lookup or create the kind value for the given class
|
||||||
|
/// name.
|
||||||
|
unsigned getUserClassKind(const StringRef &Name);
|
||||||
|
|
||||||
/// getOperandClass - Lookup or create the class for the given operand.
|
/// getOperandClass - Lookup or create the class for the given operand.
|
||||||
ClassInfo *getOperandClass(const StringRef &Token,
|
ClassInfo *getOperandClass(const StringRef &Token,
|
||||||
const CodeGenInstruction::OperandInfo &OI);
|
const CodeGenInstruction::OperandInfo &OI);
|
||||||
|
@ -439,7 +452,7 @@ void InstructionInfo::dump() {
|
||||||
|
|
||||||
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
|
||||||
Operand &Op = Operands[i];
|
Operand &Op = Operands[i];
|
||||||
errs() << " op[" << i << "] = ";
|
errs() << " op[" << i << "] = " << Op.Class->ClassName << " - ";
|
||||||
if (Op.Class->Kind == ClassInfo::Token) {
|
if (Op.Class->Kind == ClassInfo::Token) {
|
||||||
errs() << '\"' << Tokens[i] << "\"\n";
|
errs() << '\"' << Tokens[i] << "\"\n";
|
||||||
continue;
|
continue;
|
||||||
|
@ -478,6 +491,7 @@ ClassInfo *AsmMatcherInfo::getTokenClass(const StringRef &Token) {
|
||||||
if (!Entry) {
|
if (!Entry) {
|
||||||
Entry = new ClassInfo();
|
Entry = new ClassInfo();
|
||||||
Entry->Kind = ClassInfo::Token;
|
Entry->Kind = ClassInfo::Token;
|
||||||
|
Entry->ClassName = "Token";
|
||||||
Entry->Name = "MCK_" + getEnumNameForToken(Token);
|
Entry->Name = "MCK_" + getEnumNameForToken(Token);
|
||||||
Entry->ValueName = Token;
|
Entry->ValueName = Token;
|
||||||
Entry->PredicateMethod = "<invalid>";
|
Entry->PredicateMethod = "<invalid>";
|
||||||
|
@ -488,28 +502,28 @@ ClassInfo *AsmMatcherInfo::getTokenClass(const StringRef &Token) {
|
||||||
return Entry;
|
return Entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned AsmMatcherInfo::getUserClassKind(const StringRef &Name) {
|
||||||
|
unsigned &Entry = UserClasses[Name];
|
||||||
|
|
||||||
|
if (!Entry)
|
||||||
|
Entry = ClassInfo::UserClass0 + UserClasses.size() - 1;
|
||||||
|
|
||||||
|
return Entry;
|
||||||
|
}
|
||||||
|
|
||||||
ClassInfo *
|
ClassInfo *
|
||||||
AsmMatcherInfo::getOperandClass(const StringRef &Token,
|
AsmMatcherInfo::getOperandClass(const StringRef &Token,
|
||||||
const CodeGenInstruction::OperandInfo &OI) {
|
const CodeGenInstruction::OperandInfo &OI) {
|
||||||
std::string ClassName;
|
std::string ClassName;
|
||||||
if (OI.Rec->isSubClassOf("RegisterClass")) {
|
if (OI.Rec->isSubClassOf("RegisterClass")) {
|
||||||
ClassName = "Reg";
|
ClassName = "Reg";
|
||||||
} else if (OI.Rec->isSubClassOf("Operand")) {
|
|
||||||
// FIXME: This should not be hard coded.
|
|
||||||
const RecordVal *RV = OI.Rec->getValue("Type");
|
|
||||||
|
|
||||||
// FIXME: Yet another total hack.
|
|
||||||
if (RV->getValue()->getAsString() == "iPTR" ||
|
|
||||||
OI.Rec->getName() == "i8mem_NOREX" ||
|
|
||||||
OI.Rec->getName() == "lea32mem" ||
|
|
||||||
OI.Rec->getName() == "lea64mem" ||
|
|
||||||
OI.Rec->getName() == "i128mem" ||
|
|
||||||
OI.Rec->getName() == "sdmem" ||
|
|
||||||
OI.Rec->getName() == "ssmem" ||
|
|
||||||
OI.Rec->getName() == "lea64_32mem") {
|
|
||||||
ClassName = "Mem";
|
|
||||||
} else {
|
} else {
|
||||||
ClassName = "Imm";
|
try {
|
||||||
|
ClassName = OI.Rec->getValueAsString("ParserMatchClass");
|
||||||
|
assert(ClassName != "Reg" && "'Reg' class name is reserved!");
|
||||||
|
} catch(...) {
|
||||||
|
PrintError(OI.Rec->getLoc(), "operand has no match class!");
|
||||||
|
ClassName = "Invalid";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,11 +535,9 @@ AsmMatcherInfo::getOperandClass(const StringRef &Token,
|
||||||
if (ClassName == "Reg") {
|
if (ClassName == "Reg") {
|
||||||
Entry->Kind = ClassInfo::Register;
|
Entry->Kind = ClassInfo::Register;
|
||||||
} else {
|
} else {
|
||||||
if (ClassName == "Mem")
|
Entry->Kind = getUserClassKind(ClassName);
|
||||||
Entry->Kind = ClassInfo::UserClass0;
|
|
||||||
else
|
|
||||||
Entry->Kind = ClassInfo::UserClass0 + 1;
|
|
||||||
}
|
}
|
||||||
|
Entry->ClassName = ClassName;
|
||||||
Entry->Name = "MCK_" + ClassName;
|
Entry->Name = "MCK_" + ClassName;
|
||||||
Entry->ValueName = OI.Rec->getName();
|
Entry->ValueName = OI.Rec->getName();
|
||||||
Entry->PredicateMethod = "is" + ClassName;
|
Entry->PredicateMethod = "is" + ClassName;
|
||||||
|
@ -665,7 +677,7 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
|
||||||
for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex)
|
for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex)
|
||||||
Signature += "Imp";
|
Signature += "Imp";
|
||||||
|
|
||||||
Signature += Op.Class->Name;
|
Signature += Op.Class->ClassName;
|
||||||
Signature += utostr(Op.OperandInfo->MINumOperands);
|
Signature += utostr(Op.OperandInfo->MINumOperands);
|
||||||
Signature += "_" + utostr(MIOperandList[i].second);
|
Signature += "_" + utostr(MIOperandList[i].second);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue