Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/AsmMatcherEmitter.cpp
35258 views
//===- AsmMatcherEmitter.cpp - Generate an assembly matcher ---------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This tablegen backend emits a target specifier matcher for converting parsed9// assembly operands in the MCInst structures. It also emits a matcher for10// custom operand parsing.11//12// Converting assembly operands into MCInst structures13// ---------------------------------------------------14//15// The input to the target specific matcher is a list of literal tokens and16// operands. The target specific parser should generally eliminate any syntax17// which is not relevant for matching; for example, comma tokens should have18// already been consumed and eliminated by the parser. Most instructions will19// end up with a single literal token (the instruction name) and some number of20// operands.21//22// Some example inputs, for X86:23// 'addl' (immediate ...) (register ...)24// 'add' (immediate ...) (memory ...)25// 'call' '*' %epc26//27// The assembly matcher is responsible for converting this input into a precise28// machine instruction (i.e., an instruction with a well defined encoding). This29// mapping has several properties which complicate matching:30//31// - It may be ambiguous; many architectures can legally encode particular32// variants of an instruction in different ways (for example, using a smaller33// encoding for small immediates). Such ambiguities should never be34// arbitrarily resolved by the assembler, the assembler is always responsible35// for choosing the "best" available instruction.36//37// - It may depend on the subtarget or the assembler context. Instructions38// which are invalid for the current mode, but otherwise unambiguous (e.g.,39// an SSE instruction in a file being assembled for i486) should be accepted40// and rejected by the assembler front end. However, if the proper encoding41// for an instruction is dependent on the assembler context then the matcher42// is responsible for selecting the correct machine instruction for the43// current mode.44//45// The core matching algorithm attempts to exploit the regularity in most46// instruction sets to quickly determine the set of possibly matching47// instructions, and the simplify the generated code. Additionally, this helps48// to ensure that the ambiguities are intentionally resolved by the user.49//50// The matching is divided into two distinct phases:51//52// 1. Classification: Each operand is mapped to the unique set which (a)53// contains it, and (b) is the largest such subset for which a single54// instruction could match all members.55//56// For register classes, we can generate these subgroups automatically. For57// arbitrary operands, we expect the user to define the classes and their58// relations to one another (for example, 8-bit signed immediates as a59// subset of 32-bit immediates).60//61// By partitioning the operands in this way, we guarantee that for any62// tuple of classes, any single instruction must match either all or none63// of the sets of operands which could classify to that tuple.64//65// In addition, the subset relation amongst classes induces a partial order66// on such tuples, which we use to resolve ambiguities.67//68// 2. The input can now be treated as a tuple of classes (static tokens are69// simple singleton sets). Each such tuple should generally map to a single70// instruction (we currently ignore cases where this isn't true, whee!!!),71// which we can emit a simple matcher for.72//73// Custom Operand Parsing74// ----------------------75//76// Some targets need a custom way to parse operands, some specific instructions77// can contain arguments that can represent processor flags and other kinds of78// identifiers that need to be mapped to specific values in the final encoded79// instructions. The target specific custom operand parsing works in the80// following way:81//82// 1. A operand match table is built, each entry contains a mnemonic, an83// operand class, a mask for all operand positions for that same84// class/mnemonic and target features to be checked while trying to match.85//86// 2. The operand matcher will try every possible entry with the same87// mnemonic and will check if the target feature for this mnemonic also88// matches. After that, if the operand to be matched has its index89// present in the mask, a successful match occurs. Otherwise, fallback90// to the regular operand parsing.91//92// 3. For a match success, each operand class that has a 'ParserMethod'93// becomes part of a switch from where the custom method is called.94//95//===----------------------------------------------------------------------===//9697#include "Common/CodeGenInstAlias.h"98#include "Common/CodeGenInstruction.h"99#include "Common/CodeGenRegisters.h"100#include "Common/CodeGenTarget.h"101#include "Common/SubtargetFeatureInfo.h"102#include "Common/Types.h"103#include "llvm/ADT/CachedHashString.h"104#include "llvm/ADT/PointerUnion.h"105#include "llvm/ADT/STLExtras.h"106#include "llvm/ADT/SmallPtrSet.h"107#include "llvm/ADT/SmallVector.h"108#include "llvm/ADT/StringExtras.h"109#include "llvm/Support/CommandLine.h"110#include "llvm/Support/Debug.h"111#include "llvm/Support/ErrorHandling.h"112#include "llvm/TableGen/Error.h"113#include "llvm/TableGen/Record.h"114#include "llvm/TableGen/StringMatcher.h"115#include "llvm/TableGen/StringToOffsetTable.h"116#include "llvm/TableGen/TableGenBackend.h"117#include <cassert>118#include <cctype>119#include <forward_list>120#include <map>121#include <set>122123using namespace llvm;124125#define DEBUG_TYPE "asm-matcher-emitter"126127cl::OptionCategory AsmMatcherEmitterCat("Options for -gen-asm-matcher");128129static cl::opt<std::string>130MatchPrefix("match-prefix", cl::init(""),131cl::desc("Only match instructions with the given prefix"),132cl::cat(AsmMatcherEmitterCat));133134namespace {135class AsmMatcherInfo;136137// Register sets are used as keys in some second-order sets TableGen creates138// when generating its data structures. This means that the order of two139// RegisterSets can be seen in the outputted AsmMatcher tables occasionally, and140// can even affect compiler output (at least seen in diagnostics produced when141// all matches fail). So we use a type that sorts them consistently.142typedef std::set<Record *, LessRecordByID> RegisterSet;143144class AsmMatcherEmitter {145RecordKeeper &Records;146147public:148AsmMatcherEmitter(RecordKeeper &R) : Records(R) {}149150void run(raw_ostream &o);151};152153/// ClassInfo - Helper class for storing the information about a particular154/// class of operands which can be matched.155struct ClassInfo {156enum ClassInfoKind {157/// Invalid kind, for use as a sentinel value.158Invalid = 0,159160/// The class for a particular token.161Token,162163/// The (first) register class, subsequent register classes are164/// RegisterClass0+1, and so on.165RegisterClass0,166167/// The (first) user defined class, subsequent user defined classes are168/// UserClass0+1, and so on.169UserClass0 = 1 << 16170};171172/// Kind - The class kind, which is either a predefined kind, or (UserClass0 +173/// N) for the Nth user defined class.174unsigned Kind;175176/// SuperClasses - The super classes of this class. Note that for simplicities177/// sake user operands only record their immediate super class, while register178/// operands include all superclasses.179std::vector<ClassInfo *> SuperClasses;180181/// Name - The full class name, suitable for use in an enum.182std::string Name;183184/// ClassName - The unadorned generic name for this class (e.g., Token).185std::string ClassName;186187/// ValueName - The name of the value this class represents; for a token this188/// is the literal token string, for an operand it is the TableGen class (or189/// empty if this is a derived class).190std::string ValueName;191192/// PredicateMethod - The name of the operand method to test whether the193/// operand matches this class; this is not valid for Token or register kinds.194std::string PredicateMethod;195196/// RenderMethod - The name of the operand method to add this operand to an197/// MCInst; this is not valid for Token or register kinds.198std::string RenderMethod;199200/// ParserMethod - The name of the operand method to do a target specific201/// parsing on the operand.202std::string ParserMethod;203204/// For register classes: the records for all the registers in this class.205RegisterSet Registers;206207/// For custom match classes: the diagnostic kind for when the predicate208/// fails.209std::string DiagnosticType;210211/// For custom match classes: the diagnostic string for when the predicate212/// fails.213std::string DiagnosticString;214215/// Is this operand optional and not always required.216bool IsOptional;217218/// DefaultMethod - The name of the method that returns the default operand219/// for optional operand220std::string DefaultMethod;221222public:223/// isRegisterClass() - Check if this is a register class.224bool isRegisterClass() const {225return Kind >= RegisterClass0 && Kind < UserClass0;226}227228/// isUserClass() - Check if this is a user defined class.229bool isUserClass() const { return Kind >= UserClass0; }230231/// isRelatedTo - Check whether this class is "related" to \p RHS. Classes232/// are related if they are in the same class hierarchy.233bool isRelatedTo(const ClassInfo &RHS) const {234// Tokens are only related to tokens.235if (Kind == Token || RHS.Kind == Token)236return Kind == Token && RHS.Kind == Token;237238// Registers classes are only related to registers classes, and only if239// their intersection is non-empty.240if (isRegisterClass() || RHS.isRegisterClass()) {241if (!isRegisterClass() || !RHS.isRegisterClass())242return false;243244std::vector<Record *> Tmp;245std::set_intersection(Registers.begin(), Registers.end(),246RHS.Registers.begin(), RHS.Registers.end(),247std::back_inserter(Tmp), LessRecordByID());248249return !Tmp.empty();250}251252// Otherwise we have two users operands; they are related if they are in the253// same class hierarchy.254//255// FIXME: This is an oversimplification, they should only be related if they256// intersect, however we don't have that information.257assert(isUserClass() && RHS.isUserClass() && "Unexpected class!");258const ClassInfo *Root = this;259while (!Root->SuperClasses.empty())260Root = Root->SuperClasses.front();261262const ClassInfo *RHSRoot = &RHS;263while (!RHSRoot->SuperClasses.empty())264RHSRoot = RHSRoot->SuperClasses.front();265266return Root == RHSRoot;267}268269/// isSubsetOf - Test whether this class is a subset of \p RHS.270bool isSubsetOf(const ClassInfo &RHS) const {271// This is a subset of RHS if it is the same class...272if (this == &RHS)273return true;274275// ... or if any of its super classes are a subset of RHS.276SmallVector<const ClassInfo *, 16> Worklist(SuperClasses.begin(),277SuperClasses.end());278SmallPtrSet<const ClassInfo *, 16> Visited;279while (!Worklist.empty()) {280auto *CI = Worklist.pop_back_val();281if (CI == &RHS)282return true;283for (auto *Super : CI->SuperClasses)284if (Visited.insert(Super).second)285Worklist.push_back(Super);286}287288return false;289}290291int getTreeDepth() const {292int Depth = 0;293const ClassInfo *Root = this;294while (!Root->SuperClasses.empty()) {295Depth++;296Root = Root->SuperClasses.front();297}298return Depth;299}300301const ClassInfo *findRoot() const {302const ClassInfo *Root = this;303while (!Root->SuperClasses.empty())304Root = Root->SuperClasses.front();305return Root;306}307308/// Compare two classes. This does not produce a total ordering, but does309/// guarantee that subclasses are sorted before their parents, and that the310/// ordering is transitive.311bool operator<(const ClassInfo &RHS) const {312if (this == &RHS)313return false;314315// First, enforce the ordering between the three different types of class.316// Tokens sort before registers, which sort before user classes.317if (Kind == Token) {318if (RHS.Kind != Token)319return true;320assert(RHS.Kind == Token);321} else if (isRegisterClass()) {322if (RHS.Kind == Token)323return false;324else if (RHS.isUserClass())325return true;326assert(RHS.isRegisterClass());327} else if (isUserClass()) {328if (!RHS.isUserClass())329return false;330assert(RHS.isUserClass());331} else {332llvm_unreachable("Unknown ClassInfoKind");333}334335if (Kind == Token || isUserClass()) {336// Related tokens and user classes get sorted by depth in the inheritence337// tree (so that subclasses are before their parents).338if (isRelatedTo(RHS)) {339if (getTreeDepth() > RHS.getTreeDepth())340return true;341if (getTreeDepth() < RHS.getTreeDepth())342return false;343} else {344// Unrelated tokens and user classes are ordered by the name of their345// root nodes, so that there is a consistent ordering between346// unconnected trees.347return findRoot()->ValueName < RHS.findRoot()->ValueName;348}349} else if (isRegisterClass()) {350// For register sets, sort by number of registers. This guarantees that351// a set will always sort before all of it's strict supersets.352if (Registers.size() != RHS.Registers.size())353return Registers.size() < RHS.Registers.size();354} else {355llvm_unreachable("Unknown ClassInfoKind");356}357358// FIXME: We should be able to just return false here, as we only need a359// partial order (we use stable sorts, so this is deterministic) and the360// name of a class shouldn't be significant. However, some of the backends361// accidentally rely on this behaviour, so it will have to stay like this362// until they are fixed.363return ValueName < RHS.ValueName;364}365};366367class AsmVariantInfo {368public:369StringRef RegisterPrefix;370StringRef TokenizingCharacters;371StringRef SeparatorCharacters;372StringRef BreakCharacters;373StringRef Name;374int AsmVariantNo;375};376377bool getPreferSmallerInstructions(CodeGenTarget const &Target) {378return Target.getAsmParser()->getValueAsBit("PreferSmallerInstructions");379}380381/// MatchableInfo - Helper class for storing the necessary information for an382/// instruction or alias which is capable of being matched.383struct MatchableInfo {384struct AsmOperand {385/// Token - This is the token that the operand came from.386StringRef Token;387388/// The unique class instance this operand should match.389ClassInfo *Class;390391/// The operand name this is, if anything.392StringRef SrcOpName;393394/// The operand name this is, before renaming for tied operands.395StringRef OrigSrcOpName;396397/// The suboperand index within SrcOpName, or -1 for the entire operand.398int SubOpIdx;399400/// Whether the token is "isolated", i.e., it is preceded and followed401/// by separators.402bool IsIsolatedToken;403404/// Register record if this token is singleton register.405Record *SingletonReg;406407explicit AsmOperand(bool IsIsolatedToken, StringRef T)408: Token(T), Class(nullptr), SubOpIdx(-1),409IsIsolatedToken(IsIsolatedToken), SingletonReg(nullptr) {}410};411412/// ResOperand - This represents a single operand in the result instruction413/// generated by the match. In cases (like addressing modes) where a single414/// assembler operand expands to multiple MCOperands, this represents the415/// single assembler operand, not the MCOperand.416struct ResOperand {417enum {418/// RenderAsmOperand - This represents an operand result that is419/// generated by calling the render method on the assembly operand. The420/// corresponding AsmOperand is specified by AsmOperandNum.421RenderAsmOperand,422423/// TiedOperand - This represents a result operand that is a duplicate of424/// a previous result operand.425TiedOperand,426427/// ImmOperand - This represents an immediate value that is dumped into428/// the operand.429ImmOperand,430431/// RegOperand - This represents a fixed register that is dumped in.432RegOperand433} Kind;434435/// Tuple containing the index of the (earlier) result operand that should436/// be copied from, as well as the indices of the corresponding (parsed)437/// operands in the asm string.438struct TiedOperandsTuple {439unsigned ResOpnd;440unsigned SrcOpnd1Idx;441unsigned SrcOpnd2Idx;442};443444union {445/// This is the operand # in the AsmOperands list that this should be446/// copied from.447unsigned AsmOperandNum;448449/// Description of tied operands.450TiedOperandsTuple TiedOperands;451452/// ImmVal - This is the immediate value added to the instruction.453int64_t ImmVal;454455/// Register - This is the register record.456Record *Register;457};458459/// MINumOperands - The number of MCInst operands populated by this460/// operand.461unsigned MINumOperands;462463static ResOperand getRenderedOp(unsigned AsmOpNum, unsigned NumOperands) {464ResOperand X;465X.Kind = RenderAsmOperand;466X.AsmOperandNum = AsmOpNum;467X.MINumOperands = NumOperands;468return X;469}470471static ResOperand getTiedOp(unsigned TiedOperandNum, unsigned SrcOperand1,472unsigned SrcOperand2) {473ResOperand X;474X.Kind = TiedOperand;475X.TiedOperands = {TiedOperandNum, SrcOperand1, SrcOperand2};476X.MINumOperands = 1;477return X;478}479480static ResOperand getImmOp(int64_t Val) {481ResOperand X;482X.Kind = ImmOperand;483X.ImmVal = Val;484X.MINumOperands = 1;485return X;486}487488static ResOperand getRegOp(Record *Reg) {489ResOperand X;490X.Kind = RegOperand;491X.Register = Reg;492X.MINumOperands = 1;493return X;494}495};496497/// AsmVariantID - Target's assembly syntax variant no.498int AsmVariantID;499500/// AsmString - The assembly string for this instruction (with variants501/// removed), e.g. "movsx $src, $dst".502std::string AsmString;503504/// TheDef - This is the definition of the instruction or InstAlias that this505/// matchable came from.506Record *const TheDef;507508// ResInstSize - The size of the resulting instruction for this matchable.509unsigned ResInstSize;510511/// DefRec - This is the definition that it came from.512PointerUnion<const CodeGenInstruction *, const CodeGenInstAlias *> DefRec;513514const CodeGenInstruction *getResultInst() const {515if (isa<const CodeGenInstruction *>(DefRec))516return cast<const CodeGenInstruction *>(DefRec);517return cast<const CodeGenInstAlias *>(DefRec)->ResultInst;518}519520/// ResOperands - This is the operand list that should be built for the result521/// MCInst.522SmallVector<ResOperand, 8> ResOperands;523524/// Mnemonic - This is the first token of the matched instruction, its525/// mnemonic.526StringRef Mnemonic;527528/// AsmOperands - The textual operands that this instruction matches,529/// annotated with a class and where in the OperandList they were defined.530/// This directly corresponds to the tokenized AsmString after the mnemonic is531/// removed.532SmallVector<AsmOperand, 8> AsmOperands;533534/// Predicates - The required subtarget features to match this instruction.535SmallVector<const SubtargetFeatureInfo *, 4> RequiredFeatures;536537/// ConversionFnKind - The enum value which is passed to the generated538/// convertToMCInst to convert parsed operands into an MCInst for this539/// function.540std::string ConversionFnKind;541542/// If this instruction is deprecated in some form.543bool HasDeprecation = false;544545/// If this is an alias, this is use to determine whether or not to using546/// the conversion function defined by the instruction's AsmMatchConverter547/// or to use the function generated by the alias.548bool UseInstAsmMatchConverter;549550MatchableInfo(const CodeGenInstruction &CGI)551: AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef),552ResInstSize(TheDef->getValueAsInt("Size")), DefRec(&CGI),553UseInstAsmMatchConverter(true) {}554555MatchableInfo(std::unique_ptr<const CodeGenInstAlias> Alias)556: AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef),557ResInstSize(Alias->ResultInst->TheDef->getValueAsInt("Size")),558DefRec(Alias.release()), UseInstAsmMatchConverter(TheDef->getValueAsBit(559"UseInstAsmMatchConverter")) {}560561// Could remove this and the dtor if PointerUnion supported unique_ptr562// elements with a dynamic failure/assertion (like the one below) in the case563// where it was copied while being in an owning state.564MatchableInfo(const MatchableInfo &RHS)565: AsmVariantID(RHS.AsmVariantID), AsmString(RHS.AsmString),566TheDef(RHS.TheDef), ResInstSize(RHS.ResInstSize), DefRec(RHS.DefRec),567ResOperands(RHS.ResOperands), Mnemonic(RHS.Mnemonic),568AsmOperands(RHS.AsmOperands), RequiredFeatures(RHS.RequiredFeatures),569ConversionFnKind(RHS.ConversionFnKind),570HasDeprecation(RHS.HasDeprecation),571UseInstAsmMatchConverter(RHS.UseInstAsmMatchConverter) {572assert(!isa<const CodeGenInstAlias *>(DefRec));573}574575~MatchableInfo() {576delete dyn_cast_if_present<const CodeGenInstAlias *>(DefRec);577}578579// Two-operand aliases clone from the main matchable, but mark the second580// operand as a tied operand of the first for purposes of the assembler.581void formTwoOperandAlias(StringRef Constraint);582583void initialize(const AsmMatcherInfo &Info,584SmallPtrSetImpl<Record *> &SingletonRegisters,585AsmVariantInfo const &Variant, bool HasMnemonicFirst);586587/// validate - Return true if this matchable is a valid thing to match against588/// and perform a bunch of validity checking.589bool validate(StringRef CommentDelimiter, bool IsAlias) const;590591/// findAsmOperand - Find the AsmOperand with the specified name and592/// suboperand index.593int findAsmOperand(StringRef N, int SubOpIdx) const {594auto I = find_if(AsmOperands, [&](const AsmOperand &Op) {595return Op.SrcOpName == N && Op.SubOpIdx == SubOpIdx;596});597return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1;598}599600/// findAsmOperandNamed - Find the first AsmOperand with the specified name.601/// This does not check the suboperand index.602int findAsmOperandNamed(StringRef N, int LastIdx = -1) const {603auto I =604llvm::find_if(llvm::drop_begin(AsmOperands, LastIdx + 1),605[&](const AsmOperand &Op) { return Op.SrcOpName == N; });606return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1;607}608609int findAsmOperandOriginallyNamed(StringRef N) const {610auto I = find_if(AsmOperands, [&](const AsmOperand &Op) {611return Op.OrigSrcOpName == N;612});613return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1;614}615616void buildInstructionResultOperands();617void buildAliasResultOperands(bool AliasConstraintsAreChecked);618619/// shouldBeMatchedBefore - Compare two matchables for ordering.620bool shouldBeMatchedBefore(const MatchableInfo &RHS,621bool PreferSmallerInstructions) const {622// The primary comparator is the instruction mnemonic.623if (int Cmp = Mnemonic.compare_insensitive(RHS.Mnemonic))624return Cmp == -1;625626// (Optionally) Order by the resultant instuctions size.627// eg. for ARM thumb instructions smaller encodings should be preferred.628if (PreferSmallerInstructions && ResInstSize != RHS.ResInstSize)629return ResInstSize < RHS.ResInstSize;630631if (AsmOperands.size() != RHS.AsmOperands.size())632return AsmOperands.size() < RHS.AsmOperands.size();633634// Compare lexicographically by operand. The matcher validates that other635// orderings wouldn't be ambiguous using \see couldMatchAmbiguouslyWith().636for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {637if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class)638return true;639if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class)640return false;641}642643// For X86 AVX/AVX512 instructions, we prefer vex encoding because the644// vex encoding size is smaller. Since X86InstrSSE.td is included ahead645// of X86InstrAVX512.td, the AVX instruction ID is less than AVX512 ID.646// We use the ID to sort AVX instruction before AVX512 instruction in647// matching table. As well as InstAlias.648if (getResultInst()->TheDef->isSubClassOf("Instruction") &&649getResultInst()->TheDef->getValueAsBit("HasPositionOrder") &&650RHS.getResultInst()->TheDef->isSubClassOf("Instruction") &&651RHS.getResultInst()->TheDef->getValueAsBit("HasPositionOrder"))652return getResultInst()->TheDef->getID() <653RHS.getResultInst()->TheDef->getID();654655// Give matches that require more features higher precedence. This is useful656// because we cannot define AssemblerPredicates with the negation of657// processor features. For example, ARM v6 "nop" may be either a HINT or658// MOV. With v6, we want to match HINT. The assembler has no way to659// predicate MOV under "NoV6", but HINT will always match first because it660// requires V6 while MOV does not.661if (RequiredFeatures.size() != RHS.RequiredFeatures.size())662return RequiredFeatures.size() > RHS.RequiredFeatures.size();663664return false;665}666667/// couldMatchAmbiguouslyWith - Check whether this matchable could668/// ambiguously match the same set of operands as \p RHS (without being a669/// strictly superior match).670bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS,671bool PreferSmallerInstructions) const {672// The primary comparator is the instruction mnemonic.673if (Mnemonic != RHS.Mnemonic)674return false;675676// Different variants can't conflict.677if (AsmVariantID != RHS.AsmVariantID)678return false;679680// The size of instruction is unambiguous.681if (PreferSmallerInstructions && ResInstSize != RHS.ResInstSize)682return false;683684// The number of operands is unambiguous.685if (AsmOperands.size() != RHS.AsmOperands.size())686return false;687688// Otherwise, make sure the ordering of the two instructions is unambiguous689// by checking that either (a) a token or operand kind discriminates them,690// or (b) the ordering among equivalent kinds is consistent.691692// Tokens and operand kinds are unambiguous (assuming a correct target693// specific parser).694for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i)695if (AsmOperands[i].Class->Kind != RHS.AsmOperands[i].Class->Kind ||696AsmOperands[i].Class->Kind == ClassInfo::Token)697if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class ||698*RHS.AsmOperands[i].Class < *AsmOperands[i].Class)699return false;700701// Otherwise, this operand could commute if all operands are equivalent, or702// there is a pair of operands that compare less than and a pair that703// compare greater than.704bool HasLT = false, HasGT = false;705for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {706if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class)707HasLT = true;708if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class)709HasGT = true;710}711712return HasLT == HasGT;713}714715void dump() const;716717private:718void tokenizeAsmString(AsmMatcherInfo const &Info,719AsmVariantInfo const &Variant);720void addAsmOperand(StringRef Token, bool IsIsolatedToken = false);721};722723struct OperandMatchEntry {724unsigned OperandMask;725const MatchableInfo *MI;726ClassInfo *CI;727728static OperandMatchEntry create(const MatchableInfo *mi, ClassInfo *ci,729unsigned opMask) {730OperandMatchEntry X;731X.OperandMask = opMask;732X.CI = ci;733X.MI = mi;734return X;735}736};737738class AsmMatcherInfo {739public:740/// Tracked Records741RecordKeeper &Records;742743/// The tablegen AsmParser record.744Record *AsmParser;745746/// Target - The target information.747CodeGenTarget &Target;748749/// The classes which are needed for matching.750std::forward_list<ClassInfo> Classes;751752/// The information on the matchables to match.753std::vector<std::unique_ptr<MatchableInfo>> Matchables;754755/// Info for custom matching operands by user defined methods.756std::vector<OperandMatchEntry> OperandMatchInfo;757758/// Map of Register records to their class information.759typedef std::map<Record *, ClassInfo *, LessRecordByID> RegisterClassesTy;760RegisterClassesTy RegisterClasses;761762/// Map of Predicate records to their subtarget information.763std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;764765/// Map of AsmOperandClass records to their class information.766std::map<Record *, ClassInfo *> AsmOperandClasses;767768/// Map of RegisterClass records to their class information.769std::map<Record *, ClassInfo *> RegisterClassClasses;770771private:772/// Map of token to class information which has already been constructed.773std::map<std::string, ClassInfo *> TokenClasses;774775private:776/// getTokenClass - Lookup or create the class for the given token.777ClassInfo *getTokenClass(StringRef Token);778779/// getOperandClass - Lookup or create the class for the given operand.780ClassInfo *getOperandClass(const CGIOperandList::OperandInfo &OI,781int SubOpIdx);782ClassInfo *getOperandClass(Record *Rec, int SubOpIdx);783784/// buildRegisterClasses - Build the ClassInfo* instances for register785/// classes.786void buildRegisterClasses(SmallPtrSetImpl<Record *> &SingletonRegisters);787788/// buildOperandClasses - Build the ClassInfo* instances for user defined789/// operand classes.790void buildOperandClasses();791792void buildInstructionOperandReference(MatchableInfo *II, StringRef OpName,793unsigned AsmOpIdx);794void buildAliasOperandReference(MatchableInfo *II, StringRef OpName,795MatchableInfo::AsmOperand &Op);796797public:798AsmMatcherInfo(Record *AsmParser, CodeGenTarget &Target,799RecordKeeper &Records);800801/// Construct the various tables used during matching.802void buildInfo();803804/// buildOperandMatchInfo - Build the necessary information to handle user805/// defined operand parsing methods.806void buildOperandMatchInfo();807808/// getSubtargetFeature - Lookup or create the subtarget feature info for the809/// given operand.810const SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const {811assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!");812const auto &I = SubtargetFeatures.find(Def);813return I == SubtargetFeatures.end() ? nullptr : &I->second;814}815816RecordKeeper &getRecords() const { return Records; }817818bool hasOptionalOperands() const {819return any_of(Classes,820[](const ClassInfo &Class) { return Class.IsOptional; });821}822};823824} // end anonymous namespace825826#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)827LLVM_DUMP_METHOD void MatchableInfo::dump() const {828errs() << TheDef->getName() << " -- "829<< "flattened:\"" << AsmString << "\"\n";830831errs() << " variant: " << AsmVariantID << "\n";832833for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {834const AsmOperand &Op = AsmOperands[i];835errs() << " op[" << i << "] = " << Op.Class->ClassName << " - ";836errs() << '\"' << Op.Token << "\"\n";837}838}839#endif840841static std::pair<StringRef, StringRef>842parseTwoOperandConstraint(StringRef S, ArrayRef<SMLoc> Loc) {843// Split via the '='.844std::pair<StringRef, StringRef> Ops = S.split('=');845if (Ops.second == "")846PrintFatalError(Loc, "missing '=' in two-operand alias constraint");847// Trim whitespace and the leading '$' on the operand names.848size_t start = Ops.first.find_first_of('$');849if (start == std::string::npos)850PrintFatalError(Loc, "expected '$' prefix on asm operand name");851Ops.first = Ops.first.slice(start + 1, std::string::npos);852size_t end = Ops.first.find_last_of(" \t");853Ops.first = Ops.first.slice(0, end);854// Now the second operand.855start = Ops.second.find_first_of('$');856if (start == std::string::npos)857PrintFatalError(Loc, "expected '$' prefix on asm operand name");858Ops.second = Ops.second.slice(start + 1, std::string::npos);859end = Ops.second.find_last_of(" \t");860Ops.first = Ops.first.slice(0, end);861return Ops;862}863864void MatchableInfo::formTwoOperandAlias(StringRef Constraint) {865// Figure out which operands are aliased and mark them as tied.866std::pair<StringRef, StringRef> Ops =867parseTwoOperandConstraint(Constraint, TheDef->getLoc());868869// Find the AsmOperands that refer to the operands we're aliasing.870int SrcAsmOperand = findAsmOperandNamed(Ops.first);871int DstAsmOperand = findAsmOperandNamed(Ops.second);872if (SrcAsmOperand == -1)873PrintFatalError(TheDef->getLoc(),874"unknown source two-operand alias operand '" + Ops.first +875"'.");876if (DstAsmOperand == -1)877PrintFatalError(TheDef->getLoc(),878"unknown destination two-operand alias operand '" +879Ops.second + "'.");880881// Find the ResOperand that refers to the operand we're aliasing away882// and update it to refer to the combined operand instead.883for (ResOperand &Op : ResOperands) {884if (Op.Kind == ResOperand::RenderAsmOperand &&885Op.AsmOperandNum == (unsigned)SrcAsmOperand) {886Op.AsmOperandNum = DstAsmOperand;887break;888}889}890// Remove the AsmOperand for the alias operand.891AsmOperands.erase(AsmOperands.begin() + SrcAsmOperand);892// Adjust the ResOperand references to any AsmOperands that followed893// the one we just deleted.894for (ResOperand &Op : ResOperands) {895switch (Op.Kind) {896default:897// Nothing to do for operands that don't reference AsmOperands.898break;899case ResOperand::RenderAsmOperand:900if (Op.AsmOperandNum > (unsigned)SrcAsmOperand)901--Op.AsmOperandNum;902break;903}904}905}906907/// extractSingletonRegisterForAsmOperand - Extract singleton register,908/// if present, from specified token.909static void extractSingletonRegisterForAsmOperand(MatchableInfo::AsmOperand &Op,910const AsmMatcherInfo &Info,911StringRef RegisterPrefix) {912StringRef Tok = Op.Token;913914// If this token is not an isolated token, i.e., it isn't separated from915// other tokens (e.g. with whitespace), don't interpret it as a register name.916if (!Op.IsIsolatedToken)917return;918919if (RegisterPrefix.empty()) {920std::string LoweredTok = Tok.lower();921if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(LoweredTok))922Op.SingletonReg = Reg->TheDef;923return;924}925926if (!Tok.starts_with(RegisterPrefix))927return;928929StringRef RegName = Tok.substr(RegisterPrefix.size());930if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName))931Op.SingletonReg = Reg->TheDef;932933// If there is no register prefix (i.e. "%" in "%eax"), then this may934// be some random non-register token, just ignore it.935}936937void MatchableInfo::initialize(const AsmMatcherInfo &Info,938SmallPtrSetImpl<Record *> &SingletonRegisters,939AsmVariantInfo const &Variant,940bool HasMnemonicFirst) {941AsmVariantID = Variant.AsmVariantNo;942AsmString = CodeGenInstruction::FlattenAsmStringVariants(943AsmString, Variant.AsmVariantNo);944945tokenizeAsmString(Info, Variant);946947// The first token of the instruction is the mnemonic, which must be a948// simple string, not a $foo variable or a singleton register.949if (AsmOperands.empty())950PrintFatalError(TheDef->getLoc(),951"Instruction '" + TheDef->getName() + "' has no tokens");952953assert(!AsmOperands[0].Token.empty());954if (HasMnemonicFirst) {955Mnemonic = AsmOperands[0].Token;956if (Mnemonic[0] == '$')957PrintFatalError(TheDef->getLoc(),958"Invalid instruction mnemonic '" + Mnemonic + "'!");959960// Remove the first operand, it is tracked in the mnemonic field.961AsmOperands.erase(AsmOperands.begin());962} else if (AsmOperands[0].Token[0] != '$')963Mnemonic = AsmOperands[0].Token;964965// Compute the require features.966for (Record *Predicate : TheDef->getValueAsListOfDefs("Predicates"))967if (const SubtargetFeatureInfo *Feature =968Info.getSubtargetFeature(Predicate))969RequiredFeatures.push_back(Feature);970971// Collect singleton registers, if used.972for (MatchableInfo::AsmOperand &Op : AsmOperands) {973extractSingletonRegisterForAsmOperand(Op, Info, Variant.RegisterPrefix);974if (Record *Reg = Op.SingletonReg)975SingletonRegisters.insert(Reg);976}977978const RecordVal *DepMask = TheDef->getValue("DeprecatedFeatureMask");979if (!DepMask)980DepMask = TheDef->getValue("ComplexDeprecationPredicate");981982HasDeprecation =983DepMask ? !DepMask->getValue()->getAsUnquotedString().empty() : false;984}985986/// Append an AsmOperand for the given substring of AsmString.987void MatchableInfo::addAsmOperand(StringRef Token, bool IsIsolatedToken) {988AsmOperands.push_back(AsmOperand(IsIsolatedToken, Token));989}990991/// tokenizeAsmString - Tokenize a simplified assembly string.992void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info,993AsmVariantInfo const &Variant) {994StringRef String = AsmString;995size_t Prev = 0;996bool InTok = false;997bool IsIsolatedToken = true;998for (size_t i = 0, e = String.size(); i != e; ++i) {999char Char = String[i];1000if (Variant.BreakCharacters.contains(Char)) {1001if (InTok) {1002addAsmOperand(String.slice(Prev, i), false);1003Prev = i;1004IsIsolatedToken = false;1005}1006InTok = true;1007continue;1008}1009if (Variant.TokenizingCharacters.contains(Char)) {1010if (InTok) {1011addAsmOperand(String.slice(Prev, i), IsIsolatedToken);1012InTok = false;1013IsIsolatedToken = false;1014}1015addAsmOperand(String.slice(i, i + 1), IsIsolatedToken);1016Prev = i + 1;1017IsIsolatedToken = true;1018continue;1019}1020if (Variant.SeparatorCharacters.contains(Char)) {1021if (InTok) {1022addAsmOperand(String.slice(Prev, i), IsIsolatedToken);1023InTok = false;1024}1025Prev = i + 1;1026IsIsolatedToken = true;1027continue;1028}10291030switch (Char) {1031case '\\':1032if (InTok) {1033addAsmOperand(String.slice(Prev, i), false);1034InTok = false;1035IsIsolatedToken = false;1036}1037++i;1038assert(i != String.size() && "Invalid quoted character");1039addAsmOperand(String.slice(i, i + 1), IsIsolatedToken);1040Prev = i + 1;1041IsIsolatedToken = false;1042break;10431044case '$': {1045if (InTok) {1046addAsmOperand(String.slice(Prev, i), IsIsolatedToken);1047InTok = false;1048IsIsolatedToken = false;1049}10501051// If this isn't "${", start new identifier looking like "$xxx"1052if (i + 1 == String.size() || String[i + 1] != '{') {1053Prev = i;1054break;1055}10561057size_t EndPos = String.find('}', i);1058assert(EndPos != StringRef::npos &&1059"Missing brace in operand reference!");1060addAsmOperand(String.slice(i, EndPos + 1), IsIsolatedToken);1061Prev = EndPos + 1;1062i = EndPos;1063IsIsolatedToken = false;1064break;1065}10661067default:1068InTok = true;1069break;1070}1071}1072if (InTok && Prev != String.size())1073addAsmOperand(String.substr(Prev), IsIsolatedToken);1074}10751076bool MatchableInfo::validate(StringRef CommentDelimiter, bool IsAlias) const {1077// Reject matchables with no .s string.1078if (AsmString.empty())1079PrintFatalError(TheDef->getLoc(), "instruction with empty asm string");10801081// Reject any matchables with a newline in them, they should be marked1082// isCodeGenOnly if they are pseudo instructions.1083if (AsmString.find('\n') != std::string::npos)1084PrintFatalError(TheDef->getLoc(),1085"multiline instruction is not valid for the asmparser, "1086"mark it isCodeGenOnly");10871088// Remove comments from the asm string. We know that the asmstring only1089// has one line.1090if (!CommentDelimiter.empty() &&1091StringRef(AsmString).contains(CommentDelimiter))1092PrintFatalError(TheDef->getLoc(),1093"asmstring for instruction has comment character in it, "1094"mark it isCodeGenOnly");10951096// Reject matchables with operand modifiers, these aren't something we can1097// handle, the target should be refactored to use operands instead of1098// modifiers.1099//1100// Also, check for instructions which reference the operand multiple times,1101// if they don't define a custom AsmMatcher: this implies a constraint that1102// the built-in matching code would not honor.1103std::set<std::string> OperandNames;1104for (const AsmOperand &Op : AsmOperands) {1105StringRef Tok = Op.Token;1106if (Tok[0] == '$' && Tok.contains(':'))1107PrintFatalError(1108TheDef->getLoc(),1109"matchable with operand modifier '" + Tok +1110"' not supported by asm matcher. Mark isCodeGenOnly!");1111// Verify that any operand is only mentioned once.1112// We reject aliases and ignore instructions for now.1113if (!IsAlias && TheDef->getValueAsString("AsmMatchConverter").empty() &&1114Tok[0] == '$' && !OperandNames.insert(std::string(Tok)).second) {1115LLVM_DEBUG({1116errs() << "warning: '" << TheDef->getName() << "': "1117<< "ignoring instruction with tied operand '" << Tok << "'\n";1118});1119return false;1120}1121}11221123return true;1124}11251126static std::string getEnumNameForToken(StringRef Str) {1127std::string Res;11281129for (char C : Str) {1130switch (C) {1131case '*':1132Res += "_STAR_";1133break;1134case '%':1135Res += "_PCT_";1136break;1137case ':':1138Res += "_COLON_";1139break;1140case '!':1141Res += "_EXCLAIM_";1142break;1143case '.':1144Res += "_DOT_";1145break;1146case '<':1147Res += "_LT_";1148break;1149case '>':1150Res += "_GT_";1151break;1152case '-':1153Res += "_MINUS_";1154break;1155case '#':1156Res += "_HASH_";1157break;1158default:1159if (isAlnum(C))1160Res += C;1161else1162Res += "_" + utostr((unsigned)C) + "_";1163}1164}11651166return Res;1167}11681169ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) {1170ClassInfo *&Entry = TokenClasses[std::string(Token)];11711172if (!Entry) {1173Classes.emplace_front();1174Entry = &Classes.front();1175Entry->Kind = ClassInfo::Token;1176Entry->ClassName = "Token";1177Entry->Name = "MCK_" + getEnumNameForToken(Token);1178Entry->ValueName = std::string(Token);1179Entry->PredicateMethod = "<invalid>";1180Entry->RenderMethod = "<invalid>";1181Entry->ParserMethod = "";1182Entry->DiagnosticType = "";1183Entry->IsOptional = false;1184Entry->DefaultMethod = "<invalid>";1185}11861187return Entry;1188}11891190ClassInfo *1191AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI,1192int SubOpIdx) {1193Record *Rec = OI.Rec;1194if (SubOpIdx != -1)1195Rec = cast<DefInit>(OI.MIOperandInfo->getArg(SubOpIdx))->getDef();1196return getOperandClass(Rec, SubOpIdx);1197}11981199ClassInfo *AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) {1200if (Rec->isSubClassOf("RegisterOperand")) {1201// RegisterOperand may have an associated ParserMatchClass. If it does,1202// use it, else just fall back to the underlying register class.1203const RecordVal *R = Rec->getValue("ParserMatchClass");1204if (!R || !R->getValue())1205PrintFatalError(Rec->getLoc(),1206"Record `" + Rec->getName() +1207"' does not have a ParserMatchClass!\n");12081209if (DefInit *DI = dyn_cast<DefInit>(R->getValue())) {1210Record *MatchClass = DI->getDef();1211if (ClassInfo *CI = AsmOperandClasses[MatchClass])1212return CI;1213}12141215// No custom match class. Just use the register class.1216Record *ClassRec = Rec->getValueAsDef("RegClass");1217if (!ClassRec)1218PrintFatalError(Rec->getLoc(),1219"RegisterOperand `" + Rec->getName() +1220"' has no associated register class!\n");1221if (ClassInfo *CI = RegisterClassClasses[ClassRec])1222return CI;1223PrintFatalError(Rec->getLoc(), "register class has no class info!");1224}12251226if (Rec->isSubClassOf("RegisterClass")) {1227if (ClassInfo *CI = RegisterClassClasses[Rec])1228return CI;1229PrintFatalError(Rec->getLoc(), "register class has no class info!");1230}12311232if (!Rec->isSubClassOf("Operand"))1233PrintFatalError(Rec->getLoc(),1234"Operand `" + Rec->getName() +1235"' does not derive from class Operand!\n");1236Record *MatchClass = Rec->getValueAsDef("ParserMatchClass");1237if (ClassInfo *CI = AsmOperandClasses[MatchClass])1238return CI;12391240PrintFatalError(Rec->getLoc(), "operand has no match class!");1241}12421243struct LessRegisterSet {1244bool operator()(const RegisterSet &LHS, const RegisterSet &RHS) const {1245// std::set<T> defines its own compariso "operator<", but it1246// performs a lexicographical comparison by T's innate comparison1247// for some reason. We don't want non-deterministic pointer1248// comparisons so use this instead.1249return std::lexicographical_compare(LHS.begin(), LHS.end(), RHS.begin(),1250RHS.end(), LessRecordByID());1251}1252};12531254void AsmMatcherInfo::buildRegisterClasses(1255SmallPtrSetImpl<Record *> &SingletonRegisters) {1256const auto &Registers = Target.getRegBank().getRegisters();1257auto &RegClassList = Target.getRegBank().getRegClasses();12581259typedef std::set<RegisterSet, LessRegisterSet> RegisterSetSet;12601261// The register sets used for matching.1262RegisterSetSet RegisterSets;12631264// Gather the defined sets.1265for (const CodeGenRegisterClass &RC : RegClassList)1266RegisterSets.insert(1267RegisterSet(RC.getOrder().begin(), RC.getOrder().end()));12681269// Add any required singleton sets.1270for (Record *Rec : SingletonRegisters) {1271RegisterSets.insert(RegisterSet(&Rec, &Rec + 1));1272}12731274// Introduce derived sets where necessary (when a register does not determine1275// a unique register set class), and build the mapping of registers to the set1276// they should classify to.1277std::map<Record *, RegisterSet> RegisterMap;1278for (const CodeGenRegister &CGR : Registers) {1279// Compute the intersection of all sets containing this register.1280RegisterSet ContainingSet;12811282for (const RegisterSet &RS : RegisterSets) {1283if (!RS.count(CGR.TheDef))1284continue;12851286if (ContainingSet.empty()) {1287ContainingSet = RS;1288continue;1289}12901291RegisterSet Tmp;1292std::set_intersection(ContainingSet.begin(), ContainingSet.end(),1293RS.begin(), RS.end(),1294std::inserter(Tmp, Tmp.begin()), LessRecordByID());1295ContainingSet = std::move(Tmp);1296}12971298if (!ContainingSet.empty()) {1299RegisterSets.insert(ContainingSet);1300RegisterMap.insert(std::pair(CGR.TheDef, ContainingSet));1301}1302}13031304// Construct the register classes.1305std::map<RegisterSet, ClassInfo *, LessRegisterSet> RegisterSetClasses;1306unsigned Index = 0;1307for (const RegisterSet &RS : RegisterSets) {1308Classes.emplace_front();1309ClassInfo *CI = &Classes.front();1310CI->Kind = ClassInfo::RegisterClass0 + Index;1311CI->ClassName = "Reg" + utostr(Index);1312CI->Name = "MCK_Reg" + utostr(Index);1313CI->ValueName = "";1314CI->PredicateMethod = ""; // unused1315CI->RenderMethod = "addRegOperands";1316CI->Registers = RS;1317// FIXME: diagnostic type.1318CI->DiagnosticType = "";1319CI->IsOptional = false;1320CI->DefaultMethod = ""; // unused1321RegisterSetClasses.insert(std::pair(RS, CI));1322++Index;1323}13241325// Find the superclasses; we could compute only the subgroup lattice edges,1326// but there isn't really a point.1327for (const RegisterSet &RS : RegisterSets) {1328ClassInfo *CI = RegisterSetClasses[RS];1329for (const RegisterSet &RS2 : RegisterSets)1330if (RS != RS2 && std::includes(RS2.begin(), RS2.end(), RS.begin(),1331RS.end(), LessRecordByID()))1332CI->SuperClasses.push_back(RegisterSetClasses[RS2]);1333}13341335// Name the register classes which correspond to a user defined RegisterClass.1336for (const CodeGenRegisterClass &RC : RegClassList) {1337// Def will be NULL for non-user defined register classes.1338Record *Def = RC.getDef();1339if (!Def)1340continue;1341ClassInfo *CI = RegisterSetClasses[RegisterSet(RC.getOrder().begin(),1342RC.getOrder().end())];1343if (CI->ValueName.empty()) {1344CI->ClassName = RC.getName();1345CI->Name = "MCK_" + RC.getName();1346CI->ValueName = RC.getName();1347} else1348CI->ValueName = CI->ValueName + "," + RC.getName();13491350Init *DiagnosticType = Def->getValueInit("DiagnosticType");1351if (StringInit *SI = dyn_cast<StringInit>(DiagnosticType))1352CI->DiagnosticType = std::string(SI->getValue());13531354Init *DiagnosticString = Def->getValueInit("DiagnosticString");1355if (StringInit *SI = dyn_cast<StringInit>(DiagnosticString))1356CI->DiagnosticString = std::string(SI->getValue());13571358// If we have a diagnostic string but the diagnostic type is not specified1359// explicitly, create an anonymous diagnostic type.1360if (!CI->DiagnosticString.empty() && CI->DiagnosticType.empty())1361CI->DiagnosticType = RC.getName();13621363RegisterClassClasses.insert(std::pair(Def, CI));1364}13651366// Populate the map for individual registers.1367for (auto &It : RegisterMap)1368RegisterClasses[It.first] = RegisterSetClasses[It.second];13691370// Name the register classes which correspond to singleton registers.1371for (Record *Rec : SingletonRegisters) {1372ClassInfo *CI = RegisterClasses[Rec];1373assert(CI && "Missing singleton register class info!");13741375if (CI->ValueName.empty()) {1376CI->ClassName = std::string(Rec->getName());1377CI->Name = "MCK_" + Rec->getName().str();1378CI->ValueName = std::string(Rec->getName());1379} else1380CI->ValueName = CI->ValueName + "," + Rec->getName().str();1381}1382}13831384void AsmMatcherInfo::buildOperandClasses() {1385std::vector<Record *> AsmOperands =1386Records.getAllDerivedDefinitions("AsmOperandClass");13871388// Pre-populate AsmOperandClasses map.1389for (Record *Rec : AsmOperands) {1390Classes.emplace_front();1391AsmOperandClasses[Rec] = &Classes.front();1392}13931394unsigned Index = 0;1395for (Record *Rec : AsmOperands) {1396ClassInfo *CI = AsmOperandClasses[Rec];1397CI->Kind = ClassInfo::UserClass0 + Index;13981399ListInit *Supers = Rec->getValueAsListInit("SuperClasses");1400for (Init *I : Supers->getValues()) {1401DefInit *DI = dyn_cast<DefInit>(I);1402if (!DI) {1403PrintError(Rec->getLoc(), "Invalid super class reference!");1404continue;1405}14061407ClassInfo *SC = AsmOperandClasses[DI->getDef()];1408if (!SC)1409PrintError(Rec->getLoc(), "Invalid super class reference!");1410else1411CI->SuperClasses.push_back(SC);1412}1413CI->ClassName = std::string(Rec->getValueAsString("Name"));1414CI->Name = "MCK_" + CI->ClassName;1415CI->ValueName = std::string(Rec->getName());14161417// Get or construct the predicate method name.1418Init *PMName = Rec->getValueInit("PredicateMethod");1419if (StringInit *SI = dyn_cast<StringInit>(PMName)) {1420CI->PredicateMethod = std::string(SI->getValue());1421} else {1422assert(isa<UnsetInit>(PMName) && "Unexpected PredicateMethod field!");1423CI->PredicateMethod = "is" + CI->ClassName;1424}14251426// Get or construct the render method name.1427Init *RMName = Rec->getValueInit("RenderMethod");1428if (StringInit *SI = dyn_cast<StringInit>(RMName)) {1429CI->RenderMethod = std::string(SI->getValue());1430} else {1431assert(isa<UnsetInit>(RMName) && "Unexpected RenderMethod field!");1432CI->RenderMethod = "add" + CI->ClassName + "Operands";1433}14341435// Get the parse method name or leave it as empty.1436Init *PRMName = Rec->getValueInit("ParserMethod");1437if (StringInit *SI = dyn_cast<StringInit>(PRMName))1438CI->ParserMethod = std::string(SI->getValue());14391440// Get the diagnostic type and string or leave them as empty.1441Init *DiagnosticType = Rec->getValueInit("DiagnosticType");1442if (StringInit *SI = dyn_cast<StringInit>(DiagnosticType))1443CI->DiagnosticType = std::string(SI->getValue());1444Init *DiagnosticString = Rec->getValueInit("DiagnosticString");1445if (StringInit *SI = dyn_cast<StringInit>(DiagnosticString))1446CI->DiagnosticString = std::string(SI->getValue());1447// If we have a DiagnosticString, we need a DiagnosticType for use within1448// the matcher.1449if (!CI->DiagnosticString.empty() && CI->DiagnosticType.empty())1450CI->DiagnosticType = CI->ClassName;14511452Init *IsOptional = Rec->getValueInit("IsOptional");1453if (BitInit *BI = dyn_cast<BitInit>(IsOptional))1454CI->IsOptional = BI->getValue();14551456// Get or construct the default method name.1457Init *DMName = Rec->getValueInit("DefaultMethod");1458if (StringInit *SI = dyn_cast<StringInit>(DMName)) {1459CI->DefaultMethod = std::string(SI->getValue());1460} else {1461assert(isa<UnsetInit>(DMName) && "Unexpected DefaultMethod field!");1462CI->DefaultMethod = "default" + CI->ClassName + "Operands";1463}14641465++Index;1466}1467}14681469AsmMatcherInfo::AsmMatcherInfo(Record *asmParser, CodeGenTarget &target,1470RecordKeeper &records)1471: Records(records), AsmParser(asmParser), Target(target) {}14721473/// buildOperandMatchInfo - Build the necessary information to handle user1474/// defined operand parsing methods.1475void AsmMatcherInfo::buildOperandMatchInfo() {14761477/// Map containing a mask with all operands indices that can be found for1478/// that class inside a instruction.1479typedef std::map<ClassInfo *, unsigned, deref<std::less<>>> OpClassMaskTy;1480OpClassMaskTy OpClassMask;14811482bool CallCustomParserForAllOperands =1483AsmParser->getValueAsBit("CallCustomParserForAllOperands");1484for (const auto &MI : Matchables) {1485OpClassMask.clear();14861487// Keep track of all operands of this instructions which belong to the1488// same class.1489unsigned NumOptionalOps = 0;1490for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) {1491const MatchableInfo::AsmOperand &Op = MI->AsmOperands[i];1492if (CallCustomParserForAllOperands || !Op.Class->ParserMethod.empty()) {1493unsigned &OperandMask = OpClassMask[Op.Class];1494OperandMask |= maskTrailingOnes<unsigned>(NumOptionalOps + 1)1495<< (i - NumOptionalOps);1496}1497if (Op.Class->IsOptional)1498++NumOptionalOps;1499}15001501// Generate operand match info for each mnemonic/operand class pair.1502for (const auto &OCM : OpClassMask) {1503unsigned OpMask = OCM.second;1504ClassInfo *CI = OCM.first;1505OperandMatchInfo.push_back(1506OperandMatchEntry::create(MI.get(), CI, OpMask));1507}1508}1509}15101511void AsmMatcherInfo::buildInfo() {1512// Build information about all of the AssemblerPredicates.1513const std::vector<std::pair<Record *, SubtargetFeatureInfo>>1514&SubtargetFeaturePairs = SubtargetFeatureInfo::getAll(Records);1515SubtargetFeatures.insert(SubtargetFeaturePairs.begin(),1516SubtargetFeaturePairs.end());1517#ifndef NDEBUG1518for (const auto &Pair : SubtargetFeatures)1519LLVM_DEBUG(Pair.second.dump());1520#endif // NDEBUG15211522bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst");1523bool ReportMultipleNearMisses =1524AsmParser->getValueAsBit("ReportMultipleNearMisses");15251526// Parse the instructions; we need to do this first so that we can gather the1527// singleton register classes.1528SmallPtrSet<Record *, 16> SingletonRegisters;1529unsigned VariantCount = Target.getAsmParserVariantCount();1530for (unsigned VC = 0; VC != VariantCount; ++VC) {1531Record *AsmVariant = Target.getAsmParserVariant(VC);1532StringRef CommentDelimiter =1533AsmVariant->getValueAsString("CommentDelimiter");1534AsmVariantInfo Variant;1535Variant.RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix");1536Variant.TokenizingCharacters =1537AsmVariant->getValueAsString("TokenizingCharacters");1538Variant.SeparatorCharacters =1539AsmVariant->getValueAsString("SeparatorCharacters");1540Variant.BreakCharacters = AsmVariant->getValueAsString("BreakCharacters");1541Variant.Name = AsmVariant->getValueAsString("Name");1542Variant.AsmVariantNo = AsmVariant->getValueAsInt("Variant");15431544for (const CodeGenInstruction *CGI : Target.getInstructionsByEnumValue()) {15451546// If the tblgen -match-prefix option is specified (for tblgen hackers),1547// filter the set of instructions we consider.1548if (!StringRef(CGI->TheDef->getName()).starts_with(MatchPrefix))1549continue;15501551// Ignore "codegen only" instructions.1552if (CGI->TheDef->getValueAsBit("isCodeGenOnly"))1553continue;15541555// Ignore instructions for different instructions1556StringRef V = CGI->TheDef->getValueAsString("AsmVariantName");1557if (!V.empty() && V != Variant.Name)1558continue;15591560auto II = std::make_unique<MatchableInfo>(*CGI);15611562II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst);15631564// Ignore instructions which shouldn't be matched and diagnose invalid1565// instruction definitions with an error.1566if (!II->validate(CommentDelimiter, false))1567continue;15681569Matchables.push_back(std::move(II));1570}15711572// Parse all of the InstAlias definitions and stick them in the list of1573// matchables.1574std::vector<Record *> AllInstAliases =1575Records.getAllDerivedDefinitions("InstAlias");1576for (Record *InstAlias : AllInstAliases) {1577auto Alias = std::make_unique<CodeGenInstAlias>(InstAlias, Target);15781579// If the tblgen -match-prefix option is specified (for tblgen hackers),1580// filter the set of instruction aliases we consider, based on the target1581// instruction.1582if (!StringRef(Alias->ResultInst->TheDef->getName())1583.starts_with(MatchPrefix))1584continue;15851586StringRef V = Alias->TheDef->getValueAsString("AsmVariantName");1587if (!V.empty() && V != Variant.Name)1588continue;15891590auto II = std::make_unique<MatchableInfo>(std::move(Alias));15911592II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst);15931594// Validate the alias definitions.1595II->validate(CommentDelimiter, true);15961597Matchables.push_back(std::move(II));1598}1599}16001601// Build info for the register classes.1602buildRegisterClasses(SingletonRegisters);16031604// Build info for the user defined assembly operand classes.1605buildOperandClasses();16061607// Build the information about matchables, now that we have fully formed1608// classes.1609std::vector<std::unique_ptr<MatchableInfo>> NewMatchables;1610for (auto &II : Matchables) {1611// Parse the tokens after the mnemonic.1612// Note: buildInstructionOperandReference may insert new AsmOperands, so1613// don't precompute the loop bound.1614for (unsigned i = 0; i != II->AsmOperands.size(); ++i) {1615MatchableInfo::AsmOperand &Op = II->AsmOperands[i];1616StringRef Token = Op.Token;16171618// Check for singleton registers.1619if (Record *RegRecord = Op.SingletonReg) {1620Op.Class = RegisterClasses[RegRecord];1621assert(Op.Class && Op.Class->Registers.size() == 1 &&1622"Unexpected class for singleton register");1623continue;1624}16251626// Check for simple tokens.1627if (Token[0] != '$') {1628Op.Class = getTokenClass(Token);1629continue;1630}16311632if (Token.size() > 1 && isdigit(Token[1])) {1633Op.Class = getTokenClass(Token);1634continue;1635}16361637// Otherwise this is an operand reference.1638StringRef OperandName;1639if (Token[1] == '{')1640OperandName = Token.substr(2, Token.size() - 3);1641else1642OperandName = Token.substr(1);16431644if (isa<const CodeGenInstruction *>(II->DefRec))1645buildInstructionOperandReference(II.get(), OperandName, i);1646else1647buildAliasOperandReference(II.get(), OperandName, Op);1648}16491650if (isa<const CodeGenInstruction *>(II->DefRec)) {1651II->buildInstructionResultOperands();1652// If the instruction has a two-operand alias, build up the1653// matchable here. We'll add them in bulk at the end to avoid1654// confusing this loop.1655StringRef Constraint =1656II->TheDef->getValueAsString("TwoOperandAliasConstraint");1657if (Constraint != "") {1658// Start by making a copy of the original matchable.1659auto AliasII = std::make_unique<MatchableInfo>(*II);16601661// Adjust it to be a two-operand alias.1662AliasII->formTwoOperandAlias(Constraint);16631664// Add the alias to the matchables list.1665NewMatchables.push_back(std::move(AliasII));1666}1667} else1668// FIXME: The tied operands checking is not yet integrated with the1669// framework for reporting multiple near misses. To prevent invalid1670// formats from being matched with an alias if a tied-operands check1671// would otherwise have disallowed it, we just disallow such constructs1672// in TableGen completely.1673II->buildAliasResultOperands(!ReportMultipleNearMisses);1674}1675if (!NewMatchables.empty())1676Matchables.insert(Matchables.end(),1677std::make_move_iterator(NewMatchables.begin()),1678std::make_move_iterator(NewMatchables.end()));16791680// Process token alias definitions and set up the associated superclass1681// information.1682std::vector<Record *> AllTokenAliases =1683Records.getAllDerivedDefinitions("TokenAlias");1684for (Record *Rec : AllTokenAliases) {1685ClassInfo *FromClass = getTokenClass(Rec->getValueAsString("FromToken"));1686ClassInfo *ToClass = getTokenClass(Rec->getValueAsString("ToToken"));1687if (FromClass == ToClass)1688PrintFatalError(Rec->getLoc(),1689"error: Destination value identical to source value.");1690FromClass->SuperClasses.push_back(ToClass);1691}16921693// Reorder classes so that classes precede super classes.1694Classes.sort();16951696#ifdef EXPENSIVE_CHECKS1697// Verify that the table is sorted and operator < works transitively.1698for (auto I = Classes.begin(), E = Classes.end(); I != E; ++I) {1699for (auto J = I; J != E; ++J) {1700assert(!(*J < *I));1701assert(I == J || !J->isSubsetOf(*I));1702}1703}1704#endif1705}17061707/// buildInstructionOperandReference - The specified operand is a reference to a1708/// named operand such as $src. Resolve the Class and OperandInfo pointers.1709void AsmMatcherInfo::buildInstructionOperandReference(MatchableInfo *II,1710StringRef OperandName,1711unsigned AsmOpIdx) {1712const CodeGenInstruction &CGI = *cast<const CodeGenInstruction *>(II->DefRec);1713const CGIOperandList &Operands = CGI.Operands;1714MatchableInfo::AsmOperand *Op = &II->AsmOperands[AsmOpIdx];17151716// Map this token to an operand.1717unsigned Idx;1718if (!Operands.hasOperandNamed(OperandName, Idx))1719PrintFatalError(II->TheDef->getLoc(),1720"error: unable to find operand: '" + OperandName + "'");17211722// If the instruction operand has multiple suboperands, but the parser1723// match class for the asm operand is still the default "ImmAsmOperand",1724// then handle each suboperand separately.1725if (Op->SubOpIdx == -1 && Operands[Idx].MINumOperands > 1) {1726Record *Rec = Operands[Idx].Rec;1727assert(Rec->isSubClassOf("Operand") && "Unexpected operand!");1728Record *MatchClass = Rec->getValueAsDef("ParserMatchClass");1729if (MatchClass && MatchClass->getValueAsString("Name") == "Imm") {1730// Insert remaining suboperands after AsmOpIdx in II->AsmOperands.1731StringRef Token = Op->Token; // save this in case Op gets moved1732for (unsigned SI = 1, SE = Operands[Idx].MINumOperands; SI != SE; ++SI) {1733MatchableInfo::AsmOperand NewAsmOp(/*IsIsolatedToken=*/true, Token);1734NewAsmOp.SubOpIdx = SI;1735II->AsmOperands.insert(II->AsmOperands.begin() + AsmOpIdx + SI,1736NewAsmOp);1737}1738// Replace Op with first suboperand.1739Op = &II->AsmOperands[AsmOpIdx]; // update the pointer in case it moved1740Op->SubOpIdx = 0;1741}1742}17431744// Set up the operand class.1745Op->Class = getOperandClass(Operands[Idx], Op->SubOpIdx);1746Op->OrigSrcOpName = OperandName;17471748// If the named operand is tied, canonicalize it to the untied operand.1749// For example, something like:1750// (outs GPR:$dst), (ins GPR:$src)1751// with an asmstring of1752// "inc $src"1753// we want to canonicalize to:1754// "inc $dst"1755// so that we know how to provide the $dst operand when filling in the result.1756int OITied = -1;1757if (Operands[Idx].MINumOperands == 1)1758OITied = Operands[Idx].getTiedRegister();1759if (OITied != -1) {1760// The tied operand index is an MIOperand index, find the operand that1761// contains it.1762std::pair<unsigned, unsigned> Idx = Operands.getSubOperandNumber(OITied);1763OperandName = Operands[Idx.first].Name;1764Op->SubOpIdx = Idx.second;1765}17661767Op->SrcOpName = OperandName;1768}17691770/// buildAliasOperandReference - When parsing an operand reference out of the1771/// matching string (e.g. "movsx $src, $dst"), determine what the class of the1772/// operand reference is by looking it up in the result pattern definition.1773void AsmMatcherInfo::buildAliasOperandReference(MatchableInfo *II,1774StringRef OperandName,1775MatchableInfo::AsmOperand &Op) {1776const CodeGenInstAlias &CGA = *cast<const CodeGenInstAlias *>(II->DefRec);17771778// Set up the operand class.1779for (unsigned i = 0, e = CGA.ResultOperands.size(); i != e; ++i)1780if (CGA.ResultOperands[i].isRecord() &&1781CGA.ResultOperands[i].getName() == OperandName) {1782// It's safe to go with the first one we find, because CodeGenInstAlias1783// validates that all operands with the same name have the same record.1784Op.SubOpIdx = CGA.ResultInstOperandIndex[i].second;1785// Use the match class from the Alias definition, not the1786// destination instruction, as we may have an immediate that's1787// being munged by the match class.1788Op.Class =1789getOperandClass(CGA.ResultOperands[i].getRecord(), Op.SubOpIdx);1790Op.SrcOpName = OperandName;1791Op.OrigSrcOpName = OperandName;1792return;1793}17941795PrintFatalError(II->TheDef->getLoc(),1796"error: unable to find operand: '" + OperandName + "'");1797}17981799void MatchableInfo::buildInstructionResultOperands() {1800const CodeGenInstruction *ResultInst = getResultInst();18011802// Loop over all operands of the result instruction, determining how to1803// populate them.1804for (const CGIOperandList::OperandInfo &OpInfo : ResultInst->Operands) {1805// If this is a tied operand, just copy from the previously handled operand.1806int TiedOp = -1;1807if (OpInfo.MINumOperands == 1)1808TiedOp = OpInfo.getTiedRegister();1809if (TiedOp != -1) {1810int TiedSrcOperand = findAsmOperandOriginallyNamed(OpInfo.Name);1811if (TiedSrcOperand != -1 &&1812ResOperands[TiedOp].Kind == ResOperand::RenderAsmOperand)1813ResOperands.push_back(ResOperand::getTiedOp(1814TiedOp, ResOperands[TiedOp].AsmOperandNum, TiedSrcOperand));1815else1816ResOperands.push_back(ResOperand::getTiedOp(TiedOp, 0, 0));1817continue;1818}18191820int SrcOperand = findAsmOperandNamed(OpInfo.Name);1821if (OpInfo.Name.empty() || SrcOperand == -1) {1822// This may happen for operands that are tied to a suboperand of a1823// complex operand. Simply use a dummy value here; nobody should1824// use this operand slot.1825// FIXME: The long term goal is for the MCOperand list to not contain1826// tied operands at all.1827ResOperands.push_back(ResOperand::getImmOp(0));1828continue;1829}18301831// Check if the one AsmOperand populates the entire operand.1832unsigned NumOperands = OpInfo.MINumOperands;1833if (AsmOperands[SrcOperand].SubOpIdx == -1) {1834ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, NumOperands));1835continue;1836}18371838// Add a separate ResOperand for each suboperand.1839for (unsigned AI = 0; AI < NumOperands; ++AI) {1840assert(AsmOperands[SrcOperand + AI].SubOpIdx == (int)AI &&1841AsmOperands[SrcOperand + AI].SrcOpName == OpInfo.Name &&1842"unexpected AsmOperands for suboperands");1843ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand + AI, 1));1844}1845}1846}18471848void MatchableInfo::buildAliasResultOperands(bool AliasConstraintsAreChecked) {1849const CodeGenInstAlias &CGA = *cast<const CodeGenInstAlias *>(DefRec);1850const CodeGenInstruction *ResultInst = getResultInst();18511852// Map of: $reg -> #lastref1853// where $reg is the name of the operand in the asm string1854// where #lastref is the last processed index where $reg was referenced in1855// the asm string.1856SmallDenseMap<StringRef, int> OperandRefs;18571858// Loop over all operands of the result instruction, determining how to1859// populate them.1860unsigned AliasOpNo = 0;1861unsigned LastOpNo = CGA.ResultInstOperandIndex.size();1862for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {1863const CGIOperandList::OperandInfo *OpInfo = &ResultInst->Operands[i];18641865// If this is a tied operand, just copy from the previously handled operand.1866int TiedOp = -1;1867if (OpInfo->MINumOperands == 1)1868TiedOp = OpInfo->getTiedRegister();1869if (TiedOp != -1) {1870unsigned SrcOp1 = 0;1871unsigned SrcOp2 = 0;18721873// If an operand has been specified twice in the asm string,1874// add the two source operand's indices to the TiedOp so that1875// at runtime the 'tied' constraint is checked.1876if (ResOperands[TiedOp].Kind == ResOperand::RenderAsmOperand) {1877SrcOp1 = ResOperands[TiedOp].AsmOperandNum;18781879// Find the next operand (similarly named operand) in the string.1880StringRef Name = AsmOperands[SrcOp1].SrcOpName;1881auto Insert = OperandRefs.try_emplace(Name, SrcOp1);1882SrcOp2 = findAsmOperandNamed(Name, Insert.first->second);18831884// Not updating the record in OperandRefs will cause TableGen1885// to fail with an error at the end of this function.1886if (AliasConstraintsAreChecked)1887Insert.first->second = SrcOp2;18881889// In case it only has one reference in the asm string,1890// it doesn't need to be checked for tied constraints.1891SrcOp2 = (SrcOp2 == (unsigned)-1) ? SrcOp1 : SrcOp2;1892}18931894// If the alias operand is of a different operand class, we only want1895// to benefit from the tied-operands check and just match the operand1896// as a normal, but not copy the original (TiedOp) to the result1897// instruction. We do this by passing -1 as the tied operand to copy.1898if (ResultInst->Operands[i].Rec->getName() !=1899ResultInst->Operands[TiedOp].Rec->getName()) {1900SrcOp1 = ResOperands[TiedOp].AsmOperandNum;1901int SubIdx = CGA.ResultInstOperandIndex[AliasOpNo].second;1902StringRef Name = CGA.ResultOperands[AliasOpNo].getName();1903SrcOp2 = findAsmOperand(Name, SubIdx);1904ResOperands.push_back(1905ResOperand::getTiedOp((unsigned)-1, SrcOp1, SrcOp2));1906} else {1907ResOperands.push_back(ResOperand::getTiedOp(TiedOp, SrcOp1, SrcOp2));1908continue;1909}1910}19111912// Handle all the suboperands for this operand.1913const std::string &OpName = OpInfo->Name;1914for (; AliasOpNo < LastOpNo &&1915CGA.ResultInstOperandIndex[AliasOpNo].first == i;1916++AliasOpNo) {1917int SubIdx = CGA.ResultInstOperandIndex[AliasOpNo].second;19181919// Find out what operand from the asmparser that this MCInst operand1920// comes from.1921switch (CGA.ResultOperands[AliasOpNo].Kind) {1922case CodeGenInstAlias::ResultOperand::K_Record: {1923StringRef Name = CGA.ResultOperands[AliasOpNo].getName();1924int SrcOperand = findAsmOperand(Name, SubIdx);1925if (SrcOperand == -1)1926PrintFatalError(TheDef->getLoc(),1927"Instruction '" + TheDef->getName() +1928"' has operand '" + OpName +1929"' that doesn't appear in asm string!");19301931// Add it to the operand references. If it is added a second time, the1932// record won't be updated and it will fail later on.1933OperandRefs.try_emplace(Name, SrcOperand);19341935unsigned NumOperands = (SubIdx == -1 ? OpInfo->MINumOperands : 1);1936ResOperands.push_back(1937ResOperand::getRenderedOp(SrcOperand, NumOperands));1938break;1939}1940case CodeGenInstAlias::ResultOperand::K_Imm: {1941int64_t ImmVal = CGA.ResultOperands[AliasOpNo].getImm();1942ResOperands.push_back(ResOperand::getImmOp(ImmVal));1943break;1944}1945case CodeGenInstAlias::ResultOperand::K_Reg: {1946Record *Reg = CGA.ResultOperands[AliasOpNo].getRegister();1947ResOperands.push_back(ResOperand::getRegOp(Reg));1948break;1949}1950}1951}1952}19531954// Check that operands are not repeated more times than is supported.1955for (auto &T : OperandRefs) {1956if (T.second != -1 && findAsmOperandNamed(T.first, T.second) != -1)1957PrintFatalError(TheDef->getLoc(),1958"Operand '" + T.first + "' can never be matched");1959}1960}19611962static unsigned1963getConverterOperandID(const std::string &Name,1964SmallSetVector<CachedHashString, 16> &Table,1965bool &IsNew) {1966IsNew = Table.insert(CachedHashString(Name));19671968unsigned ID = IsNew ? Table.size() - 1 : find(Table, Name) - Table.begin();19691970assert(ID < Table.size());19711972return ID;1973}19741975static unsigned1976emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,1977std::vector<std::unique_ptr<MatchableInfo>> &Infos,1978bool HasMnemonicFirst, bool HasOptionalOperands,1979raw_ostream &OS) {1980SmallSetVector<CachedHashString, 16> OperandConversionKinds;1981SmallSetVector<CachedHashString, 16> InstructionConversionKinds;1982std::vector<std::vector<uint8_t>> ConversionTable;1983size_t MaxRowLength = 2; // minimum is custom converter plus terminator.19841985// TargetOperandClass - This is the target's operand class, like X86Operand.1986std::string TargetOperandClass = Target.getName().str() + "Operand";19871988// Write the convert function to a separate stream, so we can drop it after1989// the enum. We'll build up the conversion handlers for the individual1990// operand types opportunistically as we encounter them.1991std::string ConvertFnBody;1992raw_string_ostream CvtOS(ConvertFnBody);1993// Start the unified conversion function.1994if (HasOptionalOperands) {1995CvtOS << "void " << Target.getName() << ClassName << "::\n"1996<< "convertToMCInst(unsigned Kind, MCInst &Inst, "1997<< "unsigned Opcode,\n"1998<< " const OperandVector &Operands,\n"1999<< " const SmallBitVector &OptionalOperandsMask,\n"2000<< " ArrayRef<unsigned> DefaultsOffset) {\n";2001} else {2002CvtOS << "void " << Target.getName() << ClassName << "::\n"2003<< "convertToMCInst(unsigned Kind, MCInst &Inst, "2004<< "unsigned Opcode,\n"2005<< " const OperandVector &Operands) {\n";2006}2007CvtOS << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n";2008CvtOS << " const uint8_t *Converter = ConversionTable[Kind];\n";2009CvtOS << " Inst.setOpcode(Opcode);\n";2010CvtOS << " for (const uint8_t *p = Converter; *p; p += 2) {\n";2011if (HasOptionalOperands) {2012// When optional operands are involved, formal and actual operand indices2013// may differ. Map the former to the latter by subtracting the number of2014// absent optional operands.2015// FIXME: This is not an operand index in the CVT_Tied case2016CvtOS << " unsigned OpIdx = *(p + 1) - DefaultsOffset[*(p + 1)];\n";2017} else {2018CvtOS << " unsigned OpIdx = *(p + 1);\n";2019}2020CvtOS << " switch (*p) {\n";2021CvtOS << " default: llvm_unreachable(\"invalid conversion entry!\");\n";2022CvtOS << " case CVT_Reg:\n";2023CvtOS << " static_cast<" << TargetOperandClass2024<< " &>(*Operands[OpIdx]).addRegOperands(Inst, 1);\n";2025CvtOS << " break;\n";2026CvtOS << " case CVT_Tied: {\n";2027CvtOS << " assert(*(p + 1) < (size_t)(std::end(TiedAsmOperandTable) -\n";2028CvtOS2029<< " std::begin(TiedAsmOperandTable)) &&\n";2030CvtOS << " \"Tied operand not found\");\n";2031CvtOS << " unsigned TiedResOpnd = TiedAsmOperandTable[*(p + 1)][0];\n";2032CvtOS << " if (TiedResOpnd != (uint8_t)-1)\n";2033CvtOS << " Inst.addOperand(Inst.getOperand(TiedResOpnd));\n";2034CvtOS << " break;\n";2035CvtOS << " }\n";20362037std::string OperandFnBody;2038raw_string_ostream OpOS(OperandFnBody);2039// Start the operand number lookup function.2040OpOS << "void " << Target.getName() << ClassName << "::\n"2041<< "convertToMapAndConstraints(unsigned Kind,\n";2042OpOS.indent(27);2043OpOS << "const OperandVector &Operands) {\n"2044<< " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n"2045<< " unsigned NumMCOperands = 0;\n"2046<< " const uint8_t *Converter = ConversionTable[Kind];\n"2047<< " for (const uint8_t *p = Converter; *p; p += 2) {\n"2048<< " switch (*p) {\n"2049<< " default: llvm_unreachable(\"invalid conversion entry!\");\n"2050<< " case CVT_Reg:\n"2051<< " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n"2052<< " Operands[*(p + 1)]->setConstraint(\"r\");\n"2053<< " ++NumMCOperands;\n"2054<< " break;\n"2055<< " case CVT_Tied:\n"2056<< " ++NumMCOperands;\n"2057<< " break;\n";20582059// Pre-populate the operand conversion kinds with the standard always2060// available entries.2061OperandConversionKinds.insert(CachedHashString("CVT_Done"));2062OperandConversionKinds.insert(CachedHashString("CVT_Reg"));2063OperandConversionKinds.insert(CachedHashString("CVT_Tied"));2064enum { CVT_Done, CVT_Reg, CVT_Tied };20652066// Map of e.g. <0, 2, 3> -> "Tie_0_2_3" enum label.2067std::map<std::tuple<uint8_t, uint8_t, uint8_t>, std::string>2068TiedOperandsEnumMap;20692070for (auto &II : Infos) {2071// Check if we have a custom match function.2072StringRef AsmMatchConverter =2073II->getResultInst()->TheDef->getValueAsString("AsmMatchConverter");2074if (!AsmMatchConverter.empty() && II->UseInstAsmMatchConverter) {2075std::string Signature = ("ConvertCustom_" + AsmMatchConverter).str();2076II->ConversionFnKind = Signature;20772078// Check if we have already generated this signature.2079if (!InstructionConversionKinds.insert(CachedHashString(Signature)))2080continue;20812082// Remember this converter for the kind enum.2083unsigned KindID = OperandConversionKinds.size();2084OperandConversionKinds.insert(2085CachedHashString("CVT_" + getEnumNameForToken(AsmMatchConverter)));20862087// Add the converter row for this instruction.2088ConversionTable.emplace_back();2089ConversionTable.back().push_back(KindID);2090ConversionTable.back().push_back(CVT_Done);20912092// Add the handler to the conversion driver function.2093CvtOS << " case CVT_" << getEnumNameForToken(AsmMatchConverter)2094<< ":\n"2095<< " " << AsmMatchConverter << "(Inst, Operands);\n"2096<< " break;\n";20972098// FIXME: Handle the operand number lookup for custom match functions.2099continue;2100}21012102// Build the conversion function signature.2103std::string Signature = "Convert";21042105std::vector<uint8_t> ConversionRow;21062107// Compute the convert enum and the case body.2108MaxRowLength = std::max(MaxRowLength, II->ResOperands.size() * 2 + 1);21092110for (unsigned i = 0, e = II->ResOperands.size(); i != e; ++i) {2111const MatchableInfo::ResOperand &OpInfo = II->ResOperands[i];21122113// Generate code to populate each result operand.2114switch (OpInfo.Kind) {2115case MatchableInfo::ResOperand::RenderAsmOperand: {2116// This comes from something we parsed.2117const MatchableInfo::AsmOperand &Op =2118II->AsmOperands[OpInfo.AsmOperandNum];21192120// Registers are always converted the same, don't duplicate the2121// conversion function based on them.2122Signature += "__";2123std::string Class;2124Class = Op.Class->isRegisterClass() ? "Reg" : Op.Class->ClassName;2125Signature += Class;2126Signature += utostr(OpInfo.MINumOperands);2127Signature += "_" + itostr(OpInfo.AsmOperandNum);21282129// Add the conversion kind, if necessary, and get the associated ID2130// the index of its entry in the vector).2131std::string Name =2132"CVT_" +2133(Op.Class->isRegisterClass() ? "Reg" : Op.Class->RenderMethod);2134if (Op.Class->IsOptional) {2135// For optional operands we must also care about DefaultMethod2136assert(HasOptionalOperands);2137Name += "_" + Op.Class->DefaultMethod;2138}2139Name = getEnumNameForToken(Name);21402141bool IsNewConverter = false;2142unsigned ID =2143getConverterOperandID(Name, OperandConversionKinds, IsNewConverter);21442145// Add the operand entry to the instruction kind conversion row.2146ConversionRow.push_back(ID);2147ConversionRow.push_back(OpInfo.AsmOperandNum + HasMnemonicFirst);21482149if (!IsNewConverter)2150break;21512152// This is a new operand kind. Add a handler for it to the2153// converter driver.2154CvtOS << " case " << Name << ":\n";2155if (Op.Class->IsOptional) {2156// If optional operand is not present in actual instruction then we2157// should call its DefaultMethod before RenderMethod2158assert(HasOptionalOperands);2159CvtOS << " if (OptionalOperandsMask[*(p + 1) - 1]) {\n"2160<< " " << Op.Class->DefaultMethod << "()"2161<< "->" << Op.Class->RenderMethod << "(Inst, "2162<< OpInfo.MINumOperands << ");\n"2163<< " } else {\n"2164<< " static_cast<" << TargetOperandClass2165<< " &>(*Operands[OpIdx])." << Op.Class->RenderMethod2166<< "(Inst, " << OpInfo.MINumOperands << ");\n"2167<< " }\n";2168} else {2169CvtOS << " static_cast<" << TargetOperandClass2170<< " &>(*Operands[OpIdx])." << Op.Class->RenderMethod2171<< "(Inst, " << OpInfo.MINumOperands << ");\n";2172}2173CvtOS << " break;\n";21742175// Add a handler for the operand number lookup.2176OpOS << " case " << Name << ":\n"2177<< " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n";21782179if (Op.Class->isRegisterClass())2180OpOS << " Operands[*(p + 1)]->setConstraint(\"r\");\n";2181else2182OpOS << " Operands[*(p + 1)]->setConstraint(\"m\");\n";2183OpOS << " NumMCOperands += " << OpInfo.MINumOperands << ";\n"2184<< " break;\n";2185break;2186}2187case MatchableInfo::ResOperand::TiedOperand: {2188// If this operand is tied to a previous one, just copy the MCInst2189// operand from the earlier one.We can only tie single MCOperand values.2190assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand");2191uint8_t TiedOp = OpInfo.TiedOperands.ResOpnd;2192uint8_t SrcOp1 = OpInfo.TiedOperands.SrcOpnd1Idx + HasMnemonicFirst;2193uint8_t SrcOp2 = OpInfo.TiedOperands.SrcOpnd2Idx + HasMnemonicFirst;2194assert((i > TiedOp || TiedOp == (uint8_t)-1) &&2195"Tied operand precedes its target!");2196auto TiedTupleName = std::string("Tie") + utostr(TiedOp) + '_' +2197utostr(SrcOp1) + '_' + utostr(SrcOp2);2198Signature += "__" + TiedTupleName;2199ConversionRow.push_back(CVT_Tied);2200ConversionRow.push_back(TiedOp);2201ConversionRow.push_back(SrcOp1);2202ConversionRow.push_back(SrcOp2);22032204// Also create an 'enum' for this combination of tied operands.2205auto Key = std::tuple(TiedOp, SrcOp1, SrcOp2);2206TiedOperandsEnumMap.emplace(Key, TiedTupleName);2207break;2208}2209case MatchableInfo::ResOperand::ImmOperand: {2210int64_t Val = OpInfo.ImmVal;2211std::string Ty = "imm_" + itostr(Val);2212Ty = getEnumNameForToken(Ty);2213Signature += "__" + Ty;22142215std::string Name = "CVT_" + Ty;2216bool IsNewConverter = false;2217unsigned ID =2218getConverterOperandID(Name, OperandConversionKinds, IsNewConverter);2219// Add the operand entry to the instruction kind conversion row.2220ConversionRow.push_back(ID);2221ConversionRow.push_back(0);22222223if (!IsNewConverter)2224break;22252226CvtOS << " case " << Name << ":\n"2227<< " Inst.addOperand(MCOperand::createImm(" << Val << "));\n"2228<< " break;\n";22292230OpOS << " case " << Name << ":\n"2231<< " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n"2232<< " Operands[*(p + 1)]->setConstraint(\"\");\n"2233<< " ++NumMCOperands;\n"2234<< " break;\n";2235break;2236}2237case MatchableInfo::ResOperand::RegOperand: {2238std::string Reg, Name;2239if (!OpInfo.Register) {2240Name = "reg0";2241Reg = "0";2242} else {2243Reg = getQualifiedName(OpInfo.Register);2244Name = "reg" + OpInfo.Register->getName().str();2245}2246Signature += "__" + Name;2247Name = "CVT_" + Name;2248bool IsNewConverter = false;2249unsigned ID =2250getConverterOperandID(Name, OperandConversionKinds, IsNewConverter);2251// Add the operand entry to the instruction kind conversion row.2252ConversionRow.push_back(ID);2253ConversionRow.push_back(0);22542255if (!IsNewConverter)2256break;2257CvtOS << " case " << Name << ":\n"2258<< " Inst.addOperand(MCOperand::createReg(" << Reg << "));\n"2259<< " break;\n";22602261OpOS << " case " << Name << ":\n"2262<< " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n"2263<< " Operands[*(p + 1)]->setConstraint(\"m\");\n"2264<< " ++NumMCOperands;\n"2265<< " break;\n";2266}2267}2268}22692270// If there were no operands, add to the signature to that effect2271if (Signature == "Convert")2272Signature += "_NoOperands";22732274II->ConversionFnKind = Signature;22752276// Save the signature. If we already have it, don't add a new row2277// to the table.2278if (!InstructionConversionKinds.insert(CachedHashString(Signature)))2279continue;22802281// Add the row to the table.2282ConversionTable.push_back(std::move(ConversionRow));2283}22842285// Finish up the converter driver function.2286CvtOS << " }\n }\n}\n\n";22872288// Finish up the operand number lookup function.2289OpOS << " }\n }\n}\n\n";22902291// Output a static table for tied operands.2292if (TiedOperandsEnumMap.size()) {2293// The number of tied operand combinations will be small in practice,2294// but just add the assert to be sure.2295assert(TiedOperandsEnumMap.size() <= 254 &&2296"Too many tied-operand combinations to reference with "2297"an 8bit offset from the conversion table, where index "2298"'255' is reserved as operand not to be copied.");22992300OS << "enum {\n";2301for (auto &KV : TiedOperandsEnumMap) {2302OS << " " << KV.second << ",\n";2303}2304OS << "};\n\n";23052306OS << "static const uint8_t TiedAsmOperandTable[][3] = {\n";2307for (auto &KV : TiedOperandsEnumMap) {2308OS << " /* " << KV.second << " */ { " << utostr(std::get<0>(KV.first))2309<< ", " << utostr(std::get<1>(KV.first)) << ", "2310<< utostr(std::get<2>(KV.first)) << " },\n";2311}2312OS << "};\n\n";2313} else2314OS << "static const uint8_t TiedAsmOperandTable[][3] = "2315"{ /* empty */ {0, 0, 0} };\n\n";23162317OS << "namespace {\n";23182319// Output the operand conversion kind enum.2320OS << "enum OperatorConversionKind {\n";2321for (const auto &Converter : OperandConversionKinds)2322OS << " " << Converter << ",\n";2323OS << " CVT_NUM_CONVERTERS\n";2324OS << "};\n\n";23252326// Output the instruction conversion kind enum.2327OS << "enum InstructionConversionKind {\n";2328for (const auto &Signature : InstructionConversionKinds)2329OS << " " << Signature << ",\n";2330OS << " CVT_NUM_SIGNATURES\n";2331OS << "};\n\n";23322333OS << "} // end anonymous namespace\n\n";23342335// Output the conversion table.2336OS << "static const uint8_t ConversionTable[CVT_NUM_SIGNATURES]["2337<< MaxRowLength << "] = {\n";23382339for (unsigned Row = 0, ERow = ConversionTable.size(); Row != ERow; ++Row) {2340assert(ConversionTable[Row].size() % 2 == 0 && "bad conversion row!");2341OS << " // " << InstructionConversionKinds[Row] << "\n";2342OS << " { ";2343for (unsigned i = 0, e = ConversionTable[Row].size(); i != e; i += 2) {2344OS << OperandConversionKinds[ConversionTable[Row][i]] << ", ";2345if (OperandConversionKinds[ConversionTable[Row][i]] !=2346CachedHashString("CVT_Tied")) {2347OS << (unsigned)(ConversionTable[Row][i + 1]) << ", ";2348continue;2349}23502351// For a tied operand, emit a reference to the TiedAsmOperandTable2352// that contains the operand to copy, and the parsed operands to2353// check for their tied constraints.2354auto Key = std::tuple((uint8_t)ConversionTable[Row][i + 1],2355(uint8_t)ConversionTable[Row][i + 2],2356(uint8_t)ConversionTable[Row][i + 3]);2357auto TiedOpndEnum = TiedOperandsEnumMap.find(Key);2358assert(TiedOpndEnum != TiedOperandsEnumMap.end() &&2359"No record for tied operand pair");2360OS << TiedOpndEnum->second << ", ";2361i += 2;2362}2363OS << "CVT_Done },\n";2364}23652366OS << "};\n\n";23672368// Spit out the conversion driver function.2369OS << ConvertFnBody;23702371// Spit out the operand number lookup function.2372OS << OperandFnBody;23732374return ConversionTable.size();2375}23762377/// emitMatchClassEnumeration - Emit the enumeration for match class kinds.2378static void emitMatchClassEnumeration(CodeGenTarget &Target,2379std::forward_list<ClassInfo> &Infos,2380raw_ostream &OS) {2381OS << "namespace {\n\n";23822383OS << "/// MatchClassKind - The kinds of classes which participate in\n"2384<< "/// instruction matching.\n";2385OS << "enum MatchClassKind {\n";2386OS << " InvalidMatchClass = 0,\n";2387OS << " OptionalMatchClass = 1,\n";2388ClassInfo::ClassInfoKind LastKind = ClassInfo::Token;2389StringRef LastName = "OptionalMatchClass";2390for (const auto &CI : Infos) {2391if (LastKind == ClassInfo::Token && CI.Kind != ClassInfo::Token) {2392OS << " MCK_LAST_TOKEN = " << LastName << ",\n";2393} else if (LastKind < ClassInfo::UserClass0 &&2394CI.Kind >= ClassInfo::UserClass0) {2395OS << " MCK_LAST_REGISTER = " << LastName << ",\n";2396}2397LastKind = (ClassInfo::ClassInfoKind)CI.Kind;2398LastName = CI.Name;23992400OS << " " << CI.Name << ", // ";2401if (CI.Kind == ClassInfo::Token) {2402OS << "'" << CI.ValueName << "'\n";2403} else if (CI.isRegisterClass()) {2404if (!CI.ValueName.empty())2405OS << "register class '" << CI.ValueName << "'\n";2406else2407OS << "derived register class\n";2408} else {2409OS << "user defined class '" << CI.ValueName << "'\n";2410}2411}2412OS << " NumMatchClassKinds\n";2413OS << "};\n\n";24142415OS << "} // end anonymous namespace\n\n";2416}24172418/// emitMatchClassDiagStrings - Emit a function to get the diagnostic text to be2419/// used when an assembly operand does not match the expected operand class.2420static void emitOperandMatchErrorDiagStrings(AsmMatcherInfo &Info,2421raw_ostream &OS) {2422// If the target does not use DiagnosticString for any operands, don't emit2423// an unused function.2424if (llvm::all_of(Info.Classes, [](const ClassInfo &CI) {2425return CI.DiagnosticString.empty();2426}))2427return;24282429OS << "static const char *getMatchKindDiag(" << Info.Target.getName()2430<< "AsmParser::" << Info.Target.getName()2431<< "MatchResultTy MatchResult) {\n";2432OS << " switch (MatchResult) {\n";24332434for (const auto &CI : Info.Classes) {2435if (!CI.DiagnosticString.empty()) {2436assert(!CI.DiagnosticType.empty() &&2437"DiagnosticString set without DiagnosticType");2438OS << " case " << Info.Target.getName() << "AsmParser::Match_"2439<< CI.DiagnosticType << ":\n";2440OS << " return \"" << CI.DiagnosticString << "\";\n";2441}2442}24432444OS << " default:\n";2445OS << " return nullptr;\n";24462447OS << " }\n";2448OS << "}\n\n";2449}24502451static void emitRegisterMatchErrorFunc(AsmMatcherInfo &Info, raw_ostream &OS) {2452OS << "static unsigned getDiagKindFromRegisterClass(MatchClassKind "2453"RegisterClass) {\n";2454if (none_of(Info.Classes, [](const ClassInfo &CI) {2455return CI.isRegisterClass() && !CI.DiagnosticType.empty();2456})) {2457OS << " return MCTargetAsmParser::Match_InvalidOperand;\n";2458} else {2459OS << " switch (RegisterClass) {\n";2460for (const auto &CI : Info.Classes) {2461if (CI.isRegisterClass() && !CI.DiagnosticType.empty()) {2462OS << " case " << CI.Name << ":\n";2463OS << " return " << Info.Target.getName() << "AsmParser::Match_"2464<< CI.DiagnosticType << ";\n";2465}2466}24672468OS << " default:\n";2469OS << " return MCTargetAsmParser::Match_InvalidOperand;\n";24702471OS << " }\n";2472}2473OS << "}\n\n";2474}24752476/// emitValidateOperandClass - Emit the function to validate an operand class.2477static void emitValidateOperandClass(AsmMatcherInfo &Info, raw_ostream &OS) {2478OS << "static unsigned validateOperandClass(MCParsedAsmOperand &GOp, "2479<< "MatchClassKind Kind) {\n";2480OS << " " << Info.Target.getName() << "Operand &Operand = ("2481<< Info.Target.getName() << "Operand &)GOp;\n";24822483// The InvalidMatchClass is not to match any operand.2484OS << " if (Kind == InvalidMatchClass)\n";2485OS << " return MCTargetAsmParser::Match_InvalidOperand;\n\n";24862487// Check for Token operands first.2488// FIXME: Use a more specific diagnostic type.2489OS << " if (Operand.isToken() && Kind <= MCK_LAST_TOKEN)\n";2490OS << " return isSubclass(matchTokenString(Operand.getToken()), Kind) ?\n"2491<< " MCTargetAsmParser::Match_Success :\n"2492<< " MCTargetAsmParser::Match_InvalidOperand;\n\n";24932494// Check the user classes. We don't care what order since we're only2495// actually matching against one of them.2496OS << " switch (Kind) {\n"2497" default: break;\n";2498for (const auto &CI : Info.Classes) {2499if (!CI.isUserClass())2500continue;25012502OS << " // '" << CI.ClassName << "' class\n";2503OS << " case " << CI.Name << ": {\n";2504OS << " DiagnosticPredicate DP(Operand." << CI.PredicateMethod2505<< "());\n";2506OS << " if (DP.isMatch())\n";2507OS << " return MCTargetAsmParser::Match_Success;\n";2508if (!CI.DiagnosticType.empty()) {2509OS << " if (DP.isNearMatch())\n";2510OS << " return " << Info.Target.getName() << "AsmParser::Match_"2511<< CI.DiagnosticType << ";\n";2512OS << " break;\n";2513} else2514OS << " break;\n";2515OS << " }\n";2516}2517OS << " } // end switch (Kind)\n\n";25182519// Check for register operands, including sub-classes.2520OS << " if (Operand.isReg()) {\n";2521OS << " MatchClassKind OpKind;\n";2522OS << " switch (Operand.getReg().id()) {\n";2523OS << " default: OpKind = InvalidMatchClass; break;\n";2524for (const auto &RC : Info.RegisterClasses)2525OS << " case " << RC.first->getValueAsString("Namespace")2526<< "::" << RC.first->getName() << ": OpKind = " << RC.second->Name2527<< "; break;\n";2528OS << " }\n";2529OS << " return isSubclass(OpKind, Kind) ? "2530<< "(unsigned)MCTargetAsmParser::Match_Success :\n "2531<< " getDiagKindFromRegisterClass(Kind);\n }\n\n";25322533// Expected operand is a register, but actual is not.2534OS << " if (Kind > MCK_LAST_TOKEN && Kind <= MCK_LAST_REGISTER)\n";2535OS << " return getDiagKindFromRegisterClass(Kind);\n\n";25362537// Generic fallthrough match failure case for operands that don't have2538// specialized diagnostic types.2539OS << " return MCTargetAsmParser::Match_InvalidOperand;\n";2540OS << "}\n\n";2541}25422543/// emitIsSubclass - Emit the subclass predicate function.2544static void emitIsSubclass(CodeGenTarget &Target,2545std::forward_list<ClassInfo> &Infos,2546raw_ostream &OS) {2547OS << "/// isSubclass - Compute whether \\p A is a subclass of \\p B.\n";2548OS << "static bool isSubclass(MatchClassKind A, MatchClassKind B) {\n";2549OS << " if (A == B)\n";2550OS << " return true;\n\n";25512552bool EmittedSwitch = false;2553for (const auto &A : Infos) {2554std::vector<StringRef> SuperClasses;2555if (A.IsOptional)2556SuperClasses.push_back("OptionalMatchClass");2557for (const auto &B : Infos) {2558if (&A != &B && A.isSubsetOf(B))2559SuperClasses.push_back(B.Name);2560}25612562if (SuperClasses.empty())2563continue;25642565// If this is the first SuperClass, emit the switch header.2566if (!EmittedSwitch) {2567OS << " switch (A) {\n";2568OS << " default:\n";2569OS << " return false;\n";2570EmittedSwitch = true;2571}25722573OS << "\n case " << A.Name << ":\n";25742575if (SuperClasses.size() == 1) {2576OS << " return B == " << SuperClasses.back() << ";\n";2577continue;2578}25792580if (!SuperClasses.empty()) {2581OS << " switch (B) {\n";2582OS << " default: return false;\n";2583for (StringRef SC : SuperClasses)2584OS << " case " << SC << ": return true;\n";2585OS << " }\n";2586} else {2587// No case statement to emit2588OS << " return false;\n";2589}2590}25912592// If there were case statements emitted into the string stream write the2593// default.2594if (EmittedSwitch)2595OS << " }\n";2596else2597OS << " return false;\n";25982599OS << "}\n\n";2600}26012602/// emitMatchTokenString - Emit the function to match a token string to the2603/// appropriate match class value.2604static void emitMatchTokenString(CodeGenTarget &Target,2605std::forward_list<ClassInfo> &Infos,2606raw_ostream &OS) {2607// Construct the match list.2608std::vector<StringMatcher::StringPair> Matches;2609for (const auto &CI : Infos) {2610if (CI.Kind == ClassInfo::Token)2611Matches.emplace_back(CI.ValueName, "return " + CI.Name + ";");2612}26132614OS << "static MatchClassKind matchTokenString(StringRef Name) {\n";26152616StringMatcher("Name", Matches, OS).Emit();26172618OS << " return InvalidMatchClass;\n";2619OS << "}\n\n";2620}26212622/// emitMatchRegisterName - Emit the function to match a string to the target2623/// specific register enum.2624static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser,2625raw_ostream &OS) {2626// Construct the match list.2627std::vector<StringMatcher::StringPair> Matches;2628const auto &Regs = Target.getRegBank().getRegisters();2629std::string Namespace =2630Regs.front().TheDef->getValueAsString("Namespace").str();2631for (const CodeGenRegister &Reg : Regs) {2632StringRef AsmName = Reg.TheDef->getValueAsString("AsmName");2633if (AsmName.empty())2634continue;26352636Matches.emplace_back(AsmName.str(), "return " + Namespace +2637"::" + Reg.getName().str() + ';');2638}26392640OS << "static MCRegister MatchRegisterName(StringRef Name) {\n";26412642bool IgnoreDuplicates =2643AsmParser->getValueAsBit("AllowDuplicateRegisterNames");2644StringMatcher("Name", Matches, OS).Emit(0, IgnoreDuplicates);26452646OS << " return " << Namespace << "::NoRegister;\n";2647OS << "}\n\n";2648}26492650/// Emit the function to match a string to the target2651/// specific register enum.2652static void emitMatchRegisterAltName(CodeGenTarget &Target, Record *AsmParser,2653raw_ostream &OS) {2654// Construct the match list.2655std::vector<StringMatcher::StringPair> Matches;2656const auto &Regs = Target.getRegBank().getRegisters();2657std::string Namespace =2658Regs.front().TheDef->getValueAsString("Namespace").str();2659for (const CodeGenRegister &Reg : Regs) {26602661auto AltNames = Reg.TheDef->getValueAsListOfStrings("AltNames");26622663for (auto AltName : AltNames) {2664AltName = StringRef(AltName).trim();26652666// don't handle empty alternative names2667if (AltName.empty())2668continue;26692670Matches.emplace_back(AltName.str(), "return " + Namespace +2671"::" + Reg.getName().str() + ';');2672}2673}26742675OS << "static MCRegister MatchRegisterAltName(StringRef Name) {\n";26762677bool IgnoreDuplicates =2678AsmParser->getValueAsBit("AllowDuplicateRegisterNames");2679StringMatcher("Name", Matches, OS).Emit(0, IgnoreDuplicates);26802681OS << " return " << Namespace << "::NoRegister;\n";2682OS << "}\n\n";2683}26842685/// emitOperandDiagnosticTypes - Emit the operand matching diagnostic types.2686static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) {2687// Get the set of diagnostic types from all of the operand classes.2688std::set<StringRef> Types;2689for (const auto &OpClassEntry : Info.AsmOperandClasses) {2690if (!OpClassEntry.second->DiagnosticType.empty())2691Types.insert(OpClassEntry.second->DiagnosticType);2692}2693for (const auto &OpClassEntry : Info.RegisterClassClasses) {2694if (!OpClassEntry.second->DiagnosticType.empty())2695Types.insert(OpClassEntry.second->DiagnosticType);2696}26972698if (Types.empty())2699return;27002701// Now emit the enum entries.2702for (StringRef Type : Types)2703OS << " Match_" << Type << ",\n";2704OS << " END_OPERAND_DIAGNOSTIC_TYPES\n";2705}27062707/// emitGetSubtargetFeatureName - Emit the helper function to get the2708/// user-level name for a subtarget feature.2709static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) {2710OS << "// User-level names for subtarget features that participate in\n"2711<< "// instruction matching.\n"2712<< "static const char *getSubtargetFeatureName(uint64_t Val) {\n";2713if (!Info.SubtargetFeatures.empty()) {2714OS << " switch(Val) {\n";2715for (const auto &SF : Info.SubtargetFeatures) {2716const SubtargetFeatureInfo &SFI = SF.second;2717// FIXME: Totally just a placeholder name to get the algorithm working.2718OS << " case " << SFI.getEnumBitName() << ": return \""2719<< SFI.TheDef->getValueAsString("PredicateName") << "\";\n";2720}2721OS << " default: return \"(unknown)\";\n";2722OS << " }\n";2723} else {2724// Nothing to emit, so skip the switch2725OS << " return \"(unknown)\";\n";2726}2727OS << "}\n\n";2728}27292730static std::string GetAliasRequiredFeatures(Record *R,2731const AsmMatcherInfo &Info) {2732std::vector<Record *> ReqFeatures = R->getValueAsListOfDefs("Predicates");2733std::string Result;27342735if (ReqFeatures.empty())2736return Result;27372738for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) {2739const SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]);27402741if (!F)2742PrintFatalError(R->getLoc(),2743"Predicate '" + ReqFeatures[i]->getName() +2744"' is not marked as an AssemblerPredicate!");27452746if (i)2747Result += " && ";27482749Result += "Features.test(" + F->getEnumBitName() + ')';2750}27512752return Result;2753}27542755static void2756emitMnemonicAliasVariant(raw_ostream &OS, const AsmMatcherInfo &Info,2757std::vector<Record *> &Aliases, unsigned Indent = 0,2758StringRef AsmParserVariantName = StringRef()) {2759// Keep track of all the aliases from a mnemonic. Use an std::map so that the2760// iteration order of the map is stable.2761std::map<std::string, std::vector<Record *>> AliasesFromMnemonic;27622763for (Record *R : Aliases) {2764// FIXME: Allow AssemblerVariantName to be a comma separated list.2765StringRef AsmVariantName = R->getValueAsString("AsmVariantName");2766if (AsmVariantName != AsmParserVariantName)2767continue;2768AliasesFromMnemonic[R->getValueAsString("FromMnemonic").lower()].push_back(2769R);2770}2771if (AliasesFromMnemonic.empty())2772return;27732774// Process each alias a "from" mnemonic at a time, building the code executed2775// by the string remapper.2776std::vector<StringMatcher::StringPair> Cases;2777for (const auto &AliasEntry : AliasesFromMnemonic) {2778const std::vector<Record *> &ToVec = AliasEntry.second;27792780// Loop through each alias and emit code that handles each case. If there2781// are two instructions without predicates, emit an error. If there is one,2782// emit it last.2783std::string MatchCode;2784int AliasWithNoPredicate = -1;27852786for (unsigned i = 0, e = ToVec.size(); i != e; ++i) {2787Record *R = ToVec[i];2788std::string FeatureMask = GetAliasRequiredFeatures(R, Info);27892790// If this unconditionally matches, remember it for later and diagnose2791// duplicates.2792if (FeatureMask.empty()) {2793if (AliasWithNoPredicate != -1 &&2794R->getValueAsString("ToMnemonic") !=2795ToVec[AliasWithNoPredicate]->getValueAsString("ToMnemonic")) {2796// We can't have two different aliases from the same mnemonic with no2797// predicate.2798PrintError(2799ToVec[AliasWithNoPredicate]->getLoc(),2800"two different MnemonicAliases with the same 'from' mnemonic!");2801PrintFatalError(R->getLoc(), "this is the other MnemonicAlias.");2802}28032804AliasWithNoPredicate = i;2805continue;2806}2807if (R->getValueAsString("ToMnemonic") == AliasEntry.first)2808PrintFatalError(R->getLoc(), "MnemonicAlias to the same string");28092810if (!MatchCode.empty())2811MatchCode += "else ";2812MatchCode += "if (" + FeatureMask + ")\n";2813MatchCode += " Mnemonic = \"";2814MatchCode += R->getValueAsString("ToMnemonic").lower();2815MatchCode += "\";\n";2816}28172818if (AliasWithNoPredicate != -1) {2819Record *R = ToVec[AliasWithNoPredicate];2820if (!MatchCode.empty())2821MatchCode += "else\n ";2822MatchCode += "Mnemonic = \"";2823MatchCode += R->getValueAsString("ToMnemonic").lower();2824MatchCode += "\";\n";2825}28262827MatchCode += "return;";28282829Cases.push_back(std::pair(AliasEntry.first, MatchCode));2830}2831StringMatcher("Mnemonic", Cases, OS).Emit(Indent);2832}28332834/// emitMnemonicAliases - If the target has any MnemonicAlias<> definitions,2835/// emit a function for them and return true, otherwise return false.2836static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info,2837CodeGenTarget &Target) {2838// Ignore aliases when match-prefix is set.2839if (!MatchPrefix.empty())2840return false;28412842std::vector<Record *> Aliases =2843Info.getRecords().getAllDerivedDefinitions("MnemonicAlias");2844if (Aliases.empty())2845return false;28462847OS << "static void applyMnemonicAliases(StringRef &Mnemonic, "2848"const FeatureBitset &Features, unsigned VariantID) {\n";2849OS << " switch (VariantID) {\n";2850unsigned VariantCount = Target.getAsmParserVariantCount();2851for (unsigned VC = 0; VC != VariantCount; ++VC) {2852Record *AsmVariant = Target.getAsmParserVariant(VC);2853int AsmParserVariantNo = AsmVariant->getValueAsInt("Variant");2854StringRef AsmParserVariantName = AsmVariant->getValueAsString("Name");2855OS << " case " << AsmParserVariantNo << ":\n";2856emitMnemonicAliasVariant(OS, Info, Aliases, /*Indent=*/2,2857AsmParserVariantName);2858OS << " break;\n";2859}2860OS << " }\n";28612862// Emit aliases that apply to all variants.2863emitMnemonicAliasVariant(OS, Info, Aliases);28642865OS << "}\n\n";28662867return true;2868}28692870static void2871emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,2872const AsmMatcherInfo &Info, StringRef ClassName,2873StringToOffsetTable &StringTable,2874unsigned MaxMnemonicIndex, unsigned MaxFeaturesIndex,2875bool HasMnemonicFirst, const Record &AsmParser) {2876unsigned MaxMask = 0;2877for (const OperandMatchEntry &OMI : Info.OperandMatchInfo) {2878MaxMask |= OMI.OperandMask;2879}28802881// Emit the static custom operand parsing table;2882OS << "namespace {\n";2883OS << " struct OperandMatchEntry {\n";2884OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n";2885OS << " " << getMinimalTypeForRange(MaxMask) << " OperandMask;\n";2886OS << " "2887<< getMinimalTypeForRange(2888std::distance(Info.Classes.begin(), Info.Classes.end()) +28892 /* Include 'InvalidMatchClass' and 'OptionalMatchClass' */)2890<< " Class;\n";2891OS << " " << getMinimalTypeForRange(MaxFeaturesIndex)2892<< " RequiredFeaturesIdx;\n\n";2893OS << " StringRef getMnemonic() const {\n";2894OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n";2895OS << " MnemonicTable[Mnemonic]);\n";2896OS << " }\n";2897OS << " };\n\n";28982899OS << " // Predicate for searching for an opcode.\n";2900OS << " struct LessOpcodeOperand {\n";2901OS << " bool operator()(const OperandMatchEntry &LHS, StringRef RHS) {\n";2902OS << " return LHS.getMnemonic() < RHS;\n";2903OS << " }\n";2904OS << " bool operator()(StringRef LHS, const OperandMatchEntry &RHS) {\n";2905OS << " return LHS < RHS.getMnemonic();\n";2906OS << " }\n";2907OS << " bool operator()(const OperandMatchEntry &LHS,";2908OS << " const OperandMatchEntry &RHS) {\n";2909OS << " return LHS.getMnemonic() < RHS.getMnemonic();\n";2910OS << " }\n";2911OS << " };\n";29122913OS << "} // end anonymous namespace\n\n";29142915OS << "static const OperandMatchEntry OperandMatchTable["2916<< Info.OperandMatchInfo.size() << "] = {\n";29172918OS << " /* Operand List Mnemonic, Mask, Operand Class, Features */\n";2919for (const OperandMatchEntry &OMI : Info.OperandMatchInfo) {2920const MatchableInfo &II = *OMI.MI;29212922OS << " { ";29232924// Store a pascal-style length byte in the mnemonic.2925std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.lower();2926OS << StringTable.GetOrAddStringOffset(LenMnemonic, false) << " /* "2927<< II.Mnemonic << " */, ";29282929OS << OMI.OperandMask;2930OS << " /* ";2931ListSeparator LS;2932for (int i = 0, e = 31; i != e; ++i)2933if (OMI.OperandMask & (1 << i))2934OS << LS << i;2935OS << " */, ";29362937OS << OMI.CI->Name;29382939// Write the required features mask.2940OS << ", AMFBS";2941if (II.RequiredFeatures.empty())2942OS << "_None";2943else2944for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i)2945OS << '_' << II.RequiredFeatures[i]->TheDef->getName();29462947OS << " },\n";2948}2949OS << "};\n\n";29502951// Emit the operand class switch to call the correct custom parser for2952// the found operand class.2953OS << "ParseStatus " << Target.getName() << ClassName << "::\n"2954<< "tryCustomParseOperand(OperandVector"2955<< " &Operands,\n unsigned MCK) {\n\n"2956<< " switch(MCK) {\n";29572958for (const auto &CI : Info.Classes) {2959if (CI.ParserMethod.empty())2960continue;2961OS << " case " << CI.Name << ":\n"2962<< " return " << CI.ParserMethod << "(Operands);\n";2963}29642965OS << " default:\n";2966OS << " return ParseStatus::NoMatch;\n";2967OS << " }\n";2968OS << " return ParseStatus::NoMatch;\n";2969OS << "}\n\n";29702971// Emit the static custom operand parser. This code is very similar with2972// the other matcher. Also use MatchResultTy here just in case we go for2973// a better error handling.2974OS << "ParseStatus " << Target.getName() << ClassName << "::\n"2975<< "MatchOperandParserImpl(OperandVector"2976<< " &Operands,\n StringRef Mnemonic,\n"2977<< " bool ParseForAllFeatures) {\n";29782979// Emit code to get the available features.2980OS << " // Get the current feature set.\n";2981OS << " const FeatureBitset &AvailableFeatures = "2982"getAvailableFeatures();\n\n";29832984OS << " // Get the next operand index.\n";2985OS << " unsigned NextOpNum = Operands.size()"2986<< (HasMnemonicFirst ? " - 1" : "") << ";\n";29872988// Emit code to search the table.2989OS << " // Search the table.\n";2990if (HasMnemonicFirst) {2991OS << " auto MnemonicRange =\n";2992OS << " std::equal_range(std::begin(OperandMatchTable), "2993"std::end(OperandMatchTable),\n";2994OS << " Mnemonic, LessOpcodeOperand());\n\n";2995} else {2996OS << " auto MnemonicRange = std::pair(std::begin(OperandMatchTable),"2997" std::end(OperandMatchTable));\n";2998OS << " if (!Mnemonic.empty())\n";2999OS << " MnemonicRange =\n";3000OS << " std::equal_range(std::begin(OperandMatchTable), "3001"std::end(OperandMatchTable),\n";3002OS << " Mnemonic, LessOpcodeOperand());\n\n";3003}30043005OS << " if (MnemonicRange.first == MnemonicRange.second)\n";3006OS << " return ParseStatus::NoMatch;\n\n";30073008OS << " for (const OperandMatchEntry *it = MnemonicRange.first,\n"3009<< " *ie = MnemonicRange.second; it != ie; ++it) {\n";30103011OS << " // equal_range guarantees that instruction mnemonic matches.\n";3012OS << " assert(Mnemonic == it->getMnemonic());\n\n";30133014// Emit check that the required features are available.3015OS << " // check if the available features match\n";3016OS << " const FeatureBitset &RequiredFeatures = "3017"FeatureBitsets[it->RequiredFeaturesIdx];\n";3018OS << " if (!ParseForAllFeatures && (AvailableFeatures & "3019"RequiredFeatures) != RequiredFeatures)\n";3020OS << " continue;\n\n";30213022// Emit check to ensure the operand number matches.3023OS << " // check if the operand in question has a custom parser.\n";3024OS << " if (!(it->OperandMask & (1 << NextOpNum)))\n";3025OS << " continue;\n\n";30263027// Emit call to the custom parser method3028StringRef ParserName = AsmParser.getValueAsString("OperandParserMethod");3029if (ParserName.empty())3030ParserName = "tryCustomParseOperand";3031OS << " // call custom parse method to handle the operand\n";3032OS << " ParseStatus Result = " << ParserName << "(Operands, it->Class);\n";3033OS << " if (!Result.isNoMatch())\n";3034OS << " return Result;\n";3035OS << " }\n\n";30363037OS << " // Okay, we had no match.\n";3038OS << " return ParseStatus::NoMatch;\n";3039OS << "}\n\n";3040}30413042static void emitAsmTiedOperandConstraints(CodeGenTarget &Target,3043AsmMatcherInfo &Info, raw_ostream &OS,3044bool HasOptionalOperands) {3045std::string AsmParserName =3046std::string(Info.AsmParser->getValueAsString("AsmParserClassName"));3047OS << "static bool ";3048OS << "checkAsmTiedOperandConstraints(const " << Target.getName()3049<< AsmParserName << "&AsmParser,\n";3050OS << " unsigned Kind, const OperandVector "3051"&Operands,\n";3052if (HasOptionalOperands)3053OS << " ArrayRef<unsigned> DefaultsOffset,\n";3054OS << " uint64_t &ErrorInfo) {\n";3055OS << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n";3056OS << " const uint8_t *Converter = ConversionTable[Kind];\n";3057OS << " for (const uint8_t *p = Converter; *p; p += 2) {\n";3058OS << " switch (*p) {\n";3059OS << " case CVT_Tied: {\n";3060OS << " unsigned OpIdx = *(p + 1);\n";3061OS << " assert(OpIdx < (size_t)(std::end(TiedAsmOperandTable) -\n";3062OS << " std::begin(TiedAsmOperandTable)) &&\n";3063OS << " \"Tied operand not found\");\n";3064OS << " unsigned OpndNum1 = TiedAsmOperandTable[OpIdx][1];\n";3065OS << " unsigned OpndNum2 = TiedAsmOperandTable[OpIdx][2];\n";3066if (HasOptionalOperands) {3067// When optional operands are involved, formal and actual operand indices3068// may differ. Map the former to the latter by subtracting the number of3069// absent optional operands.3070OS << " OpndNum1 = OpndNum1 - DefaultsOffset[OpndNum1];\n";3071OS << " OpndNum2 = OpndNum2 - DefaultsOffset[OpndNum2];\n";3072}3073OS << " if (OpndNum1 != OpndNum2) {\n";3074OS << " auto &SrcOp1 = Operands[OpndNum1];\n";3075OS << " auto &SrcOp2 = Operands[OpndNum2];\n";3076OS << " if (!AsmParser.areEqualRegs(*SrcOp1, *SrcOp2)) {\n";3077OS << " ErrorInfo = OpndNum2;\n";3078OS << " return false;\n";3079OS << " }\n";3080OS << " }\n";3081OS << " break;\n";3082OS << " }\n";3083OS << " default:\n";3084OS << " break;\n";3085OS << " }\n";3086OS << " }\n";3087OS << " return true;\n";3088OS << "}\n\n";3089}30903091static void emitMnemonicSpellChecker(raw_ostream &OS, CodeGenTarget &Target,3092unsigned VariantCount) {3093OS << "static std::string " << Target.getName()3094<< "MnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,"3095<< " unsigned VariantID) {\n";3096if (!VariantCount)3097OS << " return \"\";";3098else {3099OS << " const unsigned MaxEditDist = 2;\n";3100OS << " std::vector<StringRef> Candidates;\n";3101OS << " StringRef Prev = \"\";\n\n";31023103OS << " // Find the appropriate table for this asm variant.\n";3104OS << " const MatchEntry *Start, *End;\n";3105OS << " switch (VariantID) {\n";3106OS << " default: llvm_unreachable(\"invalid variant!\");\n";3107for (unsigned VC = 0; VC != VariantCount; ++VC) {3108Record *AsmVariant = Target.getAsmParserVariant(VC);3109int AsmVariantNo = AsmVariant->getValueAsInt("Variant");3110OS << " case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC3111<< "); End = std::end(MatchTable" << VC << "); break;\n";3112}3113OS << " }\n\n";3114OS << " for (auto I = Start; I < End; I++) {\n";3115OS << " // Ignore unsupported instructions.\n";3116OS << " const FeatureBitset &RequiredFeatures = "3117"FeatureBitsets[I->RequiredFeaturesIdx];\n";3118OS << " if ((FBS & RequiredFeatures) != RequiredFeatures)\n";3119OS << " continue;\n";3120OS << "\n";3121OS << " StringRef T = I->getMnemonic();\n";3122OS << " // Avoid recomputing the edit distance for the same string.\n";3123OS << " if (T == Prev)\n";3124OS << " continue;\n";3125OS << "\n";3126OS << " Prev = T;\n";3127OS << " unsigned Dist = S.edit_distance(T, false, MaxEditDist);\n";3128OS << " if (Dist <= MaxEditDist)\n";3129OS << " Candidates.push_back(T);\n";3130OS << " }\n";3131OS << "\n";3132OS << " if (Candidates.empty())\n";3133OS << " return \"\";\n";3134OS << "\n";3135OS << " std::string Res = \", did you mean: \";\n";3136OS << " unsigned i = 0;\n";3137OS << " for (; i < Candidates.size() - 1; i++)\n";3138OS << " Res += Candidates[i].str() + \", \";\n";3139OS << " return Res + Candidates[i].str() + \"?\";\n";3140}3141OS << "}\n";3142OS << "\n";3143}31443145static void emitMnemonicChecker(raw_ostream &OS, CodeGenTarget &Target,3146unsigned VariantCount, bool HasMnemonicFirst,3147bool HasMnemonicAliases) {3148OS << "static bool " << Target.getName()3149<< "CheckMnemonic(StringRef Mnemonic,\n";3150OS << " "3151<< "const FeatureBitset &AvailableFeatures,\n";3152OS << " "3153<< "unsigned VariantID) {\n";31543155if (!VariantCount) {3156OS << " return false;\n";3157} else {3158if (HasMnemonicAliases) {3159OS << " // Process all MnemonicAliases to remap the mnemonic.\n";3160OS << " applyMnemonicAliases(Mnemonic, AvailableFeatures, VariantID);";3161OS << "\n\n";3162}3163OS << " // Find the appropriate table for this asm variant.\n";3164OS << " const MatchEntry *Start, *End;\n";3165OS << " switch (VariantID) {\n";3166OS << " default: llvm_unreachable(\"invalid variant!\");\n";3167for (unsigned VC = 0; VC != VariantCount; ++VC) {3168Record *AsmVariant = Target.getAsmParserVariant(VC);3169int AsmVariantNo = AsmVariant->getValueAsInt("Variant");3170OS << " case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC3171<< "); End = std::end(MatchTable" << VC << "); break;\n";3172}3173OS << " }\n\n";31743175OS << " // Search the table.\n";3176if (HasMnemonicFirst) {3177OS << " auto MnemonicRange = "3178"std::equal_range(Start, End, Mnemonic, LessOpcode());\n\n";3179} else {3180OS << " auto MnemonicRange = std::pair(Start, End);\n";3181OS << " unsigned SIndex = Mnemonic.empty() ? 0 : 1;\n";3182OS << " if (!Mnemonic.empty())\n";3183OS << " MnemonicRange = "3184<< "std::equal_range(Start, End, Mnemonic.lower(), LessOpcode());\n\n";3185}31863187OS << " if (MnemonicRange.first == MnemonicRange.second)\n";3188OS << " return false;\n\n";31893190OS << " for (const MatchEntry *it = MnemonicRange.first, "3191<< "*ie = MnemonicRange.second;\n";3192OS << " it != ie; ++it) {\n";3193OS << " const FeatureBitset &RequiredFeatures =\n";3194OS << " FeatureBitsets[it->RequiredFeaturesIdx];\n";3195OS << " if ((AvailableFeatures & RequiredFeatures) == ";3196OS << "RequiredFeatures)\n";3197OS << " return true;\n";3198OS << " }\n";3199OS << " return false;\n";3200}3201OS << "}\n";3202OS << "\n";3203}32043205// Emit a function mapping match classes to strings, for debugging.3206static void emitMatchClassKindNames(std::forward_list<ClassInfo> &Infos,3207raw_ostream &OS) {3208OS << "#ifndef NDEBUG\n";3209OS << "const char *getMatchClassName(MatchClassKind Kind) {\n";3210OS << " switch (Kind) {\n";32113212OS << " case InvalidMatchClass: return \"InvalidMatchClass\";\n";3213OS << " case OptionalMatchClass: return \"OptionalMatchClass\";\n";3214for (const auto &CI : Infos) {3215OS << " case " << CI.Name << ": return \"" << CI.Name << "\";\n";3216}3217OS << " case NumMatchClassKinds: return \"NumMatchClassKinds\";\n";32183219OS << " }\n";3220OS << " llvm_unreachable(\"unhandled MatchClassKind!\");\n";3221OS << "}\n\n";3222OS << "#endif // NDEBUG\n";3223}32243225static std::string3226getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset) {3227std::string Name = "AMFBS";3228for (const auto &Feature : FeatureBitset)3229Name += ("_" + Feature->getName()).str();3230return Name;3231}32323233void AsmMatcherEmitter::run(raw_ostream &OS) {3234CodeGenTarget Target(Records);3235Record *AsmParser = Target.getAsmParser();3236StringRef ClassName = AsmParser->getValueAsString("AsmParserClassName");32373238emitSourceFileHeader("Assembly Matcher Source Fragment", OS, Records);32393240// Compute the information on the instructions to match.3241AsmMatcherInfo Info(AsmParser, Target, Records);3242Info.buildInfo();32433244bool PreferSmallerInstructions = getPreferSmallerInstructions(Target);3245// Sort the instruction table using the partial order on classes. We use3246// stable_sort to ensure that ambiguous instructions are still3247// deterministically ordered.3248llvm::stable_sort(3249Info.Matchables,3250[PreferSmallerInstructions](const std::unique_ptr<MatchableInfo> &A,3251const std::unique_ptr<MatchableInfo> &B) {3252return A->shouldBeMatchedBefore(*B, PreferSmallerInstructions);3253});32543255#ifdef EXPENSIVE_CHECKS3256// Verify that the table is sorted and operator < works transitively.3257for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E;3258++I) {3259for (auto J = I; J != E; ++J) {3260assert(!(*J)->shouldBeMatchedBefore(**I, PreferSmallerInstructions));3261}3262}3263#endif32643265DEBUG_WITH_TYPE("instruction_info", {3266for (const auto &MI : Info.Matchables)3267MI->dump();3268});32693270// Check for ambiguous matchables.3271DEBUG_WITH_TYPE("ambiguous_instrs", {3272unsigned NumAmbiguous = 0;3273for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E;3274++I) {3275for (auto J = std::next(I); J != E; ++J) {3276const MatchableInfo &A = **I;3277const MatchableInfo &B = **J;32783279if (A.couldMatchAmbiguouslyWith(B, PreferSmallerInstructions)) {3280errs() << "warning: ambiguous matchables:\n";3281A.dump();3282errs() << "\nis incomparable with:\n";3283B.dump();3284errs() << "\n\n";3285++NumAmbiguous;3286}3287}3288}3289if (NumAmbiguous)3290errs() << "warning: " << NumAmbiguous << " ambiguous matchables!\n";3291});32923293// Compute the information on the custom operand parsing.3294Info.buildOperandMatchInfo();32953296bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst");3297bool HasOptionalOperands = Info.hasOptionalOperands();3298bool ReportMultipleNearMisses =3299AsmParser->getValueAsBit("ReportMultipleNearMisses");33003301// Write the output.33023303// Information for the class declaration.3304OS << "\n#ifdef GET_ASSEMBLER_HEADER\n";3305OS << "#undef GET_ASSEMBLER_HEADER\n";3306OS << " // This should be included into the middle of the declaration of\n";3307OS << " // your subclasses implementation of MCTargetAsmParser.\n";3308OS << " FeatureBitset ComputeAvailableFeatures(const FeatureBitset &FB) "3309"const;\n";3310if (HasOptionalOperands) {3311OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "3312<< "unsigned Opcode,\n"3313<< " const OperandVector &Operands,\n"3314<< " const SmallBitVector "3315"&OptionalOperandsMask,\n"3316<< " ArrayRef<unsigned> DefaultsOffset);\n";3317} else {3318OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "3319<< "unsigned Opcode,\n"3320<< " const OperandVector &Operands);\n";3321}3322OS << " void convertToMapAndConstraints(unsigned Kind,\n ";3323OS << " const OperandVector &Operands) override;\n";3324OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n"3325<< " MCInst &Inst,\n";3326if (ReportMultipleNearMisses)3327OS << " SmallVectorImpl<NearMissInfo> "3328"*NearMisses,\n";3329else3330OS << " uint64_t &ErrorInfo,\n"3331<< " FeatureBitset &MissingFeatures,\n";3332OS << " bool matchingInlineAsm,\n"3333<< " unsigned VariantID = 0);\n";3334if (!ReportMultipleNearMisses)3335OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n"3336<< " MCInst &Inst,\n"3337<< " uint64_t &ErrorInfo,\n"3338<< " bool matchingInlineAsm,\n"3339<< " unsigned VariantID = 0) {\n"3340<< " FeatureBitset MissingFeatures;\n"3341<< " return MatchInstructionImpl(Operands, Inst, ErrorInfo, "3342"MissingFeatures,\n"3343<< " matchingInlineAsm, VariantID);\n"3344<< " }\n\n";33453346if (!Info.OperandMatchInfo.empty()) {3347OS << " ParseStatus MatchOperandParserImpl(\n";3348OS << " OperandVector &Operands,\n";3349OS << " StringRef Mnemonic,\n";3350OS << " bool ParseForAllFeatures = false);\n";33513352OS << " ParseStatus tryCustomParseOperand(\n";3353OS << " OperandVector &Operands,\n";3354OS << " unsigned MCK);\n\n";3355}33563357OS << "#endif // GET_ASSEMBLER_HEADER\n\n";33583359// Emit the operand match diagnostic enum names.3360OS << "\n#ifdef GET_OPERAND_DIAGNOSTIC_TYPES\n";3361OS << "#undef GET_OPERAND_DIAGNOSTIC_TYPES\n\n";3362emitOperandDiagnosticTypes(Info, OS);3363OS << "#endif // GET_OPERAND_DIAGNOSTIC_TYPES\n\n";33643365OS << "\n#ifdef GET_REGISTER_MATCHER\n";3366OS << "#undef GET_REGISTER_MATCHER\n\n";33673368// Emit the subtarget feature enumeration.3369SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(3370Info.SubtargetFeatures, OS);33713372// Emit the function to match a register name to number.3373// This should be omitted for Mips target3374if (AsmParser->getValueAsBit("ShouldEmitMatchRegisterName"))3375emitMatchRegisterName(Target, AsmParser, OS);33763377if (AsmParser->getValueAsBit("ShouldEmitMatchRegisterAltName"))3378emitMatchRegisterAltName(Target, AsmParser, OS);33793380OS << "#endif // GET_REGISTER_MATCHER\n\n";33813382OS << "\n#ifdef GET_SUBTARGET_FEATURE_NAME\n";3383OS << "#undef GET_SUBTARGET_FEATURE_NAME\n\n";33843385// Generate the helper function to get the names for subtarget features.3386emitGetSubtargetFeatureName(Info, OS);33873388OS << "#endif // GET_SUBTARGET_FEATURE_NAME\n\n";33893390OS << "\n#ifdef GET_MATCHER_IMPLEMENTATION\n";3391OS << "#undef GET_MATCHER_IMPLEMENTATION\n\n";33923393// Generate the function that remaps for mnemonic aliases.3394bool HasMnemonicAliases = emitMnemonicAliases(OS, Info, Target);33953396// Generate the convertToMCInst function to convert operands into an MCInst.3397// Also, generate the convertToMapAndConstraints function for MS-style inline3398// assembly. The latter doesn't actually generate a MCInst.3399unsigned NumConverters =3400emitConvertFuncs(Target, ClassName, Info.Matchables, HasMnemonicFirst,3401HasOptionalOperands, OS);34023403// Emit the enumeration for classes which participate in matching.3404emitMatchClassEnumeration(Target, Info.Classes, OS);34053406// Emit a function to get the user-visible string to describe an operand3407// match failure in diagnostics.3408emitOperandMatchErrorDiagStrings(Info, OS);34093410// Emit a function to map register classes to operand match failure codes.3411emitRegisterMatchErrorFunc(Info, OS);34123413// Emit the routine to match token strings to their match class.3414emitMatchTokenString(Target, Info.Classes, OS);34153416// Emit the subclass predicate routine.3417emitIsSubclass(Target, Info.Classes, OS);34183419// Emit the routine to validate an operand against a match class.3420emitValidateOperandClass(Info, OS);34213422emitMatchClassKindNames(Info.Classes, OS);34233424// Emit the available features compute function.3425SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(3426Info.Target.getName(), ClassName, "ComputeAvailableFeatures",3427Info.SubtargetFeatures, OS);34283429if (!ReportMultipleNearMisses)3430emitAsmTiedOperandConstraints(Target, Info, OS, HasOptionalOperands);34313432StringToOffsetTable StringTable;34333434size_t MaxNumOperands = 0;3435unsigned MaxMnemonicIndex = 0;3436bool HasDeprecation = false;3437for (const auto &MI : Info.Matchables) {3438MaxNumOperands = std::max(MaxNumOperands, MI->AsmOperands.size());3439HasDeprecation |= MI->HasDeprecation;34403441// Store a pascal-style length byte in the mnemonic.3442std::string LenMnemonic = char(MI->Mnemonic.size()) + MI->Mnemonic.lower();3443MaxMnemonicIndex = std::max(3444MaxMnemonicIndex, StringTable.GetOrAddStringOffset(LenMnemonic, false));3445}34463447OS << "static const char MnemonicTable[] =\n";3448StringTable.EmitString(OS);3449OS << ";\n\n";34503451std::vector<std::vector<Record *>> FeatureBitsets;3452for (const auto &MI : Info.Matchables) {3453if (MI->RequiredFeatures.empty())3454continue;3455FeatureBitsets.emplace_back();3456for (unsigned I = 0, E = MI->RequiredFeatures.size(); I != E; ++I)3457FeatureBitsets.back().push_back(MI->RequiredFeatures[I]->TheDef);3458}34593460llvm::sort(FeatureBitsets, [&](const std::vector<Record *> &A,3461const std::vector<Record *> &B) {3462if (A.size() < B.size())3463return true;3464if (A.size() > B.size())3465return false;3466for (auto Pair : zip(A, B)) {3467if (std::get<0>(Pair)->getName() < std::get<1>(Pair)->getName())3468return true;3469if (std::get<0>(Pair)->getName() > std::get<1>(Pair)->getName())3470return false;3471}3472return false;3473});3474FeatureBitsets.erase(llvm::unique(FeatureBitsets), FeatureBitsets.end());3475OS << "// Feature bitsets.\n"3476<< "enum : " << getMinimalTypeForRange(FeatureBitsets.size()) << " {\n"3477<< " AMFBS_None,\n";3478for (const auto &FeatureBitset : FeatureBitsets) {3479if (FeatureBitset.empty())3480continue;3481OS << " " << getNameForFeatureBitset(FeatureBitset) << ",\n";3482}3483OS << "};\n\n"3484<< "static constexpr FeatureBitset FeatureBitsets[] = {\n"3485<< " {}, // AMFBS_None\n";3486for (const auto &FeatureBitset : FeatureBitsets) {3487if (FeatureBitset.empty())3488continue;3489OS << " {";3490for (const auto &Feature : FeatureBitset) {3491const auto &I = Info.SubtargetFeatures.find(Feature);3492assert(I != Info.SubtargetFeatures.end() && "Didn't import predicate?");3493OS << I->second.getEnumBitName() << ", ";3494}3495OS << "},\n";3496}3497OS << "};\n\n";34983499// Emit the static match table; unused classes get initialized to 0 which is3500// guaranteed to be InvalidMatchClass.3501//3502// FIXME: We can reduce the size of this table very easily. First, we change3503// it so that store the kinds in separate bit-fields for each index, which3504// only needs to be the max width used for classes at that index (we also need3505// to reject based on this during classification). If we then make sure to3506// order the match kinds appropriately (putting mnemonics last), then we3507// should only end up using a few bits for each class, especially the ones3508// following the mnemonic.3509OS << "namespace {\n";3510OS << " struct MatchEntry {\n";3511OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n";3512OS << " uint16_t Opcode;\n";3513OS << " " << getMinimalTypeForRange(NumConverters) << " ConvertFn;\n";3514OS << " " << getMinimalTypeForRange(FeatureBitsets.size())3515<< " RequiredFeaturesIdx;\n";3516OS << " "3517<< getMinimalTypeForRange(3518std::distance(Info.Classes.begin(), Info.Classes.end()) +35192 /* Include 'InvalidMatchClass' and 'OptionalMatchClass' */)3520<< " Classes[" << MaxNumOperands << "];\n";3521OS << " StringRef getMnemonic() const {\n";3522OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n";3523OS << " MnemonicTable[Mnemonic]);\n";3524OS << " }\n";3525OS << " };\n\n";35263527OS << " // Predicate for searching for an opcode.\n";3528OS << " struct LessOpcode {\n";3529OS << " bool operator()(const MatchEntry &LHS, StringRef RHS) {\n";3530OS << " return LHS.getMnemonic() < RHS;\n";3531OS << " }\n";3532OS << " bool operator()(StringRef LHS, const MatchEntry &RHS) {\n";3533OS << " return LHS < RHS.getMnemonic();\n";3534OS << " }\n";3535OS << " bool operator()(const MatchEntry &LHS, const MatchEntry &RHS) {\n";3536OS << " return LHS.getMnemonic() < RHS.getMnemonic();\n";3537OS << " }\n";3538OS << " };\n";35393540OS << "} // end anonymous namespace\n\n";35413542unsigned VariantCount = Target.getAsmParserVariantCount();3543for (unsigned VC = 0; VC != VariantCount; ++VC) {3544Record *AsmVariant = Target.getAsmParserVariant(VC);3545int AsmVariantNo = AsmVariant->getValueAsInt("Variant");35463547OS << "static const MatchEntry MatchTable" << VC << "[] = {\n";35483549for (const auto &MI : Info.Matchables) {3550if (MI->AsmVariantID != AsmVariantNo)3551continue;35523553// Store a pascal-style length byte in the mnemonic.3554std::string LenMnemonic =3555char(MI->Mnemonic.size()) + MI->Mnemonic.lower();3556OS << " { " << StringTable.GetOrAddStringOffset(LenMnemonic, false)3557<< " /* " << MI->Mnemonic << " */, " << Target.getInstNamespace()3558<< "::" << MI->getResultInst()->TheDef->getName() << ", "3559<< MI->ConversionFnKind << ", ";35603561// Write the required features mask.3562OS << "AMFBS";3563if (MI->RequiredFeatures.empty())3564OS << "_None";3565else3566for (unsigned i = 0, e = MI->RequiredFeatures.size(); i != e; ++i)3567OS << '_' << MI->RequiredFeatures[i]->TheDef->getName();35683569OS << ", { ";3570ListSeparator LS;3571for (const MatchableInfo::AsmOperand &Op : MI->AsmOperands)3572OS << LS << Op.Class->Name;3573OS << " }, },\n";3574}35753576OS << "};\n\n";3577}35783579OS << "#include \"llvm/Support/Debug.h\"\n";3580OS << "#include \"llvm/Support/Format.h\"\n\n";35813582// Finally, build the match function.3583OS << "unsigned " << Target.getName() << ClassName << "::\n"3584<< "MatchInstructionImpl(const OperandVector &Operands,\n";3585OS << " MCInst &Inst,\n";3586if (ReportMultipleNearMisses)3587OS << " SmallVectorImpl<NearMissInfo> *NearMisses,\n";3588else3589OS << " uint64_t &ErrorInfo,\n"3590<< " FeatureBitset &MissingFeatures,\n";3591OS << " bool matchingInlineAsm, unsigned VariantID) {\n";35923593if (!ReportMultipleNearMisses) {3594OS << " // Eliminate obvious mismatches.\n";3595OS << " if (Operands.size() > " << (MaxNumOperands + HasMnemonicFirst)3596<< ") {\n";3597OS << " ErrorInfo = " << (MaxNumOperands + HasMnemonicFirst) << ";\n";3598OS << " return Match_InvalidOperand;\n";3599OS << " }\n\n";3600}36013602// Emit code to get the available features.3603OS << " // Get the current feature set.\n";3604OS << " const FeatureBitset &AvailableFeatures = "3605"getAvailableFeatures();\n\n";36063607OS << " // Get the instruction mnemonic, which is the first token.\n";3608if (HasMnemonicFirst) {3609OS << " StringRef Mnemonic = ((" << Target.getName()3610<< "Operand &)*Operands[0]).getToken();\n\n";3611} else {3612OS << " StringRef Mnemonic;\n";3613OS << " if (Operands[0]->isToken())\n";3614OS << " Mnemonic = ((" << Target.getName()3615<< "Operand &)*Operands[0]).getToken();\n\n";3616}36173618if (HasMnemonicAliases) {3619OS << " // Process all MnemonicAliases to remap the mnemonic.\n";3620OS << " applyMnemonicAliases(Mnemonic, AvailableFeatures, VariantID);\n\n";3621}36223623// Emit code to compute the class list for this operand vector.3624if (!ReportMultipleNearMisses) {3625OS << " // Some state to try to produce better error messages.\n";3626OS << " bool HadMatchOtherThanFeatures = false;\n";3627OS << " bool HadMatchOtherThanPredicate = false;\n";3628OS << " unsigned RetCode = Match_InvalidOperand;\n";3629OS << " MissingFeatures.set();\n";3630OS << " // Set ErrorInfo to the operand that mismatches if it is\n";3631OS << " // wrong for all instances of the instruction.\n";3632OS << " ErrorInfo = ~0ULL;\n";3633}36343635if (HasOptionalOperands) {3636OS << " SmallBitVector OptionalOperandsMask(" << MaxNumOperands << ");\n";3637}36383639// Emit code to search the table.3640OS << " // Find the appropriate table for this asm variant.\n";3641OS << " const MatchEntry *Start, *End;\n";3642OS << " switch (VariantID) {\n";3643OS << " default: llvm_unreachable(\"invalid variant!\");\n";3644for (unsigned VC = 0; VC != VariantCount; ++VC) {3645Record *AsmVariant = Target.getAsmParserVariant(VC);3646int AsmVariantNo = AsmVariant->getValueAsInt("Variant");3647OS << " case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC3648<< "); End = std::end(MatchTable" << VC << "); break;\n";3649}3650OS << " }\n";36513652OS << " // Search the table.\n";3653if (HasMnemonicFirst) {3654OS << " auto MnemonicRange = "3655"std::equal_range(Start, End, Mnemonic, LessOpcode());\n\n";3656} else {3657OS << " auto MnemonicRange = std::pair(Start, End);\n";3658OS << " unsigned SIndex = Mnemonic.empty() ? 0 : 1;\n";3659OS << " if (!Mnemonic.empty())\n";3660OS << " MnemonicRange = "3661"std::equal_range(Start, End, Mnemonic.lower(), LessOpcode());\n\n";3662}36633664OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"AsmMatcher: found \" "3665"<<\n"3666<< " std::distance(MnemonicRange.first, MnemonicRange.second) <<\n"3667<< " \" encodings with mnemonic '\" << Mnemonic << \"'\\n\");\n\n";36683669OS << " // Return a more specific error code if no mnemonics match.\n";3670OS << " if (MnemonicRange.first == MnemonicRange.second)\n";3671OS << " return Match_MnemonicFail;\n\n";36723673OS << " for (const MatchEntry *it = MnemonicRange.first, "3674<< "*ie = MnemonicRange.second;\n";3675OS << " it != ie; ++it) {\n";3676OS << " const FeatureBitset &RequiredFeatures = "3677"FeatureBitsets[it->RequiredFeaturesIdx];\n";3678OS << " bool HasRequiredFeatures =\n";3679OS << " (AvailableFeatures & RequiredFeatures) == RequiredFeatures;\n";3680OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Trying to match "3681"opcode \"\n";3682OS << " << MII.getName(it->Opcode) "3683"<< \"\\n\");\n";36843685if (ReportMultipleNearMisses) {3686OS << " // Some state to record ways in which this instruction did not "3687"match.\n";3688OS << " NearMissInfo OperandNearMiss = NearMissInfo::getSuccess();\n";3689OS << " NearMissInfo FeaturesNearMiss = NearMissInfo::getSuccess();\n";3690OS << " NearMissInfo EarlyPredicateNearMiss = "3691"NearMissInfo::getSuccess();\n";3692OS << " NearMissInfo LatePredicateNearMiss = "3693"NearMissInfo::getSuccess();\n";3694OS << " bool MultipleInvalidOperands = false;\n";3695}36963697if (HasMnemonicFirst) {3698OS << " // equal_range guarantees that instruction mnemonic matches.\n";3699OS << " assert(Mnemonic == it->getMnemonic());\n";3700}37013702// Emit check that the subclasses match.3703if (!ReportMultipleNearMisses)3704OS << " bool OperandsValid = true;\n";3705if (HasOptionalOperands) {3706OS << " OptionalOperandsMask.reset(0, " << MaxNumOperands << ");\n";3707}3708OS << " for (unsigned FormalIdx = " << (HasMnemonicFirst ? "0" : "SIndex")3709<< ", ActualIdx = " << (HasMnemonicFirst ? "1" : "SIndex")3710<< "; FormalIdx != " << MaxNumOperands << "; ++FormalIdx) {\n";3711OS << " auto Formal = "3712<< "static_cast<MatchClassKind>(it->Classes[FormalIdx]);\n";3713OS << " DEBUG_WITH_TYPE(\"asm-matcher\",\n";3714OS << " dbgs() << \" Matching formal operand class \" "3715"<< getMatchClassName(Formal)\n";3716OS << " << \" against actual operand at index \" "3717"<< ActualIdx);\n";3718OS << " if (ActualIdx < Operands.size())\n";3719OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \" (\";\n";3720OS << " Operands[ActualIdx]->print(dbgs()); dbgs() << "3721"\"): \");\n";3722OS << " else\n";3723OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \": \");\n";3724OS << " if (ActualIdx >= Operands.size()) {\n";3725OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"actual operand "3726"index out of range\\n\");\n";3727if (ReportMultipleNearMisses) {3728OS << " bool ThisOperandValid = (Formal == "3729<< "InvalidMatchClass) || "3730"isSubclass(Formal, OptionalMatchClass);\n";3731OS << " if (!ThisOperandValid) {\n";3732OS << " if (!OperandNearMiss) {\n";3733OS << " // Record info about match failure for later use.\n";3734OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"recording "3735"too-few-operands near miss\\n\");\n";3736OS << " OperandNearMiss =\n";3737OS << " NearMissInfo::getTooFewOperands(Formal, "3738"it->Opcode);\n";3739OS << " } else if (OperandNearMiss.getKind() != "3740"NearMissInfo::NearMissTooFewOperands) {\n";3741OS << " // If more than one operand is invalid, give up on this "3742"match entry.\n";3743OS << " DEBUG_WITH_TYPE(\n";3744OS << " \"asm-matcher\",\n";3745OS << " dbgs() << \"second invalid operand, giving up on "3746"this opcode\\n\");\n";3747OS << " MultipleInvalidOperands = true;\n";3748OS << " break;\n";3749OS << " }\n";3750OS << " } else {\n";3751OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"but formal "3752"operand not required\\n\");\n";3753OS << " if (isSubclass(Formal, OptionalMatchClass)) {\n";3754OS << " OptionalOperandsMask.set(FormalIdx);\n";3755OS << " }\n";3756OS << " }\n";3757OS << " continue;\n";3758} else {3759OS << " if (Formal == InvalidMatchClass) {\n";3760if (HasOptionalOperands) {3761OS << " OptionalOperandsMask.set(FormalIdx, " << MaxNumOperands3762<< ");\n";3763}3764OS << " break;\n";3765OS << " }\n";3766OS << " if (isSubclass(Formal, OptionalMatchClass)) {\n";3767if (HasOptionalOperands) {3768OS << " OptionalOperandsMask.set(FormalIdx);\n";3769}3770OS << " continue;\n";3771OS << " }\n";3772OS << " OperandsValid = false;\n";3773OS << " ErrorInfo = ActualIdx;\n";3774OS << " break;\n";3775}3776OS << " }\n";3777OS << " MCParsedAsmOperand &Actual = *Operands[ActualIdx];\n";3778OS << " unsigned Diag = validateOperandClass(Actual, Formal);\n";3779OS << " if (Diag == Match_Success) {\n";3780OS << " DEBUG_WITH_TYPE(\"asm-matcher\",\n";3781OS << " dbgs() << \"match success using generic "3782"matcher\\n\");\n";3783OS << " ++ActualIdx;\n";3784OS << " continue;\n";3785OS << " }\n";3786OS << " // If the generic handler indicates an invalid operand\n";3787OS << " // failure, check for a special case.\n";3788OS << " if (Diag != Match_Success) {\n";3789OS << " unsigned TargetDiag = validateTargetOperandClass(Actual, "3790"Formal);\n";3791OS << " if (TargetDiag == Match_Success) {\n";3792OS << " DEBUG_WITH_TYPE(\"asm-matcher\",\n";3793OS << " dbgs() << \"match success using target "3794"matcher\\n\");\n";3795OS << " ++ActualIdx;\n";3796OS << " continue;\n";3797OS << " }\n";3798OS << " // If the target matcher returned a specific error code use\n";3799OS << " // that, else use the one from the generic matcher.\n";3800OS << " if (TargetDiag != Match_InvalidOperand && "3801"HasRequiredFeatures)\n";3802OS << " Diag = TargetDiag;\n";3803OS << " }\n";3804OS << " // If current formal operand wasn't matched and it is optional\n"3805<< " // then try to match next formal operand\n";3806OS << " if (Diag == Match_InvalidOperand "3807<< "&& isSubclass(Formal, OptionalMatchClass)) {\n";3808if (HasOptionalOperands) {3809OS << " OptionalOperandsMask.set(FormalIdx);\n";3810}3811OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"ignoring "3812"optional operand\\n\");\n";3813OS << " continue;\n";3814OS << " }\n";38153816if (ReportMultipleNearMisses) {3817OS << " if (!OperandNearMiss) {\n";3818OS << " // If this is the first invalid operand we have seen, "3819"record some\n";3820OS << " // information about it.\n";3821OS << " DEBUG_WITH_TYPE(\n";3822OS << " \"asm-matcher\",\n";3823OS << " dbgs()\n";3824OS << " << \"operand match failed, recording near-miss with "3825"diag code \"\n";3826OS << " << Diag << \"\\n\");\n";3827OS << " OperandNearMiss =\n";3828OS << " NearMissInfo::getMissedOperand(Diag, Formal, "3829"it->Opcode, ActualIdx);\n";3830OS << " ++ActualIdx;\n";3831OS << " } else {\n";3832OS << " // If more than one operand is invalid, give up on this "3833"match entry.\n";3834OS << " DEBUG_WITH_TYPE(\n";3835OS << " \"asm-matcher\",\n";3836OS << " dbgs() << \"second operand mismatch, skipping this "3837"opcode\\n\");\n";3838OS << " MultipleInvalidOperands = true;\n";3839OS << " break;\n";3840OS << " }\n";3841OS << " }\n\n";3842} else {3843OS << " // If this operand is broken for all of the instances of "3844"this\n";3845OS << " // mnemonic, keep track of it so we can report loc info.\n";3846OS << " // If we already had a match that only failed due to a\n";3847OS << " // target predicate, that diagnostic is preferred.\n";3848OS << " if (!HadMatchOtherThanPredicate &&\n";3849OS << " (it == MnemonicRange.first || ErrorInfo <= ActualIdx)) "3850"{\n";3851OS << " if (HasRequiredFeatures && (ErrorInfo != ActualIdx || Diag "3852"!= Match_InvalidOperand))\n";3853OS << " RetCode = Diag;\n";3854OS << " ErrorInfo = ActualIdx;\n";3855OS << " }\n";3856OS << " // Otherwise, just reject this instance of the mnemonic.\n";3857OS << " OperandsValid = false;\n";3858OS << " break;\n";3859OS << " }\n\n";3860}38613862if (ReportMultipleNearMisses)3863OS << " if (MultipleInvalidOperands) {\n";3864else3865OS << " if (!OperandsValid) {\n";3866OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Opcode result: "3867"multiple \"\n";3868OS << " \"operand mismatches, "3869"ignoring \"\n";3870OS << " \"this opcode\\n\");\n";3871OS << " continue;\n";3872OS << " }\n";38733874// Emit check that the required features are available.3875OS << " if (!HasRequiredFeatures) {\n";3876if (!ReportMultipleNearMisses)3877OS << " HadMatchOtherThanFeatures = true;\n";3878OS << " FeatureBitset NewMissingFeatures = RequiredFeatures & "3879"~AvailableFeatures;\n";3880OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Missing target "3881"features:\";\n";3882OS << " for (unsigned I = 0, E = "3883"NewMissingFeatures.size(); I != E; ++I)\n";3884OS << " if (NewMissingFeatures[I])\n";3885OS << " dbgs() << ' ' << I;\n";3886OS << " dbgs() << \"\\n\");\n";3887if (ReportMultipleNearMisses) {3888OS << " FeaturesNearMiss = "3889"NearMissInfo::getMissedFeature(NewMissingFeatures);\n";3890} else {3891OS << " if (NewMissingFeatures.count() <=\n"3892" MissingFeatures.count())\n";3893OS << " MissingFeatures = NewMissingFeatures;\n";3894OS << " continue;\n";3895}3896OS << " }\n";3897OS << "\n";3898OS << " Inst.clear();\n\n";3899OS << " Inst.setOpcode(it->Opcode);\n";3900// Verify the instruction with the target-specific match predicate function.3901OS << " // We have a potential match but have not rendered the operands.\n"3902<< " // Check the target predicate to handle any context sensitive\n"3903" // constraints.\n"3904<< " // For example, Ties that are referenced multiple times must be\n"3905" // checked here to ensure the input is the same for each match\n"3906" // constraints. If we leave it any later the ties will have been\n"3907" // canonicalized\n"3908<< " unsigned MatchResult;\n"3909<< " if ((MatchResult = checkEarlyTargetMatchPredicate(Inst, "3910"Operands)) != Match_Success) {\n"3911<< " Inst.clear();\n";3912OS << " DEBUG_WITH_TYPE(\n";3913OS << " \"asm-matcher\",\n";3914OS << " dbgs() << \"Early target match predicate failed with diag "3915"code \"\n";3916OS << " << MatchResult << \"\\n\");\n";3917if (ReportMultipleNearMisses) {3918OS << " EarlyPredicateNearMiss = "3919"NearMissInfo::getMissedPredicate(MatchResult);\n";3920} else {3921OS << " RetCode = MatchResult;\n"3922<< " HadMatchOtherThanPredicate = true;\n"3923<< " continue;\n";3924}3925OS << " }\n\n";39263927if (ReportMultipleNearMisses) {3928OS << " // If we did not successfully match the operands, then we can't "3929"convert to\n";3930OS << " // an MCInst, so bail out on this instruction variant now.\n";3931OS << " if (OperandNearMiss) {\n";3932OS << " // If the operand mismatch was the only problem, reprrt it as "3933"a near-miss.\n";3934OS << " if (NearMisses && !FeaturesNearMiss && "3935"!EarlyPredicateNearMiss) {\n";3936OS << " DEBUG_WITH_TYPE(\n";3937OS << " \"asm-matcher\",\n";3938OS << " dbgs()\n";3939OS << " << \"Opcode result: one mismatched operand, adding "3940"near-miss\\n\");\n";3941OS << " NearMisses->push_back(OperandNearMiss);\n";3942OS << " } else {\n";3943OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Opcode result: "3944"multiple \"\n";3945OS << " \"types of "3946"mismatch, so not \"\n";3947OS << " \"reporting "3948"near-miss\\n\");\n";3949OS << " }\n";3950OS << " continue;\n";3951OS << " }\n\n";3952}39533954// When converting parsed operands to MCInst we need to know whether optional3955// operands were parsed or not so that we can choose the correct converter3956// function. We also need to know this when checking tied operand constraints.3957// DefaultsOffset is an array of deltas between the formal (MCInst) and the3958// actual (parsed operand array) operand indices. When all optional operands3959// are present, all elements of the array are zeros. If some of the optional3960// operands are absent, the array might look like '0, 0, 1, 1, 1, 2, 2, 3',3961// where each increment in value reflects the absence of an optional operand.3962if (HasOptionalOperands) {3963OS << " unsigned DefaultsOffset[" << (MaxNumOperands + 1)3964<< "] = { 0 };\n";3965OS << " assert(OptionalOperandsMask.size() == " << (MaxNumOperands)3966<< ");\n";3967OS << " for (unsigned i = 0, NumDefaults = 0; i < " << (MaxNumOperands)3968<< "; ++i) {\n";3969OS << " DefaultsOffset[i + 1] = NumDefaults;\n";3970OS << " NumDefaults += (OptionalOperandsMask[i] ? 1 : 0);\n";3971OS << " }\n\n";3972}39733974OS << " if (matchingInlineAsm) {\n";3975OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n";3976if (!ReportMultipleNearMisses) {3977if (HasOptionalOperands) {3978OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "3979"Operands,\n";3980OS << " DefaultsOffset, "3981"ErrorInfo))\n";3982} else {3983OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "3984"Operands,\n";3985OS << " ErrorInfo))\n";3986}3987OS << " return Match_InvalidTiedOperand;\n";3988OS << "\n";3989}3990OS << " return Match_Success;\n";3991OS << " }\n\n";3992OS << " // We have selected a definite instruction, convert the parsed\n"3993<< " // operands into the appropriate MCInst.\n";3994if (HasOptionalOperands) {3995OS << " convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands,\n"3996<< " OptionalOperandsMask, DefaultsOffset);\n";3997} else {3998OS << " convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands);\n";3999}4000OS << "\n";40014002// Verify the instruction with the target-specific match predicate function.4003OS << " // We have a potential match. Check the target predicate to\n"4004<< " // handle any context sensitive constraints.\n"4005<< " if ((MatchResult = checkTargetMatchPredicate(Inst)) !="4006<< " Match_Success) {\n"4007<< " DEBUG_WITH_TYPE(\"asm-matcher\",\n"4008<< " dbgs() << \"Target match predicate failed with "4009"diag code \"\n"4010<< " << MatchResult << \"\\n\");\n"4011<< " Inst.clear();\n";4012if (ReportMultipleNearMisses) {4013OS << " LatePredicateNearMiss = "4014"NearMissInfo::getMissedPredicate(MatchResult);\n";4015} else {4016OS << " RetCode = MatchResult;\n"4017<< " HadMatchOtherThanPredicate = true;\n"4018<< " continue;\n";4019}4020OS << " }\n\n";40214022if (ReportMultipleNearMisses) {4023OS << " int NumNearMisses = ((int)(bool)OperandNearMiss +\n";4024OS << " (int)(bool)FeaturesNearMiss +\n";4025OS << " (int)(bool)EarlyPredicateNearMiss +\n";4026OS << " (int)(bool)LatePredicateNearMiss);\n";4027OS << " if (NumNearMisses == 1) {\n";4028OS << " // We had exactly one type of near-miss, so add that to the "4029"list.\n";4030OS << " assert(!OperandNearMiss && \"OperandNearMiss was handled "4031"earlier\");\n";4032OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Opcode result: "4033"found one type of \"\n";4034OS << " \"mismatch, so "4035"reporting a \"\n";4036OS << " \"near-miss\\n\");\n";4037OS << " if (NearMisses && FeaturesNearMiss)\n";4038OS << " NearMisses->push_back(FeaturesNearMiss);\n";4039OS << " else if (NearMisses && EarlyPredicateNearMiss)\n";4040OS << " NearMisses->push_back(EarlyPredicateNearMiss);\n";4041OS << " else if (NearMisses && LatePredicateNearMiss)\n";4042OS << " NearMisses->push_back(LatePredicateNearMiss);\n";4043OS << "\n";4044OS << " continue;\n";4045OS << " } else if (NumNearMisses > 1) {\n";4046OS << " // This instruction missed in more than one way, so ignore "4047"it.\n";4048OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Opcode result: "4049"multiple \"\n";4050OS << " \"types of mismatch, "4051"so not \"\n";4052OS << " \"reporting "4053"near-miss\\n\");\n";4054OS << " continue;\n";4055OS << " }\n";4056}40574058// Call the post-processing function, if used.4059StringRef InsnCleanupFn = AsmParser->getValueAsString("AsmParserInstCleanup");4060if (!InsnCleanupFn.empty())4061OS << " " << InsnCleanupFn << "(Inst);\n";40624063if (HasDeprecation) {4064OS << " std::string Info;\n";4065OS << " if "4066"(!getParser().getTargetParser().getTargetOptions()."4067"MCNoDeprecatedWarn &&\n";4068OS << " MII.getDeprecatedInfo(Inst, getSTI(), Info)) {\n";4069OS << " SMLoc Loc = ((" << Target.getName()4070<< "Operand &)*Operands[0]).getStartLoc();\n";4071OS << " getParser().Warning(Loc, Info, std::nullopt);\n";4072OS << " }\n";4073}40744075if (!ReportMultipleNearMisses) {4076if (HasOptionalOperands) {4077OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "4078"Operands,\n";4079OS << " DefaultsOffset, "4080"ErrorInfo))\n";4081} else {4082OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "4083"Operands,\n";4084OS << " ErrorInfo))\n";4085}4086OS << " return Match_InvalidTiedOperand;\n";4087OS << "\n";4088}40894090OS << " DEBUG_WITH_TYPE(\n";4091OS << " \"asm-matcher\",\n";4092OS << " dbgs() << \"Opcode result: complete match, selecting this "4093"opcode\\n\");\n";4094OS << " return Match_Success;\n";4095OS << " }\n\n";40964097if (ReportMultipleNearMisses) {4098OS << " // No instruction variants matched exactly.\n";4099OS << " return Match_NearMisses;\n";4100} else {4101OS << " // Okay, we had no match. Try to return a useful error code.\n";4102OS << " if (HadMatchOtherThanPredicate || !HadMatchOtherThanFeatures)\n";4103OS << " return RetCode;\n\n";4104OS << " ErrorInfo = 0;\n";4105OS << " return Match_MissingFeature;\n";4106}4107OS << "}\n\n";41084109if (!Info.OperandMatchInfo.empty())4110emitCustomOperandParsing(OS, Target, Info, ClassName, StringTable,4111MaxMnemonicIndex, FeatureBitsets.size(),4112HasMnemonicFirst, *AsmParser);41134114OS << "#endif // GET_MATCHER_IMPLEMENTATION\n\n";41154116OS << "\n#ifdef GET_MNEMONIC_SPELL_CHECKER\n";4117OS << "#undef GET_MNEMONIC_SPELL_CHECKER\n\n";41184119emitMnemonicSpellChecker(OS, Target, VariantCount);41204121OS << "#endif // GET_MNEMONIC_SPELL_CHECKER\n\n";41224123OS << "\n#ifdef GET_MNEMONIC_CHECKER\n";4124OS << "#undef GET_MNEMONIC_CHECKER\n\n";41254126emitMnemonicChecker(OS, Target, VariantCount, HasMnemonicFirst,4127HasMnemonicAliases);41284129OS << "#endif // GET_MNEMONIC_CHECKER\n\n";4130}41314132static TableGen::Emitter::OptClass<AsmMatcherEmitter>4133X("gen-asm-matcher", "Generate assembly instruction matcher");413441354136