mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-10 02:29:32 +00:00
llvm-mc/AsmParser: Implement user defined super classes.
- We can now discriminate SUB32ri8 from SUB32ri, for example. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78530 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
22cd2547fe
commit
5fe6338ac8
@ -137,6 +137,19 @@ struct X86Operand {
|
|||||||
|
|
||||||
bool isImm() const { return Kind == Immediate; }
|
bool isImm() const { return Kind == Immediate; }
|
||||||
|
|
||||||
|
bool isImmSExt8() const {
|
||||||
|
// Accept immediates which fit in 8 bits when sign extended, and
|
||||||
|
// non-absolute immediates.
|
||||||
|
if (!isImm())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!getImm().isAbsolute())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
int64_t Value = getImm().getConstant();
|
||||||
|
return Value == (int64_t) (int8_t) Value;
|
||||||
|
}
|
||||||
|
|
||||||
bool isMem() const { return Kind == Memory; }
|
bool isMem() const { return Kind == Memory; }
|
||||||
|
|
||||||
bool isReg() const { return Kind == Register; }
|
bool isReg() const { return Kind == Register; }
|
||||||
@ -151,6 +164,12 @@ struct X86Operand {
|
|||||||
Inst.addOperand(MCOperand::CreateMCValue(getImm()));
|
Inst.addOperand(MCOperand::CreateMCValue(getImm()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addImmSExt8Operands(MCInst &Inst, unsigned N) {
|
||||||
|
// FIXME: Support user customization of the render method.
|
||||||
|
assert(N == 1 && "Invalid number of operands!");
|
||||||
|
Inst.addOperand(MCOperand::CreateMCValue(getImm()));
|
||||||
|
}
|
||||||
|
|
||||||
void addMemOperands(MCInst &Inst, unsigned N) {
|
void addMemOperands(MCInst &Inst, unsigned N) {
|
||||||
assert((N == 4 || N == 5) && "Invalid number of operands!");
|
assert((N == 4 || N == 5) && "Invalid number of operands!");
|
||||||
|
|
||||||
|
@ -212,9 +212,15 @@ def piclabel: Operand<i32> {
|
|||||||
|
|
||||||
// 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 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 ParserMatchSuperClass = "Imm";
|
||||||
|
}
|
||||||
|
|
||||||
// Branch targets have OtherVT type and print as pc-relative values.
|
// Branch targets have OtherVT type and print as pc-relative values.
|
||||||
def brtarget : Operand<OtherVT> {
|
def brtarget : Operand<OtherVT> {
|
||||||
|
@ -16,3 +16,17 @@
|
|||||||
movl %eax, 10(%ebp, %ebx, 4)
|
movl %eax, 10(%ebp, %ebx, 4)
|
||||||
// RUN: grep {MCInst(opcode=.*, operands=.reg:0, imm:4, reg:21, val:10, reg:0, reg:19.)} %t
|
// RUN: grep {MCInst(opcode=.*, operands=.reg:0, imm:4, reg:21, val:10, reg:0, reg:19.)} %t
|
||||||
movl %eax, 10(, %ebx, 4)
|
movl %eax, 10(, %ebx, 4)
|
||||||
|
|
||||||
|
// FIXME: Check that this matches SUB32ri8
|
||||||
|
// RUN: grep {MCInst(opcode=.*, operands=.reg:19, reg:0, val:1.)} %t
|
||||||
|
subl $1, %eax
|
||||||
|
|
||||||
|
// FIXME: Check that this matches SUB32ri8
|
||||||
|
// RUN: grep {MCInst(opcode=.*, operands=.reg:19, reg:0, val:-1.)} %t
|
||||||
|
subl $-1, %eax
|
||||||
|
|
||||||
|
// FIXME: Check that this matches SUB32ri
|
||||||
|
// RUN: grep {MCInst(opcode=.*, operands=.reg:19, reg:0, val:256.)} %t
|
||||||
|
subl $256, %eax
|
||||||
|
|
||||||
|
|
||||||
|
@ -289,6 +289,12 @@ struct ClassInfo {
|
|||||||
/// N) for the Nth user defined class.
|
/// N) for the Nth user defined class.
|
||||||
unsigned Kind;
|
unsigned Kind;
|
||||||
|
|
||||||
|
/// SuperClassKind - The super class kind for user classes.
|
||||||
|
unsigned SuperClassKind;
|
||||||
|
|
||||||
|
/// SuperClass - The super class, or 0.
|
||||||
|
ClassInfo *SuperClass;
|
||||||
|
|
||||||
/// Name - The full class name, suitable for use in an enum.
|
/// Name - The full class name, suitable for use in an enum.
|
||||||
std::string Name;
|
std::string Name;
|
||||||
|
|
||||||
@ -308,27 +314,40 @@ struct ClassInfo {
|
|||||||
/// MCInst; this is not valid for Token kinds.
|
/// MCInst; this is not valid for Token kinds.
|
||||||
std::string RenderMethod;
|
std::string RenderMethod;
|
||||||
|
|
||||||
|
/// isUserClass() - Check if this is a user defined class.
|
||||||
|
bool isUserClass() const {
|
||||||
|
return Kind >= UserClass0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getRootClass - Return the root class of this one.
|
||||||
|
const ClassInfo *getRootClass() const {
|
||||||
|
const ClassInfo *CI = this;
|
||||||
|
while (CI->SuperClass)
|
||||||
|
CI = CI->SuperClass;
|
||||||
|
return CI;
|
||||||
|
}
|
||||||
|
|
||||||
/// operator< - Compare two classes.
|
/// operator< - Compare two classes.
|
||||||
bool operator<(const ClassInfo &RHS) const {
|
bool operator<(const ClassInfo &RHS) const {
|
||||||
// Incompatible kinds are comparable.
|
// Incompatible kinds are comparable for classes in disjoint hierarchies.
|
||||||
if (Kind != RHS.Kind)
|
if (Kind != RHS.Kind && getRootClass() != RHS.getRootClass())
|
||||||
return Kind < RHS.Kind;
|
return Kind < RHS.Kind;
|
||||||
|
|
||||||
switch (Kind) {
|
switch (Kind) {
|
||||||
case Invalid:
|
case Invalid:
|
||||||
assert(0 && "Invalid kind!");
|
assert(0 && "Invalid kind!");
|
||||||
case Token:
|
case Token:
|
||||||
// Tokens are always comparable.
|
// Tokens are comparable by value.
|
||||||
//
|
//
|
||||||
// FIXME: Compare by enum value.
|
// FIXME: Compare by enum value.
|
||||||
return ValueName < RHS.ValueName;
|
return ValueName < RHS.ValueName;
|
||||||
|
|
||||||
case Register:
|
|
||||||
// FIXME: Compare by subset relation.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// FIXME: Allow user defined relation.
|
// This class preceeds the RHS if the RHS is a super class.
|
||||||
|
for (ClassInfo *Parent = SuperClass; Parent; Parent = Parent->SuperClass)
|
||||||
|
if (Parent == &RHS)
|
||||||
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -525,6 +544,7 @@ unsigned AsmMatcherInfo::getUserClassKind(const StringRef &Name) {
|
|||||||
ClassInfo *
|
ClassInfo *
|
||||||
AsmMatcherInfo::getOperandClass(const StringRef &Token,
|
AsmMatcherInfo::getOperandClass(const StringRef &Token,
|
||||||
const CodeGenInstruction::OperandInfo &OI) {
|
const CodeGenInstruction::OperandInfo &OI) {
|
||||||
|
unsigned SuperClass = ClassInfo::Invalid;
|
||||||
std::string ClassName;
|
std::string ClassName;
|
||||||
if (OI.Rec->isSubClassOf("RegisterClass")) {
|
if (OI.Rec->isSubClassOf("RegisterClass")) {
|
||||||
ClassName = "Reg";
|
ClassName = "Reg";
|
||||||
@ -536,17 +556,24 @@ AsmMatcherInfo::getOperandClass(const StringRef &Token,
|
|||||||
PrintError(OI.Rec->getLoc(), "operand has no match class!");
|
PrintError(OI.Rec->getLoc(), "operand has no match class!");
|
||||||
ClassName = "Invalid";
|
ClassName = "Invalid";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine the super class.
|
||||||
|
try {
|
||||||
|
std::string SuperClassName =
|
||||||
|
OI.Rec->getValueAsString("ParserMatchSuperClass");
|
||||||
|
SuperClass = getUserClassKind(SuperClassName);
|
||||||
|
} catch(...) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassInfo *&Entry = OperandClasses[ClassName];
|
ClassInfo *&Entry = OperandClasses[ClassName];
|
||||||
|
|
||||||
if (!Entry) {
|
if (!Entry) {
|
||||||
Entry = new ClassInfo();
|
Entry = new ClassInfo();
|
||||||
// FIXME: Hack.
|
|
||||||
if (ClassName == "Reg") {
|
if (ClassName == "Reg") {
|
||||||
Entry->Kind = ClassInfo::Register;
|
Entry->Kind = ClassInfo::Register;
|
||||||
} else {
|
} else {
|
||||||
Entry->Kind = getUserClassKind(ClassName);
|
Entry->Kind = getUserClassKind(ClassName);
|
||||||
|
Entry->SuperClassKind = SuperClass;
|
||||||
}
|
}
|
||||||
Entry->ClassName = ClassName;
|
Entry->ClassName = ClassName;
|
||||||
Entry->Name = "MCK_" + ClassName;
|
Entry->Name = "MCK_" + ClassName;
|
||||||
@ -622,6 +649,27 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
|
|||||||
|
|
||||||
Instructions.push_back(II.take());
|
Instructions.push_back(II.take());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bind user super classes.
|
||||||
|
std::map<unsigned, ClassInfo*> UserClasses;
|
||||||
|
for (unsigned i = 0, e = Classes.size(); i != e; ++i) {
|
||||||
|
ClassInfo &CI = *Classes[i];
|
||||||
|
if (CI.isUserClass())
|
||||||
|
UserClasses[CI.Kind] = &CI;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = Classes.size(); i != e; ++i) {
|
||||||
|
ClassInfo &CI = *Classes[i];
|
||||||
|
if (CI.isUserClass() && CI.SuperClassKind != ClassInfo::Invalid) {
|
||||||
|
CI.SuperClass = UserClasses[CI.SuperClassKind];
|
||||||
|
assert(CI.SuperClass && "Missing super class definition!");
|
||||||
|
} else {
|
||||||
|
CI.SuperClass = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reorder classes so that classes preceed super classes.
|
||||||
|
std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EmitConvertToMCInst(CodeGenTarget &Target,
|
static void EmitConvertToMCInst(CodeGenTarget &Target,
|
||||||
@ -790,8 +838,22 @@ static void EmitClassifyOperand(CodeGenTarget &Target,
|
|||||||
ClassInfo &CI = **it;
|
ClassInfo &CI = **it;
|
||||||
|
|
||||||
if (CI.Kind != ClassInfo::Token) {
|
if (CI.Kind != ClassInfo::Token) {
|
||||||
OS << " if (Operand." << CI.PredicateMethod << "())\n";
|
OS << " // '" << CI.ClassName << "' class";
|
||||||
|
if (CI.SuperClass) {
|
||||||
|
OS << ", subclass of '" << CI.SuperClass->ClassName << "'";
|
||||||
|
assert(CI < *CI.SuperClass && "Invalid class relation!");
|
||||||
|
}
|
||||||
|
OS << "\n";
|
||||||
|
|
||||||
|
OS << " if (Operand." << CI.PredicateMethod << "()) {\n";
|
||||||
|
|
||||||
|
// Validate subclass relationships.
|
||||||
|
if (CI.SuperClass)
|
||||||
|
OS << " assert(Operand." << CI.SuperClass->PredicateMethod
|
||||||
|
<< "() && \"Invalid class relationship!\");\n";
|
||||||
|
|
||||||
OS << " return " << CI.Name << ";\n\n";
|
OS << " return " << CI.Name << ";\n\n";
|
||||||
|
OS << " }";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OS << " return InvalidMatchClass;\n";
|
OS << " return InvalidMatchClass;\n";
|
||||||
|
Loading…
Reference in New Issue
Block a user