mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-05 12:31:33 +00:00
llvm-mc/AsmMatcher: Change assembler parser match classes to their own record
structure. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78581 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b2d555b25b
commit
338825c192
@ -278,6 +278,32 @@ def ptr_rc : PointerLikeRegClass<0>;
|
|||||||
/// it to be resolved by inference in the context it is used.
|
/// it to be resolved by inference in the context it is used.
|
||||||
def unknown;
|
def unknown;
|
||||||
|
|
||||||
|
/// AsmOperandClass - Representation for the kinds of operands which the target
|
||||||
|
/// specific parser can create and the assembly matcher may need to distinguish.
|
||||||
|
///
|
||||||
|
/// Operand classes are used to define the order in which instructions are
|
||||||
|
/// matched, to ensure that the instruction which gets matched for any
|
||||||
|
/// particular list of operands is deterministic.
|
||||||
|
///
|
||||||
|
/// The target specific parser must be able to classify a 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 super class field
|
||||||
|
/// should be defined.
|
||||||
|
class AsmOperandClass {
|
||||||
|
/// The name to use for this class, this should be usable as an enum value,
|
||||||
|
/// and will be used to generated the names for the methods to test whether a
|
||||||
|
/// particular target specific operand matches this class, and the method to
|
||||||
|
/// convert an operand of this class into an MCInst operand.
|
||||||
|
string Name = ?;
|
||||||
|
|
||||||
|
/// The super class of this operand.
|
||||||
|
AsmOperandClass SuperClass = ?;
|
||||||
|
}
|
||||||
|
|
||||||
|
def ImmAsmOperand : AsmOperandClass {
|
||||||
|
let Name = "Imm";
|
||||||
|
}
|
||||||
|
|
||||||
/// Operand Types - These provide the built-in operand types that may be used
|
/// Operand Types - These provide the built-in operand types that may be used
|
||||||
/// by a target. Targets can optionally provide their own operand types as
|
/// by a target. Targets can optionally provide their own operand types as
|
||||||
/// needed, though this should not be needed for RISC targets.
|
/// needed, though this should not be needed for RISC targets.
|
||||||
@ -295,13 +321,7 @@ class Operand<ValueType ty> {
|
|||||||
// into a unique class, which does not partially overlap with any other
|
// 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
|
// classes. It can match a subset of some other class, in which case
|
||||||
// ParserMatchSuperClass should be set to the name of that class.
|
// ParserMatchSuperClass should be set to the name of that class.
|
||||||
string ParserMatchClass = "Imm";
|
AsmOperandClass ParserMatchClass = ImmAsmOperand;
|
||||||
|
|
||||||
// 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>;
|
||||||
|
@ -33,14 +33,14 @@ def i64i8imm : Operand<i64>;
|
|||||||
def lea64mem : Operand<i64> {
|
def lea64mem : Operand<i64> {
|
||||||
let PrintMethod = "printlea64mem";
|
let PrintMethod = "printlea64mem";
|
||||||
let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm);
|
let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm);
|
||||||
let ParserMatchClass = "Mem";
|
let ParserMatchClass = X86MemAsmOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
def lea64_32mem : Operand<i32> {
|
def lea64_32mem : Operand<i32> {
|
||||||
let PrintMethod = "printlea64_32mem";
|
let PrintMethod = "printlea64_32mem";
|
||||||
let AsmOperandLowerMethod = "lower_lea64_32mem";
|
let AsmOperandLowerMethod = "lower_lea64_32mem";
|
||||||
let MIOperandInfo = (ops GR32, i8imm, GR32_NOSP, i32imm);
|
let MIOperandInfo = (ops GR32, i8imm, GR32_NOSP, i32imm);
|
||||||
let ParserMatchClass = "Mem";
|
let ParserMatchClass = X86MemAsmOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -170,10 +170,14 @@ def ptr_rc_nosp : PointerLikeRegClass<1>;
|
|||||||
|
|
||||||
// *mem - Operand definitions for the funky X86 addressing mode operands.
|
// *mem - Operand definitions for the funky X86 addressing mode operands.
|
||||||
//
|
//
|
||||||
|
def X86MemAsmOperand : AsmOperandClass {
|
||||||
|
let Name = "Mem";
|
||||||
|
let SuperClass = ImmAsmOperand;
|
||||||
|
}
|
||||||
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";
|
let ParserMatchClass = X86MemAsmOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
def i8mem : X86MemOperand<"printi8mem">;
|
def i8mem : X86MemOperand<"printi8mem">;
|
||||||
@ -193,13 +197,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";
|
let ParserMatchClass = X86MemAsmOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
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";
|
let ParserMatchClass = X86MemAsmOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
def SSECC : Operand<i8> {
|
def SSECC : Operand<i8> {
|
||||||
@ -210,16 +214,19 @@ def piclabel: Operand<i32> {
|
|||||||
let PrintMethod = "printPICLabel";
|
let PrintMethod = "printPICLabel";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def ImmSExt8AsmOperand : AsmOperandClass {
|
||||||
|
let Name = "ImmSExt8";
|
||||||
|
let SuperClass = ImmAsmOperand;
|
||||||
|
}
|
||||||
|
|
||||||
// A couple of more descriptive operand definitions.
|
// A couple of more descriptive operand definitions.
|
||||||
// 16-bits but only 8 bits are significant.
|
// 16-bits but only 8 bits are significant.
|
||||||
def i16i8imm : Operand<i16> {
|
def i16i8imm : Operand<i16> {
|
||||||
let ParserMatchClass = "ImmSExt8";
|
let ParserMatchClass = ImmSExt8AsmOperand;
|
||||||
let ParserMatchSuperClass = "Imm";
|
|
||||||
}
|
}
|
||||||
// 32-bits but only 8 bits are significant.
|
// 32-bits but only 8 bits are significant.
|
||||||
def i32i8imm : Operand<i32> {
|
def i32i8imm : Operand<i32> {
|
||||||
let ParserMatchClass = "ImmSExt8";
|
let ParserMatchClass = ImmSExt8AsmOperand;
|
||||||
let ParserMatchSuperClass = "Imm";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Branch targets have OtherVT type and print as pc-relative values.
|
// Branch targets have OtherVT type and print as pc-relative values.
|
||||||
|
@ -87,12 +87,12 @@ def sse_load_f64 : ComplexPattern<v2f64, 5, "SelectScalarSSELoad", [],
|
|||||||
def ssmem : Operand<v4f32> {
|
def ssmem : Operand<v4f32> {
|
||||||
let PrintMethod = "printf32mem";
|
let PrintMethod = "printf32mem";
|
||||||
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";
|
let ParserMatchClass = X86MemAsmOperand;
|
||||||
}
|
}
|
||||||
def sdmem : Operand<v2f64> {
|
def sdmem : Operand<v2f64> {
|
||||||
let PrintMethod = "printf64mem";
|
let PrintMethod = "printf64mem";
|
||||||
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";
|
let ParserMatchClass = X86MemAsmOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -87,11 +87,9 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
namespace {
|
|
||||||
static cl::opt<std::string>
|
static cl::opt<std::string>
|
||||||
MatchPrefix("match-prefix", cl::init(""),
|
MatchPrefix("match-prefix", cl::init(""),
|
||||||
cl::desc("Only match instructions with the given prefix"));
|
cl::desc("Only match instructions with the given prefix"));
|
||||||
}
|
|
||||||
|
|
||||||
/// FlattenVariants - Flatten an .td file assembly string by selecting the
|
/// FlattenVariants - Flatten an .td file assembly string by selecting the
|
||||||
/// variant at index \arg N.
|
/// variant at index \arg N.
|
||||||
@ -455,21 +453,16 @@ private:
|
|||||||
/// Map of token to class information which has already been constructed.
|
/// Map of token to class information which has already been constructed.
|
||||||
std::map<std::string, ClassInfo*> TokenClasses;
|
std::map<std::string, ClassInfo*> TokenClasses;
|
||||||
|
|
||||||
/// Map of operand name to class information which has already been
|
/// The ClassInfo instance for registers.
|
||||||
/// constructed.
|
ClassInfo *TheRegisterClass;
|
||||||
std::map<std::string, ClassInfo*> OperandClasses;
|
|
||||||
|
|
||||||
/// Map of user class names to kind value.
|
/// Map of AsmOperandClass records to their class information.
|
||||||
std::map<std::string, unsigned> UserClasses;
|
std::map<Record*, ClassInfo*> AsmOperandClasses;
|
||||||
|
|
||||||
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);
|
||||||
@ -543,66 +536,68 @@ 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) {
|
||||||
unsigned SuperClass = ClassInfo::Invalid;
|
if (OI.Rec->isSubClassOf("RegisterClass"))
|
||||||
std::string ClassName;
|
return TheRegisterClass;
|
||||||
if (OI.Rec->isSubClassOf("RegisterClass")) {
|
|
||||||
ClassName = "Reg";
|
|
||||||
} else {
|
|
||||||
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";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the super class.
|
assert(OI.Rec->isSubClassOf("Operand") && "Unexpected operand!");
|
||||||
try {
|
Record *MatchClass = OI.Rec->getValueAsDef("ParserMatchClass");
|
||||||
std::string SuperClassName =
|
ClassInfo *CI = AsmOperandClasses[MatchClass];
|
||||||
OI.Rec->getValueAsString("ParserMatchSuperClass");
|
|
||||||
SuperClass = getUserClassKind(SuperClassName);
|
if (!CI) {
|
||||||
} catch(...) { }
|
PrintError(OI.Rec->getLoc(), "operand has no match class!");
|
||||||
|
throw std::string("ERROR: Missing match class!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassInfo *&Entry = OperandClasses[ClassName];
|
return CI;
|
||||||
|
|
||||||
if (!Entry) {
|
|
||||||
Entry = new ClassInfo();
|
|
||||||
if (ClassName == "Reg") {
|
|
||||||
Entry->Kind = ClassInfo::Register;
|
|
||||||
Entry->SuperClassKind = SuperClass;
|
|
||||||
} else {
|
|
||||||
Entry->Kind = getUserClassKind(ClassName);
|
|
||||||
Entry->SuperClassKind = SuperClass;
|
|
||||||
}
|
|
||||||
Entry->ClassName = ClassName;
|
|
||||||
Entry->Name = "MCK_" + ClassName;
|
|
||||||
Entry->ValueName = OI.Rec->getName();
|
|
||||||
Entry->PredicateMethod = "is" + ClassName;
|
|
||||||
Entry->RenderMethod = "add" + ClassName + "Operands";
|
|
||||||
Classes.push_back(Entry);
|
|
||||||
} else {
|
|
||||||
// Verify the super class matches.
|
|
||||||
assert(SuperClass == Entry->SuperClassKind &&
|
|
||||||
"Cannot redefine super class kind!");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
|
void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
|
||||||
|
// Build the assembly match class information.
|
||||||
|
|
||||||
|
// Construct the "Reg" class.
|
||||||
|
//
|
||||||
|
// FIXME: This needs to dice up the RegisterClass instances.
|
||||||
|
ClassInfo *RegClass = TheRegisterClass = new ClassInfo();
|
||||||
|
RegClass->Kind = ClassInfo::Register;
|
||||||
|
RegClass->SuperClassKind = ClassInfo::Invalid;
|
||||||
|
RegClass->ClassName = "Reg";
|
||||||
|
RegClass->Name = "MCK_Reg";
|
||||||
|
RegClass->ValueName = "<register class>";
|
||||||
|
RegClass->PredicateMethod = "isReg";
|
||||||
|
RegClass->RenderMethod = "addRegOperands";
|
||||||
|
Classes.push_back(RegClass);
|
||||||
|
|
||||||
|
// Build info for the user defined assembly operand classes.
|
||||||
|
std::vector<Record*> AsmOperands;
|
||||||
|
AsmOperands = Records.getAllDerivedDefinitions("AsmOperandClass");
|
||||||
|
unsigned Index = 0;
|
||||||
|
for (std::vector<Record*>::iterator it = AsmOperands.begin(),
|
||||||
|
ie = AsmOperands.end(); it != ie; ++it, ++Index) {
|
||||||
|
ClassInfo *CI = new ClassInfo();
|
||||||
|
CI->Kind = ClassInfo::UserClass0 + Index;
|
||||||
|
|
||||||
|
Init *Super = (*it)->getValueInit("SuperClass");
|
||||||
|
if (DefInit *DI = dynamic_cast<DefInit*>(Super)) {
|
||||||
|
CI->SuperClass = AsmOperandClasses[DI->getDef()];
|
||||||
|
if (!CI->SuperClass)
|
||||||
|
PrintError((*it)->getLoc(), "Invalid super class reference!");
|
||||||
|
} else {
|
||||||
|
assert(dynamic_cast<UnsetInit*>(Super) && "Unexpected SuperClass field!");
|
||||||
|
CI->SuperClass = 0;
|
||||||
|
}
|
||||||
|
CI->ClassName = (*it)->getValueAsString("Name");
|
||||||
|
CI->Name = "MCK_" + CI->ClassName;
|
||||||
|
CI->ValueName = (*it)->getName();
|
||||||
|
CI->PredicateMethod = "is" + CI->ClassName;
|
||||||
|
CI->RenderMethod = "add" + CI->ClassName + "Operands";
|
||||||
|
AsmOperandClasses[*it] = CI;
|
||||||
|
Classes.push_back(CI);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the instruction information.
|
||||||
for (std::map<std::string, CodeGenInstruction>::const_iterator
|
for (std::map<std::string, CodeGenInstruction>::const_iterator
|
||||||
it = Target.getInstructions().begin(),
|
it = Target.getInstructions().begin(),
|
||||||
ie = Target.getInstructions().end();
|
ie = Target.getInstructions().end();
|
||||||
|
Loading…
Reference in New Issue
Block a user