From 0dbcadaa2fdf7038431931bab090f4467d8e308f Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Mon, 9 Jan 2012 19:13:28 +0000 Subject: 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 --- include/llvm/Target/Target.td | 14 +++- lib/Target/X86/X86.td | 6 +- utils/TableGen/AsmMatcherEmitter.cpp | 158 ++++++++++++++++++----------------- utils/TableGen/CodeGenTarget.cpp | 20 +++++ utils/TableGen/CodeGenTarget.h | 10 +++ 5 files changed, 128 insertions(+), 80 deletions(-) diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index c9b6a8ec41..be08b9c9be 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -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 AssemblyParsers = [DefaultAsmParser]; + /// AssemblyParserVariants - The AsmParserVariant instances available for + /// this target. + list AssemblyParserVariants = [DefaultAsmParserVariant]; + // AssemblyWriters - The AsmWriter instances available for this target. list AssemblyWriters = [DefaultAsmWriter]; } diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td index 48c7387af3..91fe227b21 100644 --- a/lib/Target/X86/X86.td +++ b/lib/Target/X86/X86.td @@ -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]; } diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 1ab2d02444..737e948d24 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -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 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 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 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 II(new MatchableInfo(Alias)); + + II->Initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); + + // Validate the alias definitions. + II->Validate(CommentDelimiter, false); + + Matchables.push_back(II.take()); } - - OwningPtr 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 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 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. diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index cb9851841e..be3ea74958 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -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 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 LI = + TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); + return LI.size(); +} + /// getAsmWriter - Return the AssemblyWriter definition for this target. /// Record *CodeGenTarget::getAsmWriter() const { diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index 730216c331..85463da597 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -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; -- cgit v1.2.3-18-g5258