xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/AsmMatcherEmitter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- AsmMatcherEmitter.cpp - Generate an assembly matcher ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This tablegen backend emits a target specifier matcher for converting parsed
100b57cec5SDimitry Andric // assembly operands in the MCInst structures. It also emits a matcher for
110b57cec5SDimitry Andric // custom operand parsing.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric // Converting assembly operands into MCInst structures
140b57cec5SDimitry Andric // ---------------------------------------------------
150b57cec5SDimitry Andric //
160b57cec5SDimitry Andric // The input to the target specific matcher is a list of literal tokens and
170b57cec5SDimitry Andric // operands. The target specific parser should generally eliminate any syntax
180b57cec5SDimitry Andric // which is not relevant for matching; for example, comma tokens should have
190b57cec5SDimitry Andric // already been consumed and eliminated by the parser. Most instructions will
200b57cec5SDimitry Andric // end up with a single literal token (the instruction name) and some number of
210b57cec5SDimitry Andric // operands.
220b57cec5SDimitry Andric //
230b57cec5SDimitry Andric // Some example inputs, for X86:
240b57cec5SDimitry Andric //   'addl' (immediate ...) (register ...)
250b57cec5SDimitry Andric //   'add' (immediate ...) (memory ...)
260b57cec5SDimitry Andric //   'call' '*' %epc
270b57cec5SDimitry Andric //
280b57cec5SDimitry Andric // The assembly matcher is responsible for converting this input into a precise
290b57cec5SDimitry Andric // machine instruction (i.e., an instruction with a well defined encoding). This
300b57cec5SDimitry Andric // mapping has several properties which complicate matching:
310b57cec5SDimitry Andric //
320b57cec5SDimitry Andric //  - It may be ambiguous; many architectures can legally encode particular
330b57cec5SDimitry Andric //    variants of an instruction in different ways (for example, using a smaller
340b57cec5SDimitry Andric //    encoding for small immediates). Such ambiguities should never be
350b57cec5SDimitry Andric //    arbitrarily resolved by the assembler, the assembler is always responsible
360b57cec5SDimitry Andric //    for choosing the "best" available instruction.
370b57cec5SDimitry Andric //
380b57cec5SDimitry Andric //  - It may depend on the subtarget or the assembler context. Instructions
390b57cec5SDimitry Andric //    which are invalid for the current mode, but otherwise unambiguous (e.g.,
400b57cec5SDimitry Andric //    an SSE instruction in a file being assembled for i486) should be accepted
410b57cec5SDimitry Andric //    and rejected by the assembler front end. However, if the proper encoding
420b57cec5SDimitry Andric //    for an instruction is dependent on the assembler context then the matcher
430b57cec5SDimitry Andric //    is responsible for selecting the correct machine instruction for the
440b57cec5SDimitry Andric //    current mode.
450b57cec5SDimitry Andric //
460b57cec5SDimitry Andric // The core matching algorithm attempts to exploit the regularity in most
470b57cec5SDimitry Andric // instruction sets to quickly determine the set of possibly matching
480b57cec5SDimitry Andric // instructions, and the simplify the generated code. Additionally, this helps
490b57cec5SDimitry Andric // to ensure that the ambiguities are intentionally resolved by the user.
500b57cec5SDimitry Andric //
510b57cec5SDimitry Andric // The matching is divided into two distinct phases:
520b57cec5SDimitry Andric //
530b57cec5SDimitry Andric //   1. Classification: Each operand is mapped to the unique set which (a)
540b57cec5SDimitry Andric //      contains it, and (b) is the largest such subset for which a single
550b57cec5SDimitry Andric //      instruction could match all members.
560b57cec5SDimitry Andric //
570b57cec5SDimitry Andric //      For register classes, we can generate these subgroups automatically. For
580b57cec5SDimitry Andric //      arbitrary operands, we expect the user to define the classes and their
590b57cec5SDimitry Andric //      relations to one another (for example, 8-bit signed immediates as a
600b57cec5SDimitry Andric //      subset of 32-bit immediates).
610b57cec5SDimitry Andric //
620b57cec5SDimitry Andric //      By partitioning the operands in this way, we guarantee that for any
630b57cec5SDimitry Andric //      tuple of classes, any single instruction must match either all or none
640b57cec5SDimitry Andric //      of the sets of operands which could classify to that tuple.
650b57cec5SDimitry Andric //
660b57cec5SDimitry Andric //      In addition, the subset relation amongst classes induces a partial order
670b57cec5SDimitry Andric //      on such tuples, which we use to resolve ambiguities.
680b57cec5SDimitry Andric //
690b57cec5SDimitry Andric //   2. The input can now be treated as a tuple of classes (static tokens are
700b57cec5SDimitry Andric //      simple singleton sets). Each such tuple should generally map to a single
710b57cec5SDimitry Andric //      instruction (we currently ignore cases where this isn't true, whee!!!),
720b57cec5SDimitry Andric //      which we can emit a simple matcher for.
730b57cec5SDimitry Andric //
740b57cec5SDimitry Andric // Custom Operand Parsing
750b57cec5SDimitry Andric // ----------------------
760b57cec5SDimitry Andric //
770b57cec5SDimitry Andric //  Some targets need a custom way to parse operands, some specific instructions
780b57cec5SDimitry Andric //  can contain arguments that can represent processor flags and other kinds of
790b57cec5SDimitry Andric //  identifiers that need to be mapped to specific values in the final encoded
800b57cec5SDimitry Andric //  instructions. The target specific custom operand parsing works in the
810b57cec5SDimitry Andric //  following way:
820b57cec5SDimitry Andric //
830b57cec5SDimitry Andric //   1. A operand match table is built, each entry contains a mnemonic, an
840b57cec5SDimitry Andric //      operand class, a mask for all operand positions for that same
850b57cec5SDimitry Andric //      class/mnemonic and target features to be checked while trying to match.
860b57cec5SDimitry Andric //
870b57cec5SDimitry Andric //   2. The operand matcher will try every possible entry with the same
880b57cec5SDimitry Andric //      mnemonic and will check if the target feature for this mnemonic also
890b57cec5SDimitry Andric //      matches. After that, if the operand to be matched has its index
900b57cec5SDimitry Andric //      present in the mask, a successful match occurs. Otherwise, fallback
910b57cec5SDimitry Andric //      to the regular operand parsing.
920b57cec5SDimitry Andric //
930b57cec5SDimitry Andric //   3. For a match success, each operand class that has a 'ParserMethod'
940b57cec5SDimitry Andric //      becomes part of a switch from where the custom method is called.
950b57cec5SDimitry Andric //
960b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
970b57cec5SDimitry Andric 
98*0fca6ea1SDimitry Andric #include "Common/CodeGenInstAlias.h"
99*0fca6ea1SDimitry Andric #include "Common/CodeGenInstruction.h"
100*0fca6ea1SDimitry Andric #include "Common/CodeGenRegisters.h"
101*0fca6ea1SDimitry Andric #include "Common/CodeGenTarget.h"
102*0fca6ea1SDimitry Andric #include "Common/SubtargetFeatureInfo.h"
103*0fca6ea1SDimitry Andric #include "Common/Types.h"
1040b57cec5SDimitry Andric #include "llvm/ADT/CachedHashString.h"
1050b57cec5SDimitry Andric #include "llvm/ADT/PointerUnion.h"
1060b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
1070b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
1080b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
1090b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
1100b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
1110b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
1120b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
1130b57cec5SDimitry Andric #include "llvm/TableGen/Error.h"
1140b57cec5SDimitry Andric #include "llvm/TableGen/Record.h"
1150b57cec5SDimitry Andric #include "llvm/TableGen/StringMatcher.h"
1160b57cec5SDimitry Andric #include "llvm/TableGen/StringToOffsetTable.h"
1170b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
1180b57cec5SDimitry Andric #include <cassert>
1190b57cec5SDimitry Andric #include <cctype>
1200b57cec5SDimitry Andric #include <forward_list>
1210b57cec5SDimitry Andric #include <map>
1220b57cec5SDimitry Andric #include <set>
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric using namespace llvm;
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric #define DEBUG_TYPE "asm-matcher-emitter"
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric cl::OptionCategory AsmMatcherEmitterCat("Options for -gen-asm-matcher");
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric static cl::opt<std::string>
1310b57cec5SDimitry Andric     MatchPrefix("match-prefix", cl::init(""),
1320b57cec5SDimitry Andric                 cl::desc("Only match instructions with the given prefix"),
1330b57cec5SDimitry Andric                 cl::cat(AsmMatcherEmitterCat));
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric namespace {
1360b57cec5SDimitry Andric class AsmMatcherInfo;
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric // Register sets are used as keys in some second-order sets TableGen creates
1390b57cec5SDimitry Andric // when generating its data structures. This means that the order of two
1400b57cec5SDimitry Andric // RegisterSets can be seen in the outputted AsmMatcher tables occasionally, and
1410b57cec5SDimitry Andric // can even affect compiler output (at least seen in diagnostics produced when
1420b57cec5SDimitry Andric // all matches fail). So we use a type that sorts them consistently.
1430b57cec5SDimitry Andric typedef std::set<Record *, LessRecordByID> RegisterSet;
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric class AsmMatcherEmitter {
1460b57cec5SDimitry Andric   RecordKeeper &Records;
147*0fca6ea1SDimitry Andric 
1480b57cec5SDimitry Andric public:
1490b57cec5SDimitry Andric   AsmMatcherEmitter(RecordKeeper &R) : Records(R) {}
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   void run(raw_ostream &o);
1520b57cec5SDimitry Andric };
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric /// ClassInfo - Helper class for storing the information about a particular
1550b57cec5SDimitry Andric /// class of operands which can be matched.
1560b57cec5SDimitry Andric struct ClassInfo {
1570b57cec5SDimitry Andric   enum ClassInfoKind {
1580b57cec5SDimitry Andric     /// Invalid kind, for use as a sentinel value.
1590b57cec5SDimitry Andric     Invalid = 0,
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric     /// The class for a particular token.
1620b57cec5SDimitry Andric     Token,
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric     /// The (first) register class, subsequent register classes are
1650b57cec5SDimitry Andric     /// RegisterClass0+1, and so on.
1660b57cec5SDimitry Andric     RegisterClass0,
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric     /// The (first) user defined class, subsequent user defined classes are
1690b57cec5SDimitry Andric     /// UserClass0+1, and so on.
1700b57cec5SDimitry Andric     UserClass0 = 1 << 16
1710b57cec5SDimitry Andric   };
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   /// Kind - The class kind, which is either a predefined kind, or (UserClass0 +
1740b57cec5SDimitry Andric   /// N) for the Nth user defined class.
1750b57cec5SDimitry Andric   unsigned Kind;
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   /// SuperClasses - The super classes of this class. Note that for simplicities
1780b57cec5SDimitry Andric   /// sake user operands only record their immediate super class, while register
1790b57cec5SDimitry Andric   /// operands include all superclasses.
1800b57cec5SDimitry Andric   std::vector<ClassInfo *> SuperClasses;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   /// Name - The full class name, suitable for use in an enum.
1830b57cec5SDimitry Andric   std::string Name;
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   /// ClassName - The unadorned generic name for this class (e.g., Token).
1860b57cec5SDimitry Andric   std::string ClassName;
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   /// ValueName - The name of the value this class represents; for a token this
1890b57cec5SDimitry Andric   /// is the literal token string, for an operand it is the TableGen class (or
1900b57cec5SDimitry Andric   /// empty if this is a derived class).
1910b57cec5SDimitry Andric   std::string ValueName;
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   /// PredicateMethod - The name of the operand method to test whether the
1940b57cec5SDimitry Andric   /// operand matches this class; this is not valid for Token or register kinds.
1950b57cec5SDimitry Andric   std::string PredicateMethod;
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   /// RenderMethod - The name of the operand method to add this operand to an
1980b57cec5SDimitry Andric   /// MCInst; this is not valid for Token or register kinds.
1990b57cec5SDimitry Andric   std::string RenderMethod;
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   /// ParserMethod - The name of the operand method to do a target specific
2020b57cec5SDimitry Andric   /// parsing on the operand.
2030b57cec5SDimitry Andric   std::string ParserMethod;
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   /// For register classes: the records for all the registers in this class.
2060b57cec5SDimitry Andric   RegisterSet Registers;
2070b57cec5SDimitry Andric 
208*0fca6ea1SDimitry Andric   /// For custom match classes: the diagnostic kind for when the predicate
209*0fca6ea1SDimitry Andric   /// fails.
2100b57cec5SDimitry Andric   std::string DiagnosticType;
2110b57cec5SDimitry Andric 
212*0fca6ea1SDimitry Andric   /// For custom match classes: the diagnostic string for when the predicate
213*0fca6ea1SDimitry Andric   /// fails.
2140b57cec5SDimitry Andric   std::string DiagnosticString;
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   /// Is this operand optional and not always required.
2170b57cec5SDimitry Andric   bool IsOptional;
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   /// DefaultMethod - The name of the method that returns the default operand
2200b57cec5SDimitry Andric   /// for optional operand
2210b57cec5SDimitry Andric   std::string DefaultMethod;
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric public:
2240b57cec5SDimitry Andric   /// isRegisterClass() - Check if this is a register class.
2250b57cec5SDimitry Andric   bool isRegisterClass() const {
2260b57cec5SDimitry Andric     return Kind >= RegisterClass0 && Kind < UserClass0;
2270b57cec5SDimitry Andric   }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   /// isUserClass() - Check if this is a user defined class.
230*0fca6ea1SDimitry Andric   bool isUserClass() const { return Kind >= UserClass0; }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   /// isRelatedTo - Check whether this class is "related" to \p RHS. Classes
2330b57cec5SDimitry Andric   /// are related if they are in the same class hierarchy.
2340b57cec5SDimitry Andric   bool isRelatedTo(const ClassInfo &RHS) const {
2350b57cec5SDimitry Andric     // Tokens are only related to tokens.
2360b57cec5SDimitry Andric     if (Kind == Token || RHS.Kind == Token)
2370b57cec5SDimitry Andric       return Kind == Token && RHS.Kind == Token;
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric     // Registers classes are only related to registers classes, and only if
2400b57cec5SDimitry Andric     // their intersection is non-empty.
2410b57cec5SDimitry Andric     if (isRegisterClass() || RHS.isRegisterClass()) {
2420b57cec5SDimitry Andric       if (!isRegisterClass() || !RHS.isRegisterClass())
2430b57cec5SDimitry Andric         return false;
2440b57cec5SDimitry Andric 
245*0fca6ea1SDimitry Andric       std::vector<Record *> Tmp;
2460b57cec5SDimitry Andric       std::set_intersection(Registers.begin(), Registers.end(),
2470b57cec5SDimitry Andric                             RHS.Registers.begin(), RHS.Registers.end(),
248*0fca6ea1SDimitry Andric                             std::back_inserter(Tmp), LessRecordByID());
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric       return !Tmp.empty();
2510b57cec5SDimitry Andric     }
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric     // Otherwise we have two users operands; they are related if they are in the
2540b57cec5SDimitry Andric     // same class hierarchy.
2550b57cec5SDimitry Andric     //
2560b57cec5SDimitry Andric     // FIXME: This is an oversimplification, they should only be related if they
2570b57cec5SDimitry Andric     // intersect, however we don't have that information.
2580b57cec5SDimitry Andric     assert(isUserClass() && RHS.isUserClass() && "Unexpected class!");
2590b57cec5SDimitry Andric     const ClassInfo *Root = this;
2600b57cec5SDimitry Andric     while (!Root->SuperClasses.empty())
2610b57cec5SDimitry Andric       Root = Root->SuperClasses.front();
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric     const ClassInfo *RHSRoot = &RHS;
2640b57cec5SDimitry Andric     while (!RHSRoot->SuperClasses.empty())
2650b57cec5SDimitry Andric       RHSRoot = RHSRoot->SuperClasses.front();
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric     return Root == RHSRoot;
2680b57cec5SDimitry Andric   }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   /// isSubsetOf - Test whether this class is a subset of \p RHS.
2710b57cec5SDimitry Andric   bool isSubsetOf(const ClassInfo &RHS) const {
2720b57cec5SDimitry Andric     // This is a subset of RHS if it is the same class...
2730b57cec5SDimitry Andric     if (this == &RHS)
2740b57cec5SDimitry Andric       return true;
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric     // ... or if any of its super classes are a subset of RHS.
2770b57cec5SDimitry Andric     SmallVector<const ClassInfo *, 16> Worklist(SuperClasses.begin(),
2780b57cec5SDimitry Andric                                                 SuperClasses.end());
2790b57cec5SDimitry Andric     SmallPtrSet<const ClassInfo *, 16> Visited;
2800b57cec5SDimitry Andric     while (!Worklist.empty()) {
2810b57cec5SDimitry Andric       auto *CI = Worklist.pop_back_val();
2820b57cec5SDimitry Andric       if (CI == &RHS)
2830b57cec5SDimitry Andric         return true;
2840b57cec5SDimitry Andric       for (auto *Super : CI->SuperClasses)
2850b57cec5SDimitry Andric         if (Visited.insert(Super).second)
2860b57cec5SDimitry Andric           Worklist.push_back(Super);
2870b57cec5SDimitry Andric     }
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric     return false;
2900b57cec5SDimitry Andric   }
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric   int getTreeDepth() const {
2930b57cec5SDimitry Andric     int Depth = 0;
2940b57cec5SDimitry Andric     const ClassInfo *Root = this;
2950b57cec5SDimitry Andric     while (!Root->SuperClasses.empty()) {
2960b57cec5SDimitry Andric       Depth++;
2970b57cec5SDimitry Andric       Root = Root->SuperClasses.front();
2980b57cec5SDimitry Andric     }
2990b57cec5SDimitry Andric     return Depth;
3000b57cec5SDimitry Andric   }
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   const ClassInfo *findRoot() const {
3030b57cec5SDimitry Andric     const ClassInfo *Root = this;
3040b57cec5SDimitry Andric     while (!Root->SuperClasses.empty())
3050b57cec5SDimitry Andric       Root = Root->SuperClasses.front();
3060b57cec5SDimitry Andric     return Root;
3070b57cec5SDimitry Andric   }
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   /// Compare two classes. This does not produce a total ordering, but does
3100b57cec5SDimitry Andric   /// guarantee that subclasses are sorted before their parents, and that the
3110b57cec5SDimitry Andric   /// ordering is transitive.
3120b57cec5SDimitry Andric   bool operator<(const ClassInfo &RHS) const {
3130b57cec5SDimitry Andric     if (this == &RHS)
3140b57cec5SDimitry Andric       return false;
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric     // First, enforce the ordering between the three different types of class.
3170b57cec5SDimitry Andric     // Tokens sort before registers, which sort before user classes.
3180b57cec5SDimitry Andric     if (Kind == Token) {
3190b57cec5SDimitry Andric       if (RHS.Kind != Token)
3200b57cec5SDimitry Andric         return true;
3210b57cec5SDimitry Andric       assert(RHS.Kind == Token);
3220b57cec5SDimitry Andric     } else if (isRegisterClass()) {
3230b57cec5SDimitry Andric       if (RHS.Kind == Token)
3240b57cec5SDimitry Andric         return false;
3250b57cec5SDimitry Andric       else if (RHS.isUserClass())
3260b57cec5SDimitry Andric         return true;
3270b57cec5SDimitry Andric       assert(RHS.isRegisterClass());
3280b57cec5SDimitry Andric     } else if (isUserClass()) {
3290b57cec5SDimitry Andric       if (!RHS.isUserClass())
3300b57cec5SDimitry Andric         return false;
3310b57cec5SDimitry Andric       assert(RHS.isUserClass());
3320b57cec5SDimitry Andric     } else {
3330b57cec5SDimitry Andric       llvm_unreachable("Unknown ClassInfoKind");
3340b57cec5SDimitry Andric     }
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric     if (Kind == Token || isUserClass()) {
3370b57cec5SDimitry Andric       // Related tokens and user classes get sorted by depth in the inheritence
3380b57cec5SDimitry Andric       // tree (so that subclasses are before their parents).
3390b57cec5SDimitry Andric       if (isRelatedTo(RHS)) {
3400b57cec5SDimitry Andric         if (getTreeDepth() > RHS.getTreeDepth())
3410b57cec5SDimitry Andric           return true;
3420b57cec5SDimitry Andric         if (getTreeDepth() < RHS.getTreeDepth())
3430b57cec5SDimitry Andric           return false;
3440b57cec5SDimitry Andric       } else {
3450b57cec5SDimitry Andric         // Unrelated tokens and user classes are ordered by the name of their
3460b57cec5SDimitry Andric         // root nodes, so that there is a consistent ordering between
3470b57cec5SDimitry Andric         // unconnected trees.
3480b57cec5SDimitry Andric         return findRoot()->ValueName < RHS.findRoot()->ValueName;
3490b57cec5SDimitry Andric       }
3500b57cec5SDimitry Andric     } else if (isRegisterClass()) {
3510b57cec5SDimitry Andric       // For register sets, sort by number of registers. This guarantees that
3520b57cec5SDimitry Andric       // a set will always sort before all of it's strict supersets.
3530b57cec5SDimitry Andric       if (Registers.size() != RHS.Registers.size())
3540b57cec5SDimitry Andric         return Registers.size() < RHS.Registers.size();
3550b57cec5SDimitry Andric     } else {
3560b57cec5SDimitry Andric       llvm_unreachable("Unknown ClassInfoKind");
3570b57cec5SDimitry Andric     }
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric     // FIXME: We should be able to just return false here, as we only need a
3600b57cec5SDimitry Andric     // partial order (we use stable sorts, so this is deterministic) and the
3610b57cec5SDimitry Andric     // name of a class shouldn't be significant. However, some of the backends
3620b57cec5SDimitry Andric     // accidentally rely on this behaviour, so it will have to stay like this
3630b57cec5SDimitry Andric     // until they are fixed.
3640b57cec5SDimitry Andric     return ValueName < RHS.ValueName;
3650b57cec5SDimitry Andric   }
3660b57cec5SDimitry Andric };
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric class AsmVariantInfo {
3690b57cec5SDimitry Andric public:
3700b57cec5SDimitry Andric   StringRef RegisterPrefix;
3710b57cec5SDimitry Andric   StringRef TokenizingCharacters;
3720b57cec5SDimitry Andric   StringRef SeparatorCharacters;
3730b57cec5SDimitry Andric   StringRef BreakCharacters;
3740b57cec5SDimitry Andric   StringRef Name;
3750b57cec5SDimitry Andric   int AsmVariantNo;
3760b57cec5SDimitry Andric };
3770b57cec5SDimitry Andric 
378*0fca6ea1SDimitry Andric bool getPreferSmallerInstructions(CodeGenTarget const &Target) {
379*0fca6ea1SDimitry Andric   return Target.getAsmParser()->getValueAsBit("PreferSmallerInstructions");
380*0fca6ea1SDimitry Andric }
381*0fca6ea1SDimitry Andric 
3820b57cec5SDimitry Andric /// MatchableInfo - Helper class for storing the necessary information for an
3830b57cec5SDimitry Andric /// instruction or alias which is capable of being matched.
3840b57cec5SDimitry Andric struct MatchableInfo {
3850b57cec5SDimitry Andric   struct AsmOperand {
3860b57cec5SDimitry Andric     /// Token - This is the token that the operand came from.
3870b57cec5SDimitry Andric     StringRef Token;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric     /// The unique class instance this operand should match.
3900b57cec5SDimitry Andric     ClassInfo *Class;
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric     /// The operand name this is, if anything.
3930b57cec5SDimitry Andric     StringRef SrcOpName;
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric     /// The operand name this is, before renaming for tied operands.
3960b57cec5SDimitry Andric     StringRef OrigSrcOpName;
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric     /// The suboperand index within SrcOpName, or -1 for the entire operand.
3990b57cec5SDimitry Andric     int SubOpIdx;
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric     /// Whether the token is "isolated", i.e., it is preceded and followed
4020b57cec5SDimitry Andric     /// by separators.
4030b57cec5SDimitry Andric     bool IsIsolatedToken;
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric     /// Register record if this token is singleton register.
4060b57cec5SDimitry Andric     Record *SingletonReg;
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric     explicit AsmOperand(bool IsIsolatedToken, StringRef T)
4090b57cec5SDimitry Andric         : Token(T), Class(nullptr), SubOpIdx(-1),
4100b57cec5SDimitry Andric           IsIsolatedToken(IsIsolatedToken), SingletonReg(nullptr) {}
4110b57cec5SDimitry Andric   };
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   /// ResOperand - This represents a single operand in the result instruction
4140b57cec5SDimitry Andric   /// generated by the match.  In cases (like addressing modes) where a single
4150b57cec5SDimitry Andric   /// assembler operand expands to multiple MCOperands, this represents the
4160b57cec5SDimitry Andric   /// single assembler operand, not the MCOperand.
4170b57cec5SDimitry Andric   struct ResOperand {
4180b57cec5SDimitry Andric     enum {
4190b57cec5SDimitry Andric       /// RenderAsmOperand - This represents an operand result that is
4200b57cec5SDimitry Andric       /// generated by calling the render method on the assembly operand.  The
4210b57cec5SDimitry Andric       /// corresponding AsmOperand is specified by AsmOperandNum.
4220b57cec5SDimitry Andric       RenderAsmOperand,
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric       /// TiedOperand - This represents a result operand that is a duplicate of
4250b57cec5SDimitry Andric       /// a previous result operand.
4260b57cec5SDimitry Andric       TiedOperand,
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric       /// ImmOperand - This represents an immediate value that is dumped into
4290b57cec5SDimitry Andric       /// the operand.
4300b57cec5SDimitry Andric       ImmOperand,
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric       /// RegOperand - This represents a fixed register that is dumped in.
4330b57cec5SDimitry Andric       RegOperand
4340b57cec5SDimitry Andric     } Kind;
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric     /// Tuple containing the index of the (earlier) result operand that should
4370b57cec5SDimitry Andric     /// be copied from, as well as the indices of the corresponding (parsed)
4380b57cec5SDimitry Andric     /// operands in the asm string.
4390b57cec5SDimitry Andric     struct TiedOperandsTuple {
4400b57cec5SDimitry Andric       unsigned ResOpnd;
4410b57cec5SDimitry Andric       unsigned SrcOpnd1Idx;
4420b57cec5SDimitry Andric       unsigned SrcOpnd2Idx;
4430b57cec5SDimitry Andric     };
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric     union {
4460b57cec5SDimitry Andric       /// This is the operand # in the AsmOperands list that this should be
4470b57cec5SDimitry Andric       /// copied from.
4480b57cec5SDimitry Andric       unsigned AsmOperandNum;
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric       /// Description of tied operands.
4510b57cec5SDimitry Andric       TiedOperandsTuple TiedOperands;
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric       /// ImmVal - This is the immediate value added to the instruction.
4540b57cec5SDimitry Andric       int64_t ImmVal;
4550b57cec5SDimitry Andric 
4560b57cec5SDimitry Andric       /// Register - This is the register record.
4570b57cec5SDimitry Andric       Record *Register;
4580b57cec5SDimitry Andric     };
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric     /// MINumOperands - The number of MCInst operands populated by this
4610b57cec5SDimitry Andric     /// operand.
4620b57cec5SDimitry Andric     unsigned MINumOperands;
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric     static ResOperand getRenderedOp(unsigned AsmOpNum, unsigned NumOperands) {
4650b57cec5SDimitry Andric       ResOperand X;
4660b57cec5SDimitry Andric       X.Kind = RenderAsmOperand;
4670b57cec5SDimitry Andric       X.AsmOperandNum = AsmOpNum;
4680b57cec5SDimitry Andric       X.MINumOperands = NumOperands;
4690b57cec5SDimitry Andric       return X;
4700b57cec5SDimitry Andric     }
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric     static ResOperand getTiedOp(unsigned TiedOperandNum, unsigned SrcOperand1,
4730b57cec5SDimitry Andric                                 unsigned SrcOperand2) {
4740b57cec5SDimitry Andric       ResOperand X;
4750b57cec5SDimitry Andric       X.Kind = TiedOperand;
4760b57cec5SDimitry Andric       X.TiedOperands = {TiedOperandNum, SrcOperand1, SrcOperand2};
4770b57cec5SDimitry Andric       X.MINumOperands = 1;
4780b57cec5SDimitry Andric       return X;
4790b57cec5SDimitry Andric     }
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric     static ResOperand getImmOp(int64_t Val) {
4820b57cec5SDimitry Andric       ResOperand X;
4830b57cec5SDimitry Andric       X.Kind = ImmOperand;
4840b57cec5SDimitry Andric       X.ImmVal = Val;
4850b57cec5SDimitry Andric       X.MINumOperands = 1;
4860b57cec5SDimitry Andric       return X;
4870b57cec5SDimitry Andric     }
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric     static ResOperand getRegOp(Record *Reg) {
4900b57cec5SDimitry Andric       ResOperand X;
4910b57cec5SDimitry Andric       X.Kind = RegOperand;
4920b57cec5SDimitry Andric       X.Register = Reg;
4930b57cec5SDimitry Andric       X.MINumOperands = 1;
4940b57cec5SDimitry Andric       return X;
4950b57cec5SDimitry Andric     }
4960b57cec5SDimitry Andric   };
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric   /// AsmVariantID - Target's assembly syntax variant no.
4990b57cec5SDimitry Andric   int AsmVariantID;
5000b57cec5SDimitry Andric 
5010b57cec5SDimitry Andric   /// AsmString - The assembly string for this instruction (with variants
5020b57cec5SDimitry Andric   /// removed), e.g. "movsx $src, $dst".
5030b57cec5SDimitry Andric   std::string AsmString;
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric   /// TheDef - This is the definition of the instruction or InstAlias that this
5060b57cec5SDimitry Andric   /// matchable came from.
5070b57cec5SDimitry Andric   Record *const TheDef;
5080b57cec5SDimitry Andric 
509*0fca6ea1SDimitry Andric   // ResInstSize - The size of the resulting instruction for this matchable.
510*0fca6ea1SDimitry Andric   unsigned ResInstSize;
511*0fca6ea1SDimitry Andric 
5120b57cec5SDimitry Andric   /// DefRec - This is the definition that it came from.
5130b57cec5SDimitry Andric   PointerUnion<const CodeGenInstruction *, const CodeGenInstAlias *> DefRec;
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric   const CodeGenInstruction *getResultInst() const {
51606c3fb27SDimitry Andric     if (isa<const CodeGenInstruction *>(DefRec))
51706c3fb27SDimitry Andric       return cast<const CodeGenInstruction *>(DefRec);
51806c3fb27SDimitry Andric     return cast<const CodeGenInstAlias *>(DefRec)->ResultInst;
5190b57cec5SDimitry Andric   }
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric   /// ResOperands - This is the operand list that should be built for the result
5220b57cec5SDimitry Andric   /// MCInst.
5230b57cec5SDimitry Andric   SmallVector<ResOperand, 8> ResOperands;
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric   /// Mnemonic - This is the first token of the matched instruction, its
5260b57cec5SDimitry Andric   /// mnemonic.
5270b57cec5SDimitry Andric   StringRef Mnemonic;
5280b57cec5SDimitry Andric 
5290b57cec5SDimitry Andric   /// AsmOperands - The textual operands that this instruction matches,
5300b57cec5SDimitry Andric   /// annotated with a class and where in the OperandList they were defined.
5310b57cec5SDimitry Andric   /// This directly corresponds to the tokenized AsmString after the mnemonic is
5320b57cec5SDimitry Andric   /// removed.
5330b57cec5SDimitry Andric   SmallVector<AsmOperand, 8> AsmOperands;
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   /// Predicates - The required subtarget features to match this instruction.
5360b57cec5SDimitry Andric   SmallVector<const SubtargetFeatureInfo *, 4> RequiredFeatures;
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric   /// ConversionFnKind - The enum value which is passed to the generated
5390b57cec5SDimitry Andric   /// convertToMCInst to convert parsed operands into an MCInst for this
5400b57cec5SDimitry Andric   /// function.
5410b57cec5SDimitry Andric   std::string ConversionFnKind;
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric   /// If this instruction is deprecated in some form.
54406c3fb27SDimitry Andric   bool HasDeprecation = false;
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric   /// If this is an alias, this is use to determine whether or not to using
5470b57cec5SDimitry Andric   /// the conversion function defined by the instruction's AsmMatchConverter
5480b57cec5SDimitry Andric   /// or to use the function generated by the alias.
5490b57cec5SDimitry Andric   bool UseInstAsmMatchConverter;
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric   MatchableInfo(const CodeGenInstruction &CGI)
552*0fca6ea1SDimitry Andric       : AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef),
553*0fca6ea1SDimitry Andric         ResInstSize(TheDef->getValueAsInt("Size")), DefRec(&CGI),
554*0fca6ea1SDimitry Andric         UseInstAsmMatchConverter(true) {}
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric   MatchableInfo(std::unique_ptr<const CodeGenInstAlias> Alias)
5570b57cec5SDimitry Andric       : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef),
558*0fca6ea1SDimitry Andric         ResInstSize(Alias->ResultInst->TheDef->getValueAsInt("Size")),
559*0fca6ea1SDimitry Andric         DefRec(Alias.release()), UseInstAsmMatchConverter(TheDef->getValueAsBit(
560*0fca6ea1SDimitry Andric                                      "UseInstAsmMatchConverter")) {}
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric   // Could remove this and the dtor if PointerUnion supported unique_ptr
5630b57cec5SDimitry Andric   // elements with a dynamic failure/assertion (like the one below) in the case
5640b57cec5SDimitry Andric   // where it was copied while being in an owning state.
5650b57cec5SDimitry Andric   MatchableInfo(const MatchableInfo &RHS)
5660b57cec5SDimitry Andric       : AsmVariantID(RHS.AsmVariantID), AsmString(RHS.AsmString),
567*0fca6ea1SDimitry Andric         TheDef(RHS.TheDef), ResInstSize(RHS.ResInstSize), DefRec(RHS.DefRec),
568*0fca6ea1SDimitry Andric         ResOperands(RHS.ResOperands), Mnemonic(RHS.Mnemonic),
569*0fca6ea1SDimitry Andric         AsmOperands(RHS.AsmOperands), RequiredFeatures(RHS.RequiredFeatures),
5700b57cec5SDimitry Andric         ConversionFnKind(RHS.ConversionFnKind),
5710b57cec5SDimitry Andric         HasDeprecation(RHS.HasDeprecation),
5720b57cec5SDimitry Andric         UseInstAsmMatchConverter(RHS.UseInstAsmMatchConverter) {
57306c3fb27SDimitry Andric     assert(!isa<const CodeGenInstAlias *>(DefRec));
5740b57cec5SDimitry Andric   }
5750b57cec5SDimitry Andric 
5760b57cec5SDimitry Andric   ~MatchableInfo() {
57706c3fb27SDimitry Andric     delete dyn_cast_if_present<const CodeGenInstAlias *>(DefRec);
5780b57cec5SDimitry Andric   }
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   // Two-operand aliases clone from the main matchable, but mark the second
5810b57cec5SDimitry Andric   // operand as a tied operand of the first for purposes of the assembler.
5820b57cec5SDimitry Andric   void formTwoOperandAlias(StringRef Constraint);
5830b57cec5SDimitry Andric 
5840b57cec5SDimitry Andric   void initialize(const AsmMatcherInfo &Info,
5850b57cec5SDimitry Andric                   SmallPtrSetImpl<Record *> &SingletonRegisters,
586*0fca6ea1SDimitry Andric                   AsmVariantInfo const &Variant, bool HasMnemonicFirst);
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric   /// validate - Return true if this matchable is a valid thing to match against
5890b57cec5SDimitry Andric   /// and perform a bunch of validity checking.
5900b57cec5SDimitry Andric   bool validate(StringRef CommentDelimiter, bool IsAlias) const;
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric   /// findAsmOperand - Find the AsmOperand with the specified name and
5930b57cec5SDimitry Andric   /// suboperand index.
5940b57cec5SDimitry Andric   int findAsmOperand(StringRef N, int SubOpIdx) const {
5950b57cec5SDimitry Andric     auto I = find_if(AsmOperands, [&](const AsmOperand &Op) {
5960b57cec5SDimitry Andric       return Op.SrcOpName == N && Op.SubOpIdx == SubOpIdx;
5970b57cec5SDimitry Andric     });
5980b57cec5SDimitry Andric     return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1;
5990b57cec5SDimitry Andric   }
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric   /// findAsmOperandNamed - Find the first AsmOperand with the specified name.
6020b57cec5SDimitry Andric   /// This does not check the suboperand index.
6030b57cec5SDimitry Andric   int findAsmOperandNamed(StringRef N, int LastIdx = -1) const {
604bdd1243dSDimitry Andric     auto I =
605bdd1243dSDimitry Andric         llvm::find_if(llvm::drop_begin(AsmOperands, LastIdx + 1),
6060b57cec5SDimitry Andric                       [&](const AsmOperand &Op) { return Op.SrcOpName == N; });
6070b57cec5SDimitry Andric     return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1;
6080b57cec5SDimitry Andric   }
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   int findAsmOperandOriginallyNamed(StringRef N) const {
611*0fca6ea1SDimitry Andric     auto I = find_if(AsmOperands, [&](const AsmOperand &Op) {
612*0fca6ea1SDimitry Andric       return Op.OrigSrcOpName == N;
613*0fca6ea1SDimitry Andric     });
6140b57cec5SDimitry Andric     return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1;
6150b57cec5SDimitry Andric   }
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric   void buildInstructionResultOperands();
6180b57cec5SDimitry Andric   void buildAliasResultOperands(bool AliasConstraintsAreChecked);
6190b57cec5SDimitry Andric 
620*0fca6ea1SDimitry Andric   /// shouldBeMatchedBefore - Compare two matchables for ordering.
621*0fca6ea1SDimitry Andric   bool shouldBeMatchedBefore(const MatchableInfo &RHS,
622*0fca6ea1SDimitry Andric                              bool PreferSmallerInstructions) const {
6230b57cec5SDimitry Andric     // The primary comparator is the instruction mnemonic.
624fe6060f1SDimitry Andric     if (int Cmp = Mnemonic.compare_insensitive(RHS.Mnemonic))
6250b57cec5SDimitry Andric       return Cmp == -1;
6260b57cec5SDimitry Andric 
627*0fca6ea1SDimitry Andric     // (Optionally) Order by the resultant instuctions size.
628*0fca6ea1SDimitry Andric     // eg. for ARM thumb instructions smaller encodings should be preferred.
629*0fca6ea1SDimitry Andric     if (PreferSmallerInstructions && ResInstSize != RHS.ResInstSize)
630*0fca6ea1SDimitry Andric       return ResInstSize < RHS.ResInstSize;
631*0fca6ea1SDimitry Andric 
6320b57cec5SDimitry Andric     if (AsmOperands.size() != RHS.AsmOperands.size())
6330b57cec5SDimitry Andric       return AsmOperands.size() < RHS.AsmOperands.size();
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric     // Compare lexicographically by operand. The matcher validates that other
6360b57cec5SDimitry Andric     // orderings wouldn't be ambiguous using \see couldMatchAmbiguouslyWith().
6370b57cec5SDimitry Andric     for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
6380b57cec5SDimitry Andric       if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class)
6390b57cec5SDimitry Andric         return true;
6400b57cec5SDimitry Andric       if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class)
6410b57cec5SDimitry Andric         return false;
6420b57cec5SDimitry Andric     }
6430b57cec5SDimitry Andric 
64406c3fb27SDimitry Andric     // For X86 AVX/AVX512 instructions, we prefer vex encoding because the
64506c3fb27SDimitry Andric     // vex encoding size is smaller. Since X86InstrSSE.td is included ahead
64606c3fb27SDimitry Andric     // of X86InstrAVX512.td, the AVX instruction ID is less than AVX512 ID.
64706c3fb27SDimitry Andric     // We use the ID to sort AVX instruction before AVX512 instruction in
648*0fca6ea1SDimitry Andric     // matching table. As well as InstAlias.
649*0fca6ea1SDimitry Andric     if (getResultInst()->TheDef->isSubClassOf("Instruction") &&
650*0fca6ea1SDimitry Andric         getResultInst()->TheDef->getValueAsBit("HasPositionOrder") &&
651*0fca6ea1SDimitry Andric         RHS.getResultInst()->TheDef->isSubClassOf("Instruction") &&
652*0fca6ea1SDimitry Andric         RHS.getResultInst()->TheDef->getValueAsBit("HasPositionOrder"))
653*0fca6ea1SDimitry Andric       return getResultInst()->TheDef->getID() <
654*0fca6ea1SDimitry Andric              RHS.getResultInst()->TheDef->getID();
65506c3fb27SDimitry Andric 
6560b57cec5SDimitry Andric     // Give matches that require more features higher precedence. This is useful
6570b57cec5SDimitry Andric     // because we cannot define AssemblerPredicates with the negation of
6580b57cec5SDimitry Andric     // processor features. For example, ARM v6 "nop" may be either a HINT or
6590b57cec5SDimitry Andric     // MOV. With v6, we want to match HINT. The assembler has no way to
6600b57cec5SDimitry Andric     // predicate MOV under "NoV6", but HINT will always match first because it
6610b57cec5SDimitry Andric     // requires V6 while MOV does not.
6620b57cec5SDimitry Andric     if (RequiredFeatures.size() != RHS.RequiredFeatures.size())
6630b57cec5SDimitry Andric       return RequiredFeatures.size() > RHS.RequiredFeatures.size();
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric     return false;
6660b57cec5SDimitry Andric   }
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric   /// couldMatchAmbiguouslyWith - Check whether this matchable could
6690b57cec5SDimitry Andric   /// ambiguously match the same set of operands as \p RHS (without being a
6700b57cec5SDimitry Andric   /// strictly superior match).
671*0fca6ea1SDimitry Andric   bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS,
672*0fca6ea1SDimitry Andric                                  bool PreferSmallerInstructions) const {
6730b57cec5SDimitry Andric     // The primary comparator is the instruction mnemonic.
6740b57cec5SDimitry Andric     if (Mnemonic != RHS.Mnemonic)
6750b57cec5SDimitry Andric       return false;
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric     // Different variants can't conflict.
6780b57cec5SDimitry Andric     if (AsmVariantID != RHS.AsmVariantID)
6790b57cec5SDimitry Andric       return false;
6800b57cec5SDimitry Andric 
681*0fca6ea1SDimitry Andric     // The size of instruction is unambiguous.
682*0fca6ea1SDimitry Andric     if (PreferSmallerInstructions && ResInstSize != RHS.ResInstSize)
683*0fca6ea1SDimitry Andric       return false;
684*0fca6ea1SDimitry Andric 
6850b57cec5SDimitry Andric     // The number of operands is unambiguous.
6860b57cec5SDimitry Andric     if (AsmOperands.size() != RHS.AsmOperands.size())
6870b57cec5SDimitry Andric       return false;
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric     // Otherwise, make sure the ordering of the two instructions is unambiguous
6900b57cec5SDimitry Andric     // by checking that either (a) a token or operand kind discriminates them,
6910b57cec5SDimitry Andric     // or (b) the ordering among equivalent kinds is consistent.
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric     // Tokens and operand kinds are unambiguous (assuming a correct target
6940b57cec5SDimitry Andric     // specific parser).
6950b57cec5SDimitry Andric     for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i)
6960b57cec5SDimitry Andric       if (AsmOperands[i].Class->Kind != RHS.AsmOperands[i].Class->Kind ||
6970b57cec5SDimitry Andric           AsmOperands[i].Class->Kind == ClassInfo::Token)
6980b57cec5SDimitry Andric         if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class ||
6990b57cec5SDimitry Andric             *RHS.AsmOperands[i].Class < *AsmOperands[i].Class)
7000b57cec5SDimitry Andric           return false;
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric     // Otherwise, this operand could commute if all operands are equivalent, or
7030b57cec5SDimitry Andric     // there is a pair of operands that compare less than and a pair that
7040b57cec5SDimitry Andric     // compare greater than.
7050b57cec5SDimitry Andric     bool HasLT = false, HasGT = false;
7060b57cec5SDimitry Andric     for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
7070b57cec5SDimitry Andric       if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class)
7080b57cec5SDimitry Andric         HasLT = true;
7090b57cec5SDimitry Andric       if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class)
7100b57cec5SDimitry Andric         HasGT = true;
7110b57cec5SDimitry Andric     }
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric     return HasLT == HasGT;
7140b57cec5SDimitry Andric   }
7150b57cec5SDimitry Andric 
7160b57cec5SDimitry Andric   void dump() const;
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric private:
7190b57cec5SDimitry Andric   void tokenizeAsmString(AsmMatcherInfo const &Info,
7200b57cec5SDimitry Andric                          AsmVariantInfo const &Variant);
7210b57cec5SDimitry Andric   void addAsmOperand(StringRef Token, bool IsIsolatedToken = false);
7220b57cec5SDimitry Andric };
7230b57cec5SDimitry Andric 
7240b57cec5SDimitry Andric struct OperandMatchEntry {
7250b57cec5SDimitry Andric   unsigned OperandMask;
7260b57cec5SDimitry Andric   const MatchableInfo *MI;
7270b57cec5SDimitry Andric   ClassInfo *CI;
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric   static OperandMatchEntry create(const MatchableInfo *mi, ClassInfo *ci,
7300b57cec5SDimitry Andric                                   unsigned opMask) {
7310b57cec5SDimitry Andric     OperandMatchEntry X;
7320b57cec5SDimitry Andric     X.OperandMask = opMask;
7330b57cec5SDimitry Andric     X.CI = ci;
7340b57cec5SDimitry Andric     X.MI = mi;
7350b57cec5SDimitry Andric     return X;
7360b57cec5SDimitry Andric   }
7370b57cec5SDimitry Andric };
7380b57cec5SDimitry Andric 
7390b57cec5SDimitry Andric class AsmMatcherInfo {
7400b57cec5SDimitry Andric public:
7410b57cec5SDimitry Andric   /// Tracked Records
7420b57cec5SDimitry Andric   RecordKeeper &Records;
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric   /// The tablegen AsmParser record.
7450b57cec5SDimitry Andric   Record *AsmParser;
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric   /// Target - The target information.
7480b57cec5SDimitry Andric   CodeGenTarget &Target;
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric   /// The classes which are needed for matching.
7510b57cec5SDimitry Andric   std::forward_list<ClassInfo> Classes;
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric   /// The information on the matchables to match.
7540b57cec5SDimitry Andric   std::vector<std::unique_ptr<MatchableInfo>> Matchables;
7550b57cec5SDimitry Andric 
7560b57cec5SDimitry Andric   /// Info for custom matching operands by user defined methods.
7570b57cec5SDimitry Andric   std::vector<OperandMatchEntry> OperandMatchInfo;
7580b57cec5SDimitry Andric 
7590b57cec5SDimitry Andric   /// Map of Register records to their class information.
7600b57cec5SDimitry Andric   typedef std::map<Record *, ClassInfo *, LessRecordByID> RegisterClassesTy;
7610b57cec5SDimitry Andric   RegisterClassesTy RegisterClasses;
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric   /// Map of Predicate records to their subtarget information.
7640b57cec5SDimitry Andric   std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric   /// Map of AsmOperandClass records to their class information.
7670b57cec5SDimitry Andric   std::map<Record *, ClassInfo *> AsmOperandClasses;
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric   /// Map of RegisterClass records to their class information.
7700b57cec5SDimitry Andric   std::map<Record *, ClassInfo *> RegisterClassClasses;
7710b57cec5SDimitry Andric 
7720b57cec5SDimitry Andric private:
7730b57cec5SDimitry Andric   /// Map of token to class information which has already been constructed.
7740b57cec5SDimitry Andric   std::map<std::string, ClassInfo *> TokenClasses;
7750b57cec5SDimitry Andric 
7760b57cec5SDimitry Andric private:
7770b57cec5SDimitry Andric   /// getTokenClass - Lookup or create the class for the given token.
7780b57cec5SDimitry Andric   ClassInfo *getTokenClass(StringRef Token);
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric   /// getOperandClass - Lookup or create the class for the given operand.
7810b57cec5SDimitry Andric   ClassInfo *getOperandClass(const CGIOperandList::OperandInfo &OI,
7820b57cec5SDimitry Andric                              int SubOpIdx);
7830b57cec5SDimitry Andric   ClassInfo *getOperandClass(Record *Rec, int SubOpIdx);
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric   /// buildRegisterClasses - Build the ClassInfo* instances for register
7860b57cec5SDimitry Andric   /// classes.
7870b57cec5SDimitry Andric   void buildRegisterClasses(SmallPtrSetImpl<Record *> &SingletonRegisters);
7880b57cec5SDimitry Andric 
7890b57cec5SDimitry Andric   /// buildOperandClasses - Build the ClassInfo* instances for user defined
7900b57cec5SDimitry Andric   /// operand classes.
7910b57cec5SDimitry Andric   void buildOperandClasses();
7920b57cec5SDimitry Andric 
7930b57cec5SDimitry Andric   void buildInstructionOperandReference(MatchableInfo *II, StringRef OpName,
7940b57cec5SDimitry Andric                                         unsigned AsmOpIdx);
7950b57cec5SDimitry Andric   void buildAliasOperandReference(MatchableInfo *II, StringRef OpName,
7960b57cec5SDimitry Andric                                   MatchableInfo::AsmOperand &Op);
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric public:
799*0fca6ea1SDimitry Andric   AsmMatcherInfo(Record *AsmParser, CodeGenTarget &Target,
8000b57cec5SDimitry Andric                  RecordKeeper &Records);
8010b57cec5SDimitry Andric 
8020b57cec5SDimitry Andric   /// Construct the various tables used during matching.
8030b57cec5SDimitry Andric   void buildInfo();
8040b57cec5SDimitry Andric 
8050b57cec5SDimitry Andric   /// buildOperandMatchInfo - Build the necessary information to handle user
8060b57cec5SDimitry Andric   /// defined operand parsing methods.
8070b57cec5SDimitry Andric   void buildOperandMatchInfo();
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric   /// getSubtargetFeature - Lookup or create the subtarget feature info for the
8100b57cec5SDimitry Andric   /// given operand.
8110b57cec5SDimitry Andric   const SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const {
8120b57cec5SDimitry Andric     assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!");
8130b57cec5SDimitry Andric     const auto &I = SubtargetFeatures.find(Def);
8140b57cec5SDimitry Andric     return I == SubtargetFeatures.end() ? nullptr : &I->second;
8150b57cec5SDimitry Andric   }
8160b57cec5SDimitry Andric 
817*0fca6ea1SDimitry Andric   RecordKeeper &getRecords() const { return Records; }
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric   bool hasOptionalOperands() const {
820e8d8bef9SDimitry Andric     return any_of(Classes,
821e8d8bef9SDimitry Andric                   [](const ClassInfo &Class) { return Class.IsOptional; });
8220b57cec5SDimitry Andric   }
8230b57cec5SDimitry Andric };
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric } // end anonymous namespace
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
8280b57cec5SDimitry Andric LLVM_DUMP_METHOD void MatchableInfo::dump() const {
829*0fca6ea1SDimitry Andric   errs() << TheDef->getName() << " -- "
830*0fca6ea1SDimitry Andric          << "flattened:\"" << AsmString << "\"\n";
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric   errs() << "  variant: " << AsmVariantID << "\n";
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric   for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
8350b57cec5SDimitry Andric     const AsmOperand &Op = AsmOperands[i];
8360b57cec5SDimitry Andric     errs() << "  op[" << i << "] = " << Op.Class->ClassName << " - ";
8370b57cec5SDimitry Andric     errs() << '\"' << Op.Token << "\"\n";
8380b57cec5SDimitry Andric   }
8390b57cec5SDimitry Andric }
8400b57cec5SDimitry Andric #endif
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric static std::pair<StringRef, StringRef>
8430b57cec5SDimitry Andric parseTwoOperandConstraint(StringRef S, ArrayRef<SMLoc> Loc) {
8440b57cec5SDimitry Andric   // Split via the '='.
8450b57cec5SDimitry Andric   std::pair<StringRef, StringRef> Ops = S.split('=');
8460b57cec5SDimitry Andric   if (Ops.second == "")
8470b57cec5SDimitry Andric     PrintFatalError(Loc, "missing '=' in two-operand alias constraint");
8480b57cec5SDimitry Andric   // Trim whitespace and the leading '$' on the operand names.
8490b57cec5SDimitry Andric   size_t start = Ops.first.find_first_of('$');
8500b57cec5SDimitry Andric   if (start == std::string::npos)
8510b57cec5SDimitry Andric     PrintFatalError(Loc, "expected '$' prefix on asm operand name");
8520b57cec5SDimitry Andric   Ops.first = Ops.first.slice(start + 1, std::string::npos);
8530b57cec5SDimitry Andric   size_t end = Ops.first.find_last_of(" \t");
8540b57cec5SDimitry Andric   Ops.first = Ops.first.slice(0, end);
8550b57cec5SDimitry Andric   // Now the second operand.
8560b57cec5SDimitry Andric   start = Ops.second.find_first_of('$');
8570b57cec5SDimitry Andric   if (start == std::string::npos)
8580b57cec5SDimitry Andric     PrintFatalError(Loc, "expected '$' prefix on asm operand name");
8590b57cec5SDimitry Andric   Ops.second = Ops.second.slice(start + 1, std::string::npos);
8600b57cec5SDimitry Andric   end = Ops.second.find_last_of(" \t");
8610b57cec5SDimitry Andric   Ops.first = Ops.first.slice(0, end);
8620b57cec5SDimitry Andric   return Ops;
8630b57cec5SDimitry Andric }
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric void MatchableInfo::formTwoOperandAlias(StringRef Constraint) {
8660b57cec5SDimitry Andric   // Figure out which operands are aliased and mark them as tied.
8670b57cec5SDimitry Andric   std::pair<StringRef, StringRef> Ops =
8680b57cec5SDimitry Andric       parseTwoOperandConstraint(Constraint, TheDef->getLoc());
8690b57cec5SDimitry Andric 
8700b57cec5SDimitry Andric   // Find the AsmOperands that refer to the operands we're aliasing.
8710b57cec5SDimitry Andric   int SrcAsmOperand = findAsmOperandNamed(Ops.first);
8720b57cec5SDimitry Andric   int DstAsmOperand = findAsmOperandNamed(Ops.second);
8730b57cec5SDimitry Andric   if (SrcAsmOperand == -1)
8740b57cec5SDimitry Andric     PrintFatalError(TheDef->getLoc(),
8750b57cec5SDimitry Andric                     "unknown source two-operand alias operand '" + Ops.first +
8760b57cec5SDimitry Andric                         "'.");
8770b57cec5SDimitry Andric   if (DstAsmOperand == -1)
8780b57cec5SDimitry Andric     PrintFatalError(TheDef->getLoc(),
8790b57cec5SDimitry Andric                     "unknown destination two-operand alias operand '" +
8800b57cec5SDimitry Andric                         Ops.second + "'.");
8810b57cec5SDimitry Andric 
8820b57cec5SDimitry Andric   // Find the ResOperand that refers to the operand we're aliasing away
8830b57cec5SDimitry Andric   // and update it to refer to the combined operand instead.
8840b57cec5SDimitry Andric   for (ResOperand &Op : ResOperands) {
8850b57cec5SDimitry Andric     if (Op.Kind == ResOperand::RenderAsmOperand &&
8860b57cec5SDimitry Andric         Op.AsmOperandNum == (unsigned)SrcAsmOperand) {
8870b57cec5SDimitry Andric       Op.AsmOperandNum = DstAsmOperand;
8880b57cec5SDimitry Andric       break;
8890b57cec5SDimitry Andric     }
8900b57cec5SDimitry Andric   }
8910b57cec5SDimitry Andric   // Remove the AsmOperand for the alias operand.
8920b57cec5SDimitry Andric   AsmOperands.erase(AsmOperands.begin() + SrcAsmOperand);
8930b57cec5SDimitry Andric   // Adjust the ResOperand references to any AsmOperands that followed
8940b57cec5SDimitry Andric   // the one we just deleted.
8950b57cec5SDimitry Andric   for (ResOperand &Op : ResOperands) {
8960b57cec5SDimitry Andric     switch (Op.Kind) {
8970b57cec5SDimitry Andric     default:
8980b57cec5SDimitry Andric       // Nothing to do for operands that don't reference AsmOperands.
8990b57cec5SDimitry Andric       break;
9000b57cec5SDimitry Andric     case ResOperand::RenderAsmOperand:
9010b57cec5SDimitry Andric       if (Op.AsmOperandNum > (unsigned)SrcAsmOperand)
9020b57cec5SDimitry Andric         --Op.AsmOperandNum;
9030b57cec5SDimitry Andric       break;
9040b57cec5SDimitry Andric     }
9050b57cec5SDimitry Andric   }
9060b57cec5SDimitry Andric }
9070b57cec5SDimitry Andric 
9080b57cec5SDimitry Andric /// extractSingletonRegisterForAsmOperand - Extract singleton register,
9090b57cec5SDimitry Andric /// if present, from specified token.
910*0fca6ea1SDimitry Andric static void extractSingletonRegisterForAsmOperand(MatchableInfo::AsmOperand &Op,
9110b57cec5SDimitry Andric                                                   const AsmMatcherInfo &Info,
9120b57cec5SDimitry Andric                                                   StringRef RegisterPrefix) {
9130b57cec5SDimitry Andric   StringRef Tok = Op.Token;
9140b57cec5SDimitry Andric 
9150b57cec5SDimitry Andric   // If this token is not an isolated token, i.e., it isn't separated from
9160b57cec5SDimitry Andric   // other tokens (e.g. with whitespace), don't interpret it as a register name.
9170b57cec5SDimitry Andric   if (!Op.IsIsolatedToken)
9180b57cec5SDimitry Andric     return;
9190b57cec5SDimitry Andric 
9200b57cec5SDimitry Andric   if (RegisterPrefix.empty()) {
9210b57cec5SDimitry Andric     std::string LoweredTok = Tok.lower();
9220b57cec5SDimitry Andric     if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(LoweredTok))
9230b57cec5SDimitry Andric       Op.SingletonReg = Reg->TheDef;
9240b57cec5SDimitry Andric     return;
9250b57cec5SDimitry Andric   }
9260b57cec5SDimitry Andric 
9275f757f3fSDimitry Andric   if (!Tok.starts_with(RegisterPrefix))
9280b57cec5SDimitry Andric     return;
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric   StringRef RegName = Tok.substr(RegisterPrefix.size());
9310b57cec5SDimitry Andric   if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName))
9320b57cec5SDimitry Andric     Op.SingletonReg = Reg->TheDef;
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric   // If there is no register prefix (i.e. "%" in "%eax"), then this may
9350b57cec5SDimitry Andric   // be some random non-register token, just ignore it.
9360b57cec5SDimitry Andric }
9370b57cec5SDimitry Andric 
9380b57cec5SDimitry Andric void MatchableInfo::initialize(const AsmMatcherInfo &Info,
9390b57cec5SDimitry Andric                                SmallPtrSetImpl<Record *> &SingletonRegisters,
9400b57cec5SDimitry Andric                                AsmVariantInfo const &Variant,
9410b57cec5SDimitry Andric                                bool HasMnemonicFirst) {
9420b57cec5SDimitry Andric   AsmVariantID = Variant.AsmVariantNo;
943*0fca6ea1SDimitry Andric   AsmString = CodeGenInstruction::FlattenAsmStringVariants(
944*0fca6ea1SDimitry Andric       AsmString, Variant.AsmVariantNo);
9450b57cec5SDimitry Andric 
9460b57cec5SDimitry Andric   tokenizeAsmString(Info, Variant);
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric   // The first token of the instruction is the mnemonic, which must be a
9490b57cec5SDimitry Andric   // simple string, not a $foo variable or a singleton register.
9500b57cec5SDimitry Andric   if (AsmOperands.empty())
9510b57cec5SDimitry Andric     PrintFatalError(TheDef->getLoc(),
9520b57cec5SDimitry Andric                     "Instruction '" + TheDef->getName() + "' has no tokens");
9530b57cec5SDimitry Andric 
9540b57cec5SDimitry Andric   assert(!AsmOperands[0].Token.empty());
9550b57cec5SDimitry Andric   if (HasMnemonicFirst) {
9560b57cec5SDimitry Andric     Mnemonic = AsmOperands[0].Token;
9570b57cec5SDimitry Andric     if (Mnemonic[0] == '$')
9580b57cec5SDimitry Andric       PrintFatalError(TheDef->getLoc(),
9590b57cec5SDimitry Andric                       "Invalid instruction mnemonic '" + Mnemonic + "'!");
9600b57cec5SDimitry Andric 
9610b57cec5SDimitry Andric     // Remove the first operand, it is tracked in the mnemonic field.
9620b57cec5SDimitry Andric     AsmOperands.erase(AsmOperands.begin());
9630b57cec5SDimitry Andric   } else if (AsmOperands[0].Token[0] != '$')
9640b57cec5SDimitry Andric     Mnemonic = AsmOperands[0].Token;
9650b57cec5SDimitry Andric 
9660b57cec5SDimitry Andric   // Compute the require features.
9670b57cec5SDimitry Andric   for (Record *Predicate : TheDef->getValueAsListOfDefs("Predicates"))
9680b57cec5SDimitry Andric     if (const SubtargetFeatureInfo *Feature =
9690b57cec5SDimitry Andric             Info.getSubtargetFeature(Predicate))
9700b57cec5SDimitry Andric       RequiredFeatures.push_back(Feature);
9710b57cec5SDimitry Andric 
9720b57cec5SDimitry Andric   // Collect singleton registers, if used.
9730b57cec5SDimitry Andric   for (MatchableInfo::AsmOperand &Op : AsmOperands) {
9740b57cec5SDimitry Andric     extractSingletonRegisterForAsmOperand(Op, Info, Variant.RegisterPrefix);
9750b57cec5SDimitry Andric     if (Record *Reg = Op.SingletonReg)
9760b57cec5SDimitry Andric       SingletonRegisters.insert(Reg);
9770b57cec5SDimitry Andric   }
9780b57cec5SDimitry Andric 
9790b57cec5SDimitry Andric   const RecordVal *DepMask = TheDef->getValue("DeprecatedFeatureMask");
9800b57cec5SDimitry Andric   if (!DepMask)
9810b57cec5SDimitry Andric     DepMask = TheDef->getValue("ComplexDeprecationPredicate");
9820b57cec5SDimitry Andric 
9830b57cec5SDimitry Andric   HasDeprecation =
9840b57cec5SDimitry Andric       DepMask ? !DepMask->getValue()->getAsUnquotedString().empty() : false;
9850b57cec5SDimitry Andric }
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric /// Append an AsmOperand for the given substring of AsmString.
9880b57cec5SDimitry Andric void MatchableInfo::addAsmOperand(StringRef Token, bool IsIsolatedToken) {
9890b57cec5SDimitry Andric   AsmOperands.push_back(AsmOperand(IsIsolatedToken, Token));
9900b57cec5SDimitry Andric }
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric /// tokenizeAsmString - Tokenize a simplified assembly string.
9930b57cec5SDimitry Andric void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info,
9940b57cec5SDimitry Andric                                       AsmVariantInfo const &Variant) {
9950b57cec5SDimitry Andric   StringRef String = AsmString;
9960b57cec5SDimitry Andric   size_t Prev = 0;
9970b57cec5SDimitry Andric   bool InTok = false;
9980b57cec5SDimitry Andric   bool IsIsolatedToken = true;
9990b57cec5SDimitry Andric   for (size_t i = 0, e = String.size(); i != e; ++i) {
10000b57cec5SDimitry Andric     char Char = String[i];
1001cb14a3feSDimitry Andric     if (Variant.BreakCharacters.contains(Char)) {
10020b57cec5SDimitry Andric       if (InTok) {
10030b57cec5SDimitry Andric         addAsmOperand(String.slice(Prev, i), false);
10040b57cec5SDimitry Andric         Prev = i;
10050b57cec5SDimitry Andric         IsIsolatedToken = false;
10060b57cec5SDimitry Andric       }
10070b57cec5SDimitry Andric       InTok = true;
10080b57cec5SDimitry Andric       continue;
10090b57cec5SDimitry Andric     }
1010cb14a3feSDimitry Andric     if (Variant.TokenizingCharacters.contains(Char)) {
10110b57cec5SDimitry Andric       if (InTok) {
10120b57cec5SDimitry Andric         addAsmOperand(String.slice(Prev, i), IsIsolatedToken);
10130b57cec5SDimitry Andric         InTok = false;
10140b57cec5SDimitry Andric         IsIsolatedToken = false;
10150b57cec5SDimitry Andric       }
10160b57cec5SDimitry Andric       addAsmOperand(String.slice(i, i + 1), IsIsolatedToken);
10170b57cec5SDimitry Andric       Prev = i + 1;
10180b57cec5SDimitry Andric       IsIsolatedToken = true;
10190b57cec5SDimitry Andric       continue;
10200b57cec5SDimitry Andric     }
1021cb14a3feSDimitry Andric     if (Variant.SeparatorCharacters.contains(Char)) {
10220b57cec5SDimitry Andric       if (InTok) {
10230b57cec5SDimitry Andric         addAsmOperand(String.slice(Prev, i), IsIsolatedToken);
10240b57cec5SDimitry Andric         InTok = false;
10250b57cec5SDimitry Andric       }
10260b57cec5SDimitry Andric       Prev = i + 1;
10270b57cec5SDimitry Andric       IsIsolatedToken = true;
10280b57cec5SDimitry Andric       continue;
10290b57cec5SDimitry Andric     }
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric     switch (Char) {
10320b57cec5SDimitry Andric     case '\\':
10330b57cec5SDimitry Andric       if (InTok) {
10340b57cec5SDimitry Andric         addAsmOperand(String.slice(Prev, i), false);
10350b57cec5SDimitry Andric         InTok = false;
10360b57cec5SDimitry Andric         IsIsolatedToken = false;
10370b57cec5SDimitry Andric       }
10380b57cec5SDimitry Andric       ++i;
10390b57cec5SDimitry Andric       assert(i != String.size() && "Invalid quoted character");
10400b57cec5SDimitry Andric       addAsmOperand(String.slice(i, i + 1), IsIsolatedToken);
10410b57cec5SDimitry Andric       Prev = i + 1;
10420b57cec5SDimitry Andric       IsIsolatedToken = false;
10430b57cec5SDimitry Andric       break;
10440b57cec5SDimitry Andric 
10450b57cec5SDimitry Andric     case '$': {
10460b57cec5SDimitry Andric       if (InTok) {
1047e8d8bef9SDimitry Andric         addAsmOperand(String.slice(Prev, i), IsIsolatedToken);
10480b57cec5SDimitry Andric         InTok = false;
10490b57cec5SDimitry Andric         IsIsolatedToken = false;
10500b57cec5SDimitry Andric       }
10510b57cec5SDimitry Andric 
10520b57cec5SDimitry Andric       // If this isn't "${", start new identifier looking like "$xxx"
10530b57cec5SDimitry Andric       if (i + 1 == String.size() || String[i + 1] != '{') {
10540b57cec5SDimitry Andric         Prev = i;
10550b57cec5SDimitry Andric         break;
10560b57cec5SDimitry Andric       }
10570b57cec5SDimitry Andric 
10580b57cec5SDimitry Andric       size_t EndPos = String.find('}', i);
10590b57cec5SDimitry Andric       assert(EndPos != StringRef::npos &&
10600b57cec5SDimitry Andric              "Missing brace in operand reference!");
10610b57cec5SDimitry Andric       addAsmOperand(String.slice(i, EndPos + 1), IsIsolatedToken);
10620b57cec5SDimitry Andric       Prev = EndPos + 1;
10630b57cec5SDimitry Andric       i = EndPos;
10640b57cec5SDimitry Andric       IsIsolatedToken = false;
10650b57cec5SDimitry Andric       break;
10660b57cec5SDimitry Andric     }
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric     default:
10690b57cec5SDimitry Andric       InTok = true;
10700b57cec5SDimitry Andric       break;
10710b57cec5SDimitry Andric     }
10720b57cec5SDimitry Andric   }
10730b57cec5SDimitry Andric   if (InTok && Prev != String.size())
10740b57cec5SDimitry Andric     addAsmOperand(String.substr(Prev), IsIsolatedToken);
10750b57cec5SDimitry Andric }
10760b57cec5SDimitry Andric 
10770b57cec5SDimitry Andric bool MatchableInfo::validate(StringRef CommentDelimiter, bool IsAlias) const {
10780b57cec5SDimitry Andric   // Reject matchables with no .s string.
10790b57cec5SDimitry Andric   if (AsmString.empty())
10800b57cec5SDimitry Andric     PrintFatalError(TheDef->getLoc(), "instruction with empty asm string");
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric   // Reject any matchables with a newline in them, they should be marked
10830b57cec5SDimitry Andric   // isCodeGenOnly if they are pseudo instructions.
10840b57cec5SDimitry Andric   if (AsmString.find('\n') != std::string::npos)
10850b57cec5SDimitry Andric     PrintFatalError(TheDef->getLoc(),
10860b57cec5SDimitry Andric                     "multiline instruction is not valid for the asmparser, "
10870b57cec5SDimitry Andric                     "mark it isCodeGenOnly");
10880b57cec5SDimitry Andric 
10890b57cec5SDimitry Andric   // Remove comments from the asm string.  We know that the asmstring only
10900b57cec5SDimitry Andric   // has one line.
10910b57cec5SDimitry Andric   if (!CommentDelimiter.empty() &&
1092349cc55cSDimitry Andric       StringRef(AsmString).contains(CommentDelimiter))
10930b57cec5SDimitry Andric     PrintFatalError(TheDef->getLoc(),
10940b57cec5SDimitry Andric                     "asmstring for instruction has comment character in it, "
10950b57cec5SDimitry Andric                     "mark it isCodeGenOnly");
10960b57cec5SDimitry Andric 
10970b57cec5SDimitry Andric   // Reject matchables with operand modifiers, these aren't something we can
10980b57cec5SDimitry Andric   // handle, the target should be refactored to use operands instead of
10990b57cec5SDimitry Andric   // modifiers.
11000b57cec5SDimitry Andric   //
11010b57cec5SDimitry Andric   // Also, check for instructions which reference the operand multiple times,
11020b57cec5SDimitry Andric   // if they don't define a custom AsmMatcher: this implies a constraint that
11030b57cec5SDimitry Andric   // the built-in matching code would not honor.
11040b57cec5SDimitry Andric   std::set<std::string> OperandNames;
11050b57cec5SDimitry Andric   for (const AsmOperand &Op : AsmOperands) {
11060b57cec5SDimitry Andric     StringRef Tok = Op.Token;
1107349cc55cSDimitry Andric     if (Tok[0] == '$' && Tok.contains(':'))
1108*0fca6ea1SDimitry Andric       PrintFatalError(
1109*0fca6ea1SDimitry Andric           TheDef->getLoc(),
11100b57cec5SDimitry Andric           "matchable with operand modifier '" + Tok +
11110b57cec5SDimitry Andric               "' not supported by asm matcher.  Mark isCodeGenOnly!");
11120b57cec5SDimitry Andric     // Verify that any operand is only mentioned once.
11130b57cec5SDimitry Andric     // We reject aliases and ignore instructions for now.
11140b57cec5SDimitry Andric     if (!IsAlias && TheDef->getValueAsString("AsmMatchConverter").empty() &&
11155ffd83dbSDimitry Andric         Tok[0] == '$' && !OperandNames.insert(std::string(Tok)).second) {
11160b57cec5SDimitry Andric       LLVM_DEBUG({
11170b57cec5SDimitry Andric         errs() << "warning: '" << TheDef->getName() << "': "
1118*0fca6ea1SDimitry Andric                << "ignoring instruction with tied operand '" << Tok << "'\n";
11190b57cec5SDimitry Andric       });
11200b57cec5SDimitry Andric       return false;
11210b57cec5SDimitry Andric     }
11220b57cec5SDimitry Andric   }
11230b57cec5SDimitry Andric 
11240b57cec5SDimitry Andric   return true;
11250b57cec5SDimitry Andric }
11260b57cec5SDimitry Andric 
11270b57cec5SDimitry Andric static std::string getEnumNameForToken(StringRef Str) {
11280b57cec5SDimitry Andric   std::string Res;
11290b57cec5SDimitry Andric 
1130fe6060f1SDimitry Andric   for (char C : Str) {
1131fe6060f1SDimitry Andric     switch (C) {
1132*0fca6ea1SDimitry Andric     case '*':
1133*0fca6ea1SDimitry Andric       Res += "_STAR_";
1134*0fca6ea1SDimitry Andric       break;
1135*0fca6ea1SDimitry Andric     case '%':
1136*0fca6ea1SDimitry Andric       Res += "_PCT_";
1137*0fca6ea1SDimitry Andric       break;
1138*0fca6ea1SDimitry Andric     case ':':
1139*0fca6ea1SDimitry Andric       Res += "_COLON_";
1140*0fca6ea1SDimitry Andric       break;
1141*0fca6ea1SDimitry Andric     case '!':
1142*0fca6ea1SDimitry Andric       Res += "_EXCLAIM_";
1143*0fca6ea1SDimitry Andric       break;
1144*0fca6ea1SDimitry Andric     case '.':
1145*0fca6ea1SDimitry Andric       Res += "_DOT_";
1146*0fca6ea1SDimitry Andric       break;
1147*0fca6ea1SDimitry Andric     case '<':
1148*0fca6ea1SDimitry Andric       Res += "_LT_";
1149*0fca6ea1SDimitry Andric       break;
1150*0fca6ea1SDimitry Andric     case '>':
1151*0fca6ea1SDimitry Andric       Res += "_GT_";
1152*0fca6ea1SDimitry Andric       break;
1153*0fca6ea1SDimitry Andric     case '-':
1154*0fca6ea1SDimitry Andric       Res += "_MINUS_";
1155*0fca6ea1SDimitry Andric       break;
1156*0fca6ea1SDimitry Andric     case '#':
1157*0fca6ea1SDimitry Andric       Res += "_HASH_";
1158*0fca6ea1SDimitry Andric       break;
11590b57cec5SDimitry Andric     default:
1160fe6060f1SDimitry Andric       if (isAlnum(C))
1161fe6060f1SDimitry Andric         Res += C;
11620b57cec5SDimitry Andric       else
1163fe6060f1SDimitry Andric         Res += "_" + utostr((unsigned)C) + "_";
11640b57cec5SDimitry Andric     }
11650b57cec5SDimitry Andric   }
11660b57cec5SDimitry Andric 
11670b57cec5SDimitry Andric   return Res;
11680b57cec5SDimitry Andric }
11690b57cec5SDimitry Andric 
11700b57cec5SDimitry Andric ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) {
11715ffd83dbSDimitry Andric   ClassInfo *&Entry = TokenClasses[std::string(Token)];
11720b57cec5SDimitry Andric 
11730b57cec5SDimitry Andric   if (!Entry) {
11740b57cec5SDimitry Andric     Classes.emplace_front();
11750b57cec5SDimitry Andric     Entry = &Classes.front();
11760b57cec5SDimitry Andric     Entry->Kind = ClassInfo::Token;
11770b57cec5SDimitry Andric     Entry->ClassName = "Token";
11780b57cec5SDimitry Andric     Entry->Name = "MCK_" + getEnumNameForToken(Token);
11795ffd83dbSDimitry Andric     Entry->ValueName = std::string(Token);
11800b57cec5SDimitry Andric     Entry->PredicateMethod = "<invalid>";
11810b57cec5SDimitry Andric     Entry->RenderMethod = "<invalid>";
11820b57cec5SDimitry Andric     Entry->ParserMethod = "";
11830b57cec5SDimitry Andric     Entry->DiagnosticType = "";
11840b57cec5SDimitry Andric     Entry->IsOptional = false;
11850b57cec5SDimitry Andric     Entry->DefaultMethod = "<invalid>";
11860b57cec5SDimitry Andric   }
11870b57cec5SDimitry Andric 
11880b57cec5SDimitry Andric   return Entry;
11890b57cec5SDimitry Andric }
11900b57cec5SDimitry Andric 
11910b57cec5SDimitry Andric ClassInfo *
11920b57cec5SDimitry Andric AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI,
11930b57cec5SDimitry Andric                                 int SubOpIdx) {
11940b57cec5SDimitry Andric   Record *Rec = OI.Rec;
11950b57cec5SDimitry Andric   if (SubOpIdx != -1)
11960b57cec5SDimitry Andric     Rec = cast<DefInit>(OI.MIOperandInfo->getArg(SubOpIdx))->getDef();
11970b57cec5SDimitry Andric   return getOperandClass(Rec, SubOpIdx);
11980b57cec5SDimitry Andric }
11990b57cec5SDimitry Andric 
1200*0fca6ea1SDimitry Andric ClassInfo *AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) {
12010b57cec5SDimitry Andric   if (Rec->isSubClassOf("RegisterOperand")) {
12020b57cec5SDimitry Andric     // RegisterOperand may have an associated ParserMatchClass. If it does,
12030b57cec5SDimitry Andric     // use it, else just fall back to the underlying register class.
12040b57cec5SDimitry Andric     const RecordVal *R = Rec->getValue("ParserMatchClass");
12050b57cec5SDimitry Andric     if (!R || !R->getValue())
12060b57cec5SDimitry Andric       PrintFatalError(Rec->getLoc(),
12070b57cec5SDimitry Andric                       "Record `" + Rec->getName() +
12080b57cec5SDimitry Andric                           "' does not have a ParserMatchClass!\n");
12090b57cec5SDimitry Andric 
12100b57cec5SDimitry Andric     if (DefInit *DI = dyn_cast<DefInit>(R->getValue())) {
12110b57cec5SDimitry Andric       Record *MatchClass = DI->getDef();
12120b57cec5SDimitry Andric       if (ClassInfo *CI = AsmOperandClasses[MatchClass])
12130b57cec5SDimitry Andric         return CI;
12140b57cec5SDimitry Andric     }
12150b57cec5SDimitry Andric 
12160b57cec5SDimitry Andric     // No custom match class. Just use the register class.
12170b57cec5SDimitry Andric     Record *ClassRec = Rec->getValueAsDef("RegClass");
12180b57cec5SDimitry Andric     if (!ClassRec)
1219*0fca6ea1SDimitry Andric       PrintFatalError(Rec->getLoc(),
1220*0fca6ea1SDimitry Andric                       "RegisterOperand `" + Rec->getName() +
12210b57cec5SDimitry Andric                           "' has no associated register class!\n");
12220b57cec5SDimitry Andric     if (ClassInfo *CI = RegisterClassClasses[ClassRec])
12230b57cec5SDimitry Andric       return CI;
12240b57cec5SDimitry Andric     PrintFatalError(Rec->getLoc(), "register class has no class info!");
12250b57cec5SDimitry Andric   }
12260b57cec5SDimitry Andric 
12270b57cec5SDimitry Andric   if (Rec->isSubClassOf("RegisterClass")) {
12280b57cec5SDimitry Andric     if (ClassInfo *CI = RegisterClassClasses[Rec])
12290b57cec5SDimitry Andric       return CI;
12300b57cec5SDimitry Andric     PrintFatalError(Rec->getLoc(), "register class has no class info!");
12310b57cec5SDimitry Andric   }
12320b57cec5SDimitry Andric 
12330b57cec5SDimitry Andric   if (!Rec->isSubClassOf("Operand"))
1234*0fca6ea1SDimitry Andric     PrintFatalError(Rec->getLoc(),
1235*0fca6ea1SDimitry Andric                     "Operand `" + Rec->getName() +
12360b57cec5SDimitry Andric                         "' does not derive from class Operand!\n");
12370b57cec5SDimitry Andric   Record *MatchClass = Rec->getValueAsDef("ParserMatchClass");
12380b57cec5SDimitry Andric   if (ClassInfo *CI = AsmOperandClasses[MatchClass])
12390b57cec5SDimitry Andric     return CI;
12400b57cec5SDimitry Andric 
12410b57cec5SDimitry Andric   PrintFatalError(Rec->getLoc(), "operand has no match class!");
12420b57cec5SDimitry Andric }
12430b57cec5SDimitry Andric 
12440b57cec5SDimitry Andric struct LessRegisterSet {
12450b57cec5SDimitry Andric   bool operator()(const RegisterSet &LHS, const RegisterSet &RHS) const {
12460b57cec5SDimitry Andric     // std::set<T> defines its own compariso "operator<", but it
12470b57cec5SDimitry Andric     // performs a lexicographical comparison by T's innate comparison
12480b57cec5SDimitry Andric     // for some reason. We don't want non-deterministic pointer
12490b57cec5SDimitry Andric     // comparisons so use this instead.
1250*0fca6ea1SDimitry Andric     return std::lexicographical_compare(LHS.begin(), LHS.end(), RHS.begin(),
1251*0fca6ea1SDimitry Andric                                         RHS.end(), LessRecordByID());
12520b57cec5SDimitry Andric   }
12530b57cec5SDimitry Andric };
12540b57cec5SDimitry Andric 
1255*0fca6ea1SDimitry Andric void AsmMatcherInfo::buildRegisterClasses(
1256*0fca6ea1SDimitry Andric     SmallPtrSetImpl<Record *> &SingletonRegisters) {
12570b57cec5SDimitry Andric   const auto &Registers = Target.getRegBank().getRegisters();
12580b57cec5SDimitry Andric   auto &RegClassList = Target.getRegBank().getRegClasses();
12590b57cec5SDimitry Andric 
12600b57cec5SDimitry Andric   typedef std::set<RegisterSet, LessRegisterSet> RegisterSetSet;
12610b57cec5SDimitry Andric 
12620b57cec5SDimitry Andric   // The register sets used for matching.
12630b57cec5SDimitry Andric   RegisterSetSet RegisterSets;
12640b57cec5SDimitry Andric 
12650b57cec5SDimitry Andric   // Gather the defined sets.
12660b57cec5SDimitry Andric   for (const CodeGenRegisterClass &RC : RegClassList)
12670b57cec5SDimitry Andric     RegisterSets.insert(
12680b57cec5SDimitry Andric         RegisterSet(RC.getOrder().begin(), RC.getOrder().end()));
12690b57cec5SDimitry Andric 
12700b57cec5SDimitry Andric   // Add any required singleton sets.
12710b57cec5SDimitry Andric   for (Record *Rec : SingletonRegisters) {
12720b57cec5SDimitry Andric     RegisterSets.insert(RegisterSet(&Rec, &Rec + 1));
12730b57cec5SDimitry Andric   }
12740b57cec5SDimitry Andric 
12750b57cec5SDimitry Andric   // Introduce derived sets where necessary (when a register does not determine
12760b57cec5SDimitry Andric   // a unique register set class), and build the mapping of registers to the set
12770b57cec5SDimitry Andric   // they should classify to.
12780b57cec5SDimitry Andric   std::map<Record *, RegisterSet> RegisterMap;
12790b57cec5SDimitry Andric   for (const CodeGenRegister &CGR : Registers) {
12800b57cec5SDimitry Andric     // Compute the intersection of all sets containing this register.
12810b57cec5SDimitry Andric     RegisterSet ContainingSet;
12820b57cec5SDimitry Andric 
12830b57cec5SDimitry Andric     for (const RegisterSet &RS : RegisterSets) {
12840b57cec5SDimitry Andric       if (!RS.count(CGR.TheDef))
12850b57cec5SDimitry Andric         continue;
12860b57cec5SDimitry Andric 
12870b57cec5SDimitry Andric       if (ContainingSet.empty()) {
12880b57cec5SDimitry Andric         ContainingSet = RS;
12890b57cec5SDimitry Andric         continue;
12900b57cec5SDimitry Andric       }
12910b57cec5SDimitry Andric 
12920b57cec5SDimitry Andric       RegisterSet Tmp;
1293*0fca6ea1SDimitry Andric       std::set_intersection(ContainingSet.begin(), ContainingSet.end(),
1294*0fca6ea1SDimitry Andric                             RS.begin(), RS.end(),
1295*0fca6ea1SDimitry Andric                             std::inserter(Tmp, Tmp.begin()), LessRecordByID());
1296*0fca6ea1SDimitry Andric       ContainingSet = std::move(Tmp);
12970b57cec5SDimitry Andric     }
12980b57cec5SDimitry Andric 
12990b57cec5SDimitry Andric     if (!ContainingSet.empty()) {
13000b57cec5SDimitry Andric       RegisterSets.insert(ContainingSet);
1301*0fca6ea1SDimitry Andric       RegisterMap.insert(std::pair(CGR.TheDef, ContainingSet));
13020b57cec5SDimitry Andric     }
13030b57cec5SDimitry Andric   }
13040b57cec5SDimitry Andric 
13050b57cec5SDimitry Andric   // Construct the register classes.
13060b57cec5SDimitry Andric   std::map<RegisterSet, ClassInfo *, LessRegisterSet> RegisterSetClasses;
13070b57cec5SDimitry Andric   unsigned Index = 0;
13080b57cec5SDimitry Andric   for (const RegisterSet &RS : RegisterSets) {
13090b57cec5SDimitry Andric     Classes.emplace_front();
13100b57cec5SDimitry Andric     ClassInfo *CI = &Classes.front();
13110b57cec5SDimitry Andric     CI->Kind = ClassInfo::RegisterClass0 + Index;
13120b57cec5SDimitry Andric     CI->ClassName = "Reg" + utostr(Index);
13130b57cec5SDimitry Andric     CI->Name = "MCK_Reg" + utostr(Index);
13140b57cec5SDimitry Andric     CI->ValueName = "";
13150b57cec5SDimitry Andric     CI->PredicateMethod = ""; // unused
13160b57cec5SDimitry Andric     CI->RenderMethod = "addRegOperands";
13170b57cec5SDimitry Andric     CI->Registers = RS;
13180b57cec5SDimitry Andric     // FIXME: diagnostic type.
13190b57cec5SDimitry Andric     CI->DiagnosticType = "";
13200b57cec5SDimitry Andric     CI->IsOptional = false;
13210b57cec5SDimitry Andric     CI->DefaultMethod = ""; // unused
1322*0fca6ea1SDimitry Andric     RegisterSetClasses.insert(std::pair(RS, CI));
13230b57cec5SDimitry Andric     ++Index;
13240b57cec5SDimitry Andric   }
13250b57cec5SDimitry Andric 
13260b57cec5SDimitry Andric   // Find the superclasses; we could compute only the subgroup lattice edges,
13270b57cec5SDimitry Andric   // but there isn't really a point.
13280b57cec5SDimitry Andric   for (const RegisterSet &RS : RegisterSets) {
13290b57cec5SDimitry Andric     ClassInfo *CI = RegisterSetClasses[RS];
13300b57cec5SDimitry Andric     for (const RegisterSet &RS2 : RegisterSets)
1331*0fca6ea1SDimitry Andric       if (RS != RS2 && std::includes(RS2.begin(), RS2.end(), RS.begin(),
1332*0fca6ea1SDimitry Andric                                      RS.end(), LessRecordByID()))
13330b57cec5SDimitry Andric         CI->SuperClasses.push_back(RegisterSetClasses[RS2]);
13340b57cec5SDimitry Andric   }
13350b57cec5SDimitry Andric 
13360b57cec5SDimitry Andric   // Name the register classes which correspond to a user defined RegisterClass.
13370b57cec5SDimitry Andric   for (const CodeGenRegisterClass &RC : RegClassList) {
13380b57cec5SDimitry Andric     // Def will be NULL for non-user defined register classes.
13390b57cec5SDimitry Andric     Record *Def = RC.getDef();
13400b57cec5SDimitry Andric     if (!Def)
13410b57cec5SDimitry Andric       continue;
13420b57cec5SDimitry Andric     ClassInfo *CI = RegisterSetClasses[RegisterSet(RC.getOrder().begin(),
13430b57cec5SDimitry Andric                                                    RC.getOrder().end())];
13440b57cec5SDimitry Andric     if (CI->ValueName.empty()) {
13450b57cec5SDimitry Andric       CI->ClassName = RC.getName();
13460b57cec5SDimitry Andric       CI->Name = "MCK_" + RC.getName();
13470b57cec5SDimitry Andric       CI->ValueName = RC.getName();
13480b57cec5SDimitry Andric     } else
13490b57cec5SDimitry Andric       CI->ValueName = CI->ValueName + "," + RC.getName();
13500b57cec5SDimitry Andric 
13510b57cec5SDimitry Andric     Init *DiagnosticType = Def->getValueInit("DiagnosticType");
13520b57cec5SDimitry Andric     if (StringInit *SI = dyn_cast<StringInit>(DiagnosticType))
13535ffd83dbSDimitry Andric       CI->DiagnosticType = std::string(SI->getValue());
13540b57cec5SDimitry Andric 
13550b57cec5SDimitry Andric     Init *DiagnosticString = Def->getValueInit("DiagnosticString");
13560b57cec5SDimitry Andric     if (StringInit *SI = dyn_cast<StringInit>(DiagnosticString))
13575ffd83dbSDimitry Andric       CI->DiagnosticString = std::string(SI->getValue());
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric     // If we have a diagnostic string but the diagnostic type is not specified
13600b57cec5SDimitry Andric     // explicitly, create an anonymous diagnostic type.
13610b57cec5SDimitry Andric     if (!CI->DiagnosticString.empty() && CI->DiagnosticType.empty())
13620b57cec5SDimitry Andric       CI->DiagnosticType = RC.getName();
13630b57cec5SDimitry Andric 
1364*0fca6ea1SDimitry Andric     RegisterClassClasses.insert(std::pair(Def, CI));
13650b57cec5SDimitry Andric   }
13660b57cec5SDimitry Andric 
13670b57cec5SDimitry Andric   // Populate the map for individual registers.
1368fe6060f1SDimitry Andric   for (auto &It : RegisterMap)
1369fe6060f1SDimitry Andric     RegisterClasses[It.first] = RegisterSetClasses[It.second];
13700b57cec5SDimitry Andric 
13710b57cec5SDimitry Andric   // Name the register classes which correspond to singleton registers.
13720b57cec5SDimitry Andric   for (Record *Rec : SingletonRegisters) {
13730b57cec5SDimitry Andric     ClassInfo *CI = RegisterClasses[Rec];
13740b57cec5SDimitry Andric     assert(CI && "Missing singleton register class info!");
13750b57cec5SDimitry Andric 
13760b57cec5SDimitry Andric     if (CI->ValueName.empty()) {
13775ffd83dbSDimitry Andric       CI->ClassName = std::string(Rec->getName());
13780b57cec5SDimitry Andric       CI->Name = "MCK_" + Rec->getName().str();
13795ffd83dbSDimitry Andric       CI->ValueName = std::string(Rec->getName());
13800b57cec5SDimitry Andric     } else
13810b57cec5SDimitry Andric       CI->ValueName = CI->ValueName + "," + Rec->getName().str();
13820b57cec5SDimitry Andric   }
13830b57cec5SDimitry Andric }
13840b57cec5SDimitry Andric 
13850b57cec5SDimitry Andric void AsmMatcherInfo::buildOperandClasses() {
13860b57cec5SDimitry Andric   std::vector<Record *> AsmOperands =
13870b57cec5SDimitry Andric       Records.getAllDerivedDefinitions("AsmOperandClass");
13880b57cec5SDimitry Andric 
13890b57cec5SDimitry Andric   // Pre-populate AsmOperandClasses map.
13900b57cec5SDimitry Andric   for (Record *Rec : AsmOperands) {
13910b57cec5SDimitry Andric     Classes.emplace_front();
13920b57cec5SDimitry Andric     AsmOperandClasses[Rec] = &Classes.front();
13930b57cec5SDimitry Andric   }
13940b57cec5SDimitry Andric 
13950b57cec5SDimitry Andric   unsigned Index = 0;
13960b57cec5SDimitry Andric   for (Record *Rec : AsmOperands) {
13970b57cec5SDimitry Andric     ClassInfo *CI = AsmOperandClasses[Rec];
13980b57cec5SDimitry Andric     CI->Kind = ClassInfo::UserClass0 + Index;
13990b57cec5SDimitry Andric 
14000b57cec5SDimitry Andric     ListInit *Supers = Rec->getValueAsListInit("SuperClasses");
14010b57cec5SDimitry Andric     for (Init *I : Supers->getValues()) {
14020b57cec5SDimitry Andric       DefInit *DI = dyn_cast<DefInit>(I);
14030b57cec5SDimitry Andric       if (!DI) {
14040b57cec5SDimitry Andric         PrintError(Rec->getLoc(), "Invalid super class reference!");
14050b57cec5SDimitry Andric         continue;
14060b57cec5SDimitry Andric       }
14070b57cec5SDimitry Andric 
14080b57cec5SDimitry Andric       ClassInfo *SC = AsmOperandClasses[DI->getDef()];
14090b57cec5SDimitry Andric       if (!SC)
14100b57cec5SDimitry Andric         PrintError(Rec->getLoc(), "Invalid super class reference!");
14110b57cec5SDimitry Andric       else
14120b57cec5SDimitry Andric         CI->SuperClasses.push_back(SC);
14130b57cec5SDimitry Andric     }
14145ffd83dbSDimitry Andric     CI->ClassName = std::string(Rec->getValueAsString("Name"));
14150b57cec5SDimitry Andric     CI->Name = "MCK_" + CI->ClassName;
14165ffd83dbSDimitry Andric     CI->ValueName = std::string(Rec->getName());
14170b57cec5SDimitry Andric 
14180b57cec5SDimitry Andric     // Get or construct the predicate method name.
14190b57cec5SDimitry Andric     Init *PMName = Rec->getValueInit("PredicateMethod");
14200b57cec5SDimitry Andric     if (StringInit *SI = dyn_cast<StringInit>(PMName)) {
14215ffd83dbSDimitry Andric       CI->PredicateMethod = std::string(SI->getValue());
14220b57cec5SDimitry Andric     } else {
14230b57cec5SDimitry Andric       assert(isa<UnsetInit>(PMName) && "Unexpected PredicateMethod field!");
14240b57cec5SDimitry Andric       CI->PredicateMethod = "is" + CI->ClassName;
14250b57cec5SDimitry Andric     }
14260b57cec5SDimitry Andric 
14270b57cec5SDimitry Andric     // Get or construct the render method name.
14280b57cec5SDimitry Andric     Init *RMName = Rec->getValueInit("RenderMethod");
14290b57cec5SDimitry Andric     if (StringInit *SI = dyn_cast<StringInit>(RMName)) {
14305ffd83dbSDimitry Andric       CI->RenderMethod = std::string(SI->getValue());
14310b57cec5SDimitry Andric     } else {
14320b57cec5SDimitry Andric       assert(isa<UnsetInit>(RMName) && "Unexpected RenderMethod field!");
14330b57cec5SDimitry Andric       CI->RenderMethod = "add" + CI->ClassName + "Operands";
14340b57cec5SDimitry Andric     }
14350b57cec5SDimitry Andric 
14360b57cec5SDimitry Andric     // Get the parse method name or leave it as empty.
14370b57cec5SDimitry Andric     Init *PRMName = Rec->getValueInit("ParserMethod");
14380b57cec5SDimitry Andric     if (StringInit *SI = dyn_cast<StringInit>(PRMName))
14395ffd83dbSDimitry Andric       CI->ParserMethod = std::string(SI->getValue());
14400b57cec5SDimitry Andric 
14410b57cec5SDimitry Andric     // Get the diagnostic type and string or leave them as empty.
14420b57cec5SDimitry Andric     Init *DiagnosticType = Rec->getValueInit("DiagnosticType");
14430b57cec5SDimitry Andric     if (StringInit *SI = dyn_cast<StringInit>(DiagnosticType))
14445ffd83dbSDimitry Andric       CI->DiagnosticType = std::string(SI->getValue());
14450b57cec5SDimitry Andric     Init *DiagnosticString = Rec->getValueInit("DiagnosticString");
14460b57cec5SDimitry Andric     if (StringInit *SI = dyn_cast<StringInit>(DiagnosticString))
14475ffd83dbSDimitry Andric       CI->DiagnosticString = std::string(SI->getValue());
14480b57cec5SDimitry Andric     // If we have a DiagnosticString, we need a DiagnosticType for use within
14490b57cec5SDimitry Andric     // the matcher.
14500b57cec5SDimitry Andric     if (!CI->DiagnosticString.empty() && CI->DiagnosticType.empty())
14510b57cec5SDimitry Andric       CI->DiagnosticType = CI->ClassName;
14520b57cec5SDimitry Andric 
14530b57cec5SDimitry Andric     Init *IsOptional = Rec->getValueInit("IsOptional");
14540b57cec5SDimitry Andric     if (BitInit *BI = dyn_cast<BitInit>(IsOptional))
14550b57cec5SDimitry Andric       CI->IsOptional = BI->getValue();
14560b57cec5SDimitry Andric 
14570b57cec5SDimitry Andric     // Get or construct the default method name.
14580b57cec5SDimitry Andric     Init *DMName = Rec->getValueInit("DefaultMethod");
14590b57cec5SDimitry Andric     if (StringInit *SI = dyn_cast<StringInit>(DMName)) {
14605ffd83dbSDimitry Andric       CI->DefaultMethod = std::string(SI->getValue());
14610b57cec5SDimitry Andric     } else {
14620b57cec5SDimitry Andric       assert(isa<UnsetInit>(DMName) && "Unexpected DefaultMethod field!");
14630b57cec5SDimitry Andric       CI->DefaultMethod = "default" + CI->ClassName + "Operands";
14640b57cec5SDimitry Andric     }
14650b57cec5SDimitry Andric 
14660b57cec5SDimitry Andric     ++Index;
14670b57cec5SDimitry Andric   }
14680b57cec5SDimitry Andric }
14690b57cec5SDimitry Andric 
1470*0fca6ea1SDimitry Andric AsmMatcherInfo::AsmMatcherInfo(Record *asmParser, CodeGenTarget &target,
14710b57cec5SDimitry Andric                                RecordKeeper &records)
1472*0fca6ea1SDimitry Andric     : Records(records), AsmParser(asmParser), Target(target) {}
14730b57cec5SDimitry Andric 
14740b57cec5SDimitry Andric /// buildOperandMatchInfo - Build the necessary information to handle user
14750b57cec5SDimitry Andric /// defined operand parsing methods.
14760b57cec5SDimitry Andric void AsmMatcherInfo::buildOperandMatchInfo() {
14770b57cec5SDimitry Andric 
14780b57cec5SDimitry Andric   /// Map containing a mask with all operands indices that can be found for
14790b57cec5SDimitry Andric   /// that class inside a instruction.
14808bcb0991SDimitry Andric   typedef std::map<ClassInfo *, unsigned, deref<std::less<>>> OpClassMaskTy;
14810b57cec5SDimitry Andric   OpClassMaskTy OpClassMask;
14820b57cec5SDimitry Andric 
1483bdd1243dSDimitry Andric   bool CallCustomParserForAllOperands =
1484bdd1243dSDimitry Andric       AsmParser->getValueAsBit("CallCustomParserForAllOperands");
14850b57cec5SDimitry Andric   for (const auto &MI : Matchables) {
14860b57cec5SDimitry Andric     OpClassMask.clear();
14870b57cec5SDimitry Andric 
14880b57cec5SDimitry Andric     // Keep track of all operands of this instructions which belong to the
14890b57cec5SDimitry Andric     // same class.
1490bdd1243dSDimitry Andric     unsigned NumOptionalOps = 0;
14910b57cec5SDimitry Andric     for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) {
14920b57cec5SDimitry Andric       const MatchableInfo::AsmOperand &Op = MI->AsmOperands[i];
1493bdd1243dSDimitry Andric       if (CallCustomParserForAllOperands || !Op.Class->ParserMethod.empty()) {
14940b57cec5SDimitry Andric         unsigned &OperandMask = OpClassMask[Op.Class];
1495bdd1243dSDimitry Andric         OperandMask |= maskTrailingOnes<unsigned>(NumOptionalOps + 1)
1496bdd1243dSDimitry Andric                        << (i - NumOptionalOps);
1497bdd1243dSDimitry Andric       }
1498bdd1243dSDimitry Andric       if (Op.Class->IsOptional)
1499bdd1243dSDimitry Andric         ++NumOptionalOps;
15000b57cec5SDimitry Andric     }
15010b57cec5SDimitry Andric 
15020b57cec5SDimitry Andric     // Generate operand match info for each mnemonic/operand class pair.
15030b57cec5SDimitry Andric     for (const auto &OCM : OpClassMask) {
15040b57cec5SDimitry Andric       unsigned OpMask = OCM.second;
15050b57cec5SDimitry Andric       ClassInfo *CI = OCM.first;
1506*0fca6ea1SDimitry Andric       OperandMatchInfo.push_back(
1507*0fca6ea1SDimitry Andric           OperandMatchEntry::create(MI.get(), CI, OpMask));
15080b57cec5SDimitry Andric     }
15090b57cec5SDimitry Andric   }
15100b57cec5SDimitry Andric }
15110b57cec5SDimitry Andric 
15120b57cec5SDimitry Andric void AsmMatcherInfo::buildInfo() {
15130b57cec5SDimitry Andric   // Build information about all of the AssemblerPredicates.
15140b57cec5SDimitry Andric   const std::vector<std::pair<Record *, SubtargetFeatureInfo>>
15150b57cec5SDimitry Andric       &SubtargetFeaturePairs = SubtargetFeatureInfo::getAll(Records);
15160b57cec5SDimitry Andric   SubtargetFeatures.insert(SubtargetFeaturePairs.begin(),
15170b57cec5SDimitry Andric                            SubtargetFeaturePairs.end());
15180b57cec5SDimitry Andric #ifndef NDEBUG
15190b57cec5SDimitry Andric   for (const auto &Pair : SubtargetFeatures)
15200b57cec5SDimitry Andric     LLVM_DEBUG(Pair.second.dump());
15210b57cec5SDimitry Andric #endif // NDEBUG
15220b57cec5SDimitry Andric 
15230b57cec5SDimitry Andric   bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst");
15240b57cec5SDimitry Andric   bool ReportMultipleNearMisses =
15250b57cec5SDimitry Andric       AsmParser->getValueAsBit("ReportMultipleNearMisses");
15260b57cec5SDimitry Andric 
15270b57cec5SDimitry Andric   // Parse the instructions; we need to do this first so that we can gather the
15280b57cec5SDimitry Andric   // singleton register classes.
15290b57cec5SDimitry Andric   SmallPtrSet<Record *, 16> SingletonRegisters;
15300b57cec5SDimitry Andric   unsigned VariantCount = Target.getAsmParserVariantCount();
15310b57cec5SDimitry Andric   for (unsigned VC = 0; VC != VariantCount; ++VC) {
15320b57cec5SDimitry Andric     Record *AsmVariant = Target.getAsmParserVariant(VC);
15330b57cec5SDimitry Andric     StringRef CommentDelimiter =
15340b57cec5SDimitry Andric         AsmVariant->getValueAsString("CommentDelimiter");
15350b57cec5SDimitry Andric     AsmVariantInfo Variant;
15360b57cec5SDimitry Andric     Variant.RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix");
15370b57cec5SDimitry Andric     Variant.TokenizingCharacters =
15380b57cec5SDimitry Andric         AsmVariant->getValueAsString("TokenizingCharacters");
15390b57cec5SDimitry Andric     Variant.SeparatorCharacters =
15400b57cec5SDimitry Andric         AsmVariant->getValueAsString("SeparatorCharacters");
1541*0fca6ea1SDimitry Andric     Variant.BreakCharacters = AsmVariant->getValueAsString("BreakCharacters");
15420b57cec5SDimitry Andric     Variant.Name = AsmVariant->getValueAsString("Name");
15430b57cec5SDimitry Andric     Variant.AsmVariantNo = AsmVariant->getValueAsInt("Variant");
15440b57cec5SDimitry Andric 
15450b57cec5SDimitry Andric     for (const CodeGenInstruction *CGI : Target.getInstructionsByEnumValue()) {
15460b57cec5SDimitry Andric 
15470b57cec5SDimitry Andric       // If the tblgen -match-prefix option is specified (for tblgen hackers),
15480b57cec5SDimitry Andric       // filter the set of instructions we consider.
15495f757f3fSDimitry Andric       if (!StringRef(CGI->TheDef->getName()).starts_with(MatchPrefix))
15500b57cec5SDimitry Andric         continue;
15510b57cec5SDimitry Andric 
15520b57cec5SDimitry Andric       // Ignore "codegen only" instructions.
15530b57cec5SDimitry Andric       if (CGI->TheDef->getValueAsBit("isCodeGenOnly"))
15540b57cec5SDimitry Andric         continue;
15550b57cec5SDimitry Andric 
15560b57cec5SDimitry Andric       // Ignore instructions for different instructions
15570b57cec5SDimitry Andric       StringRef V = CGI->TheDef->getValueAsString("AsmVariantName");
15580b57cec5SDimitry Andric       if (!V.empty() && V != Variant.Name)
15590b57cec5SDimitry Andric         continue;
15600b57cec5SDimitry Andric 
15618bcb0991SDimitry Andric       auto II = std::make_unique<MatchableInfo>(*CGI);
15620b57cec5SDimitry Andric 
15630b57cec5SDimitry Andric       II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst);
15640b57cec5SDimitry Andric 
15650b57cec5SDimitry Andric       // Ignore instructions which shouldn't be matched and diagnose invalid
15660b57cec5SDimitry Andric       // instruction definitions with an error.
15670b57cec5SDimitry Andric       if (!II->validate(CommentDelimiter, false))
15680b57cec5SDimitry Andric         continue;
15690b57cec5SDimitry Andric 
15700b57cec5SDimitry Andric       Matchables.push_back(std::move(II));
15710b57cec5SDimitry Andric     }
15720b57cec5SDimitry Andric 
15730b57cec5SDimitry Andric     // Parse all of the InstAlias definitions and stick them in the list of
15740b57cec5SDimitry Andric     // matchables.
15750b57cec5SDimitry Andric     std::vector<Record *> AllInstAliases =
15760b57cec5SDimitry Andric         Records.getAllDerivedDefinitions("InstAlias");
1577fe6060f1SDimitry Andric     for (Record *InstAlias : AllInstAliases) {
1578fe6060f1SDimitry Andric       auto Alias = std::make_unique<CodeGenInstAlias>(InstAlias, Target);
15790b57cec5SDimitry Andric 
15800b57cec5SDimitry Andric       // If the tblgen -match-prefix option is specified (for tblgen hackers),
15810b57cec5SDimitry Andric       // filter the set of instruction aliases we consider, based on the target
15820b57cec5SDimitry Andric       // instruction.
15830b57cec5SDimitry Andric       if (!StringRef(Alias->ResultInst->TheDef->getName())
15845f757f3fSDimitry Andric                .starts_with(MatchPrefix))
15850b57cec5SDimitry Andric         continue;
15860b57cec5SDimitry Andric 
15870b57cec5SDimitry Andric       StringRef V = Alias->TheDef->getValueAsString("AsmVariantName");
15880b57cec5SDimitry Andric       if (!V.empty() && V != Variant.Name)
15890b57cec5SDimitry Andric         continue;
15900b57cec5SDimitry Andric 
15918bcb0991SDimitry Andric       auto II = std::make_unique<MatchableInfo>(std::move(Alias));
15920b57cec5SDimitry Andric 
15930b57cec5SDimitry Andric       II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst);
15940b57cec5SDimitry Andric 
15950b57cec5SDimitry Andric       // Validate the alias definitions.
15960b57cec5SDimitry Andric       II->validate(CommentDelimiter, true);
15970b57cec5SDimitry Andric 
15980b57cec5SDimitry Andric       Matchables.push_back(std::move(II));
15990b57cec5SDimitry Andric     }
16000b57cec5SDimitry Andric   }
16010b57cec5SDimitry Andric 
16020b57cec5SDimitry Andric   // Build info for the register classes.
16030b57cec5SDimitry Andric   buildRegisterClasses(SingletonRegisters);
16040b57cec5SDimitry Andric 
16050b57cec5SDimitry Andric   // Build info for the user defined assembly operand classes.
16060b57cec5SDimitry Andric   buildOperandClasses();
16070b57cec5SDimitry Andric 
16080b57cec5SDimitry Andric   // Build the information about matchables, now that we have fully formed
16090b57cec5SDimitry Andric   // classes.
16100b57cec5SDimitry Andric   std::vector<std::unique_ptr<MatchableInfo>> NewMatchables;
16110b57cec5SDimitry Andric   for (auto &II : Matchables) {
16120b57cec5SDimitry Andric     // Parse the tokens after the mnemonic.
16130b57cec5SDimitry Andric     // Note: buildInstructionOperandReference may insert new AsmOperands, so
16140b57cec5SDimitry Andric     // don't precompute the loop bound.
16150b57cec5SDimitry Andric     for (unsigned i = 0; i != II->AsmOperands.size(); ++i) {
16160b57cec5SDimitry Andric       MatchableInfo::AsmOperand &Op = II->AsmOperands[i];
16170b57cec5SDimitry Andric       StringRef Token = Op.Token;
16180b57cec5SDimitry Andric 
16190b57cec5SDimitry Andric       // Check for singleton registers.
16200b57cec5SDimitry Andric       if (Record *RegRecord = Op.SingletonReg) {
16210b57cec5SDimitry Andric         Op.Class = RegisterClasses[RegRecord];
16220b57cec5SDimitry Andric         assert(Op.Class && Op.Class->Registers.size() == 1 &&
16230b57cec5SDimitry Andric                "Unexpected class for singleton register");
16240b57cec5SDimitry Andric         continue;
16250b57cec5SDimitry Andric       }
16260b57cec5SDimitry Andric 
16270b57cec5SDimitry Andric       // Check for simple tokens.
16280b57cec5SDimitry Andric       if (Token[0] != '$') {
16290b57cec5SDimitry Andric         Op.Class = getTokenClass(Token);
16300b57cec5SDimitry Andric         continue;
16310b57cec5SDimitry Andric       }
16320b57cec5SDimitry Andric 
16330b57cec5SDimitry Andric       if (Token.size() > 1 && isdigit(Token[1])) {
16340b57cec5SDimitry Andric         Op.Class = getTokenClass(Token);
16350b57cec5SDimitry Andric         continue;
16360b57cec5SDimitry Andric       }
16370b57cec5SDimitry Andric 
16380b57cec5SDimitry Andric       // Otherwise this is an operand reference.
16390b57cec5SDimitry Andric       StringRef OperandName;
16400b57cec5SDimitry Andric       if (Token[1] == '{')
16410b57cec5SDimitry Andric         OperandName = Token.substr(2, Token.size() - 3);
16420b57cec5SDimitry Andric       else
16430b57cec5SDimitry Andric         OperandName = Token.substr(1);
16440b57cec5SDimitry Andric 
164506c3fb27SDimitry Andric       if (isa<const CodeGenInstruction *>(II->DefRec))
16460b57cec5SDimitry Andric         buildInstructionOperandReference(II.get(), OperandName, i);
16470b57cec5SDimitry Andric       else
16480b57cec5SDimitry Andric         buildAliasOperandReference(II.get(), OperandName, Op);
16490b57cec5SDimitry Andric     }
16500b57cec5SDimitry Andric 
165106c3fb27SDimitry Andric     if (isa<const CodeGenInstruction *>(II->DefRec)) {
16520b57cec5SDimitry Andric       II->buildInstructionResultOperands();
16530b57cec5SDimitry Andric       // If the instruction has a two-operand alias, build up the
16540b57cec5SDimitry Andric       // matchable here. We'll add them in bulk at the end to avoid
16550b57cec5SDimitry Andric       // confusing this loop.
16560b57cec5SDimitry Andric       StringRef Constraint =
16570b57cec5SDimitry Andric           II->TheDef->getValueAsString("TwoOperandAliasConstraint");
16580b57cec5SDimitry Andric       if (Constraint != "") {
16590b57cec5SDimitry Andric         // Start by making a copy of the original matchable.
16608bcb0991SDimitry Andric         auto AliasII = std::make_unique<MatchableInfo>(*II);
16610b57cec5SDimitry Andric 
16620b57cec5SDimitry Andric         // Adjust it to be a two-operand alias.
16630b57cec5SDimitry Andric         AliasII->formTwoOperandAlias(Constraint);
16640b57cec5SDimitry Andric 
16650b57cec5SDimitry Andric         // Add the alias to the matchables list.
16660b57cec5SDimitry Andric         NewMatchables.push_back(std::move(AliasII));
16670b57cec5SDimitry Andric       }
16680b57cec5SDimitry Andric     } else
16690b57cec5SDimitry Andric       // FIXME: The tied operands checking is not yet integrated with the
16700b57cec5SDimitry Andric       // framework for reporting multiple near misses. To prevent invalid
16710b57cec5SDimitry Andric       // formats from being matched with an alias if a tied-operands check
16720b57cec5SDimitry Andric       // would otherwise have disallowed it, we just disallow such constructs
16730b57cec5SDimitry Andric       // in TableGen completely.
16740b57cec5SDimitry Andric       II->buildAliasResultOperands(!ReportMultipleNearMisses);
16750b57cec5SDimitry Andric   }
16760b57cec5SDimitry Andric   if (!NewMatchables.empty())
16770b57cec5SDimitry Andric     Matchables.insert(Matchables.end(),
16780b57cec5SDimitry Andric                       std::make_move_iterator(NewMatchables.begin()),
16790b57cec5SDimitry Andric                       std::make_move_iterator(NewMatchables.end()));
16800b57cec5SDimitry Andric 
16810b57cec5SDimitry Andric   // Process token alias definitions and set up the associated superclass
16820b57cec5SDimitry Andric   // information.
16830b57cec5SDimitry Andric   std::vector<Record *> AllTokenAliases =
16840b57cec5SDimitry Andric       Records.getAllDerivedDefinitions("TokenAlias");
16850b57cec5SDimitry Andric   for (Record *Rec : AllTokenAliases) {
16860b57cec5SDimitry Andric     ClassInfo *FromClass = getTokenClass(Rec->getValueAsString("FromToken"));
16870b57cec5SDimitry Andric     ClassInfo *ToClass = getTokenClass(Rec->getValueAsString("ToToken"));
16880b57cec5SDimitry Andric     if (FromClass == ToClass)
16890b57cec5SDimitry Andric       PrintFatalError(Rec->getLoc(),
16900b57cec5SDimitry Andric                       "error: Destination value identical to source value.");
16910b57cec5SDimitry Andric     FromClass->SuperClasses.push_back(ToClass);
16920b57cec5SDimitry Andric   }
16930b57cec5SDimitry Andric 
16940b57cec5SDimitry Andric   // Reorder classes so that classes precede super classes.
16950b57cec5SDimitry Andric   Classes.sort();
16960b57cec5SDimitry Andric 
16970b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
16980b57cec5SDimitry Andric   // Verify that the table is sorted and operator < works transitively.
16990b57cec5SDimitry Andric   for (auto I = Classes.begin(), E = Classes.end(); I != E; ++I) {
17000b57cec5SDimitry Andric     for (auto J = I; J != E; ++J) {
17010b57cec5SDimitry Andric       assert(!(*J < *I));
17020b57cec5SDimitry Andric       assert(I == J || !J->isSubsetOf(*I));
17030b57cec5SDimitry Andric     }
17040b57cec5SDimitry Andric   }
17050b57cec5SDimitry Andric #endif
17060b57cec5SDimitry Andric }
17070b57cec5SDimitry Andric 
17080b57cec5SDimitry Andric /// buildInstructionOperandReference - The specified operand is a reference to a
17090b57cec5SDimitry Andric /// named operand such as $src.  Resolve the Class and OperandInfo pointers.
1710*0fca6ea1SDimitry Andric void AsmMatcherInfo::buildInstructionOperandReference(MatchableInfo *II,
17110b57cec5SDimitry Andric                                                       StringRef OperandName,
17120b57cec5SDimitry Andric                                                       unsigned AsmOpIdx) {
171306c3fb27SDimitry Andric   const CodeGenInstruction &CGI = *cast<const CodeGenInstruction *>(II->DefRec);
17140b57cec5SDimitry Andric   const CGIOperandList &Operands = CGI.Operands;
17150b57cec5SDimitry Andric   MatchableInfo::AsmOperand *Op = &II->AsmOperands[AsmOpIdx];
17160b57cec5SDimitry Andric 
17170b57cec5SDimitry Andric   // Map this token to an operand.
17180b57cec5SDimitry Andric   unsigned Idx;
17190b57cec5SDimitry Andric   if (!Operands.hasOperandNamed(OperandName, Idx))
17200b57cec5SDimitry Andric     PrintFatalError(II->TheDef->getLoc(),
17210b57cec5SDimitry Andric                     "error: unable to find operand: '" + OperandName + "'");
17220b57cec5SDimitry Andric 
17230b57cec5SDimitry Andric   // If the instruction operand has multiple suboperands, but the parser
17240b57cec5SDimitry Andric   // match class for the asm operand is still the default "ImmAsmOperand",
17250b57cec5SDimitry Andric   // then handle each suboperand separately.
17260b57cec5SDimitry Andric   if (Op->SubOpIdx == -1 && Operands[Idx].MINumOperands > 1) {
17270b57cec5SDimitry Andric     Record *Rec = Operands[Idx].Rec;
17280b57cec5SDimitry Andric     assert(Rec->isSubClassOf("Operand") && "Unexpected operand!");
17290b57cec5SDimitry Andric     Record *MatchClass = Rec->getValueAsDef("ParserMatchClass");
17300b57cec5SDimitry Andric     if (MatchClass && MatchClass->getValueAsString("Name") == "Imm") {
17310b57cec5SDimitry Andric       // Insert remaining suboperands after AsmOpIdx in II->AsmOperands.
17320b57cec5SDimitry Andric       StringRef Token = Op->Token; // save this in case Op gets moved
17330b57cec5SDimitry Andric       for (unsigned SI = 1, SE = Operands[Idx].MINumOperands; SI != SE; ++SI) {
17340b57cec5SDimitry Andric         MatchableInfo::AsmOperand NewAsmOp(/*IsIsolatedToken=*/true, Token);
17350b57cec5SDimitry Andric         NewAsmOp.SubOpIdx = SI;
1736*0fca6ea1SDimitry Andric         II->AsmOperands.insert(II->AsmOperands.begin() + AsmOpIdx + SI,
1737*0fca6ea1SDimitry Andric                                NewAsmOp);
17380b57cec5SDimitry Andric       }
17390b57cec5SDimitry Andric       // Replace Op with first suboperand.
17400b57cec5SDimitry Andric       Op = &II->AsmOperands[AsmOpIdx]; // update the pointer in case it moved
17410b57cec5SDimitry Andric       Op->SubOpIdx = 0;
17420b57cec5SDimitry Andric     }
17430b57cec5SDimitry Andric   }
17440b57cec5SDimitry Andric 
17450b57cec5SDimitry Andric   // Set up the operand class.
17460b57cec5SDimitry Andric   Op->Class = getOperandClass(Operands[Idx], Op->SubOpIdx);
17470b57cec5SDimitry Andric   Op->OrigSrcOpName = OperandName;
17480b57cec5SDimitry Andric 
17490b57cec5SDimitry Andric   // If the named operand is tied, canonicalize it to the untied operand.
17500b57cec5SDimitry Andric   // For example, something like:
17510b57cec5SDimitry Andric   //   (outs GPR:$dst), (ins GPR:$src)
17520b57cec5SDimitry Andric   // with an asmstring of
17530b57cec5SDimitry Andric   //   "inc $src"
17540b57cec5SDimitry Andric   // we want to canonicalize to:
17550b57cec5SDimitry Andric   //   "inc $dst"
17560b57cec5SDimitry Andric   // so that we know how to provide the $dst operand when filling in the result.
17570b57cec5SDimitry Andric   int OITied = -1;
17580b57cec5SDimitry Andric   if (Operands[Idx].MINumOperands == 1)
17590b57cec5SDimitry Andric     OITied = Operands[Idx].getTiedRegister();
17600b57cec5SDimitry Andric   if (OITied != -1) {
17610b57cec5SDimitry Andric     // The tied operand index is an MIOperand index, find the operand that
17620b57cec5SDimitry Andric     // contains it.
17630b57cec5SDimitry Andric     std::pair<unsigned, unsigned> Idx = Operands.getSubOperandNumber(OITied);
17640b57cec5SDimitry Andric     OperandName = Operands[Idx.first].Name;
17650b57cec5SDimitry Andric     Op->SubOpIdx = Idx.second;
17660b57cec5SDimitry Andric   }
17670b57cec5SDimitry Andric 
17680b57cec5SDimitry Andric   Op->SrcOpName = OperandName;
17690b57cec5SDimitry Andric }
17700b57cec5SDimitry Andric 
17710b57cec5SDimitry Andric /// buildAliasOperandReference - When parsing an operand reference out of the
17720b57cec5SDimitry Andric /// matching string (e.g. "movsx $src, $dst"), determine what the class of the
17730b57cec5SDimitry Andric /// operand reference is by looking it up in the result pattern definition.
17740b57cec5SDimitry Andric void AsmMatcherInfo::buildAliasOperandReference(MatchableInfo *II,
17750b57cec5SDimitry Andric                                                 StringRef OperandName,
17760b57cec5SDimitry Andric                                                 MatchableInfo::AsmOperand &Op) {
177706c3fb27SDimitry Andric   const CodeGenInstAlias &CGA = *cast<const CodeGenInstAlias *>(II->DefRec);
17780b57cec5SDimitry Andric 
17790b57cec5SDimitry Andric   // Set up the operand class.
17800b57cec5SDimitry Andric   for (unsigned i = 0, e = CGA.ResultOperands.size(); i != e; ++i)
17810b57cec5SDimitry Andric     if (CGA.ResultOperands[i].isRecord() &&
17820b57cec5SDimitry Andric         CGA.ResultOperands[i].getName() == OperandName) {
17830b57cec5SDimitry Andric       // It's safe to go with the first one we find, because CodeGenInstAlias
17840b57cec5SDimitry Andric       // validates that all operands with the same name have the same record.
17850b57cec5SDimitry Andric       Op.SubOpIdx = CGA.ResultInstOperandIndex[i].second;
17860b57cec5SDimitry Andric       // Use the match class from the Alias definition, not the
17870b57cec5SDimitry Andric       // destination instruction, as we may have an immediate that's
17880b57cec5SDimitry Andric       // being munged by the match class.
1789*0fca6ea1SDimitry Andric       Op.Class =
1790*0fca6ea1SDimitry Andric           getOperandClass(CGA.ResultOperands[i].getRecord(), Op.SubOpIdx);
17910b57cec5SDimitry Andric       Op.SrcOpName = OperandName;
17920b57cec5SDimitry Andric       Op.OrigSrcOpName = OperandName;
17930b57cec5SDimitry Andric       return;
17940b57cec5SDimitry Andric     }
17950b57cec5SDimitry Andric 
17960b57cec5SDimitry Andric   PrintFatalError(II->TheDef->getLoc(),
17970b57cec5SDimitry Andric                   "error: unable to find operand: '" + OperandName + "'");
17980b57cec5SDimitry Andric }
17990b57cec5SDimitry Andric 
18000b57cec5SDimitry Andric void MatchableInfo::buildInstructionResultOperands() {
18010b57cec5SDimitry Andric   const CodeGenInstruction *ResultInst = getResultInst();
18020b57cec5SDimitry Andric 
18030b57cec5SDimitry Andric   // Loop over all operands of the result instruction, determining how to
18040b57cec5SDimitry Andric   // populate them.
18050b57cec5SDimitry Andric   for (const CGIOperandList::OperandInfo &OpInfo : ResultInst->Operands) {
18060b57cec5SDimitry Andric     // If this is a tied operand, just copy from the previously handled operand.
18070b57cec5SDimitry Andric     int TiedOp = -1;
18080b57cec5SDimitry Andric     if (OpInfo.MINumOperands == 1)
18090b57cec5SDimitry Andric       TiedOp = OpInfo.getTiedRegister();
18100b57cec5SDimitry Andric     if (TiedOp != -1) {
18110b57cec5SDimitry Andric       int TiedSrcOperand = findAsmOperandOriginallyNamed(OpInfo.Name);
18120b57cec5SDimitry Andric       if (TiedSrcOperand != -1 &&
18130b57cec5SDimitry Andric           ResOperands[TiedOp].Kind == ResOperand::RenderAsmOperand)
18140b57cec5SDimitry Andric         ResOperands.push_back(ResOperand::getTiedOp(
18150b57cec5SDimitry Andric             TiedOp, ResOperands[TiedOp].AsmOperandNum, TiedSrcOperand));
18160b57cec5SDimitry Andric       else
18170b57cec5SDimitry Andric         ResOperands.push_back(ResOperand::getTiedOp(TiedOp, 0, 0));
18180b57cec5SDimitry Andric       continue;
18190b57cec5SDimitry Andric     }
18200b57cec5SDimitry Andric 
18210b57cec5SDimitry Andric     int SrcOperand = findAsmOperandNamed(OpInfo.Name);
18220b57cec5SDimitry Andric     if (OpInfo.Name.empty() || SrcOperand == -1) {
18230b57cec5SDimitry Andric       // This may happen for operands that are tied to a suboperand of a
18240b57cec5SDimitry Andric       // complex operand.  Simply use a dummy value here; nobody should
18250b57cec5SDimitry Andric       // use this operand slot.
18260b57cec5SDimitry Andric       // FIXME: The long term goal is for the MCOperand list to not contain
18270b57cec5SDimitry Andric       // tied operands at all.
18280b57cec5SDimitry Andric       ResOperands.push_back(ResOperand::getImmOp(0));
18290b57cec5SDimitry Andric       continue;
18300b57cec5SDimitry Andric     }
18310b57cec5SDimitry Andric 
18320b57cec5SDimitry Andric     // Check if the one AsmOperand populates the entire operand.
18330b57cec5SDimitry Andric     unsigned NumOperands = OpInfo.MINumOperands;
18340b57cec5SDimitry Andric     if (AsmOperands[SrcOperand].SubOpIdx == -1) {
18350b57cec5SDimitry Andric       ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, NumOperands));
18360b57cec5SDimitry Andric       continue;
18370b57cec5SDimitry Andric     }
18380b57cec5SDimitry Andric 
18390b57cec5SDimitry Andric     // Add a separate ResOperand for each suboperand.
18400b57cec5SDimitry Andric     for (unsigned AI = 0; AI < NumOperands; ++AI) {
18410b57cec5SDimitry Andric       assert(AsmOperands[SrcOperand + AI].SubOpIdx == (int)AI &&
18420b57cec5SDimitry Andric              AsmOperands[SrcOperand + AI].SrcOpName == OpInfo.Name &&
18430b57cec5SDimitry Andric              "unexpected AsmOperands for suboperands");
18440b57cec5SDimitry Andric       ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand + AI, 1));
18450b57cec5SDimitry Andric     }
18460b57cec5SDimitry Andric   }
18470b57cec5SDimitry Andric }
18480b57cec5SDimitry Andric 
18490b57cec5SDimitry Andric void MatchableInfo::buildAliasResultOperands(bool AliasConstraintsAreChecked) {
185006c3fb27SDimitry Andric   const CodeGenInstAlias &CGA = *cast<const CodeGenInstAlias *>(DefRec);
18510b57cec5SDimitry Andric   const CodeGenInstruction *ResultInst = getResultInst();
18520b57cec5SDimitry Andric 
18530b57cec5SDimitry Andric   // Map of:  $reg -> #lastref
18540b57cec5SDimitry Andric   //   where $reg is the name of the operand in the asm string
18550b57cec5SDimitry Andric   //   where #lastref is the last processed index where $reg was referenced in
18560b57cec5SDimitry Andric   //   the asm string.
18570b57cec5SDimitry Andric   SmallDenseMap<StringRef, int> OperandRefs;
18580b57cec5SDimitry Andric 
18590b57cec5SDimitry Andric   // Loop over all operands of the result instruction, determining how to
18600b57cec5SDimitry Andric   // populate them.
18610b57cec5SDimitry Andric   unsigned AliasOpNo = 0;
18620b57cec5SDimitry Andric   unsigned LastOpNo = CGA.ResultInstOperandIndex.size();
18630b57cec5SDimitry Andric   for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
18640b57cec5SDimitry Andric     const CGIOperandList::OperandInfo *OpInfo = &ResultInst->Operands[i];
18650b57cec5SDimitry Andric 
18660b57cec5SDimitry Andric     // If this is a tied operand, just copy from the previously handled operand.
18670b57cec5SDimitry Andric     int TiedOp = -1;
18680b57cec5SDimitry Andric     if (OpInfo->MINumOperands == 1)
18690b57cec5SDimitry Andric       TiedOp = OpInfo->getTiedRegister();
18700b57cec5SDimitry Andric     if (TiedOp != -1) {
18710b57cec5SDimitry Andric       unsigned SrcOp1 = 0;
18720b57cec5SDimitry Andric       unsigned SrcOp2 = 0;
18730b57cec5SDimitry Andric 
18740b57cec5SDimitry Andric       // If an operand has been specified twice in the asm string,
18750b57cec5SDimitry Andric       // add the two source operand's indices to the TiedOp so that
18760b57cec5SDimitry Andric       // at runtime the 'tied' constraint is checked.
18770b57cec5SDimitry Andric       if (ResOperands[TiedOp].Kind == ResOperand::RenderAsmOperand) {
18780b57cec5SDimitry Andric         SrcOp1 = ResOperands[TiedOp].AsmOperandNum;
18790b57cec5SDimitry Andric 
18800b57cec5SDimitry Andric         // Find the next operand (similarly named operand) in the string.
18810b57cec5SDimitry Andric         StringRef Name = AsmOperands[SrcOp1].SrcOpName;
18820b57cec5SDimitry Andric         auto Insert = OperandRefs.try_emplace(Name, SrcOp1);
18830b57cec5SDimitry Andric         SrcOp2 = findAsmOperandNamed(Name, Insert.first->second);
18840b57cec5SDimitry Andric 
18850b57cec5SDimitry Andric         // Not updating the record in OperandRefs will cause TableGen
18860b57cec5SDimitry Andric         // to fail with an error at the end of this function.
18870b57cec5SDimitry Andric         if (AliasConstraintsAreChecked)
18880b57cec5SDimitry Andric           Insert.first->second = SrcOp2;
18890b57cec5SDimitry Andric 
18900b57cec5SDimitry Andric         // In case it only has one reference in the asm string,
18910b57cec5SDimitry Andric         // it doesn't need to be checked for tied constraints.
18920b57cec5SDimitry Andric         SrcOp2 = (SrcOp2 == (unsigned)-1) ? SrcOp1 : SrcOp2;
18930b57cec5SDimitry Andric       }
18940b57cec5SDimitry Andric 
18950b57cec5SDimitry Andric       // If the alias operand is of a different operand class, we only want
18960b57cec5SDimitry Andric       // to benefit from the tied-operands check and just match the operand
18970b57cec5SDimitry Andric       // as a normal, but not copy the original (TiedOp) to the result
18980b57cec5SDimitry Andric       // instruction. We do this by passing -1 as the tied operand to copy.
18990b57cec5SDimitry Andric       if (ResultInst->Operands[i].Rec->getName() !=
19000b57cec5SDimitry Andric           ResultInst->Operands[TiedOp].Rec->getName()) {
19010b57cec5SDimitry Andric         SrcOp1 = ResOperands[TiedOp].AsmOperandNum;
19020b57cec5SDimitry Andric         int SubIdx = CGA.ResultInstOperandIndex[AliasOpNo].second;
19030b57cec5SDimitry Andric         StringRef Name = CGA.ResultOperands[AliasOpNo].getName();
19040b57cec5SDimitry Andric         SrcOp2 = findAsmOperand(Name, SubIdx);
19050b57cec5SDimitry Andric         ResOperands.push_back(
19060b57cec5SDimitry Andric             ResOperand::getTiedOp((unsigned)-1, SrcOp1, SrcOp2));
19070b57cec5SDimitry Andric       } else {
19080b57cec5SDimitry Andric         ResOperands.push_back(ResOperand::getTiedOp(TiedOp, SrcOp1, SrcOp2));
19090b57cec5SDimitry Andric         continue;
19100b57cec5SDimitry Andric       }
19110b57cec5SDimitry Andric     }
19120b57cec5SDimitry Andric 
19130b57cec5SDimitry Andric     // Handle all the suboperands for this operand.
19140b57cec5SDimitry Andric     const std::string &OpName = OpInfo->Name;
19150b57cec5SDimitry Andric     for (; AliasOpNo < LastOpNo &&
1916*0fca6ea1SDimitry Andric            CGA.ResultInstOperandIndex[AliasOpNo].first == i;
1917*0fca6ea1SDimitry Andric          ++AliasOpNo) {
19180b57cec5SDimitry Andric       int SubIdx = CGA.ResultInstOperandIndex[AliasOpNo].second;
19190b57cec5SDimitry Andric 
19200b57cec5SDimitry Andric       // Find out what operand from the asmparser that this MCInst operand
19210b57cec5SDimitry Andric       // comes from.
19220b57cec5SDimitry Andric       switch (CGA.ResultOperands[AliasOpNo].Kind) {
19230b57cec5SDimitry Andric       case CodeGenInstAlias::ResultOperand::K_Record: {
19240b57cec5SDimitry Andric         StringRef Name = CGA.ResultOperands[AliasOpNo].getName();
19250b57cec5SDimitry Andric         int SrcOperand = findAsmOperand(Name, SubIdx);
19260b57cec5SDimitry Andric         if (SrcOperand == -1)
1927*0fca6ea1SDimitry Andric           PrintFatalError(TheDef->getLoc(),
1928*0fca6ea1SDimitry Andric                           "Instruction '" + TheDef->getName() +
1929*0fca6ea1SDimitry Andric                               "' has operand '" + OpName +
19300b57cec5SDimitry Andric                               "' that doesn't appear in asm string!");
19310b57cec5SDimitry Andric 
19320b57cec5SDimitry Andric         // Add it to the operand references. If it is added a second time, the
19330b57cec5SDimitry Andric         // record won't be updated and it will fail later on.
19340b57cec5SDimitry Andric         OperandRefs.try_emplace(Name, SrcOperand);
19350b57cec5SDimitry Andric 
19360b57cec5SDimitry Andric         unsigned NumOperands = (SubIdx == -1 ? OpInfo->MINumOperands : 1);
1937*0fca6ea1SDimitry Andric         ResOperands.push_back(
1938*0fca6ea1SDimitry Andric             ResOperand::getRenderedOp(SrcOperand, NumOperands));
19390b57cec5SDimitry Andric         break;
19400b57cec5SDimitry Andric       }
19410b57cec5SDimitry Andric       case CodeGenInstAlias::ResultOperand::K_Imm: {
19420b57cec5SDimitry Andric         int64_t ImmVal = CGA.ResultOperands[AliasOpNo].getImm();
19430b57cec5SDimitry Andric         ResOperands.push_back(ResOperand::getImmOp(ImmVal));
19440b57cec5SDimitry Andric         break;
19450b57cec5SDimitry Andric       }
19460b57cec5SDimitry Andric       case CodeGenInstAlias::ResultOperand::K_Reg: {
19470b57cec5SDimitry Andric         Record *Reg = CGA.ResultOperands[AliasOpNo].getRegister();
19480b57cec5SDimitry Andric         ResOperands.push_back(ResOperand::getRegOp(Reg));
19490b57cec5SDimitry Andric         break;
19500b57cec5SDimitry Andric       }
19510b57cec5SDimitry Andric       }
19520b57cec5SDimitry Andric     }
19530b57cec5SDimitry Andric   }
19540b57cec5SDimitry Andric 
19550b57cec5SDimitry Andric   // Check that operands are not repeated more times than is supported.
19560b57cec5SDimitry Andric   for (auto &T : OperandRefs) {
19570b57cec5SDimitry Andric     if (T.second != -1 && findAsmOperandNamed(T.first, T.second) != -1)
19580b57cec5SDimitry Andric       PrintFatalError(TheDef->getLoc(),
19590b57cec5SDimitry Andric                       "Operand '" + T.first + "' can never be matched");
19600b57cec5SDimitry Andric   }
19610b57cec5SDimitry Andric }
19620b57cec5SDimitry Andric 
19630b57cec5SDimitry Andric static unsigned
19640b57cec5SDimitry Andric getConverterOperandID(const std::string &Name,
19650b57cec5SDimitry Andric                       SmallSetVector<CachedHashString, 16> &Table,
19660b57cec5SDimitry Andric                       bool &IsNew) {
19670b57cec5SDimitry Andric   IsNew = Table.insert(CachedHashString(Name));
19680b57cec5SDimitry Andric 
19690b57cec5SDimitry Andric   unsigned ID = IsNew ? Table.size() - 1 : find(Table, Name) - Table.begin();
19700b57cec5SDimitry Andric 
19710b57cec5SDimitry Andric   assert(ID < Table.size());
19720b57cec5SDimitry Andric 
19730b57cec5SDimitry Andric   return ID;
19740b57cec5SDimitry Andric }
19750b57cec5SDimitry Andric 
19760b57cec5SDimitry Andric static unsigned
19770b57cec5SDimitry Andric emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
19780b57cec5SDimitry Andric                  std::vector<std::unique_ptr<MatchableInfo>> &Infos,
19790b57cec5SDimitry Andric                  bool HasMnemonicFirst, bool HasOptionalOperands,
19800b57cec5SDimitry Andric                  raw_ostream &OS) {
19810b57cec5SDimitry Andric   SmallSetVector<CachedHashString, 16> OperandConversionKinds;
19820b57cec5SDimitry Andric   SmallSetVector<CachedHashString, 16> InstructionConversionKinds;
19830b57cec5SDimitry Andric   std::vector<std::vector<uint8_t>> ConversionTable;
19840b57cec5SDimitry Andric   size_t MaxRowLength = 2; // minimum is custom converter plus terminator.
19850b57cec5SDimitry Andric 
19860b57cec5SDimitry Andric   // TargetOperandClass - This is the target's operand class, like X86Operand.
19870b57cec5SDimitry Andric   std::string TargetOperandClass = Target.getName().str() + "Operand";
19880b57cec5SDimitry Andric 
19890b57cec5SDimitry Andric   // Write the convert function to a separate stream, so we can drop it after
19900b57cec5SDimitry Andric   // the enum. We'll build up the conversion handlers for the individual
19910b57cec5SDimitry Andric   // operand types opportunistically as we encounter them.
19920b57cec5SDimitry Andric   std::string ConvertFnBody;
19930b57cec5SDimitry Andric   raw_string_ostream CvtOS(ConvertFnBody);
19940b57cec5SDimitry Andric   // Start the unified conversion function.
19950b57cec5SDimitry Andric   if (HasOptionalOperands) {
19960b57cec5SDimitry Andric     CvtOS << "void " << Target.getName() << ClassName << "::\n"
19970b57cec5SDimitry Andric           << "convertToMCInst(unsigned Kind, MCInst &Inst, "
19980b57cec5SDimitry Andric           << "unsigned Opcode,\n"
19990b57cec5SDimitry Andric           << "                const OperandVector &Operands,\n"
2000*0fca6ea1SDimitry Andric           << "                const SmallBitVector &OptionalOperandsMask,\n"
2001*0fca6ea1SDimitry Andric           << "                ArrayRef<unsigned> DefaultsOffset) {\n";
20020b57cec5SDimitry Andric   } else {
20030b57cec5SDimitry Andric     CvtOS << "void " << Target.getName() << ClassName << "::\n"
20040b57cec5SDimitry Andric           << "convertToMCInst(unsigned Kind, MCInst &Inst, "
20050b57cec5SDimitry Andric           << "unsigned Opcode,\n"
20060b57cec5SDimitry Andric           << "                const OperandVector &Operands) {\n";
20070b57cec5SDimitry Andric   }
20080b57cec5SDimitry Andric   CvtOS << "  assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n";
20090b57cec5SDimitry Andric   CvtOS << "  const uint8_t *Converter = ConversionTable[Kind];\n";
20100b57cec5SDimitry Andric   CvtOS << "  Inst.setOpcode(Opcode);\n";
20110b57cec5SDimitry Andric   CvtOS << "  for (const uint8_t *p = Converter; *p; p += 2) {\n";
20120b57cec5SDimitry Andric   if (HasOptionalOperands) {
2013*0fca6ea1SDimitry Andric     // When optional operands are involved, formal and actual operand indices
2014*0fca6ea1SDimitry Andric     // may differ. Map the former to the latter by subtracting the number of
2015*0fca6ea1SDimitry Andric     // absent optional operands.
2016*0fca6ea1SDimitry Andric     // FIXME: This is not an operand index in the CVT_Tied case
2017*0fca6ea1SDimitry Andric     CvtOS << "    unsigned OpIdx = *(p + 1) - DefaultsOffset[*(p + 1)];\n";
20180b57cec5SDimitry Andric   } else {
2019*0fca6ea1SDimitry Andric     CvtOS << "    unsigned OpIdx = *(p + 1);\n";
20200b57cec5SDimitry Andric   }
20210b57cec5SDimitry Andric   CvtOS << "    switch (*p) {\n";
20220b57cec5SDimitry Andric   CvtOS << "    default: llvm_unreachable(\"invalid conversion entry!\");\n";
20230b57cec5SDimitry Andric   CvtOS << "    case CVT_Reg:\n";
20240b57cec5SDimitry Andric   CvtOS << "      static_cast<" << TargetOperandClass
20250b57cec5SDimitry Andric         << " &>(*Operands[OpIdx]).addRegOperands(Inst, 1);\n";
20260b57cec5SDimitry Andric   CvtOS << "      break;\n";
20270b57cec5SDimitry Andric   CvtOS << "    case CVT_Tied: {\n";
2028*0fca6ea1SDimitry Andric   CvtOS << "      assert(*(p + 1) < (size_t)(std::end(TiedAsmOperandTable) -\n";
2029*0fca6ea1SDimitry Andric   CvtOS
2030*0fca6ea1SDimitry Andric       << "                              std::begin(TiedAsmOperandTable)) &&\n";
20310b57cec5SDimitry Andric   CvtOS << "             \"Tied operand not found\");\n";
2032*0fca6ea1SDimitry Andric   CvtOS << "      unsigned TiedResOpnd = TiedAsmOperandTable[*(p + 1)][0];\n";
20330b57cec5SDimitry Andric   CvtOS << "      if (TiedResOpnd != (uint8_t)-1)\n";
20340b57cec5SDimitry Andric   CvtOS << "        Inst.addOperand(Inst.getOperand(TiedResOpnd));\n";
20350b57cec5SDimitry Andric   CvtOS << "      break;\n";
20360b57cec5SDimitry Andric   CvtOS << "    }\n";
20370b57cec5SDimitry Andric 
20380b57cec5SDimitry Andric   std::string OperandFnBody;
20390b57cec5SDimitry Andric   raw_string_ostream OpOS(OperandFnBody);
20400b57cec5SDimitry Andric   // Start the operand number lookup function.
20410b57cec5SDimitry Andric   OpOS << "void " << Target.getName() << ClassName << "::\n"
20420b57cec5SDimitry Andric        << "convertToMapAndConstraints(unsigned Kind,\n";
20430b57cec5SDimitry Andric   OpOS.indent(27);
20440b57cec5SDimitry Andric   OpOS << "const OperandVector &Operands) {\n"
20450b57cec5SDimitry Andric        << "  assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n"
20460b57cec5SDimitry Andric        << "  unsigned NumMCOperands = 0;\n"
20470b57cec5SDimitry Andric        << "  const uint8_t *Converter = ConversionTable[Kind];\n"
20480b57cec5SDimitry Andric        << "  for (const uint8_t *p = Converter; *p; p += 2) {\n"
20490b57cec5SDimitry Andric        << "    switch (*p) {\n"
20500b57cec5SDimitry Andric        << "    default: llvm_unreachable(\"invalid conversion entry!\");\n"
20510b57cec5SDimitry Andric        << "    case CVT_Reg:\n"
20520b57cec5SDimitry Andric        << "      Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n"
20530b57cec5SDimitry Andric        << "      Operands[*(p + 1)]->setConstraint(\"r\");\n"
20540b57cec5SDimitry Andric        << "      ++NumMCOperands;\n"
20550b57cec5SDimitry Andric        << "      break;\n"
20560b57cec5SDimitry Andric        << "    case CVT_Tied:\n"
20570b57cec5SDimitry Andric        << "      ++NumMCOperands;\n"
20580b57cec5SDimitry Andric        << "      break;\n";
20590b57cec5SDimitry Andric 
20600b57cec5SDimitry Andric   // Pre-populate the operand conversion kinds with the standard always
20610b57cec5SDimitry Andric   // available entries.
20620b57cec5SDimitry Andric   OperandConversionKinds.insert(CachedHashString("CVT_Done"));
20630b57cec5SDimitry Andric   OperandConversionKinds.insert(CachedHashString("CVT_Reg"));
20640b57cec5SDimitry Andric   OperandConversionKinds.insert(CachedHashString("CVT_Tied"));
20650b57cec5SDimitry Andric   enum { CVT_Done, CVT_Reg, CVT_Tied };
20660b57cec5SDimitry Andric 
20670b57cec5SDimitry Andric   // Map of e.g. <0, 2, 3> -> "Tie_0_2_3" enum label.
20680b57cec5SDimitry Andric   std::map<std::tuple<uint8_t, uint8_t, uint8_t>, std::string>
20690b57cec5SDimitry Andric       TiedOperandsEnumMap;
20700b57cec5SDimitry Andric 
20710b57cec5SDimitry Andric   for (auto &II : Infos) {
20720b57cec5SDimitry Andric     // Check if we have a custom match function.
20730b57cec5SDimitry Andric     StringRef AsmMatchConverter =
20740b57cec5SDimitry Andric         II->getResultInst()->TheDef->getValueAsString("AsmMatchConverter");
20750b57cec5SDimitry Andric     if (!AsmMatchConverter.empty() && II->UseInstAsmMatchConverter) {
20760b57cec5SDimitry Andric       std::string Signature = ("ConvertCustom_" + AsmMatchConverter).str();
20770b57cec5SDimitry Andric       II->ConversionFnKind = Signature;
20780b57cec5SDimitry Andric 
20790b57cec5SDimitry Andric       // Check if we have already generated this signature.
20800b57cec5SDimitry Andric       if (!InstructionConversionKinds.insert(CachedHashString(Signature)))
20810b57cec5SDimitry Andric         continue;
20820b57cec5SDimitry Andric 
20830b57cec5SDimitry Andric       // Remember this converter for the kind enum.
20840b57cec5SDimitry Andric       unsigned KindID = OperandConversionKinds.size();
20850b57cec5SDimitry Andric       OperandConversionKinds.insert(
20860b57cec5SDimitry Andric           CachedHashString("CVT_" + getEnumNameForToken(AsmMatchConverter)));
20870b57cec5SDimitry Andric 
20880b57cec5SDimitry Andric       // Add the converter row for this instruction.
20890b57cec5SDimitry Andric       ConversionTable.emplace_back();
20900b57cec5SDimitry Andric       ConversionTable.back().push_back(KindID);
20910b57cec5SDimitry Andric       ConversionTable.back().push_back(CVT_Done);
20920b57cec5SDimitry Andric 
20930b57cec5SDimitry Andric       // Add the handler to the conversion driver function.
2094*0fca6ea1SDimitry Andric       CvtOS << "    case CVT_" << getEnumNameForToken(AsmMatchConverter)
2095*0fca6ea1SDimitry Andric             << ":\n"
20960b57cec5SDimitry Andric             << "      " << AsmMatchConverter << "(Inst, Operands);\n"
20970b57cec5SDimitry Andric             << "      break;\n";
20980b57cec5SDimitry Andric 
20990b57cec5SDimitry Andric       // FIXME: Handle the operand number lookup for custom match functions.
21000b57cec5SDimitry Andric       continue;
21010b57cec5SDimitry Andric     }
21020b57cec5SDimitry Andric 
21030b57cec5SDimitry Andric     // Build the conversion function signature.
21040b57cec5SDimitry Andric     std::string Signature = "Convert";
21050b57cec5SDimitry Andric 
21060b57cec5SDimitry Andric     std::vector<uint8_t> ConversionRow;
21070b57cec5SDimitry Andric 
21080b57cec5SDimitry Andric     // Compute the convert enum and the case body.
21090b57cec5SDimitry Andric     MaxRowLength = std::max(MaxRowLength, II->ResOperands.size() * 2 + 1);
21100b57cec5SDimitry Andric 
21110b57cec5SDimitry Andric     for (unsigned i = 0, e = II->ResOperands.size(); i != e; ++i) {
21120b57cec5SDimitry Andric       const MatchableInfo::ResOperand &OpInfo = II->ResOperands[i];
21130b57cec5SDimitry Andric 
21140b57cec5SDimitry Andric       // Generate code to populate each result operand.
21150b57cec5SDimitry Andric       switch (OpInfo.Kind) {
21160b57cec5SDimitry Andric       case MatchableInfo::ResOperand::RenderAsmOperand: {
21170b57cec5SDimitry Andric         // This comes from something we parsed.
21180b57cec5SDimitry Andric         const MatchableInfo::AsmOperand &Op =
21190b57cec5SDimitry Andric             II->AsmOperands[OpInfo.AsmOperandNum];
21200b57cec5SDimitry Andric 
21210b57cec5SDimitry Andric         // Registers are always converted the same, don't duplicate the
21220b57cec5SDimitry Andric         // conversion function based on them.
21230b57cec5SDimitry Andric         Signature += "__";
21240b57cec5SDimitry Andric         std::string Class;
21250b57cec5SDimitry Andric         Class = Op.Class->isRegisterClass() ? "Reg" : Op.Class->ClassName;
21260b57cec5SDimitry Andric         Signature += Class;
21270b57cec5SDimitry Andric         Signature += utostr(OpInfo.MINumOperands);
21280b57cec5SDimitry Andric         Signature += "_" + itostr(OpInfo.AsmOperandNum);
21290b57cec5SDimitry Andric 
21300b57cec5SDimitry Andric         // Add the conversion kind, if necessary, and get the associated ID
21310b57cec5SDimitry Andric         // the index of its entry in the vector).
2132*0fca6ea1SDimitry Andric         std::string Name =
2133*0fca6ea1SDimitry Andric             "CVT_" +
2134*0fca6ea1SDimitry Andric             (Op.Class->isRegisterClass() ? "Reg" : Op.Class->RenderMethod);
21350b57cec5SDimitry Andric         if (Op.Class->IsOptional) {
21360b57cec5SDimitry Andric           // For optional operands we must also care about DefaultMethod
21370b57cec5SDimitry Andric           assert(HasOptionalOperands);
21380b57cec5SDimitry Andric           Name += "_" + Op.Class->DefaultMethod;
21390b57cec5SDimitry Andric         }
21400b57cec5SDimitry Andric         Name = getEnumNameForToken(Name);
21410b57cec5SDimitry Andric 
21420b57cec5SDimitry Andric         bool IsNewConverter = false;
2143*0fca6ea1SDimitry Andric         unsigned ID =
2144*0fca6ea1SDimitry Andric             getConverterOperandID(Name, OperandConversionKinds, IsNewConverter);
21450b57cec5SDimitry Andric 
21460b57cec5SDimitry Andric         // Add the operand entry to the instruction kind conversion row.
21470b57cec5SDimitry Andric         ConversionRow.push_back(ID);
21480b57cec5SDimitry Andric         ConversionRow.push_back(OpInfo.AsmOperandNum + HasMnemonicFirst);
21490b57cec5SDimitry Andric 
21500b57cec5SDimitry Andric         if (!IsNewConverter)
21510b57cec5SDimitry Andric           break;
21520b57cec5SDimitry Andric 
21530b57cec5SDimitry Andric         // This is a new operand kind. Add a handler for it to the
21540b57cec5SDimitry Andric         // converter driver.
21550b57cec5SDimitry Andric         CvtOS << "    case " << Name << ":\n";
21560b57cec5SDimitry Andric         if (Op.Class->IsOptional) {
21570b57cec5SDimitry Andric           // If optional operand is not present in actual instruction then we
21580b57cec5SDimitry Andric           // should call its DefaultMethod before RenderMethod
21590b57cec5SDimitry Andric           assert(HasOptionalOperands);
21600b57cec5SDimitry Andric           CvtOS << "      if (OptionalOperandsMask[*(p + 1) - 1]) {\n"
21610b57cec5SDimitry Andric                 << "        " << Op.Class->DefaultMethod << "()"
21620b57cec5SDimitry Andric                 << "->" << Op.Class->RenderMethod << "(Inst, "
21630b57cec5SDimitry Andric                 << OpInfo.MINumOperands << ");\n"
21640b57cec5SDimitry Andric                 << "      } else {\n"
21650b57cec5SDimitry Andric                 << "        static_cast<" << TargetOperandClass
21660b57cec5SDimitry Andric                 << " &>(*Operands[OpIdx])." << Op.Class->RenderMethod
21670b57cec5SDimitry Andric                 << "(Inst, " << OpInfo.MINumOperands << ");\n"
21680b57cec5SDimitry Andric                 << "      }\n";
21690b57cec5SDimitry Andric         } else {
21700b57cec5SDimitry Andric           CvtOS << "      static_cast<" << TargetOperandClass
21710b57cec5SDimitry Andric                 << " &>(*Operands[OpIdx])." << Op.Class->RenderMethod
21720b57cec5SDimitry Andric                 << "(Inst, " << OpInfo.MINumOperands << ");\n";
21730b57cec5SDimitry Andric         }
21740b57cec5SDimitry Andric         CvtOS << "      break;\n";
21750b57cec5SDimitry Andric 
21760b57cec5SDimitry Andric         // Add a handler for the operand number lookup.
21770b57cec5SDimitry Andric         OpOS << "    case " << Name << ":\n"
21780b57cec5SDimitry Andric              << "      Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n";
21790b57cec5SDimitry Andric 
21800b57cec5SDimitry Andric         if (Op.Class->isRegisterClass())
21810b57cec5SDimitry Andric           OpOS << "      Operands[*(p + 1)]->setConstraint(\"r\");\n";
21820b57cec5SDimitry Andric         else
21830b57cec5SDimitry Andric           OpOS << "      Operands[*(p + 1)]->setConstraint(\"m\");\n";
21840b57cec5SDimitry Andric         OpOS << "      NumMCOperands += " << OpInfo.MINumOperands << ";\n"
21850b57cec5SDimitry Andric              << "      break;\n";
21860b57cec5SDimitry Andric         break;
21870b57cec5SDimitry Andric       }
21880b57cec5SDimitry Andric       case MatchableInfo::ResOperand::TiedOperand: {
21890b57cec5SDimitry Andric         // If this operand is tied to a previous one, just copy the MCInst
21900b57cec5SDimitry Andric         // operand from the earlier one.We can only tie single MCOperand values.
21910b57cec5SDimitry Andric         assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand");
21920b57cec5SDimitry Andric         uint8_t TiedOp = OpInfo.TiedOperands.ResOpnd;
2193*0fca6ea1SDimitry Andric         uint8_t SrcOp1 = OpInfo.TiedOperands.SrcOpnd1Idx + HasMnemonicFirst;
2194*0fca6ea1SDimitry Andric         uint8_t SrcOp2 = OpInfo.TiedOperands.SrcOpnd2Idx + HasMnemonicFirst;
21950b57cec5SDimitry Andric         assert((i > TiedOp || TiedOp == (uint8_t)-1) &&
21960b57cec5SDimitry Andric                "Tied operand precedes its target!");
21970b57cec5SDimitry Andric         auto TiedTupleName = std::string("Tie") + utostr(TiedOp) + '_' +
21980b57cec5SDimitry Andric                              utostr(SrcOp1) + '_' + utostr(SrcOp2);
21990b57cec5SDimitry Andric         Signature += "__" + TiedTupleName;
22000b57cec5SDimitry Andric         ConversionRow.push_back(CVT_Tied);
22010b57cec5SDimitry Andric         ConversionRow.push_back(TiedOp);
22020b57cec5SDimitry Andric         ConversionRow.push_back(SrcOp1);
22030b57cec5SDimitry Andric         ConversionRow.push_back(SrcOp2);
22040b57cec5SDimitry Andric 
22050b57cec5SDimitry Andric         // Also create an 'enum' for this combination of tied operands.
2206*0fca6ea1SDimitry Andric         auto Key = std::tuple(TiedOp, SrcOp1, SrcOp2);
22070b57cec5SDimitry Andric         TiedOperandsEnumMap.emplace(Key, TiedTupleName);
22080b57cec5SDimitry Andric         break;
22090b57cec5SDimitry Andric       }
22100b57cec5SDimitry Andric       case MatchableInfo::ResOperand::ImmOperand: {
22110b57cec5SDimitry Andric         int64_t Val = OpInfo.ImmVal;
22120b57cec5SDimitry Andric         std::string Ty = "imm_" + itostr(Val);
22130b57cec5SDimitry Andric         Ty = getEnumNameForToken(Ty);
22140b57cec5SDimitry Andric         Signature += "__" + Ty;
22150b57cec5SDimitry Andric 
22160b57cec5SDimitry Andric         std::string Name = "CVT_" + Ty;
22170b57cec5SDimitry Andric         bool IsNewConverter = false;
2218*0fca6ea1SDimitry Andric         unsigned ID =
2219*0fca6ea1SDimitry Andric             getConverterOperandID(Name, OperandConversionKinds, IsNewConverter);
22200b57cec5SDimitry Andric         // Add the operand entry to the instruction kind conversion row.
22210b57cec5SDimitry Andric         ConversionRow.push_back(ID);
22220b57cec5SDimitry Andric         ConversionRow.push_back(0);
22230b57cec5SDimitry Andric 
22240b57cec5SDimitry Andric         if (!IsNewConverter)
22250b57cec5SDimitry Andric           break;
22260b57cec5SDimitry Andric 
22270b57cec5SDimitry Andric         CvtOS << "    case " << Name << ":\n"
22280b57cec5SDimitry Andric               << "      Inst.addOperand(MCOperand::createImm(" << Val << "));\n"
22290b57cec5SDimitry Andric               << "      break;\n";
22300b57cec5SDimitry Andric 
22310b57cec5SDimitry Andric         OpOS << "    case " << Name << ":\n"
22320b57cec5SDimitry Andric              << "      Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n"
22330b57cec5SDimitry Andric              << "      Operands[*(p + 1)]->setConstraint(\"\");\n"
22340b57cec5SDimitry Andric              << "      ++NumMCOperands;\n"
22350b57cec5SDimitry Andric              << "      break;\n";
22360b57cec5SDimitry Andric         break;
22370b57cec5SDimitry Andric       }
22380b57cec5SDimitry Andric       case MatchableInfo::ResOperand::RegOperand: {
22390b57cec5SDimitry Andric         std::string Reg, Name;
22400b57cec5SDimitry Andric         if (!OpInfo.Register) {
22410b57cec5SDimitry Andric           Name = "reg0";
22420b57cec5SDimitry Andric           Reg = "0";
22430b57cec5SDimitry Andric         } else {
22440b57cec5SDimitry Andric           Reg = getQualifiedName(OpInfo.Register);
22450b57cec5SDimitry Andric           Name = "reg" + OpInfo.Register->getName().str();
22460b57cec5SDimitry Andric         }
22470b57cec5SDimitry Andric         Signature += "__" + Name;
22480b57cec5SDimitry Andric         Name = "CVT_" + Name;
22490b57cec5SDimitry Andric         bool IsNewConverter = false;
2250*0fca6ea1SDimitry Andric         unsigned ID =
2251*0fca6ea1SDimitry Andric             getConverterOperandID(Name, OperandConversionKinds, IsNewConverter);
22520b57cec5SDimitry Andric         // Add the operand entry to the instruction kind conversion row.
22530b57cec5SDimitry Andric         ConversionRow.push_back(ID);
22540b57cec5SDimitry Andric         ConversionRow.push_back(0);
22550b57cec5SDimitry Andric 
22560b57cec5SDimitry Andric         if (!IsNewConverter)
22570b57cec5SDimitry Andric           break;
22580b57cec5SDimitry Andric         CvtOS << "    case " << Name << ":\n"
22590b57cec5SDimitry Andric               << "      Inst.addOperand(MCOperand::createReg(" << Reg << "));\n"
22600b57cec5SDimitry Andric               << "      break;\n";
22610b57cec5SDimitry Andric 
22620b57cec5SDimitry Andric         OpOS << "    case " << Name << ":\n"
22630b57cec5SDimitry Andric              << "      Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n"
22640b57cec5SDimitry Andric              << "      Operands[*(p + 1)]->setConstraint(\"m\");\n"
22650b57cec5SDimitry Andric              << "      ++NumMCOperands;\n"
22660b57cec5SDimitry Andric              << "      break;\n";
22670b57cec5SDimitry Andric       }
22680b57cec5SDimitry Andric       }
22690b57cec5SDimitry Andric     }
22700b57cec5SDimitry Andric 
22710b57cec5SDimitry Andric     // If there were no operands, add to the signature to that effect
22720b57cec5SDimitry Andric     if (Signature == "Convert")
22730b57cec5SDimitry Andric       Signature += "_NoOperands";
22740b57cec5SDimitry Andric 
22750b57cec5SDimitry Andric     II->ConversionFnKind = Signature;
22760b57cec5SDimitry Andric 
22770b57cec5SDimitry Andric     // Save the signature. If we already have it, don't add a new row
22780b57cec5SDimitry Andric     // to the table.
22790b57cec5SDimitry Andric     if (!InstructionConversionKinds.insert(CachedHashString(Signature)))
22800b57cec5SDimitry Andric       continue;
22810b57cec5SDimitry Andric 
22820b57cec5SDimitry Andric     // Add the row to the table.
22830b57cec5SDimitry Andric     ConversionTable.push_back(std::move(ConversionRow));
22840b57cec5SDimitry Andric   }
22850b57cec5SDimitry Andric 
22860b57cec5SDimitry Andric   // Finish up the converter driver function.
22870b57cec5SDimitry Andric   CvtOS << "    }\n  }\n}\n\n";
22880b57cec5SDimitry Andric 
22890b57cec5SDimitry Andric   // Finish up the operand number lookup function.
22900b57cec5SDimitry Andric   OpOS << "    }\n  }\n}\n\n";
22910b57cec5SDimitry Andric 
22920b57cec5SDimitry Andric   // Output a static table for tied operands.
22930b57cec5SDimitry Andric   if (TiedOperandsEnumMap.size()) {
22940b57cec5SDimitry Andric     // The number of tied operand combinations will be small in practice,
22950b57cec5SDimitry Andric     // but just add the assert to be sure.
22960b57cec5SDimitry Andric     assert(TiedOperandsEnumMap.size() <= 254 &&
22970b57cec5SDimitry Andric            "Too many tied-operand combinations to reference with "
22980b57cec5SDimitry Andric            "an 8bit offset from the conversion table, where index "
22990b57cec5SDimitry Andric            "'255' is reserved as operand not to be copied.");
23000b57cec5SDimitry Andric 
23010b57cec5SDimitry Andric     OS << "enum {\n";
23020b57cec5SDimitry Andric     for (auto &KV : TiedOperandsEnumMap) {
23030b57cec5SDimitry Andric       OS << "  " << KV.second << ",\n";
23040b57cec5SDimitry Andric     }
23050b57cec5SDimitry Andric     OS << "};\n\n";
23060b57cec5SDimitry Andric 
23070b57cec5SDimitry Andric     OS << "static const uint8_t TiedAsmOperandTable[][3] = {\n";
23080b57cec5SDimitry Andric     for (auto &KV : TiedOperandsEnumMap) {
2309*0fca6ea1SDimitry Andric       OS << "  /* " << KV.second << " */ { " << utostr(std::get<0>(KV.first))
2310*0fca6ea1SDimitry Andric          << ", " << utostr(std::get<1>(KV.first)) << ", "
23110b57cec5SDimitry Andric          << utostr(std::get<2>(KV.first)) << " },\n";
23120b57cec5SDimitry Andric     }
23130b57cec5SDimitry Andric     OS << "};\n\n";
23140b57cec5SDimitry Andric   } else
23150b57cec5SDimitry Andric     OS << "static const uint8_t TiedAsmOperandTable[][3] = "
23160b57cec5SDimitry Andric           "{ /* empty  */ {0, 0, 0} };\n\n";
23170b57cec5SDimitry Andric 
23180b57cec5SDimitry Andric   OS << "namespace {\n";
23190b57cec5SDimitry Andric 
23200b57cec5SDimitry Andric   // Output the operand conversion kind enum.
23210b57cec5SDimitry Andric   OS << "enum OperatorConversionKind {\n";
23220b57cec5SDimitry Andric   for (const auto &Converter : OperandConversionKinds)
23230b57cec5SDimitry Andric     OS << "  " << Converter << ",\n";
23240b57cec5SDimitry Andric   OS << "  CVT_NUM_CONVERTERS\n";
23250b57cec5SDimitry Andric   OS << "};\n\n";
23260b57cec5SDimitry Andric 
23270b57cec5SDimitry Andric   // Output the instruction conversion kind enum.
23280b57cec5SDimitry Andric   OS << "enum InstructionConversionKind {\n";
23290b57cec5SDimitry Andric   for (const auto &Signature : InstructionConversionKinds)
23300b57cec5SDimitry Andric     OS << "  " << Signature << ",\n";
23310b57cec5SDimitry Andric   OS << "  CVT_NUM_SIGNATURES\n";
23320b57cec5SDimitry Andric   OS << "};\n\n";
23330b57cec5SDimitry Andric 
23340b57cec5SDimitry Andric   OS << "} // end anonymous namespace\n\n";
23350b57cec5SDimitry Andric 
23360b57cec5SDimitry Andric   // Output the conversion table.
23370b57cec5SDimitry Andric   OS << "static const uint8_t ConversionTable[CVT_NUM_SIGNATURES]["
23380b57cec5SDimitry Andric      << MaxRowLength << "] = {\n";
23390b57cec5SDimitry Andric 
23400b57cec5SDimitry Andric   for (unsigned Row = 0, ERow = ConversionTable.size(); Row != ERow; ++Row) {
23410b57cec5SDimitry Andric     assert(ConversionTable[Row].size() % 2 == 0 && "bad conversion row!");
23420b57cec5SDimitry Andric     OS << "  // " << InstructionConversionKinds[Row] << "\n";
23430b57cec5SDimitry Andric     OS << "  { ";
23440b57cec5SDimitry Andric     for (unsigned i = 0, e = ConversionTable[Row].size(); i != e; i += 2) {
23450b57cec5SDimitry Andric       OS << OperandConversionKinds[ConversionTable[Row][i]] << ", ";
23460b57cec5SDimitry Andric       if (OperandConversionKinds[ConversionTable[Row][i]] !=
23470b57cec5SDimitry Andric           CachedHashString("CVT_Tied")) {
23480b57cec5SDimitry Andric         OS << (unsigned)(ConversionTable[Row][i + 1]) << ", ";
23490b57cec5SDimitry Andric         continue;
23500b57cec5SDimitry Andric       }
23510b57cec5SDimitry Andric 
23520b57cec5SDimitry Andric       // For a tied operand, emit a reference to the TiedAsmOperandTable
23530b57cec5SDimitry Andric       // that contains the operand to copy, and the parsed operands to
23540b57cec5SDimitry Andric       // check for their tied constraints.
2355*0fca6ea1SDimitry Andric       auto Key = std::tuple((uint8_t)ConversionTable[Row][i + 1],
23560b57cec5SDimitry Andric                             (uint8_t)ConversionTable[Row][i + 2],
23570b57cec5SDimitry Andric                             (uint8_t)ConversionTable[Row][i + 3]);
23580b57cec5SDimitry Andric       auto TiedOpndEnum = TiedOperandsEnumMap.find(Key);
23590b57cec5SDimitry Andric       assert(TiedOpndEnum != TiedOperandsEnumMap.end() &&
23600b57cec5SDimitry Andric              "No record for tied operand pair");
23610b57cec5SDimitry Andric       OS << TiedOpndEnum->second << ", ";
23620b57cec5SDimitry Andric       i += 2;
23630b57cec5SDimitry Andric     }
23640b57cec5SDimitry Andric     OS << "CVT_Done },\n";
23650b57cec5SDimitry Andric   }
23660b57cec5SDimitry Andric 
23670b57cec5SDimitry Andric   OS << "};\n\n";
23680b57cec5SDimitry Andric 
23690b57cec5SDimitry Andric   // Spit out the conversion driver function.
2370*0fca6ea1SDimitry Andric   OS << ConvertFnBody;
23710b57cec5SDimitry Andric 
23720b57cec5SDimitry Andric   // Spit out the operand number lookup function.
2373*0fca6ea1SDimitry Andric   OS << OperandFnBody;
23740b57cec5SDimitry Andric 
23750b57cec5SDimitry Andric   return ConversionTable.size();
23760b57cec5SDimitry Andric }
23770b57cec5SDimitry Andric 
23780b57cec5SDimitry Andric /// emitMatchClassEnumeration - Emit the enumeration for match class kinds.
23790b57cec5SDimitry Andric static void emitMatchClassEnumeration(CodeGenTarget &Target,
23800b57cec5SDimitry Andric                                       std::forward_list<ClassInfo> &Infos,
23810b57cec5SDimitry Andric                                       raw_ostream &OS) {
23820b57cec5SDimitry Andric   OS << "namespace {\n\n";
23830b57cec5SDimitry Andric 
23840b57cec5SDimitry Andric   OS << "/// MatchClassKind - The kinds of classes which participate in\n"
23850b57cec5SDimitry Andric      << "/// instruction matching.\n";
23860b57cec5SDimitry Andric   OS << "enum MatchClassKind {\n";
23870b57cec5SDimitry Andric   OS << "  InvalidMatchClass = 0,\n";
23880b57cec5SDimitry Andric   OS << "  OptionalMatchClass = 1,\n";
23890b57cec5SDimitry Andric   ClassInfo::ClassInfoKind LastKind = ClassInfo::Token;
23900b57cec5SDimitry Andric   StringRef LastName = "OptionalMatchClass";
23910b57cec5SDimitry Andric   for (const auto &CI : Infos) {
23920b57cec5SDimitry Andric     if (LastKind == ClassInfo::Token && CI.Kind != ClassInfo::Token) {
23930b57cec5SDimitry Andric       OS << "  MCK_LAST_TOKEN = " << LastName << ",\n";
23940b57cec5SDimitry Andric     } else if (LastKind < ClassInfo::UserClass0 &&
23950b57cec5SDimitry Andric                CI.Kind >= ClassInfo::UserClass0) {
23960b57cec5SDimitry Andric       OS << "  MCK_LAST_REGISTER = " << LastName << ",\n";
23970b57cec5SDimitry Andric     }
23980b57cec5SDimitry Andric     LastKind = (ClassInfo::ClassInfoKind)CI.Kind;
23990b57cec5SDimitry Andric     LastName = CI.Name;
24000b57cec5SDimitry Andric 
24010b57cec5SDimitry Andric     OS << "  " << CI.Name << ", // ";
24020b57cec5SDimitry Andric     if (CI.Kind == ClassInfo::Token) {
24030b57cec5SDimitry Andric       OS << "'" << CI.ValueName << "'\n";
24040b57cec5SDimitry Andric     } else if (CI.isRegisterClass()) {
24050b57cec5SDimitry Andric       if (!CI.ValueName.empty())
24060b57cec5SDimitry Andric         OS << "register class '" << CI.ValueName << "'\n";
24070b57cec5SDimitry Andric       else
24080b57cec5SDimitry Andric         OS << "derived register class\n";
24090b57cec5SDimitry Andric     } else {
24100b57cec5SDimitry Andric       OS << "user defined class '" << CI.ValueName << "'\n";
24110b57cec5SDimitry Andric     }
24120b57cec5SDimitry Andric   }
24130b57cec5SDimitry Andric   OS << "  NumMatchClassKinds\n";
24140b57cec5SDimitry Andric   OS << "};\n\n";
24150b57cec5SDimitry Andric 
24168bcb0991SDimitry Andric   OS << "} // end anonymous namespace\n\n";
24170b57cec5SDimitry Andric }
24180b57cec5SDimitry Andric 
24190b57cec5SDimitry Andric /// emitMatchClassDiagStrings - Emit a function to get the diagnostic text to be
24200b57cec5SDimitry Andric /// used when an assembly operand does not match the expected operand class.
2421*0fca6ea1SDimitry Andric static void emitOperandMatchErrorDiagStrings(AsmMatcherInfo &Info,
2422*0fca6ea1SDimitry Andric                                              raw_ostream &OS) {
24230b57cec5SDimitry Andric   // If the target does not use DiagnosticString for any operands, don't emit
24240b57cec5SDimitry Andric   // an unused function.
2425e8d8bef9SDimitry Andric   if (llvm::all_of(Info.Classes, [](const ClassInfo &CI) {
2426e8d8bef9SDimitry Andric         return CI.DiagnosticString.empty();
2427e8d8bef9SDimitry Andric       }))
24280b57cec5SDimitry Andric     return;
24290b57cec5SDimitry Andric 
24300b57cec5SDimitry Andric   OS << "static const char *getMatchKindDiag(" << Info.Target.getName()
24310b57cec5SDimitry Andric      << "AsmParser::" << Info.Target.getName()
24320b57cec5SDimitry Andric      << "MatchResultTy MatchResult) {\n";
24330b57cec5SDimitry Andric   OS << "  switch (MatchResult) {\n";
24340b57cec5SDimitry Andric 
24350b57cec5SDimitry Andric   for (const auto &CI : Info.Classes) {
24360b57cec5SDimitry Andric     if (!CI.DiagnosticString.empty()) {
24370b57cec5SDimitry Andric       assert(!CI.DiagnosticType.empty() &&
24380b57cec5SDimitry Andric              "DiagnosticString set without DiagnosticType");
2439*0fca6ea1SDimitry Andric       OS << "  case " << Info.Target.getName() << "AsmParser::Match_"
2440*0fca6ea1SDimitry Andric          << CI.DiagnosticType << ":\n";
24410b57cec5SDimitry Andric       OS << "    return \"" << CI.DiagnosticString << "\";\n";
24420b57cec5SDimitry Andric     }
24430b57cec5SDimitry Andric   }
24440b57cec5SDimitry Andric 
24450b57cec5SDimitry Andric   OS << "  default:\n";
24460b57cec5SDimitry Andric   OS << "    return nullptr;\n";
24470b57cec5SDimitry Andric 
24480b57cec5SDimitry Andric   OS << "  }\n";
24490b57cec5SDimitry Andric   OS << "}\n\n";
24500b57cec5SDimitry Andric }
24510b57cec5SDimitry Andric 
24520b57cec5SDimitry Andric static void emitRegisterMatchErrorFunc(AsmMatcherInfo &Info, raw_ostream &OS) {
24530b57cec5SDimitry Andric   OS << "static unsigned getDiagKindFromRegisterClass(MatchClassKind "
24540b57cec5SDimitry Andric         "RegisterClass) {\n";
24550b57cec5SDimitry Andric   if (none_of(Info.Classes, [](const ClassInfo &CI) {
24560b57cec5SDimitry Andric         return CI.isRegisterClass() && !CI.DiagnosticType.empty();
24570b57cec5SDimitry Andric       })) {
24580b57cec5SDimitry Andric     OS << "  return MCTargetAsmParser::Match_InvalidOperand;\n";
24590b57cec5SDimitry Andric   } else {
24600b57cec5SDimitry Andric     OS << "  switch (RegisterClass) {\n";
24610b57cec5SDimitry Andric     for (const auto &CI : Info.Classes) {
24620b57cec5SDimitry Andric       if (CI.isRegisterClass() && !CI.DiagnosticType.empty()) {
24630b57cec5SDimitry Andric         OS << "  case " << CI.Name << ":\n";
24640b57cec5SDimitry Andric         OS << "    return " << Info.Target.getName() << "AsmParser::Match_"
24650b57cec5SDimitry Andric            << CI.DiagnosticType << ";\n";
24660b57cec5SDimitry Andric       }
24670b57cec5SDimitry Andric     }
24680b57cec5SDimitry Andric 
24690b57cec5SDimitry Andric     OS << "  default:\n";
24700b57cec5SDimitry Andric     OS << "    return MCTargetAsmParser::Match_InvalidOperand;\n";
24710b57cec5SDimitry Andric 
24720b57cec5SDimitry Andric     OS << "  }\n";
24730b57cec5SDimitry Andric   }
24740b57cec5SDimitry Andric   OS << "}\n\n";
24750b57cec5SDimitry Andric }
24760b57cec5SDimitry Andric 
24770b57cec5SDimitry Andric /// emitValidateOperandClass - Emit the function to validate an operand class.
2478*0fca6ea1SDimitry Andric static void emitValidateOperandClass(AsmMatcherInfo &Info, raw_ostream &OS) {
24790b57cec5SDimitry Andric   OS << "static unsigned validateOperandClass(MCParsedAsmOperand &GOp, "
24800b57cec5SDimitry Andric      << "MatchClassKind Kind) {\n";
24810b57cec5SDimitry Andric   OS << "  " << Info.Target.getName() << "Operand &Operand = ("
24820b57cec5SDimitry Andric      << Info.Target.getName() << "Operand &)GOp;\n";
24830b57cec5SDimitry Andric 
24840b57cec5SDimitry Andric   // The InvalidMatchClass is not to match any operand.
24850b57cec5SDimitry Andric   OS << "  if (Kind == InvalidMatchClass)\n";
24860b57cec5SDimitry Andric   OS << "    return MCTargetAsmParser::Match_InvalidOperand;\n\n";
24870b57cec5SDimitry Andric 
24880b57cec5SDimitry Andric   // Check for Token operands first.
24890b57cec5SDimitry Andric   // FIXME: Use a more specific diagnostic type.
24900b57cec5SDimitry Andric   OS << "  if (Operand.isToken() && Kind <= MCK_LAST_TOKEN)\n";
24910b57cec5SDimitry Andric   OS << "    return isSubclass(matchTokenString(Operand.getToken()), Kind) ?\n"
24920b57cec5SDimitry Andric      << "             MCTargetAsmParser::Match_Success :\n"
24930b57cec5SDimitry Andric      << "             MCTargetAsmParser::Match_InvalidOperand;\n\n";
24940b57cec5SDimitry Andric 
24950b57cec5SDimitry Andric   // Check the user classes. We don't care what order since we're only
24960b57cec5SDimitry Andric   // actually matching against one of them.
24970b57cec5SDimitry Andric   OS << "  switch (Kind) {\n"
24980b57cec5SDimitry Andric         "  default: break;\n";
24990b57cec5SDimitry Andric   for (const auto &CI : Info.Classes) {
25000b57cec5SDimitry Andric     if (!CI.isUserClass())
25010b57cec5SDimitry Andric       continue;
25020b57cec5SDimitry Andric 
25030b57cec5SDimitry Andric     OS << "  // '" << CI.ClassName << "' class\n";
25040b57cec5SDimitry Andric     OS << "  case " << CI.Name << ": {\n";
25050b57cec5SDimitry Andric     OS << "    DiagnosticPredicate DP(Operand." << CI.PredicateMethod
25060b57cec5SDimitry Andric        << "());\n";
25070b57cec5SDimitry Andric     OS << "    if (DP.isMatch())\n";
25080b57cec5SDimitry Andric     OS << "      return MCTargetAsmParser::Match_Success;\n";
25090b57cec5SDimitry Andric     if (!CI.DiagnosticType.empty()) {
25100b57cec5SDimitry Andric       OS << "    if (DP.isNearMatch())\n";
25110b57cec5SDimitry Andric       OS << "      return " << Info.Target.getName() << "AsmParser::Match_"
25120b57cec5SDimitry Andric          << CI.DiagnosticType << ";\n";
25130b57cec5SDimitry Andric       OS << "    break;\n";
2514*0fca6ea1SDimitry Andric     } else
25150b57cec5SDimitry Andric       OS << "    break;\n";
25160b57cec5SDimitry Andric     OS << "    }\n";
25170b57cec5SDimitry Andric   }
25180b57cec5SDimitry Andric   OS << "  } // end switch (Kind)\n\n";
25190b57cec5SDimitry Andric 
25200b57cec5SDimitry Andric   // Check for register operands, including sub-classes.
25210b57cec5SDimitry Andric   OS << "  if (Operand.isReg()) {\n";
25220b57cec5SDimitry Andric   OS << "    MatchClassKind OpKind;\n";
2523*0fca6ea1SDimitry Andric   OS << "    switch (Operand.getReg().id()) {\n";
25240b57cec5SDimitry Andric   OS << "    default: OpKind = InvalidMatchClass; break;\n";
25250b57cec5SDimitry Andric   for (const auto &RC : Info.RegisterClasses)
2526*0fca6ea1SDimitry Andric     OS << "    case " << RC.first->getValueAsString("Namespace")
2527*0fca6ea1SDimitry Andric        << "::" << RC.first->getName() << ": OpKind = " << RC.second->Name
25280b57cec5SDimitry Andric        << "; break;\n";
25290b57cec5SDimitry Andric   OS << "    }\n";
25300b57cec5SDimitry Andric   OS << "    return isSubclass(OpKind, Kind) ? "
25310b57cec5SDimitry Andric      << "(unsigned)MCTargetAsmParser::Match_Success :\n                     "
25320b57cec5SDimitry Andric      << "                 getDiagKindFromRegisterClass(Kind);\n  }\n\n";
25330b57cec5SDimitry Andric 
25340b57cec5SDimitry Andric   // Expected operand is a register, but actual is not.
25350b57cec5SDimitry Andric   OS << "  if (Kind > MCK_LAST_TOKEN && Kind <= MCK_LAST_REGISTER)\n";
25360b57cec5SDimitry Andric   OS << "    return getDiagKindFromRegisterClass(Kind);\n\n";
25370b57cec5SDimitry Andric 
25380b57cec5SDimitry Andric   // Generic fallthrough match failure case for operands that don't have
25390b57cec5SDimitry Andric   // specialized diagnostic types.
25400b57cec5SDimitry Andric   OS << "  return MCTargetAsmParser::Match_InvalidOperand;\n";
25410b57cec5SDimitry Andric   OS << "}\n\n";
25420b57cec5SDimitry Andric }
25430b57cec5SDimitry Andric 
25440b57cec5SDimitry Andric /// emitIsSubclass - Emit the subclass predicate function.
25450b57cec5SDimitry Andric static void emitIsSubclass(CodeGenTarget &Target,
25460b57cec5SDimitry Andric                            std::forward_list<ClassInfo> &Infos,
25470b57cec5SDimitry Andric                            raw_ostream &OS) {
25480b57cec5SDimitry Andric   OS << "/// isSubclass - Compute whether \\p A is a subclass of \\p B.\n";
25490b57cec5SDimitry Andric   OS << "static bool isSubclass(MatchClassKind A, MatchClassKind B) {\n";
25500b57cec5SDimitry Andric   OS << "  if (A == B)\n";
25510b57cec5SDimitry Andric   OS << "    return true;\n\n";
25520b57cec5SDimitry Andric 
25530b57cec5SDimitry Andric   bool EmittedSwitch = false;
25540b57cec5SDimitry Andric   for (const auto &A : Infos) {
25550b57cec5SDimitry Andric     std::vector<StringRef> SuperClasses;
25560b57cec5SDimitry Andric     if (A.IsOptional)
25570b57cec5SDimitry Andric       SuperClasses.push_back("OptionalMatchClass");
25580b57cec5SDimitry Andric     for (const auto &B : Infos) {
25590b57cec5SDimitry Andric       if (&A != &B && A.isSubsetOf(B))
25600b57cec5SDimitry Andric         SuperClasses.push_back(B.Name);
25610b57cec5SDimitry Andric     }
25620b57cec5SDimitry Andric 
25630b57cec5SDimitry Andric     if (SuperClasses.empty())
25640b57cec5SDimitry Andric       continue;
25650b57cec5SDimitry Andric 
25660b57cec5SDimitry Andric     // If this is the first SuperClass, emit the switch header.
25670b57cec5SDimitry Andric     if (!EmittedSwitch) {
25680b57cec5SDimitry Andric       OS << "  switch (A) {\n";
25690b57cec5SDimitry Andric       OS << "  default:\n";
25700b57cec5SDimitry Andric       OS << "    return false;\n";
25710b57cec5SDimitry Andric       EmittedSwitch = true;
25720b57cec5SDimitry Andric     }
25730b57cec5SDimitry Andric 
25740b57cec5SDimitry Andric     OS << "\n  case " << A.Name << ":\n";
25750b57cec5SDimitry Andric 
25760b57cec5SDimitry Andric     if (SuperClasses.size() == 1) {
25770b57cec5SDimitry Andric       OS << "    return B == " << SuperClasses.back() << ";\n";
25780b57cec5SDimitry Andric       continue;
25790b57cec5SDimitry Andric     }
25800b57cec5SDimitry Andric 
25810b57cec5SDimitry Andric     if (!SuperClasses.empty()) {
25820b57cec5SDimitry Andric       OS << "    switch (B) {\n";
25830b57cec5SDimitry Andric       OS << "    default: return false;\n";
25840b57cec5SDimitry Andric       for (StringRef SC : SuperClasses)
25850b57cec5SDimitry Andric         OS << "    case " << SC << ": return true;\n";
25860b57cec5SDimitry Andric       OS << "    }\n";
25870b57cec5SDimitry Andric     } else {
25880b57cec5SDimitry Andric       // No case statement to emit
25890b57cec5SDimitry Andric       OS << "    return false;\n";
25900b57cec5SDimitry Andric     }
25910b57cec5SDimitry Andric   }
25920b57cec5SDimitry Andric 
25930b57cec5SDimitry Andric   // If there were case statements emitted into the string stream write the
25940b57cec5SDimitry Andric   // default.
25950b57cec5SDimitry Andric   if (EmittedSwitch)
25960b57cec5SDimitry Andric     OS << "  }\n";
25970b57cec5SDimitry Andric   else
25980b57cec5SDimitry Andric     OS << "  return false;\n";
25990b57cec5SDimitry Andric 
26000b57cec5SDimitry Andric   OS << "}\n\n";
26010b57cec5SDimitry Andric }
26020b57cec5SDimitry Andric 
26030b57cec5SDimitry Andric /// emitMatchTokenString - Emit the function to match a token string to the
26040b57cec5SDimitry Andric /// appropriate match class value.
26050b57cec5SDimitry Andric static void emitMatchTokenString(CodeGenTarget &Target,
26060b57cec5SDimitry Andric                                  std::forward_list<ClassInfo> &Infos,
26070b57cec5SDimitry Andric                                  raw_ostream &OS) {
26080b57cec5SDimitry Andric   // Construct the match list.
26090b57cec5SDimitry Andric   std::vector<StringMatcher::StringPair> Matches;
26100b57cec5SDimitry Andric   for (const auto &CI : Infos) {
26110b57cec5SDimitry Andric     if (CI.Kind == ClassInfo::Token)
26120b57cec5SDimitry Andric       Matches.emplace_back(CI.ValueName, "return " + CI.Name + ";");
26130b57cec5SDimitry Andric   }
26140b57cec5SDimitry Andric 
26150b57cec5SDimitry Andric   OS << "static MatchClassKind matchTokenString(StringRef Name) {\n";
26160b57cec5SDimitry Andric 
26170b57cec5SDimitry Andric   StringMatcher("Name", Matches, OS).Emit();
26180b57cec5SDimitry Andric 
26190b57cec5SDimitry Andric   OS << "  return InvalidMatchClass;\n";
26200b57cec5SDimitry Andric   OS << "}\n\n";
26210b57cec5SDimitry Andric }
26220b57cec5SDimitry Andric 
26230b57cec5SDimitry Andric /// emitMatchRegisterName - Emit the function to match a string to the target
26240b57cec5SDimitry Andric /// specific register enum.
26250b57cec5SDimitry Andric static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser,
26260b57cec5SDimitry Andric                                   raw_ostream &OS) {
26270b57cec5SDimitry Andric   // Construct the match list.
26280b57cec5SDimitry Andric   std::vector<StringMatcher::StringPair> Matches;
26290b57cec5SDimitry Andric   const auto &Regs = Target.getRegBank().getRegisters();
2630*0fca6ea1SDimitry Andric   std::string Namespace =
2631*0fca6ea1SDimitry Andric       Regs.front().TheDef->getValueAsString("Namespace").str();
26320b57cec5SDimitry Andric   for (const CodeGenRegister &Reg : Regs) {
2633*0fca6ea1SDimitry Andric     StringRef AsmName = Reg.TheDef->getValueAsString("AsmName");
2634*0fca6ea1SDimitry Andric     if (AsmName.empty())
26350b57cec5SDimitry Andric       continue;
26360b57cec5SDimitry Andric 
2637*0fca6ea1SDimitry Andric     Matches.emplace_back(AsmName.str(), "return " + Namespace +
2638*0fca6ea1SDimitry Andric                                             "::" + Reg.getName().str() + ';');
26390b57cec5SDimitry Andric   }
26400b57cec5SDimitry Andric 
2641*0fca6ea1SDimitry Andric   OS << "static MCRegister MatchRegisterName(StringRef Name) {\n";
26420b57cec5SDimitry Andric 
26430b57cec5SDimitry Andric   bool IgnoreDuplicates =
26440b57cec5SDimitry Andric       AsmParser->getValueAsBit("AllowDuplicateRegisterNames");
26450b57cec5SDimitry Andric   StringMatcher("Name", Matches, OS).Emit(0, IgnoreDuplicates);
26460b57cec5SDimitry Andric 
2647*0fca6ea1SDimitry Andric   OS << "  return " << Namespace << "::NoRegister;\n";
26480b57cec5SDimitry Andric   OS << "}\n\n";
26490b57cec5SDimitry Andric }
26500b57cec5SDimitry Andric 
26510b57cec5SDimitry Andric /// Emit the function to match a string to the target
26520b57cec5SDimitry Andric /// specific register enum.
26530b57cec5SDimitry Andric static void emitMatchRegisterAltName(CodeGenTarget &Target, Record *AsmParser,
26540b57cec5SDimitry Andric                                      raw_ostream &OS) {
26550b57cec5SDimitry Andric   // Construct the match list.
26560b57cec5SDimitry Andric   std::vector<StringMatcher::StringPair> Matches;
26570b57cec5SDimitry Andric   const auto &Regs = Target.getRegBank().getRegisters();
2658*0fca6ea1SDimitry Andric   std::string Namespace =
2659*0fca6ea1SDimitry Andric       Regs.front().TheDef->getValueAsString("Namespace").str();
26600b57cec5SDimitry Andric   for (const CodeGenRegister &Reg : Regs) {
26610b57cec5SDimitry Andric 
26620b57cec5SDimitry Andric     auto AltNames = Reg.TheDef->getValueAsListOfStrings("AltNames");
26630b57cec5SDimitry Andric 
26640b57cec5SDimitry Andric     for (auto AltName : AltNames) {
26650b57cec5SDimitry Andric       AltName = StringRef(AltName).trim();
26660b57cec5SDimitry Andric 
26670b57cec5SDimitry Andric       // don't handle empty alternative names
26680b57cec5SDimitry Andric       if (AltName.empty())
26690b57cec5SDimitry Andric         continue;
26700b57cec5SDimitry Andric 
2671*0fca6ea1SDimitry Andric       Matches.emplace_back(AltName.str(), "return " + Namespace +
2672*0fca6ea1SDimitry Andric                                               "::" + Reg.getName().str() + ';');
26730b57cec5SDimitry Andric     }
26740b57cec5SDimitry Andric   }
26750b57cec5SDimitry Andric 
2676*0fca6ea1SDimitry Andric   OS << "static MCRegister MatchRegisterAltName(StringRef Name) {\n";
26770b57cec5SDimitry Andric 
26780b57cec5SDimitry Andric   bool IgnoreDuplicates =
26790b57cec5SDimitry Andric       AsmParser->getValueAsBit("AllowDuplicateRegisterNames");
26800b57cec5SDimitry Andric   StringMatcher("Name", Matches, OS).Emit(0, IgnoreDuplicates);
26810b57cec5SDimitry Andric 
2682*0fca6ea1SDimitry Andric   OS << "  return " << Namespace << "::NoRegister;\n";
26830b57cec5SDimitry Andric   OS << "}\n\n";
26840b57cec5SDimitry Andric }
26850b57cec5SDimitry Andric 
26860b57cec5SDimitry Andric /// emitOperandDiagnosticTypes - Emit the operand matching diagnostic types.
26870b57cec5SDimitry Andric static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) {
26880b57cec5SDimitry Andric   // Get the set of diagnostic types from all of the operand classes.
26890b57cec5SDimitry Andric   std::set<StringRef> Types;
26900b57cec5SDimitry Andric   for (const auto &OpClassEntry : Info.AsmOperandClasses) {
26910b57cec5SDimitry Andric     if (!OpClassEntry.second->DiagnosticType.empty())
26920b57cec5SDimitry Andric       Types.insert(OpClassEntry.second->DiagnosticType);
26930b57cec5SDimitry Andric   }
26940b57cec5SDimitry Andric   for (const auto &OpClassEntry : Info.RegisterClassClasses) {
26950b57cec5SDimitry Andric     if (!OpClassEntry.second->DiagnosticType.empty())
26960b57cec5SDimitry Andric       Types.insert(OpClassEntry.second->DiagnosticType);
26970b57cec5SDimitry Andric   }
26980b57cec5SDimitry Andric 
2699*0fca6ea1SDimitry Andric   if (Types.empty())
2700*0fca6ea1SDimitry Andric     return;
27010b57cec5SDimitry Andric 
27020b57cec5SDimitry Andric   // Now emit the enum entries.
27030b57cec5SDimitry Andric   for (StringRef Type : Types)
27040b57cec5SDimitry Andric     OS << "  Match_" << Type << ",\n";
27050b57cec5SDimitry Andric   OS << "  END_OPERAND_DIAGNOSTIC_TYPES\n";
27060b57cec5SDimitry Andric }
27070b57cec5SDimitry Andric 
27080b57cec5SDimitry Andric /// emitGetSubtargetFeatureName - Emit the helper function to get the
27090b57cec5SDimitry Andric /// user-level name for a subtarget feature.
27100b57cec5SDimitry Andric static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) {
27110b57cec5SDimitry Andric   OS << "// User-level names for subtarget features that participate in\n"
27120b57cec5SDimitry Andric      << "// instruction matching.\n"
27130b57cec5SDimitry Andric      << "static const char *getSubtargetFeatureName(uint64_t Val) {\n";
27140b57cec5SDimitry Andric   if (!Info.SubtargetFeatures.empty()) {
27150b57cec5SDimitry Andric     OS << "  switch(Val) {\n";
27160b57cec5SDimitry Andric     for (const auto &SF : Info.SubtargetFeatures) {
27170b57cec5SDimitry Andric       const SubtargetFeatureInfo &SFI = SF.second;
27180b57cec5SDimitry Andric       // FIXME: Totally just a placeholder name to get the algorithm working.
27190b57cec5SDimitry Andric       OS << "  case " << SFI.getEnumBitName() << ": return \""
27200b57cec5SDimitry Andric          << SFI.TheDef->getValueAsString("PredicateName") << "\";\n";
27210b57cec5SDimitry Andric     }
27220b57cec5SDimitry Andric     OS << "  default: return \"(unknown)\";\n";
27230b57cec5SDimitry Andric     OS << "  }\n";
27240b57cec5SDimitry Andric   } else {
27250b57cec5SDimitry Andric     // Nothing to emit, so skip the switch
27260b57cec5SDimitry Andric     OS << "  return \"(unknown)\";\n";
27270b57cec5SDimitry Andric   }
27280b57cec5SDimitry Andric   OS << "}\n\n";
27290b57cec5SDimitry Andric }
27300b57cec5SDimitry Andric 
27310b57cec5SDimitry Andric static std::string GetAliasRequiredFeatures(Record *R,
27320b57cec5SDimitry Andric                                             const AsmMatcherInfo &Info) {
27330b57cec5SDimitry Andric   std::vector<Record *> ReqFeatures = R->getValueAsListOfDefs("Predicates");
27340b57cec5SDimitry Andric   std::string Result;
27350b57cec5SDimitry Andric 
27360b57cec5SDimitry Andric   if (ReqFeatures.empty())
27370b57cec5SDimitry Andric     return Result;
27380b57cec5SDimitry Andric 
27390b57cec5SDimitry Andric   for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) {
27400b57cec5SDimitry Andric     const SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]);
27410b57cec5SDimitry Andric 
27420b57cec5SDimitry Andric     if (!F)
2743*0fca6ea1SDimitry Andric       PrintFatalError(R->getLoc(),
2744*0fca6ea1SDimitry Andric                       "Predicate '" + ReqFeatures[i]->getName() +
27450b57cec5SDimitry Andric                           "' is not marked as an AssemblerPredicate!");
27460b57cec5SDimitry Andric 
27470b57cec5SDimitry Andric     if (i)
27480b57cec5SDimitry Andric       Result += " && ";
27490b57cec5SDimitry Andric 
27500b57cec5SDimitry Andric     Result += "Features.test(" + F->getEnumBitName() + ')';
27510b57cec5SDimitry Andric   }
27520b57cec5SDimitry Andric 
27530b57cec5SDimitry Andric   return Result;
27540b57cec5SDimitry Andric }
27550b57cec5SDimitry Andric 
2756*0fca6ea1SDimitry Andric static void
2757*0fca6ea1SDimitry Andric emitMnemonicAliasVariant(raw_ostream &OS, const AsmMatcherInfo &Info,
2758*0fca6ea1SDimitry Andric                          std::vector<Record *> &Aliases, unsigned Indent = 0,
27590b57cec5SDimitry Andric                          StringRef AsmParserVariantName = StringRef()) {
27600b57cec5SDimitry Andric   // Keep track of all the aliases from a mnemonic.  Use an std::map so that the
27610b57cec5SDimitry Andric   // iteration order of the map is stable.
27620b57cec5SDimitry Andric   std::map<std::string, std::vector<Record *>> AliasesFromMnemonic;
27630b57cec5SDimitry Andric 
27640b57cec5SDimitry Andric   for (Record *R : Aliases) {
27650b57cec5SDimitry Andric     // FIXME: Allow AssemblerVariantName to be a comma separated list.
27660b57cec5SDimitry Andric     StringRef AsmVariantName = R->getValueAsString("AsmVariantName");
27670b57cec5SDimitry Andric     if (AsmVariantName != AsmParserVariantName)
27680b57cec5SDimitry Andric       continue;
2769*0fca6ea1SDimitry Andric     AliasesFromMnemonic[R->getValueAsString("FromMnemonic").lower()].push_back(
2770*0fca6ea1SDimitry Andric         R);
27710b57cec5SDimitry Andric   }
27720b57cec5SDimitry Andric   if (AliasesFromMnemonic.empty())
27730b57cec5SDimitry Andric     return;
27740b57cec5SDimitry Andric 
27750b57cec5SDimitry Andric   // Process each alias a "from" mnemonic at a time, building the code executed
27760b57cec5SDimitry Andric   // by the string remapper.
27770b57cec5SDimitry Andric   std::vector<StringMatcher::StringPair> Cases;
27780b57cec5SDimitry Andric   for (const auto &AliasEntry : AliasesFromMnemonic) {
27790b57cec5SDimitry Andric     const std::vector<Record *> &ToVec = AliasEntry.second;
27800b57cec5SDimitry Andric 
27810b57cec5SDimitry Andric     // Loop through each alias and emit code that handles each case.  If there
27820b57cec5SDimitry Andric     // are two instructions without predicates, emit an error.  If there is one,
27830b57cec5SDimitry Andric     // emit it last.
27840b57cec5SDimitry Andric     std::string MatchCode;
27850b57cec5SDimitry Andric     int AliasWithNoPredicate = -1;
27860b57cec5SDimitry Andric 
27870b57cec5SDimitry Andric     for (unsigned i = 0, e = ToVec.size(); i != e; ++i) {
27880b57cec5SDimitry Andric       Record *R = ToVec[i];
27890b57cec5SDimitry Andric       std::string FeatureMask = GetAliasRequiredFeatures(R, Info);
27900b57cec5SDimitry Andric 
27910b57cec5SDimitry Andric       // If this unconditionally matches, remember it for later and diagnose
27920b57cec5SDimitry Andric       // duplicates.
27930b57cec5SDimitry Andric       if (FeatureMask.empty()) {
2794fe6060f1SDimitry Andric         if (AliasWithNoPredicate != -1 &&
2795fe6060f1SDimitry Andric             R->getValueAsString("ToMnemonic") !=
2796fe6060f1SDimitry Andric                 ToVec[AliasWithNoPredicate]->getValueAsString("ToMnemonic")) {
2797fe6060f1SDimitry Andric           // We can't have two different aliases from the same mnemonic with no
2798fe6060f1SDimitry Andric           // predicate.
2799fe6060f1SDimitry Andric           PrintError(
2800fe6060f1SDimitry Andric               ToVec[AliasWithNoPredicate]->getLoc(),
2801fe6060f1SDimitry Andric               "two different MnemonicAliases with the same 'from' mnemonic!");
28020b57cec5SDimitry Andric           PrintFatalError(R->getLoc(), "this is the other MnemonicAlias.");
28030b57cec5SDimitry Andric         }
28040b57cec5SDimitry Andric 
28050b57cec5SDimitry Andric         AliasWithNoPredicate = i;
28060b57cec5SDimitry Andric         continue;
28070b57cec5SDimitry Andric       }
28080b57cec5SDimitry Andric       if (R->getValueAsString("ToMnemonic") == AliasEntry.first)
28090b57cec5SDimitry Andric         PrintFatalError(R->getLoc(), "MnemonicAlias to the same string");
28100b57cec5SDimitry Andric 
28110b57cec5SDimitry Andric       if (!MatchCode.empty())
28120b57cec5SDimitry Andric         MatchCode += "else ";
28130b57cec5SDimitry Andric       MatchCode += "if (" + FeatureMask + ")\n";
28140b57cec5SDimitry Andric       MatchCode += "  Mnemonic = \"";
2815fe6060f1SDimitry Andric       MatchCode += R->getValueAsString("ToMnemonic").lower();
28160b57cec5SDimitry Andric       MatchCode += "\";\n";
28170b57cec5SDimitry Andric     }
28180b57cec5SDimitry Andric 
28190b57cec5SDimitry Andric     if (AliasWithNoPredicate != -1) {
28200b57cec5SDimitry Andric       Record *R = ToVec[AliasWithNoPredicate];
28210b57cec5SDimitry Andric       if (!MatchCode.empty())
28220b57cec5SDimitry Andric         MatchCode += "else\n  ";
28230b57cec5SDimitry Andric       MatchCode += "Mnemonic = \"";
2824fe6060f1SDimitry Andric       MatchCode += R->getValueAsString("ToMnemonic").lower();
28250b57cec5SDimitry Andric       MatchCode += "\";\n";
28260b57cec5SDimitry Andric     }
28270b57cec5SDimitry Andric 
28280b57cec5SDimitry Andric     MatchCode += "return;";
28290b57cec5SDimitry Andric 
2830*0fca6ea1SDimitry Andric     Cases.push_back(std::pair(AliasEntry.first, MatchCode));
28310b57cec5SDimitry Andric   }
28320b57cec5SDimitry Andric   StringMatcher("Mnemonic", Cases, OS).Emit(Indent);
28330b57cec5SDimitry Andric }
28340b57cec5SDimitry Andric 
28350b57cec5SDimitry Andric /// emitMnemonicAliases - If the target has any MnemonicAlias<> definitions,
28360b57cec5SDimitry Andric /// emit a function for them and return true, otherwise return false.
28370b57cec5SDimitry Andric static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info,
28380b57cec5SDimitry Andric                                 CodeGenTarget &Target) {
28390b57cec5SDimitry Andric   // Ignore aliases when match-prefix is set.
28400b57cec5SDimitry Andric   if (!MatchPrefix.empty())
28410b57cec5SDimitry Andric     return false;
28420b57cec5SDimitry Andric 
28430b57cec5SDimitry Andric   std::vector<Record *> Aliases =
28440b57cec5SDimitry Andric       Info.getRecords().getAllDerivedDefinitions("MnemonicAlias");
2845*0fca6ea1SDimitry Andric   if (Aliases.empty())
2846*0fca6ea1SDimitry Andric     return false;
28470b57cec5SDimitry Andric 
28480b57cec5SDimitry Andric   OS << "static void applyMnemonicAliases(StringRef &Mnemonic, "
28490b57cec5SDimitry Andric         "const FeatureBitset &Features, unsigned VariantID) {\n";
28500b57cec5SDimitry Andric   OS << "  switch (VariantID) {\n";
28510b57cec5SDimitry Andric   unsigned VariantCount = Target.getAsmParserVariantCount();
28520b57cec5SDimitry Andric   for (unsigned VC = 0; VC != VariantCount; ++VC) {
28530b57cec5SDimitry Andric     Record *AsmVariant = Target.getAsmParserVariant(VC);
28540b57cec5SDimitry Andric     int AsmParserVariantNo = AsmVariant->getValueAsInt("Variant");
28550b57cec5SDimitry Andric     StringRef AsmParserVariantName = AsmVariant->getValueAsString("Name");
28560b57cec5SDimitry Andric     OS << "  case " << AsmParserVariantNo << ":\n";
28570b57cec5SDimitry Andric     emitMnemonicAliasVariant(OS, Info, Aliases, /*Indent=*/2,
28580b57cec5SDimitry Andric                              AsmParserVariantName);
28590b57cec5SDimitry Andric     OS << "    break;\n";
28600b57cec5SDimitry Andric   }
28610b57cec5SDimitry Andric   OS << "  }\n";
28620b57cec5SDimitry Andric 
28630b57cec5SDimitry Andric   // Emit aliases that apply to all variants.
28640b57cec5SDimitry Andric   emitMnemonicAliasVariant(OS, Info, Aliases);
28650b57cec5SDimitry Andric 
28660b57cec5SDimitry Andric   OS << "}\n\n";
28670b57cec5SDimitry Andric 
28680b57cec5SDimitry Andric   return true;
28690b57cec5SDimitry Andric }
28700b57cec5SDimitry Andric 
2871bdd1243dSDimitry Andric static void
2872bdd1243dSDimitry Andric emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
28730b57cec5SDimitry Andric                          const AsmMatcherInfo &Info, StringRef ClassName,
28740b57cec5SDimitry Andric                          StringToOffsetTable &StringTable,
2875bdd1243dSDimitry Andric                          unsigned MaxMnemonicIndex, unsigned MaxFeaturesIndex,
2876bdd1243dSDimitry Andric                          bool HasMnemonicFirst, const Record &AsmParser) {
28770b57cec5SDimitry Andric   unsigned MaxMask = 0;
28780b57cec5SDimitry Andric   for (const OperandMatchEntry &OMI : Info.OperandMatchInfo) {
28790b57cec5SDimitry Andric     MaxMask |= OMI.OperandMask;
28800b57cec5SDimitry Andric   }
28810b57cec5SDimitry Andric 
28820b57cec5SDimitry Andric   // Emit the static custom operand parsing table;
28830b57cec5SDimitry Andric   OS << "namespace {\n";
28840b57cec5SDimitry Andric   OS << "  struct OperandMatchEntry {\n";
2885*0fca6ea1SDimitry Andric   OS << "    " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n";
2886*0fca6ea1SDimitry Andric   OS << "    " << getMinimalTypeForRange(MaxMask) << " OperandMask;\n";
2887*0fca6ea1SDimitry Andric   OS << "    "
2888*0fca6ea1SDimitry Andric      << getMinimalTypeForRange(
2889*0fca6ea1SDimitry Andric             std::distance(Info.Classes.begin(), Info.Classes.end()) +
2890*0fca6ea1SDimitry Andric             2 /* Include 'InvalidMatchClass' and 'OptionalMatchClass' */)
2891*0fca6ea1SDimitry Andric      << " Class;\n";
28920b57cec5SDimitry Andric   OS << "    " << getMinimalTypeForRange(MaxFeaturesIndex)
28930b57cec5SDimitry Andric      << " RequiredFeaturesIdx;\n\n";
28940b57cec5SDimitry Andric   OS << "    StringRef getMnemonic() const {\n";
28950b57cec5SDimitry Andric   OS << "      return StringRef(MnemonicTable + Mnemonic + 1,\n";
28960b57cec5SDimitry Andric   OS << "                       MnemonicTable[Mnemonic]);\n";
28970b57cec5SDimitry Andric   OS << "    }\n";
28980b57cec5SDimitry Andric   OS << "  };\n\n";
28990b57cec5SDimitry Andric 
29000b57cec5SDimitry Andric   OS << "  // Predicate for searching for an opcode.\n";
29010b57cec5SDimitry Andric   OS << "  struct LessOpcodeOperand {\n";
29020b57cec5SDimitry Andric   OS << "    bool operator()(const OperandMatchEntry &LHS, StringRef RHS) {\n";
29030b57cec5SDimitry Andric   OS << "      return LHS.getMnemonic()  < RHS;\n";
29040b57cec5SDimitry Andric   OS << "    }\n";
29050b57cec5SDimitry Andric   OS << "    bool operator()(StringRef LHS, const OperandMatchEntry &RHS) {\n";
29060b57cec5SDimitry Andric   OS << "      return LHS < RHS.getMnemonic();\n";
29070b57cec5SDimitry Andric   OS << "    }\n";
29080b57cec5SDimitry Andric   OS << "    bool operator()(const OperandMatchEntry &LHS,";
29090b57cec5SDimitry Andric   OS << " const OperandMatchEntry &RHS) {\n";
29100b57cec5SDimitry Andric   OS << "      return LHS.getMnemonic() < RHS.getMnemonic();\n";
29110b57cec5SDimitry Andric   OS << "    }\n";
29120b57cec5SDimitry Andric   OS << "  };\n";
29130b57cec5SDimitry Andric 
29148bcb0991SDimitry Andric   OS << "} // end anonymous namespace\n\n";
29150b57cec5SDimitry Andric 
29160b57cec5SDimitry Andric   OS << "static const OperandMatchEntry OperandMatchTable["
29170b57cec5SDimitry Andric      << Info.OperandMatchInfo.size() << "] = {\n";
29180b57cec5SDimitry Andric 
29190b57cec5SDimitry Andric   OS << "  /* Operand List Mnemonic, Mask, Operand Class, Features */\n";
29200b57cec5SDimitry Andric   for (const OperandMatchEntry &OMI : Info.OperandMatchInfo) {
29210b57cec5SDimitry Andric     const MatchableInfo &II = *OMI.MI;
29220b57cec5SDimitry Andric 
29230b57cec5SDimitry Andric     OS << "  { ";
29240b57cec5SDimitry Andric 
29250b57cec5SDimitry Andric     // Store a pascal-style length byte in the mnemonic.
2926e8d8bef9SDimitry Andric     std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.lower();
2927*0fca6ea1SDimitry Andric     OS << StringTable.GetOrAddStringOffset(LenMnemonic, false) << " /* "
2928*0fca6ea1SDimitry Andric        << II.Mnemonic << " */, ";
29290b57cec5SDimitry Andric 
29300b57cec5SDimitry Andric     OS << OMI.OperandMask;
29310b57cec5SDimitry Andric     OS << " /* ";
2932fe6060f1SDimitry Andric     ListSeparator LS;
29330b57cec5SDimitry Andric     for (int i = 0, e = 31; i != e; ++i)
2934fe6060f1SDimitry Andric       if (OMI.OperandMask & (1 << i))
2935fe6060f1SDimitry Andric         OS << LS << i;
29360b57cec5SDimitry Andric     OS << " */, ";
29370b57cec5SDimitry Andric 
29380b57cec5SDimitry Andric     OS << OMI.CI->Name;
29390b57cec5SDimitry Andric 
29400b57cec5SDimitry Andric     // Write the required features mask.
29410b57cec5SDimitry Andric     OS << ", AMFBS";
29420b57cec5SDimitry Andric     if (II.RequiredFeatures.empty())
29430b57cec5SDimitry Andric       OS << "_None";
29440b57cec5SDimitry Andric     else
29450b57cec5SDimitry Andric       for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i)
29460b57cec5SDimitry Andric         OS << '_' << II.RequiredFeatures[i]->TheDef->getName();
29470b57cec5SDimitry Andric 
29480b57cec5SDimitry Andric     OS << " },\n";
29490b57cec5SDimitry Andric   }
29500b57cec5SDimitry Andric   OS << "};\n\n";
29510b57cec5SDimitry Andric 
29520b57cec5SDimitry Andric   // Emit the operand class switch to call the correct custom parser for
29530b57cec5SDimitry Andric   // the found operand class.
295406c3fb27SDimitry Andric   OS << "ParseStatus " << Target.getName() << ClassName << "::\n"
29550b57cec5SDimitry Andric      << "tryCustomParseOperand(OperandVector"
29560b57cec5SDimitry Andric      << " &Operands,\n                      unsigned MCK) {\n\n"
29570b57cec5SDimitry Andric      << "  switch(MCK) {\n";
29580b57cec5SDimitry Andric 
29590b57cec5SDimitry Andric   for (const auto &CI : Info.Classes) {
29600b57cec5SDimitry Andric     if (CI.ParserMethod.empty())
29610b57cec5SDimitry Andric       continue;
29620b57cec5SDimitry Andric     OS << "  case " << CI.Name << ":\n"
29630b57cec5SDimitry Andric        << "    return " << CI.ParserMethod << "(Operands);\n";
29640b57cec5SDimitry Andric   }
29650b57cec5SDimitry Andric 
29660b57cec5SDimitry Andric   OS << "  default:\n";
296706c3fb27SDimitry Andric   OS << "    return ParseStatus::NoMatch;\n";
29680b57cec5SDimitry Andric   OS << "  }\n";
296906c3fb27SDimitry Andric   OS << "  return ParseStatus::NoMatch;\n";
29700b57cec5SDimitry Andric   OS << "}\n\n";
29710b57cec5SDimitry Andric 
29720b57cec5SDimitry Andric   // Emit the static custom operand parser. This code is very similar with
29730b57cec5SDimitry Andric   // the other matcher. Also use MatchResultTy here just in case we go for
29740b57cec5SDimitry Andric   // a better error handling.
297506c3fb27SDimitry Andric   OS << "ParseStatus " << Target.getName() << ClassName << "::\n"
29760b57cec5SDimitry Andric      << "MatchOperandParserImpl(OperandVector"
29770b57cec5SDimitry Andric      << " &Operands,\n                       StringRef Mnemonic,\n"
29780b57cec5SDimitry Andric      << "                       bool ParseForAllFeatures) {\n";
29790b57cec5SDimitry Andric 
29800b57cec5SDimitry Andric   // Emit code to get the available features.
29810b57cec5SDimitry Andric   OS << "  // Get the current feature set.\n";
2982*0fca6ea1SDimitry Andric   OS << "  const FeatureBitset &AvailableFeatures = "
2983*0fca6ea1SDimitry Andric         "getAvailableFeatures();\n\n";
29840b57cec5SDimitry Andric 
29850b57cec5SDimitry Andric   OS << "  // Get the next operand index.\n";
29860b57cec5SDimitry Andric   OS << "  unsigned NextOpNum = Operands.size()"
29870b57cec5SDimitry Andric      << (HasMnemonicFirst ? " - 1" : "") << ";\n";
29880b57cec5SDimitry Andric 
29890b57cec5SDimitry Andric   // Emit code to search the table.
29900b57cec5SDimitry Andric   OS << "  // Search the table.\n";
29910b57cec5SDimitry Andric   if (HasMnemonicFirst) {
29920b57cec5SDimitry Andric     OS << "  auto MnemonicRange =\n";
29930b57cec5SDimitry Andric     OS << "    std::equal_range(std::begin(OperandMatchTable), "
29940b57cec5SDimitry Andric           "std::end(OperandMatchTable),\n";
29950b57cec5SDimitry Andric     OS << "                     Mnemonic, LessOpcodeOperand());\n\n";
29960b57cec5SDimitry Andric   } else {
2997*0fca6ea1SDimitry Andric     OS << "  auto MnemonicRange = std::pair(std::begin(OperandMatchTable),"
29980b57cec5SDimitry Andric           " std::end(OperandMatchTable));\n";
29990b57cec5SDimitry Andric     OS << "  if (!Mnemonic.empty())\n";
30000b57cec5SDimitry Andric     OS << "    MnemonicRange =\n";
30010b57cec5SDimitry Andric     OS << "      std::equal_range(std::begin(OperandMatchTable), "
30020b57cec5SDimitry Andric           "std::end(OperandMatchTable),\n";
30030b57cec5SDimitry Andric     OS << "                       Mnemonic, LessOpcodeOperand());\n\n";
30040b57cec5SDimitry Andric   }
30050b57cec5SDimitry Andric 
30060b57cec5SDimitry Andric   OS << "  if (MnemonicRange.first == MnemonicRange.second)\n";
300706c3fb27SDimitry Andric   OS << "    return ParseStatus::NoMatch;\n\n";
30080b57cec5SDimitry Andric 
30090b57cec5SDimitry Andric   OS << "  for (const OperandMatchEntry *it = MnemonicRange.first,\n"
30100b57cec5SDimitry Andric      << "       *ie = MnemonicRange.second; it != ie; ++it) {\n";
30110b57cec5SDimitry Andric 
30120b57cec5SDimitry Andric   OS << "    // equal_range guarantees that instruction mnemonic matches.\n";
30130b57cec5SDimitry Andric   OS << "    assert(Mnemonic == it->getMnemonic());\n\n";
30140b57cec5SDimitry Andric 
30150b57cec5SDimitry Andric   // Emit check that the required features are available.
30160b57cec5SDimitry Andric   OS << "    // check if the available features match\n";
30170b57cec5SDimitry Andric   OS << "    const FeatureBitset &RequiredFeatures = "
30180b57cec5SDimitry Andric         "FeatureBitsets[it->RequiredFeaturesIdx];\n";
30190b57cec5SDimitry Andric   OS << "    if (!ParseForAllFeatures && (AvailableFeatures & "
30200b57cec5SDimitry Andric         "RequiredFeatures) != RequiredFeatures)\n";
30210b57cec5SDimitry Andric   OS << "      continue;\n\n";
30220b57cec5SDimitry Andric 
30230b57cec5SDimitry Andric   // Emit check to ensure the operand number matches.
30240b57cec5SDimitry Andric   OS << "    // check if the operand in question has a custom parser.\n";
30250b57cec5SDimitry Andric   OS << "    if (!(it->OperandMask & (1 << NextOpNum)))\n";
30260b57cec5SDimitry Andric   OS << "      continue;\n\n";
30270b57cec5SDimitry Andric 
30280b57cec5SDimitry Andric   // Emit call to the custom parser method
3029bdd1243dSDimitry Andric   StringRef ParserName = AsmParser.getValueAsString("OperandParserMethod");
3030bdd1243dSDimitry Andric   if (ParserName.empty())
3031bdd1243dSDimitry Andric     ParserName = "tryCustomParseOperand";
30320b57cec5SDimitry Andric   OS << "    // call custom parse method to handle the operand\n";
303306c3fb27SDimitry Andric   OS << "    ParseStatus Result = " << ParserName << "(Operands, it->Class);\n";
303406c3fb27SDimitry Andric   OS << "    if (!Result.isNoMatch())\n";
30350b57cec5SDimitry Andric   OS << "      return Result;\n";
30360b57cec5SDimitry Andric   OS << "  }\n\n";
30370b57cec5SDimitry Andric 
30380b57cec5SDimitry Andric   OS << "  // Okay, we had no match.\n";
303906c3fb27SDimitry Andric   OS << "  return ParseStatus::NoMatch;\n";
30400b57cec5SDimitry Andric   OS << "}\n\n";
30410b57cec5SDimitry Andric }
30420b57cec5SDimitry Andric 
30430b57cec5SDimitry Andric static void emitAsmTiedOperandConstraints(CodeGenTarget &Target,
3044*0fca6ea1SDimitry Andric                                           AsmMatcherInfo &Info, raw_ostream &OS,
3045*0fca6ea1SDimitry Andric                                           bool HasOptionalOperands) {
30460b57cec5SDimitry Andric   std::string AsmParserName =
30475ffd83dbSDimitry Andric       std::string(Info.AsmParser->getValueAsString("AsmParserClassName"));
30480b57cec5SDimitry Andric   OS << "static bool ";
30490b57cec5SDimitry Andric   OS << "checkAsmTiedOperandConstraints(const " << Target.getName()
30500b57cec5SDimitry Andric      << AsmParserName << "&AsmParser,\n";
3051*0fca6ea1SDimitry Andric   OS << "                               unsigned Kind, const OperandVector "
3052*0fca6ea1SDimitry Andric         "&Operands,\n";
3053*0fca6ea1SDimitry Andric   if (HasOptionalOperands)
3054*0fca6ea1SDimitry Andric     OS << "                               ArrayRef<unsigned> DefaultsOffset,\n";
30550b57cec5SDimitry Andric   OS << "                               uint64_t &ErrorInfo) {\n";
30560b57cec5SDimitry Andric   OS << "  assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n";
30570b57cec5SDimitry Andric   OS << "  const uint8_t *Converter = ConversionTable[Kind];\n";
30580b57cec5SDimitry Andric   OS << "  for (const uint8_t *p = Converter; *p; p += 2) {\n";
30590b57cec5SDimitry Andric   OS << "    switch (*p) {\n";
30600b57cec5SDimitry Andric   OS << "    case CVT_Tied: {\n";
30610b57cec5SDimitry Andric   OS << "      unsigned OpIdx = *(p + 1);\n";
30620b57cec5SDimitry Andric   OS << "      assert(OpIdx < (size_t)(std::end(TiedAsmOperandTable) -\n";
30630b57cec5SDimitry Andric   OS << "                              std::begin(TiedAsmOperandTable)) &&\n";
30640b57cec5SDimitry Andric   OS << "             \"Tied operand not found\");\n";
30650b57cec5SDimitry Andric   OS << "      unsigned OpndNum1 = TiedAsmOperandTable[OpIdx][1];\n";
30660b57cec5SDimitry Andric   OS << "      unsigned OpndNum2 = TiedAsmOperandTable[OpIdx][2];\n";
3067*0fca6ea1SDimitry Andric   if (HasOptionalOperands) {
3068*0fca6ea1SDimitry Andric     // When optional operands are involved, formal and actual operand indices
3069*0fca6ea1SDimitry Andric     // may differ. Map the former to the latter by subtracting the number of
3070*0fca6ea1SDimitry Andric     // absent optional operands.
3071*0fca6ea1SDimitry Andric     OS << "      OpndNum1 = OpndNum1 - DefaultsOffset[OpndNum1];\n";
3072*0fca6ea1SDimitry Andric     OS << "      OpndNum2 = OpndNum2 - DefaultsOffset[OpndNum2];\n";
3073*0fca6ea1SDimitry Andric   }
30740b57cec5SDimitry Andric   OS << "      if (OpndNum1 != OpndNum2) {\n";
30750b57cec5SDimitry Andric   OS << "        auto &SrcOp1 = Operands[OpndNum1];\n";
30760b57cec5SDimitry Andric   OS << "        auto &SrcOp2 = Operands[OpndNum2];\n";
3077bdd1243dSDimitry Andric   OS << "        if (!AsmParser.areEqualRegs(*SrcOp1, *SrcOp2)) {\n";
30780b57cec5SDimitry Andric   OS << "          ErrorInfo = OpndNum2;\n";
30790b57cec5SDimitry Andric   OS << "          return false;\n";
30800b57cec5SDimitry Andric   OS << "        }\n";
30810b57cec5SDimitry Andric   OS << "      }\n";
30820b57cec5SDimitry Andric   OS << "      break;\n";
30830b57cec5SDimitry Andric   OS << "    }\n";
30840b57cec5SDimitry Andric   OS << "    default:\n";
30850b57cec5SDimitry Andric   OS << "      break;\n";
30860b57cec5SDimitry Andric   OS << "    }\n";
30870b57cec5SDimitry Andric   OS << "  }\n";
30880b57cec5SDimitry Andric   OS << "  return true;\n";
30890b57cec5SDimitry Andric   OS << "}\n\n";
30900b57cec5SDimitry Andric }
30910b57cec5SDimitry Andric 
30920b57cec5SDimitry Andric static void emitMnemonicSpellChecker(raw_ostream &OS, CodeGenTarget &Target,
30930b57cec5SDimitry Andric                                      unsigned VariantCount) {
30940b57cec5SDimitry Andric   OS << "static std::string " << Target.getName()
30950b57cec5SDimitry Andric      << "MnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,"
30960b57cec5SDimitry Andric      << " unsigned VariantID) {\n";
30970b57cec5SDimitry Andric   if (!VariantCount)
30980b57cec5SDimitry Andric     OS << "  return \"\";";
30990b57cec5SDimitry Andric   else {
31000b57cec5SDimitry Andric     OS << "  const unsigned MaxEditDist = 2;\n";
31010b57cec5SDimitry Andric     OS << "  std::vector<StringRef> Candidates;\n";
31020b57cec5SDimitry Andric     OS << "  StringRef Prev = \"\";\n\n";
31030b57cec5SDimitry Andric 
31040b57cec5SDimitry Andric     OS << "  // Find the appropriate table for this asm variant.\n";
31050b57cec5SDimitry Andric     OS << "  const MatchEntry *Start, *End;\n";
31060b57cec5SDimitry Andric     OS << "  switch (VariantID) {\n";
31070b57cec5SDimitry Andric     OS << "  default: llvm_unreachable(\"invalid variant!\");\n";
31080b57cec5SDimitry Andric     for (unsigned VC = 0; VC != VariantCount; ++VC) {
31090b57cec5SDimitry Andric       Record *AsmVariant = Target.getAsmParserVariant(VC);
31100b57cec5SDimitry Andric       int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
31110b57cec5SDimitry Andric       OS << "  case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC
31120b57cec5SDimitry Andric          << "); End = std::end(MatchTable" << VC << "); break;\n";
31130b57cec5SDimitry Andric     }
31140b57cec5SDimitry Andric     OS << "  }\n\n";
31150b57cec5SDimitry Andric     OS << "  for (auto I = Start; I < End; I++) {\n";
31160b57cec5SDimitry Andric     OS << "    // Ignore unsupported instructions.\n";
31170b57cec5SDimitry Andric     OS << "    const FeatureBitset &RequiredFeatures = "
31180b57cec5SDimitry Andric           "FeatureBitsets[I->RequiredFeaturesIdx];\n";
31190b57cec5SDimitry Andric     OS << "    if ((FBS & RequiredFeatures) != RequiredFeatures)\n";
31200b57cec5SDimitry Andric     OS << "      continue;\n";
31210b57cec5SDimitry Andric     OS << "\n";
31220b57cec5SDimitry Andric     OS << "    StringRef T = I->getMnemonic();\n";
31230b57cec5SDimitry Andric     OS << "    // Avoid recomputing the edit distance for the same string.\n";
3124*0fca6ea1SDimitry Andric     OS << "    if (T == Prev)\n";
31250b57cec5SDimitry Andric     OS << "      continue;\n";
31260b57cec5SDimitry Andric     OS << "\n";
31270b57cec5SDimitry Andric     OS << "    Prev = T;\n";
31280b57cec5SDimitry Andric     OS << "    unsigned Dist = S.edit_distance(T, false, MaxEditDist);\n";
31290b57cec5SDimitry Andric     OS << "    if (Dist <= MaxEditDist)\n";
31300b57cec5SDimitry Andric     OS << "      Candidates.push_back(T);\n";
31310b57cec5SDimitry Andric     OS << "  }\n";
31320b57cec5SDimitry Andric     OS << "\n";
31330b57cec5SDimitry Andric     OS << "  if (Candidates.empty())\n";
31340b57cec5SDimitry Andric     OS << "    return \"\";\n";
31350b57cec5SDimitry Andric     OS << "\n";
31360b57cec5SDimitry Andric     OS << "  std::string Res = \", did you mean: \";\n";
31370b57cec5SDimitry Andric     OS << "  unsigned i = 0;\n";
31380b57cec5SDimitry Andric     OS << "  for (; i < Candidates.size() - 1; i++)\n";
31390b57cec5SDimitry Andric     OS << "    Res += Candidates[i].str() + \", \";\n";
31400b57cec5SDimitry Andric     OS << "  return Res + Candidates[i].str() + \"?\";\n";
31410b57cec5SDimitry Andric   }
31420b57cec5SDimitry Andric   OS << "}\n";
31430b57cec5SDimitry Andric   OS << "\n";
31440b57cec5SDimitry Andric }
31450b57cec5SDimitry Andric 
3146*0fca6ea1SDimitry Andric static void emitMnemonicChecker(raw_ostream &OS, CodeGenTarget &Target,
3147*0fca6ea1SDimitry Andric                                 unsigned VariantCount, bool HasMnemonicFirst,
3148e8d8bef9SDimitry Andric                                 bool HasMnemonicAliases) {
3149e8d8bef9SDimitry Andric   OS << "static bool " << Target.getName()
3150e8d8bef9SDimitry Andric      << "CheckMnemonic(StringRef Mnemonic,\n";
3151e8d8bef9SDimitry Andric   OS << "                                "
3152e8d8bef9SDimitry Andric      << "const FeatureBitset &AvailableFeatures,\n";
3153e8d8bef9SDimitry Andric   OS << "                                "
3154e8d8bef9SDimitry Andric      << "unsigned VariantID) {\n";
3155e8d8bef9SDimitry Andric 
3156e8d8bef9SDimitry Andric   if (!VariantCount) {
3157e8d8bef9SDimitry Andric     OS << "  return false;\n";
3158e8d8bef9SDimitry Andric   } else {
3159e8d8bef9SDimitry Andric     if (HasMnemonicAliases) {
3160e8d8bef9SDimitry Andric       OS << "  // Process all MnemonicAliases to remap the mnemonic.\n";
3161e8d8bef9SDimitry Andric       OS << "  applyMnemonicAliases(Mnemonic, AvailableFeatures, VariantID);";
3162e8d8bef9SDimitry Andric       OS << "\n\n";
3163e8d8bef9SDimitry Andric     }
3164e8d8bef9SDimitry Andric     OS << "  // Find the appropriate table for this asm variant.\n";
3165e8d8bef9SDimitry Andric     OS << "  const MatchEntry *Start, *End;\n";
3166e8d8bef9SDimitry Andric     OS << "  switch (VariantID) {\n";
3167e8d8bef9SDimitry Andric     OS << "  default: llvm_unreachable(\"invalid variant!\");\n";
3168e8d8bef9SDimitry Andric     for (unsigned VC = 0; VC != VariantCount; ++VC) {
3169e8d8bef9SDimitry Andric       Record *AsmVariant = Target.getAsmParserVariant(VC);
3170e8d8bef9SDimitry Andric       int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
3171e8d8bef9SDimitry Andric       OS << "  case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC
3172e8d8bef9SDimitry Andric          << "); End = std::end(MatchTable" << VC << "); break;\n";
3173e8d8bef9SDimitry Andric     }
3174e8d8bef9SDimitry Andric     OS << "  }\n\n";
3175e8d8bef9SDimitry Andric 
3176e8d8bef9SDimitry Andric     OS << "  // Search the table.\n";
3177e8d8bef9SDimitry Andric     if (HasMnemonicFirst) {
3178e8d8bef9SDimitry Andric       OS << "  auto MnemonicRange = "
3179e8d8bef9SDimitry Andric             "std::equal_range(Start, End, Mnemonic, LessOpcode());\n\n";
3180e8d8bef9SDimitry Andric     } else {
3181*0fca6ea1SDimitry Andric       OS << "  auto MnemonicRange = std::pair(Start, End);\n";
3182e8d8bef9SDimitry Andric       OS << "  unsigned SIndex = Mnemonic.empty() ? 0 : 1;\n";
3183e8d8bef9SDimitry Andric       OS << "  if (!Mnemonic.empty())\n";
3184e8d8bef9SDimitry Andric       OS << "    MnemonicRange = "
3185e8d8bef9SDimitry Andric          << "std::equal_range(Start, End, Mnemonic.lower(), LessOpcode());\n\n";
3186e8d8bef9SDimitry Andric     }
3187e8d8bef9SDimitry Andric 
3188e8d8bef9SDimitry Andric     OS << "  if (MnemonicRange.first == MnemonicRange.second)\n";
3189e8d8bef9SDimitry Andric     OS << "    return false;\n\n";
3190e8d8bef9SDimitry Andric 
3191e8d8bef9SDimitry Andric     OS << "  for (const MatchEntry *it = MnemonicRange.first, "
3192e8d8bef9SDimitry Andric        << "*ie = MnemonicRange.second;\n";
3193e8d8bef9SDimitry Andric     OS << "       it != ie; ++it) {\n";
3194e8d8bef9SDimitry Andric     OS << "    const FeatureBitset &RequiredFeatures =\n";
3195e8d8bef9SDimitry Andric     OS << "      FeatureBitsets[it->RequiredFeaturesIdx];\n";
3196e8d8bef9SDimitry Andric     OS << "    if ((AvailableFeatures & RequiredFeatures) == ";
3197e8d8bef9SDimitry Andric     OS << "RequiredFeatures)\n";
3198e8d8bef9SDimitry Andric     OS << "      return true;\n";
3199e8d8bef9SDimitry Andric     OS << "  }\n";
3200e8d8bef9SDimitry Andric     OS << "  return false;\n";
3201e8d8bef9SDimitry Andric   }
3202e8d8bef9SDimitry Andric   OS << "}\n";
3203e8d8bef9SDimitry Andric   OS << "\n";
3204e8d8bef9SDimitry Andric }
32050b57cec5SDimitry Andric 
32060b57cec5SDimitry Andric // Emit a function mapping match classes to strings, for debugging.
32070b57cec5SDimitry Andric static void emitMatchClassKindNames(std::forward_list<ClassInfo> &Infos,
32080b57cec5SDimitry Andric                                     raw_ostream &OS) {
32090b57cec5SDimitry Andric   OS << "#ifndef NDEBUG\n";
32100b57cec5SDimitry Andric   OS << "const char *getMatchClassName(MatchClassKind Kind) {\n";
32110b57cec5SDimitry Andric   OS << "  switch (Kind) {\n";
32120b57cec5SDimitry Andric 
32130b57cec5SDimitry Andric   OS << "  case InvalidMatchClass: return \"InvalidMatchClass\";\n";
32140b57cec5SDimitry Andric   OS << "  case OptionalMatchClass: return \"OptionalMatchClass\";\n";
32150b57cec5SDimitry Andric   for (const auto &CI : Infos) {
32160b57cec5SDimitry Andric     OS << "  case " << CI.Name << ": return \"" << CI.Name << "\";\n";
32170b57cec5SDimitry Andric   }
32180b57cec5SDimitry Andric   OS << "  case NumMatchClassKinds: return \"NumMatchClassKinds\";\n";
32190b57cec5SDimitry Andric 
32200b57cec5SDimitry Andric   OS << "  }\n";
32210b57cec5SDimitry Andric   OS << "  llvm_unreachable(\"unhandled MatchClassKind!\");\n";
32220b57cec5SDimitry Andric   OS << "}\n\n";
32230b57cec5SDimitry Andric   OS << "#endif // NDEBUG\n";
32240b57cec5SDimitry Andric }
32250b57cec5SDimitry Andric 
32260b57cec5SDimitry Andric static std::string
32270b57cec5SDimitry Andric getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset) {
32280b57cec5SDimitry Andric   std::string Name = "AMFBS";
32290b57cec5SDimitry Andric   for (const auto &Feature : FeatureBitset)
32300b57cec5SDimitry Andric     Name += ("_" + Feature->getName()).str();
32310b57cec5SDimitry Andric   return Name;
32320b57cec5SDimitry Andric }
32330b57cec5SDimitry Andric 
32340b57cec5SDimitry Andric void AsmMatcherEmitter::run(raw_ostream &OS) {
32350b57cec5SDimitry Andric   CodeGenTarget Target(Records);
32360b57cec5SDimitry Andric   Record *AsmParser = Target.getAsmParser();
32370b57cec5SDimitry Andric   StringRef ClassName = AsmParser->getValueAsString("AsmParserClassName");
32380b57cec5SDimitry Andric 
32395f757f3fSDimitry Andric   emitSourceFileHeader("Assembly Matcher Source Fragment", OS, Records);
324006c3fb27SDimitry Andric 
32410b57cec5SDimitry Andric   // Compute the information on the instructions to match.
32420b57cec5SDimitry Andric   AsmMatcherInfo Info(AsmParser, Target, Records);
32430b57cec5SDimitry Andric   Info.buildInfo();
32440b57cec5SDimitry Andric 
3245*0fca6ea1SDimitry Andric   bool PreferSmallerInstructions = getPreferSmallerInstructions(Target);
32460b57cec5SDimitry Andric   // Sort the instruction table using the partial order on classes. We use
32470b57cec5SDimitry Andric   // stable_sort to ensure that ambiguous instructions are still
32480b57cec5SDimitry Andric   // deterministically ordered.
32490b57cec5SDimitry Andric   llvm::stable_sort(
32500b57cec5SDimitry Andric       Info.Matchables,
3251*0fca6ea1SDimitry Andric       [PreferSmallerInstructions](const std::unique_ptr<MatchableInfo> &A,
3252*0fca6ea1SDimitry Andric                                   const std::unique_ptr<MatchableInfo> &B) {
3253*0fca6ea1SDimitry Andric         return A->shouldBeMatchedBefore(*B, PreferSmallerInstructions);
3254*0fca6ea1SDimitry Andric       });
32550b57cec5SDimitry Andric 
32560b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
32570b57cec5SDimitry Andric   // Verify that the table is sorted and operator < works transitively.
32580b57cec5SDimitry Andric   for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E;
32590b57cec5SDimitry Andric        ++I) {
32600b57cec5SDimitry Andric     for (auto J = I; J != E; ++J) {
3261*0fca6ea1SDimitry Andric       assert(!(*J)->shouldBeMatchedBefore(**I, PreferSmallerInstructions));
32620b57cec5SDimitry Andric     }
32630b57cec5SDimitry Andric   }
32640b57cec5SDimitry Andric #endif
32650b57cec5SDimitry Andric 
32660b57cec5SDimitry Andric   DEBUG_WITH_TYPE("instruction_info", {
32670b57cec5SDimitry Andric     for (const auto &MI : Info.Matchables)
32680b57cec5SDimitry Andric       MI->dump();
32690b57cec5SDimitry Andric   });
32700b57cec5SDimitry Andric 
32710b57cec5SDimitry Andric   // Check for ambiguous matchables.
32720b57cec5SDimitry Andric   DEBUG_WITH_TYPE("ambiguous_instrs", {
32730b57cec5SDimitry Andric     unsigned NumAmbiguous = 0;
32740b57cec5SDimitry Andric     for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E;
32750b57cec5SDimitry Andric          ++I) {
32760b57cec5SDimitry Andric       for (auto J = std::next(I); J != E; ++J) {
32770b57cec5SDimitry Andric         const MatchableInfo &A = **I;
32780b57cec5SDimitry Andric         const MatchableInfo &B = **J;
32790b57cec5SDimitry Andric 
3280*0fca6ea1SDimitry Andric         if (A.couldMatchAmbiguouslyWith(B, PreferSmallerInstructions)) {
32810b57cec5SDimitry Andric           errs() << "warning: ambiguous matchables:\n";
32820b57cec5SDimitry Andric           A.dump();
32830b57cec5SDimitry Andric           errs() << "\nis incomparable with:\n";
32840b57cec5SDimitry Andric           B.dump();
32850b57cec5SDimitry Andric           errs() << "\n\n";
32860b57cec5SDimitry Andric           ++NumAmbiguous;
32870b57cec5SDimitry Andric         }
32880b57cec5SDimitry Andric       }
32890b57cec5SDimitry Andric     }
32900b57cec5SDimitry Andric     if (NumAmbiguous)
3291*0fca6ea1SDimitry Andric       errs() << "warning: " << NumAmbiguous << " ambiguous matchables!\n";
32920b57cec5SDimitry Andric   });
32930b57cec5SDimitry Andric 
32940b57cec5SDimitry Andric   // Compute the information on the custom operand parsing.
32950b57cec5SDimitry Andric   Info.buildOperandMatchInfo();
32960b57cec5SDimitry Andric 
32970b57cec5SDimitry Andric   bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst");
32980b57cec5SDimitry Andric   bool HasOptionalOperands = Info.hasOptionalOperands();
32990b57cec5SDimitry Andric   bool ReportMultipleNearMisses =
33000b57cec5SDimitry Andric       AsmParser->getValueAsBit("ReportMultipleNearMisses");
33010b57cec5SDimitry Andric 
33020b57cec5SDimitry Andric   // Write the output.
33030b57cec5SDimitry Andric 
33040b57cec5SDimitry Andric   // Information for the class declaration.
33050b57cec5SDimitry Andric   OS << "\n#ifdef GET_ASSEMBLER_HEADER\n";
33060b57cec5SDimitry Andric   OS << "#undef GET_ASSEMBLER_HEADER\n";
33070b57cec5SDimitry Andric   OS << "  // This should be included into the middle of the declaration of\n";
33080b57cec5SDimitry Andric   OS << "  // your subclasses implementation of MCTargetAsmParser.\n";
3309*0fca6ea1SDimitry Andric   OS << "  FeatureBitset ComputeAvailableFeatures(const FeatureBitset &FB) "
3310*0fca6ea1SDimitry Andric         "const;\n";
33110b57cec5SDimitry Andric   if (HasOptionalOperands) {
33120b57cec5SDimitry Andric     OS << "  void convertToMCInst(unsigned Kind, MCInst &Inst, "
33130b57cec5SDimitry Andric        << "unsigned Opcode,\n"
33140b57cec5SDimitry Andric        << "                       const OperandVector &Operands,\n"
3315*0fca6ea1SDimitry Andric        << "                       const SmallBitVector "
3316*0fca6ea1SDimitry Andric           "&OptionalOperandsMask,\n"
3317*0fca6ea1SDimitry Andric        << "                       ArrayRef<unsigned> DefaultsOffset);\n";
33180b57cec5SDimitry Andric   } else {
33190b57cec5SDimitry Andric     OS << "  void convertToMCInst(unsigned Kind, MCInst &Inst, "
33200b57cec5SDimitry Andric        << "unsigned Opcode,\n"
33210b57cec5SDimitry Andric        << "                       const OperandVector &Operands);\n";
33220b57cec5SDimitry Andric   }
33230b57cec5SDimitry Andric   OS << "  void convertToMapAndConstraints(unsigned Kind,\n                ";
33240b57cec5SDimitry Andric   OS << "           const OperandVector &Operands) override;\n";
33250b57cec5SDimitry Andric   OS << "  unsigned MatchInstructionImpl(const OperandVector &Operands,\n"
33260b57cec5SDimitry Andric      << "                                MCInst &Inst,\n";
33270b57cec5SDimitry Andric   if (ReportMultipleNearMisses)
3328*0fca6ea1SDimitry Andric     OS << "                                SmallVectorImpl<NearMissInfo> "
3329*0fca6ea1SDimitry Andric           "*NearMisses,\n";
33300b57cec5SDimitry Andric   else
33310b57cec5SDimitry Andric     OS << "                                uint64_t &ErrorInfo,\n"
33320b57cec5SDimitry Andric        << "                                FeatureBitset &MissingFeatures,\n";
33330b57cec5SDimitry Andric   OS << "                                bool matchingInlineAsm,\n"
33340b57cec5SDimitry Andric      << "                                unsigned VariantID = 0);\n";
33350b57cec5SDimitry Andric   if (!ReportMultipleNearMisses)
33360b57cec5SDimitry Andric     OS << "  unsigned MatchInstructionImpl(const OperandVector &Operands,\n"
33370b57cec5SDimitry Andric        << "                                MCInst &Inst,\n"
33380b57cec5SDimitry Andric        << "                                uint64_t &ErrorInfo,\n"
33390b57cec5SDimitry Andric        << "                                bool matchingInlineAsm,\n"
33400b57cec5SDimitry Andric        << "                                unsigned VariantID = 0) {\n"
33410b57cec5SDimitry Andric        << "    FeatureBitset MissingFeatures;\n"
3342*0fca6ea1SDimitry Andric        << "    return MatchInstructionImpl(Operands, Inst, ErrorInfo, "
3343*0fca6ea1SDimitry Andric           "MissingFeatures,\n"
33440b57cec5SDimitry Andric        << "                                matchingInlineAsm, VariantID);\n"
33450b57cec5SDimitry Andric        << "  }\n\n";
33460b57cec5SDimitry Andric 
33470b57cec5SDimitry Andric   if (!Info.OperandMatchInfo.empty()) {
334806c3fb27SDimitry Andric     OS << "  ParseStatus MatchOperandParserImpl(\n";
33490b57cec5SDimitry Andric     OS << "    OperandVector &Operands,\n";
33500b57cec5SDimitry Andric     OS << "    StringRef Mnemonic,\n";
33510b57cec5SDimitry Andric     OS << "    bool ParseForAllFeatures = false);\n";
33520b57cec5SDimitry Andric 
335306c3fb27SDimitry Andric     OS << "  ParseStatus tryCustomParseOperand(\n";
33540b57cec5SDimitry Andric     OS << "    OperandVector &Operands,\n";
33550b57cec5SDimitry Andric     OS << "    unsigned MCK);\n\n";
33560b57cec5SDimitry Andric   }
33570b57cec5SDimitry Andric 
3358cb14a3feSDimitry Andric   OS << "#endif // GET_ASSEMBLER_HEADER\n\n";
33590b57cec5SDimitry Andric 
33600b57cec5SDimitry Andric   // Emit the operand match diagnostic enum names.
33610b57cec5SDimitry Andric   OS << "\n#ifdef GET_OPERAND_DIAGNOSTIC_TYPES\n";
33620b57cec5SDimitry Andric   OS << "#undef GET_OPERAND_DIAGNOSTIC_TYPES\n\n";
33630b57cec5SDimitry Andric   emitOperandDiagnosticTypes(Info, OS);
33640b57cec5SDimitry Andric   OS << "#endif // GET_OPERAND_DIAGNOSTIC_TYPES\n\n";
33650b57cec5SDimitry Andric 
33660b57cec5SDimitry Andric   OS << "\n#ifdef GET_REGISTER_MATCHER\n";
33670b57cec5SDimitry Andric   OS << "#undef GET_REGISTER_MATCHER\n\n";
33680b57cec5SDimitry Andric 
33690b57cec5SDimitry Andric   // Emit the subtarget feature enumeration.
33700b57cec5SDimitry Andric   SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(
33710b57cec5SDimitry Andric       Info.SubtargetFeatures, OS);
33720b57cec5SDimitry Andric 
33730b57cec5SDimitry Andric   // Emit the function to match a register name to number.
33740b57cec5SDimitry Andric   // This should be omitted for Mips target
33750b57cec5SDimitry Andric   if (AsmParser->getValueAsBit("ShouldEmitMatchRegisterName"))
33760b57cec5SDimitry Andric     emitMatchRegisterName(Target, AsmParser, OS);
33770b57cec5SDimitry Andric 
33780b57cec5SDimitry Andric   if (AsmParser->getValueAsBit("ShouldEmitMatchRegisterAltName"))
33790b57cec5SDimitry Andric     emitMatchRegisterAltName(Target, AsmParser, OS);
33800b57cec5SDimitry Andric 
33810b57cec5SDimitry Andric   OS << "#endif // GET_REGISTER_MATCHER\n\n";
33820b57cec5SDimitry Andric 
33830b57cec5SDimitry Andric   OS << "\n#ifdef GET_SUBTARGET_FEATURE_NAME\n";
33840b57cec5SDimitry Andric   OS << "#undef GET_SUBTARGET_FEATURE_NAME\n\n";
33850b57cec5SDimitry Andric 
33860b57cec5SDimitry Andric   // Generate the helper function to get the names for subtarget features.
33870b57cec5SDimitry Andric   emitGetSubtargetFeatureName(Info, OS);
33880b57cec5SDimitry Andric 
33890b57cec5SDimitry Andric   OS << "#endif // GET_SUBTARGET_FEATURE_NAME\n\n";
33900b57cec5SDimitry Andric 
33910b57cec5SDimitry Andric   OS << "\n#ifdef GET_MATCHER_IMPLEMENTATION\n";
33920b57cec5SDimitry Andric   OS << "#undef GET_MATCHER_IMPLEMENTATION\n\n";
33930b57cec5SDimitry Andric 
33940b57cec5SDimitry Andric   // Generate the function that remaps for mnemonic aliases.
33950b57cec5SDimitry Andric   bool HasMnemonicAliases = emitMnemonicAliases(OS, Info, Target);
33960b57cec5SDimitry Andric 
33970b57cec5SDimitry Andric   // Generate the convertToMCInst function to convert operands into an MCInst.
33980b57cec5SDimitry Andric   // Also, generate the convertToMapAndConstraints function for MS-style inline
33990b57cec5SDimitry Andric   // assembly.  The latter doesn't actually generate a MCInst.
3400*0fca6ea1SDimitry Andric   unsigned NumConverters =
3401*0fca6ea1SDimitry Andric       emitConvertFuncs(Target, ClassName, Info.Matchables, HasMnemonicFirst,
34020b57cec5SDimitry Andric                        HasOptionalOperands, OS);
34030b57cec5SDimitry Andric 
34040b57cec5SDimitry Andric   // Emit the enumeration for classes which participate in matching.
34050b57cec5SDimitry Andric   emitMatchClassEnumeration(Target, Info.Classes, OS);
34060b57cec5SDimitry Andric 
34070b57cec5SDimitry Andric   // Emit a function to get the user-visible string to describe an operand
34080b57cec5SDimitry Andric   // match failure in diagnostics.
34090b57cec5SDimitry Andric   emitOperandMatchErrorDiagStrings(Info, OS);
34100b57cec5SDimitry Andric 
34110b57cec5SDimitry Andric   // Emit a function to map register classes to operand match failure codes.
34120b57cec5SDimitry Andric   emitRegisterMatchErrorFunc(Info, OS);
34130b57cec5SDimitry Andric 
34140b57cec5SDimitry Andric   // Emit the routine to match token strings to their match class.
34150b57cec5SDimitry Andric   emitMatchTokenString(Target, Info.Classes, OS);
34160b57cec5SDimitry Andric 
34170b57cec5SDimitry Andric   // Emit the subclass predicate routine.
34180b57cec5SDimitry Andric   emitIsSubclass(Target, Info.Classes, OS);
34190b57cec5SDimitry Andric 
34200b57cec5SDimitry Andric   // Emit the routine to validate an operand against a match class.
34210b57cec5SDimitry Andric   emitValidateOperandClass(Info, OS);
34220b57cec5SDimitry Andric 
34230b57cec5SDimitry Andric   emitMatchClassKindNames(Info.Classes, OS);
34240b57cec5SDimitry Andric 
34250b57cec5SDimitry Andric   // Emit the available features compute function.
34260b57cec5SDimitry Andric   SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
34270b57cec5SDimitry Andric       Info.Target.getName(), ClassName, "ComputeAvailableFeatures",
34280b57cec5SDimitry Andric       Info.SubtargetFeatures, OS);
34290b57cec5SDimitry Andric 
34300b57cec5SDimitry Andric   if (!ReportMultipleNearMisses)
3431*0fca6ea1SDimitry Andric     emitAsmTiedOperandConstraints(Target, Info, OS, HasOptionalOperands);
34320b57cec5SDimitry Andric 
34330b57cec5SDimitry Andric   StringToOffsetTable StringTable;
34340b57cec5SDimitry Andric 
34350b57cec5SDimitry Andric   size_t MaxNumOperands = 0;
34360b57cec5SDimitry Andric   unsigned MaxMnemonicIndex = 0;
34370b57cec5SDimitry Andric   bool HasDeprecation = false;
34380b57cec5SDimitry Andric   for (const auto &MI : Info.Matchables) {
34390b57cec5SDimitry Andric     MaxNumOperands = std::max(MaxNumOperands, MI->AsmOperands.size());
34400b57cec5SDimitry Andric     HasDeprecation |= MI->HasDeprecation;
34410b57cec5SDimitry Andric 
34420b57cec5SDimitry Andric     // Store a pascal-style length byte in the mnemonic.
3443e8d8bef9SDimitry Andric     std::string LenMnemonic = char(MI->Mnemonic.size()) + MI->Mnemonic.lower();
3444*0fca6ea1SDimitry Andric     MaxMnemonicIndex = std::max(
3445*0fca6ea1SDimitry Andric         MaxMnemonicIndex, StringTable.GetOrAddStringOffset(LenMnemonic, false));
34460b57cec5SDimitry Andric   }
34470b57cec5SDimitry Andric 
344881ad6265SDimitry Andric   OS << "static const char MnemonicTable[] =\n";
34490b57cec5SDimitry Andric   StringTable.EmitString(OS);
34500b57cec5SDimitry Andric   OS << ";\n\n";
34510b57cec5SDimitry Andric 
34520b57cec5SDimitry Andric   std::vector<std::vector<Record *>> FeatureBitsets;
34530b57cec5SDimitry Andric   for (const auto &MI : Info.Matchables) {
34540b57cec5SDimitry Andric     if (MI->RequiredFeatures.empty())
34550b57cec5SDimitry Andric       continue;
34560b57cec5SDimitry Andric     FeatureBitsets.emplace_back();
34570b57cec5SDimitry Andric     for (unsigned I = 0, E = MI->RequiredFeatures.size(); I != E; ++I)
34580b57cec5SDimitry Andric       FeatureBitsets.back().push_back(MI->RequiredFeatures[I]->TheDef);
34590b57cec5SDimitry Andric   }
34600b57cec5SDimitry Andric 
34610b57cec5SDimitry Andric   llvm::sort(FeatureBitsets, [&](const std::vector<Record *> &A,
34620b57cec5SDimitry Andric                                  const std::vector<Record *> &B) {
34630b57cec5SDimitry Andric     if (A.size() < B.size())
34640b57cec5SDimitry Andric       return true;
34650b57cec5SDimitry Andric     if (A.size() > B.size())
34660b57cec5SDimitry Andric       return false;
3467480093f4SDimitry Andric     for (auto Pair : zip(A, B)) {
34680b57cec5SDimitry Andric       if (std::get<0>(Pair)->getName() < std::get<1>(Pair)->getName())
34690b57cec5SDimitry Andric         return true;
34700b57cec5SDimitry Andric       if (std::get<0>(Pair)->getName() > std::get<1>(Pair)->getName())
34710b57cec5SDimitry Andric         return false;
34720b57cec5SDimitry Andric     }
34730b57cec5SDimitry Andric     return false;
34740b57cec5SDimitry Andric   });
3475*0fca6ea1SDimitry Andric   FeatureBitsets.erase(llvm::unique(FeatureBitsets), FeatureBitsets.end());
34760b57cec5SDimitry Andric   OS << "// Feature bitsets.\n"
34770b57cec5SDimitry Andric      << "enum : " << getMinimalTypeForRange(FeatureBitsets.size()) << " {\n"
34780b57cec5SDimitry Andric      << "  AMFBS_None,\n";
34790b57cec5SDimitry Andric   for (const auto &FeatureBitset : FeatureBitsets) {
34800b57cec5SDimitry Andric     if (FeatureBitset.empty())
34810b57cec5SDimitry Andric       continue;
34820b57cec5SDimitry Andric     OS << "  " << getNameForFeatureBitset(FeatureBitset) << ",\n";
34830b57cec5SDimitry Andric   }
34840b57cec5SDimitry Andric   OS << "};\n\n"
34858bcb0991SDimitry Andric      << "static constexpr FeatureBitset FeatureBitsets[] = {\n"
34860b57cec5SDimitry Andric      << "  {}, // AMFBS_None\n";
34870b57cec5SDimitry Andric   for (const auto &FeatureBitset : FeatureBitsets) {
34880b57cec5SDimitry Andric     if (FeatureBitset.empty())
34890b57cec5SDimitry Andric       continue;
34900b57cec5SDimitry Andric     OS << "  {";
34910b57cec5SDimitry Andric     for (const auto &Feature : FeatureBitset) {
34920b57cec5SDimitry Andric       const auto &I = Info.SubtargetFeatures.find(Feature);
34930b57cec5SDimitry Andric       assert(I != Info.SubtargetFeatures.end() && "Didn't import predicate?");
34940b57cec5SDimitry Andric       OS << I->second.getEnumBitName() << ", ";
34950b57cec5SDimitry Andric     }
34960b57cec5SDimitry Andric     OS << "},\n";
34970b57cec5SDimitry Andric   }
34980b57cec5SDimitry Andric   OS << "};\n\n";
34990b57cec5SDimitry Andric 
35000b57cec5SDimitry Andric   // Emit the static match table; unused classes get initialized to 0 which is
35010b57cec5SDimitry Andric   // guaranteed to be InvalidMatchClass.
35020b57cec5SDimitry Andric   //
35030b57cec5SDimitry Andric   // FIXME: We can reduce the size of this table very easily. First, we change
35040b57cec5SDimitry Andric   // it so that store the kinds in separate bit-fields for each index, which
35050b57cec5SDimitry Andric   // only needs to be the max width used for classes at that index (we also need
35060b57cec5SDimitry Andric   // to reject based on this during classification). If we then make sure to
35070b57cec5SDimitry Andric   // order the match kinds appropriately (putting mnemonics last), then we
35080b57cec5SDimitry Andric   // should only end up using a few bits for each class, especially the ones
35090b57cec5SDimitry Andric   // following the mnemonic.
35100b57cec5SDimitry Andric   OS << "namespace {\n";
35110b57cec5SDimitry Andric   OS << "  struct MatchEntry {\n";
3512*0fca6ea1SDimitry Andric   OS << "    " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n";
35130b57cec5SDimitry Andric   OS << "    uint16_t Opcode;\n";
3514*0fca6ea1SDimitry Andric   OS << "    " << getMinimalTypeForRange(NumConverters) << " ConvertFn;\n";
35150b57cec5SDimitry Andric   OS << "    " << getMinimalTypeForRange(FeatureBitsets.size())
35160b57cec5SDimitry Andric      << " RequiredFeaturesIdx;\n";
3517*0fca6ea1SDimitry Andric   OS << "    "
3518*0fca6ea1SDimitry Andric      << getMinimalTypeForRange(
3519*0fca6ea1SDimitry Andric             std::distance(Info.Classes.begin(), Info.Classes.end()) +
3520*0fca6ea1SDimitry Andric             2 /* Include 'InvalidMatchClass' and 'OptionalMatchClass' */)
35210b57cec5SDimitry Andric      << " Classes[" << MaxNumOperands << "];\n";
35220b57cec5SDimitry Andric   OS << "    StringRef getMnemonic() const {\n";
35230b57cec5SDimitry Andric   OS << "      return StringRef(MnemonicTable + Mnemonic + 1,\n";
35240b57cec5SDimitry Andric   OS << "                       MnemonicTable[Mnemonic]);\n";
35250b57cec5SDimitry Andric   OS << "    }\n";
35260b57cec5SDimitry Andric   OS << "  };\n\n";
35270b57cec5SDimitry Andric 
35280b57cec5SDimitry Andric   OS << "  // Predicate for searching for an opcode.\n";
35290b57cec5SDimitry Andric   OS << "  struct LessOpcode {\n";
35300b57cec5SDimitry Andric   OS << "    bool operator()(const MatchEntry &LHS, StringRef RHS) {\n";
35310b57cec5SDimitry Andric   OS << "      return LHS.getMnemonic() < RHS;\n";
35320b57cec5SDimitry Andric   OS << "    }\n";
35330b57cec5SDimitry Andric   OS << "    bool operator()(StringRef LHS, const MatchEntry &RHS) {\n";
35340b57cec5SDimitry Andric   OS << "      return LHS < RHS.getMnemonic();\n";
35350b57cec5SDimitry Andric   OS << "    }\n";
35360b57cec5SDimitry Andric   OS << "    bool operator()(const MatchEntry &LHS, const MatchEntry &RHS) {\n";
35370b57cec5SDimitry Andric   OS << "      return LHS.getMnemonic() < RHS.getMnemonic();\n";
35380b57cec5SDimitry Andric   OS << "    }\n";
35390b57cec5SDimitry Andric   OS << "  };\n";
35400b57cec5SDimitry Andric 
35418bcb0991SDimitry Andric   OS << "} // end anonymous namespace\n\n";
35420b57cec5SDimitry Andric 
35430b57cec5SDimitry Andric   unsigned VariantCount = Target.getAsmParserVariantCount();
35440b57cec5SDimitry Andric   for (unsigned VC = 0; VC != VariantCount; ++VC) {
35450b57cec5SDimitry Andric     Record *AsmVariant = Target.getAsmParserVariant(VC);
35460b57cec5SDimitry Andric     int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
35470b57cec5SDimitry Andric 
35480b57cec5SDimitry Andric     OS << "static const MatchEntry MatchTable" << VC << "[] = {\n";
35490b57cec5SDimitry Andric 
35500b57cec5SDimitry Andric     for (const auto &MI : Info.Matchables) {
35510b57cec5SDimitry Andric       if (MI->AsmVariantID != AsmVariantNo)
35520b57cec5SDimitry Andric         continue;
35530b57cec5SDimitry Andric 
35540b57cec5SDimitry Andric       // Store a pascal-style length byte in the mnemonic.
3555e8d8bef9SDimitry Andric       std::string LenMnemonic =
3556e8d8bef9SDimitry Andric           char(MI->Mnemonic.size()) + MI->Mnemonic.lower();
35570b57cec5SDimitry Andric       OS << "  { " << StringTable.GetOrAddStringOffset(LenMnemonic, false)
3558*0fca6ea1SDimitry Andric          << " /* " << MI->Mnemonic << " */, " << Target.getInstNamespace()
3559*0fca6ea1SDimitry Andric          << "::" << MI->getResultInst()->TheDef->getName() << ", "
35600b57cec5SDimitry Andric          << MI->ConversionFnKind << ", ";
35610b57cec5SDimitry Andric 
35620b57cec5SDimitry Andric       // Write the required features mask.
35630b57cec5SDimitry Andric       OS << "AMFBS";
35640b57cec5SDimitry Andric       if (MI->RequiredFeatures.empty())
35650b57cec5SDimitry Andric         OS << "_None";
35660b57cec5SDimitry Andric       else
35670b57cec5SDimitry Andric         for (unsigned i = 0, e = MI->RequiredFeatures.size(); i != e; ++i)
35680b57cec5SDimitry Andric           OS << '_' << MI->RequiredFeatures[i]->TheDef->getName();
35690b57cec5SDimitry Andric 
35700b57cec5SDimitry Andric       OS << ", { ";
3571fe6060f1SDimitry Andric       ListSeparator LS;
3572fe6060f1SDimitry Andric       for (const MatchableInfo::AsmOperand &Op : MI->AsmOperands)
3573fe6060f1SDimitry Andric         OS << LS << Op.Class->Name;
35740b57cec5SDimitry Andric       OS << " }, },\n";
35750b57cec5SDimitry Andric     }
35760b57cec5SDimitry Andric 
35770b57cec5SDimitry Andric     OS << "};\n\n";
35780b57cec5SDimitry Andric   }
35790b57cec5SDimitry Andric 
35800b57cec5SDimitry Andric   OS << "#include \"llvm/Support/Debug.h\"\n";
35810b57cec5SDimitry Andric   OS << "#include \"llvm/Support/Format.h\"\n\n";
35820b57cec5SDimitry Andric 
35830b57cec5SDimitry Andric   // Finally, build the match function.
35840b57cec5SDimitry Andric   OS << "unsigned " << Target.getName() << ClassName << "::\n"
35850b57cec5SDimitry Andric      << "MatchInstructionImpl(const OperandVector &Operands,\n";
35860b57cec5SDimitry Andric   OS << "                     MCInst &Inst,\n";
35870b57cec5SDimitry Andric   if (ReportMultipleNearMisses)
35880b57cec5SDimitry Andric     OS << "                     SmallVectorImpl<NearMissInfo> *NearMisses,\n";
35890b57cec5SDimitry Andric   else
35900b57cec5SDimitry Andric     OS << "                     uint64_t &ErrorInfo,\n"
35910b57cec5SDimitry Andric        << "                     FeatureBitset &MissingFeatures,\n";
35920b57cec5SDimitry Andric   OS << "                     bool matchingInlineAsm, unsigned VariantID) {\n";
35930b57cec5SDimitry Andric 
35940b57cec5SDimitry Andric   if (!ReportMultipleNearMisses) {
35950b57cec5SDimitry Andric     OS << "  // Eliminate obvious mismatches.\n";
3596*0fca6ea1SDimitry Andric     OS << "  if (Operands.size() > " << (MaxNumOperands + HasMnemonicFirst)
3597*0fca6ea1SDimitry Andric        << ") {\n";
3598*0fca6ea1SDimitry Andric     OS << "    ErrorInfo = " << (MaxNumOperands + HasMnemonicFirst) << ";\n";
35990b57cec5SDimitry Andric     OS << "    return Match_InvalidOperand;\n";
36000b57cec5SDimitry Andric     OS << "  }\n\n";
36010b57cec5SDimitry Andric   }
36020b57cec5SDimitry Andric 
36030b57cec5SDimitry Andric   // Emit code to get the available features.
36040b57cec5SDimitry Andric   OS << "  // Get the current feature set.\n";
3605*0fca6ea1SDimitry Andric   OS << "  const FeatureBitset &AvailableFeatures = "
3606*0fca6ea1SDimitry Andric         "getAvailableFeatures();\n\n";
36070b57cec5SDimitry Andric 
36080b57cec5SDimitry Andric   OS << "  // Get the instruction mnemonic, which is the first token.\n";
36090b57cec5SDimitry Andric   if (HasMnemonicFirst) {
36100b57cec5SDimitry Andric     OS << "  StringRef Mnemonic = ((" << Target.getName()
36110b57cec5SDimitry Andric        << "Operand &)*Operands[0]).getToken();\n\n";
36120b57cec5SDimitry Andric   } else {
36130b57cec5SDimitry Andric     OS << "  StringRef Mnemonic;\n";
36140b57cec5SDimitry Andric     OS << "  if (Operands[0]->isToken())\n";
36150b57cec5SDimitry Andric     OS << "    Mnemonic = ((" << Target.getName()
36160b57cec5SDimitry Andric        << "Operand &)*Operands[0]).getToken();\n\n";
36170b57cec5SDimitry Andric   }
36180b57cec5SDimitry Andric 
36190b57cec5SDimitry Andric   if (HasMnemonicAliases) {
36200b57cec5SDimitry Andric     OS << "  // Process all MnemonicAliases to remap the mnemonic.\n";
36210b57cec5SDimitry Andric     OS << "  applyMnemonicAliases(Mnemonic, AvailableFeatures, VariantID);\n\n";
36220b57cec5SDimitry Andric   }
36230b57cec5SDimitry Andric 
36240b57cec5SDimitry Andric   // Emit code to compute the class list for this operand vector.
36250b57cec5SDimitry Andric   if (!ReportMultipleNearMisses) {
36260b57cec5SDimitry Andric     OS << "  // Some state to try to produce better error messages.\n";
36270b57cec5SDimitry Andric     OS << "  bool HadMatchOtherThanFeatures = false;\n";
36280b57cec5SDimitry Andric     OS << "  bool HadMatchOtherThanPredicate = false;\n";
36290b57cec5SDimitry Andric     OS << "  unsigned RetCode = Match_InvalidOperand;\n";
36300b57cec5SDimitry Andric     OS << "  MissingFeatures.set();\n";
36310b57cec5SDimitry Andric     OS << "  // Set ErrorInfo to the operand that mismatches if it is\n";
36320b57cec5SDimitry Andric     OS << "  // wrong for all instances of the instruction.\n";
36330b57cec5SDimitry Andric     OS << "  ErrorInfo = ~0ULL;\n";
36340b57cec5SDimitry Andric   }
36350b57cec5SDimitry Andric 
36360b57cec5SDimitry Andric   if (HasOptionalOperands) {
36370b57cec5SDimitry Andric     OS << "  SmallBitVector OptionalOperandsMask(" << MaxNumOperands << ");\n";
36380b57cec5SDimitry Andric   }
36390b57cec5SDimitry Andric 
36400b57cec5SDimitry Andric   // Emit code to search the table.
36410b57cec5SDimitry Andric   OS << "  // Find the appropriate table for this asm variant.\n";
36420b57cec5SDimitry Andric   OS << "  const MatchEntry *Start, *End;\n";
36430b57cec5SDimitry Andric   OS << "  switch (VariantID) {\n";
36440b57cec5SDimitry Andric   OS << "  default: llvm_unreachable(\"invalid variant!\");\n";
36450b57cec5SDimitry Andric   for (unsigned VC = 0; VC != VariantCount; ++VC) {
36460b57cec5SDimitry Andric     Record *AsmVariant = Target.getAsmParserVariant(VC);
36470b57cec5SDimitry Andric     int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
36480b57cec5SDimitry Andric     OS << "  case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC
36490b57cec5SDimitry Andric        << "); End = std::end(MatchTable" << VC << "); break;\n";
36500b57cec5SDimitry Andric   }
36510b57cec5SDimitry Andric   OS << "  }\n";
36520b57cec5SDimitry Andric 
36530b57cec5SDimitry Andric   OS << "  // Search the table.\n";
36540b57cec5SDimitry Andric   if (HasMnemonicFirst) {
36550b57cec5SDimitry Andric     OS << "  auto MnemonicRange = "
36560b57cec5SDimitry Andric           "std::equal_range(Start, End, Mnemonic, LessOpcode());\n\n";
36570b57cec5SDimitry Andric   } else {
3658*0fca6ea1SDimitry Andric     OS << "  auto MnemonicRange = std::pair(Start, End);\n";
36590b57cec5SDimitry Andric     OS << "  unsigned SIndex = Mnemonic.empty() ? 0 : 1;\n";
36600b57cec5SDimitry Andric     OS << "  if (!Mnemonic.empty())\n";
36610b57cec5SDimitry Andric     OS << "    MnemonicRange = "
36620b57cec5SDimitry Andric           "std::equal_range(Start, End, Mnemonic.lower(), LessOpcode());\n\n";
36630b57cec5SDimitry Andric   }
36640b57cec5SDimitry Andric 
3665*0fca6ea1SDimitry Andric   OS << "  DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"AsmMatcher: found \" "
3666*0fca6ea1SDimitry Andric         "<<\n"
36670b57cec5SDimitry Andric      << "  std::distance(MnemonicRange.first, MnemonicRange.second) <<\n"
36680b57cec5SDimitry Andric      << "  \" encodings with mnemonic '\" << Mnemonic << \"'\\n\");\n\n";
36690b57cec5SDimitry Andric 
36700b57cec5SDimitry Andric   OS << "  // Return a more specific error code if no mnemonics match.\n";
36710b57cec5SDimitry Andric   OS << "  if (MnemonicRange.first == MnemonicRange.second)\n";
36720b57cec5SDimitry Andric   OS << "    return Match_MnemonicFail;\n\n";
36730b57cec5SDimitry Andric 
36740b57cec5SDimitry Andric   OS << "  for (const MatchEntry *it = MnemonicRange.first, "
36750b57cec5SDimitry Andric      << "*ie = MnemonicRange.second;\n";
36760b57cec5SDimitry Andric   OS << "       it != ie; ++it) {\n";
36770b57cec5SDimitry Andric   OS << "    const FeatureBitset &RequiredFeatures = "
36780b57cec5SDimitry Andric         "FeatureBitsets[it->RequiredFeaturesIdx];\n";
36790b57cec5SDimitry Andric   OS << "    bool HasRequiredFeatures =\n";
36800b57cec5SDimitry Andric   OS << "      (AvailableFeatures & RequiredFeatures) == RequiredFeatures;\n";
3681*0fca6ea1SDimitry Andric   OS << "    DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Trying to match "
3682*0fca6ea1SDimitry Andric         "opcode \"\n";
3683*0fca6ea1SDimitry Andric   OS << "                                          << MII.getName(it->Opcode) "
3684*0fca6ea1SDimitry Andric         "<< \"\\n\");\n";
36850b57cec5SDimitry Andric 
36860b57cec5SDimitry Andric   if (ReportMultipleNearMisses) {
3687*0fca6ea1SDimitry Andric     OS << "    // Some state to record ways in which this instruction did not "
3688*0fca6ea1SDimitry Andric           "match.\n";
36890b57cec5SDimitry Andric     OS << "    NearMissInfo OperandNearMiss = NearMissInfo::getSuccess();\n";
36900b57cec5SDimitry Andric     OS << "    NearMissInfo FeaturesNearMiss = NearMissInfo::getSuccess();\n";
3691*0fca6ea1SDimitry Andric     OS << "    NearMissInfo EarlyPredicateNearMiss = "
3692*0fca6ea1SDimitry Andric           "NearMissInfo::getSuccess();\n";
3693*0fca6ea1SDimitry Andric     OS << "    NearMissInfo LatePredicateNearMiss = "
3694*0fca6ea1SDimitry Andric           "NearMissInfo::getSuccess();\n";
36950b57cec5SDimitry Andric     OS << "    bool MultipleInvalidOperands = false;\n";
36960b57cec5SDimitry Andric   }
36970b57cec5SDimitry Andric 
36980b57cec5SDimitry Andric   if (HasMnemonicFirst) {
36990b57cec5SDimitry Andric     OS << "    // equal_range guarantees that instruction mnemonic matches.\n";
37000b57cec5SDimitry Andric     OS << "    assert(Mnemonic == it->getMnemonic());\n";
37010b57cec5SDimitry Andric   }
37020b57cec5SDimitry Andric 
37030b57cec5SDimitry Andric   // Emit check that the subclasses match.
37040b57cec5SDimitry Andric   if (!ReportMultipleNearMisses)
37050b57cec5SDimitry Andric     OS << "    bool OperandsValid = true;\n";
37060b57cec5SDimitry Andric   if (HasOptionalOperands) {
37070b57cec5SDimitry Andric     OS << "    OptionalOperandsMask.reset(0, " << MaxNumOperands << ");\n";
37080b57cec5SDimitry Andric   }
37090b57cec5SDimitry Andric   OS << "    for (unsigned FormalIdx = " << (HasMnemonicFirst ? "0" : "SIndex")
37100b57cec5SDimitry Andric      << ", ActualIdx = " << (HasMnemonicFirst ? "1" : "SIndex")
37110b57cec5SDimitry Andric      << "; FormalIdx != " << MaxNumOperands << "; ++FormalIdx) {\n";
37120b57cec5SDimitry Andric   OS << "      auto Formal = "
37130b57cec5SDimitry Andric      << "static_cast<MatchClassKind>(it->Classes[FormalIdx]);\n";
37140b57cec5SDimitry Andric   OS << "      DEBUG_WITH_TYPE(\"asm-matcher\",\n";
3715*0fca6ea1SDimitry Andric   OS << "                      dbgs() << \"  Matching formal operand class \" "
3716*0fca6ea1SDimitry Andric         "<< getMatchClassName(Formal)\n";
3717*0fca6ea1SDimitry Andric   OS << "                             << \" against actual operand at index \" "
3718*0fca6ea1SDimitry Andric         "<< ActualIdx);\n";
37190b57cec5SDimitry Andric   OS << "      if (ActualIdx < Operands.size())\n";
37200b57cec5SDimitry Andric   OS << "        DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \" (\";\n";
3721*0fca6ea1SDimitry Andric   OS << "                        Operands[ActualIdx]->print(dbgs()); dbgs() << "
3722*0fca6ea1SDimitry Andric         "\"): \");\n";
37230b57cec5SDimitry Andric   OS << "      else\n";
37240b57cec5SDimitry Andric   OS << "        DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \": \");\n";
37250b57cec5SDimitry Andric   OS << "      if (ActualIdx >= Operands.size()) {\n";
3726bdd1243dSDimitry Andric   OS << "        DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"actual operand "
3727bdd1243dSDimitry Andric         "index out of range\\n\");\n";
37280b57cec5SDimitry Andric   if (ReportMultipleNearMisses) {
3729*0fca6ea1SDimitry Andric     OS << "        bool ThisOperandValid = (Formal == "
3730*0fca6ea1SDimitry Andric        << "InvalidMatchClass) || "
37310b57cec5SDimitry Andric           "isSubclass(Formal, OptionalMatchClass);\n";
37320b57cec5SDimitry Andric     OS << "        if (!ThisOperandValid) {\n";
37330b57cec5SDimitry Andric     OS << "          if (!OperandNearMiss) {\n";
37340b57cec5SDimitry Andric     OS << "            // Record info about match failure for later use.\n";
3735*0fca6ea1SDimitry Andric     OS << "            DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"recording "
3736*0fca6ea1SDimitry Andric           "too-few-operands near miss\\n\");\n";
37370b57cec5SDimitry Andric     OS << "            OperandNearMiss =\n";
3738*0fca6ea1SDimitry Andric     OS << "                NearMissInfo::getTooFewOperands(Formal, "
3739*0fca6ea1SDimitry Andric           "it->Opcode);\n";
3740*0fca6ea1SDimitry Andric     OS << "          } else if (OperandNearMiss.getKind() != "
3741*0fca6ea1SDimitry Andric           "NearMissInfo::NearMissTooFewOperands) {\n";
3742*0fca6ea1SDimitry Andric     OS << "            // If more than one operand is invalid, give up on this "
3743*0fca6ea1SDimitry Andric           "match entry.\n";
37440b57cec5SDimitry Andric     OS << "            DEBUG_WITH_TYPE(\n";
37450b57cec5SDimitry Andric     OS << "                \"asm-matcher\",\n";
3746*0fca6ea1SDimitry Andric     OS << "                dbgs() << \"second invalid operand, giving up on "
3747*0fca6ea1SDimitry Andric           "this opcode\\n\");\n";
37480b57cec5SDimitry Andric     OS << "            MultipleInvalidOperands = true;\n";
37490b57cec5SDimitry Andric     OS << "            break;\n";
37500b57cec5SDimitry Andric     OS << "          }\n";
37510b57cec5SDimitry Andric     OS << "        } else {\n";
3752bdd1243dSDimitry Andric     OS << "          DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"but formal "
3753bdd1243dSDimitry Andric           "operand not required\\n\");\n";
3754*0fca6ea1SDimitry Andric     OS << "          if (isSubclass(Formal, OptionalMatchClass)) {\n";
3755*0fca6ea1SDimitry Andric     OS << "            OptionalOperandsMask.set(FormalIdx);\n";
3756*0fca6ea1SDimitry Andric     OS << "          }\n";
37570b57cec5SDimitry Andric     OS << "        }\n";
37580b57cec5SDimitry Andric     OS << "        continue;\n";
37590b57cec5SDimitry Andric   } else {
3760bdd1243dSDimitry Andric     OS << "        if (Formal == InvalidMatchClass) {\n";
37610b57cec5SDimitry Andric     if (HasOptionalOperands) {
37620b57cec5SDimitry Andric       OS << "          OptionalOperandsMask.set(FormalIdx, " << MaxNumOperands
37630b57cec5SDimitry Andric          << ");\n";
37640b57cec5SDimitry Andric     }
37650b57cec5SDimitry Andric     OS << "          break;\n";
3766bdd1243dSDimitry Andric     OS << "        }\n";
3767bdd1243dSDimitry Andric     OS << "        if (isSubclass(Formal, OptionalMatchClass)) {\n";
3768bdd1243dSDimitry Andric     if (HasOptionalOperands) {
3769bdd1243dSDimitry Andric       OS << "          OptionalOperandsMask.set(FormalIdx);\n";
3770bdd1243dSDimitry Andric     }
3771bdd1243dSDimitry Andric     OS << "          continue;\n";
3772bdd1243dSDimitry Andric     OS << "        }\n";
3773bdd1243dSDimitry Andric     OS << "        OperandsValid = false;\n";
3774bdd1243dSDimitry Andric     OS << "        ErrorInfo = ActualIdx;\n";
3775bdd1243dSDimitry Andric     OS << "        break;\n";
37760b57cec5SDimitry Andric   }
37770b57cec5SDimitry Andric   OS << "      }\n";
37780b57cec5SDimitry Andric   OS << "      MCParsedAsmOperand &Actual = *Operands[ActualIdx];\n";
37790b57cec5SDimitry Andric   OS << "      unsigned Diag = validateOperandClass(Actual, Formal);\n";
37800b57cec5SDimitry Andric   OS << "      if (Diag == Match_Success) {\n";
37810b57cec5SDimitry Andric   OS << "        DEBUG_WITH_TYPE(\"asm-matcher\",\n";
3782*0fca6ea1SDimitry Andric   OS << "                        dbgs() << \"match success using generic "
3783*0fca6ea1SDimitry Andric         "matcher\\n\");\n";
37840b57cec5SDimitry Andric   OS << "        ++ActualIdx;\n";
37850b57cec5SDimitry Andric   OS << "        continue;\n";
37860b57cec5SDimitry Andric   OS << "      }\n";
37870b57cec5SDimitry Andric   OS << "      // If the generic handler indicates an invalid operand\n";
37880b57cec5SDimitry Andric   OS << "      // failure, check for a special case.\n";
37890b57cec5SDimitry Andric   OS << "      if (Diag != Match_Success) {\n";
3790*0fca6ea1SDimitry Andric   OS << "        unsigned TargetDiag = validateTargetOperandClass(Actual, "
3791*0fca6ea1SDimitry Andric         "Formal);\n";
37920b57cec5SDimitry Andric   OS << "        if (TargetDiag == Match_Success) {\n";
37930b57cec5SDimitry Andric   OS << "          DEBUG_WITH_TYPE(\"asm-matcher\",\n";
3794*0fca6ea1SDimitry Andric   OS << "                          dbgs() << \"match success using target "
3795*0fca6ea1SDimitry Andric         "matcher\\n\");\n";
37960b57cec5SDimitry Andric   OS << "          ++ActualIdx;\n";
37970b57cec5SDimitry Andric   OS << "          continue;\n";
37980b57cec5SDimitry Andric   OS << "        }\n";
37990b57cec5SDimitry Andric   OS << "        // If the target matcher returned a specific error code use\n";
38000b57cec5SDimitry Andric   OS << "        // that, else use the one from the generic matcher.\n";
38010b57cec5SDimitry Andric   OS << "        if (TargetDiag != Match_InvalidOperand && "
38020b57cec5SDimitry Andric         "HasRequiredFeatures)\n";
38030b57cec5SDimitry Andric   OS << "          Diag = TargetDiag;\n";
38040b57cec5SDimitry Andric   OS << "      }\n";
38050b57cec5SDimitry Andric   OS << "      // If current formal operand wasn't matched and it is optional\n"
38060b57cec5SDimitry Andric      << "      // then try to match next formal operand\n";
38070b57cec5SDimitry Andric   OS << "      if (Diag == Match_InvalidOperand "
38080b57cec5SDimitry Andric      << "&& isSubclass(Formal, OptionalMatchClass)) {\n";
38090b57cec5SDimitry Andric   if (HasOptionalOperands) {
38100b57cec5SDimitry Andric     OS << "        OptionalOperandsMask.set(FormalIdx);\n";
38110b57cec5SDimitry Andric   }
3812*0fca6ea1SDimitry Andric   OS << "        DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"ignoring "
3813*0fca6ea1SDimitry Andric         "optional operand\\n\");\n";
38140b57cec5SDimitry Andric   OS << "        continue;\n";
38150b57cec5SDimitry Andric   OS << "      }\n";
38160b57cec5SDimitry Andric 
38170b57cec5SDimitry Andric   if (ReportMultipleNearMisses) {
38180b57cec5SDimitry Andric     OS << "      if (!OperandNearMiss) {\n";
3819*0fca6ea1SDimitry Andric     OS << "        // If this is the first invalid operand we have seen, "
3820*0fca6ea1SDimitry Andric           "record some\n";
38210b57cec5SDimitry Andric     OS << "        // information about it.\n";
38220b57cec5SDimitry Andric     OS << "        DEBUG_WITH_TYPE(\n";
38230b57cec5SDimitry Andric     OS << "            \"asm-matcher\",\n";
38240b57cec5SDimitry Andric     OS << "            dbgs()\n";
3825*0fca6ea1SDimitry Andric     OS << "                << \"operand match failed, recording near-miss with "
3826*0fca6ea1SDimitry Andric           "diag code \"\n";
38270b57cec5SDimitry Andric     OS << "                << Diag << \"\\n\");\n";
38280b57cec5SDimitry Andric     OS << "        OperandNearMiss =\n";
3829*0fca6ea1SDimitry Andric     OS << "            NearMissInfo::getMissedOperand(Diag, Formal, "
3830*0fca6ea1SDimitry Andric           "it->Opcode, ActualIdx);\n";
38310b57cec5SDimitry Andric     OS << "        ++ActualIdx;\n";
38320b57cec5SDimitry Andric     OS << "      } else {\n";
3833*0fca6ea1SDimitry Andric     OS << "        // If more than one operand is invalid, give up on this "
3834*0fca6ea1SDimitry Andric           "match entry.\n";
38350b57cec5SDimitry Andric     OS << "        DEBUG_WITH_TYPE(\n";
38360b57cec5SDimitry Andric     OS << "            \"asm-matcher\",\n";
3837*0fca6ea1SDimitry Andric     OS << "            dbgs() << \"second operand mismatch, skipping this "
3838*0fca6ea1SDimitry Andric           "opcode\\n\");\n";
38390b57cec5SDimitry Andric     OS << "        MultipleInvalidOperands = true;\n";
38400b57cec5SDimitry Andric     OS << "        break;\n";
38410b57cec5SDimitry Andric     OS << "      }\n";
38420b57cec5SDimitry Andric     OS << "    }\n\n";
38430b57cec5SDimitry Andric   } else {
3844*0fca6ea1SDimitry Andric     OS << "      // If this operand is broken for all of the instances of "
3845*0fca6ea1SDimitry Andric           "this\n";
38460b57cec5SDimitry Andric     OS << "      // mnemonic, keep track of it so we can report loc info.\n";
38470b57cec5SDimitry Andric     OS << "      // If we already had a match that only failed due to a\n";
38480b57cec5SDimitry Andric     OS << "      // target predicate, that diagnostic is preferred.\n";
38490b57cec5SDimitry Andric     OS << "      if (!HadMatchOtherThanPredicate &&\n";
3850*0fca6ea1SDimitry Andric     OS << "          (it == MnemonicRange.first || ErrorInfo <= ActualIdx)) "
3851*0fca6ea1SDimitry Andric           "{\n";
38520b57cec5SDimitry Andric     OS << "        if (HasRequiredFeatures && (ErrorInfo != ActualIdx || Diag "
38530b57cec5SDimitry Andric           "!= Match_InvalidOperand))\n";
38540b57cec5SDimitry Andric     OS << "          RetCode = Diag;\n";
38550b57cec5SDimitry Andric     OS << "        ErrorInfo = ActualIdx;\n";
38560b57cec5SDimitry Andric     OS << "      }\n";
38570b57cec5SDimitry Andric     OS << "      // Otherwise, just reject this instance of the mnemonic.\n";
38580b57cec5SDimitry Andric     OS << "      OperandsValid = false;\n";
38590b57cec5SDimitry Andric     OS << "      break;\n";
38600b57cec5SDimitry Andric     OS << "    }\n\n";
38610b57cec5SDimitry Andric   }
38620b57cec5SDimitry Andric 
38630b57cec5SDimitry Andric   if (ReportMultipleNearMisses)
38640b57cec5SDimitry Andric     OS << "    if (MultipleInvalidOperands) {\n";
38650b57cec5SDimitry Andric   else
38660b57cec5SDimitry Andric     OS << "    if (!OperandsValid) {\n";
3867*0fca6ea1SDimitry Andric   OS << "      DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Opcode result: "
3868*0fca6ea1SDimitry Andric         "multiple \"\n";
3869*0fca6ea1SDimitry Andric   OS << "                                               \"operand mismatches, "
3870*0fca6ea1SDimitry Andric         "ignoring \"\n";
38710b57cec5SDimitry Andric   OS << "                                               \"this opcode\\n\");\n";
38720b57cec5SDimitry Andric   OS << "      continue;\n";
38730b57cec5SDimitry Andric   OS << "    }\n";
38740b57cec5SDimitry Andric 
38750b57cec5SDimitry Andric   // Emit check that the required features are available.
38760b57cec5SDimitry Andric   OS << "    if (!HasRequiredFeatures) {\n";
38770b57cec5SDimitry Andric   if (!ReportMultipleNearMisses)
38780b57cec5SDimitry Andric     OS << "      HadMatchOtherThanFeatures = true;\n";
38790b57cec5SDimitry Andric   OS << "      FeatureBitset NewMissingFeatures = RequiredFeatures & "
38800b57cec5SDimitry Andric         "~AvailableFeatures;\n";
3881*0fca6ea1SDimitry Andric   OS << "      DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Missing target "
3882*0fca6ea1SDimitry Andric         "features:\";\n";
3883*0fca6ea1SDimitry Andric   OS << "                      for (unsigned I = 0, E = "
3884*0fca6ea1SDimitry Andric         "NewMissingFeatures.size(); I != E; ++I)\n";
38850b57cec5SDimitry Andric   OS << "                        if (NewMissingFeatures[I])\n";
38860b57cec5SDimitry Andric   OS << "                          dbgs() << ' ' << I;\n";
38870b57cec5SDimitry Andric   OS << "                      dbgs() << \"\\n\");\n";
38880b57cec5SDimitry Andric   if (ReportMultipleNearMisses) {
3889*0fca6ea1SDimitry Andric     OS << "      FeaturesNearMiss = "
3890*0fca6ea1SDimitry Andric           "NearMissInfo::getMissedFeature(NewMissingFeatures);\n";
38910b57cec5SDimitry Andric   } else {
38920b57cec5SDimitry Andric     OS << "      if (NewMissingFeatures.count() <=\n"
38930b57cec5SDimitry Andric           "          MissingFeatures.count())\n";
38940b57cec5SDimitry Andric     OS << "        MissingFeatures = NewMissingFeatures;\n";
38950b57cec5SDimitry Andric     OS << "      continue;\n";
38960b57cec5SDimitry Andric   }
38970b57cec5SDimitry Andric   OS << "    }\n";
38980b57cec5SDimitry Andric   OS << "\n";
38990b57cec5SDimitry Andric   OS << "    Inst.clear();\n\n";
39000b57cec5SDimitry Andric   OS << "    Inst.setOpcode(it->Opcode);\n";
39010b57cec5SDimitry Andric   // Verify the instruction with the target-specific match predicate function.
39020b57cec5SDimitry Andric   OS << "    // We have a potential match but have not rendered the operands.\n"
39030b57cec5SDimitry Andric      << "    // Check the target predicate to handle any context sensitive\n"
39040b57cec5SDimitry Andric         "    // constraints.\n"
39050b57cec5SDimitry Andric      << "    // For example, Ties that are referenced multiple times must be\n"
39060b57cec5SDimitry Andric         "    // checked here to ensure the input is the same for each match\n"
39070b57cec5SDimitry Andric         "    // constraints. If we leave it any later the ties will have been\n"
39080b57cec5SDimitry Andric         "    // canonicalized\n"
39090b57cec5SDimitry Andric      << "    unsigned MatchResult;\n"
39100b57cec5SDimitry Andric      << "    if ((MatchResult = checkEarlyTargetMatchPredicate(Inst, "
39110b57cec5SDimitry Andric         "Operands)) != Match_Success) {\n"
39120b57cec5SDimitry Andric      << "      Inst.clear();\n";
39130b57cec5SDimitry Andric   OS << "      DEBUG_WITH_TYPE(\n";
39140b57cec5SDimitry Andric   OS << "          \"asm-matcher\",\n";
3915*0fca6ea1SDimitry Andric   OS << "          dbgs() << \"Early target match predicate failed with diag "
3916*0fca6ea1SDimitry Andric         "code \"\n";
39170b57cec5SDimitry Andric   OS << "                 << MatchResult << \"\\n\");\n";
39180b57cec5SDimitry Andric   if (ReportMultipleNearMisses) {
3919*0fca6ea1SDimitry Andric     OS << "      EarlyPredicateNearMiss = "
3920*0fca6ea1SDimitry Andric           "NearMissInfo::getMissedPredicate(MatchResult);\n";
39210b57cec5SDimitry Andric   } else {
39220b57cec5SDimitry Andric     OS << "      RetCode = MatchResult;\n"
39230b57cec5SDimitry Andric        << "      HadMatchOtherThanPredicate = true;\n"
39240b57cec5SDimitry Andric        << "      continue;\n";
39250b57cec5SDimitry Andric   }
39260b57cec5SDimitry Andric   OS << "    }\n\n";
39270b57cec5SDimitry Andric 
39280b57cec5SDimitry Andric   if (ReportMultipleNearMisses) {
3929*0fca6ea1SDimitry Andric     OS << "    // If we did not successfully match the operands, then we can't "
3930*0fca6ea1SDimitry Andric           "convert to\n";
39310b57cec5SDimitry Andric     OS << "    // an MCInst, so bail out on this instruction variant now.\n";
39320b57cec5SDimitry Andric     OS << "    if (OperandNearMiss) {\n";
3933*0fca6ea1SDimitry Andric     OS << "      // If the operand mismatch was the only problem, reprrt it as "
3934*0fca6ea1SDimitry Andric           "a near-miss.\n";
3935*0fca6ea1SDimitry Andric     OS << "      if (NearMisses && !FeaturesNearMiss && "
3936*0fca6ea1SDimitry Andric           "!EarlyPredicateNearMiss) {\n";
39370b57cec5SDimitry Andric     OS << "        DEBUG_WITH_TYPE(\n";
39380b57cec5SDimitry Andric     OS << "            \"asm-matcher\",\n";
39390b57cec5SDimitry Andric     OS << "            dbgs()\n";
3940*0fca6ea1SDimitry Andric     OS << "                << \"Opcode result: one mismatched operand, adding "
3941*0fca6ea1SDimitry Andric           "near-miss\\n\");\n";
39420b57cec5SDimitry Andric     OS << "        NearMisses->push_back(OperandNearMiss);\n";
39430b57cec5SDimitry Andric     OS << "      } else {\n";
3944*0fca6ea1SDimitry Andric     OS << "        DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Opcode result: "
3945*0fca6ea1SDimitry Andric           "multiple \"\n";
3946*0fca6ea1SDimitry Andric     OS << "                                                 \"types of "
3947*0fca6ea1SDimitry Andric           "mismatch, so not \"\n";
3948*0fca6ea1SDimitry Andric     OS << "                                                 \"reporting "
3949*0fca6ea1SDimitry Andric           "near-miss\\n\");\n";
39500b57cec5SDimitry Andric     OS << "      }\n";
39510b57cec5SDimitry Andric     OS << "      continue;\n";
39520b57cec5SDimitry Andric     OS << "    }\n\n";
39530b57cec5SDimitry Andric   }
39540b57cec5SDimitry Andric 
3955*0fca6ea1SDimitry Andric   // When converting parsed operands to MCInst we need to know whether optional
3956*0fca6ea1SDimitry Andric   // operands were parsed or not so that we can choose the correct converter
3957*0fca6ea1SDimitry Andric   // function. We also need to know this when checking tied operand constraints.
3958*0fca6ea1SDimitry Andric   // DefaultsOffset is an array of deltas between the formal (MCInst) and the
3959*0fca6ea1SDimitry Andric   // actual (parsed operand array) operand indices. When all optional operands
3960*0fca6ea1SDimitry Andric   // are present, all elements of the array are zeros. If some of the optional
3961*0fca6ea1SDimitry Andric   // operands are absent, the array might look like '0, 0, 1, 1, 1, 2, 2, 3',
3962*0fca6ea1SDimitry Andric   // where each increment in value reflects the absence of an optional operand.
3963*0fca6ea1SDimitry Andric   if (HasOptionalOperands) {
3964*0fca6ea1SDimitry Andric     OS << "    unsigned DefaultsOffset[" << (MaxNumOperands + 1)
3965*0fca6ea1SDimitry Andric        << "] = { 0 };\n";
3966*0fca6ea1SDimitry Andric     OS << "    assert(OptionalOperandsMask.size() == " << (MaxNumOperands)
3967*0fca6ea1SDimitry Andric        << ");\n";
3968*0fca6ea1SDimitry Andric     OS << "    for (unsigned i = 0, NumDefaults = 0; i < " << (MaxNumOperands)
3969*0fca6ea1SDimitry Andric        << "; ++i) {\n";
3970*0fca6ea1SDimitry Andric     OS << "      DefaultsOffset[i + 1] = NumDefaults;\n";
3971*0fca6ea1SDimitry Andric     OS << "      NumDefaults += (OptionalOperandsMask[i] ? 1 : 0);\n";
3972*0fca6ea1SDimitry Andric     OS << "    }\n\n";
3973*0fca6ea1SDimitry Andric   }
3974*0fca6ea1SDimitry Andric 
39750b57cec5SDimitry Andric   OS << "    if (matchingInlineAsm) {\n";
39760b57cec5SDimitry Andric   OS << "      convertToMapAndConstraints(it->ConvertFn, Operands);\n";
39770b57cec5SDimitry Andric   if (!ReportMultipleNearMisses) {
3978*0fca6ea1SDimitry Andric     if (HasOptionalOperands) {
39790b57cec5SDimitry Andric       OS << "      if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
3980*0fca6ea1SDimitry Andric             "Operands,\n";
3981*0fca6ea1SDimitry Andric       OS << "                                          DefaultsOffset, "
3982*0fca6ea1SDimitry Andric             "ErrorInfo))\n";
3983*0fca6ea1SDimitry Andric     } else {
3984*0fca6ea1SDimitry Andric       OS << "      if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
3985*0fca6ea1SDimitry Andric             "Operands,\n";
3986*0fca6ea1SDimitry Andric       OS << "                                          ErrorInfo))\n";
3987*0fca6ea1SDimitry Andric     }
39880b57cec5SDimitry Andric     OS << "        return Match_InvalidTiedOperand;\n";
39890b57cec5SDimitry Andric     OS << "\n";
39900b57cec5SDimitry Andric   }
39910b57cec5SDimitry Andric   OS << "      return Match_Success;\n";
39920b57cec5SDimitry Andric   OS << "    }\n\n";
39930b57cec5SDimitry Andric   OS << "    // We have selected a definite instruction, convert the parsed\n"
39940b57cec5SDimitry Andric      << "    // operands into the appropriate MCInst.\n";
39950b57cec5SDimitry Andric   if (HasOptionalOperands) {
39960b57cec5SDimitry Andric     OS << "    convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands,\n"
3997*0fca6ea1SDimitry Andric        << "                    OptionalOperandsMask, DefaultsOffset);\n";
39980b57cec5SDimitry Andric   } else {
39990b57cec5SDimitry Andric     OS << "    convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands);\n";
40000b57cec5SDimitry Andric   }
40010b57cec5SDimitry Andric   OS << "\n";
40020b57cec5SDimitry Andric 
40030b57cec5SDimitry Andric   // Verify the instruction with the target-specific match predicate function.
40040b57cec5SDimitry Andric   OS << "    // We have a potential match. Check the target predicate to\n"
40050b57cec5SDimitry Andric      << "    // handle any context sensitive constraints.\n"
40060b57cec5SDimitry Andric      << "    if ((MatchResult = checkTargetMatchPredicate(Inst)) !="
40070b57cec5SDimitry Andric      << " Match_Success) {\n"
40080b57cec5SDimitry Andric      << "      DEBUG_WITH_TYPE(\"asm-matcher\",\n"
4009*0fca6ea1SDimitry Andric      << "                      dbgs() << \"Target match predicate failed with "
4010*0fca6ea1SDimitry Andric         "diag code \"\n"
40110b57cec5SDimitry Andric      << "                             << MatchResult << \"\\n\");\n"
40120b57cec5SDimitry Andric      << "      Inst.clear();\n";
40130b57cec5SDimitry Andric   if (ReportMultipleNearMisses) {
4014*0fca6ea1SDimitry Andric     OS << "      LatePredicateNearMiss = "
4015*0fca6ea1SDimitry Andric           "NearMissInfo::getMissedPredicate(MatchResult);\n";
40160b57cec5SDimitry Andric   } else {
40170b57cec5SDimitry Andric     OS << "      RetCode = MatchResult;\n"
40180b57cec5SDimitry Andric        << "      HadMatchOtherThanPredicate = true;\n"
40190b57cec5SDimitry Andric        << "      continue;\n";
40200b57cec5SDimitry Andric   }
40210b57cec5SDimitry Andric   OS << "    }\n\n";
40220b57cec5SDimitry Andric 
40230b57cec5SDimitry Andric   if (ReportMultipleNearMisses) {
40240b57cec5SDimitry Andric     OS << "    int NumNearMisses = ((int)(bool)OperandNearMiss +\n";
40250b57cec5SDimitry Andric     OS << "                         (int)(bool)FeaturesNearMiss +\n";
40260b57cec5SDimitry Andric     OS << "                         (int)(bool)EarlyPredicateNearMiss +\n";
40270b57cec5SDimitry Andric     OS << "                         (int)(bool)LatePredicateNearMiss);\n";
40280b57cec5SDimitry Andric     OS << "    if (NumNearMisses == 1) {\n";
4029*0fca6ea1SDimitry Andric     OS << "      // We had exactly one type of near-miss, so add that to the "
4030*0fca6ea1SDimitry Andric           "list.\n";
4031*0fca6ea1SDimitry Andric     OS << "      assert(!OperandNearMiss && \"OperandNearMiss was handled "
4032*0fca6ea1SDimitry Andric           "earlier\");\n";
4033*0fca6ea1SDimitry Andric     OS << "      DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Opcode result: "
4034*0fca6ea1SDimitry Andric           "found one type of \"\n";
4035*0fca6ea1SDimitry Andric     OS << "                                            \"mismatch, so "
4036*0fca6ea1SDimitry Andric           "reporting a \"\n";
40370b57cec5SDimitry Andric     OS << "                                            \"near-miss\\n\");\n";
40380b57cec5SDimitry Andric     OS << "      if (NearMisses && FeaturesNearMiss)\n";
40390b57cec5SDimitry Andric     OS << "        NearMisses->push_back(FeaturesNearMiss);\n";
40400b57cec5SDimitry Andric     OS << "      else if (NearMisses && EarlyPredicateNearMiss)\n";
40410b57cec5SDimitry Andric     OS << "        NearMisses->push_back(EarlyPredicateNearMiss);\n";
40420b57cec5SDimitry Andric     OS << "      else if (NearMisses && LatePredicateNearMiss)\n";
40430b57cec5SDimitry Andric     OS << "        NearMisses->push_back(LatePredicateNearMiss);\n";
40440b57cec5SDimitry Andric     OS << "\n";
40450b57cec5SDimitry Andric     OS << "      continue;\n";
40460b57cec5SDimitry Andric     OS << "    } else if (NumNearMisses > 1) {\n";
4047*0fca6ea1SDimitry Andric     OS << "      // This instruction missed in more than one way, so ignore "
4048*0fca6ea1SDimitry Andric           "it.\n";
4049*0fca6ea1SDimitry Andric     OS << "      DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Opcode result: "
4050*0fca6ea1SDimitry Andric           "multiple \"\n";
4051*0fca6ea1SDimitry Andric     OS << "                                               \"types of mismatch, "
4052*0fca6ea1SDimitry Andric           "so not \"\n";
4053*0fca6ea1SDimitry Andric     OS << "                                               \"reporting "
4054*0fca6ea1SDimitry Andric           "near-miss\\n\");\n";
40550b57cec5SDimitry Andric     OS << "      continue;\n";
40560b57cec5SDimitry Andric     OS << "    }\n";
40570b57cec5SDimitry Andric   }
40580b57cec5SDimitry Andric 
40590b57cec5SDimitry Andric   // Call the post-processing function, if used.
40600b57cec5SDimitry Andric   StringRef InsnCleanupFn = AsmParser->getValueAsString("AsmParserInstCleanup");
40610b57cec5SDimitry Andric   if (!InsnCleanupFn.empty())
40620b57cec5SDimitry Andric     OS << "    " << InsnCleanupFn << "(Inst);\n";
40630b57cec5SDimitry Andric 
40640b57cec5SDimitry Andric   if (HasDeprecation) {
40650b57cec5SDimitry Andric     OS << "    std::string Info;\n";
4066*0fca6ea1SDimitry Andric     OS << "    if "
4067*0fca6ea1SDimitry Andric           "(!getParser().getTargetParser().getTargetOptions()."
4068*0fca6ea1SDimitry Andric           "MCNoDeprecatedWarn &&\n";
40695ffd83dbSDimitry Andric     OS << "        MII.getDeprecatedInfo(Inst, getSTI(), Info)) {\n";
40700b57cec5SDimitry Andric     OS << "      SMLoc Loc = ((" << Target.getName()
40710b57cec5SDimitry Andric        << "Operand &)*Operands[0]).getStartLoc();\n";
4072bdd1243dSDimitry Andric     OS << "      getParser().Warning(Loc, Info, std::nullopt);\n";
40730b57cec5SDimitry Andric     OS << "    }\n";
40740b57cec5SDimitry Andric   }
40750b57cec5SDimitry Andric 
40760b57cec5SDimitry Andric   if (!ReportMultipleNearMisses) {
4077*0fca6ea1SDimitry Andric     if (HasOptionalOperands) {
40780b57cec5SDimitry Andric       OS << "    if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
4079*0fca6ea1SDimitry Andric             "Operands,\n";
4080*0fca6ea1SDimitry Andric       OS << "                                         DefaultsOffset, "
4081*0fca6ea1SDimitry Andric             "ErrorInfo))\n";
4082*0fca6ea1SDimitry Andric     } else {
4083*0fca6ea1SDimitry Andric       OS << "    if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
4084*0fca6ea1SDimitry Andric             "Operands,\n";
4085*0fca6ea1SDimitry Andric       OS << "                                         ErrorInfo))\n";
4086*0fca6ea1SDimitry Andric     }
40870b57cec5SDimitry Andric     OS << "      return Match_InvalidTiedOperand;\n";
40880b57cec5SDimitry Andric     OS << "\n";
40890b57cec5SDimitry Andric   }
40900b57cec5SDimitry Andric 
40910b57cec5SDimitry Andric   OS << "    DEBUG_WITH_TYPE(\n";
40920b57cec5SDimitry Andric   OS << "        \"asm-matcher\",\n";
4093*0fca6ea1SDimitry Andric   OS << "        dbgs() << \"Opcode result: complete match, selecting this "
4094*0fca6ea1SDimitry Andric         "opcode\\n\");\n";
40950b57cec5SDimitry Andric   OS << "    return Match_Success;\n";
40960b57cec5SDimitry Andric   OS << "  }\n\n";
40970b57cec5SDimitry Andric 
40980b57cec5SDimitry Andric   if (ReportMultipleNearMisses) {
40990b57cec5SDimitry Andric     OS << "  // No instruction variants matched exactly.\n";
41000b57cec5SDimitry Andric     OS << "  return Match_NearMisses;\n";
41010b57cec5SDimitry Andric   } else {
41020b57cec5SDimitry Andric     OS << "  // Okay, we had no match.  Try to return a useful error code.\n";
41030b57cec5SDimitry Andric     OS << "  if (HadMatchOtherThanPredicate || !HadMatchOtherThanFeatures)\n";
41040b57cec5SDimitry Andric     OS << "    return RetCode;\n\n";
41050b57cec5SDimitry Andric     OS << "  ErrorInfo = 0;\n";
41060b57cec5SDimitry Andric     OS << "  return Match_MissingFeature;\n";
41070b57cec5SDimitry Andric   }
41080b57cec5SDimitry Andric   OS << "}\n\n";
41090b57cec5SDimitry Andric 
41100b57cec5SDimitry Andric   if (!Info.OperandMatchInfo.empty())
41110b57cec5SDimitry Andric     emitCustomOperandParsing(OS, Target, Info, ClassName, StringTable,
41120b57cec5SDimitry Andric                              MaxMnemonicIndex, FeatureBitsets.size(),
4113bdd1243dSDimitry Andric                              HasMnemonicFirst, *AsmParser);
41140b57cec5SDimitry Andric 
41150b57cec5SDimitry Andric   OS << "#endif // GET_MATCHER_IMPLEMENTATION\n\n";
41160b57cec5SDimitry Andric 
41170b57cec5SDimitry Andric   OS << "\n#ifdef GET_MNEMONIC_SPELL_CHECKER\n";
41180b57cec5SDimitry Andric   OS << "#undef GET_MNEMONIC_SPELL_CHECKER\n\n";
41190b57cec5SDimitry Andric 
41200b57cec5SDimitry Andric   emitMnemonicSpellChecker(OS, Target, VariantCount);
41210b57cec5SDimitry Andric 
41220b57cec5SDimitry Andric   OS << "#endif // GET_MNEMONIC_SPELL_CHECKER\n\n";
4123e8d8bef9SDimitry Andric 
4124e8d8bef9SDimitry Andric   OS << "\n#ifdef GET_MNEMONIC_CHECKER\n";
4125e8d8bef9SDimitry Andric   OS << "#undef GET_MNEMONIC_CHECKER\n\n";
4126e8d8bef9SDimitry Andric 
4127*0fca6ea1SDimitry Andric   emitMnemonicChecker(OS, Target, VariantCount, HasMnemonicFirst,
4128*0fca6ea1SDimitry Andric                       HasMnemonicAliases);
4129e8d8bef9SDimitry Andric 
4130e8d8bef9SDimitry Andric   OS << "#endif // GET_MNEMONIC_CHECKER\n\n";
41310b57cec5SDimitry Andric }
41320b57cec5SDimitry Andric 
413306c3fb27SDimitry Andric static TableGen::Emitter::OptClass<AsmMatcherEmitter>
413406c3fb27SDimitry Andric     X("gen-asm-matcher", "Generate assembly instruction matcher");
4135