mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 00:32:55 +00:00
Split AsmParser into two components - AsmParser and AsmParserVariant
AsmParser holds info specific to target parser. AsmParserVariant holds info specific to asm variants supported by the target. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147787 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8bf295b1bf
commit
0dbcadaa2f
@ -712,7 +712,15 @@ class AsmParser {
|
||||
// function of the AsmParser class to call on every matched instruction.
|
||||
// This can be used to perform target specific instruction post-processing.
|
||||
string AsmParserInstCleanup = "";
|
||||
}
|
||||
def DefaultAsmParser : AsmParser;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AsmParserVariant - Subtargets can have multiple different assembly parsers
|
||||
// (e.g. AT&T vs Intel syntax on X86 for example). This class can be
|
||||
// implemented by targets to describe such variants.
|
||||
//
|
||||
class AsmParserVariant {
|
||||
// Variant - AsmParsers can be of multiple different variants. Variants are
|
||||
// used to support targets that need to parser multiple formats for the
|
||||
// assembly language.
|
||||
@ -729,7 +737,7 @@ class AsmParser {
|
||||
// purposes of matching.
|
||||
string RegisterPrefix = "";
|
||||
}
|
||||
def DefaultAsmParser : AsmParser;
|
||||
def DefaultAsmParserVariant : AsmParserVariant;
|
||||
|
||||
/// AssemblerPredicate - This is a Predicate that can be used when the assembler
|
||||
/// matches instructions and aliases.
|
||||
@ -840,6 +848,10 @@ class Target {
|
||||
// AssemblyParsers - The AsmParser instances available for this target.
|
||||
list<AsmParser> AssemblyParsers = [DefaultAsmParser];
|
||||
|
||||
/// AssemblyParserVariants - The AsmParserVariant instances available for
|
||||
/// this target.
|
||||
list<AsmParserVariant> AssemblyParserVariants = [DefaultAsmParserVariant];
|
||||
|
||||
// AssemblyWriters - The AsmWriter instances available for this target.
|
||||
list<AsmWriter> AssemblyWriters = [DefaultAsmWriter];
|
||||
}
|
||||
|
@ -246,6 +246,9 @@ include "X86CallingConv.td"
|
||||
// Currently the X86 assembly parser only supports ATT syntax.
|
||||
def ATTAsmParser : AsmParser {
|
||||
string AsmParserClassName = "ATTAsmParser";
|
||||
}
|
||||
|
||||
def ATTAsmParserVariant : AsmParserVariant {
|
||||
int Variant = 0;
|
||||
|
||||
// Discard comments in assembly strings.
|
||||
@ -275,8 +278,7 @@ def IntelAsmWriter : AsmWriter {
|
||||
def X86 : Target {
|
||||
// Information about the instructions...
|
||||
let InstructionSet = X86InstrInfo;
|
||||
|
||||
let AssemblyParsers = [ATTAsmParser];
|
||||
|
||||
let AssemblyParserVariants = [ATTAsmParserVariant];
|
||||
let AssemblyWriters = [ATTAsmWriter, IntelAsmWriter];
|
||||
}
|
||||
|
@ -1171,88 +1171,92 @@ void AsmMatcherInfo::BuildInfo() {
|
||||
assert(FeatureNo < 32 && "Too many subtarget features!");
|
||||
}
|
||||
|
||||
std::string CommentDelimiter = AsmParser->getValueAsString("CommentDelimiter");
|
||||
std::string RegisterPrefix = AsmParser->getValueAsString("RegisterPrefix");
|
||||
int AsmVariantNo = AsmParser->getValueAsInt("Variant");
|
||||
|
||||
// Parse the instructions; we need to do this first so that we can gather the
|
||||
// singleton register classes.
|
||||
SmallPtrSet<Record*, 16> SingletonRegisters;
|
||||
for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
|
||||
E = Target.inst_end(); I != E; ++I) {
|
||||
const CodeGenInstruction &CGI = **I;
|
||||
|
||||
// If the tblgen -match-prefix option is specified (for tblgen hackers),
|
||||
// filter the set of instructions we consider.
|
||||
if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix))
|
||||
continue;
|
||||
|
||||
// Ignore "codegen only" instructions.
|
||||
if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
|
||||
continue;
|
||||
|
||||
// Validate the operand list to ensure we can handle this instruction.
|
||||
for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) {
|
||||
const CGIOperandList::OperandInfo &OI = CGI.Operands[i];
|
||||
|
||||
// Validate tied operands.
|
||||
if (OI.getTiedRegister() != -1) {
|
||||
// If we have a tied operand that consists of multiple MCOperands,
|
||||
// reject it. We reject aliases and ignore instructions for now.
|
||||
if (OI.MINumOperands != 1) {
|
||||
// FIXME: Should reject these. The ARM backend hits this with $lane
|
||||
// in a bunch of instructions. It is unclear what the right answer is.
|
||||
DEBUG({
|
||||
errs() << "warning: '" << CGI.TheDef->getName() << "': "
|
||||
<< "ignoring instruction with multi-operand tied operand '"
|
||||
<< OI.Name << "'\n";
|
||||
});
|
||||
continue;
|
||||
}
|
||||
unsigned VariantCount = Target.getAsmParserVariantCount();
|
||||
for (unsigned VC = 0; VC != VariantCount; ++VC) {
|
||||
Record *AsmVariant = Target.getAsmParserVariant(VC);
|
||||
std::string CommentDelimiter = AsmVariant->getValueAsString("CommentDelimiter");
|
||||
std::string RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix");
|
||||
int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
|
||||
|
||||
for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
|
||||
E = Target.inst_end(); I != E; ++I) {
|
||||
const CodeGenInstruction &CGI = **I;
|
||||
|
||||
// If the tblgen -match-prefix option is specified (for tblgen hackers),
|
||||
// filter the set of instructions we consider.
|
||||
if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix))
|
||||
continue;
|
||||
|
||||
// Ignore "codegen only" instructions.
|
||||
if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
|
||||
continue;
|
||||
|
||||
// Validate the operand list to ensure we can handle this instruction.
|
||||
for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) {
|
||||
const CGIOperandList::OperandInfo &OI = CGI.Operands[i];
|
||||
|
||||
// Validate tied operands.
|
||||
if (OI.getTiedRegister() != -1) {
|
||||
// If we have a tied operand that consists of multiple MCOperands,
|
||||
// reject it. We reject aliases and ignore instructions for now.
|
||||
if (OI.MINumOperands != 1) {
|
||||
// FIXME: Should reject these. The ARM backend hits this with $lane
|
||||
// in a bunch of instructions. It is unclear what the right answer is.
|
||||
DEBUG({
|
||||
errs() << "warning: '" << CGI.TheDef->getName() << "': "
|
||||
<< "ignoring instruction with multi-operand tied operand '"
|
||||
<< OI.Name << "'\n";
|
||||
});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OwningPtr<MatchableInfo> II(new MatchableInfo(CGI));
|
||||
|
||||
II->Initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix);
|
||||
|
||||
// Ignore instructions which shouldn't be matched and diagnose invalid
|
||||
// instruction definitions with an error.
|
||||
if (!II->Validate(CommentDelimiter, true))
|
||||
continue;
|
||||
|
||||
// Ignore "Int_*" and "*_Int" instructions, which are internal aliases.
|
||||
//
|
||||
// FIXME: This is a total hack.
|
||||
if (StringRef(II->TheDef->getName()).startswith("Int_") ||
|
||||
StringRef(II->TheDef->getName()).endswith("_Int"))
|
||||
continue;
|
||||
|
||||
Matchables.push_back(II.take());
|
||||
}
|
||||
|
||||
// Parse all of the InstAlias definitions and stick them in the list of
|
||||
// matchables.
|
||||
std::vector<Record*> AllInstAliases =
|
||||
Records.getAllDerivedDefinitions("InstAlias");
|
||||
for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) {
|
||||
CodeGenInstAlias *Alias = new CodeGenInstAlias(AllInstAliases[i], Target);
|
||||
|
||||
// If the tblgen -match-prefix option is specified (for tblgen hackers),
|
||||
// filter the set of instruction aliases we consider, based on the target
|
||||
// instruction.
|
||||
if (!StringRef(Alias->ResultInst->TheDef->getName()).startswith(
|
||||
MatchPrefix))
|
||||
continue;
|
||||
|
||||
OwningPtr<MatchableInfo> II(new MatchableInfo(Alias));
|
||||
|
||||
II->Initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix);
|
||||
|
||||
// Validate the alias definitions.
|
||||
II->Validate(CommentDelimiter, false);
|
||||
|
||||
Matchables.push_back(II.take());
|
||||
}
|
||||
|
||||
OwningPtr<MatchableInfo> II(new MatchableInfo(CGI));
|
||||
|
||||
II->Initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix);
|
||||
|
||||
// Ignore instructions which shouldn't be matched and diagnose invalid
|
||||
// instruction definitions with an error.
|
||||
if (!II->Validate(CommentDelimiter, true))
|
||||
continue;
|
||||
|
||||
// Ignore "Int_*" and "*_Int" instructions, which are internal aliases.
|
||||
//
|
||||
// FIXME: This is a total hack.
|
||||
if (StringRef(II->TheDef->getName()).startswith("Int_") ||
|
||||
StringRef(II->TheDef->getName()).endswith("_Int"))
|
||||
continue;
|
||||
|
||||
Matchables.push_back(II.take());
|
||||
}
|
||||
|
||||
// Parse all of the InstAlias definitions and stick them in the list of
|
||||
// matchables.
|
||||
std::vector<Record*> AllInstAliases =
|
||||
Records.getAllDerivedDefinitions("InstAlias");
|
||||
for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) {
|
||||
CodeGenInstAlias *Alias = new CodeGenInstAlias(AllInstAliases[i], Target);
|
||||
|
||||
// If the tblgen -match-prefix option is specified (for tblgen hackers),
|
||||
// filter the set of instruction aliases we consider, based on the target
|
||||
// instruction.
|
||||
if (!StringRef(Alias->ResultInst->TheDef->getName()).startswith(
|
||||
MatchPrefix))
|
||||
continue;
|
||||
|
||||
OwningPtr<MatchableInfo> II(new MatchableInfo(Alias));
|
||||
|
||||
II->Initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix);
|
||||
|
||||
// Validate the alias definitions.
|
||||
II->Validate(CommentDelimiter, false);
|
||||
|
||||
Matchables.push_back(II.take());
|
||||
}
|
||||
|
||||
// Build info for the register classes.
|
||||
|
@ -150,6 +150,26 @@ Record *CodeGenTarget::getAsmParser() const {
|
||||
return LI[AsmParserNum];
|
||||
}
|
||||
|
||||
/// getAsmParserVariant - Return the AssmblyParserVariant definition for
|
||||
/// this target.
|
||||
///
|
||||
Record *CodeGenTarget::getAsmParserVariant(unsigned i) const {
|
||||
std::vector<Record*> LI =
|
||||
TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
|
||||
if (i >= LI.size())
|
||||
throw "Target does not have an AsmParserVariant #" + utostr(i) + "!";
|
||||
return LI[i];
|
||||
}
|
||||
|
||||
/// getAsmParserVariantCount - Return the AssmblyParserVariant definition
|
||||
/// available for this target.
|
||||
///
|
||||
unsigned CodeGenTarget::getAsmParserVariantCount() const {
|
||||
std::vector<Record*> LI =
|
||||
TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
|
||||
return LI.size();
|
||||
}
|
||||
|
||||
/// getAsmWriter - Return the AssemblyWriter definition for this target.
|
||||
///
|
||||
Record *CodeGenTarget::getAsmWriter() const {
|
||||
|
@ -91,6 +91,16 @@ public:
|
||||
///
|
||||
Record *getAsmParser() const;
|
||||
|
||||
/// getAsmParserVariant - Return the AssmblyParserVariant definition for
|
||||
/// this target.
|
||||
///
|
||||
Record *getAsmParserVariant(unsigned i) const;
|
||||
|
||||
/// getAsmParserVariantCount - Return the AssmblyParserVariant definition
|
||||
/// available for this target.
|
||||
///
|
||||
unsigned getAsmParserVariantCount() const;
|
||||
|
||||
/// getAsmWriter - Return the AssemblyWriter definition for this target.
|
||||
///
|
||||
Record *getAsmWriter() const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user