1198090Srdivacky//===- AsmMatcherEmitter.cpp - Generate an assembly matcher ---------------===// 2198090Srdivacky// 3198090Srdivacky// The LLVM Compiler Infrastructure 4198090Srdivacky// 5198090Srdivacky// This file is distributed under the University of Illinois Open Source 6198090Srdivacky// License. See LICENSE.TXT for details. 7198090Srdivacky// 8198090Srdivacky//===----------------------------------------------------------------------===// 9198090Srdivacky// 10198090Srdivacky// This tablegen backend emits a target specifier matcher for converting parsed 11218893Sdim// assembly operands in the MCInst structures. It also emits a matcher for 12218893Sdim// custom operand parsing. 13198090Srdivacky// 14218893Sdim// Converting assembly operands into MCInst structures 15218893Sdim// --------------------------------------------------- 16218893Sdim// 17198090Srdivacky// The input to the target specific matcher is a list of literal tokens and 18198090Srdivacky// operands. The target specific parser should generally eliminate any syntax 19198090Srdivacky// which is not relevant for matching; for example, comma tokens should have 20198090Srdivacky// already been consumed and eliminated by the parser. Most instructions will 21198090Srdivacky// end up with a single literal token (the instruction name) and some number of 22198090Srdivacky// operands. 23198090Srdivacky// 24198090Srdivacky// Some example inputs, for X86: 25198090Srdivacky// 'addl' (immediate ...) (register ...) 26198090Srdivacky// 'add' (immediate ...) (memory ...) 27218893Sdim// 'call' '*' %epc 28198090Srdivacky// 29198090Srdivacky// The assembly matcher is responsible for converting this input into a precise 30198090Srdivacky// machine instruction (i.e., an instruction with a well defined encoding). This 31198090Srdivacky// mapping has several properties which complicate matching: 32198090Srdivacky// 33198090Srdivacky// - It may be ambiguous; many architectures can legally encode particular 34198090Srdivacky// variants of an instruction in different ways (for example, using a smaller 35198090Srdivacky// encoding for small immediates). Such ambiguities should never be 36198090Srdivacky// arbitrarily resolved by the assembler, the assembler is always responsible 37198090Srdivacky// for choosing the "best" available instruction. 38198090Srdivacky// 39198090Srdivacky// - It may depend on the subtarget or the assembler context. Instructions 40198090Srdivacky// which are invalid for the current mode, but otherwise unambiguous (e.g., 41198090Srdivacky// an SSE instruction in a file being assembled for i486) should be accepted 42198090Srdivacky// and rejected by the assembler front end. However, if the proper encoding 43198090Srdivacky// for an instruction is dependent on the assembler context then the matcher 44198090Srdivacky// is responsible for selecting the correct machine instruction for the 45198090Srdivacky// current mode. 46198090Srdivacky// 47198090Srdivacky// The core matching algorithm attempts to exploit the regularity in most 48198090Srdivacky// instruction sets to quickly determine the set of possibly matching 49198090Srdivacky// instructions, and the simplify the generated code. Additionally, this helps 50198090Srdivacky// to ensure that the ambiguities are intentionally resolved by the user. 51198090Srdivacky// 52198090Srdivacky// The matching is divided into two distinct phases: 53198090Srdivacky// 54198090Srdivacky// 1. Classification: Each operand is mapped to the unique set which (a) 55198090Srdivacky// contains it, and (b) is the largest such subset for which a single 56198090Srdivacky// instruction could match all members. 57198090Srdivacky// 58198090Srdivacky// For register classes, we can generate these subgroups automatically. For 59198090Srdivacky// arbitrary operands, we expect the user to define the classes and their 60198090Srdivacky// relations to one another (for example, 8-bit signed immediates as a 61198090Srdivacky// subset of 32-bit immediates). 62198090Srdivacky// 63198090Srdivacky// By partitioning the operands in this way, we guarantee that for any 64198090Srdivacky// tuple of classes, any single instruction must match either all or none 65198090Srdivacky// of the sets of operands which could classify to that tuple. 66198090Srdivacky// 67198090Srdivacky// In addition, the subset relation amongst classes induces a partial order 68198090Srdivacky// on such tuples, which we use to resolve ambiguities. 69198090Srdivacky// 70198090Srdivacky// 2. The input can now be treated as a tuple of classes (static tokens are 71198090Srdivacky// simple singleton sets). Each such tuple should generally map to a single 72198090Srdivacky// instruction (we currently ignore cases where this isn't true, whee!!!), 73198090Srdivacky// which we can emit a simple matcher for. 74198090Srdivacky// 75218893Sdim// Custom Operand Parsing 76218893Sdim// ---------------------- 77218893Sdim// 78218893Sdim// Some targets need a custom way to parse operands, some specific instructions 79218893Sdim// can contain arguments that can represent processor flags and other kinds of 80245431Sdim// identifiers that need to be mapped to specific values in the final encoded 81218893Sdim// instructions. The target specific custom operand parsing works in the 82218893Sdim// following way: 83218893Sdim// 84218893Sdim// 1. A operand match table is built, each entry contains a mnemonic, an 85218893Sdim// operand class, a mask for all operand positions for that same 86218893Sdim// class/mnemonic and target features to be checked while trying to match. 87218893Sdim// 88218893Sdim// 2. The operand matcher will try every possible entry with the same 89218893Sdim// mnemonic and will check if the target feature for this mnemonic also 90218893Sdim// matches. After that, if the operand to be matched has its index 91221345Sdim// present in the mask, a successful match occurs. Otherwise, fallback 92218893Sdim// to the regular operand parsing. 93218893Sdim// 94218893Sdim// 3. For a match success, each operand class that has a 'ParserMethod' 95218893Sdim// becomes part of a switch from where the custom method is called. 96218893Sdim// 97198090Srdivacky//===----------------------------------------------------------------------===// 98198090Srdivacky 99198090Srdivacky#include "CodeGenTarget.h" 100198090Srdivacky#include "llvm/ADT/OwningPtr.h" 101218893Sdim#include "llvm/ADT/PointerUnion.h" 102252723Sdim#include "llvm/ADT/STLExtras.h" 103218893Sdim#include "llvm/ADT/SmallPtrSet.h" 104198090Srdivacky#include "llvm/ADT/SmallVector.h" 105198090Srdivacky#include "llvm/ADT/StringExtras.h" 106198090Srdivacky#include "llvm/Support/CommandLine.h" 107198090Srdivacky#include "llvm/Support/Debug.h" 108235633Sdim#include "llvm/Support/ErrorHandling.h" 109226890Sdim#include "llvm/TableGen/Error.h" 110226890Sdim#include "llvm/TableGen/Record.h" 111245431Sdim#include "llvm/TableGen/StringMatcher.h" 112263509Sdim#include "llvm/TableGen/StringToOffsetTable.h" 113245431Sdim#include "llvm/TableGen/TableGenBackend.h" 114245431Sdim#include <cassert> 115263509Sdim#include <cctype> 116198090Srdivacky#include <map> 117198090Srdivacky#include <set> 118263509Sdim#include <sstream> 119198090Srdivackyusing namespace llvm; 120198090Srdivacky 121198090Srdivackystatic cl::opt<std::string> 122198090SrdivackyMatchPrefix("match-prefix", cl::init(""), 123198090Srdivacky cl::desc("Only match instructions with the given prefix")); 124198090Srdivacky 125198090Srdivackynamespace { 126218893Sdimclass AsmMatcherInfo; 127212904Sdimstruct SubtargetFeatureInfo; 128212904Sdim 129263509Sdim// Register sets are used as keys in some second-order sets TableGen creates 130263509Sdim// when generating its data structures. This means that the order of two 131263509Sdim// RegisterSets can be seen in the outputted AsmMatcher tables occasionally, and 132263509Sdim// can even affect compiler output (at least seen in diagnostics produced when 133263509Sdim// all matches fail). So we use a type that sorts them consistently. 134263509Sdimtypedef std::set<Record*, LessRecordByID> RegisterSet; 135263509Sdim 136245431Sdimclass AsmMatcherEmitter { 137245431Sdim RecordKeeper &Records; 138245431Sdimpublic: 139245431Sdim AsmMatcherEmitter(RecordKeeper &R) : Records(R) {} 140245431Sdim 141245431Sdim void run(raw_ostream &o); 142245431Sdim}; 143245431Sdim 144198090Srdivacky/// ClassInfo - Helper class for storing the information about a particular 145198090Srdivacky/// class of operands which can be matched. 146198090Srdivackystruct ClassInfo { 147198090Srdivacky enum ClassInfoKind { 148198090Srdivacky /// Invalid kind, for use as a sentinel value. 149198090Srdivacky Invalid = 0, 150198090Srdivacky 151198090Srdivacky /// The class for a particular token. 152198090Srdivacky Token, 153198090Srdivacky 154198090Srdivacky /// The (first) register class, subsequent register classes are 155198090Srdivacky /// RegisterClass0+1, and so on. 156198090Srdivacky RegisterClass0, 157198090Srdivacky 158198090Srdivacky /// The (first) user defined class, subsequent user defined classes are 159198090Srdivacky /// UserClass0+1, and so on. 160198090Srdivacky UserClass0 = 1<<16 161198090Srdivacky }; 162198090Srdivacky 163198090Srdivacky /// Kind - The class kind, which is either a predefined kind, or (UserClass0 + 164198090Srdivacky /// N) for the Nth user defined class. 165198090Srdivacky unsigned Kind; 166198090Srdivacky 167198090Srdivacky /// SuperClasses - The super classes of this class. Note that for simplicities 168198090Srdivacky /// sake user operands only record their immediate super class, while register 169198090Srdivacky /// operands include all superclasses. 170198090Srdivacky std::vector<ClassInfo*> SuperClasses; 171198090Srdivacky 172198090Srdivacky /// Name - The full class name, suitable for use in an enum. 173198090Srdivacky std::string Name; 174198090Srdivacky 175198090Srdivacky /// ClassName - The unadorned generic name for this class (e.g., Token). 176198090Srdivacky std::string ClassName; 177198090Srdivacky 178198090Srdivacky /// ValueName - The name of the value this class represents; for a token this 179198090Srdivacky /// is the literal token string, for an operand it is the TableGen class (or 180198090Srdivacky /// empty if this is a derived class). 181198090Srdivacky std::string ValueName; 182198090Srdivacky 183198090Srdivacky /// PredicateMethod - The name of the operand method to test whether the 184198090Srdivacky /// operand matches this class; this is not valid for Token or register kinds. 185198090Srdivacky std::string PredicateMethod; 186198090Srdivacky 187198090Srdivacky /// RenderMethod - The name of the operand method to add this operand to an 188198090Srdivacky /// MCInst; this is not valid for Token or register kinds. 189198090Srdivacky std::string RenderMethod; 190198090Srdivacky 191218893Sdim /// ParserMethod - The name of the operand method to do a target specific 192218893Sdim /// parsing on the operand. 193218893Sdim std::string ParserMethod; 194218893Sdim 195198090Srdivacky /// For register classes, the records for all the registers in this class. 196263509Sdim RegisterSet Registers; 197198090Srdivacky 198245431Sdim /// For custom match classes, he diagnostic kind for when the predicate fails. 199245431Sdim std::string DiagnosticType; 200198090Srdivackypublic: 201198090Srdivacky /// isRegisterClass() - Check if this is a register class. 202198090Srdivacky bool isRegisterClass() const { 203198090Srdivacky return Kind >= RegisterClass0 && Kind < UserClass0; 204198090Srdivacky } 205198090Srdivacky 206198090Srdivacky /// isUserClass() - Check if this is a user defined class. 207198090Srdivacky bool isUserClass() const { 208198090Srdivacky return Kind >= UserClass0; 209198090Srdivacky } 210198090Srdivacky 211245431Sdim /// isRelatedTo - Check whether this class is "related" to \p RHS. Classes 212198090Srdivacky /// are related if they are in the same class hierarchy. 213198090Srdivacky bool isRelatedTo(const ClassInfo &RHS) const { 214198090Srdivacky // Tokens are only related to tokens. 215198090Srdivacky if (Kind == Token || RHS.Kind == Token) 216198090Srdivacky return Kind == Token && RHS.Kind == Token; 217198090Srdivacky 218198090Srdivacky // Registers classes are only related to registers classes, and only if 219198090Srdivacky // their intersection is non-empty. 220198090Srdivacky if (isRegisterClass() || RHS.isRegisterClass()) { 221198090Srdivacky if (!isRegisterClass() || !RHS.isRegisterClass()) 222198090Srdivacky return false; 223198090Srdivacky 224263509Sdim RegisterSet Tmp; 225263509Sdim std::insert_iterator<RegisterSet> II(Tmp, Tmp.begin()); 226218893Sdim std::set_intersection(Registers.begin(), Registers.end(), 227198090Srdivacky RHS.Registers.begin(), RHS.Registers.end(), 228263509Sdim II, LessRecordByID()); 229198090Srdivacky 230198090Srdivacky return !Tmp.empty(); 231198090Srdivacky } 232198090Srdivacky 233198090Srdivacky // Otherwise we have two users operands; they are related if they are in the 234198090Srdivacky // same class hierarchy. 235198090Srdivacky // 236198090Srdivacky // FIXME: This is an oversimplification, they should only be related if they 237198090Srdivacky // intersect, however we don't have that information. 238198090Srdivacky assert(isUserClass() && RHS.isUserClass() && "Unexpected class!"); 239198090Srdivacky const ClassInfo *Root = this; 240198090Srdivacky while (!Root->SuperClasses.empty()) 241198090Srdivacky Root = Root->SuperClasses.front(); 242198090Srdivacky 243198090Srdivacky const ClassInfo *RHSRoot = &RHS; 244198090Srdivacky while (!RHSRoot->SuperClasses.empty()) 245198090Srdivacky RHSRoot = RHSRoot->SuperClasses.front(); 246218893Sdim 247198090Srdivacky return Root == RHSRoot; 248198090Srdivacky } 249198090Srdivacky 250245431Sdim /// isSubsetOf - Test whether this class is a subset of \p RHS. 251198090Srdivacky bool isSubsetOf(const ClassInfo &RHS) const { 252198090Srdivacky // This is a subset of RHS if it is the same class... 253198090Srdivacky if (this == &RHS) 254198090Srdivacky return true; 255198090Srdivacky 256198090Srdivacky // ... or if any of its super classes are a subset of RHS. 257198090Srdivacky for (std::vector<ClassInfo*>::const_iterator it = SuperClasses.begin(), 258198090Srdivacky ie = SuperClasses.end(); it != ie; ++it) 259198090Srdivacky if ((*it)->isSubsetOf(RHS)) 260198090Srdivacky return true; 261198090Srdivacky 262198090Srdivacky return false; 263198090Srdivacky } 264198090Srdivacky 265198090Srdivacky /// operator< - Compare two classes. 266198090Srdivacky bool operator<(const ClassInfo &RHS) const { 267208599Srdivacky if (this == &RHS) 268208599Srdivacky return false; 269208599Srdivacky 270198090Srdivacky // Unrelated classes can be ordered by kind. 271198090Srdivacky if (!isRelatedTo(RHS)) 272198090Srdivacky return Kind < RHS.Kind; 273198090Srdivacky 274198090Srdivacky switch (Kind) { 275198090Srdivacky case Invalid: 276235633Sdim llvm_unreachable("Invalid kind!"); 277198090Srdivacky 278198090Srdivacky default: 279221345Sdim // This class precedes the RHS if it is a proper subset of the RHS. 280208599Srdivacky if (isSubsetOf(RHS)) 281210299Sed return true; 282208599Srdivacky if (RHS.isSubsetOf(*this)) 283210299Sed return false; 284208599Srdivacky 285208599Srdivacky // Otherwise, order by name to ensure we have a total ordering. 286208599Srdivacky return ValueName < RHS.ValueName; 287198090Srdivacky } 288198090Srdivacky } 289198090Srdivacky}; 290198090Srdivacky 291245431Sdimnamespace { 292245431Sdim/// Sort ClassInfo pointers independently of pointer value. 293245431Sdimstruct LessClassInfoPtr { 294245431Sdim bool operator()(const ClassInfo *LHS, const ClassInfo *RHS) const { 295245431Sdim return *LHS < *RHS; 296245431Sdim } 297245431Sdim}; 298245431Sdim} 299245431Sdim 300218893Sdim/// MatchableInfo - Helper class for storing the necessary information for an 301218893Sdim/// instruction or alias which is capable of being matched. 302218893Sdimstruct MatchableInfo { 303218893Sdim struct AsmOperand { 304218893Sdim /// Token - This is the token that the operand came from. 305218893Sdim StringRef Token; 306218893Sdim 307198090Srdivacky /// The unique class instance this operand should match. 308198090Srdivacky ClassInfo *Class; 309198090Srdivacky 310218893Sdim /// The operand name this is, if anything. 311218893Sdim StringRef SrcOpName; 312218893Sdim 313218893Sdim /// The suboperand index within SrcOpName, or -1 for the entire operand. 314218893Sdim int SubOpIdx; 315218893Sdim 316235633Sdim /// Register record if this token is singleton register. 317235633Sdim Record *SingletonReg; 318235633Sdim 319235633Sdim explicit AsmOperand(StringRef T) : Token(T), Class(0), SubOpIdx(-1), 320235633Sdim SingletonReg(0) {} 321198090Srdivacky }; 322198090Srdivacky 323218893Sdim /// ResOperand - This represents a single operand in the result instruction 324218893Sdim /// generated by the match. In cases (like addressing modes) where a single 325218893Sdim /// assembler operand expands to multiple MCOperands, this represents the 326218893Sdim /// single assembler operand, not the MCOperand. 327218893Sdim struct ResOperand { 328218893Sdim enum { 329218893Sdim /// RenderAsmOperand - This represents an operand result that is 330218893Sdim /// generated by calling the render method on the assembly operand. The 331218893Sdim /// corresponding AsmOperand is specified by AsmOperandNum. 332218893Sdim RenderAsmOperand, 333198090Srdivacky 334218893Sdim /// TiedOperand - This represents a result operand that is a duplicate of 335218893Sdim /// a previous result operand. 336218893Sdim TiedOperand, 337198090Srdivacky 338218893Sdim /// ImmOperand - This represents an immediate value that is dumped into 339218893Sdim /// the operand. 340218893Sdim ImmOperand, 341218893Sdim 342218893Sdim /// RegOperand - This represents a fixed register that is dumped in. 343218893Sdim RegOperand 344218893Sdim } Kind; 345218893Sdim 346218893Sdim union { 347218893Sdim /// This is the operand # in the AsmOperands list that this should be 348218893Sdim /// copied from. 349218893Sdim unsigned AsmOperandNum; 350218893Sdim 351218893Sdim /// TiedOperandNum - This is the (earlier) result operand that should be 352218893Sdim /// copied from. 353218893Sdim unsigned TiedOperandNum; 354218893Sdim 355218893Sdim /// ImmVal - This is the immediate value added to the instruction. 356218893Sdim int64_t ImmVal; 357218893Sdim 358218893Sdim /// Register - This is the register record. 359218893Sdim Record *Register; 360218893Sdim }; 361218893Sdim 362218893Sdim /// MINumOperands - The number of MCInst operands populated by this 363218893Sdim /// operand. 364218893Sdim unsigned MINumOperands; 365218893Sdim 366218893Sdim static ResOperand getRenderedOp(unsigned AsmOpNum, unsigned NumOperands) { 367218893Sdim ResOperand X; 368218893Sdim X.Kind = RenderAsmOperand; 369218893Sdim X.AsmOperandNum = AsmOpNum; 370218893Sdim X.MINumOperands = NumOperands; 371218893Sdim return X; 372218893Sdim } 373218893Sdim 374218893Sdim static ResOperand getTiedOp(unsigned TiedOperandNum) { 375218893Sdim ResOperand X; 376218893Sdim X.Kind = TiedOperand; 377218893Sdim X.TiedOperandNum = TiedOperandNum; 378218893Sdim X.MINumOperands = 1; 379218893Sdim return X; 380218893Sdim } 381218893Sdim 382218893Sdim static ResOperand getImmOp(int64_t Val) { 383218893Sdim ResOperand X; 384218893Sdim X.Kind = ImmOperand; 385218893Sdim X.ImmVal = Val; 386218893Sdim X.MINumOperands = 1; 387218893Sdim return X; 388218893Sdim } 389218893Sdim 390218893Sdim static ResOperand getRegOp(Record *Reg) { 391218893Sdim ResOperand X; 392218893Sdim X.Kind = RegOperand; 393218893Sdim X.Register = Reg; 394218893Sdim X.MINumOperands = 1; 395218893Sdim return X; 396218893Sdim } 397218893Sdim }; 398218893Sdim 399235633Sdim /// AsmVariantID - Target's assembly syntax variant no. 400235633Sdim int AsmVariantID; 401235633Sdim 402218893Sdim /// TheDef - This is the definition of the instruction or InstAlias that this 403218893Sdim /// matchable came from. 404218893Sdim Record *const TheDef; 405218893Sdim 406218893Sdim /// DefRec - This is the definition that it came from. 407218893Sdim PointerUnion<const CodeGenInstruction*, const CodeGenInstAlias*> DefRec; 408218893Sdim 409218893Sdim const CodeGenInstruction *getResultInst() const { 410218893Sdim if (DefRec.is<const CodeGenInstruction*>()) 411218893Sdim return DefRec.get<const CodeGenInstruction*>(); 412218893Sdim return DefRec.get<const CodeGenInstAlias*>()->ResultInst; 413218893Sdim } 414218893Sdim 415218893Sdim /// ResOperands - This is the operand list that should be built for the result 416218893Sdim /// MCInst. 417245431Sdim SmallVector<ResOperand, 8> ResOperands; 418218893Sdim 419198090Srdivacky /// AsmString - The assembly string for this instruction (with variants 420218893Sdim /// removed), e.g. "movsx $src, $dst". 421198090Srdivacky std::string AsmString; 422198090Srdivacky 423218893Sdim /// Mnemonic - This is the first token of the matched instruction, its 424218893Sdim /// mnemonic. 425218893Sdim StringRef Mnemonic; 426198090Srdivacky 427218893Sdim /// AsmOperands - The textual operands that this instruction matches, 428218893Sdim /// annotated with a class and where in the OperandList they were defined. 429218893Sdim /// This directly corresponds to the tokenized AsmString after the mnemonic is 430218893Sdim /// removed. 431245431Sdim SmallVector<AsmOperand, 8> AsmOperands; 432198090Srdivacky 433212904Sdim /// Predicates - The required subtarget features to match this instruction. 434212904Sdim SmallVector<SubtargetFeatureInfo*, 4> RequiredFeatures; 435212904Sdim 436198090Srdivacky /// ConversionFnKind - The enum value which is passed to the generated 437245431Sdim /// convertToMCInst to convert parsed operands into an MCInst for this 438198090Srdivacky /// function. 439198090Srdivacky std::string ConversionFnKind; 440198090Srdivacky 441263509Sdim /// If this instruction is deprecated in some form. 442263509Sdim bool HasDeprecation; 443263509Sdim 444218893Sdim MatchableInfo(const CodeGenInstruction &CGI) 445235633Sdim : AsmVariantID(0), TheDef(CGI.TheDef), DefRec(&CGI), 446235633Sdim AsmString(CGI.AsmString) { 447218893Sdim } 448198090Srdivacky 449218893Sdim MatchableInfo(const CodeGenInstAlias *Alias) 450235633Sdim : AsmVariantID(0), TheDef(Alias->TheDef), DefRec(Alias), 451235633Sdim AsmString(Alias->AsmString) { 452218893Sdim } 453218893Sdim 454245431Sdim // Two-operand aliases clone from the main matchable, but mark the second 455245431Sdim // operand as a tied operand of the first for purposes of the assembler. 456245431Sdim void formTwoOperandAlias(StringRef Constraint); 457245431Sdim 458245431Sdim void initialize(const AsmMatcherInfo &Info, 459235633Sdim SmallPtrSet<Record*, 16> &SingletonRegisters, 460235633Sdim int AsmVariantNo, std::string &RegisterPrefix); 461218893Sdim 462245431Sdim /// validate - Return true if this matchable is a valid thing to match against 463218893Sdim /// and perform a bunch of validity checking. 464245431Sdim bool validate(StringRef CommentDelimiter, bool Hack) const; 465218893Sdim 466235633Sdim /// extractSingletonRegisterForAsmOperand - Extract singleton register, 467235633Sdim /// if present, from specified token. 468235633Sdim void 469235633Sdim extractSingletonRegisterForAsmOperand(unsigned i, const AsmMatcherInfo &Info, 470235633Sdim std::string &RegisterPrefix); 471218893Sdim 472245431Sdim /// findAsmOperand - Find the AsmOperand with the specified name and 473218893Sdim /// suboperand index. 474245431Sdim int findAsmOperand(StringRef N, int SubOpIdx) const { 475218893Sdim for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) 476218893Sdim if (N == AsmOperands[i].SrcOpName && 477218893Sdim SubOpIdx == AsmOperands[i].SubOpIdx) 478218893Sdim return i; 479218893Sdim return -1; 480218893Sdim } 481218893Sdim 482245431Sdim /// findAsmOperandNamed - Find the first AsmOperand with the specified name. 483218893Sdim /// This does not check the suboperand index. 484245431Sdim int findAsmOperandNamed(StringRef N) const { 485218893Sdim for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) 486218893Sdim if (N == AsmOperands[i].SrcOpName) 487218893Sdim return i; 488218893Sdim return -1; 489218893Sdim } 490218893Sdim 491245431Sdim void buildInstructionResultOperands(); 492245431Sdim void buildAliasResultOperands(); 493218893Sdim 494218893Sdim /// operator< - Compare two matchables. 495218893Sdim bool operator<(const MatchableInfo &RHS) const { 496218893Sdim // The primary comparator is the instruction mnemonic. 497218893Sdim if (Mnemonic != RHS.Mnemonic) 498218893Sdim return Mnemonic < RHS.Mnemonic; 499218893Sdim 500218893Sdim if (AsmOperands.size() != RHS.AsmOperands.size()) 501218893Sdim return AsmOperands.size() < RHS.AsmOperands.size(); 502218893Sdim 503198090Srdivacky // Compare lexicographically by operand. The matcher validates that other 504245431Sdim // orderings wouldn't be ambiguous using \see couldMatchAmbiguouslyWith(). 505218893Sdim for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { 506218893Sdim if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class) 507198090Srdivacky return true; 508218893Sdim if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class) 509198090Srdivacky return false; 510198090Srdivacky } 511198090Srdivacky 512245431Sdim // Give matches that require more features higher precedence. This is useful 513245431Sdim // because we cannot define AssemblerPredicates with the negation of 514245431Sdim // processor features. For example, ARM v6 "nop" may be either a HINT or 515245431Sdim // MOV. With v6, we want to match HINT. The assembler has no way to 516245431Sdim // predicate MOV under "NoV6", but HINT will always match first because it 517245431Sdim // requires V6 while MOV does not. 518245431Sdim if (RequiredFeatures.size() != RHS.RequiredFeatures.size()) 519245431Sdim return RequiredFeatures.size() > RHS.RequiredFeatures.size(); 520245431Sdim 521198090Srdivacky return false; 522198090Srdivacky } 523198090Srdivacky 524245431Sdim /// couldMatchAmbiguouslyWith - Check whether this matchable could 525245431Sdim /// ambiguously match the same set of operands as \p RHS (without being a 526198090Srdivacky /// strictly superior match). 527245431Sdim bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS) { 528218893Sdim // The primary comparator is the instruction mnemonic. 529218893Sdim if (Mnemonic != RHS.Mnemonic) 530218893Sdim return false; 531218893Sdim 532198090Srdivacky // The number of operands is unambiguous. 533218893Sdim if (AsmOperands.size() != RHS.AsmOperands.size()) 534198090Srdivacky return false; 535198090Srdivacky 536202878Srdivacky // Otherwise, make sure the ordering of the two instructions is unambiguous 537202878Srdivacky // by checking that either (a) a token or operand kind discriminates them, 538202878Srdivacky // or (b) the ordering among equivalent kinds is consistent. 539202878Srdivacky 540198090Srdivacky // Tokens and operand kinds are unambiguous (assuming a correct target 541198090Srdivacky // specific parser). 542218893Sdim for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) 543218893Sdim if (AsmOperands[i].Class->Kind != RHS.AsmOperands[i].Class->Kind || 544218893Sdim AsmOperands[i].Class->Kind == ClassInfo::Token) 545218893Sdim if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class || 546218893Sdim *RHS.AsmOperands[i].Class < *AsmOperands[i].Class) 547198090Srdivacky return false; 548218893Sdim 549198090Srdivacky // Otherwise, this operand could commute if all operands are equivalent, or 550198090Srdivacky // there is a pair of operands that compare less than and a pair that 551198090Srdivacky // compare greater than. 552198090Srdivacky bool HasLT = false, HasGT = false; 553218893Sdim for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { 554218893Sdim if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class) 555198090Srdivacky HasLT = true; 556218893Sdim if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class) 557198090Srdivacky HasGT = true; 558198090Srdivacky } 559198090Srdivacky 560198090Srdivacky return !(HasLT ^ HasGT); 561198090Srdivacky } 562198090Srdivacky 563198090Srdivacky void dump(); 564218893Sdim 565218893Sdimprivate: 566245431Sdim void tokenizeAsmString(const AsmMatcherInfo &Info); 567198090Srdivacky}; 568198090Srdivacky 569212904Sdim/// SubtargetFeatureInfo - Helper class for storing information on a subtarget 570212904Sdim/// feature which participates in instruction matching. 571212904Sdimstruct SubtargetFeatureInfo { 572212904Sdim /// \brief The predicate record for this feature. 573212904Sdim Record *TheDef; 574212904Sdim 575212904Sdim /// \brief An unique index assigned to represent this feature. 576212904Sdim unsigned Index; 577212904Sdim 578218893Sdim SubtargetFeatureInfo(Record *D, unsigned Idx) : TheDef(D), Index(Idx) {} 579218893Sdim 580212904Sdim /// \brief The name of the enumerated constant identifying this feature. 581218893Sdim std::string getEnumName() const { 582218893Sdim return "Feature_" + TheDef->getName(); 583218893Sdim } 584212904Sdim}; 585212904Sdim 586218893Sdimstruct OperandMatchEntry { 587218893Sdim unsigned OperandMask; 588218893Sdim MatchableInfo* MI; 589218893Sdim ClassInfo *CI; 590218893Sdim 591245431Sdim static OperandMatchEntry create(MatchableInfo* mi, ClassInfo *ci, 592218893Sdim unsigned opMask) { 593218893Sdim OperandMatchEntry X; 594218893Sdim X.OperandMask = opMask; 595218893Sdim X.CI = ci; 596218893Sdim X.MI = mi; 597218893Sdim return X; 598218893Sdim } 599218893Sdim}; 600218893Sdim 601218893Sdim 602198090Srdivackyclass AsmMatcherInfo { 603198090Srdivackypublic: 604218893Sdim /// Tracked Records 605218893Sdim RecordKeeper &Records; 606218893Sdim 607198090Srdivacky /// The tablegen AsmParser record. 608198090Srdivacky Record *AsmParser; 609198090Srdivacky 610218893Sdim /// Target - The target information. 611218893Sdim CodeGenTarget &Target; 612198090Srdivacky 613198090Srdivacky /// The classes which are needed for matching. 614198090Srdivacky std::vector<ClassInfo*> Classes; 615198090Srdivacky 616218893Sdim /// The information on the matchables to match. 617218893Sdim std::vector<MatchableInfo*> Matchables; 618218893Sdim 619218893Sdim /// Info for custom matching operands by user defined methods. 620218893Sdim std::vector<OperandMatchEntry> OperandMatchInfo; 621218893Sdim 622198090Srdivacky /// Map of Register records to their class information. 623245431Sdim typedef std::map<Record*, ClassInfo*, LessRecordByID> RegisterClassesTy; 624245431Sdim RegisterClassesTy RegisterClasses; 625198090Srdivacky 626212904Sdim /// Map of Predicate records to their subtarget information. 627263509Sdim std::map<Record*, SubtargetFeatureInfo*, LessRecordByID> SubtargetFeatures; 628212904Sdim 629245431Sdim /// Map of AsmOperandClass records to their class information. 630245431Sdim std::map<Record*, ClassInfo*> AsmOperandClasses; 631245431Sdim 632198090Srdivackyprivate: 633198090Srdivacky /// Map of token to class information which has already been constructed. 634198090Srdivacky std::map<std::string, ClassInfo*> TokenClasses; 635198090Srdivacky 636198090Srdivacky /// Map of RegisterClass records to their class information. 637198090Srdivacky std::map<Record*, ClassInfo*> RegisterClassClasses; 638198090Srdivacky 639198090Srdivackyprivate: 640198090Srdivacky /// getTokenClass - Lookup or create the class for the given token. 641203954Srdivacky ClassInfo *getTokenClass(StringRef Token); 642198090Srdivacky 643198090Srdivacky /// getOperandClass - Lookup or create the class for the given operand. 644218893Sdim ClassInfo *getOperandClass(const CGIOperandList::OperandInfo &OI, 645235633Sdim int SubOpIdx); 646235633Sdim ClassInfo *getOperandClass(Record *Rec, int SubOpIdx); 647198090Srdivacky 648245431Sdim /// buildRegisterClasses - Build the ClassInfo* instances for register 649198090Srdivacky /// classes. 650245431Sdim void buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters); 651198090Srdivacky 652245431Sdim /// buildOperandClasses - Build the ClassInfo* instances for user defined 653198090Srdivacky /// operand classes. 654245431Sdim void buildOperandClasses(); 655198090Srdivacky 656245431Sdim void buildInstructionOperandReference(MatchableInfo *II, StringRef OpName, 657218893Sdim unsigned AsmOpIdx); 658245431Sdim void buildAliasOperandReference(MatchableInfo *II, StringRef OpName, 659218893Sdim MatchableInfo::AsmOperand &Op); 660218893Sdim 661198090Srdivackypublic: 662218893Sdim AsmMatcherInfo(Record *AsmParser, 663218893Sdim CodeGenTarget &Target, 664218893Sdim RecordKeeper &Records); 665198090Srdivacky 666245431Sdim /// buildInfo - Construct the various tables used during matching. 667245431Sdim void buildInfo(); 668218893Sdim 669245431Sdim /// buildOperandMatchInfo - Build the necessary information to handle user 670218893Sdim /// defined operand parsing methods. 671245431Sdim void buildOperandMatchInfo(); 672218893Sdim 673218893Sdim /// getSubtargetFeature - Lookup or create the subtarget feature info for the 674218893Sdim /// given operand. 675218893Sdim SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const { 676218893Sdim assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!"); 677263509Sdim std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator I = 678218893Sdim SubtargetFeatures.find(Def); 679218893Sdim return I == SubtargetFeatures.end() ? 0 : I->second; 680218893Sdim } 681218893Sdim 682218893Sdim RecordKeeper &getRecords() const { 683218893Sdim return Records; 684218893Sdim } 685198090Srdivacky}; 686198090Srdivacky 687245431Sdim} // End anonymous namespace 688198090Srdivacky 689218893Sdimvoid MatchableInfo::dump() { 690218893Sdim errs() << TheDef->getName() << " -- " << "flattened:\"" << AsmString <<"\"\n"; 691218893Sdim 692218893Sdim for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { 693218893Sdim AsmOperand &Op = AsmOperands[i]; 694218893Sdim errs() << " op[" << i << "] = " << Op.Class->ClassName << " - "; 695218893Sdim errs() << '\"' << Op.Token << "\"\n"; 696198090Srdivacky } 697218893Sdim} 698198090Srdivacky 699245431Sdimstatic std::pair<StringRef, StringRef> 700245431SdimparseTwoOperandConstraint(StringRef S, ArrayRef<SMLoc> Loc) { 701245431Sdim // Split via the '='. 702245431Sdim std::pair<StringRef, StringRef> Ops = S.split('='); 703245431Sdim if (Ops.second == "") 704245431Sdim PrintFatalError(Loc, "missing '=' in two-operand alias constraint"); 705245431Sdim // Trim whitespace and the leading '$' on the operand names. 706245431Sdim size_t start = Ops.first.find_first_of('$'); 707245431Sdim if (start == std::string::npos) 708245431Sdim PrintFatalError(Loc, "expected '$' prefix on asm operand name"); 709245431Sdim Ops.first = Ops.first.slice(start + 1, std::string::npos); 710245431Sdim size_t end = Ops.first.find_last_of(" \t"); 711245431Sdim Ops.first = Ops.first.slice(0, end); 712245431Sdim // Now the second operand. 713245431Sdim start = Ops.second.find_first_of('$'); 714245431Sdim if (start == std::string::npos) 715245431Sdim PrintFatalError(Loc, "expected '$' prefix on asm operand name"); 716245431Sdim Ops.second = Ops.second.slice(start + 1, std::string::npos); 717245431Sdim end = Ops.second.find_last_of(" \t"); 718245431Sdim Ops.first = Ops.first.slice(0, end); 719245431Sdim return Ops; 720245431Sdim} 721245431Sdim 722245431Sdimvoid MatchableInfo::formTwoOperandAlias(StringRef Constraint) { 723245431Sdim // Figure out which operands are aliased and mark them as tied. 724245431Sdim std::pair<StringRef, StringRef> Ops = 725245431Sdim parseTwoOperandConstraint(Constraint, TheDef->getLoc()); 726245431Sdim 727245431Sdim // Find the AsmOperands that refer to the operands we're aliasing. 728245431Sdim int SrcAsmOperand = findAsmOperandNamed(Ops.first); 729245431Sdim int DstAsmOperand = findAsmOperandNamed(Ops.second); 730245431Sdim if (SrcAsmOperand == -1) 731245431Sdim PrintFatalError(TheDef->getLoc(), 732245431Sdim "unknown source two-operand alias operand '" + 733245431Sdim Ops.first.str() + "'."); 734245431Sdim if (DstAsmOperand == -1) 735245431Sdim PrintFatalError(TheDef->getLoc(), 736245431Sdim "unknown destination two-operand alias operand '" + 737245431Sdim Ops.second.str() + "'."); 738245431Sdim 739245431Sdim // Find the ResOperand that refers to the operand we're aliasing away 740245431Sdim // and update it to refer to the combined operand instead. 741245431Sdim for (unsigned i = 0, e = ResOperands.size(); i != e; ++i) { 742245431Sdim ResOperand &Op = ResOperands[i]; 743245431Sdim if (Op.Kind == ResOperand::RenderAsmOperand && 744245431Sdim Op.AsmOperandNum == (unsigned)SrcAsmOperand) { 745245431Sdim Op.AsmOperandNum = DstAsmOperand; 746245431Sdim break; 747245431Sdim } 748245431Sdim } 749245431Sdim // Remove the AsmOperand for the alias operand. 750245431Sdim AsmOperands.erase(AsmOperands.begin() + SrcAsmOperand); 751245431Sdim // Adjust the ResOperand references to any AsmOperands that followed 752245431Sdim // the one we just deleted. 753245431Sdim for (unsigned i = 0, e = ResOperands.size(); i != e; ++i) { 754245431Sdim ResOperand &Op = ResOperands[i]; 755245431Sdim switch(Op.Kind) { 756245431Sdim default: 757245431Sdim // Nothing to do for operands that don't reference AsmOperands. 758245431Sdim break; 759245431Sdim case ResOperand::RenderAsmOperand: 760245431Sdim if (Op.AsmOperandNum > (unsigned)SrcAsmOperand) 761245431Sdim --Op.AsmOperandNum; 762245431Sdim break; 763245431Sdim case ResOperand::TiedOperand: 764245431Sdim if (Op.TiedOperandNum > (unsigned)SrcAsmOperand) 765245431Sdim --Op.TiedOperandNum; 766245431Sdim break; 767245431Sdim } 768245431Sdim } 769245431Sdim} 770245431Sdim 771245431Sdimvoid MatchableInfo::initialize(const AsmMatcherInfo &Info, 772235633Sdim SmallPtrSet<Record*, 16> &SingletonRegisters, 773235633Sdim int AsmVariantNo, std::string &RegisterPrefix) { 774235633Sdim AsmVariantID = AsmVariantNo; 775235633Sdim AsmString = 776235633Sdim CodeGenInstruction::FlattenAsmStringVariants(AsmString, AsmVariantNo); 777218893Sdim 778245431Sdim tokenizeAsmString(Info); 779218893Sdim 780218893Sdim // Compute the require features. 781218893Sdim std::vector<Record*> Predicates =TheDef->getValueAsListOfDefs("Predicates"); 782218893Sdim for (unsigned i = 0, e = Predicates.size(); i != e; ++i) 783218893Sdim if (SubtargetFeatureInfo *Feature = 784218893Sdim Info.getSubtargetFeature(Predicates[i])) 785218893Sdim RequiredFeatures.push_back(Feature); 786218893Sdim 787218893Sdim // Collect singleton registers, if used. 788218893Sdim for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { 789235633Sdim extractSingletonRegisterForAsmOperand(i, Info, RegisterPrefix); 790235633Sdim if (Record *Reg = AsmOperands[i].SingletonReg) 791218893Sdim SingletonRegisters.insert(Reg); 792218893Sdim } 793263509Sdim 794263509Sdim const RecordVal *DepMask = TheDef->getValue("DeprecatedFeatureMask"); 795263509Sdim if (!DepMask) 796263509Sdim DepMask = TheDef->getValue("ComplexDeprecationPredicate"); 797263509Sdim 798263509Sdim HasDeprecation = 799263509Sdim DepMask ? !DepMask->getValue()->getAsUnquotedString().empty() : false; 800218893Sdim} 801218893Sdim 802245431Sdim/// tokenizeAsmString - Tokenize a simplified assembly string. 803245431Sdimvoid MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info) { 804218893Sdim StringRef String = AsmString; 805218893Sdim unsigned Prev = 0; 806218893Sdim bool InTok = true; 807218893Sdim for (unsigned i = 0, e = String.size(); i != e; ++i) { 808218893Sdim switch (String[i]) { 809218893Sdim case '[': 810218893Sdim case ']': 811218893Sdim case '*': 812218893Sdim case '!': 813218893Sdim case ' ': 814218893Sdim case '\t': 815218893Sdim case ',': 816218893Sdim if (InTok) { 817218893Sdim AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); 818218893Sdim InTok = false; 819218893Sdim } 820218893Sdim if (!isspace(String[i]) && String[i] != ',') 821218893Sdim AsmOperands.push_back(AsmOperand(String.substr(i, 1))); 822218893Sdim Prev = i + 1; 823218893Sdim break; 824218893Sdim 825218893Sdim case '\\': 826218893Sdim if (InTok) { 827218893Sdim AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); 828218893Sdim InTok = false; 829218893Sdim } 830218893Sdim ++i; 831218893Sdim assert(i != String.size() && "Invalid quoted character"); 832218893Sdim AsmOperands.push_back(AsmOperand(String.substr(i, 1))); 833218893Sdim Prev = i + 1; 834218893Sdim break; 835218893Sdim 836218893Sdim case '$': { 837218893Sdim if (InTok) { 838218893Sdim AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); 839218893Sdim InTok = false; 840218893Sdim } 841218893Sdim 842218893Sdim // If this isn't "${", treat like a normal token. 843218893Sdim if (i + 1 == String.size() || String[i + 1] != '{') { 844218893Sdim Prev = i; 845218893Sdim break; 846218893Sdim } 847218893Sdim 848218893Sdim StringRef::iterator End = std::find(String.begin() + i, String.end(),'}'); 849218893Sdim assert(End != String.end() && "Missing brace in operand reference!"); 850218893Sdim size_t EndPos = End - String.begin(); 851218893Sdim AsmOperands.push_back(AsmOperand(String.slice(i, EndPos+1))); 852218893Sdim Prev = EndPos + 1; 853218893Sdim i = EndPos; 854218893Sdim break; 855198090Srdivacky } 856198090Srdivacky 857218893Sdim case '.': 858263509Sdim if (!Info.AsmParser->getValueAsBit("MnemonicContainsDot")) { 859263509Sdim if (InTok) 860263509Sdim AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); 861263509Sdim Prev = i; 862263509Sdim } 863218893Sdim InTok = true; 864218893Sdim break; 865218893Sdim 866218893Sdim default: 867218893Sdim InTok = true; 868198090Srdivacky } 869218893Sdim } 870218893Sdim if (InTok && Prev != String.size()) 871218893Sdim AsmOperands.push_back(AsmOperand(String.substr(Prev))); 872198090Srdivacky 873218893Sdim // The first token of the instruction is the mnemonic, which must be a 874218893Sdim // simple string, not a $foo variable or a singleton register. 875235633Sdim if (AsmOperands.empty()) 876245431Sdim PrintFatalError(TheDef->getLoc(), 877235633Sdim "Instruction '" + TheDef->getName() + "' has no tokens"); 878218893Sdim Mnemonic = AsmOperands[0].Token; 879245431Sdim if (Mnemonic.empty()) 880245431Sdim PrintFatalError(TheDef->getLoc(), 881245431Sdim "Missing instruction mnemonic"); 882235633Sdim // FIXME : Check and raise an error if it is a register. 883235633Sdim if (Mnemonic[0] == '$') 884245431Sdim PrintFatalError(TheDef->getLoc(), 885218893Sdim "Invalid instruction mnemonic '" + Mnemonic.str() + "'!"); 886218893Sdim 887218893Sdim // Remove the first operand, it is tracked in the mnemonic field. 888218893Sdim AsmOperands.erase(AsmOperands.begin()); 889218893Sdim} 890218893Sdim 891245431Sdimbool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const { 892218893Sdim // Reject matchables with no .s string. 893218893Sdim if (AsmString.empty()) 894245431Sdim PrintFatalError(TheDef->getLoc(), "instruction with empty asm string"); 895218893Sdim 896218893Sdim // Reject any matchables with a newline in them, they should be marked 897218893Sdim // isCodeGenOnly if they are pseudo instructions. 898218893Sdim if (AsmString.find('\n') != std::string::npos) 899245431Sdim PrintFatalError(TheDef->getLoc(), 900218893Sdim "multiline instruction is not valid for the asmparser, " 901218893Sdim "mark it isCodeGenOnly"); 902218893Sdim 903218893Sdim // Remove comments from the asm string. We know that the asmstring only 904218893Sdim // has one line. 905218893Sdim if (!CommentDelimiter.empty() && 906218893Sdim StringRef(AsmString).find(CommentDelimiter) != StringRef::npos) 907245431Sdim PrintFatalError(TheDef->getLoc(), 908218893Sdim "asmstring for instruction has comment character in it, " 909218893Sdim "mark it isCodeGenOnly"); 910218893Sdim 911218893Sdim // Reject matchables with operand modifiers, these aren't something we can 912218893Sdim // handle, the target should be refactored to use operands instead of 913218893Sdim // modifiers. 914218893Sdim // 915218893Sdim // Also, check for instructions which reference the operand multiple times; 916218893Sdim // this implies a constraint we would not honor. 917218893Sdim std::set<std::string> OperandNames; 918218893Sdim for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { 919218893Sdim StringRef Tok = AsmOperands[i].Token; 920218893Sdim if (Tok[0] == '$' && Tok.find(':') != StringRef::npos) 921245431Sdim PrintFatalError(TheDef->getLoc(), 922218893Sdim "matchable with operand modifier '" + Tok.str() + 923218893Sdim "' not supported by asm matcher. Mark isCodeGenOnly!"); 924218893Sdim 925218893Sdim // Verify that any operand is only mentioned once. 926218893Sdim // We reject aliases and ignore instructions for now. 927218893Sdim if (Tok[0] == '$' && !OperandNames.insert(Tok).second) { 928218893Sdim if (!Hack) 929245431Sdim PrintFatalError(TheDef->getLoc(), 930218893Sdim "ERROR: matchable with tied operand '" + Tok.str() + 931218893Sdim "' can never be matched!"); 932218893Sdim // FIXME: Should reject these. The ARM backend hits this with $lane in a 933218893Sdim // bunch of instructions. It is unclear what the right answer is. 934218893Sdim DEBUG({ 935218893Sdim errs() << "warning: '" << TheDef->getName() << "': " 936218893Sdim << "ignoring instruction with tied operand '" 937218893Sdim << Tok.str() << "'\n"; 938218893Sdim }); 939218893Sdim return false; 940218893Sdim } 941198090Srdivacky } 942218893Sdim 943218893Sdim return true; 944198090Srdivacky} 945198090Srdivacky 946235633Sdim/// extractSingletonRegisterForAsmOperand - Extract singleton register, 947235633Sdim/// if present, from specified token. 948235633Sdimvoid MatchableInfo:: 949235633SdimextractSingletonRegisterForAsmOperand(unsigned OperandNo, 950235633Sdim const AsmMatcherInfo &Info, 951235633Sdim std::string &RegisterPrefix) { 952235633Sdim StringRef Tok = AsmOperands[OperandNo].Token; 953235633Sdim if (RegisterPrefix.empty()) { 954235633Sdim std::string LoweredTok = Tok.lower(); 955235633Sdim if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(LoweredTok)) 956235633Sdim AsmOperands[OperandNo].SingletonReg = Reg->TheDef; 957235633Sdim return; 958235633Sdim } 959218893Sdim 960235633Sdim if (!Tok.startswith(RegisterPrefix)) 961235633Sdim return; 962235633Sdim 963235633Sdim StringRef RegName = Tok.substr(RegisterPrefix.size()); 964218893Sdim if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName)) 965235633Sdim AsmOperands[OperandNo].SingletonReg = Reg->TheDef; 966218893Sdim 967218893Sdim // If there is no register prefix (i.e. "%" in "%eax"), then this may 968218893Sdim // be some random non-register token, just ignore it. 969235633Sdim return; 970218893Sdim} 971218893Sdim 972203954Srdivackystatic std::string getEnumNameForToken(StringRef Str) { 973198090Srdivacky std::string Res; 974218893Sdim 975198090Srdivacky for (StringRef::iterator it = Str.begin(), ie = Str.end(); it != ie; ++it) { 976198090Srdivacky switch (*it) { 977198090Srdivacky case '*': Res += "_STAR_"; break; 978198090Srdivacky case '%': Res += "_PCT_"; break; 979198090Srdivacky case ':': Res += "_COLON_"; break; 980218893Sdim case '!': Res += "_EXCLAIM_"; break; 981218893Sdim case '.': Res += "_DOT_"; break; 982252723Sdim case '<': Res += "_LT_"; break; 983252723Sdim case '>': Res += "_GT_"; break; 984198090Srdivacky default: 985252723Sdim if ((*it >= 'A' && *it <= 'Z') || 986252723Sdim (*it >= 'a' && *it <= 'z') || 987252723Sdim (*it >= '0' && *it <= '9')) 988198090Srdivacky Res += *it; 989218893Sdim else 990198090Srdivacky Res += "_" + utostr((unsigned) *it) + "_"; 991198090Srdivacky } 992198090Srdivacky } 993198090Srdivacky 994198090Srdivacky return Res; 995198090Srdivacky} 996198090Srdivacky 997203954SrdivackyClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) { 998198090Srdivacky ClassInfo *&Entry = TokenClasses[Token]; 999218893Sdim 1000198090Srdivacky if (!Entry) { 1001198090Srdivacky Entry = new ClassInfo(); 1002198090Srdivacky Entry->Kind = ClassInfo::Token; 1003198090Srdivacky Entry->ClassName = "Token"; 1004198090Srdivacky Entry->Name = "MCK_" + getEnumNameForToken(Token); 1005198090Srdivacky Entry->ValueName = Token; 1006198090Srdivacky Entry->PredicateMethod = "<invalid>"; 1007198090Srdivacky Entry->RenderMethod = "<invalid>"; 1008218893Sdim Entry->ParserMethod = ""; 1009245431Sdim Entry->DiagnosticType = ""; 1010198090Srdivacky Classes.push_back(Entry); 1011198090Srdivacky } 1012198090Srdivacky 1013198090Srdivacky return Entry; 1014198090Srdivacky} 1015198090Srdivacky 1016198090SrdivackyClassInfo * 1017218893SdimAsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI, 1018218893Sdim int SubOpIdx) { 1019218893Sdim Record *Rec = OI.Rec; 1020218893Sdim if (SubOpIdx != -1) 1021245431Sdim Rec = cast<DefInit>(OI.MIOperandInfo->getArg(SubOpIdx))->getDef(); 1022235633Sdim return getOperandClass(Rec, SubOpIdx); 1023235633Sdim} 1024198090Srdivacky 1025235633SdimClassInfo * 1026235633SdimAsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) { 1027224145Sdim if (Rec->isSubClassOf("RegisterOperand")) { 1028224145Sdim // RegisterOperand may have an associated ParserMatchClass. If it does, 1029224145Sdim // use it, else just fall back to the underlying register class. 1030224145Sdim const RecordVal *R = Rec->getValue("ParserMatchClass"); 1031224145Sdim if (R == 0 || R->getValue() == 0) 1032245431Sdim PrintFatalError("Record `" + Rec->getName() + 1033245431Sdim "' does not have a ParserMatchClass!\n"); 1034224145Sdim 1035245431Sdim if (DefInit *DI= dyn_cast<DefInit>(R->getValue())) { 1036224145Sdim Record *MatchClass = DI->getDef(); 1037224145Sdim if (ClassInfo *CI = AsmOperandClasses[MatchClass]) 1038224145Sdim return CI; 1039224145Sdim } 1040224145Sdim 1041224145Sdim // No custom match class. Just use the register class. 1042224145Sdim Record *ClassRec = Rec->getValueAsDef("RegClass"); 1043224145Sdim if (!ClassRec) 1044245431Sdim PrintFatalError(Rec->getLoc(), "RegisterOperand `" + Rec->getName() + 1045224145Sdim "' has no associated register class!\n"); 1046224145Sdim if (ClassInfo *CI = RegisterClassClasses[ClassRec]) 1047224145Sdim return CI; 1048245431Sdim PrintFatalError(Rec->getLoc(), "register class has no class info!"); 1049224145Sdim } 1050224145Sdim 1051224145Sdim 1052218893Sdim if (Rec->isSubClassOf("RegisterClass")) { 1053218893Sdim if (ClassInfo *CI = RegisterClassClasses[Rec]) 1054218893Sdim return CI; 1055245431Sdim PrintFatalError(Rec->getLoc(), "register class has no class info!"); 1056218893Sdim } 1057198090Srdivacky 1058245431Sdim if (!Rec->isSubClassOf("Operand")) 1059245431Sdim PrintFatalError(Rec->getLoc(), "Operand `" + Rec->getName() + 1060245431Sdim "' does not derive from class Operand!\n"); 1061218893Sdim Record *MatchClass = Rec->getValueAsDef("ParserMatchClass"); 1062218893Sdim if (ClassInfo *CI = AsmOperandClasses[MatchClass]) 1063198090Srdivacky return CI; 1064198090Srdivacky 1065245431Sdim PrintFatalError(Rec->getLoc(), "operand has no match class!"); 1066198090Srdivacky} 1067198090Srdivacky 1068263509Sdimstruct LessRegisterSet { 1069263509Sdim bool operator() (const RegisterSet &LHS, const RegisterSet & RHS) const { 1070263509Sdim // std::set<T> defines its own compariso "operator<", but it 1071263509Sdim // performs a lexicographical comparison by T's innate comparison 1072263509Sdim // for some reason. We don't want non-deterministic pointer 1073263509Sdim // comparisons so use this instead. 1074263509Sdim return std::lexicographical_compare(LHS.begin(), LHS.end(), 1075263509Sdim RHS.begin(), RHS.end(), 1076263509Sdim LessRecordByID()); 1077263509Sdim } 1078263509Sdim}; 1079263509Sdim 1080218893Sdimvoid AsmMatcherInfo:: 1081245431SdimbuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { 1082224145Sdim const std::vector<CodeGenRegister*> &Registers = 1083224145Sdim Target.getRegBank().getRegisters(); 1084226890Sdim ArrayRef<CodeGenRegisterClass*> RegClassList = 1085226890Sdim Target.getRegBank().getRegClasses(); 1086198090Srdivacky 1087263509Sdim typedef std::set<RegisterSet, LessRegisterSet> RegisterSetSet; 1088263509Sdim 1089198090Srdivacky // The register sets used for matching. 1090263509Sdim RegisterSetSet RegisterSets; 1091198090Srdivacky 1092218893Sdim // Gather the defined sets. 1093226890Sdim for (ArrayRef<CodeGenRegisterClass*>::const_iterator it = 1094263509Sdim RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) 1095263509Sdim RegisterSets.insert(RegisterSet( 1096226890Sdim (*it)->getOrder().begin(), (*it)->getOrder().end())); 1097198090Srdivacky 1098198090Srdivacky // Add any required singleton sets. 1099218893Sdim for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(), 1100218893Sdim ie = SingletonRegisters.end(); it != ie; ++it) { 1101218893Sdim Record *Rec = *it; 1102263509Sdim RegisterSets.insert(RegisterSet(&Rec, &Rec + 1)); 1103218893Sdim } 1104218893Sdim 1105198090Srdivacky // Introduce derived sets where necessary (when a register does not determine 1106198090Srdivacky // a unique register set class), and build the mapping of registers to the set 1107198090Srdivacky // they should classify to. 1108263509Sdim std::map<Record*, RegisterSet> RegisterMap; 1109224145Sdim for (std::vector<CodeGenRegister*>::const_iterator it = Registers.begin(), 1110198090Srdivacky ie = Registers.end(); it != ie; ++it) { 1111224145Sdim const CodeGenRegister &CGR = **it; 1112198090Srdivacky // Compute the intersection of all sets containing this register. 1113263509Sdim RegisterSet ContainingSet; 1114218893Sdim 1115263509Sdim for (RegisterSetSet::iterator it = RegisterSets.begin(), 1116198090Srdivacky ie = RegisterSets.end(); it != ie; ++it) { 1117198090Srdivacky if (!it->count(CGR.TheDef)) 1118198090Srdivacky continue; 1119198090Srdivacky 1120198090Srdivacky if (ContainingSet.empty()) { 1121198090Srdivacky ContainingSet = *it; 1122218893Sdim continue; 1123198090Srdivacky } 1124218893Sdim 1125263509Sdim RegisterSet Tmp; 1126218893Sdim std::swap(Tmp, ContainingSet); 1127263509Sdim std::insert_iterator<RegisterSet> II(ContainingSet, 1128263509Sdim ContainingSet.begin()); 1129263509Sdim std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II, 1130263509Sdim LessRecordByID()); 1131198090Srdivacky } 1132198090Srdivacky 1133198090Srdivacky if (!ContainingSet.empty()) { 1134198090Srdivacky RegisterSets.insert(ContainingSet); 1135198090Srdivacky RegisterMap.insert(std::make_pair(CGR.TheDef, ContainingSet)); 1136198090Srdivacky } 1137198090Srdivacky } 1138198090Srdivacky 1139198090Srdivacky // Construct the register classes. 1140263509Sdim std::map<RegisterSet, ClassInfo*, LessRegisterSet> RegisterSetClasses; 1141198090Srdivacky unsigned Index = 0; 1142263509Sdim for (RegisterSetSet::iterator it = RegisterSets.begin(), 1143198090Srdivacky ie = RegisterSets.end(); it != ie; ++it, ++Index) { 1144198090Srdivacky ClassInfo *CI = new ClassInfo(); 1145198090Srdivacky CI->Kind = ClassInfo::RegisterClass0 + Index; 1146198090Srdivacky CI->ClassName = "Reg" + utostr(Index); 1147198090Srdivacky CI->Name = "MCK_Reg" + utostr(Index); 1148198090Srdivacky CI->ValueName = ""; 1149198090Srdivacky CI->PredicateMethod = ""; // unused 1150198090Srdivacky CI->RenderMethod = "addRegOperands"; 1151198090Srdivacky CI->Registers = *it; 1152245431Sdim // FIXME: diagnostic type. 1153245431Sdim CI->DiagnosticType = ""; 1154198090Srdivacky Classes.push_back(CI); 1155198090Srdivacky RegisterSetClasses.insert(std::make_pair(*it, CI)); 1156198090Srdivacky } 1157198090Srdivacky 1158198090Srdivacky // Find the superclasses; we could compute only the subgroup lattice edges, 1159198090Srdivacky // but there isn't really a point. 1160263509Sdim for (RegisterSetSet::iterator it = RegisterSets.begin(), 1161198090Srdivacky ie = RegisterSets.end(); it != ie; ++it) { 1162198090Srdivacky ClassInfo *CI = RegisterSetClasses[*it]; 1163263509Sdim for (RegisterSetSet::iterator it2 = RegisterSets.begin(), 1164198090Srdivacky ie2 = RegisterSets.end(); it2 != ie2; ++it2) 1165218893Sdim if (*it != *it2 && 1166263509Sdim std::includes(it2->begin(), it2->end(), it->begin(), it->end(), 1167263509Sdim LessRecordByID())) 1168198090Srdivacky CI->SuperClasses.push_back(RegisterSetClasses[*it2]); 1169198090Srdivacky } 1170198090Srdivacky 1171198090Srdivacky // Name the register classes which correspond to a user defined RegisterClass. 1172226890Sdim for (ArrayRef<CodeGenRegisterClass*>::const_iterator 1173218893Sdim it = RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) { 1174226890Sdim const CodeGenRegisterClass &RC = **it; 1175226890Sdim // Def will be NULL for non-user defined register classes. 1176226890Sdim Record *Def = RC.getDef(); 1177226890Sdim if (!Def) 1178226890Sdim continue; 1179263509Sdim ClassInfo *CI = RegisterSetClasses[RegisterSet(RC.getOrder().begin(), 1180263509Sdim RC.getOrder().end())]; 1181198090Srdivacky if (CI->ValueName.empty()) { 1182226890Sdim CI->ClassName = RC.getName(); 1183226890Sdim CI->Name = "MCK_" + RC.getName(); 1184226890Sdim CI->ValueName = RC.getName(); 1185198090Srdivacky } else 1186226890Sdim CI->ValueName = CI->ValueName + "," + RC.getName(); 1187198090Srdivacky 1188226890Sdim RegisterClassClasses.insert(std::make_pair(Def, CI)); 1189198090Srdivacky } 1190198090Srdivacky 1191198090Srdivacky // Populate the map for individual registers. 1192263509Sdim for (std::map<Record*, RegisterSet>::iterator it = RegisterMap.begin(), 1193198090Srdivacky ie = RegisterMap.end(); it != ie; ++it) 1194218893Sdim RegisterClasses[it->first] = RegisterSetClasses[it->second]; 1195198090Srdivacky 1196198090Srdivacky // Name the register classes which correspond to singleton registers. 1197218893Sdim for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(), 1198218893Sdim ie = SingletonRegisters.end(); it != ie; ++it) { 1199218893Sdim Record *Rec = *it; 1200218893Sdim ClassInfo *CI = RegisterClasses[Rec]; 1201218893Sdim assert(CI && "Missing singleton register class info!"); 1202198090Srdivacky 1203218893Sdim if (CI->ValueName.empty()) { 1204218893Sdim CI->ClassName = Rec->getName(); 1205218893Sdim CI->Name = "MCK_" + Rec->getName(); 1206218893Sdim CI->ValueName = Rec->getName(); 1207218893Sdim } else 1208218893Sdim CI->ValueName = CI->ValueName + "," + Rec->getName(); 1209198090Srdivacky } 1210198090Srdivacky} 1211198090Srdivacky 1212245431Sdimvoid AsmMatcherInfo::buildOperandClasses() { 1213218893Sdim std::vector<Record*> AsmOperands = 1214218893Sdim Records.getAllDerivedDefinitions("AsmOperandClass"); 1215203954Srdivacky 1216203954Srdivacky // Pre-populate AsmOperandClasses map. 1217218893Sdim for (std::vector<Record*>::iterator it = AsmOperands.begin(), 1218203954Srdivacky ie = AsmOperands.end(); it != ie; ++it) 1219203954Srdivacky AsmOperandClasses[*it] = new ClassInfo(); 1220203954Srdivacky 1221198090Srdivacky unsigned Index = 0; 1222218893Sdim for (std::vector<Record*>::iterator it = AsmOperands.begin(), 1223198090Srdivacky ie = AsmOperands.end(); it != ie; ++it, ++Index) { 1224203954Srdivacky ClassInfo *CI = AsmOperandClasses[*it]; 1225198090Srdivacky CI->Kind = ClassInfo::UserClass0 + Index; 1226198090Srdivacky 1227208599Srdivacky ListInit *Supers = (*it)->getValueAsListInit("SuperClasses"); 1228208599Srdivacky for (unsigned i = 0, e = Supers->getSize(); i != e; ++i) { 1229245431Sdim DefInit *DI = dyn_cast<DefInit>(Supers->getElement(i)); 1230208599Srdivacky if (!DI) { 1231208599Srdivacky PrintError((*it)->getLoc(), "Invalid super class reference!"); 1232208599Srdivacky continue; 1233208599Srdivacky } 1234208599Srdivacky 1235198090Srdivacky ClassInfo *SC = AsmOperandClasses[DI->getDef()]; 1236198090Srdivacky if (!SC) 1237198090Srdivacky PrintError((*it)->getLoc(), "Invalid super class reference!"); 1238198090Srdivacky else 1239198090Srdivacky CI->SuperClasses.push_back(SC); 1240198090Srdivacky } 1241198090Srdivacky CI->ClassName = (*it)->getValueAsString("Name"); 1242198090Srdivacky CI->Name = "MCK_" + CI->ClassName; 1243198090Srdivacky CI->ValueName = (*it)->getName(); 1244198090Srdivacky 1245198090Srdivacky // Get or construct the predicate method name. 1246198090Srdivacky Init *PMName = (*it)->getValueInit("PredicateMethod"); 1247245431Sdim if (StringInit *SI = dyn_cast<StringInit>(PMName)) { 1248198090Srdivacky CI->PredicateMethod = SI->getValue(); 1249198090Srdivacky } else { 1250245431Sdim assert(isa<UnsetInit>(PMName) && "Unexpected PredicateMethod field!"); 1251198090Srdivacky CI->PredicateMethod = "is" + CI->ClassName; 1252198090Srdivacky } 1253198090Srdivacky 1254198090Srdivacky // Get or construct the render method name. 1255198090Srdivacky Init *RMName = (*it)->getValueInit("RenderMethod"); 1256245431Sdim if (StringInit *SI = dyn_cast<StringInit>(RMName)) { 1257198090Srdivacky CI->RenderMethod = SI->getValue(); 1258198090Srdivacky } else { 1259245431Sdim assert(isa<UnsetInit>(RMName) && "Unexpected RenderMethod field!"); 1260198090Srdivacky CI->RenderMethod = "add" + CI->ClassName + "Operands"; 1261198090Srdivacky } 1262198090Srdivacky 1263218893Sdim // Get the parse method name or leave it as empty. 1264218893Sdim Init *PRMName = (*it)->getValueInit("ParserMethod"); 1265245431Sdim if (StringInit *SI = dyn_cast<StringInit>(PRMName)) 1266218893Sdim CI->ParserMethod = SI->getValue(); 1267218893Sdim 1268245431Sdim // Get the diagnostic type or leave it as empty. 1269245431Sdim // Get the parse method name or leave it as empty. 1270245431Sdim Init *DiagnosticType = (*it)->getValueInit("DiagnosticType"); 1271245431Sdim if (StringInit *SI = dyn_cast<StringInit>(DiagnosticType)) 1272245431Sdim CI->DiagnosticType = SI->getValue(); 1273245431Sdim 1274198090Srdivacky AsmOperandClasses[*it] = CI; 1275198090Srdivacky Classes.push_back(CI); 1276198090Srdivacky } 1277198090Srdivacky} 1278198090Srdivacky 1279218893SdimAsmMatcherInfo::AsmMatcherInfo(Record *asmParser, 1280218893Sdim CodeGenTarget &target, 1281218893Sdim RecordKeeper &records) 1282235633Sdim : Records(records), AsmParser(asmParser), Target(target) { 1283198090Srdivacky} 1284198090Srdivacky 1285245431Sdim/// buildOperandMatchInfo - Build the necessary information to handle user 1286218893Sdim/// defined operand parsing methods. 1287245431Sdimvoid AsmMatcherInfo::buildOperandMatchInfo() { 1288218893Sdim 1289245431Sdim /// Map containing a mask with all operands indices that can be found for 1290218893Sdim /// that class inside a instruction. 1291245431Sdim typedef std::map<ClassInfo*, unsigned, LessClassInfoPtr> OpClassMaskTy; 1292245431Sdim OpClassMaskTy OpClassMask; 1293218893Sdim 1294218893Sdim for (std::vector<MatchableInfo*>::const_iterator it = 1295218893Sdim Matchables.begin(), ie = Matchables.end(); 1296218893Sdim it != ie; ++it) { 1297218893Sdim MatchableInfo &II = **it; 1298218893Sdim OpClassMask.clear(); 1299218893Sdim 1300218893Sdim // Keep track of all operands of this instructions which belong to the 1301218893Sdim // same class. 1302218893Sdim for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { 1303218893Sdim MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; 1304218893Sdim if (Op.Class->ParserMethod.empty()) 1305218893Sdim continue; 1306218893Sdim unsigned &OperandMask = OpClassMask[Op.Class]; 1307218893Sdim OperandMask |= (1 << i); 1308218893Sdim } 1309218893Sdim 1310218893Sdim // Generate operand match info for each mnemonic/operand class pair. 1311245431Sdim for (OpClassMaskTy::iterator iit = OpClassMask.begin(), 1312218893Sdim iie = OpClassMask.end(); iit != iie; ++iit) { 1313218893Sdim unsigned OpMask = iit->second; 1314218893Sdim ClassInfo *CI = iit->first; 1315245431Sdim OperandMatchInfo.push_back(OperandMatchEntry::create(&II, CI, OpMask)); 1316218893Sdim } 1317218893Sdim } 1318218893Sdim} 1319218893Sdim 1320245431Sdimvoid AsmMatcherInfo::buildInfo() { 1321218893Sdim // Build information about all of the AssemblerPredicates. 1322218893Sdim std::vector<Record*> AllPredicates = 1323218893Sdim Records.getAllDerivedDefinitions("Predicate"); 1324218893Sdim for (unsigned i = 0, e = AllPredicates.size(); i != e; ++i) { 1325218893Sdim Record *Pred = AllPredicates[i]; 1326218893Sdim // Ignore predicates that are not intended for the assembler. 1327218893Sdim if (!Pred->getValueAsBit("AssemblerMatcherPredicate")) 1328218893Sdim continue; 1329218893Sdim 1330218893Sdim if (Pred->getName().empty()) 1331245431Sdim PrintFatalError(Pred->getLoc(), "Predicate has no name!"); 1332218893Sdim 1333218893Sdim unsigned FeatureNo = SubtargetFeatures.size(); 1334218893Sdim SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); 1335218893Sdim assert(FeatureNo < 32 && "Too many subtarget features!"); 1336218893Sdim } 1337218893Sdim 1338198090Srdivacky // Parse the instructions; we need to do this first so that we can gather the 1339198090Srdivacky // singleton register classes. 1340218893Sdim SmallPtrSet<Record*, 16> SingletonRegisters; 1341235633Sdim unsigned VariantCount = Target.getAsmParserVariantCount(); 1342235633Sdim for (unsigned VC = 0; VC != VariantCount; ++VC) { 1343235633Sdim Record *AsmVariant = Target.getAsmParserVariant(VC); 1344235633Sdim std::string CommentDelimiter = 1345235633Sdim AsmVariant->getValueAsString("CommentDelimiter"); 1346235633Sdim std::string RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix"); 1347235633Sdim int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); 1348198090Srdivacky 1349235633Sdim for (CodeGenTarget::inst_iterator I = Target.inst_begin(), 1350235633Sdim E = Target.inst_end(); I != E; ++I) { 1351235633Sdim const CodeGenInstruction &CGI = **I; 1352198090Srdivacky 1353235633Sdim // If the tblgen -match-prefix option is specified (for tblgen hackers), 1354235633Sdim // filter the set of instructions we consider. 1355235633Sdim if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix)) 1356235633Sdim continue; 1357198090Srdivacky 1358235633Sdim // Ignore "codegen only" instructions. 1359235633Sdim if (CGI.TheDef->getValueAsBit("isCodeGenOnly")) 1360235633Sdim continue; 1361218893Sdim 1362235633Sdim OwningPtr<MatchableInfo> II(new MatchableInfo(CGI)); 1363198090Srdivacky 1364245431Sdim II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); 1365218893Sdim 1366235633Sdim // Ignore instructions which shouldn't be matched and diagnose invalid 1367235633Sdim // instruction definitions with an error. 1368245431Sdim if (!II->validate(CommentDelimiter, true)) 1369235633Sdim continue; 1370198090Srdivacky 1371235633Sdim // Ignore "Int_*" and "*_Int" instructions, which are internal aliases. 1372235633Sdim // 1373235633Sdim // FIXME: This is a total hack. 1374235633Sdim if (StringRef(II->TheDef->getName()).startswith("Int_") || 1375235633Sdim StringRef(II->TheDef->getName()).endswith("_Int")) 1376235633Sdim continue; 1377198090Srdivacky 1378235633Sdim Matchables.push_back(II.take()); 1379235633Sdim } 1380212904Sdim 1381235633Sdim // Parse all of the InstAlias definitions and stick them in the list of 1382235633Sdim // matchables. 1383235633Sdim std::vector<Record*> AllInstAliases = 1384235633Sdim Records.getAllDerivedDefinitions("InstAlias"); 1385235633Sdim for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) { 1386235633Sdim CodeGenInstAlias *Alias = new CodeGenInstAlias(AllInstAliases[i], Target); 1387212904Sdim 1388235633Sdim // If the tblgen -match-prefix option is specified (for tblgen hackers), 1389235633Sdim // filter the set of instruction aliases we consider, based on the target 1390235633Sdim // instruction. 1391235633Sdim if (!StringRef(Alias->ResultInst->TheDef->getName()) 1392235633Sdim .startswith( MatchPrefix)) 1393235633Sdim continue; 1394212904Sdim 1395235633Sdim OwningPtr<MatchableInfo> II(new MatchableInfo(Alias)); 1396212904Sdim 1397245431Sdim II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); 1398218893Sdim 1399235633Sdim // Validate the alias definitions. 1400245431Sdim II->validate(CommentDelimiter, false); 1401218893Sdim 1402235633Sdim Matchables.push_back(II.take()); 1403235633Sdim } 1404198090Srdivacky } 1405198090Srdivacky 1406198090Srdivacky // Build info for the register classes. 1407245431Sdim buildRegisterClasses(SingletonRegisters); 1408198090Srdivacky 1409198090Srdivacky // Build info for the user defined assembly operand classes. 1410245431Sdim buildOperandClasses(); 1411198090Srdivacky 1412218893Sdim // Build the information about matchables, now that we have fully formed 1413218893Sdim // classes. 1414245431Sdim std::vector<MatchableInfo*> NewMatchables; 1415218893Sdim for (std::vector<MatchableInfo*>::iterator it = Matchables.begin(), 1416218893Sdim ie = Matchables.end(); it != ie; ++it) { 1417218893Sdim MatchableInfo *II = *it; 1418198090Srdivacky 1419218893Sdim // Parse the tokens after the mnemonic. 1420245431Sdim // Note: buildInstructionOperandReference may insert new AsmOperands, so 1421218893Sdim // don't precompute the loop bound. 1422218893Sdim for (unsigned i = 0; i != II->AsmOperands.size(); ++i) { 1423218893Sdim MatchableInfo::AsmOperand &Op = II->AsmOperands[i]; 1424218893Sdim StringRef Token = Op.Token; 1425198090Srdivacky 1426198090Srdivacky // Check for singleton registers. 1427235633Sdim if (Record *RegRecord = II->AsmOperands[i].SingletonReg) { 1428218893Sdim Op.Class = RegisterClasses[RegRecord]; 1429198090Srdivacky assert(Op.Class && Op.Class->Registers.size() == 1 && 1430198090Srdivacky "Unexpected class for singleton register"); 1431198090Srdivacky continue; 1432198090Srdivacky } 1433198090Srdivacky 1434198090Srdivacky // Check for simple tokens. 1435198090Srdivacky if (Token[0] != '$') { 1436198090Srdivacky Op.Class = getTokenClass(Token); 1437198090Srdivacky continue; 1438198090Srdivacky } 1439198090Srdivacky 1440218893Sdim if (Token.size() > 1 && isdigit(Token[1])) { 1441218893Sdim Op.Class = getTokenClass(Token); 1442218893Sdim continue; 1443218893Sdim } 1444218893Sdim 1445198090Srdivacky // Otherwise this is an operand reference. 1446198090Srdivacky StringRef OperandName; 1447198090Srdivacky if (Token[1] == '{') 1448198090Srdivacky OperandName = Token.substr(2, Token.size() - 3); 1449198090Srdivacky else 1450198090Srdivacky OperandName = Token.substr(1); 1451198090Srdivacky 1452218893Sdim if (II->DefRec.is<const CodeGenInstruction*>()) 1453245431Sdim buildInstructionOperandReference(II, OperandName, i); 1454218893Sdim else 1455245431Sdim buildAliasOperandReference(II, OperandName, Op); 1456218893Sdim } 1457198090Srdivacky 1458245431Sdim if (II->DefRec.is<const CodeGenInstruction*>()) { 1459245431Sdim II->buildInstructionResultOperands(); 1460245431Sdim // If the instruction has a two-operand alias, build up the 1461245431Sdim // matchable here. We'll add them in bulk at the end to avoid 1462245431Sdim // confusing this loop. 1463245431Sdim std::string Constraint = 1464245431Sdim II->TheDef->getValueAsString("TwoOperandAliasConstraint"); 1465245431Sdim if (Constraint != "") { 1466245431Sdim // Start by making a copy of the original matchable. 1467245431Sdim OwningPtr<MatchableInfo> AliasII(new MatchableInfo(*II)); 1468245431Sdim 1469245431Sdim // Adjust it to be a two-operand alias. 1470245431Sdim AliasII->formTwoOperandAlias(Constraint); 1471245431Sdim 1472245431Sdim // Add the alias to the matchables list. 1473245431Sdim NewMatchables.push_back(AliasII.take()); 1474245431Sdim } 1475245431Sdim } else 1476245431Sdim II->buildAliasResultOperands(); 1477218893Sdim } 1478245431Sdim if (!NewMatchables.empty()) 1479245431Sdim Matchables.insert(Matchables.end(), NewMatchables.begin(), 1480245431Sdim NewMatchables.end()); 1481203954Srdivacky 1482235633Sdim // Process token alias definitions and set up the associated superclass 1483235633Sdim // information. 1484235633Sdim std::vector<Record*> AllTokenAliases = 1485235633Sdim Records.getAllDerivedDefinitions("TokenAlias"); 1486235633Sdim for (unsigned i = 0, e = AllTokenAliases.size(); i != e; ++i) { 1487235633Sdim Record *Rec = AllTokenAliases[i]; 1488235633Sdim ClassInfo *FromClass = getTokenClass(Rec->getValueAsString("FromToken")); 1489235633Sdim ClassInfo *ToClass = getTokenClass(Rec->getValueAsString("ToToken")); 1490235633Sdim if (FromClass == ToClass) 1491245431Sdim PrintFatalError(Rec->getLoc(), 1492235633Sdim "error: Destination value identical to source value."); 1493235633Sdim FromClass->SuperClasses.push_back(ToClass); 1494235633Sdim } 1495235633Sdim 1496221345Sdim // Reorder classes so that classes precede super classes. 1497218893Sdim std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>()); 1498218893Sdim} 1499203954Srdivacky 1500245431Sdim/// buildInstructionOperandReference - The specified operand is a reference to a 1501218893Sdim/// named operand such as $src. Resolve the Class and OperandInfo pointers. 1502218893Sdimvoid AsmMatcherInfo:: 1503245431SdimbuildInstructionOperandReference(MatchableInfo *II, 1504218893Sdim StringRef OperandName, 1505218893Sdim unsigned AsmOpIdx) { 1506218893Sdim const CodeGenInstruction &CGI = *II->DefRec.get<const CodeGenInstruction*>(); 1507218893Sdim const CGIOperandList &Operands = CGI.Operands; 1508218893Sdim MatchableInfo::AsmOperand *Op = &II->AsmOperands[AsmOpIdx]; 1509218893Sdim 1510218893Sdim // Map this token to an operand. 1511218893Sdim unsigned Idx; 1512218893Sdim if (!Operands.hasOperandNamed(OperandName, Idx)) 1513245431Sdim PrintFatalError(II->TheDef->getLoc(), "error: unable to find operand: '" + 1514218893Sdim OperandName.str() + "'"); 1515218893Sdim 1516218893Sdim // If the instruction operand has multiple suboperands, but the parser 1517218893Sdim // match class for the asm operand is still the default "ImmAsmOperand", 1518218893Sdim // then handle each suboperand separately. 1519218893Sdim if (Op->SubOpIdx == -1 && Operands[Idx].MINumOperands > 1) { 1520218893Sdim Record *Rec = Operands[Idx].Rec; 1521218893Sdim assert(Rec->isSubClassOf("Operand") && "Unexpected operand!"); 1522218893Sdim Record *MatchClass = Rec->getValueAsDef("ParserMatchClass"); 1523218893Sdim if (MatchClass && MatchClass->getValueAsString("Name") == "Imm") { 1524218893Sdim // Insert remaining suboperands after AsmOpIdx in II->AsmOperands. 1525218893Sdim StringRef Token = Op->Token; // save this in case Op gets moved 1526218893Sdim for (unsigned SI = 1, SE = Operands[Idx].MINumOperands; SI != SE; ++SI) { 1527218893Sdim MatchableInfo::AsmOperand NewAsmOp(Token); 1528218893Sdim NewAsmOp.SubOpIdx = SI; 1529218893Sdim II->AsmOperands.insert(II->AsmOperands.begin()+AsmOpIdx+SI, NewAsmOp); 1530203954Srdivacky } 1531218893Sdim // Replace Op with first suboperand. 1532218893Sdim Op = &II->AsmOperands[AsmOpIdx]; // update the pointer in case it moved 1533218893Sdim Op->SubOpIdx = 0; 1534198090Srdivacky } 1535198090Srdivacky } 1536198090Srdivacky 1537218893Sdim // Set up the operand class. 1538218893Sdim Op->Class = getOperandClass(Operands[Idx], Op->SubOpIdx); 1539218893Sdim 1540218893Sdim // If the named operand is tied, canonicalize it to the untied operand. 1541218893Sdim // For example, something like: 1542218893Sdim // (outs GPR:$dst), (ins GPR:$src) 1543218893Sdim // with an asmstring of 1544218893Sdim // "inc $src" 1545218893Sdim // we want to canonicalize to: 1546218893Sdim // "inc $dst" 1547218893Sdim // so that we know how to provide the $dst operand when filling in the result. 1548252723Sdim int OITied = -1; 1549252723Sdim if (Operands[Idx].MINumOperands == 1) 1550252723Sdim OITied = Operands[Idx].getTiedRegister(); 1551218893Sdim if (OITied != -1) { 1552218893Sdim // The tied operand index is an MIOperand index, find the operand that 1553218893Sdim // contains it. 1554218893Sdim std::pair<unsigned, unsigned> Idx = Operands.getSubOperandNumber(OITied); 1555218893Sdim OperandName = Operands[Idx.first].Name; 1556218893Sdim Op->SubOpIdx = Idx.second; 1557218893Sdim } 1558218893Sdim 1559218893Sdim Op->SrcOpName = OperandName; 1560198090Srdivacky} 1561198090Srdivacky 1562245431Sdim/// buildAliasOperandReference - When parsing an operand reference out of the 1563218893Sdim/// matching string (e.g. "movsx $src, $dst"), determine what the class of the 1564218893Sdim/// operand reference is by looking it up in the result pattern definition. 1565245431Sdimvoid AsmMatcherInfo::buildAliasOperandReference(MatchableInfo *II, 1566218893Sdim StringRef OperandName, 1567218893Sdim MatchableInfo::AsmOperand &Op) { 1568218893Sdim const CodeGenInstAlias &CGA = *II->DefRec.get<const CodeGenInstAlias*>(); 1569203954Srdivacky 1570218893Sdim // Set up the operand class. 1571218893Sdim for (unsigned i = 0, e = CGA.ResultOperands.size(); i != e; ++i) 1572218893Sdim if (CGA.ResultOperands[i].isRecord() && 1573218893Sdim CGA.ResultOperands[i].getName() == OperandName) { 1574218893Sdim // It's safe to go with the first one we find, because CodeGenInstAlias 1575218893Sdim // validates that all operands with the same name have the same record. 1576218893Sdim Op.SubOpIdx = CGA.ResultInstOperandIndex[i].second; 1577235633Sdim // Use the match class from the Alias definition, not the 1578235633Sdim // destination instruction, as we may have an immediate that's 1579235633Sdim // being munged by the match class. 1580235633Sdim Op.Class = getOperandClass(CGA.ResultOperands[i].getRecord(), 1581218893Sdim Op.SubOpIdx); 1582218893Sdim Op.SrcOpName = OperandName; 1583218893Sdim return; 1584218893Sdim } 1585218893Sdim 1586245431Sdim PrintFatalError(II->TheDef->getLoc(), "error: unable to find operand: '" + 1587218893Sdim OperandName.str() + "'"); 1588203954Srdivacky} 1589203954Srdivacky 1590245431Sdimvoid MatchableInfo::buildInstructionResultOperands() { 1591218893Sdim const CodeGenInstruction *ResultInst = getResultInst(); 1592218893Sdim 1593218893Sdim // Loop over all operands of the result instruction, determining how to 1594218893Sdim // populate them. 1595218893Sdim for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { 1596218893Sdim const CGIOperandList::OperandInfo &OpInfo = ResultInst->Operands[i]; 1597218893Sdim 1598218893Sdim // If this is a tied operand, just copy from the previously handled operand. 1599252723Sdim int TiedOp = -1; 1600252723Sdim if (OpInfo.MINumOperands == 1) 1601252723Sdim TiedOp = OpInfo.getTiedRegister(); 1602218893Sdim if (TiedOp != -1) { 1603218893Sdim ResOperands.push_back(ResOperand::getTiedOp(TiedOp)); 1604218893Sdim continue; 1605218893Sdim } 1606218893Sdim 1607218893Sdim // Find out what operand from the asmparser this MCInst operand comes from. 1608245431Sdim int SrcOperand = findAsmOperandNamed(OpInfo.Name); 1609252723Sdim if (OpInfo.Name.empty() || SrcOperand == -1) { 1610252723Sdim // This may happen for operands that are tied to a suboperand of a 1611252723Sdim // complex operand. Simply use a dummy value here; nobody should 1612252723Sdim // use this operand slot. 1613252723Sdim // FIXME: The long term goal is for the MCOperand list to not contain 1614252723Sdim // tied operands at all. 1615252723Sdim ResOperands.push_back(ResOperand::getImmOp(0)); 1616252723Sdim continue; 1617252723Sdim } 1618218893Sdim 1619218893Sdim // Check if the one AsmOperand populates the entire operand. 1620218893Sdim unsigned NumOperands = OpInfo.MINumOperands; 1621218893Sdim if (AsmOperands[SrcOperand].SubOpIdx == -1) { 1622218893Sdim ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, NumOperands)); 1623218893Sdim continue; 1624218893Sdim } 1625218893Sdim 1626218893Sdim // Add a separate ResOperand for each suboperand. 1627218893Sdim for (unsigned AI = 0; AI < NumOperands; ++AI) { 1628218893Sdim assert(AsmOperands[SrcOperand+AI].SubOpIdx == (int)AI && 1629218893Sdim AsmOperands[SrcOperand+AI].SrcOpName == OpInfo.Name && 1630218893Sdim "unexpected AsmOperands for suboperands"); 1631218893Sdim ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand + AI, 1)); 1632218893Sdim } 1633218893Sdim } 1634218893Sdim} 1635218893Sdim 1636245431Sdimvoid MatchableInfo::buildAliasResultOperands() { 1637218893Sdim const CodeGenInstAlias &CGA = *DefRec.get<const CodeGenInstAlias*>(); 1638218893Sdim const CodeGenInstruction *ResultInst = getResultInst(); 1639218893Sdim 1640218893Sdim // Loop over all operands of the result instruction, determining how to 1641218893Sdim // populate them. 1642218893Sdim unsigned AliasOpNo = 0; 1643218893Sdim unsigned LastOpNo = CGA.ResultInstOperandIndex.size(); 1644218893Sdim for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { 1645218893Sdim const CGIOperandList::OperandInfo *OpInfo = &ResultInst->Operands[i]; 1646218893Sdim 1647218893Sdim // If this is a tied operand, just copy from the previously handled operand. 1648252723Sdim int TiedOp = -1; 1649252723Sdim if (OpInfo->MINumOperands == 1) 1650252723Sdim TiedOp = OpInfo->getTiedRegister(); 1651218893Sdim if (TiedOp != -1) { 1652218893Sdim ResOperands.push_back(ResOperand::getTiedOp(TiedOp)); 1653218893Sdim continue; 1654218893Sdim } 1655218893Sdim 1656218893Sdim // Handle all the suboperands for this operand. 1657218893Sdim const std::string &OpName = OpInfo->Name; 1658218893Sdim for ( ; AliasOpNo < LastOpNo && 1659218893Sdim CGA.ResultInstOperandIndex[AliasOpNo].first == i; ++AliasOpNo) { 1660218893Sdim int SubIdx = CGA.ResultInstOperandIndex[AliasOpNo].second; 1661218893Sdim 1662218893Sdim // Find out what operand from the asmparser that this MCInst operand 1663218893Sdim // comes from. 1664218893Sdim switch (CGA.ResultOperands[AliasOpNo].Kind) { 1665218893Sdim case CodeGenInstAlias::ResultOperand::K_Record: { 1666218893Sdim StringRef Name = CGA.ResultOperands[AliasOpNo].getName(); 1667245431Sdim int SrcOperand = findAsmOperand(Name, SubIdx); 1668218893Sdim if (SrcOperand == -1) 1669245431Sdim PrintFatalError(TheDef->getLoc(), "Instruction '" + 1670218893Sdim TheDef->getName() + "' has operand '" + OpName + 1671218893Sdim "' that doesn't appear in asm string!"); 1672218893Sdim unsigned NumOperands = (SubIdx == -1 ? OpInfo->MINumOperands : 1); 1673218893Sdim ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, 1674218893Sdim NumOperands)); 1675218893Sdim break; 1676218893Sdim } 1677218893Sdim case CodeGenInstAlias::ResultOperand::K_Imm: { 1678218893Sdim int64_t ImmVal = CGA.ResultOperands[AliasOpNo].getImm(); 1679218893Sdim ResOperands.push_back(ResOperand::getImmOp(ImmVal)); 1680218893Sdim break; 1681218893Sdim } 1682218893Sdim case CodeGenInstAlias::ResultOperand::K_Reg: { 1683218893Sdim Record *Reg = CGA.ResultOperands[AliasOpNo].getRegister(); 1684218893Sdim ResOperands.push_back(ResOperand::getRegOp(Reg)); 1685218893Sdim break; 1686218893Sdim } 1687218893Sdim } 1688218893Sdim } 1689218893Sdim } 1690218893Sdim} 1691218893Sdim 1692245431Sdimstatic unsigned getConverterOperandID(const std::string &Name, 1693245431Sdim SetVector<std::string> &Table, 1694245431Sdim bool &IsNew) { 1695245431Sdim IsNew = Table.insert(Name); 1696245431Sdim 1697245431Sdim unsigned ID = IsNew ? Table.size() - 1 : 1698245431Sdim std::find(Table.begin(), Table.end(), Name) - Table.begin(); 1699245431Sdim 1700245431Sdim assert(ID < Table.size()); 1701245431Sdim 1702245431Sdim return ID; 1703245431Sdim} 1704245431Sdim 1705245431Sdim 1706245431Sdimstatic void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, 1707245431Sdim std::vector<MatchableInfo*> &Infos, 1708245431Sdim raw_ostream &OS) { 1709245431Sdim SetVector<std::string> OperandConversionKinds; 1710245431Sdim SetVector<std::string> InstructionConversionKinds; 1711245431Sdim std::vector<std::vector<uint8_t> > ConversionTable; 1712245431Sdim size_t MaxRowLength = 2; // minimum is custom converter plus terminator. 1713245431Sdim 1714245431Sdim // TargetOperandClass - This is the target's operand class, like X86Operand. 1715245431Sdim std::string TargetOperandClass = Target.getName() + "Operand"; 1716245431Sdim 1717198090Srdivacky // Write the convert function to a separate stream, so we can drop it after 1718245431Sdim // the enum. We'll build up the conversion handlers for the individual 1719245431Sdim // operand types opportunistically as we encounter them. 1720198090Srdivacky std::string ConvertFnBody; 1721198090Srdivacky raw_string_ostream CvtOS(ConvertFnBody); 1722198090Srdivacky // Start the unified conversion function. 1723245431Sdim CvtOS << "void " << Target.getName() << ClassName << "::\n" 1724245431Sdim << "convertToMCInst(unsigned Kind, MCInst &Inst, " 1725198090Srdivacky << "unsigned Opcode,\n" 1726245431Sdim << " const SmallVectorImpl<MCParsedAsmOperand*" 1727245431Sdim << "> &Operands) {\n" 1728245431Sdim << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n" 1729245431Sdim << " const uint8_t *Converter = ConversionTable[Kind];\n" 1730245431Sdim << " Inst.setOpcode(Opcode);\n" 1731245431Sdim << " for (const uint8_t *p = Converter; *p; p+= 2) {\n" 1732245431Sdim << " switch (*p) {\n" 1733245431Sdim << " default: llvm_unreachable(\"invalid conversion entry!\");\n" 1734245431Sdim << " case CVT_Reg:\n" 1735245431Sdim << " static_cast<" << TargetOperandClass 1736245431Sdim << "*>(Operands[*(p + 1)])->addRegOperands(Inst, 1);\n" 1737245431Sdim << " break;\n" 1738245431Sdim << " case CVT_Tied:\n" 1739245431Sdim << " Inst.addOperand(Inst.getOperand(*(p + 1)));\n" 1740245431Sdim << " break;\n"; 1741198090Srdivacky 1742245431Sdim std::string OperandFnBody; 1743245431Sdim raw_string_ostream OpOS(OperandFnBody); 1744245431Sdim // Start the operand number lookup function. 1745245431Sdim OpOS << "void " << Target.getName() << ClassName << "::\n" 1746245431Sdim << "convertToMapAndConstraints(unsigned Kind,\n"; 1747245431Sdim OpOS.indent(27); 1748245431Sdim OpOS << "const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {\n" 1749245431Sdim << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n" 1750245431Sdim << " unsigned NumMCOperands = 0;\n" 1751245431Sdim << " const uint8_t *Converter = ConversionTable[Kind];\n" 1752245431Sdim << " for (const uint8_t *p = Converter; *p; p+= 2) {\n" 1753245431Sdim << " switch (*p) {\n" 1754245431Sdim << " default: llvm_unreachable(\"invalid conversion entry!\");\n" 1755245431Sdim << " case CVT_Reg:\n" 1756245431Sdim << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n" 1757252723Sdim << " Operands[*(p + 1)]->setConstraint(\"r\");\n" 1758245431Sdim << " ++NumMCOperands;\n" 1759245431Sdim << " break;\n" 1760245431Sdim << " case CVT_Tied:\n" 1761245431Sdim << " ++NumMCOperands;\n" 1762245431Sdim << " break;\n"; 1763198090Srdivacky 1764245431Sdim // Pre-populate the operand conversion kinds with the standard always 1765245431Sdim // available entries. 1766245431Sdim OperandConversionKinds.insert("CVT_Done"); 1767245431Sdim OperandConversionKinds.insert("CVT_Reg"); 1768245431Sdim OperandConversionKinds.insert("CVT_Tied"); 1769245431Sdim enum { CVT_Done, CVT_Reg, CVT_Tied }; 1770218893Sdim 1771218893Sdim for (std::vector<MatchableInfo*>::const_iterator it = Infos.begin(), 1772198090Srdivacky ie = Infos.end(); it != ie; ++it) { 1773218893Sdim MatchableInfo &II = **it; 1774198090Srdivacky 1775218893Sdim // Check if we have a custom match function. 1776221345Sdim std::string AsmMatchConverter = 1777221345Sdim II.getResultInst()->TheDef->getValueAsString("AsmMatchConverter"); 1778218893Sdim if (!AsmMatchConverter.empty()) { 1779221345Sdim std::string Signature = "ConvertCustom_" + AsmMatchConverter; 1780218893Sdim II.ConversionFnKind = Signature; 1781203954Srdivacky 1782218893Sdim // Check if we have already generated this signature. 1783245431Sdim if (!InstructionConversionKinds.insert(Signature)) 1784218893Sdim continue; 1785203954Srdivacky 1786245431Sdim // Remember this converter for the kind enum. 1787245431Sdim unsigned KindID = OperandConversionKinds.size(); 1788252723Sdim OperandConversionKinds.insert("CVT_" + 1789252723Sdim getEnumNameForToken(AsmMatchConverter)); 1790198090Srdivacky 1791245431Sdim // Add the converter row for this instruction. 1792245431Sdim ConversionTable.push_back(std::vector<uint8_t>()); 1793245431Sdim ConversionTable.back().push_back(KindID); 1794245431Sdim ConversionTable.back().push_back(CVT_Done); 1795245431Sdim 1796245431Sdim // Add the handler to the conversion driver function. 1797252723Sdim CvtOS << " case CVT_" 1798252723Sdim << getEnumNameForToken(AsmMatchConverter) << ":\n" 1799245431Sdim << " " << AsmMatchConverter << "(Inst, Operands);\n" 1800245431Sdim << " break;\n"; 1801245431Sdim 1802245431Sdim // FIXME: Handle the operand number lookup for custom match functions. 1803218893Sdim continue; 1804198090Srdivacky } 1805198090Srdivacky 1806198090Srdivacky // Build the conversion function signature. 1807198090Srdivacky std::string Signature = "Convert"; 1808198090Srdivacky 1809245431Sdim std::vector<uint8_t> ConversionRow; 1810245431Sdim 1811218893Sdim // Compute the convert enum and the case body. 1812245431Sdim MaxRowLength = std::max(MaxRowLength, II.ResOperands.size()*2 + 1 ); 1813245431Sdim 1814218893Sdim for (unsigned i = 0, e = II.ResOperands.size(); i != e; ++i) { 1815218893Sdim const MatchableInfo::ResOperand &OpInfo = II.ResOperands[i]; 1816203954Srdivacky 1817218893Sdim // Generate code to populate each result operand. 1818218893Sdim switch (OpInfo.Kind) { 1819218893Sdim case MatchableInfo::ResOperand::RenderAsmOperand: { 1820218893Sdim // This comes from something we parsed. 1821218893Sdim MatchableInfo::AsmOperand &Op = II.AsmOperands[OpInfo.AsmOperandNum]; 1822198090Srdivacky 1823218893Sdim // Registers are always converted the same, don't duplicate the 1824218893Sdim // conversion function based on them. 1825218893Sdim Signature += "__"; 1826245431Sdim std::string Class; 1827245431Sdim Class = Op.Class->isRegisterClass() ? "Reg" : Op.Class->ClassName; 1828245431Sdim Signature += Class; 1829218893Sdim Signature += utostr(OpInfo.MINumOperands); 1830218893Sdim Signature += "_" + itostr(OpInfo.AsmOperandNum); 1831198090Srdivacky 1832245431Sdim // Add the conversion kind, if necessary, and get the associated ID 1833245431Sdim // the index of its entry in the vector). 1834245431Sdim std::string Name = "CVT_" + (Op.Class->isRegisterClass() ? "Reg" : 1835245431Sdim Op.Class->RenderMethod); 1836252723Sdim Name = getEnumNameForToken(Name); 1837245431Sdim 1838245431Sdim bool IsNewConverter = false; 1839245431Sdim unsigned ID = getConverterOperandID(Name, OperandConversionKinds, 1840245431Sdim IsNewConverter); 1841245431Sdim 1842245431Sdim // Add the operand entry to the instruction kind conversion row. 1843245431Sdim ConversionRow.push_back(ID); 1844245431Sdim ConversionRow.push_back(OpInfo.AsmOperandNum + 1); 1845245431Sdim 1846245431Sdim if (!IsNewConverter) 1847245431Sdim break; 1848245431Sdim 1849245431Sdim // This is a new operand kind. Add a handler for it to the 1850245431Sdim // converter driver. 1851245431Sdim CvtOS << " case " << Name << ":\n" 1852245431Sdim << " static_cast<" << TargetOperandClass 1853245431Sdim << "*>(Operands[*(p + 1)])->" 1854245431Sdim << Op.Class->RenderMethod << "(Inst, " << OpInfo.MINumOperands 1855245431Sdim << ");\n" 1856245431Sdim << " break;\n"; 1857245431Sdim 1858245431Sdim // Add a handler for the operand number lookup. 1859245431Sdim OpOS << " case " << Name << ":\n" 1860252723Sdim << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n"; 1861252723Sdim 1862252723Sdim if (Op.Class->isRegisterClass()) 1863252723Sdim OpOS << " Operands[*(p + 1)]->setConstraint(\"r\");\n"; 1864252723Sdim else 1865252723Sdim OpOS << " Operands[*(p + 1)]->setConstraint(\"m\");\n"; 1866252723Sdim OpOS << " NumMCOperands += " << OpInfo.MINumOperands << ";\n" 1867245431Sdim << " break;\n"; 1868218893Sdim break; 1869218893Sdim } 1870218893Sdim case MatchableInfo::ResOperand::TiedOperand: { 1871218893Sdim // If this operand is tied to a previous one, just copy the MCInst 1872218893Sdim // operand from the earlier one.We can only tie single MCOperand values. 1873252723Sdim assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand"); 1874218893Sdim unsigned TiedOp = OpInfo.TiedOperandNum; 1875221345Sdim assert(i > TiedOp && "Tied operand precedes its target!"); 1876218893Sdim Signature += "__Tie" + utostr(TiedOp); 1877245431Sdim ConversionRow.push_back(CVT_Tied); 1878245431Sdim ConversionRow.push_back(TiedOp); 1879218893Sdim break; 1880218893Sdim } 1881218893Sdim case MatchableInfo::ResOperand::ImmOperand: { 1882218893Sdim int64_t Val = OpInfo.ImmVal; 1883245431Sdim std::string Ty = "imm_" + itostr(Val); 1884245431Sdim Signature += "__" + Ty; 1885245431Sdim 1886245431Sdim std::string Name = "CVT_" + Ty; 1887245431Sdim bool IsNewConverter = false; 1888245431Sdim unsigned ID = getConverterOperandID(Name, OperandConversionKinds, 1889245431Sdim IsNewConverter); 1890245431Sdim // Add the operand entry to the instruction kind conversion row. 1891245431Sdim ConversionRow.push_back(ID); 1892245431Sdim ConversionRow.push_back(0); 1893245431Sdim 1894245431Sdim if (!IsNewConverter) 1895245431Sdim break; 1896245431Sdim 1897245431Sdim CvtOS << " case " << Name << ":\n" 1898245431Sdim << " Inst.addOperand(MCOperand::CreateImm(" << Val << "));\n" 1899245431Sdim << " break;\n"; 1900245431Sdim 1901245431Sdim OpOS << " case " << Name << ":\n" 1902245431Sdim << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n" 1903245431Sdim << " Operands[*(p + 1)]->setConstraint(\"\");\n" 1904245431Sdim << " ++NumMCOperands;\n" 1905245431Sdim << " break;\n"; 1906218893Sdim break; 1907218893Sdim } 1908218893Sdim case MatchableInfo::ResOperand::RegOperand: { 1909245431Sdim std::string Reg, Name; 1910218893Sdim if (OpInfo.Register == 0) { 1911245431Sdim Name = "reg0"; 1912245431Sdim Reg = "0"; 1913218893Sdim } else { 1914245431Sdim Reg = getQualifiedName(OpInfo.Register); 1915245431Sdim Name = "reg" + OpInfo.Register->getName(); 1916218893Sdim } 1917245431Sdim Signature += "__" + Name; 1918245431Sdim Name = "CVT_" + Name; 1919245431Sdim bool IsNewConverter = false; 1920245431Sdim unsigned ID = getConverterOperandID(Name, OperandConversionKinds, 1921245431Sdim IsNewConverter); 1922245431Sdim // Add the operand entry to the instruction kind conversion row. 1923245431Sdim ConversionRow.push_back(ID); 1924245431Sdim ConversionRow.push_back(0); 1925245431Sdim 1926245431Sdim if (!IsNewConverter) 1927245431Sdim break; 1928245431Sdim CvtOS << " case " << Name << ":\n" 1929245431Sdim << " Inst.addOperand(MCOperand::CreateReg(" << Reg << "));\n" 1930245431Sdim << " break;\n"; 1931245431Sdim 1932245431Sdim OpOS << " case " << Name << ":\n" 1933245431Sdim << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n" 1934245431Sdim << " Operands[*(p + 1)]->setConstraint(\"m\");\n" 1935245431Sdim << " ++NumMCOperands;\n" 1936245431Sdim << " break;\n"; 1937218893Sdim } 1938218893Sdim } 1939203954Srdivacky } 1940198090Srdivacky 1941245431Sdim // If there were no operands, add to the signature to that effect 1942245431Sdim if (Signature == "Convert") 1943245431Sdim Signature += "_NoOperands"; 1944245431Sdim 1945198090Srdivacky II.ConversionFnKind = Signature; 1946198090Srdivacky 1947245431Sdim // Save the signature. If we already have it, don't add a new row 1948245431Sdim // to the table. 1949245431Sdim if (!InstructionConversionKinds.insert(Signature)) 1950198090Srdivacky continue; 1951198090Srdivacky 1952245431Sdim // Add the row to the table. 1953245431Sdim ConversionTable.push_back(ConversionRow); 1954198090Srdivacky } 1955198090Srdivacky 1956245431Sdim // Finish up the converter driver function. 1957245431Sdim CvtOS << " }\n }\n}\n\n"; 1958198090Srdivacky 1959245431Sdim // Finish up the operand number lookup function. 1960245431Sdim OpOS << " }\n }\n}\n\n"; 1961198090Srdivacky 1962245431Sdim OS << "namespace {\n"; 1963198090Srdivacky 1964245431Sdim // Output the operand conversion kind enum. 1965245431Sdim OS << "enum OperatorConversionKind {\n"; 1966245431Sdim for (unsigned i = 0, e = OperandConversionKinds.size(); i != e; ++i) 1967245431Sdim OS << " " << OperandConversionKinds[i] << ",\n"; 1968245431Sdim OS << " CVT_NUM_CONVERTERS\n"; 1969198090Srdivacky OS << "};\n\n"; 1970218893Sdim 1971245431Sdim // Output the instruction conversion kind enum. 1972245431Sdim OS << "enum InstructionConversionKind {\n"; 1973245431Sdim for (SetVector<std::string>::const_iterator 1974245431Sdim i = InstructionConversionKinds.begin(), 1975245431Sdim e = InstructionConversionKinds.end(); i != e; ++i) 1976245431Sdim OS << " " << *i << ",\n"; 1977245431Sdim OS << " CVT_NUM_SIGNATURES\n"; 1978245431Sdim OS << "};\n\n"; 1979245431Sdim 1980245431Sdim 1981245431Sdim OS << "} // end anonymous namespace\n\n"; 1982245431Sdim 1983245431Sdim // Output the conversion table. 1984245431Sdim OS << "static const uint8_t ConversionTable[CVT_NUM_SIGNATURES][" 1985245431Sdim << MaxRowLength << "] = {\n"; 1986245431Sdim 1987245431Sdim for (unsigned Row = 0, ERow = ConversionTable.size(); Row != ERow; ++Row) { 1988245431Sdim assert(ConversionTable[Row].size() % 2 == 0 && "bad conversion row!"); 1989245431Sdim OS << " // " << InstructionConversionKinds[Row] << "\n"; 1990245431Sdim OS << " { "; 1991245431Sdim for (unsigned i = 0, e = ConversionTable[Row].size(); i != e; i += 2) 1992245431Sdim OS << OperandConversionKinds[ConversionTable[Row][i]] << ", " 1993245431Sdim << (unsigned)(ConversionTable[Row][i + 1]) << ", "; 1994245431Sdim OS << "CVT_Done },\n"; 1995245431Sdim } 1996245431Sdim 1997245431Sdim OS << "};\n\n"; 1998245431Sdim 1999245431Sdim // Spit out the conversion driver function. 2000198090Srdivacky OS << CvtOS.str(); 2001245431Sdim 2002245431Sdim // Spit out the operand number lookup function. 2003245431Sdim OS << OpOS.str(); 2004198090Srdivacky} 2005198090Srdivacky 2006245431Sdim/// emitMatchClassEnumeration - Emit the enumeration for match class kinds. 2007245431Sdimstatic void emitMatchClassEnumeration(CodeGenTarget &Target, 2008198090Srdivacky std::vector<ClassInfo*> &Infos, 2009198090Srdivacky raw_ostream &OS) { 2010198090Srdivacky OS << "namespace {\n\n"; 2011198090Srdivacky 2012198090Srdivacky OS << "/// MatchClassKind - The kinds of classes which participate in\n" 2013198090Srdivacky << "/// instruction matching.\n"; 2014198090Srdivacky OS << "enum MatchClassKind {\n"; 2015198090Srdivacky OS << " InvalidMatchClass = 0,\n"; 2016218893Sdim for (std::vector<ClassInfo*>::iterator it = Infos.begin(), 2017198090Srdivacky ie = Infos.end(); it != ie; ++it) { 2018198090Srdivacky ClassInfo &CI = **it; 2019198090Srdivacky OS << " " << CI.Name << ", // "; 2020198090Srdivacky if (CI.Kind == ClassInfo::Token) { 2021198090Srdivacky OS << "'" << CI.ValueName << "'\n"; 2022198090Srdivacky } else if (CI.isRegisterClass()) { 2023198090Srdivacky if (!CI.ValueName.empty()) 2024198090Srdivacky OS << "register class '" << CI.ValueName << "'\n"; 2025198090Srdivacky else 2026198090Srdivacky OS << "derived register class\n"; 2027198090Srdivacky } else { 2028198090Srdivacky OS << "user defined class '" << CI.ValueName << "'\n"; 2029198090Srdivacky } 2030198090Srdivacky } 2031198090Srdivacky OS << " NumMatchClassKinds\n"; 2032198090Srdivacky OS << "};\n\n"; 2033198090Srdivacky 2034198090Srdivacky OS << "}\n\n"; 2035198090Srdivacky} 2036198090Srdivacky 2037245431Sdim/// emitValidateOperandClass - Emit the function to validate an operand class. 2038245431Sdimstatic void emitValidateOperandClass(AsmMatcherInfo &Info, 2039218893Sdim raw_ostream &OS) { 2040245431Sdim OS << "static unsigned validateOperandClass(MCParsedAsmOperand *GOp, " 2041218893Sdim << "MatchClassKind Kind) {\n"; 2042218893Sdim OS << " " << Info.Target.getName() << "Operand &Operand = *(" 2043218893Sdim << Info.Target.getName() << "Operand*)GOp;\n"; 2044198090Srdivacky 2045224145Sdim // The InvalidMatchClass is not to match any operand. 2046224145Sdim OS << " if (Kind == InvalidMatchClass)\n"; 2047245431Sdim OS << " return MCTargetAsmParser::Match_InvalidOperand;\n\n"; 2048224145Sdim 2049218893Sdim // Check for Token operands first. 2050245431Sdim // FIXME: Use a more specific diagnostic type. 2051198090Srdivacky OS << " if (Operand.isToken())\n"; 2052245431Sdim OS << " return isSubclass(matchTokenString(Operand.getToken()), Kind) ?\n" 2053245431Sdim << " MCTargetAsmParser::Match_Success :\n" 2054245431Sdim << " MCTargetAsmParser::Match_InvalidOperand;\n\n"; 2055198090Srdivacky 2056218893Sdim // Check the user classes. We don't care what order since we're only 2057218893Sdim // actually matching against one of them. 2058218893Sdim for (std::vector<ClassInfo*>::iterator it = Info.Classes.begin(), 2059198090Srdivacky ie = Info.Classes.end(); it != ie; ++it) { 2060198090Srdivacky ClassInfo &CI = **it; 2061198090Srdivacky 2062198090Srdivacky if (!CI.isUserClass()) 2063198090Srdivacky continue; 2064198090Srdivacky 2065218893Sdim OS << " // '" << CI.ClassName << "' class\n"; 2066245431Sdim OS << " if (Kind == " << CI.Name << ") {\n"; 2067245431Sdim OS << " if (Operand." << CI.PredicateMethod << "())\n"; 2068245431Sdim OS << " return MCTargetAsmParser::Match_Success;\n"; 2069245431Sdim if (!CI.DiagnosticType.empty()) 2070245431Sdim OS << " return " << Info.Target.getName() << "AsmParser::Match_" 2071245431Sdim << CI.DiagnosticType << ";\n"; 2072198090Srdivacky OS << " }\n\n"; 2073198090Srdivacky } 2074218893Sdim 2075245431Sdim // Check for register operands, including sub-classes. 2076245431Sdim OS << " if (Operand.isReg()) {\n"; 2077245431Sdim OS << " MatchClassKind OpKind;\n"; 2078245431Sdim OS << " switch (Operand.getReg()) {\n"; 2079245431Sdim OS << " default: OpKind = InvalidMatchClass; break;\n"; 2080245431Sdim for (AsmMatcherInfo::RegisterClassesTy::iterator 2081245431Sdim it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end(); 2082245431Sdim it != ie; ++it) 2083245431Sdim OS << " case " << Info.Target.getName() << "::" 2084245431Sdim << it->first->getName() << ": OpKind = " << it->second->Name 2085245431Sdim << "; break;\n"; 2086245431Sdim OS << " }\n"; 2087245431Sdim OS << " return isSubclass(OpKind, Kind) ? " 2088245431Sdim << "MCTargetAsmParser::Match_Success :\n " 2089245431Sdim << " MCTargetAsmParser::Match_InvalidOperand;\n }\n\n"; 2090245431Sdim 2091245431Sdim // Generic fallthrough match failure case for operands that don't have 2092245431Sdim // specialized diagnostic types. 2093245431Sdim OS << " return MCTargetAsmParser::Match_InvalidOperand;\n"; 2094198090Srdivacky OS << "}\n\n"; 2095198090Srdivacky} 2096198090Srdivacky 2097245431Sdim/// emitIsSubclass - Emit the subclass predicate function. 2098245431Sdimstatic void emitIsSubclass(CodeGenTarget &Target, 2099198090Srdivacky std::vector<ClassInfo*> &Infos, 2100198090Srdivacky raw_ostream &OS) { 2101245431Sdim OS << "/// isSubclass - Compute whether \\p A is a subclass of \\p B.\n"; 2102235633Sdim OS << "static bool isSubclass(MatchClassKind A, MatchClassKind B) {\n"; 2103198090Srdivacky OS << " if (A == B)\n"; 2104198090Srdivacky OS << " return true;\n\n"; 2105198090Srdivacky 2106263509Sdim std::string OStr; 2107263509Sdim raw_string_ostream SS(OStr); 2108263509Sdim unsigned Count = 0; 2109263509Sdim SS << " switch (A) {\n"; 2110263509Sdim SS << " default:\n"; 2111263509Sdim SS << " return false;\n"; 2112218893Sdim for (std::vector<ClassInfo*>::iterator it = Infos.begin(), 2113198090Srdivacky ie = Infos.end(); it != ie; ++it) { 2114198090Srdivacky ClassInfo &A = **it; 2115198090Srdivacky 2116235633Sdim std::vector<StringRef> SuperClasses; 2117235633Sdim for (std::vector<ClassInfo*>::iterator it = Infos.begin(), 2118235633Sdim ie = Infos.end(); it != ie; ++it) { 2119235633Sdim ClassInfo &B = **it; 2120198090Srdivacky 2121235633Sdim if (&A != &B && A.isSubsetOf(B)) 2122235633Sdim SuperClasses.push_back(B.Name); 2123235633Sdim } 2124198090Srdivacky 2125235633Sdim if (SuperClasses.empty()) 2126235633Sdim continue; 2127263509Sdim ++Count; 2128198090Srdivacky 2129263509Sdim SS << "\n case " << A.Name << ":\n"; 2130198090Srdivacky 2131235633Sdim if (SuperClasses.size() == 1) { 2132263509Sdim SS << " return B == " << SuperClasses.back().str() << ";\n"; 2133235633Sdim continue; 2134235633Sdim } 2135198090Srdivacky 2136263509Sdim if (!SuperClasses.empty()) { 2137263509Sdim SS << " switch (B) {\n"; 2138263509Sdim SS << " default: return false;\n"; 2139263509Sdim for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) 2140263509Sdim SS << " case " << SuperClasses[i].str() << ": return true;\n"; 2141263509Sdim SS << " }\n"; 2142263509Sdim } else { 2143263509Sdim // No case statement to emit 2144263509Sdim SS << " return false;\n"; 2145263509Sdim } 2146198090Srdivacky } 2147263509Sdim SS << " }\n"; 2148263509Sdim 2149263509Sdim // If there were case statements emitted into the string stream, write them 2150263509Sdim // to the output stream, otherwise write the default. 2151263509Sdim if (Count) 2152263509Sdim OS << SS.str(); 2153263509Sdim else 2154263509Sdim OS << " return false;\n"; 2155263509Sdim 2156198090Srdivacky OS << "}\n\n"; 2157198090Srdivacky} 2158198090Srdivacky 2159245431Sdim/// emitMatchTokenString - Emit the function to match a token string to the 2160198090Srdivacky/// appropriate match class value. 2161245431Sdimstatic void emitMatchTokenString(CodeGenTarget &Target, 2162198090Srdivacky std::vector<ClassInfo*> &Infos, 2163198090Srdivacky raw_ostream &OS) { 2164198090Srdivacky // Construct the match list. 2165218893Sdim std::vector<StringMatcher::StringPair> Matches; 2166218893Sdim for (std::vector<ClassInfo*>::iterator it = Infos.begin(), 2167198090Srdivacky ie = Infos.end(); it != ie; ++it) { 2168198090Srdivacky ClassInfo &CI = **it; 2169198090Srdivacky 2170198090Srdivacky if (CI.Kind == ClassInfo::Token) 2171218893Sdim Matches.push_back(StringMatcher::StringPair(CI.ValueName, 2172218893Sdim "return " + CI.Name + ";")); 2173198090Srdivacky } 2174198090Srdivacky 2175235633Sdim OS << "static MatchClassKind matchTokenString(StringRef Name) {\n"; 2176198090Srdivacky 2177218893Sdim StringMatcher("Name", Matches, OS).Emit(); 2178198090Srdivacky 2179198090Srdivacky OS << " return InvalidMatchClass;\n"; 2180198090Srdivacky OS << "}\n\n"; 2181198090Srdivacky} 2182198090Srdivacky 2183245431Sdim/// emitMatchRegisterName - Emit the function to match a string to the target 2184198090Srdivacky/// specific register enum. 2185245431Sdimstatic void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, 2186198090Srdivacky raw_ostream &OS) { 2187198090Srdivacky // Construct the match list. 2188218893Sdim std::vector<StringMatcher::StringPair> Matches; 2189224145Sdim const std::vector<CodeGenRegister*> &Regs = 2190224145Sdim Target.getRegBank().getRegisters(); 2191224145Sdim for (unsigned i = 0, e = Regs.size(); i != e; ++i) { 2192224145Sdim const CodeGenRegister *Reg = Regs[i]; 2193224145Sdim if (Reg->TheDef->getValueAsString("AsmName").empty()) 2194198090Srdivacky continue; 2195198090Srdivacky 2196218893Sdim Matches.push_back(StringMatcher::StringPair( 2197224145Sdim Reg->TheDef->getValueAsString("AsmName"), 2198224145Sdim "return " + utostr(Reg->EnumValue) + ";")); 2199198090Srdivacky } 2200218893Sdim 2201203954Srdivacky OS << "static unsigned MatchRegisterName(StringRef Name) {\n"; 2202198090Srdivacky 2203218893Sdim StringMatcher("Name", Matches, OS).Emit(); 2204218893Sdim 2205198090Srdivacky OS << " return 0;\n"; 2206198090Srdivacky OS << "}\n\n"; 2207198090Srdivacky} 2208198090Srdivacky 2209245431Sdim/// emitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag 2210212904Sdim/// definitions. 2211245431Sdimstatic void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, 2212212904Sdim raw_ostream &OS) { 2213212904Sdim OS << "// Flags for subtarget features that participate in " 2214212904Sdim << "instruction matching.\n"; 2215212904Sdim OS << "enum SubtargetFeatureFlag {\n"; 2216263509Sdim for (std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator 2217212904Sdim it = Info.SubtargetFeatures.begin(), 2218212904Sdim ie = Info.SubtargetFeatures.end(); it != ie; ++it) { 2219212904Sdim SubtargetFeatureInfo &SFI = *it->second; 2220218893Sdim OS << " " << SFI.getEnumName() << " = (1 << " << SFI.Index << "),\n"; 2221212904Sdim } 2222212904Sdim OS << " Feature_None = 0\n"; 2223212904Sdim OS << "};\n\n"; 2224212904Sdim} 2225212904Sdim 2226245431Sdim/// emitOperandDiagnosticTypes - Emit the operand matching diagnostic types. 2227245431Sdimstatic void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) { 2228245431Sdim // Get the set of diagnostic types from all of the operand classes. 2229245431Sdim std::set<StringRef> Types; 2230245431Sdim for (std::map<Record*, ClassInfo*>::const_iterator 2231245431Sdim I = Info.AsmOperandClasses.begin(), 2232245431Sdim E = Info.AsmOperandClasses.end(); I != E; ++I) { 2233245431Sdim if (!I->second->DiagnosticType.empty()) 2234245431Sdim Types.insert(I->second->DiagnosticType); 2235245431Sdim } 2236245431Sdim 2237245431Sdim if (Types.empty()) return; 2238245431Sdim 2239245431Sdim // Now emit the enum entries. 2240245431Sdim for (std::set<StringRef>::const_iterator I = Types.begin(), E = Types.end(); 2241245431Sdim I != E; ++I) 2242245431Sdim OS << " Match_" << *I << ",\n"; 2243245431Sdim OS << " END_OPERAND_DIAGNOSTIC_TYPES\n"; 2244245431Sdim} 2245245431Sdim 2246245431Sdim/// emitGetSubtargetFeatureName - Emit the helper function to get the 2247245431Sdim/// user-level name for a subtarget feature. 2248245431Sdimstatic void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) { 2249245431Sdim OS << "// User-level names for subtarget features that participate in\n" 2250245431Sdim << "// instruction matching.\n" 2251263509Sdim << "static const char *getSubtargetFeatureName(unsigned Val) {\n"; 2252263509Sdim if (!Info.SubtargetFeatures.empty()) { 2253263509Sdim OS << " switch(Val) {\n"; 2254263509Sdim typedef std::map<Record*, SubtargetFeatureInfo*, LessRecordByID> RecFeatMap; 2255263509Sdim for (RecFeatMap::const_iterator it = Info.SubtargetFeatures.begin(), 2256263509Sdim ie = Info.SubtargetFeatures.end(); it != ie; ++it) { 2257263509Sdim SubtargetFeatureInfo &SFI = *it->second; 2258263509Sdim // FIXME: Totally just a placeholder name to get the algorithm working. 2259263509Sdim OS << " case " << SFI.getEnumName() << ": return \"" 2260263509Sdim << SFI.TheDef->getValueAsString("PredicateName") << "\";\n"; 2261263509Sdim } 2262263509Sdim OS << " default: return \"(unknown)\";\n"; 2263263509Sdim OS << " }\n"; 2264263509Sdim } else { 2265263509Sdim // Nothing to emit, so skip the switch 2266263509Sdim OS << " return \"(unknown)\";\n"; 2267245431Sdim } 2268263509Sdim OS << "}\n\n"; 2269245431Sdim} 2270245431Sdim 2271245431Sdim/// emitComputeAvailableFeatures - Emit the function to compute the list of 2272212904Sdim/// available features given a subtarget. 2273245431Sdimstatic void emitComputeAvailableFeatures(AsmMatcherInfo &Info, 2274212904Sdim raw_ostream &OS) { 2275212904Sdim std::string ClassName = 2276212904Sdim Info.AsmParser->getValueAsString("AsmParserClassName"); 2277212904Sdim 2278218893Sdim OS << "unsigned " << Info.Target.getName() << ClassName << "::\n" 2279224145Sdim << "ComputeAvailableFeatures(uint64_t FB) const {\n"; 2280212904Sdim OS << " unsigned Features = 0;\n"; 2281263509Sdim for (std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator 2282212904Sdim it = Info.SubtargetFeatures.begin(), 2283212904Sdim ie = Info.SubtargetFeatures.end(); it != ie; ++it) { 2284212904Sdim SubtargetFeatureInfo &SFI = *it->second; 2285224145Sdim 2286224145Sdim OS << " if ("; 2287235633Sdim std::string CondStorage = 2288235633Sdim SFI.TheDef->getValueAsString("AssemblerCondString"); 2289224145Sdim StringRef Conds = CondStorage; 2290224145Sdim std::pair<StringRef,StringRef> Comma = Conds.split(','); 2291224145Sdim bool First = true; 2292224145Sdim do { 2293224145Sdim if (!First) 2294224145Sdim OS << " && "; 2295224145Sdim 2296224145Sdim bool Neg = false; 2297224145Sdim StringRef Cond = Comma.first; 2298224145Sdim if (Cond[0] == '!') { 2299224145Sdim Neg = true; 2300224145Sdim Cond = Cond.substr(1); 2301224145Sdim } 2302224145Sdim 2303224145Sdim OS << "((FB & " << Info.Target.getName() << "::" << Cond << ")"; 2304224145Sdim if (Neg) 2305224145Sdim OS << " == 0"; 2306224145Sdim else 2307224145Sdim OS << " != 0"; 2308224145Sdim OS << ")"; 2309224145Sdim 2310224145Sdim if (Comma.second.empty()) 2311224145Sdim break; 2312224145Sdim 2313224145Sdim First = false; 2314224145Sdim Comma = Comma.second.split(','); 2315224145Sdim } while (true); 2316224145Sdim 2317224145Sdim OS << ")\n"; 2318218893Sdim OS << " Features |= " << SFI.getEnumName() << ";\n"; 2319212904Sdim } 2320212904Sdim OS << " return Features;\n"; 2321212904Sdim OS << "}\n\n"; 2322212904Sdim} 2323212904Sdim 2324218893Sdimstatic std::string GetAliasRequiredFeatures(Record *R, 2325218893Sdim const AsmMatcherInfo &Info) { 2326218893Sdim std::vector<Record*> ReqFeatures = R->getValueAsListOfDefs("Predicates"); 2327218893Sdim std::string Result; 2328218893Sdim unsigned NumFeatures = 0; 2329218893Sdim for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) { 2330218893Sdim SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]); 2331218893Sdim 2332218893Sdim if (F == 0) 2333245431Sdim PrintFatalError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() + 2334218893Sdim "' is not marked as an AssemblerPredicate!"); 2335218893Sdim 2336218893Sdim if (NumFeatures) 2337218893Sdim Result += '|'; 2338218893Sdim 2339218893Sdim Result += F->getEnumName(); 2340218893Sdim ++NumFeatures; 2341218893Sdim } 2342218893Sdim 2343218893Sdim if (NumFeatures > 1) 2344218893Sdim Result = '(' + Result + ')'; 2345218893Sdim return Result; 2346218893Sdim} 2347218893Sdim 2348252723Sdimstatic void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info, 2349252723Sdim std::vector<Record*> &Aliases, 2350252723Sdim unsigned Indent = 0, 2351252723Sdim StringRef AsmParserVariantName = StringRef()){ 2352218893Sdim // Keep track of all the aliases from a mnemonic. Use an std::map so that the 2353218893Sdim // iteration order of the map is stable. 2354218893Sdim std::map<std::string, std::vector<Record*> > AliasesFromMnemonic; 2355218893Sdim 2356218893Sdim for (unsigned i = 0, e = Aliases.size(); i != e; ++i) { 2357218893Sdim Record *R = Aliases[i]; 2358252723Sdim // FIXME: Allow AssemblerVariantName to be a comma separated list. 2359252723Sdim std::string AsmVariantName = R->getValueAsString("AsmVariantName"); 2360252723Sdim if (AsmVariantName != AsmParserVariantName) 2361252723Sdim continue; 2362218893Sdim AliasesFromMnemonic[R->getValueAsString("FromMnemonic")].push_back(R); 2363218893Sdim } 2364252723Sdim if (AliasesFromMnemonic.empty()) 2365252723Sdim return; 2366263509Sdim 2367218893Sdim // Process each alias a "from" mnemonic at a time, building the code executed 2368218893Sdim // by the string remapper. 2369218893Sdim std::vector<StringMatcher::StringPair> Cases; 2370218893Sdim for (std::map<std::string, std::vector<Record*> >::iterator 2371218893Sdim I = AliasesFromMnemonic.begin(), E = AliasesFromMnemonic.end(); 2372218893Sdim I != E; ++I) { 2373218893Sdim const std::vector<Record*> &ToVec = I->second; 2374218893Sdim 2375218893Sdim // Loop through each alias and emit code that handles each case. If there 2376218893Sdim // are two instructions without predicates, emit an error. If there is one, 2377218893Sdim // emit it last. 2378218893Sdim std::string MatchCode; 2379218893Sdim int AliasWithNoPredicate = -1; 2380218893Sdim 2381218893Sdim for (unsigned i = 0, e = ToVec.size(); i != e; ++i) { 2382218893Sdim Record *R = ToVec[i]; 2383218893Sdim std::string FeatureMask = GetAliasRequiredFeatures(R, Info); 2384218893Sdim 2385218893Sdim // If this unconditionally matches, remember it for later and diagnose 2386218893Sdim // duplicates. 2387218893Sdim if (FeatureMask.empty()) { 2388218893Sdim if (AliasWithNoPredicate != -1) { 2389218893Sdim // We can't have two aliases from the same mnemonic with no predicate. 2390218893Sdim PrintError(ToVec[AliasWithNoPredicate]->getLoc(), 2391218893Sdim "two MnemonicAliases with the same 'from' mnemonic!"); 2392245431Sdim PrintFatalError(R->getLoc(), "this is the other MnemonicAlias."); 2393218893Sdim } 2394218893Sdim 2395218893Sdim AliasWithNoPredicate = i; 2396218893Sdim continue; 2397218893Sdim } 2398218893Sdim if (R->getValueAsString("ToMnemonic") == I->first) 2399245431Sdim PrintFatalError(R->getLoc(), "MnemonicAlias to the same string"); 2400218893Sdim 2401218893Sdim if (!MatchCode.empty()) 2402218893Sdim MatchCode += "else "; 2403218893Sdim MatchCode += "if ((Features & " + FeatureMask + ") == "+FeatureMask+")\n"; 2404218893Sdim MatchCode += " Mnemonic = \"" +R->getValueAsString("ToMnemonic")+"\";\n"; 2405218893Sdim } 2406218893Sdim 2407218893Sdim if (AliasWithNoPredicate != -1) { 2408218893Sdim Record *R = ToVec[AliasWithNoPredicate]; 2409218893Sdim if (!MatchCode.empty()) 2410218893Sdim MatchCode += "else\n "; 2411218893Sdim MatchCode += "Mnemonic = \"" + R->getValueAsString("ToMnemonic")+"\";\n"; 2412218893Sdim } 2413218893Sdim 2414218893Sdim MatchCode += "return;"; 2415218893Sdim 2416218893Sdim Cases.push_back(std::make_pair(I->first, MatchCode)); 2417218893Sdim } 2418252723Sdim StringMatcher("Mnemonic", Cases, OS).Emit(Indent); 2419252723Sdim} 2420218893Sdim 2421252723Sdim/// emitMnemonicAliases - If the target has any MnemonicAlias<> definitions, 2422252723Sdim/// emit a function for them and return true, otherwise return false. 2423252723Sdimstatic bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info, 2424252723Sdim CodeGenTarget &Target) { 2425252723Sdim // Ignore aliases when match-prefix is set. 2426252723Sdim if (!MatchPrefix.empty()) 2427252723Sdim return false; 2428252723Sdim 2429252723Sdim std::vector<Record*> Aliases = 2430252723Sdim Info.getRecords().getAllDerivedDefinitions("MnemonicAlias"); 2431252723Sdim if (Aliases.empty()) return false; 2432252723Sdim 2433252723Sdim OS << "static void applyMnemonicAliases(StringRef &Mnemonic, " 2434252723Sdim "unsigned Features, unsigned VariantID) {\n"; 2435252723Sdim OS << " switch (VariantID) {\n"; 2436252723Sdim unsigned VariantCount = Target.getAsmParserVariantCount(); 2437252723Sdim for (unsigned VC = 0; VC != VariantCount; ++VC) { 2438252723Sdim Record *AsmVariant = Target.getAsmParserVariant(VC); 2439252723Sdim int AsmParserVariantNo = AsmVariant->getValueAsInt("Variant"); 2440252723Sdim std::string AsmParserVariantName = AsmVariant->getValueAsString("Name"); 2441252723Sdim OS << " case " << AsmParserVariantNo << ":\n"; 2442252723Sdim emitMnemonicAliasVariant(OS, Info, Aliases, /*Indent=*/2, 2443252723Sdim AsmParserVariantName); 2444252723Sdim OS << " break;\n"; 2445252723Sdim } 2446252723Sdim OS << " }\n"; 2447252723Sdim 2448252723Sdim // Emit aliases that apply to all variants. 2449252723Sdim emitMnemonicAliasVariant(OS, Info, Aliases); 2450252723Sdim 2451218893Sdim OS << "}\n\n"; 2452218893Sdim 2453218893Sdim return true; 2454218893Sdim} 2455218893Sdim 2456235633Sdimstatic const char *getMinimalTypeForRange(uint64_t Range) { 2457235633Sdim assert(Range < 0xFFFFFFFFULL && "Enum too large"); 2458235633Sdim if (Range > 0xFFFF) 2459235633Sdim return "uint32_t"; 2460235633Sdim if (Range > 0xFF) 2461235633Sdim return "uint16_t"; 2462235633Sdim return "uint8_t"; 2463235633Sdim} 2464235633Sdim 2465245431Sdimstatic void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, 2466245431Sdim const AsmMatcherInfo &Info, StringRef ClassName, 2467245431Sdim StringToOffsetTable &StringTable, 2468245431Sdim unsigned MaxMnemonicIndex) { 2469245431Sdim unsigned MaxMask = 0; 2470245431Sdim for (std::vector<OperandMatchEntry>::const_iterator it = 2471245431Sdim Info.OperandMatchInfo.begin(), ie = Info.OperandMatchInfo.end(); 2472245431Sdim it != ie; ++it) { 2473245431Sdim MaxMask |= it->OperandMask; 2474245431Sdim } 2475245431Sdim 2476218893Sdim // Emit the static custom operand parsing table; 2477218893Sdim OS << "namespace {\n"; 2478218893Sdim OS << " struct OperandMatchEntry {\n"; 2479235633Sdim OS << " " << getMinimalTypeForRange(1ULL << Info.SubtargetFeatures.size()) 2480235633Sdim << " RequiredFeatures;\n"; 2481245431Sdim OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) 2482245431Sdim << " Mnemonic;\n"; 2483235633Sdim OS << " " << getMinimalTypeForRange(Info.Classes.size()) 2484245431Sdim << " Class;\n"; 2485245431Sdim OS << " " << getMinimalTypeForRange(MaxMask) 2486245431Sdim << " OperandMask;\n\n"; 2487235633Sdim OS << " StringRef getMnemonic() const {\n"; 2488235633Sdim OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n"; 2489235633Sdim OS << " MnemonicTable[Mnemonic]);\n"; 2490235633Sdim OS << " }\n"; 2491218893Sdim OS << " };\n\n"; 2492218893Sdim 2493218893Sdim OS << " // Predicate for searching for an opcode.\n"; 2494218893Sdim OS << " struct LessOpcodeOperand {\n"; 2495218893Sdim OS << " bool operator()(const OperandMatchEntry &LHS, StringRef RHS) {\n"; 2496235633Sdim OS << " return LHS.getMnemonic() < RHS;\n"; 2497218893Sdim OS << " }\n"; 2498218893Sdim OS << " bool operator()(StringRef LHS, const OperandMatchEntry &RHS) {\n"; 2499235633Sdim OS << " return LHS < RHS.getMnemonic();\n"; 2500218893Sdim OS << " }\n"; 2501218893Sdim OS << " bool operator()(const OperandMatchEntry &LHS,"; 2502218893Sdim OS << " const OperandMatchEntry &RHS) {\n"; 2503235633Sdim OS << " return LHS.getMnemonic() < RHS.getMnemonic();\n"; 2504218893Sdim OS << " }\n"; 2505218893Sdim OS << " };\n"; 2506218893Sdim 2507218893Sdim OS << "} // end anonymous namespace.\n\n"; 2508218893Sdim 2509218893Sdim OS << "static const OperandMatchEntry OperandMatchTable[" 2510218893Sdim << Info.OperandMatchInfo.size() << "] = {\n"; 2511218893Sdim 2512235633Sdim OS << " /* Operand List Mask, Mnemonic, Operand Class, Features */\n"; 2513218893Sdim for (std::vector<OperandMatchEntry>::const_iterator it = 2514218893Sdim Info.OperandMatchInfo.begin(), ie = Info.OperandMatchInfo.end(); 2515218893Sdim it != ie; ++it) { 2516218893Sdim const OperandMatchEntry &OMI = *it; 2517218893Sdim const MatchableInfo &II = *OMI.MI; 2518218893Sdim 2519245431Sdim OS << " { "; 2520218893Sdim 2521245431Sdim // Write the required features mask. 2522245431Sdim if (!II.RequiredFeatures.empty()) { 2523245431Sdim for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) { 2524245431Sdim if (i) OS << "|"; 2525245431Sdim OS << II.RequiredFeatures[i]->getEnumName(); 2526245431Sdim } 2527245431Sdim } else 2528245431Sdim OS << "0"; 2529245431Sdim 2530245431Sdim // Store a pascal-style length byte in the mnemonic. 2531245431Sdim std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); 2532245431Sdim OS << ", " << StringTable.GetOrAddStringOffset(LenMnemonic, false) 2533245431Sdim << " /* " << II.Mnemonic << " */, "; 2534245431Sdim 2535245431Sdim OS << OMI.CI->Name; 2536245431Sdim 2537245431Sdim OS << ", " << OMI.OperandMask; 2538218893Sdim OS << " /* "; 2539218893Sdim bool printComma = false; 2540218893Sdim for (int i = 0, e = 31; i !=e; ++i) 2541218893Sdim if (OMI.OperandMask & (1 << i)) { 2542218893Sdim if (printComma) 2543218893Sdim OS << ", "; 2544218893Sdim OS << i; 2545218893Sdim printComma = true; 2546218893Sdim } 2547218893Sdim OS << " */"; 2548218893Sdim 2549218893Sdim OS << " },\n"; 2550218893Sdim } 2551218893Sdim OS << "};\n\n"; 2552218893Sdim 2553218893Sdim // Emit the operand class switch to call the correct custom parser for 2554218893Sdim // the found operand class. 2555218893Sdim OS << Target.getName() << ClassName << "::OperandMatchResultTy " 2556218893Sdim << Target.getName() << ClassName << "::\n" 2557235633Sdim << "tryCustomParseOperand(SmallVectorImpl<MCParsedAsmOperand*>" 2558218893Sdim << " &Operands,\n unsigned MCK) {\n\n" 2559218893Sdim << " switch(MCK) {\n"; 2560218893Sdim 2561218893Sdim for (std::vector<ClassInfo*>::const_iterator it = Info.Classes.begin(), 2562218893Sdim ie = Info.Classes.end(); it != ie; ++it) { 2563218893Sdim ClassInfo *CI = *it; 2564218893Sdim if (CI->ParserMethod.empty()) 2565218893Sdim continue; 2566218893Sdim OS << " case " << CI->Name << ":\n" 2567218893Sdim << " return " << CI->ParserMethod << "(Operands);\n"; 2568218893Sdim } 2569218893Sdim 2570218893Sdim OS << " default:\n"; 2571218893Sdim OS << " return MatchOperand_NoMatch;\n"; 2572218893Sdim OS << " }\n"; 2573218893Sdim OS << " return MatchOperand_NoMatch;\n"; 2574218893Sdim OS << "}\n\n"; 2575218893Sdim 2576218893Sdim // Emit the static custom operand parser. This code is very similar with 2577218893Sdim // the other matcher. Also use MatchResultTy here just in case we go for 2578218893Sdim // a better error handling. 2579218893Sdim OS << Target.getName() << ClassName << "::OperandMatchResultTy " 2580218893Sdim << Target.getName() << ClassName << "::\n" 2581218893Sdim << "MatchOperandParserImpl(SmallVectorImpl<MCParsedAsmOperand*>" 2582218893Sdim << " &Operands,\n StringRef Mnemonic) {\n"; 2583218893Sdim 2584218893Sdim // Emit code to get the available features. 2585218893Sdim OS << " // Get the current feature set.\n"; 2586218893Sdim OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; 2587218893Sdim 2588218893Sdim OS << " // Get the next operand index.\n"; 2589218893Sdim OS << " unsigned NextOpNum = Operands.size()-1;\n"; 2590218893Sdim 2591218893Sdim // Emit code to search the table. 2592218893Sdim OS << " // Search the table.\n"; 2593218893Sdim OS << " std::pair<const OperandMatchEntry*, const OperandMatchEntry*>"; 2594218893Sdim OS << " MnemonicRange =\n"; 2595218893Sdim OS << " std::equal_range(OperandMatchTable, OperandMatchTable+" 2596218893Sdim << Info.OperandMatchInfo.size() << ", Mnemonic,\n" 2597218893Sdim << " LessOpcodeOperand());\n\n"; 2598218893Sdim 2599218893Sdim OS << " if (MnemonicRange.first == MnemonicRange.second)\n"; 2600218893Sdim OS << " return MatchOperand_NoMatch;\n\n"; 2601218893Sdim 2602218893Sdim OS << " for (const OperandMatchEntry *it = MnemonicRange.first,\n" 2603218893Sdim << " *ie = MnemonicRange.second; it != ie; ++it) {\n"; 2604218893Sdim 2605218893Sdim OS << " // equal_range guarantees that instruction mnemonic matches.\n"; 2606235633Sdim OS << " assert(Mnemonic == it->getMnemonic());\n\n"; 2607218893Sdim 2608218893Sdim // Emit check that the required features are available. 2609218893Sdim OS << " // check if the available features match\n"; 2610218893Sdim OS << " if ((AvailableFeatures & it->RequiredFeatures) " 2611218893Sdim << "!= it->RequiredFeatures) {\n"; 2612218893Sdim OS << " continue;\n"; 2613218893Sdim OS << " }\n\n"; 2614218893Sdim 2615218893Sdim // Emit check to ensure the operand number matches. 2616218893Sdim OS << " // check if the operand in question has a custom parser.\n"; 2617218893Sdim OS << " if (!(it->OperandMask & (1 << NextOpNum)))\n"; 2618218893Sdim OS << " continue;\n\n"; 2619218893Sdim 2620218893Sdim // Emit call to the custom parser method 2621218893Sdim OS << " // call custom parse method to handle the operand\n"; 2622218893Sdim OS << " OperandMatchResultTy Result = "; 2623235633Sdim OS << "tryCustomParseOperand(Operands, it->Class);\n"; 2624218893Sdim OS << " if (Result != MatchOperand_NoMatch)\n"; 2625218893Sdim OS << " return Result;\n"; 2626218893Sdim OS << " }\n\n"; 2627218893Sdim 2628218893Sdim OS << " // Okay, we had no match.\n"; 2629218893Sdim OS << " return MatchOperand_NoMatch;\n"; 2630218893Sdim OS << "}\n\n"; 2631218893Sdim} 2632218893Sdim 2633198090Srdivackyvoid AsmMatcherEmitter::run(raw_ostream &OS) { 2634218893Sdim CodeGenTarget Target(Records); 2635198090Srdivacky Record *AsmParser = Target.getAsmParser(); 2636198090Srdivacky std::string ClassName = AsmParser->getValueAsString("AsmParserClassName"); 2637198090Srdivacky 2638198090Srdivacky // Compute the information on the instructions to match. 2639218893Sdim AsmMatcherInfo Info(AsmParser, Target, Records); 2640245431Sdim Info.buildInfo(); 2641198090Srdivacky 2642203954Srdivacky // Sort the instruction table using the partial order on classes. We use 2643203954Srdivacky // stable_sort to ensure that ambiguous instructions are still 2644203954Srdivacky // deterministically ordered. 2645218893Sdim std::stable_sort(Info.Matchables.begin(), Info.Matchables.end(), 2646218893Sdim less_ptr<MatchableInfo>()); 2647218893Sdim 2648198090Srdivacky DEBUG_WITH_TYPE("instruction_info", { 2649218893Sdim for (std::vector<MatchableInfo*>::iterator 2650218893Sdim it = Info.Matchables.begin(), ie = Info.Matchables.end(); 2651198090Srdivacky it != ie; ++it) 2652198090Srdivacky (*it)->dump(); 2653198090Srdivacky }); 2654198090Srdivacky 2655218893Sdim // Check for ambiguous matchables. 2656218893Sdim DEBUG_WITH_TYPE("ambiguous_instrs", { 2657218893Sdim unsigned NumAmbiguous = 0; 2658218893Sdim for (unsigned i = 0, e = Info.Matchables.size(); i != e; ++i) { 2659218893Sdim for (unsigned j = i + 1; j != e; ++j) { 2660218893Sdim MatchableInfo &A = *Info.Matchables[i]; 2661218893Sdim MatchableInfo &B = *Info.Matchables[j]; 2662218893Sdim 2663245431Sdim if (A.couldMatchAmbiguouslyWith(B)) { 2664218893Sdim errs() << "warning: ambiguous matchables:\n"; 2665218893Sdim A.dump(); 2666218893Sdim errs() << "\nis incomparable with:\n"; 2667218893Sdim B.dump(); 2668218893Sdim errs() << "\n\n"; 2669218893Sdim ++NumAmbiguous; 2670218893Sdim } 2671198090Srdivacky } 2672198090Srdivacky } 2673218893Sdim if (NumAmbiguous) 2674218893Sdim errs() << "warning: " << NumAmbiguous 2675218893Sdim << " ambiguous matchables!\n"; 2676218893Sdim }); 2677198090Srdivacky 2678218893Sdim // Compute the information on the custom operand parsing. 2679245431Sdim Info.buildOperandMatchInfo(); 2680218893Sdim 2681198090Srdivacky // Write the output. 2682198090Srdivacky 2683218893Sdim // Information for the class declaration. 2684218893Sdim OS << "\n#ifdef GET_ASSEMBLER_HEADER\n"; 2685218893Sdim OS << "#undef GET_ASSEMBLER_HEADER\n"; 2686218893Sdim OS << " // This should be included into the middle of the declaration of\n"; 2687226890Sdim OS << " // your subclasses implementation of MCTargetAsmParser.\n"; 2688224145Sdim OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; 2689245431Sdim OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, " 2690218893Sdim << "unsigned Opcode,\n" 2691218893Sdim << " const SmallVectorImpl<MCParsedAsmOperand*> " 2692218893Sdim << "&Operands);\n"; 2693245431Sdim OS << " void convertToMapAndConstraints(unsigned Kind,\n "; 2694245431Sdim OS << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands);\n"; 2695263509Sdim OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);\n"; 2696226890Sdim OS << " unsigned MatchInstructionImpl(\n"; 2697245431Sdim OS.indent(27); 2698245431Sdim OS << "const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n" 2699245431Sdim << " MCInst &Inst,\n" 2700245431Sdim << " unsigned &ErrorInfo," 2701245431Sdim << " bool matchingInlineAsm,\n" 2702245431Sdim << " unsigned VariantID = 0);\n"; 2703218893Sdim 2704218893Sdim if (Info.OperandMatchInfo.size()) { 2705218893Sdim OS << "\n enum OperandMatchResultTy {\n"; 2706218893Sdim OS << " MatchOperand_Success, // operand matched successfully\n"; 2707218893Sdim OS << " MatchOperand_NoMatch, // operand did not match\n"; 2708218893Sdim OS << " MatchOperand_ParseFail // operand matched but had errors\n"; 2709218893Sdim OS << " };\n"; 2710218893Sdim OS << " OperandMatchResultTy MatchOperandParserImpl(\n"; 2711218893Sdim OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; 2712218893Sdim OS << " StringRef Mnemonic);\n"; 2713218893Sdim 2714235633Sdim OS << " OperandMatchResultTy tryCustomParseOperand(\n"; 2715218893Sdim OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; 2716218893Sdim OS << " unsigned MCK);\n\n"; 2717218893Sdim } 2718218893Sdim 2719218893Sdim OS << "#endif // GET_ASSEMBLER_HEADER_INFO\n\n"; 2720218893Sdim 2721245431Sdim // Emit the operand match diagnostic enum names. 2722245431Sdim OS << "\n#ifdef GET_OPERAND_DIAGNOSTIC_TYPES\n"; 2723245431Sdim OS << "#undef GET_OPERAND_DIAGNOSTIC_TYPES\n\n"; 2724245431Sdim emitOperandDiagnosticTypes(Info, OS); 2725245431Sdim OS << "#endif // GET_OPERAND_DIAGNOSTIC_TYPES\n\n"; 2726245431Sdim 2727245431Sdim 2728218893Sdim OS << "\n#ifdef GET_REGISTER_MATCHER\n"; 2729218893Sdim OS << "#undef GET_REGISTER_MATCHER\n\n"; 2730218893Sdim 2731212904Sdim // Emit the subtarget feature enumeration. 2732245431Sdim emitSubtargetFeatureFlagEnumeration(Info, OS); 2733212904Sdim 2734198090Srdivacky // Emit the function to match a register name to number. 2735245431Sdim // This should be omitted for Mips target 2736245431Sdim if (AsmParser->getValueAsBit("ShouldEmitMatchRegisterName")) 2737245431Sdim emitMatchRegisterName(Target, AsmParser, OS); 2738198090Srdivacky 2739218893Sdim OS << "#endif // GET_REGISTER_MATCHER\n\n"; 2740218893Sdim 2741245431Sdim OS << "\n#ifdef GET_SUBTARGET_FEATURE_NAME\n"; 2742245431Sdim OS << "#undef GET_SUBTARGET_FEATURE_NAME\n\n"; 2743218893Sdim 2744245431Sdim // Generate the helper function to get the names for subtarget features. 2745245431Sdim emitGetSubtargetFeatureName(Info, OS); 2746245431Sdim 2747245431Sdim OS << "#endif // GET_SUBTARGET_FEATURE_NAME\n\n"; 2748245431Sdim 2749218893Sdim OS << "\n#ifdef GET_MATCHER_IMPLEMENTATION\n"; 2750218893Sdim OS << "#undef GET_MATCHER_IMPLEMENTATION\n\n"; 2751218893Sdim 2752218893Sdim // Generate the function that remaps for mnemonic aliases. 2753252723Sdim bool HasMnemonicAliases = emitMnemonicAliases(OS, Info, Target); 2754218893Sdim 2755245431Sdim // Generate the convertToMCInst function to convert operands into an MCInst. 2756245431Sdim // Also, generate the convertToMapAndConstraints function for MS-style inline 2757245431Sdim // assembly. The latter doesn't actually generate a MCInst. 2758245431Sdim emitConvertFuncs(Target, ClassName, Info.Matchables, OS); 2759198090Srdivacky 2760198090Srdivacky // Emit the enumeration for classes which participate in matching. 2761245431Sdim emitMatchClassEnumeration(Target, Info.Classes, OS); 2762198090Srdivacky 2763198090Srdivacky // Emit the routine to match token strings to their match class. 2764245431Sdim emitMatchTokenString(Target, Info.Classes, OS); 2765198090Srdivacky 2766198090Srdivacky // Emit the subclass predicate routine. 2767245431Sdim emitIsSubclass(Target, Info.Classes, OS); 2768198090Srdivacky 2769218893Sdim // Emit the routine to validate an operand against a match class. 2770245431Sdim emitValidateOperandClass(Info, OS); 2771218893Sdim 2772212904Sdim // Emit the available features compute function. 2773245431Sdim emitComputeAvailableFeatures(Info, OS); 2774212904Sdim 2775198090Srdivacky 2776245431Sdim StringToOffsetTable StringTable; 2777245431Sdim 2778198090Srdivacky size_t MaxNumOperands = 0; 2779245431Sdim unsigned MaxMnemonicIndex = 0; 2780263509Sdim bool HasDeprecation = false; 2781218893Sdim for (std::vector<MatchableInfo*>::const_iterator it = 2782218893Sdim Info.Matchables.begin(), ie = Info.Matchables.end(); 2783245431Sdim it != ie; ++it) { 2784245431Sdim MatchableInfo &II = **it; 2785245431Sdim MaxNumOperands = std::max(MaxNumOperands, II.AsmOperands.size()); 2786263509Sdim HasDeprecation |= II.HasDeprecation; 2787198090Srdivacky 2788245431Sdim // Store a pascal-style length byte in the mnemonic. 2789245431Sdim std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); 2790245431Sdim MaxMnemonicIndex = std::max(MaxMnemonicIndex, 2791245431Sdim StringTable.GetOrAddStringOffset(LenMnemonic, false)); 2792245431Sdim } 2793245431Sdim 2794245431Sdim OS << "static const char *const MnemonicTable =\n"; 2795245431Sdim StringTable.EmitString(OS); 2796245431Sdim OS << ";\n\n"; 2797245431Sdim 2798198090Srdivacky // Emit the static match table; unused classes get initalized to 0 which is 2799198090Srdivacky // guaranteed to be InvalidMatchClass. 2800198090Srdivacky // 2801198090Srdivacky // FIXME: We can reduce the size of this table very easily. First, we change 2802198090Srdivacky // it so that store the kinds in separate bit-fields for each index, which 2803198090Srdivacky // only needs to be the max width used for classes at that index (we also need 2804198090Srdivacky // to reject based on this during classification). If we then make sure to 2805198090Srdivacky // order the match kinds appropriately (putting mnemonics last), then we 2806198090Srdivacky // should only end up using a few bits for each class, especially the ones 2807198090Srdivacky // following the mnemonic. 2808218893Sdim OS << "namespace {\n"; 2809218893Sdim OS << " struct MatchEntry {\n"; 2810245431Sdim OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) 2811245431Sdim << " Mnemonic;\n"; 2812235633Sdim OS << " uint16_t Opcode;\n"; 2813235633Sdim OS << " " << getMinimalTypeForRange(Info.Matchables.size()) 2814235633Sdim << " ConvertFn;\n"; 2815235633Sdim OS << " " << getMinimalTypeForRange(1ULL << Info.SubtargetFeatures.size()) 2816235633Sdim << " RequiredFeatures;\n"; 2817235633Sdim OS << " " << getMinimalTypeForRange(Info.Classes.size()) 2818235633Sdim << " Classes[" << MaxNumOperands << "];\n"; 2819235633Sdim OS << " StringRef getMnemonic() const {\n"; 2820235633Sdim OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n"; 2821235633Sdim OS << " MnemonicTable[Mnemonic]);\n"; 2822235633Sdim OS << " }\n"; 2823218893Sdim OS << " };\n\n"; 2824198090Srdivacky 2825218893Sdim OS << " // Predicate for searching for an opcode.\n"; 2826218893Sdim OS << " struct LessOpcode {\n"; 2827218893Sdim OS << " bool operator()(const MatchEntry &LHS, StringRef RHS) {\n"; 2828235633Sdim OS << " return LHS.getMnemonic() < RHS;\n"; 2829218893Sdim OS << " }\n"; 2830218893Sdim OS << " bool operator()(StringRef LHS, const MatchEntry &RHS) {\n"; 2831235633Sdim OS << " return LHS < RHS.getMnemonic();\n"; 2832218893Sdim OS << " }\n"; 2833218893Sdim OS << " bool operator()(const MatchEntry &LHS, const MatchEntry &RHS) {\n"; 2834235633Sdim OS << " return LHS.getMnemonic() < RHS.getMnemonic();\n"; 2835218893Sdim OS << " }\n"; 2836218893Sdim OS << " };\n"; 2837218893Sdim 2838218893Sdim OS << "} // end anonymous namespace.\n\n"; 2839218893Sdim 2840263509Sdim unsigned VariantCount = Target.getAsmParserVariantCount(); 2841263509Sdim for (unsigned VC = 0; VC != VariantCount; ++VC) { 2842263509Sdim Record *AsmVariant = Target.getAsmParserVariant(VC); 2843263509Sdim int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); 2844218893Sdim 2845263509Sdim OS << "static const MatchEntry MatchTable" << VC << "[] = {\n"; 2846198090Srdivacky 2847263509Sdim for (std::vector<MatchableInfo*>::const_iterator it = 2848263509Sdim Info.Matchables.begin(), ie = Info.Matchables.end(); 2849263509Sdim it != ie; ++it) { 2850263509Sdim MatchableInfo &II = **it; 2851263509Sdim if (II.AsmVariantID != AsmVariantNo) 2852263509Sdim continue; 2853218893Sdim 2854263509Sdim // Store a pascal-style length byte in the mnemonic. 2855263509Sdim std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); 2856263509Sdim OS << " { " << StringTable.GetOrAddStringOffset(LenMnemonic, false) 2857263509Sdim << " /* " << II.Mnemonic << " */, " 2858263509Sdim << Target.getName() << "::" 2859263509Sdim << II.getResultInst()->TheDef->getName() << ", " 2860263509Sdim << II.ConversionFnKind << ", "; 2861212904Sdim 2862263509Sdim // Write the required features mask. 2863263509Sdim if (!II.RequiredFeatures.empty()) { 2864263509Sdim for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) { 2865263509Sdim if (i) OS << "|"; 2866263509Sdim OS << II.RequiredFeatures[i]->getEnumName(); 2867263509Sdim } 2868263509Sdim } else 2869263509Sdim OS << "0"; 2870235633Sdim 2871263509Sdim OS << ", { "; 2872263509Sdim for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { 2873263509Sdim MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; 2874263509Sdim 2875263509Sdim if (i) OS << ", "; 2876263509Sdim OS << Op.Class->Name; 2877263509Sdim } 2878263509Sdim OS << " }, },\n"; 2879235633Sdim } 2880263509Sdim 2881263509Sdim OS << "};\n\n"; 2882198090Srdivacky } 2883198090Srdivacky 2884218893Sdim // A method to determine if a mnemonic is in the list. 2885218893Sdim OS << "bool " << Target.getName() << ClassName << "::\n" 2886263509Sdim << "mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {\n"; 2887263509Sdim OS << " // Find the appropriate table for this asm variant.\n"; 2888263509Sdim OS << " const MatchEntry *Start, *End;\n"; 2889263509Sdim OS << " switch (VariantID) {\n"; 2890263509Sdim OS << " default: // unreachable\n"; 2891263509Sdim for (unsigned VC = 0; VC != VariantCount; ++VC) { 2892263509Sdim Record *AsmVariant = Target.getAsmParserVariant(VC); 2893263509Sdim int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); 2894263509Sdim OS << " case " << AsmVariantNo << ": Start = MatchTable" << VC 2895263509Sdim << "; End = array_endof(MatchTable" << VC << "); break;\n"; 2896263509Sdim } 2897263509Sdim OS << " }\n"; 2898218893Sdim OS << " // Search the table.\n"; 2899218893Sdim OS << " std::pair<const MatchEntry*, const MatchEntry*> MnemonicRange =\n"; 2900263509Sdim OS << " std::equal_range(Start, End, Mnemonic, LessOpcode());\n"; 2901218893Sdim OS << " return MnemonicRange.first != MnemonicRange.second;\n"; 2902218893Sdim OS << "}\n\n"; 2903212904Sdim 2904218893Sdim // Finally, build the match function. 2905226890Sdim OS << "unsigned " 2906218893Sdim << Target.getName() << ClassName << "::\n" 2907218893Sdim << "MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>" 2908218893Sdim << " &Operands,\n"; 2909245431Sdim OS << " MCInst &Inst,\n" 2910245431Sdim << "unsigned &ErrorInfo, bool matchingInlineAsm, unsigned VariantID) {\n"; 2911218893Sdim 2912245431Sdim OS << " // Eliminate obvious mismatches.\n"; 2913245431Sdim OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n"; 2914245431Sdim OS << " ErrorInfo = " << (MaxNumOperands+1) << ";\n"; 2915245431Sdim OS << " return Match_InvalidOperand;\n"; 2916245431Sdim OS << " }\n\n"; 2917245431Sdim 2918212904Sdim // Emit code to get the available features. 2919212904Sdim OS << " // Get the current feature set.\n"; 2920212904Sdim OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; 2921212904Sdim 2922218893Sdim OS << " // Get the instruction mnemonic, which is the first token.\n"; 2923218893Sdim OS << " StringRef Mnemonic = ((" << Target.getName() 2924218893Sdim << "Operand*)Operands[0])->getToken();\n\n"; 2925218893Sdim 2926218893Sdim if (HasMnemonicAliases) { 2927218893Sdim OS << " // Process all MnemonicAliases to remap the mnemonic.\n"; 2928252723Sdim OS << " applyMnemonicAliases(Mnemonic, AvailableFeatures, VariantID);\n\n"; 2929218893Sdim } 2930218893Sdim 2931198090Srdivacky // Emit code to compute the class list for this operand vector. 2932218893Sdim OS << " // Some state to try to produce better error messages.\n"; 2933226890Sdim OS << " bool HadMatchOtherThanFeatures = false;\n"; 2934226890Sdim OS << " bool HadMatchOtherThanPredicate = false;\n"; 2935226890Sdim OS << " unsigned RetCode = Match_InvalidOperand;\n"; 2936245431Sdim OS << " unsigned MissingFeatures = ~0U;\n"; 2937218893Sdim OS << " // Set ErrorInfo to the operand that mismatches if it is\n"; 2938218893Sdim OS << " // wrong for all instances of the instruction.\n"; 2939218893Sdim OS << " ErrorInfo = ~0U;\n"; 2940198090Srdivacky 2941198090Srdivacky // Emit code to search the table. 2942263509Sdim OS << " // Find the appropriate table for this asm variant.\n"; 2943263509Sdim OS << " const MatchEntry *Start, *End;\n"; 2944263509Sdim OS << " switch (VariantID) {\n"; 2945263509Sdim OS << " default: // unreachable\n"; 2946263509Sdim for (unsigned VC = 0; VC != VariantCount; ++VC) { 2947263509Sdim Record *AsmVariant = Target.getAsmParserVariant(VC); 2948263509Sdim int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); 2949263509Sdim OS << " case " << AsmVariantNo << ": Start = MatchTable" << VC 2950263509Sdim << "; End = array_endof(MatchTable" << VC << "); break;\n"; 2951263509Sdim } 2952263509Sdim OS << " }\n"; 2953198090Srdivacky OS << " // Search the table.\n"; 2954218893Sdim OS << " std::pair<const MatchEntry*, const MatchEntry*> MnemonicRange =\n"; 2955263509Sdim OS << " std::equal_range(Start, End, Mnemonic, LessOpcode());\n\n"; 2956212904Sdim 2957218893Sdim OS << " // Return a more specific error code if no mnemonics match.\n"; 2958218893Sdim OS << " if (MnemonicRange.first == MnemonicRange.second)\n"; 2959218893Sdim OS << " return Match_MnemonicFail;\n\n"; 2960212904Sdim 2961218893Sdim OS << " for (const MatchEntry *it = MnemonicRange.first, " 2962218893Sdim << "*ie = MnemonicRange.second;\n"; 2963218893Sdim OS << " it != ie; ++it) {\n"; 2964218893Sdim 2965218893Sdim OS << " // equal_range guarantees that instruction mnemonic matches.\n"; 2966235633Sdim OS << " assert(Mnemonic == it->getMnemonic());\n"; 2967218893Sdim 2968212904Sdim // Emit check that the subclasses match. 2969218893Sdim OS << " bool OperandsValid = true;\n"; 2970218893Sdim OS << " for (unsigned i = 0; i != " << MaxNumOperands << "; ++i) {\n"; 2971218893Sdim OS << " if (i + 1 >= Operands.size()) {\n"; 2972218893Sdim OS << " OperandsValid = (it->Classes[i] == " <<"InvalidMatchClass);\n"; 2973245431Sdim OS << " if (!OperandsValid) ErrorInfo = i + 1;\n"; 2974223017Sdim OS << " break;\n"; 2975218893Sdim OS << " }\n"; 2976245431Sdim OS << " unsigned Diag = validateOperandClass(Operands[i+1],\n"; 2977245431Sdim OS.indent(43); 2978245431Sdim OS << "(MatchClassKind)it->Classes[i]);\n"; 2979245431Sdim OS << " if (Diag == Match_Success)\n"; 2980218893Sdim OS << " continue;\n"; 2981252723Sdim OS << " // If the generic handler indicates an invalid operand\n"; 2982252723Sdim OS << " // failure, check for a special case.\n"; 2983252723Sdim OS << " if (Diag == Match_InvalidOperand) {\n"; 2984252723Sdim OS << " Diag = validateTargetOperandClass(Operands[i+1],\n"; 2985252723Sdim OS.indent(43); 2986252723Sdim OS << "(MatchClassKind)it->Classes[i]);\n"; 2987252723Sdim OS << " if (Diag == Match_Success)\n"; 2988252723Sdim OS << " continue;\n"; 2989252723Sdim OS << " }\n"; 2990218893Sdim OS << " // If this operand is broken for all of the instances of this\n"; 2991218893Sdim OS << " // mnemonic, keep track of it so we can report loc info.\n"; 2992245431Sdim OS << " // If we already had a match that only failed due to a\n"; 2993245431Sdim OS << " // target predicate, that diagnostic is preferred.\n"; 2994245431Sdim OS << " if (!HadMatchOtherThanPredicate &&\n"; 2995245431Sdim OS << " (it == MnemonicRange.first || ErrorInfo <= i+1)) {\n"; 2996218893Sdim OS << " ErrorInfo = i+1;\n"; 2997245431Sdim OS << " // InvalidOperand is the default. Prefer specificity.\n"; 2998245431Sdim OS << " if (Diag != Match_InvalidOperand)\n"; 2999245431Sdim OS << " RetCode = Diag;\n"; 3000245431Sdim OS << " }\n"; 3001218893Sdim OS << " // Otherwise, just reject this instance of the mnemonic.\n"; 3002218893Sdim OS << " OperandsValid = false;\n"; 3003218893Sdim OS << " break;\n"; 3004218893Sdim OS << " }\n\n"; 3005218893Sdim 3006218893Sdim OS << " if (!OperandsValid) continue;\n"; 3007218893Sdim 3008218893Sdim // Emit check that the required features are available. 3009218893Sdim OS << " if ((AvailableFeatures & it->RequiredFeatures) " 3010218893Sdim << "!= it->RequiredFeatures) {\n"; 3011218893Sdim OS << " HadMatchOtherThanFeatures = true;\n"; 3012245431Sdim OS << " unsigned NewMissingFeatures = it->RequiredFeatures & " 3013245431Sdim "~AvailableFeatures;\n"; 3014245431Sdim OS << " if (CountPopulation_32(NewMissingFeatures) <=\n" 3015245431Sdim " CountPopulation_32(MissingFeatures))\n"; 3016245431Sdim OS << " MissingFeatures = NewMissingFeatures;\n"; 3017218893Sdim OS << " continue;\n"; 3018218893Sdim OS << " }\n"; 3019198090Srdivacky OS << "\n"; 3020245431Sdim OS << " if (matchingInlineAsm) {\n"; 3021245431Sdim OS << " Inst.setOpcode(it->Opcode);\n"; 3022245431Sdim OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n"; 3023245431Sdim OS << " return Match_Success;\n"; 3024245431Sdim OS << " }\n\n"; 3025218893Sdim OS << " // We have selected a definite instruction, convert the parsed\n" 3026218893Sdim << " // operands into the appropriate MCInst.\n"; 3027245431Sdim OS << " convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands);\n"; 3028218893Sdim OS << "\n"; 3029205407Srdivacky 3030226890Sdim // Verify the instruction with the target-specific match predicate function. 3031226890Sdim OS << " // We have a potential match. Check the target predicate to\n" 3032226890Sdim << " // handle any context sensitive constraints.\n" 3033226890Sdim << " unsigned MatchResult;\n" 3034226890Sdim << " if ((MatchResult = checkTargetMatchPredicate(Inst)) !=" 3035226890Sdim << " Match_Success) {\n" 3036226890Sdim << " Inst.clear();\n" 3037226890Sdim << " RetCode = MatchResult;\n" 3038226890Sdim << " HadMatchOtherThanPredicate = true;\n" 3039226890Sdim << " continue;\n" 3040226890Sdim << " }\n\n"; 3041226890Sdim 3042205407Srdivacky // Call the post-processing function, if used. 3043205407Srdivacky std::string InsnCleanupFn = 3044205407Srdivacky AsmParser->getValueAsString("AsmParserInstCleanup"); 3045205407Srdivacky if (!InsnCleanupFn.empty()) 3046205407Srdivacky OS << " " << InsnCleanupFn << "(Inst);\n"; 3047205407Srdivacky 3048263509Sdim if (HasDeprecation) { 3049263509Sdim OS << " std::string Info;\n"; 3050263509Sdim OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, STI, Info)) {\n"; 3051263509Sdim OS << " SMLoc Loc = ((" << Target.getName() << "Operand*)Operands[0])->getStartLoc();\n"; 3052263509Sdim OS << " Parser.Warning(Loc, Info, None);\n"; 3053263509Sdim OS << " }\n"; 3054263509Sdim } 3055263509Sdim 3056218893Sdim OS << " return Match_Success;\n"; 3057198090Srdivacky OS << " }\n\n"; 3058198090Srdivacky 3059218893Sdim OS << " // Okay, we had no match. Try to return a useful error code.\n"; 3060245431Sdim OS << " if (HadMatchOtherThanPredicate || !HadMatchOtherThanFeatures)\n"; 3061245431Sdim OS << " return RetCode;\n\n"; 3062245431Sdim OS << " // Missing feature matches return which features were missing\n"; 3063245431Sdim OS << " ErrorInfo = MissingFeatures;\n"; 3064226890Sdim OS << " return Match_MissingFeature;\n"; 3065198090Srdivacky OS << "}\n\n"; 3066218893Sdim 3067218893Sdim if (Info.OperandMatchInfo.size()) 3068245431Sdim emitCustomOperandParsing(OS, Target, Info, ClassName, StringTable, 3069245431Sdim MaxMnemonicIndex); 3070218893Sdim 3071218893Sdim OS << "#endif // GET_MATCHER_IMPLEMENTATION\n\n"; 3072198090Srdivacky} 3073245431Sdim 3074245431Sdimnamespace llvm { 3075245431Sdim 3076245431Sdimvoid EmitAsmMatcher(RecordKeeper &RK, raw_ostream &OS) { 3077245431Sdim emitSourceFileHeader("Assembly Matcher Source Fragment", OS); 3078245431Sdim AsmMatcherEmitter(RK).run(OS); 3079245431Sdim} 3080245431Sdim 3081245431Sdim} // End llvm namespace 3082