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