mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
llvm-mc/AsmParser: Match hard coded registers (e.g. 'shldl %cl, %eax, %eax')
We now match all of 403.gcc (as emitted by clang). :) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78750 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c98077ba42
commit
1095f2ae26
@ -52,3 +52,7 @@
|
||||
// FIXME: Check that this matches the correct instruction.
|
||||
// RUN: grep {MCInst(opcode=.*, operands=.reg:80.)} %t
|
||||
call *%rax
|
||||
|
||||
// FIXME: Check that this matches the correct instruction.
|
||||
// RUN: grep {MCInst(opcode=.*, operands=.reg:21, reg:0, reg:19.)} %t
|
||||
shldl %cl, %eax, %ebx
|
||||
|
@ -532,7 +532,8 @@ private:
|
||||
|
||||
/// BuildRegisterClasses - Build the ClassInfo* instances for register
|
||||
/// classes.
|
||||
void BuildRegisterClasses(CodeGenTarget &Target);
|
||||
void BuildRegisterClasses(CodeGenTarget &Target,
|
||||
std::set<std::string> &SingletonRegisterNames);
|
||||
|
||||
/// BuildOperandClasses - Build the ClassInfo* instances for user defined
|
||||
/// operand classes.
|
||||
@ -565,6 +566,11 @@ void InstructionInfo::dump() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Op.OperandInfo) {
|
||||
errs() << "(singleton register)\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
const CodeGenInstruction::OperandInfo &OI = *Op.OperandInfo;
|
||||
errs() << OI.Name << " " << OI.Rec->getName()
|
||||
<< " (" << OI.MIOperandNo << ", " << OI.MINumOperands << ")\n";
|
||||
@ -592,6 +598,17 @@ static std::string getEnumNameForToken(const StringRef &Str) {
|
||||
return Res;
|
||||
}
|
||||
|
||||
/// getRegisterRecord - Get the register record for \arg name, or 0.
|
||||
static Record *getRegisterRecord(CodeGenTarget &Target, const StringRef &Name) {
|
||||
for (unsigned i = 0, e = Target.getRegisters().size(); i != e; ++i) {
|
||||
const CodeGenRegister &Reg = Target.getRegisters()[i];
|
||||
if (Name == Reg.TheDef->getValueAsString("AsmName"))
|
||||
return Reg.TheDef;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ClassInfo *AsmMatcherInfo::getTokenClass(const StringRef &Token) {
|
||||
ClassInfo *&Entry = TokenClasses[Token];
|
||||
|
||||
@ -635,7 +652,9 @@ AsmMatcherInfo::getOperandClass(const StringRef &Token,
|
||||
return CI;
|
||||
}
|
||||
|
||||
void AsmMatcherInfo::BuildRegisterClasses(CodeGenTarget &Target) {
|
||||
void AsmMatcherInfo::BuildRegisterClasses(CodeGenTarget &Target,
|
||||
std::set<std::string>
|
||||
&SingletonRegisterNames) {
|
||||
std::vector<CodeGenRegisterClass> RegisterClasses;
|
||||
std::vector<CodeGenRegister> Registers;
|
||||
|
||||
@ -650,7 +669,13 @@ void AsmMatcherInfo::BuildRegisterClasses(CodeGenTarget &Target) {
|
||||
ie = RegisterClasses.end(); it != ie; ++it)
|
||||
RegisterSets.insert(std::set<Record*>(it->Elements.begin(),
|
||||
it->Elements.end()));
|
||||
|
||||
|
||||
// Add any required singleton sets.
|
||||
for (std::set<std::string>::iterator it = SingletonRegisterNames.begin(),
|
||||
ie = SingletonRegisterNames.end(); it != ie; ++it)
|
||||
if (Record *Rec = getRegisterRecord(Target, *it))
|
||||
RegisterSets.insert(std::set<Record*>(&Rec, &Rec + 1));
|
||||
|
||||
// Introduce derived sets where necessary (when a register does not determine
|
||||
// a unique register set class), and build the mapping of registers to the set
|
||||
// they should classify to.
|
||||
@ -732,6 +757,22 @@ void AsmMatcherInfo::BuildRegisterClasses(CodeGenTarget &Target) {
|
||||
for (std::map<Record*, std::set<Record*> >::iterator it = RegisterMap.begin(),
|
||||
ie = RegisterMap.end(); it != ie; ++it)
|
||||
this->RegisterClasses[it->first] = RegisterSetClasses[it->second];
|
||||
|
||||
// Name the register classes which correspond to singleton registers.
|
||||
for (std::set<std::string>::iterator it = SingletonRegisterNames.begin(),
|
||||
ie = SingletonRegisterNames.end(); it != ie; ++it) {
|
||||
if (Record *Rec = getRegisterRecord(Target, *it)) {
|
||||
ClassInfo *CI = this->RegisterClasses[Rec];
|
||||
assert(CI && "Missing singleton register class info!");
|
||||
|
||||
if (CI->ValueName.empty()) {
|
||||
CI->ClassName = Rec->getName();
|
||||
CI->Name = "MCK_" + Rec->getName();
|
||||
CI->ValueName = Rec->getName();
|
||||
} else
|
||||
CI->ValueName = CI->ValueName + "," + Rec->getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AsmMatcherInfo::BuildOperandClasses(CodeGenTarget &Target) {
|
||||
@ -790,13 +831,9 @@ AsmMatcherInfo::AsmMatcherInfo(Record *_AsmParser)
|
||||
}
|
||||
|
||||
void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
|
||||
// Build info for the register classes.
|
||||
BuildRegisterClasses(Target);
|
||||
|
||||
// Build info for the user defined assembly operand classes.
|
||||
BuildOperandClasses(Target);
|
||||
|
||||
// Build the instruction information.
|
||||
// Parse the instructions; we need to do this first so that we can gather the
|
||||
// singleton register classes.
|
||||
std::set<std::string> SingletonRegisterNames;
|
||||
for (std::map<std::string, CodeGenInstruction>::const_iterator
|
||||
it = Target.getInstructions().begin(),
|
||||
ie = Target.getInstructions().end();
|
||||
@ -825,9 +862,53 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
|
||||
if (!IsAssemblerInstruction(it->first, CGI, II->Tokens))
|
||||
continue;
|
||||
|
||||
// Collect singleton registers, if used.
|
||||
if (!RegisterPrefix.empty()) {
|
||||
for (unsigned i = 0, e = II->Tokens.size(); i != e; ++i) {
|
||||
if (II->Tokens[i].startswith(RegisterPrefix)) {
|
||||
StringRef RegName = II->Tokens[i].substr(RegisterPrefix.size());
|
||||
Record *Rec = getRegisterRecord(Target, RegName);
|
||||
|
||||
if (!Rec) {
|
||||
std::string Err = "unable to find register for '" + RegName.str() +
|
||||
"' (which matches register prefix)";
|
||||
throw TGError(CGI.TheDef->getLoc(), Err);
|
||||
}
|
||||
|
||||
SingletonRegisterNames.insert(RegName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Instructions.push_back(II.take());
|
||||
}
|
||||
|
||||
// Build info for the register classes.
|
||||
BuildRegisterClasses(Target, SingletonRegisterNames);
|
||||
|
||||
// Build info for the user defined assembly operand classes.
|
||||
BuildOperandClasses(Target);
|
||||
|
||||
// Build the instruction information.
|
||||
for (std::vector<InstructionInfo*>::iterator it = Instructions.begin(),
|
||||
ie = Instructions.end(); it != ie; ++it) {
|
||||
InstructionInfo *II = *it;
|
||||
|
||||
for (unsigned i = 0, e = II->Tokens.size(); i != e; ++i) {
|
||||
StringRef Token = II->Tokens[i];
|
||||
|
||||
// Check for singleton registers.
|
||||
if (!RegisterPrefix.empty() && Token.startswith(RegisterPrefix)) {
|
||||
StringRef RegName = II->Tokens[i].substr(RegisterPrefix.size());
|
||||
InstructionInfo::Operand Op;
|
||||
Op.Class = RegisterClasses[getRegisterRecord(Target, RegName)];
|
||||
Op.OperandInfo = 0;
|
||||
assert(Op.Class && Op.Class->Registers.size() == 1 &&
|
||||
"Unexpected class for singleton register");
|
||||
II->Operands.push_back(Op);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for simple tokens.
|
||||
if (Token[0] != '$') {
|
||||
InstructionInfo::Operand Op;
|
||||
@ -847,24 +928,18 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
|
||||
// Map this token to an operand. FIXME: Move elsewhere.
|
||||
unsigned Idx;
|
||||
try {
|
||||
Idx = CGI.getOperandNamed(OperandName);
|
||||
Idx = II->Instr->getOperandNamed(OperandName);
|
||||
} catch(...) {
|
||||
errs() << "error: unable to find operand: '" << OperandName << "'!\n";
|
||||
break;
|
||||
throw std::string("error: unable to find operand: '" +
|
||||
OperandName.str() + "'");
|
||||
}
|
||||
|
||||
const CodeGenInstruction::OperandInfo &OI = CGI.OperandList[Idx];
|
||||
const CodeGenInstruction::OperandInfo &OI = II->Instr->OperandList[Idx];
|
||||
InstructionInfo::Operand Op;
|
||||
Op.Class = getOperandClass(Token, OI);
|
||||
Op.OperandInfo = &OI;
|
||||
II->Operands.push_back(Op);
|
||||
}
|
||||
|
||||
// If we broke out, ignore the instruction.
|
||||
if (II->Operands.size() != II->Tokens.size())
|
||||
continue;
|
||||
|
||||
Instructions.push_back(II.take());
|
||||
}
|
||||
|
||||
// Reorder classes so that classes preceed super classes.
|
||||
@ -1321,11 +1396,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||
Record *AsmParser = Target.getAsmParser();
|
||||
std::string ClassName = AsmParser->getValueAsString("AsmParserClassName");
|
||||
|
||||
EmitSourceFileHeader("Assembly Matcher Source Fragment", OS);
|
||||
|
||||
// Emit the function to match a register name to number.
|
||||
EmitMatchRegisterName(Target, AsmParser, OS);
|
||||
|
||||
// Compute the information on the instructions to match.
|
||||
AsmMatcherInfo Info(AsmParser);
|
||||
Info.BuildInfo(Target);
|
||||
@ -1366,6 +1436,13 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||
<< " ambiguous instructions!\n";
|
||||
});
|
||||
|
||||
// Write the output.
|
||||
|
||||
EmitSourceFileHeader("Assembly Matcher Source Fragment", OS);
|
||||
|
||||
// Emit the function to match a register name to number.
|
||||
EmitMatchRegisterName(Target, AsmParser, OS);
|
||||
|
||||
// Generate the unified function to convert operands into an MCInst.
|
||||
EmitConvertToMCInst(Target, Info.Instructions, OS);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user