mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-14 17:34:41 +00:00
Do AsmMatcher operand classification per-opcode.
When matching operands for a candidate opcode match in the auto-generated AsmMatcher, check each operand against the expected operand match class. Previously, operands were classified independently of the opcode being handled, which led to difficulties when operand match classes were more complicated than simple subclass relationships. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125245 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4f5c9d2061
commit
b9db0c50d8
@ -1,5 +1,4 @@
|
|||||||
@ RUN: llvm-mc -mcpu=cortex-a8 -triple armv7-apple-darwin -show-encoding < %s | FileCheck %s
|
@ RUN: llvm-mc -mcpu=cortex-a8 -triple armv7-apple-darwin -show-encoding < %s | FileCheck %s
|
||||||
@ XFAIL: *
|
|
||||||
|
|
||||||
@ CHECK: vadd.f64 d16, d17, d16 @ encoding: [0xa0,0x0b,0x71,0xee]
|
@ CHECK: vadd.f64 d16, d17, d16 @ encoding: [0xa0,0x0b,0x71,0xee]
|
||||||
vadd.f64 d16, d17, d16
|
vadd.f64 d16, d17, d16
|
||||||
|
@ -1621,37 +1621,35 @@ static void EmitMatchClassEnumeration(CodeGenTarget &Target,
|
|||||||
OS << "}\n\n";
|
OS << "}\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EmitClassifyOperand - Emit the function to classify an operand.
|
/// EmitValidateOperandClass - Emit the function to validate an operand class.
|
||||||
static void EmitClassifyOperand(AsmMatcherInfo &Info,
|
static void EmitValidateOperandClass(AsmMatcherInfo &Info,
|
||||||
raw_ostream &OS) {
|
raw_ostream &OS) {
|
||||||
OS << "static MatchClassKind ClassifyOperand(MCParsedAsmOperand *GOp) {\n"
|
OS << "static bool ValidateOperandClass(MCParsedAsmOperand *GOp, "
|
||||||
<< " " << Info.Target.getName() << "Operand &Operand = *("
|
<< "MatchClassKind Kind) {\n";
|
||||||
|
OS << " " << Info.Target.getName() << "Operand &Operand = *("
|
||||||
<< Info.Target.getName() << "Operand*)GOp;\n";
|
<< Info.Target.getName() << "Operand*)GOp;\n";
|
||||||
|
|
||||||
// Classify tokens.
|
// Check for Token operands first.
|
||||||
OS << " if (Operand.isToken())\n";
|
OS << " if (Operand.isToken())\n";
|
||||||
OS << " return MatchTokenString(Operand.getToken());\n\n";
|
OS << " return MatchTokenString(Operand.getToken()) == Kind;\n\n";
|
||||||
|
|
||||||
// Classify registers.
|
// Check for register operands, including sub-classes.
|
||||||
//
|
|
||||||
// FIXME: Don't hardcode isReg, getReg.
|
|
||||||
OS << " if (Operand.isReg()) {\n";
|
OS << " if (Operand.isReg()) {\n";
|
||||||
|
OS << " MatchClassKind OpKind;\n";
|
||||||
OS << " switch (Operand.getReg()) {\n";
|
OS << " switch (Operand.getReg()) {\n";
|
||||||
OS << " default: return InvalidMatchClass;\n";
|
OS << " default: OpKind = InvalidMatchClass; break;\n";
|
||||||
for (std::map<Record*, ClassInfo*>::iterator
|
for (std::map<Record*, ClassInfo*>::iterator
|
||||||
it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end();
|
it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end();
|
||||||
it != ie; ++it)
|
it != ie; ++it)
|
||||||
OS << " case " << Info.Target.getName() << "::"
|
OS << " case " << Info.Target.getName() << "::"
|
||||||
<< it->first->getName() << ": return " << it->second->Name << ";\n";
|
<< it->first->getName() << ": OpKind = " << it->second->Name
|
||||||
|
<< "; break;\n";
|
||||||
OS << " }\n";
|
OS << " }\n";
|
||||||
|
OS << " return IsSubclass(OpKind, Kind);\n";
|
||||||
OS << " }\n\n";
|
OS << " }\n\n";
|
||||||
|
|
||||||
// Classify user defined operands. To do so, we need to perform a topological
|
// Check the user classes. We don't care what order since we're only
|
||||||
// sort of the superclass relationship graph so that we always match the
|
// actually matching against one of them.
|
||||||
// narrowest type first.
|
|
||||||
|
|
||||||
// Collect the incoming edge counts for each class.
|
|
||||||
std::map<ClassInfo*, unsigned> IncomingEdges;
|
|
||||||
for (std::vector<ClassInfo*>::iterator it = Info.Classes.begin(),
|
for (std::vector<ClassInfo*>::iterator it = Info.Classes.begin(),
|
||||||
ie = Info.Classes.end(); it != ie; ++it) {
|
ie = Info.Classes.end(); it != ie; ++it) {
|
||||||
ClassInfo &CI = **it;
|
ClassInfo &CI = **it;
|
||||||
@ -1659,58 +1657,14 @@ static void EmitClassifyOperand(AsmMatcherInfo &Info,
|
|||||||
if (!CI.isUserClass())
|
if (!CI.isUserClass())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (std::vector<ClassInfo*>::iterator SI = CI.SuperClasses.begin(),
|
OS << " // '" << CI.ClassName << "' class\n";
|
||||||
SE = CI.SuperClasses.end(); SI != SE; ++SI)
|
OS << " if (Kind == " << CI.Name
|
||||||
++IncomingEdges[*SI];
|
<< " && Operand." << CI.PredicateMethod << "()) {\n";
|
||||||
}
|
OS << " return true;\n";
|
||||||
|
|
||||||
// Initialize a worklist of classes with no incoming edges.
|
|
||||||
std::vector<ClassInfo*> LeafClasses;
|
|
||||||
for (std::vector<ClassInfo*>::iterator it = Info.Classes.begin(),
|
|
||||||
ie = Info.Classes.end(); it != ie; ++it) {
|
|
||||||
if (!IncomingEdges[*it])
|
|
||||||
LeafClasses.push_back(*it);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iteratively pop the list, process that class, and update the incoming
|
|
||||||
// edge counts for its super classes. When a superclass reaches zero
|
|
||||||
// incoming edges, push it onto the worklist for processing.
|
|
||||||
while (!LeafClasses.empty()) {
|
|
||||||
ClassInfo &CI = *LeafClasses.back();
|
|
||||||
LeafClasses.pop_back();
|
|
||||||
|
|
||||||
if (!CI.isUserClass())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
OS << " // '" << CI.ClassName << "' class";
|
|
||||||
if (!CI.SuperClasses.empty()) {
|
|
||||||
OS << ", subclass of ";
|
|
||||||
for (unsigned i = 0, e = CI.SuperClasses.size(); i != e; ++i) {
|
|
||||||
if (i) OS << ", ";
|
|
||||||
OS << "'" << CI.SuperClasses[i]->ClassName << "'";
|
|
||||||
assert(CI < *CI.SuperClasses[i] && "Invalid class relation!");
|
|
||||||
|
|
||||||
--IncomingEdges[CI.SuperClasses[i]];
|
|
||||||
if (!IncomingEdges[CI.SuperClasses[i]])
|
|
||||||
LeafClasses.push_back(CI.SuperClasses[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OS << "\n";
|
|
||||||
|
|
||||||
OS << " if (Operand." << CI.PredicateMethod << "()) {\n";
|
|
||||||
|
|
||||||
// Validate subclass relationships.
|
|
||||||
if (!CI.SuperClasses.empty()) {
|
|
||||||
for (unsigned i = 0, e = CI.SuperClasses.size(); i != e; ++i)
|
|
||||||
OS << " assert(Operand." << CI.SuperClasses[i]->PredicateMethod
|
|
||||||
<< "() && \"Invalid class relationship!\");\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
OS << " return " << CI.Name << ";\n";
|
|
||||||
OS << " }\n\n";
|
OS << " }\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
OS << " return InvalidMatchClass;\n";
|
OS << " return false;\n";
|
||||||
OS << "}\n\n";
|
OS << "}\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2215,12 +2169,12 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
|||||||
// Emit the routine to match token strings to their match class.
|
// Emit the routine to match token strings to their match class.
|
||||||
EmitMatchTokenString(Target, Info.Classes, OS);
|
EmitMatchTokenString(Target, Info.Classes, OS);
|
||||||
|
|
||||||
// Emit the routine to classify an operand.
|
|
||||||
EmitClassifyOperand(Info, OS);
|
|
||||||
|
|
||||||
// Emit the subclass predicate routine.
|
// Emit the subclass predicate routine.
|
||||||
EmitIsSubclass(Target, Info.Classes, OS);
|
EmitIsSubclass(Target, Info.Classes, OS);
|
||||||
|
|
||||||
|
// Emit the routine to validate an operand against a match class.
|
||||||
|
EmitValidateOperandClass(Info, OS);
|
||||||
|
|
||||||
// Emit the available features compute function.
|
// Emit the available features compute function.
|
||||||
EmitComputeAvailableFeatures(Info, OS);
|
EmitComputeAvailableFeatures(Info, OS);
|
||||||
|
|
||||||
@ -2335,23 +2289,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
|||||||
OS << " return Match_InvalidOperand;\n";
|
OS << " return Match_InvalidOperand;\n";
|
||||||
OS << " }\n\n";
|
OS << " }\n\n";
|
||||||
|
|
||||||
OS << " // Compute the class list for this operand vector.\n";
|
|
||||||
OS << " MatchClassKind Classes[" << MaxNumOperands << "];\n";
|
|
||||||
OS << " for (unsigned i = 1, e = Operands.size(); i != e; ++i) {\n";
|
|
||||||
OS << " Classes[i-1] = ClassifyOperand(Operands[i]);\n\n";
|
|
||||||
|
|
||||||
OS << " // Check for invalid operands before matching.\n";
|
|
||||||
OS << " if (Classes[i-1] == InvalidMatchClass) {\n";
|
|
||||||
OS << " ErrorInfo = i;\n";
|
|
||||||
OS << " return Match_InvalidOperand;\n";
|
|
||||||
OS << " }\n";
|
|
||||||
OS << " }\n\n";
|
|
||||||
|
|
||||||
OS << " // Mark unused classes.\n";
|
|
||||||
OS << " for (unsigned i = Operands.size()-1, e = " << MaxNumOperands << "; "
|
|
||||||
<< "i != e; ++i)\n";
|
|
||||||
OS << " Classes[i] = InvalidMatchClass;\n\n";
|
|
||||||
|
|
||||||
OS << " // Some state to try to produce better error messages.\n";
|
OS << " // Some state to try to produce better error messages.\n";
|
||||||
OS << " bool HadMatchOtherThanFeatures = false;\n\n";
|
OS << " bool HadMatchOtherThanFeatures = false;\n\n";
|
||||||
OS << " // Set ErrorInfo to the operand that mismatches if it is \n";
|
OS << " // Set ErrorInfo to the operand that mismatches if it is \n";
|
||||||
@ -2378,7 +2315,11 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
|||||||
// Emit check that the subclasses match.
|
// Emit check that the subclasses match.
|
||||||
OS << " bool OperandsValid = true;\n";
|
OS << " bool OperandsValid = true;\n";
|
||||||
OS << " for (unsigned i = 0; i != " << MaxNumOperands << "; ++i) {\n";
|
OS << " for (unsigned i = 0; i != " << MaxNumOperands << "; ++i) {\n";
|
||||||
OS << " if (IsSubclass(Classes[i], it->Classes[i]))\n";
|
OS << " if (i + 1 >= Operands.size()) {\n";
|
||||||
|
OS << " OperandsValid = (it->Classes[i] == " <<"InvalidMatchClass);\n";
|
||||||
|
OS << " break;";
|
||||||
|
OS << " }\n";
|
||||||
|
OS << " if (ValidateOperandClass(Operands[i+1], it->Classes[i]))\n";
|
||||||
OS << " continue;\n";
|
OS << " continue;\n";
|
||||||
OS << " // If this operand is broken for all of the instances of this\n";
|
OS << " // If this operand is broken for all of the instances of this\n";
|
||||||
OS << " // mnemonic, keep track of it so we can report loc info.\n";
|
OS << " // mnemonic, keep track of it so we can report loc info.\n";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user