mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
refactor InstructionInfo to not have a pointer to CodeGenInstruction
member, and make isAssemblerInstruction() a method (pushing some code around inside it). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117895 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c76e80ded7
commit
5bc9387806
@ -169,64 +169,6 @@ static void TokenizeAsmString(StringRef AsmString,
|
||||
Tokens.push_back(AsmString.substr(Prev));
|
||||
}
|
||||
|
||||
static bool IsAssemblerInstruction(StringRef Name,
|
||||
const CodeGenInstruction &CGI,
|
||||
const SmallVectorImpl<StringRef> &Tokens) {
|
||||
// Ignore "codegen only" instructions.
|
||||
if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
|
||||
return false;
|
||||
|
||||
// Ignore "Int_*" and "*_Int" instructions, which are internal aliases.
|
||||
//
|
||||
// FIXME: This is a total hack.
|
||||
if (StringRef(Name).startswith("Int_") || StringRef(Name).endswith("_Int"))
|
||||
return false;
|
||||
|
||||
// Reject instructions with no .s string.
|
||||
if (CGI.AsmString.empty()) {
|
||||
PrintError(CGI.TheDef->getLoc(),
|
||||
"instruction with empty asm string");
|
||||
throw std::string("ERROR: Invalid instruction for asm matcher");
|
||||
}
|
||||
|
||||
// Reject any instructions with a newline in them, they should be marked
|
||||
// isCodeGenOnly if they are pseudo instructions.
|
||||
if (CGI.AsmString.find('\n') != std::string::npos) {
|
||||
PrintError(CGI.TheDef->getLoc(),
|
||||
"multiline instruction is not valid for the asmparser, "
|
||||
"mark it isCodeGenOnly");
|
||||
throw std::string("ERROR: Invalid instruction");
|
||||
}
|
||||
|
||||
// Reject instructions with attributes, these aren't something we can handle,
|
||||
// the target should be refactored to use operands instead of modifiers.
|
||||
//
|
||||
// Also, check for instructions which reference the operand multiple times;
|
||||
// this implies a constraint we would not honor.
|
||||
std::set<std::string> OperandNames;
|
||||
for (unsigned i = 1, e = Tokens.size(); i < e; ++i) {
|
||||
if (Tokens[i][0] == '$' &&
|
||||
Tokens[i].find(':') != StringRef::npos) {
|
||||
PrintError(CGI.TheDef->getLoc(),
|
||||
"instruction with operand modifier '" + Tokens[i].str() +
|
||||
"' not supported by asm matcher. Mark isCodeGenOnly!");
|
||||
throw std::string("ERROR: Invalid instruction");
|
||||
}
|
||||
|
||||
// FIXME: Should reject these. The ARM backend hits this with $lane in a
|
||||
// bunch of instructions. It is unclear what the right answer is for this.
|
||||
if (Tokens[i][0] == '$' && !OperandNames.insert(Tokens[i]).second) {
|
||||
DEBUG({
|
||||
errs() << "warning: '" << Name << "': "
|
||||
<< "ignoring instruction with tied operand '"
|
||||
<< Tokens[i].str() << "'\n";
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class AsmMatcherInfo;
|
||||
@ -392,8 +334,8 @@ struct InstructionInfo {
|
||||
/// InstrName - The target name for this instruction.
|
||||
std::string InstrName;
|
||||
|
||||
/// Instr - The instruction this matches.
|
||||
const CodeGenInstruction *Instr;
|
||||
Record *const TheDef;
|
||||
const CGIOperandList &OperandList;
|
||||
|
||||
/// AsmString - The assembly string for this instruction (with variants
|
||||
/// removed).
|
||||
@ -413,6 +355,27 @@ struct InstructionInfo {
|
||||
/// function.
|
||||
std::string ConversionFnKind;
|
||||
|
||||
InstructionInfo(const CodeGenInstruction &CGI, StringRef CommentDelimiter)
|
||||
: TheDef(CGI.TheDef), OperandList(CGI.Operands) {
|
||||
InstrName = TheDef->getName();
|
||||
// TODO: Eventually support asmparser for Variant != 0.
|
||||
AsmString = CGI.FlattenAsmStringVariants(CGI.AsmString, 0);
|
||||
|
||||
// Remove comments from the asm string. We know that the asmstring only
|
||||
// has one line.
|
||||
if (!CommentDelimiter.empty()) {
|
||||
size_t Idx = StringRef(AsmString).find(CommentDelimiter);
|
||||
if (Idx != StringRef::npos)
|
||||
AsmString = AsmString.substr(0, Idx);
|
||||
}
|
||||
|
||||
TokenizeAsmString(AsmString, Tokens);
|
||||
}
|
||||
|
||||
/// isAssemblerInstruction - Return true if this matchable is a valid thing to
|
||||
/// match against.
|
||||
bool isAssemblerInstruction() const;
|
||||
|
||||
/// getSingletonRegisterForToken - If the specified token is a singleton
|
||||
/// register, return the Record for it, otherwise return null.
|
||||
Record *getSingletonRegisterForToken(unsigned i,
|
||||
@ -604,6 +567,48 @@ static Record *getRegisterRecord(CodeGenTarget &Target, StringRef Name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool InstructionInfo::isAssemblerInstruction() const {
|
||||
StringRef Name = InstrName;
|
||||
|
||||
// Reject instructions with no .s string.
|
||||
if (AsmString.empty())
|
||||
throw TGError(TheDef->getLoc(), "instruction with empty asm string");
|
||||
|
||||
// Reject any instructions with a newline in them, they should be marked
|
||||
// isCodeGenOnly if they are pseudo instructions.
|
||||
if (AsmString.find('\n') != std::string::npos)
|
||||
throw TGError(TheDef->getLoc(),
|
||||
"multiline instruction is not valid for the asmparser, "
|
||||
"mark it isCodeGenOnly");
|
||||
|
||||
// Reject instructions with attributes, these aren't something we can handle,
|
||||
// the target should be refactored to use operands instead of modifiers.
|
||||
//
|
||||
// Also, check for instructions which reference the operand multiple times;
|
||||
// this implies a constraint we would not honor.
|
||||
std::set<std::string> OperandNames;
|
||||
for (unsigned i = 1, e = Tokens.size(); i < e; ++i) {
|
||||
if (Tokens[i][0] == '$' && Tokens[i].find(':') != StringRef::npos)
|
||||
throw TGError(TheDef->getLoc(),
|
||||
"instruction with operand modifier '" + Tokens[i].str() +
|
||||
"' not supported by asm matcher. Mark isCodeGenOnly!");
|
||||
|
||||
// FIXME: Should reject these. The ARM backend hits this with $lane in a
|
||||
// bunch of instructions. It is unclear what the right answer is for this.
|
||||
if (Tokens[i][0] == '$' && !OperandNames.insert(Tokens[i]).second) {
|
||||
DEBUG({
|
||||
errs() << "warning: '" << Name << "': "
|
||||
<< "ignoring instruction with tied operand '"
|
||||
<< Tokens[i].str() << "'\n";
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// getSingletonRegisterForToken - If the specified token is a singleton
|
||||
/// register, return the register name, otherwise return a null StringRef.
|
||||
Record *InstructionInfo::
|
||||
@ -623,7 +628,7 @@ getSingletonRegisterForToken(unsigned i, const AsmMatcherInfo &Info) const {
|
||||
|
||||
std::string Err = "unable to find register for '" + RegName.str() +
|
||||
"' (which matches register prefix)";
|
||||
throw TGError(Instr->TheDef->getLoc(), Err);
|
||||
throw TGError(TheDef->getLoc(), Err);
|
||||
}
|
||||
|
||||
|
||||
@ -908,26 +913,22 @@ void AsmMatcherInfo::BuildInfo() {
|
||||
if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix))
|
||||
continue;
|
||||
|
||||
OwningPtr<InstructionInfo> II(new InstructionInfo());
|
||||
|
||||
II->InstrName = CGI.TheDef->getName();
|
||||
II->Instr = &CGI;
|
||||
// TODO: Eventually support asmparser for Variant != 0.
|
||||
II->AsmString = CGI.FlattenAsmStringVariants(CGI.AsmString, 0);
|
||||
|
||||
// Remove comments from the asm string. We know that the asmstring only
|
||||
// has one line.
|
||||
if (!CommentDelimiter.empty()) {
|
||||
size_t Idx = StringRef(II->AsmString).find(CommentDelimiter);
|
||||
if (Idx != StringRef::npos)
|
||||
II->AsmString = II->AsmString.substr(0, Idx);
|
||||
}
|
||||
|
||||
TokenizeAsmString(II->AsmString, II->Tokens);
|
||||
// Ignore "codegen only" instructions.
|
||||
if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
|
||||
continue;
|
||||
|
||||
OwningPtr<InstructionInfo> II(new InstructionInfo(CGI, CommentDelimiter));
|
||||
|
||||
// Ignore instructions which shouldn't be matched and diagnose invalid
|
||||
// instruction definitions with an error.
|
||||
if (!IsAssemblerInstruction(CGI.TheDef->getName(), CGI, II->Tokens))
|
||||
if (!II->isAssemblerInstruction())
|
||||
continue;
|
||||
|
||||
// Ignore "Int_*" and "*_Int" instructions, which are internal aliases.
|
||||
//
|
||||
// FIXME: This is a total hack.
|
||||
if (StringRef(II->InstrName).startswith("Int_") ||
|
||||
StringRef(II->InstrName).endswith("_Int"))
|
||||
continue;
|
||||
|
||||
// Collect singleton registers, if used.
|
||||
@ -972,7 +973,7 @@ void AsmMatcherInfo::BuildInfo() {
|
||||
assert(!II->Tokens.empty() && "Instruction has no tokens?");
|
||||
StringRef Mnemonic = II->Tokens[0];
|
||||
if (Mnemonic[0] == '$' || II->getSingletonRegisterForToken(0, *this))
|
||||
throw TGError(II->Instr->TheDef->getLoc(),
|
||||
throw TGError(II->TheDef->getLoc(),
|
||||
"Invalid instruction mnemonic '" + Mnemonic.str() + "'!");
|
||||
|
||||
// Parse the tokens after the mnemonic.
|
||||
@ -1008,7 +1009,7 @@ void AsmMatcherInfo::BuildInfo() {
|
||||
|
||||
// Map this token to an operand. FIXME: Move elsewhere.
|
||||
unsigned Idx;
|
||||
if (!II->Instr->Operands.hasOperandNamed(OperandName, Idx))
|
||||
if (!II->OperandList.hasOperandNamed(OperandName, Idx))
|
||||
throw std::string("error: unable to find operand: '" +
|
||||
OperandName.str() + "'");
|
||||
|
||||
@ -1016,15 +1017,15 @@ void AsmMatcherInfo::BuildInfo() {
|
||||
// XCHG8rm). What we want is the untied operand, which we now have to
|
||||
// grovel for. Only worry about this for single entry operands, we have to
|
||||
// clean this up anyway.
|
||||
const CGIOperandList::OperandInfo *OI = &II->Instr->Operands[Idx];
|
||||
const CGIOperandList::OperandInfo *OI = &II->OperandList[Idx];
|
||||
if (OI->Constraints[0].isTied()) {
|
||||
unsigned TiedOp = OI->Constraints[0].getTiedOperand();
|
||||
|
||||
// The tied operand index is an MIOperand index, find the operand that
|
||||
// contains it.
|
||||
for (unsigned i = 0, e = II->Instr->Operands.size(); i != e; ++i) {
|
||||
if (II->Instr->Operands[i].MIOperandNo == TiedOp) {
|
||||
OI = &II->Instr->Operands[i];
|
||||
for (unsigned i = 0, e = II->OperandList.size(); i != e; ++i) {
|
||||
if (II->OperandList[i].MIOperandNo == TiedOp) {
|
||||
OI = &II->OperandList[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1096,8 +1097,8 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
|
||||
|
||||
// Find any tied operands.
|
||||
SmallVector<std::pair<unsigned, unsigned>, 4> TiedOperands;
|
||||
for (unsigned i = 0, e = II.Instr->Operands.size(); i != e; ++i) {
|
||||
const CGIOperandList::OperandInfo &OpInfo = II.Instr->Operands[i];
|
||||
for (unsigned i = 0, e = II.OperandList.size(); i != e; ++i) {
|
||||
const CGIOperandList::OperandInfo &OpInfo = II.OperandList[i];
|
||||
for (unsigned j = 0, e = OpInfo.Constraints.size(); j != e; ++j) {
|
||||
const CGIOperandList::ConstraintInfo &CI = OpInfo.Constraints[j];
|
||||
if (CI.isTied())
|
||||
@ -1110,8 +1111,8 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
|
||||
|
||||
// Compute the total number of operands.
|
||||
unsigned NumMIOperands = 0;
|
||||
for (unsigned i = 0, e = II.Instr->Operands.size(); i != e; ++i) {
|
||||
const CGIOperandList::OperandInfo &OI = II.Instr->Operands[i];
|
||||
for (unsigned i = 0, e = II.OperandList.size(); i != e; ++i) {
|
||||
const CGIOperandList::OperandInfo &OI = II.OperandList[i];
|
||||
NumMIOperands = std::max(NumMIOperands,
|
||||
OI.MIOperandNo + OI.MINumOperands);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user