xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/AsmWriterEmitter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- AsmWriterEmitter.cpp - Generate an assembly writer -----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This tablegen backend emits an assembly printer for the current target.
100b57cec5SDimitry Andric // Note that this is currently fairly skeletal, but will grow over time.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
14*0fca6ea1SDimitry Andric #include "Basic/SequenceToOffsetTable.h"
15*0fca6ea1SDimitry Andric #include "Common/AsmWriterInst.h"
16*0fca6ea1SDimitry Andric #include "Common/CodeGenInstAlias.h"
17*0fca6ea1SDimitry Andric #include "Common/CodeGenInstruction.h"
18*0fca6ea1SDimitry Andric #include "Common/CodeGenRegisters.h"
19*0fca6ea1SDimitry Andric #include "Common/CodeGenTarget.h"
20*0fca6ea1SDimitry Andric #include "Common/Types.h"
210b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
220b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
2381ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h"
240b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
250b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
260b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
270b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
280b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
290b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
300b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
310b57cec5SDimitry Andric #include "llvm/Support/Format.h"
32480093f4SDimitry Andric #include "llvm/Support/FormatVariadic.h"
330b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
340b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
350b57cec5SDimitry Andric #include "llvm/TableGen/Error.h"
360b57cec5SDimitry Andric #include "llvm/TableGen/Record.h"
370b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
380b57cec5SDimitry Andric #include <algorithm>
390b57cec5SDimitry Andric #include <cassert>
400b57cec5SDimitry Andric #include <cstddef>
410b57cec5SDimitry Andric #include <cstdint>
420b57cec5SDimitry Andric #include <deque>
430b57cec5SDimitry Andric #include <iterator>
440b57cec5SDimitry Andric #include <map>
450b57cec5SDimitry Andric #include <set>
460b57cec5SDimitry Andric #include <string>
470b57cec5SDimitry Andric #include <tuple>
480b57cec5SDimitry Andric #include <utility>
490b57cec5SDimitry Andric #include <vector>
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric using namespace llvm;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric #define DEBUG_TYPE "asm-writer-emitter"
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric namespace {
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric class AsmWriterEmitter {
580b57cec5SDimitry Andric   RecordKeeper &Records;
590b57cec5SDimitry Andric   CodeGenTarget Target;
600b57cec5SDimitry Andric   ArrayRef<const CodeGenInstruction *> NumberedInstructions;
610b57cec5SDimitry Andric   std::vector<AsmWriterInst> Instructions;
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric public:
640b57cec5SDimitry Andric   AsmWriterEmitter(RecordKeeper &R);
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   void run(raw_ostream &o);
67*0fca6ea1SDimitry Andric 
680b57cec5SDimitry Andric private:
69e8d8bef9SDimitry Andric   void EmitGetMnemonic(
70e8d8bef9SDimitry Andric       raw_ostream &o,
71e8d8bef9SDimitry Andric       std::vector<std::vector<std::string>> &TableDrivenOperandPrinters,
72e8d8bef9SDimitry Andric       unsigned &BitsLeft, unsigned &AsmStrBits);
73e8d8bef9SDimitry Andric   void EmitPrintInstruction(
74e8d8bef9SDimitry Andric       raw_ostream &o,
75e8d8bef9SDimitry Andric       std::vector<std::vector<std::string>> &TableDrivenOperandPrinters,
76e8d8bef9SDimitry Andric       unsigned &BitsLeft, unsigned &AsmStrBits);
770b57cec5SDimitry Andric   void EmitGetRegisterName(raw_ostream &o);
780b57cec5SDimitry Andric   void EmitPrintAliasInstruction(raw_ostream &O);
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   void FindUniqueOperandCommands(std::vector<std::string> &UOC,
810b57cec5SDimitry Andric                                  std::vector<std::vector<unsigned>> &InstIdxs,
820b57cec5SDimitry Andric                                  std::vector<unsigned> &InstOpsUsed,
830b57cec5SDimitry Andric                                  bool PassSubtarget) const;
840b57cec5SDimitry Andric };
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric } // end anonymous namespace
870b57cec5SDimitry Andric 
88*0fca6ea1SDimitry Andric static void
PrintCases(std::vector<std::pair<std::string,AsmWriterOperand>> & OpsToPrint,raw_ostream & O,bool PassSubtarget)89*0fca6ea1SDimitry Andric PrintCases(std::vector<std::pair<std::string, AsmWriterOperand>> &OpsToPrint,
90*0fca6ea1SDimitry Andric            raw_ostream &O, bool PassSubtarget) {
910b57cec5SDimitry Andric   O << "    case " << OpsToPrint.back().first << ":";
920b57cec5SDimitry Andric   AsmWriterOperand TheOp = OpsToPrint.back().second;
930b57cec5SDimitry Andric   OpsToPrint.pop_back();
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   // Check to see if any other operands are identical in this list, and if so,
960b57cec5SDimitry Andric   // emit a case label for them.
970b57cec5SDimitry Andric   for (unsigned i = OpsToPrint.size(); i != 0; --i)
980b57cec5SDimitry Andric     if (OpsToPrint[i - 1].second == TheOp) {
990b57cec5SDimitry Andric       O << "\n    case " << OpsToPrint[i - 1].first << ":";
1000b57cec5SDimitry Andric       OpsToPrint.erase(OpsToPrint.begin() + i - 1);
1010b57cec5SDimitry Andric     }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   // Finally, emit the code.
1040b57cec5SDimitry Andric   O << "\n      " << TheOp.getCode(PassSubtarget);
1050b57cec5SDimitry Andric   O << "\n      break;\n";
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric /// EmitInstructions - Emit the last instruction in the vector and any other
1090b57cec5SDimitry Andric /// instructions that are suitably similar to it.
EmitInstructions(std::vector<AsmWriterInst> & Insts,raw_ostream & O,bool PassSubtarget)110*0fca6ea1SDimitry Andric static void EmitInstructions(std::vector<AsmWriterInst> &Insts, raw_ostream &O,
111*0fca6ea1SDimitry Andric                              bool PassSubtarget) {
1120b57cec5SDimitry Andric   AsmWriterInst FirstInst = Insts.back();
1130b57cec5SDimitry Andric   Insts.pop_back();
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   std::vector<AsmWriterInst> SimilarInsts;
1160b57cec5SDimitry Andric   unsigned DifferingOperand = ~0;
1170b57cec5SDimitry Andric   for (unsigned i = Insts.size(); i != 0; --i) {
1180b57cec5SDimitry Andric     unsigned DiffOp = Insts[i - 1].MatchesAllButOneOp(FirstInst);
1190b57cec5SDimitry Andric     if (DiffOp != ~1U) {
1200b57cec5SDimitry Andric       if (DifferingOperand == ~0U) // First match!
1210b57cec5SDimitry Andric         DifferingOperand = DiffOp;
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric       // If this differs in the same operand as the rest of the instructions in
1240b57cec5SDimitry Andric       // this class, move it to the SimilarInsts list.
1250b57cec5SDimitry Andric       if (DifferingOperand == DiffOp || DiffOp == ~0U) {
1260b57cec5SDimitry Andric         SimilarInsts.push_back(Insts[i - 1]);
1270b57cec5SDimitry Andric         Insts.erase(Insts.begin() + i - 1);
1280b57cec5SDimitry Andric       }
1290b57cec5SDimitry Andric     }
1300b57cec5SDimitry Andric   }
1310b57cec5SDimitry Andric 
132*0fca6ea1SDimitry Andric   O << "  case " << FirstInst.CGI->Namespace
133*0fca6ea1SDimitry Andric     << "::" << FirstInst.CGI->TheDef->getName() << ":\n";
1340b57cec5SDimitry Andric   for (const AsmWriterInst &AWI : SimilarInsts)
135*0fca6ea1SDimitry Andric     O << "  case " << AWI.CGI->Namespace << "::" << AWI.CGI->TheDef->getName()
136*0fca6ea1SDimitry Andric       << ":\n";
1370b57cec5SDimitry Andric   for (unsigned i = 0, e = FirstInst.Operands.size(); i != e; ++i) {
1380b57cec5SDimitry Andric     if (i != DifferingOperand) {
1390b57cec5SDimitry Andric       // If the operand is the same for all instructions, just print it.
1400b57cec5SDimitry Andric       O << "    " << FirstInst.Operands[i].getCode(PassSubtarget);
1410b57cec5SDimitry Andric     } else {
1420b57cec5SDimitry Andric       // If this is the operand that varies between all of the instructions,
1430b57cec5SDimitry Andric       // emit a switch for just this operand now.
1440b57cec5SDimitry Andric       O << "    switch (MI->getOpcode()) {\n";
1450b57cec5SDimitry Andric       O << "    default: llvm_unreachable(\"Unexpected opcode.\");\n";
1460b57cec5SDimitry Andric       std::vector<std::pair<std::string, AsmWriterOperand>> OpsToPrint;
147*0fca6ea1SDimitry Andric       OpsToPrint.push_back(std::pair(FirstInst.CGI->Namespace.str() + "::" +
1480b57cec5SDimitry Andric                                          FirstInst.CGI->TheDef->getName().str(),
1490b57cec5SDimitry Andric                                      FirstInst.Operands[i]));
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric       for (const AsmWriterInst &AWI : SimilarInsts) {
152*0fca6ea1SDimitry Andric         OpsToPrint.push_back(std::pair(
153*0fca6ea1SDimitry Andric             AWI.CGI->Namespace.str() + "::" + AWI.CGI->TheDef->getName().str(),
1540b57cec5SDimitry Andric             AWI.Operands[i]));
1550b57cec5SDimitry Andric       }
1560b57cec5SDimitry Andric       std::reverse(OpsToPrint.begin(), OpsToPrint.end());
1570b57cec5SDimitry Andric       while (!OpsToPrint.empty())
1580b57cec5SDimitry Andric         PrintCases(OpsToPrint, O, PassSubtarget);
1590b57cec5SDimitry Andric       O << "    }";
1600b57cec5SDimitry Andric     }
1610b57cec5SDimitry Andric     O << "\n";
1620b57cec5SDimitry Andric   }
1630b57cec5SDimitry Andric   O << "    break;\n";
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric 
FindUniqueOperandCommands(std::vector<std::string> & UniqueOperandCommands,std::vector<std::vector<unsigned>> & InstIdxs,std::vector<unsigned> & InstOpsUsed,bool PassSubtarget) const166*0fca6ea1SDimitry Andric void AsmWriterEmitter::FindUniqueOperandCommands(
167*0fca6ea1SDimitry Andric     std::vector<std::string> &UniqueOperandCommands,
1680b57cec5SDimitry Andric     std::vector<std::vector<unsigned>> &InstIdxs,
169*0fca6ea1SDimitry Andric     std::vector<unsigned> &InstOpsUsed, bool PassSubtarget) const {
1700b57cec5SDimitry Andric   // This vector parallels UniqueOperandCommands, keeping track of which
1710b57cec5SDimitry Andric   // instructions each case are used for.  It is a comma separated string of
1720b57cec5SDimitry Andric   // enums.
1730b57cec5SDimitry Andric   std::vector<std::string> InstrsForCase;
1740b57cec5SDimitry Andric   InstrsForCase.resize(UniqueOperandCommands.size());
1750b57cec5SDimitry Andric   InstOpsUsed.assign(UniqueOperandCommands.size(), 0);
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   for (size_t i = 0, e = Instructions.size(); i != e; ++i) {
1780b57cec5SDimitry Andric     const AsmWriterInst &Inst = Instructions[i];
1790b57cec5SDimitry Andric     if (Inst.Operands.empty())
1800b57cec5SDimitry Andric       continue; // Instruction already done.
1810b57cec5SDimitry Andric 
182*0fca6ea1SDimitry Andric     std::string Command =
183*0fca6ea1SDimitry Andric         "    " + Inst.Operands[0].getCode(PassSubtarget) + "\n";
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric     // Check to see if we already have 'Command' in UniqueOperandCommands.
1860b57cec5SDimitry Andric     // If not, add it.
1870b57cec5SDimitry Andric     auto I = llvm::find(UniqueOperandCommands, Command);
1880b57cec5SDimitry Andric     if (I != UniqueOperandCommands.end()) {
1890b57cec5SDimitry Andric       size_t idx = I - UniqueOperandCommands.begin();
1900b57cec5SDimitry Andric       InstrsForCase[idx] += ", ";
1910b57cec5SDimitry Andric       InstrsForCase[idx] += Inst.CGI->TheDef->getName();
1920b57cec5SDimitry Andric       InstIdxs[idx].push_back(i);
1930b57cec5SDimitry Andric     } else {
1940b57cec5SDimitry Andric       UniqueOperandCommands.push_back(std::move(Command));
1955ffd83dbSDimitry Andric       InstrsForCase.push_back(std::string(Inst.CGI->TheDef->getName()));
1960b57cec5SDimitry Andric       InstIdxs.emplace_back();
1970b57cec5SDimitry Andric       InstIdxs.back().push_back(i);
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric       // This command matches one operand so far.
2000b57cec5SDimitry Andric       InstOpsUsed.push_back(1);
2010b57cec5SDimitry Andric     }
2020b57cec5SDimitry Andric   }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   // For each entry of UniqueOperandCommands, there is a set of instructions
2050b57cec5SDimitry Andric   // that uses it.  If the next command of all instructions in the set are
2060b57cec5SDimitry Andric   // identical, fold it into the command.
207*0fca6ea1SDimitry Andric   for (size_t CommandIdx = 0, e = UniqueOperandCommands.size(); CommandIdx != e;
208*0fca6ea1SDimitry Andric        ++CommandIdx) {
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric     const auto &Idxs = InstIdxs[CommandIdx];
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric     for (unsigned Op = 1;; ++Op) {
2130b57cec5SDimitry Andric       // Find the first instruction in the set.
2140b57cec5SDimitry Andric       const AsmWriterInst &FirstInst = Instructions[Idxs.front()];
2150b57cec5SDimitry Andric       // If this instruction has no more operands, we isn't anything to merge
2160b57cec5SDimitry Andric       // into this command.
2170b57cec5SDimitry Andric       if (FirstInst.Operands.size() == Op)
2180b57cec5SDimitry Andric         break;
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric       // Otherwise, scan to see if all of the other instructions in this command
2210b57cec5SDimitry Andric       // set share the operand.
222e8d8bef9SDimitry Andric       if (any_of(drop_begin(Idxs), [&](unsigned Idx) {
2230b57cec5SDimitry Andric             const AsmWriterInst &OtherInst = Instructions[Idx];
2240b57cec5SDimitry Andric             return OtherInst.Operands.size() == Op ||
2250b57cec5SDimitry Andric                    OtherInst.Operands[Op] != FirstInst.Operands[Op];
2260b57cec5SDimitry Andric           }))
2270b57cec5SDimitry Andric         break;
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric       // Okay, everything in this command set has the same next operand.  Add it
2300b57cec5SDimitry Andric       // to UniqueOperandCommands and remember that it was consumed.
231*0fca6ea1SDimitry Andric       std::string Command =
232*0fca6ea1SDimitry Andric           "    " + FirstInst.Operands[Op].getCode(PassSubtarget) + "\n";
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric       UniqueOperandCommands[CommandIdx] += Command;
2350b57cec5SDimitry Andric       InstOpsUsed[CommandIdx]++;
2360b57cec5SDimitry Andric     }
2370b57cec5SDimitry Andric   }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   // Prepend some of the instructions each case is used for onto the case val.
2400b57cec5SDimitry Andric   for (unsigned i = 0, e = InstrsForCase.size(); i != e; ++i) {
2410b57cec5SDimitry Andric     std::string Instrs = InstrsForCase[i];
2420b57cec5SDimitry Andric     if (Instrs.size() > 70) {
2430b57cec5SDimitry Andric       Instrs.erase(Instrs.begin() + 70, Instrs.end());
2440b57cec5SDimitry Andric       Instrs += "...";
2450b57cec5SDimitry Andric     }
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric     if (!Instrs.empty())
248*0fca6ea1SDimitry Andric       UniqueOperandCommands[i] =
249*0fca6ea1SDimitry Andric           "    // " + Instrs + "\n" + UniqueOperandCommands[i];
2500b57cec5SDimitry Andric   }
2510b57cec5SDimitry Andric }
2520b57cec5SDimitry Andric 
UnescapeString(std::string & Str)2530b57cec5SDimitry Andric static void UnescapeString(std::string &Str) {
2540b57cec5SDimitry Andric   for (unsigned i = 0; i != Str.size(); ++i) {
2550b57cec5SDimitry Andric     if (Str[i] == '\\' && i != Str.size() - 1) {
2560b57cec5SDimitry Andric       switch (Str[i + 1]) {
257*0fca6ea1SDimitry Andric       default:
258*0fca6ea1SDimitry Andric         continue; // Don't execute the code after the switch.
259*0fca6ea1SDimitry Andric       case 'a':
260*0fca6ea1SDimitry Andric         Str[i] = '\a';
261*0fca6ea1SDimitry Andric         break;
262*0fca6ea1SDimitry Andric       case 'b':
263*0fca6ea1SDimitry Andric         Str[i] = '\b';
264*0fca6ea1SDimitry Andric         break;
265*0fca6ea1SDimitry Andric       case 'e':
266*0fca6ea1SDimitry Andric         Str[i] = 27;
267*0fca6ea1SDimitry Andric         break;
268*0fca6ea1SDimitry Andric       case 'f':
269*0fca6ea1SDimitry Andric         Str[i] = '\f';
270*0fca6ea1SDimitry Andric         break;
271*0fca6ea1SDimitry Andric       case 'n':
272*0fca6ea1SDimitry Andric         Str[i] = '\n';
273*0fca6ea1SDimitry Andric         break;
274*0fca6ea1SDimitry Andric       case 'r':
275*0fca6ea1SDimitry Andric         Str[i] = '\r';
276*0fca6ea1SDimitry Andric         break;
277*0fca6ea1SDimitry Andric       case 't':
278*0fca6ea1SDimitry Andric         Str[i] = '\t';
279*0fca6ea1SDimitry Andric         break;
280*0fca6ea1SDimitry Andric       case 'v':
281*0fca6ea1SDimitry Andric         Str[i] = '\v';
282*0fca6ea1SDimitry Andric         break;
283*0fca6ea1SDimitry Andric       case '"':
284*0fca6ea1SDimitry Andric         Str[i] = '\"';
285*0fca6ea1SDimitry Andric         break;
286*0fca6ea1SDimitry Andric       case '\'':
287*0fca6ea1SDimitry Andric         Str[i] = '\'';
288*0fca6ea1SDimitry Andric         break;
289*0fca6ea1SDimitry Andric       case '\\':
290*0fca6ea1SDimitry Andric         Str[i] = '\\';
291*0fca6ea1SDimitry Andric         break;
2920b57cec5SDimitry Andric       }
2930b57cec5SDimitry Andric       // Nuke the second character.
2940b57cec5SDimitry Andric       Str.erase(Str.begin() + i + 1);
2950b57cec5SDimitry Andric     }
2960b57cec5SDimitry Andric   }
2970b57cec5SDimitry Andric }
2980b57cec5SDimitry Andric 
2995ffd83dbSDimitry Andric /// UnescapeAliasString - Supports literal braces in InstAlias asm string which
3005ffd83dbSDimitry Andric /// are escaped with '\\' to avoid being interpreted as variants. Braces must
3015ffd83dbSDimitry Andric /// be unescaped before c++ code is generated as (e.g.):
3025ffd83dbSDimitry Andric ///
3035ffd83dbSDimitry Andric ///   AsmString = "foo \{$\x01\}";
3045ffd83dbSDimitry Andric ///
3055ffd83dbSDimitry Andric /// causes non-standard escape character warnings.
UnescapeAliasString(std::string & Str)3065ffd83dbSDimitry Andric static void UnescapeAliasString(std::string &Str) {
3075ffd83dbSDimitry Andric   for (unsigned i = 0; i != Str.size(); ++i) {
3085ffd83dbSDimitry Andric     if (Str[i] == '\\' && i != Str.size() - 1) {
3095ffd83dbSDimitry Andric       switch (Str[i + 1]) {
310*0fca6ea1SDimitry Andric       default:
311*0fca6ea1SDimitry Andric         continue; // Don't execute the code after the switch.
312*0fca6ea1SDimitry Andric       case '{':
313*0fca6ea1SDimitry Andric         Str[i] = '{';
314*0fca6ea1SDimitry Andric         break;
315*0fca6ea1SDimitry Andric       case '}':
316*0fca6ea1SDimitry Andric         Str[i] = '}';
317*0fca6ea1SDimitry Andric         break;
3185ffd83dbSDimitry Andric       }
3195ffd83dbSDimitry Andric       // Nuke the second character.
3205ffd83dbSDimitry Andric       Str.erase(Str.begin() + i + 1);
3215ffd83dbSDimitry Andric     }
3225ffd83dbSDimitry Andric   }
3235ffd83dbSDimitry Andric }
3245ffd83dbSDimitry Andric 
EmitGetMnemonic(raw_ostream & O,std::vector<std::vector<std::string>> & TableDrivenOperandPrinters,unsigned & BitsLeft,unsigned & AsmStrBits)325e8d8bef9SDimitry Andric void AsmWriterEmitter::EmitGetMnemonic(
326e8d8bef9SDimitry Andric     raw_ostream &O,
327e8d8bef9SDimitry Andric     std::vector<std::vector<std::string>> &TableDrivenOperandPrinters,
328e8d8bef9SDimitry Andric     unsigned &BitsLeft, unsigned &AsmStrBits) {
3290b57cec5SDimitry Andric   Record *AsmWriter = Target.getAsmWriter();
3300b57cec5SDimitry Andric   StringRef ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
3310b57cec5SDimitry Andric   bool PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
3320b57cec5SDimitry Andric 
333e8d8bef9SDimitry Andric   O << "/// getMnemonic - This method is automatically generated by "
334480093f4SDimitry Andric        "tablegen\n"
3350b57cec5SDimitry Andric        "/// from the instruction set description.\n"
336e8d8bef9SDimitry Andric        "std::pair<const char *, uint64_t> "
337e8d8bef9SDimitry Andric     << Target.getName() << ClassName << "::getMnemonic(const MCInst *MI) {\n";
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   // Build an aggregate string, and build a table of offsets into it.
3400b57cec5SDimitry Andric   SequenceToOffsetTable<std::string> StringTable;
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric   /// OpcodeInfo - This encodes the index of the string to use for the first
3430b57cec5SDimitry Andric   /// chunk of the output as well as indices used for operand printing.
3440b57cec5SDimitry Andric   std::vector<uint64_t> OpcodeInfo(NumberedInstructions.size());
3450b57cec5SDimitry Andric   const unsigned OpcodeInfoBits = 64;
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   // Add all strings to the string table upfront so it can generate an optimized
3480b57cec5SDimitry Andric   // representation.
3490b57cec5SDimitry Andric   for (AsmWriterInst &AWI : Instructions) {
350*0fca6ea1SDimitry Andric     if (AWI.Operands[0].OperandType == AsmWriterOperand::isLiteralTextOperand &&
3510b57cec5SDimitry Andric         !AWI.Operands[0].Str.empty()) {
3520b57cec5SDimitry Andric       std::string Str = AWI.Operands[0].Str;
3530b57cec5SDimitry Andric       UnescapeString(Str);
3540b57cec5SDimitry Andric       StringTable.add(Str);
3550b57cec5SDimitry Andric     }
3560b57cec5SDimitry Andric   }
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   StringTable.layout();
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   unsigned MaxStringIdx = 0;
3610b57cec5SDimitry Andric   for (AsmWriterInst &AWI : Instructions) {
3620b57cec5SDimitry Andric     unsigned Idx;
3630b57cec5SDimitry Andric     if (AWI.Operands[0].OperandType != AsmWriterOperand::isLiteralTextOperand ||
3640b57cec5SDimitry Andric         AWI.Operands[0].Str.empty()) {
3650b57cec5SDimitry Andric       // Something handled by the asmwriter printer, but with no leading string.
3660b57cec5SDimitry Andric       Idx = StringTable.get("");
3670b57cec5SDimitry Andric     } else {
3680b57cec5SDimitry Andric       std::string Str = AWI.Operands[0].Str;
3690b57cec5SDimitry Andric       UnescapeString(Str);
3700b57cec5SDimitry Andric       Idx = StringTable.get(Str);
3710b57cec5SDimitry Andric       MaxStringIdx = std::max(MaxStringIdx, Idx);
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric       // Nuke the string from the operand list.  It is now handled!
3740b57cec5SDimitry Andric       AWI.Operands.erase(AWI.Operands.begin());
3750b57cec5SDimitry Andric     }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric     // Bias offset by one since we want 0 as a sentinel.
3780b57cec5SDimitry Andric     OpcodeInfo[AWI.CGIIndex] = Idx + 1;
3790b57cec5SDimitry Andric   }
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric   // Figure out how many bits we used for the string index.
382e8d8bef9SDimitry Andric   AsmStrBits = Log2_32_Ceil(MaxStringIdx + 2);
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   // To reduce code size, we compactify common instructions into a few bits
3850b57cec5SDimitry Andric   // in the opcode-indexed table.
386e8d8bef9SDimitry Andric   BitsLeft = OpcodeInfoBits - AsmStrBits;
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric   while (true) {
3890b57cec5SDimitry Andric     std::vector<std::string> UniqueOperandCommands;
3900b57cec5SDimitry Andric     std::vector<std::vector<unsigned>> InstIdxs;
3910b57cec5SDimitry Andric     std::vector<unsigned> NumInstOpsHandled;
3920b57cec5SDimitry Andric     FindUniqueOperandCommands(UniqueOperandCommands, InstIdxs,
3930b57cec5SDimitry Andric                               NumInstOpsHandled, PassSubtarget);
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric     // If we ran out of operands to print, we're done.
396*0fca6ea1SDimitry Andric     if (UniqueOperandCommands.empty())
397*0fca6ea1SDimitry Andric       break;
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric     // Compute the number of bits we need to represent these cases, this is
4000b57cec5SDimitry Andric     // ceil(log2(numentries)).
4010b57cec5SDimitry Andric     unsigned NumBits = Log2_32_Ceil(UniqueOperandCommands.size());
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric     // If we don't have enough bits for this operand, don't include it.
4040b57cec5SDimitry Andric     if (NumBits > BitsLeft) {
4050b57cec5SDimitry Andric       LLVM_DEBUG(errs() << "Not enough bits to densely encode " << NumBits
4060b57cec5SDimitry Andric                         << " more bits\n");
4070b57cec5SDimitry Andric       break;
4080b57cec5SDimitry Andric     }
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric     // Otherwise, we can include this in the initial lookup table.  Add it in.
4110b57cec5SDimitry Andric     for (size_t i = 0, e = InstIdxs.size(); i != e; ++i) {
4120b57cec5SDimitry Andric       unsigned NumOps = NumInstOpsHandled[i];
4130b57cec5SDimitry Andric       for (unsigned Idx : InstIdxs[i]) {
4140b57cec5SDimitry Andric         OpcodeInfo[Instructions[Idx].CGIIndex] |=
4150b57cec5SDimitry Andric             (uint64_t)i << (OpcodeInfoBits - BitsLeft);
4160b57cec5SDimitry Andric         // Remove the info about this operand from the instruction.
4170b57cec5SDimitry Andric         AsmWriterInst &Inst = Instructions[Idx];
4180b57cec5SDimitry Andric         if (!Inst.Operands.empty()) {
4190b57cec5SDimitry Andric           assert(NumOps <= Inst.Operands.size() &&
4200b57cec5SDimitry Andric                  "Can't remove this many ops!");
4210b57cec5SDimitry Andric           Inst.Operands.erase(Inst.Operands.begin(),
4220b57cec5SDimitry Andric                               Inst.Operands.begin() + NumOps);
4230b57cec5SDimitry Andric         }
4240b57cec5SDimitry Andric       }
4250b57cec5SDimitry Andric     }
4260b57cec5SDimitry Andric     BitsLeft -= NumBits;
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric     // Remember the handlers for this set of operands.
4290b57cec5SDimitry Andric     TableDrivenOperandPrinters.push_back(std::move(UniqueOperandCommands));
4300b57cec5SDimitry Andric   }
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric   // Emit the string table itself.
4335ffd83dbSDimitry Andric   StringTable.emitStringLiteralDef(O, "  static const char AsmStrs[]");
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   // Emit the lookup tables in pieces to minimize wasted bytes.
4360b57cec5SDimitry Andric   unsigned BytesNeeded = ((OpcodeInfoBits - BitsLeft) + 7) / 8;
4370b57cec5SDimitry Andric   unsigned Table = 0, Shift = 0;
4380b57cec5SDimitry Andric   SmallString<128> BitsString;
4390b57cec5SDimitry Andric   raw_svector_ostream BitsOS(BitsString);
4400b57cec5SDimitry Andric   // If the total bits is more than 32-bits we need to use a 64-bit type.
4410b57cec5SDimitry Andric   BitsOS << "  uint" << ((BitsLeft < (OpcodeInfoBits - 32)) ? 64 : 32)
4420b57cec5SDimitry Andric          << "_t Bits = 0;\n";
4430b57cec5SDimitry Andric   while (BytesNeeded != 0) {
4440b57cec5SDimitry Andric     // Figure out how big this table section needs to be, but no bigger than 4.
445bdd1243dSDimitry Andric     unsigned TableSize = std::min(llvm::bit_floor(BytesNeeded), 4u);
4460b57cec5SDimitry Andric     BytesNeeded -= TableSize;
4470b57cec5SDimitry Andric     TableSize *= 8; // Convert to bits;
4480b57cec5SDimitry Andric     uint64_t Mask = (1ULL << TableSize) - 1;
4490b57cec5SDimitry Andric     O << "  static const uint" << TableSize << "_t OpInfo" << Table
4500b57cec5SDimitry Andric       << "[] = {\n";
4510b57cec5SDimitry Andric     for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
4520b57cec5SDimitry Andric       O << "    " << ((OpcodeInfo[i] >> Shift) & Mask) << "U,\t// "
4530b57cec5SDimitry Andric         << NumberedInstructions[i]->TheDef->getName() << "\n";
4540b57cec5SDimitry Andric     }
4550b57cec5SDimitry Andric     O << "  };\n\n";
4560b57cec5SDimitry Andric     // Emit string to combine the individual table lookups.
4570b57cec5SDimitry Andric     BitsOS << "  Bits |= ";
4580b57cec5SDimitry Andric     // If the total bits is more than 32-bits we need to use a 64-bit type.
4590b57cec5SDimitry Andric     if (BitsLeft < (OpcodeInfoBits - 32))
4600b57cec5SDimitry Andric       BitsOS << "(uint64_t)";
4610b57cec5SDimitry Andric     BitsOS << "OpInfo" << Table << "[MI->getOpcode()] << " << Shift << ";\n";
4620b57cec5SDimitry Andric     // Prepare the shift for the next iteration and increment the table count.
4630b57cec5SDimitry Andric     Shift += TableSize;
4640b57cec5SDimitry Andric     ++Table;
4650b57cec5SDimitry Andric   }
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric   O << "  // Emit the opcode for the instruction.\n";
4680b57cec5SDimitry Andric   O << BitsString;
4690b57cec5SDimitry Andric 
470cb14a3feSDimitry Andric   // Make sure we don't return an invalid pointer if bits is 0
471cb14a3feSDimitry Andric   O << "  if (Bits == 0)\n"
472cb14a3feSDimitry Andric        "    return {nullptr, Bits};\n";
473cb14a3feSDimitry Andric 
474e8d8bef9SDimitry Andric   // Return mnemonic string and bits.
475e8d8bef9SDimitry Andric   O << "  return {AsmStrs+(Bits & " << (1 << AsmStrBits) - 1
476e8d8bef9SDimitry Andric     << ")-1, Bits};\n\n";
477e8d8bef9SDimitry Andric 
478e8d8bef9SDimitry Andric   O << "}\n";
479e8d8bef9SDimitry Andric }
480e8d8bef9SDimitry Andric 
481e8d8bef9SDimitry Andric /// EmitPrintInstruction - Generate the code for the "printInstruction" method
482e8d8bef9SDimitry Andric /// implementation. Destroys all instances of AsmWriterInst information, by
483e8d8bef9SDimitry Andric /// clearing the Instructions vector.
EmitPrintInstruction(raw_ostream & O,std::vector<std::vector<std::string>> & TableDrivenOperandPrinters,unsigned & BitsLeft,unsigned & AsmStrBits)484e8d8bef9SDimitry Andric void AsmWriterEmitter::EmitPrintInstruction(
485e8d8bef9SDimitry Andric     raw_ostream &O,
486e8d8bef9SDimitry Andric     std::vector<std::vector<std::string>> &TableDrivenOperandPrinters,
487e8d8bef9SDimitry Andric     unsigned &BitsLeft, unsigned &AsmStrBits) {
488e8d8bef9SDimitry Andric   const unsigned OpcodeInfoBits = 64;
489e8d8bef9SDimitry Andric   Record *AsmWriter = Target.getAsmWriter();
490e8d8bef9SDimitry Andric   StringRef ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
491e8d8bef9SDimitry Andric   bool PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
492e8d8bef9SDimitry Andric 
493349cc55cSDimitry Andric   // This function has some huge switch statements that causing excessive
494349cc55cSDimitry Andric   // compile time in LLVM profile instrumenation build. This print function
495349cc55cSDimitry Andric   // usually is not frequently called in compilation. Here we disable the
496349cc55cSDimitry Andric   // profile instrumenation for this function.
497e8d8bef9SDimitry Andric   O << "/// printInstruction - This method is automatically generated by "
498e8d8bef9SDimitry Andric        "tablegen\n"
499e8d8bef9SDimitry Andric        "/// from the instruction set description.\n"
500349cc55cSDimitry Andric        "LLVM_NO_PROFILE_INSTRUMENT_FUNCTION\n"
501e8d8bef9SDimitry Andric        "void "
502e8d8bef9SDimitry Andric     << Target.getName() << ClassName
503e8d8bef9SDimitry Andric     << "::printInstruction(const MCInst *MI, uint64_t Address, "
504e8d8bef9SDimitry Andric     << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
505e8d8bef9SDimitry Andric     << "raw_ostream &O) {\n";
506e8d8bef9SDimitry Andric 
507e8d8bef9SDimitry Andric   // Emit the initial tab character.
508e8d8bef9SDimitry Andric   O << "  O << \"\\t\";\n\n";
509e8d8bef9SDimitry Andric 
5100b57cec5SDimitry Andric   // Emit the starting string.
511e8d8bef9SDimitry Andric   O << "  auto MnemonicInfo = getMnemonic(MI);\n\n";
512e8d8bef9SDimitry Andric   O << "  O << MnemonicInfo.first;\n\n";
513e8d8bef9SDimitry Andric 
514e8d8bef9SDimitry Andric   O << "  uint" << ((BitsLeft < (OpcodeInfoBits - 32)) ? 64 : 32)
515e8d8bef9SDimitry Andric     << "_t Bits = MnemonicInfo.second;\n"
516e8d8bef9SDimitry Andric     << "  assert(Bits != 0 && \"Cannot print this instruction.\");\n";
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric   // Output the table driven operand information.
5190b57cec5SDimitry Andric   BitsLeft = OpcodeInfoBits - AsmStrBits;
5200b57cec5SDimitry Andric   for (unsigned i = 0, e = TableDrivenOperandPrinters.size(); i != e; ++i) {
5210b57cec5SDimitry Andric     std::vector<std::string> &Commands = TableDrivenOperandPrinters[i];
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric     // Compute the number of bits we need to represent these cases, this is
5240b57cec5SDimitry Andric     // ceil(log2(numentries)).
5250b57cec5SDimitry Andric     unsigned NumBits = Log2_32_Ceil(Commands.size());
5260b57cec5SDimitry Andric     assert(NumBits <= BitsLeft && "consistency error");
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric     // Emit code to extract this field from Bits.
529*0fca6ea1SDimitry Andric     O << "\n  // Fragment " << i << " encoded into " << NumBits << " bits for "
530*0fca6ea1SDimitry Andric       << Commands.size() << " unique commands.\n";
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric     if (Commands.size() == 2) {
5330b57cec5SDimitry Andric       // Emit two possibilitys with if/else.
534*0fca6ea1SDimitry Andric       O << "  if ((Bits >> " << (OpcodeInfoBits - BitsLeft) << ") & "
5350b57cec5SDimitry Andric         << ((1 << NumBits) - 1) << ") {\n"
536*0fca6ea1SDimitry Andric         << Commands[1] << "  } else {\n"
537*0fca6ea1SDimitry Andric         << Commands[0] << "  }\n\n";
5380b57cec5SDimitry Andric     } else if (Commands.size() == 1) {
5390b57cec5SDimitry Andric       // Emit a single possibility.
5400b57cec5SDimitry Andric       O << Commands[0] << "\n\n";
5410b57cec5SDimitry Andric     } else {
542*0fca6ea1SDimitry Andric       O << "  switch ((Bits >> " << (OpcodeInfoBits - BitsLeft) << ") & "
5430b57cec5SDimitry Andric         << ((1 << NumBits) - 1) << ") {\n"
5440b57cec5SDimitry Andric         << "  default: llvm_unreachable(\"Invalid command number.\");\n";
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric       // Print out all the cases.
5470b57cec5SDimitry Andric       for (unsigned j = 0, e = Commands.size(); j != e; ++j) {
5480b57cec5SDimitry Andric         O << "  case " << j << ":\n";
5490b57cec5SDimitry Andric         O << Commands[j];
5500b57cec5SDimitry Andric         O << "    break;\n";
5510b57cec5SDimitry Andric       }
5520b57cec5SDimitry Andric       O << "  }\n\n";
5530b57cec5SDimitry Andric     }
5540b57cec5SDimitry Andric     BitsLeft -= NumBits;
5550b57cec5SDimitry Andric   }
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric   // Okay, delete instructions with no operand info left.
558e8d8bef9SDimitry Andric   llvm::erase_if(Instructions,
5590b57cec5SDimitry Andric                  [](AsmWriterInst &Inst) { return Inst.Operands.empty(); });
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric   // Because this is a vector, we want to emit from the end.  Reverse all of the
5620b57cec5SDimitry Andric   // elements in the vector.
5630b57cec5SDimitry Andric   std::reverse(Instructions.begin(), Instructions.end());
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric   // Now that we've emitted all of the operand info that fit into 64 bits, emit
5660b57cec5SDimitry Andric   // information for those instructions that are left.  This is a less dense
5670b57cec5SDimitry Andric   // encoding, but we expect the main 64-bit table to handle the majority of
5680b57cec5SDimitry Andric   // instructions.
5690b57cec5SDimitry Andric   if (!Instructions.empty()) {
5700b57cec5SDimitry Andric     // Find the opcode # of inline asm.
5710b57cec5SDimitry Andric     O << "  switch (MI->getOpcode()) {\n";
5720b57cec5SDimitry Andric     O << "  default: llvm_unreachable(\"Unexpected opcode.\");\n";
5730b57cec5SDimitry Andric     while (!Instructions.empty())
5740b57cec5SDimitry Andric       EmitInstructions(Instructions, O, PassSubtarget);
5750b57cec5SDimitry Andric 
5760b57cec5SDimitry Andric     O << "  }\n";
5770b57cec5SDimitry Andric   }
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric   O << "}\n";
5800b57cec5SDimitry Andric }
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric static void
emitRegisterNameString(raw_ostream & O,StringRef AltName,const std::deque<CodeGenRegister> & Registers)5830b57cec5SDimitry Andric emitRegisterNameString(raw_ostream &O, StringRef AltName,
5840b57cec5SDimitry Andric                        const std::deque<CodeGenRegister> &Registers) {
5850b57cec5SDimitry Andric   SequenceToOffsetTable<std::string> StringTable;
5860b57cec5SDimitry Andric   SmallVector<std::string, 4> AsmNames(Registers.size());
5870b57cec5SDimitry Andric   unsigned i = 0;
5880b57cec5SDimitry Andric   for (const auto &Reg : Registers) {
5890b57cec5SDimitry Andric     std::string &AsmName = AsmNames[i++];
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric     // "NoRegAltName" is special. We don't need to do a lookup for that,
5920b57cec5SDimitry Andric     // as it's just a reference to the default register name.
5930b57cec5SDimitry Andric     if (AltName == "" || AltName == "NoRegAltName") {
5945ffd83dbSDimitry Andric       AsmName = std::string(Reg.TheDef->getValueAsString("AsmName"));
5950b57cec5SDimitry Andric       if (AsmName.empty())
5965ffd83dbSDimitry Andric         AsmName = std::string(Reg.getName());
5970b57cec5SDimitry Andric     } else {
5980b57cec5SDimitry Andric       // Make sure the register has an alternate name for this index.
5990b57cec5SDimitry Andric       std::vector<Record *> AltNameList =
6000b57cec5SDimitry Andric           Reg.TheDef->getValueAsListOfDefs("RegAltNameIndices");
6010b57cec5SDimitry Andric       unsigned Idx = 0, e;
6020b57cec5SDimitry Andric       for (e = AltNameList.size();
603*0fca6ea1SDimitry Andric            Idx < e && (AltNameList[Idx]->getName() != AltName); ++Idx)
6040b57cec5SDimitry Andric         ;
6050b57cec5SDimitry Andric       // If the register has an alternate name for this index, use it.
6060b57cec5SDimitry Andric       // Otherwise, leave it empty as an error flag.
6070b57cec5SDimitry Andric       if (Idx < e) {
6080b57cec5SDimitry Andric         std::vector<StringRef> AltNames =
6090b57cec5SDimitry Andric             Reg.TheDef->getValueAsListOfStrings("AltNames");
6100b57cec5SDimitry Andric         if (AltNames.size() <= Idx)
6110b57cec5SDimitry Andric           PrintFatalError(Reg.TheDef->getLoc(),
6120b57cec5SDimitry Andric                           "Register definition missing alt name for '" +
6130b57cec5SDimitry Andric                               AltName + "'.");
6145ffd83dbSDimitry Andric         AsmName = std::string(AltNames[Idx]);
6150b57cec5SDimitry Andric       }
6160b57cec5SDimitry Andric     }
6170b57cec5SDimitry Andric     StringTable.add(AsmName);
6180b57cec5SDimitry Andric   }
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric   StringTable.layout();
6215ffd83dbSDimitry Andric   StringTable.emitStringLiteralDef(O, Twine("  static const char AsmStrs") +
6225ffd83dbSDimitry Andric                                           AltName + "[]");
6230b57cec5SDimitry Andric 
6240b57cec5SDimitry Andric   O << "  static const " << getMinimalTypeForRange(StringTable.size() - 1, 32)
6250b57cec5SDimitry Andric     << " RegAsmOffset" << AltName << "[] = {";
6260b57cec5SDimitry Andric   for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
6270b57cec5SDimitry Andric     if ((i % 14) == 0)
6280b57cec5SDimitry Andric       O << "\n    ";
6290b57cec5SDimitry Andric     O << StringTable.get(AsmNames[i]) << ", ";
6300b57cec5SDimitry Andric   }
6310b57cec5SDimitry Andric   O << "\n  };\n"
6320b57cec5SDimitry Andric     << "\n";
6330b57cec5SDimitry Andric }
6340b57cec5SDimitry Andric 
EmitGetRegisterName(raw_ostream & O)6350b57cec5SDimitry Andric void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
6360b57cec5SDimitry Andric   Record *AsmWriter = Target.getAsmWriter();
6370b57cec5SDimitry Andric   StringRef ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
6380b57cec5SDimitry Andric   const auto &Registers = Target.getRegBank().getRegisters();
6390b57cec5SDimitry Andric   const std::vector<Record *> &AltNameIndices = Target.getRegAltNameIndices();
6400b57cec5SDimitry Andric   bool hasAltNames = AltNameIndices.size() > 1;
6410b57cec5SDimitry Andric   StringRef Namespace = Registers.front().TheDef->getValueAsString("Namespace");
6420b57cec5SDimitry Andric 
643*0fca6ea1SDimitry Andric   O << "\n\n/// getRegisterName - This method is automatically generated by "
644*0fca6ea1SDimitry Andric        "tblgen\n"
645*0fca6ea1SDimitry Andric        "/// from the register set description.  This returns the assembler "
646*0fca6ea1SDimitry Andric        "name\n"
6470b57cec5SDimitry Andric        "/// for the specified register.\n"
648*0fca6ea1SDimitry Andric        "const char *"
649*0fca6ea1SDimitry Andric     << Target.getName() << ClassName << "::";
6500b57cec5SDimitry Andric   if (hasAltNames)
651bdd1243dSDimitry Andric     O << "\ngetRegisterName(MCRegister Reg, unsigned AltIdx) {\n";
6520b57cec5SDimitry Andric   else
653bdd1243dSDimitry Andric     O << "getRegisterName(MCRegister Reg) {\n";
654bdd1243dSDimitry Andric   O << "  unsigned RegNo = Reg.id();\n"
655bdd1243dSDimitry Andric     << "  assert(RegNo && RegNo < " << (Registers.size() + 1)
6560b57cec5SDimitry Andric     << " && \"Invalid register number!\");\n"
6570b57cec5SDimitry Andric     << "\n";
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric   if (hasAltNames) {
6600b57cec5SDimitry Andric     for (const Record *R : AltNameIndices)
6610b57cec5SDimitry Andric       emitRegisterNameString(O, R->getName(), Registers);
6620b57cec5SDimitry Andric   } else
6630b57cec5SDimitry Andric     emitRegisterNameString(O, "", Registers);
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric   if (hasAltNames) {
6660b57cec5SDimitry Andric     O << "  switch(AltIdx) {\n"
6670b57cec5SDimitry Andric       << "  default: llvm_unreachable(\"Invalid register alt name index!\");\n";
6680b57cec5SDimitry Andric     for (const Record *R : AltNameIndices) {
6690b57cec5SDimitry Andric       StringRef AltName = R->getName();
6700b57cec5SDimitry Andric       O << "  case ";
6710b57cec5SDimitry Andric       if (!Namespace.empty())
6720b57cec5SDimitry Andric         O << Namespace << "::";
6730b57cec5SDimitry Andric       O << AltName << ":\n";
6740b57cec5SDimitry Andric       if (R->isValueUnset("FallbackRegAltNameIndex"))
6750b57cec5SDimitry Andric         O << "    assert(*(AsmStrs" << AltName << "+RegAsmOffset" << AltName
6760b57cec5SDimitry Andric           << "[RegNo-1]) &&\n"
6770b57cec5SDimitry Andric           << "           \"Invalid alt name index for register!\");\n";
6780b57cec5SDimitry Andric       else {
6790b57cec5SDimitry Andric         O << "    if (!*(AsmStrs" << AltName << "+RegAsmOffset" << AltName
6800b57cec5SDimitry Andric           << "[RegNo-1]))\n"
6810b57cec5SDimitry Andric           << "      return getRegisterName(RegNo, ";
6820b57cec5SDimitry Andric         if (!Namespace.empty())
6830b57cec5SDimitry Andric           O << Namespace << "::";
6840b57cec5SDimitry Andric         O << R->getValueAsDef("FallbackRegAltNameIndex")->getName() << ");\n";
6850b57cec5SDimitry Andric       }
6860b57cec5SDimitry Andric       O << "    return AsmStrs" << AltName << "+RegAsmOffset" << AltName
6870b57cec5SDimitry Andric         << "[RegNo-1];\n";
6880b57cec5SDimitry Andric     }
6890b57cec5SDimitry Andric     O << "  }\n";
6900b57cec5SDimitry Andric   } else {
6910b57cec5SDimitry Andric     O << "  assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n"
6920b57cec5SDimitry Andric       << "          \"Invalid alt name index for register!\");\n"
6930b57cec5SDimitry Andric       << "  return AsmStrs+RegAsmOffset[RegNo-1];\n";
6940b57cec5SDimitry Andric   }
6950b57cec5SDimitry Andric   O << "}\n";
6960b57cec5SDimitry Andric }
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric namespace {
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric // IAPrinter - Holds information about an InstAlias. Two InstAliases match if
7010b57cec5SDimitry Andric // they both have the same conditionals. In which case, we cannot print out the
7020b57cec5SDimitry Andric // alias for that pattern.
7030b57cec5SDimitry Andric class IAPrinter {
7040b57cec5SDimitry Andric   std::map<StringRef, std::pair<int, int>> OpMap;
7050b57cec5SDimitry Andric 
706480093f4SDimitry Andric   std::vector<std::string> Conds;
707480093f4SDimitry Andric 
7080b57cec5SDimitry Andric   std::string Result;
7090b57cec5SDimitry Andric   std::string AsmString;
7100b57cec5SDimitry Andric 
711480093f4SDimitry Andric   unsigned NumMIOps;
7120b57cec5SDimitry Andric 
713480093f4SDimitry Andric public:
IAPrinter(std::string R,std::string AS,unsigned NumMIOps)714480093f4SDimitry Andric   IAPrinter(std::string R, std::string AS, unsigned NumMIOps)
715480093f4SDimitry Andric       : Result(std::move(R)), AsmString(std::move(AS)), NumMIOps(NumMIOps) {}
716480093f4SDimitry Andric 
addCond(std::string C)717480093f4SDimitry Andric   void addCond(std::string C) { Conds.push_back(std::move(C)); }
getConds() const718480093f4SDimitry Andric   ArrayRef<std::string> getConds() const { return Conds; }
getCondCount() const719480093f4SDimitry Andric   size_t getCondCount() const { return Conds.size(); }
7200b57cec5SDimitry Andric 
addOperand(StringRef Op,int OpIdx,int PrintMethodIdx=-1)7210b57cec5SDimitry Andric   void addOperand(StringRef Op, int OpIdx, int PrintMethodIdx = -1) {
7220b57cec5SDimitry Andric     assert(OpIdx >= 0 && OpIdx < 0xFE && "Idx out of range");
723*0fca6ea1SDimitry Andric     assert(PrintMethodIdx >= -1 && PrintMethodIdx < 0xFF && "Idx out of range");
724*0fca6ea1SDimitry Andric     OpMap[Op] = std::pair(OpIdx, PrintMethodIdx);
7250b57cec5SDimitry Andric   }
7260b57cec5SDimitry Andric 
getNumMIOps()727480093f4SDimitry Andric   unsigned getNumMIOps() { return NumMIOps; }
728480093f4SDimitry Andric 
getResult()729480093f4SDimitry Andric   StringRef getResult() { return Result; }
730480093f4SDimitry Andric 
isOpMapped(StringRef Op)7310b57cec5SDimitry Andric   bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); }
getOpIndex(StringRef Op)7320b57cec5SDimitry Andric   int getOpIndex(StringRef Op) { return OpMap[Op].first; }
getOpData(StringRef Op)7330b57cec5SDimitry Andric   std::pair<int, int> &getOpData(StringRef Op) { return OpMap[Op]; }
7340b57cec5SDimitry Andric 
parseName(StringRef::iterator Start,StringRef::iterator End)7350b57cec5SDimitry Andric   std::pair<StringRef, StringRef::iterator> parseName(StringRef::iterator Start,
7360b57cec5SDimitry Andric                                                       StringRef::iterator End) {
7370b57cec5SDimitry Andric     StringRef::iterator I = Start;
7380b57cec5SDimitry Andric     StringRef::iterator Next;
7390b57cec5SDimitry Andric     if (*I == '{') {
7400b57cec5SDimitry Andric       // ${some_name}
7410b57cec5SDimitry Andric       Start = ++I;
7420b57cec5SDimitry Andric       while (I != End && *I != '}')
7430b57cec5SDimitry Andric         ++I;
7440b57cec5SDimitry Andric       Next = I;
7450b57cec5SDimitry Andric       // eat the final '}'
7460b57cec5SDimitry Andric       if (Next != End)
7470b57cec5SDimitry Andric         ++Next;
7480b57cec5SDimitry Andric     } else {
7490b57cec5SDimitry Andric       // $name, just eat the usual suspects.
750e8d8bef9SDimitry Andric       while (I != End && (isAlnum(*I) || *I == '_'))
7510b57cec5SDimitry Andric         ++I;
7520b57cec5SDimitry Andric       Next = I;
7530b57cec5SDimitry Andric     }
7540b57cec5SDimitry Andric 
755*0fca6ea1SDimitry Andric     return std::pair(StringRef(Start, I - Start), Next);
7560b57cec5SDimitry Andric   }
7570b57cec5SDimitry Andric 
formatAliasString(uint32_t & UnescapedSize)758480093f4SDimitry Andric   std::string formatAliasString(uint32_t &UnescapedSize) {
7590b57cec5SDimitry Andric     // Directly mangle mapped operands into the string. Each operand is
7600b57cec5SDimitry Andric     // identified by a '$' sign followed by a byte identifying the number of the
7610b57cec5SDimitry Andric     // operand. We add one to the index to avoid zero bytes.
7620b57cec5SDimitry Andric     StringRef ASM(AsmString);
763480093f4SDimitry Andric     std::string OutString;
764480093f4SDimitry Andric     raw_string_ostream OS(OutString);
7650b57cec5SDimitry Andric     for (StringRef::iterator I = ASM.begin(), E = ASM.end(); I != E;) {
7660b57cec5SDimitry Andric       OS << *I;
767480093f4SDimitry Andric       ++UnescapedSize;
7680b57cec5SDimitry Andric       if (*I == '$') {
7690b57cec5SDimitry Andric         StringRef Name;
7700b57cec5SDimitry Andric         std::tie(Name, I) = parseName(++I, E);
7710b57cec5SDimitry Andric         assert(isOpMapped(Name) && "Unmapped operand!");
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric         int OpIndex, PrintIndex;
7740b57cec5SDimitry Andric         std::tie(OpIndex, PrintIndex) = getOpData(Name);
7750b57cec5SDimitry Andric         if (PrintIndex == -1) {
7760b57cec5SDimitry Andric           // Can use the default printOperand route.
7770b57cec5SDimitry Andric           OS << format("\\x%02X", (unsigned char)OpIndex + 1);
778480093f4SDimitry Andric           ++UnescapedSize;
779480093f4SDimitry Andric         } else {
7800b57cec5SDimitry Andric           // 3 bytes if a PrintMethod is needed: 0xFF, the MCInst operand
7810b57cec5SDimitry Andric           // number, and which of our pre-detected Methods to call.
7820b57cec5SDimitry Andric           OS << format("\\xFF\\x%02X\\x%02X", OpIndex + 1, PrintIndex + 1);
783480093f4SDimitry Andric           UnescapedSize += 3;
784480093f4SDimitry Andric         }
7850b57cec5SDimitry Andric       } else {
7860b57cec5SDimitry Andric         ++I;
7870b57cec5SDimitry Andric       }
7880b57cec5SDimitry Andric     }
789480093f4SDimitry Andric     return OutString;
7900b57cec5SDimitry Andric   }
7910b57cec5SDimitry Andric 
operator ==(const IAPrinter & RHS) const7920b57cec5SDimitry Andric   bool operator==(const IAPrinter &RHS) const {
793480093f4SDimitry Andric     if (NumMIOps != RHS.NumMIOps)
794480093f4SDimitry Andric       return false;
7950b57cec5SDimitry Andric     if (Conds.size() != RHS.Conds.size())
7960b57cec5SDimitry Andric       return false;
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric     unsigned Idx = 0;
7990b57cec5SDimitry Andric     for (const auto &str : Conds)
8000b57cec5SDimitry Andric       if (str != RHS.Conds[Idx++])
8010b57cec5SDimitry Andric         return false;
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric     return true;
8040b57cec5SDimitry Andric   }
8050b57cec5SDimitry Andric };
8060b57cec5SDimitry Andric 
8070b57cec5SDimitry Andric } // end anonymous namespace
8080b57cec5SDimitry Andric 
CountNumOperands(StringRef AsmString,unsigned Variant)8090b57cec5SDimitry Andric static unsigned CountNumOperands(StringRef AsmString, unsigned Variant) {
8100b57cec5SDimitry Andric   return AsmString.count(' ') + AsmString.count('\t');
8110b57cec5SDimitry Andric }
8120b57cec5SDimitry Andric 
8130b57cec5SDimitry Andric namespace {
8140b57cec5SDimitry Andric 
8150b57cec5SDimitry Andric struct AliasPriorityComparator {
8160b57cec5SDimitry Andric   typedef std::pair<CodeGenInstAlias, int> ValueType;
operator ()__anon992240d30511::AliasPriorityComparator8170b57cec5SDimitry Andric   bool operator()(const ValueType &LHS, const ValueType &RHS) const {
8180b57cec5SDimitry Andric     if (LHS.second == RHS.second) {
8190b57cec5SDimitry Andric       // We don't actually care about the order, but for consistency it
8200b57cec5SDimitry Andric       // shouldn't depend on pointer comparisons.
8210b57cec5SDimitry Andric       return LessRecordByID()(LHS.first.TheDef, RHS.first.TheDef);
8220b57cec5SDimitry Andric     }
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric     // Aliases with larger priorities should be considered first.
8250b57cec5SDimitry Andric     return LHS.second > RHS.second;
8260b57cec5SDimitry Andric   }
8270b57cec5SDimitry Andric };
8280b57cec5SDimitry Andric 
8290b57cec5SDimitry Andric } // end anonymous namespace
8300b57cec5SDimitry Andric 
EmitPrintAliasInstruction(raw_ostream & O)8310b57cec5SDimitry Andric void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
8320b57cec5SDimitry Andric   Record *AsmWriter = Target.getAsmWriter();
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric   O << "\n#ifdef PRINT_ALIAS_INSTR\n";
8350b57cec5SDimitry Andric   O << "#undef PRINT_ALIAS_INSTR\n\n";
8360b57cec5SDimitry Andric 
8370b57cec5SDimitry Andric   //////////////////////////////
8380b57cec5SDimitry Andric   // Gather information about aliases we need to print
8390b57cec5SDimitry Andric   //////////////////////////////
8400b57cec5SDimitry Andric 
8410b57cec5SDimitry Andric   // Emit the method that prints the alias instruction.
8420b57cec5SDimitry Andric   StringRef ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
8430b57cec5SDimitry Andric   unsigned Variant = AsmWriter->getValueAsInt("Variant");
8440b57cec5SDimitry Andric   bool PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
8450b57cec5SDimitry Andric 
8460b57cec5SDimitry Andric   std::vector<Record *> AllInstAliases =
8470b57cec5SDimitry Andric       Records.getAllDerivedDefinitions("InstAlias");
8480b57cec5SDimitry Andric 
8490b57cec5SDimitry Andric   // Create a map from the qualified name to a list of potential matches.
8500b57cec5SDimitry Andric   typedef std::set<std::pair<CodeGenInstAlias, int>, AliasPriorityComparator>
8510b57cec5SDimitry Andric       AliasWithPriority;
8520b57cec5SDimitry Andric   std::map<std::string, AliasWithPriority> AliasMap;
8530b57cec5SDimitry Andric   for (Record *R : AllInstAliases) {
8540b57cec5SDimitry Andric     int Priority = R->getValueAsInt("EmitPriority");
8550b57cec5SDimitry Andric     if (Priority < 1)
8560b57cec5SDimitry Andric       continue; // Aliases with priority 0 are never emitted.
8570b57cec5SDimitry Andric 
8580b57cec5SDimitry Andric     const DagInit *DI = R->getValueAsDag("ResultInst");
8598bcb0991SDimitry Andric     AliasMap[getQualifiedName(DI->getOperatorAsDef(R->getLoc()))].insert(
860*0fca6ea1SDimitry Andric         std::pair(CodeGenInstAlias(R, Target), Priority));
8610b57cec5SDimitry Andric   }
8620b57cec5SDimitry Andric 
8630b57cec5SDimitry Andric   // A map of which conditions need to be met for each instruction operand
8640b57cec5SDimitry Andric   // before it can be matched to the mnemonic.
8650b57cec5SDimitry Andric   std::map<std::string, std::vector<IAPrinter>> IAPrinterMap;
8660b57cec5SDimitry Andric 
8675ffd83dbSDimitry Andric   std::vector<std::pair<std::string, bool>> PrintMethods;
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric   // A list of MCOperandPredicates for all operands in use, and the reverse map
8700b57cec5SDimitry Andric   std::vector<const Record *> MCOpPredicates;
8710b57cec5SDimitry Andric   DenseMap<const Record *, unsigned> MCOpPredicateMap;
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric   for (auto &Aliases : AliasMap) {
874480093f4SDimitry Andric     // Collection of instruction alias rules. May contain ambiguous rules.
875480093f4SDimitry Andric     std::vector<IAPrinter> IAPs;
876480093f4SDimitry Andric 
8770b57cec5SDimitry Andric     for (auto &Alias : Aliases.second) {
8780b57cec5SDimitry Andric       const CodeGenInstAlias &CGA = Alias.first;
8790b57cec5SDimitry Andric       unsigned LastOpNo = CGA.ResultInstOperandIndex.size();
8800b57cec5SDimitry Andric       std::string FlatInstAsmString =
881*0fca6ea1SDimitry Andric           CodeGenInstruction::FlattenAsmStringVariants(
882*0fca6ea1SDimitry Andric               CGA.ResultInst->AsmString, Variant);
8830b57cec5SDimitry Andric       unsigned NumResultOps = CountNumOperands(FlatInstAsmString, Variant);
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric       std::string FlatAliasAsmString =
886480093f4SDimitry Andric           CodeGenInstruction::FlattenAsmStringVariants(CGA.AsmString, Variant);
8875ffd83dbSDimitry Andric       UnescapeAliasString(FlatAliasAsmString);
8880b57cec5SDimitry Andric 
8890b57cec5SDimitry Andric       // Don't emit the alias if it has more operands than what it's aliasing.
8900b57cec5SDimitry Andric       if (NumResultOps < CountNumOperands(FlatAliasAsmString, Variant))
8910b57cec5SDimitry Andric         continue;
8920b57cec5SDimitry Andric 
8930b57cec5SDimitry Andric       StringRef Namespace = Target.getName();
8940b57cec5SDimitry Andric       unsigned NumMIOps = 0;
8950b57cec5SDimitry Andric       for (auto &ResultInstOpnd : CGA.ResultInst->Operands)
8960b57cec5SDimitry Andric         NumMIOps += ResultInstOpnd.MINumOperands;
8970b57cec5SDimitry Andric 
898480093f4SDimitry Andric       IAPrinter IAP(CGA.Result->getAsString(), FlatAliasAsmString, NumMIOps);
8990b57cec5SDimitry Andric 
9000b57cec5SDimitry Andric       unsigned MIOpNum = 0;
9010b57cec5SDimitry Andric       for (unsigned i = 0, e = LastOpNo; i != e; ++i) {
9020b57cec5SDimitry Andric         // Skip over tied operands as they're not part of an alias declaration.
9030b57cec5SDimitry Andric         auto &Operands = CGA.ResultInst->Operands;
9040b57cec5SDimitry Andric         while (true) {
9050b57cec5SDimitry Andric           unsigned OpNum = Operands.getSubOperandNumber(MIOpNum).first;
9060b57cec5SDimitry Andric           if (Operands[OpNum].MINumOperands == 1 &&
9070b57cec5SDimitry Andric               Operands[OpNum].getTiedRegister() != -1) {
908*0fca6ea1SDimitry Andric             // Tied operands of different RegisterClass should be explicit
909*0fca6ea1SDimitry Andric             // within an instruction's syntax and so cannot be skipped.
9100b57cec5SDimitry Andric             int TiedOpNum = Operands[OpNum].getTiedRegister();
9110b57cec5SDimitry Andric             if (Operands[OpNum].Rec->getName() ==
9120b57cec5SDimitry Andric                 Operands[TiedOpNum].Rec->getName()) {
9130b57cec5SDimitry Andric               ++MIOpNum;
9140b57cec5SDimitry Andric               continue;
9150b57cec5SDimitry Andric             }
9160b57cec5SDimitry Andric           }
9170b57cec5SDimitry Andric           break;
9180b57cec5SDimitry Andric         }
9190b57cec5SDimitry Andric 
920480093f4SDimitry Andric         // Ignore unchecked result operands.
921480093f4SDimitry Andric         while (IAP.getCondCount() < MIOpNum)
922480093f4SDimitry Andric           IAP.addCond("AliasPatternCond::K_Ignore, 0");
9230b57cec5SDimitry Andric 
9240b57cec5SDimitry Andric         const CodeGenInstAlias::ResultOperand &RO = CGA.ResultOperands[i];
9250b57cec5SDimitry Andric 
9260b57cec5SDimitry Andric         switch (RO.Kind) {
9270b57cec5SDimitry Andric         case CodeGenInstAlias::ResultOperand::K_Record: {
9280b57cec5SDimitry Andric           const Record *Rec = RO.getRecord();
9290b57cec5SDimitry Andric           StringRef ROName = RO.getName();
9300b57cec5SDimitry Andric           int PrintMethodIdx = -1;
9310b57cec5SDimitry Andric 
9320b57cec5SDimitry Andric           // These two may have a PrintMethod, which we want to record (if it's
9330b57cec5SDimitry Andric           // the first time we've seen it) and provide an index for the aliasing
9340b57cec5SDimitry Andric           // code to use.
9350b57cec5SDimitry Andric           if (Rec->isSubClassOf("RegisterOperand") ||
9360b57cec5SDimitry Andric               Rec->isSubClassOf("Operand")) {
9370b57cec5SDimitry Andric             StringRef PrintMethod = Rec->getValueAsString("PrintMethod");
9385ffd83dbSDimitry Andric             bool IsPCRel =
9395ffd83dbSDimitry Andric                 Rec->getValueAsString("OperandType") == "OPERAND_PCREL";
9400b57cec5SDimitry Andric             if (PrintMethod != "" && PrintMethod != "printOperand") {
9415ffd83dbSDimitry Andric               PrintMethodIdx = llvm::find_if(PrintMethods,
9425ffd83dbSDimitry Andric                                              [&](auto &X) {
9435ffd83dbSDimitry Andric                                                return X.first == PrintMethod;
9445ffd83dbSDimitry Andric                                              }) -
9455ffd83dbSDimitry Andric                                PrintMethods.begin();
9460b57cec5SDimitry Andric               if (static_cast<unsigned>(PrintMethodIdx) == PrintMethods.size())
9475ffd83dbSDimitry Andric                 PrintMethods.emplace_back(std::string(PrintMethod), IsPCRel);
9480b57cec5SDimitry Andric             }
9490b57cec5SDimitry Andric           }
9500b57cec5SDimitry Andric 
9510b57cec5SDimitry Andric           if (Rec->isSubClassOf("RegisterOperand"))
9520b57cec5SDimitry Andric             Rec = Rec->getValueAsDef("RegClass");
9530b57cec5SDimitry Andric           if (Rec->isSubClassOf("RegisterClass")) {
9540b57cec5SDimitry Andric             if (!IAP.isOpMapped(ROName)) {
9550b57cec5SDimitry Andric               IAP.addOperand(ROName, MIOpNum, PrintMethodIdx);
9560b57cec5SDimitry Andric               Record *R = CGA.ResultOperands[i].getRecord();
9570b57cec5SDimitry Andric               if (R->isSubClassOf("RegisterOperand"))
9580b57cec5SDimitry Andric                 R = R->getValueAsDef("RegClass");
9595ffd83dbSDimitry Andric               IAP.addCond(std::string(
9605ffd83dbSDimitry Andric                   formatv("AliasPatternCond::K_RegClass, {0}::{1}RegClassID",
9615ffd83dbSDimitry Andric                           Namespace, R->getName())));
9620b57cec5SDimitry Andric             } else {
9635ffd83dbSDimitry Andric               IAP.addCond(std::string(formatv(
9645ffd83dbSDimitry Andric                   "AliasPatternCond::K_TiedReg, {0}", IAP.getOpIndex(ROName))));
9650b57cec5SDimitry Andric             }
9660b57cec5SDimitry Andric           } else {
9670b57cec5SDimitry Andric             // Assume all printable operands are desired for now. This can be
9680b57cec5SDimitry Andric             // overridden in the InstAlias instantiation if necessary.
9690b57cec5SDimitry Andric             IAP.addOperand(ROName, MIOpNum, PrintMethodIdx);
9700b57cec5SDimitry Andric 
9710b57cec5SDimitry Andric             // There might be an additional predicate on the MCOperand
9720b57cec5SDimitry Andric             unsigned Entry = MCOpPredicateMap[Rec];
9730b57cec5SDimitry Andric             if (!Entry) {
9740b57cec5SDimitry Andric               if (!Rec->isValueUnset("MCOperandPredicate")) {
9750b57cec5SDimitry Andric                 MCOpPredicates.push_back(Rec);
9760b57cec5SDimitry Andric                 Entry = MCOpPredicates.size();
9770b57cec5SDimitry Andric                 MCOpPredicateMap[Rec] = Entry;
9780b57cec5SDimitry Andric               } else
9790b57cec5SDimitry Andric                 break; // No conditions on this operand at all
9800b57cec5SDimitry Andric             }
9815ffd83dbSDimitry Andric             IAP.addCond(
9825ffd83dbSDimitry Andric                 std::string(formatv("AliasPatternCond::K_Custom, {0}", Entry)));
9830b57cec5SDimitry Andric           }
9840b57cec5SDimitry Andric           break;
9850b57cec5SDimitry Andric         }
9860b57cec5SDimitry Andric         case CodeGenInstAlias::ResultOperand::K_Imm: {
9870b57cec5SDimitry Andric           // Just because the alias has an immediate result, doesn't mean the
9880b57cec5SDimitry Andric           // MCInst will. An MCExpr could be present, for example.
989480093f4SDimitry Andric           auto Imm = CGA.ResultOperands[i].getImm();
990480093f4SDimitry Andric           int32_t Imm32 = int32_t(Imm);
991480093f4SDimitry Andric           if (Imm != Imm32)
992480093f4SDimitry Andric             PrintFatalError("Matching an alias with an immediate out of the "
993480093f4SDimitry Andric                             "range of int32_t is not supported");
9945ffd83dbSDimitry Andric           IAP.addCond(std::string(
9955ffd83dbSDimitry Andric               formatv("AliasPatternCond::K_Imm, uint32_t({0})", Imm32)));
9960b57cec5SDimitry Andric           break;
9970b57cec5SDimitry Andric         }
9980b57cec5SDimitry Andric         case CodeGenInstAlias::ResultOperand::K_Reg:
9990b57cec5SDimitry Andric           if (!CGA.ResultOperands[i].getRegister()) {
100081ad6265SDimitry Andric             IAP.addCond(std::string(formatv(
100181ad6265SDimitry Andric                 "AliasPatternCond::K_Reg, {0}::NoRegister", Namespace)));
10020b57cec5SDimitry Andric             break;
10030b57cec5SDimitry Andric           }
10040b57cec5SDimitry Andric 
1005480093f4SDimitry Andric           StringRef Reg = CGA.ResultOperands[i].getRegister()->getName();
10065ffd83dbSDimitry Andric           IAP.addCond(std::string(
10075ffd83dbSDimitry Andric               formatv("AliasPatternCond::K_Reg, {0}::{1}", Namespace, Reg)));
10080b57cec5SDimitry Andric           break;
10090b57cec5SDimitry Andric         }
10100b57cec5SDimitry Andric 
10110b57cec5SDimitry Andric         MIOpNum += RO.getMINumOperands();
10120b57cec5SDimitry Andric       }
10130b57cec5SDimitry Andric 
1014480093f4SDimitry Andric       std::vector<Record *> ReqFeatures;
1015480093f4SDimitry Andric       if (PassSubtarget) {
1016480093f4SDimitry Andric         // We only consider ReqFeatures predicates if PassSubtarget
1017480093f4SDimitry Andric         std::vector<Record *> RF =
1018480093f4SDimitry Andric             CGA.TheDef->getValueAsListOfDefs("Predicates");
1019480093f4SDimitry Andric         copy_if(RF, std::back_inserter(ReqFeatures), [](Record *R) {
1020480093f4SDimitry Andric           return R->getValueAsBit("AssemblerMatcherPredicate");
1021480093f4SDimitry Andric         });
1022480093f4SDimitry Andric       }
1023480093f4SDimitry Andric 
1024fe6060f1SDimitry Andric       for (Record *const R : ReqFeatures) {
10255ffd83dbSDimitry Andric         const DagInit *D = R->getValueAsDag("AssemblerCondDag");
102606c3fb27SDimitry Andric         auto *Op = dyn_cast<DefInit>(D->getOperator());
102706c3fb27SDimitry Andric         if (!Op)
102806c3fb27SDimitry Andric           PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
102906c3fb27SDimitry Andric         StringRef CombineType = Op->getDef()->getName();
10305ffd83dbSDimitry Andric         if (CombineType != "any_of" && CombineType != "all_of")
10315ffd83dbSDimitry Andric           PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
10325ffd83dbSDimitry Andric         if (D->getNumArgs() == 0)
10335ffd83dbSDimitry Andric           PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
10345ffd83dbSDimitry Andric         bool IsOr = CombineType == "any_of";
103581ad6265SDimitry Andric         // Change (any_of FeatureAll, (any_of ...)) to (any_of FeatureAll, ...).
103681ad6265SDimitry Andric         if (IsOr && D->getNumArgs() == 2 && isa<DagInit>(D->getArg(1))) {
103706c3fb27SDimitry Andric           DagInit *RHS = cast<DagInit>(D->getArg(1));
103881ad6265SDimitry Andric           SmallVector<Init *> Args{D->getArg(0)};
103981ad6265SDimitry Andric           SmallVector<StringInit *> ArgNames{D->getArgName(0)};
104081ad6265SDimitry Andric           for (unsigned i = 0, e = RHS->getNumArgs(); i != e; ++i) {
104181ad6265SDimitry Andric             Args.push_back(RHS->getArg(i));
104281ad6265SDimitry Andric             ArgNames.push_back(RHS->getArgName(i));
104381ad6265SDimitry Andric           }
104481ad6265SDimitry Andric           D = DagInit::get(D->getOperator(), nullptr, Args, ArgNames);
104581ad6265SDimitry Andric         }
10460b57cec5SDimitry Andric 
10475ffd83dbSDimitry Andric         for (auto *Arg : D->getArgs()) {
10485ffd83dbSDimitry Andric           bool IsNeg = false;
10495ffd83dbSDimitry Andric           if (auto *NotArg = dyn_cast<DagInit>(Arg)) {
10505ffd83dbSDimitry Andric             if (NotArg->getOperator()->getAsString() != "not" ||
10515ffd83dbSDimitry Andric                 NotArg->getNumArgs() != 1)
10525ffd83dbSDimitry Andric               PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
10535ffd83dbSDimitry Andric             Arg = NotArg->getArg(0);
10545ffd83dbSDimitry Andric             IsNeg = true;
10550b57cec5SDimitry Andric           }
10565ffd83dbSDimitry Andric           if (!isa<DefInit>(Arg) ||
10575ffd83dbSDimitry Andric               !cast<DefInit>(Arg)->getDef()->isSubClassOf("SubtargetFeature"))
10585ffd83dbSDimitry Andric             PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
10595ffd83dbSDimitry Andric 
10605ffd83dbSDimitry Andric           IAP.addCond(std::string(formatv(
10615ffd83dbSDimitry Andric               "AliasPatternCond::K_{0}{1}Feature, {2}::{3}", IsOr ? "Or" : "",
10625ffd83dbSDimitry Andric               IsNeg ? "Neg" : "", Namespace, Arg->getAsString())));
10635ffd83dbSDimitry Andric         }
10645ffd83dbSDimitry Andric         // If an AssemblerPredicate with ors is used, note end of list should
10655ffd83dbSDimitry Andric         // these be combined.
10665ffd83dbSDimitry Andric         if (IsOr)
10675ffd83dbSDimitry Andric           IAP.addCond("AliasPatternCond::K_EndOrFeatures, 0");
10680b57cec5SDimitry Andric       }
10690b57cec5SDimitry Andric 
10700b57cec5SDimitry Andric       IAPrinterMap[Aliases.first].push_back(std::move(IAP));
10710b57cec5SDimitry Andric     }
10720b57cec5SDimitry Andric   }
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric   //////////////////////////////
10750b57cec5SDimitry Andric   // Write out the printAliasInstr function
10760b57cec5SDimitry Andric   //////////////////////////////
10770b57cec5SDimitry Andric 
10780b57cec5SDimitry Andric   std::string Header;
10790b57cec5SDimitry Andric   raw_string_ostream HeaderO(Header);
10800b57cec5SDimitry Andric 
10810b57cec5SDimitry Andric   HeaderO << "bool " << Target.getName() << ClassName
10820b57cec5SDimitry Andric           << "::printAliasInstr(const MCInst"
10835ffd83dbSDimitry Andric           << " *MI, uint64_t Address, "
10845ffd83dbSDimitry Andric           << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
10850b57cec5SDimitry Andric           << "raw_ostream &OS) {\n";
10860b57cec5SDimitry Andric 
1087480093f4SDimitry Andric   std::string PatternsForOpcode;
1088480093f4SDimitry Andric   raw_string_ostream OpcodeO(PatternsForOpcode);
10890b57cec5SDimitry Andric 
1090480093f4SDimitry Andric   unsigned PatternCount = 0;
1091480093f4SDimitry Andric   std::string Patterns;
1092480093f4SDimitry Andric   raw_string_ostream PatternO(Patterns);
1093480093f4SDimitry Andric 
1094480093f4SDimitry Andric   unsigned CondCount = 0;
1095480093f4SDimitry Andric   std::string Conds;
1096480093f4SDimitry Andric   raw_string_ostream CondO(Conds);
1097480093f4SDimitry Andric 
1098480093f4SDimitry Andric   // All flattened alias strings.
1099480093f4SDimitry Andric   std::map<std::string, uint32_t> AsmStringOffsets;
1100480093f4SDimitry Andric   std::vector<std::pair<uint32_t, std::string>> AsmStrings;
1101480093f4SDimitry Andric   size_t AsmStringsSize = 0;
1102480093f4SDimitry Andric 
1103480093f4SDimitry Andric   // Iterate over the opcodes in enum order so they are sorted by opcode for
1104480093f4SDimitry Andric   // binary search.
1105480093f4SDimitry Andric   for (const CodeGenInstruction *Inst : NumberedInstructions) {
1106480093f4SDimitry Andric     auto It = IAPrinterMap.find(getQualifiedName(Inst->TheDef));
1107480093f4SDimitry Andric     if (It == IAPrinterMap.end())
1108480093f4SDimitry Andric       continue;
1109480093f4SDimitry Andric     std::vector<IAPrinter> &IAPs = It->second;
11100b57cec5SDimitry Andric     std::vector<IAPrinter *> UniqueIAPs;
11110b57cec5SDimitry Andric 
1112480093f4SDimitry Andric     // Remove any ambiguous alias rules.
11130b57cec5SDimitry Andric     for (auto &LHS : IAPs) {
11140b57cec5SDimitry Andric       bool IsDup = false;
11150b57cec5SDimitry Andric       for (const auto &RHS : IAPs) {
11160b57cec5SDimitry Andric         if (&LHS != &RHS && LHS == RHS) {
11170b57cec5SDimitry Andric           IsDup = true;
11180b57cec5SDimitry Andric           break;
11190b57cec5SDimitry Andric         }
11200b57cec5SDimitry Andric       }
11210b57cec5SDimitry Andric 
11220b57cec5SDimitry Andric       if (!IsDup)
11230b57cec5SDimitry Andric         UniqueIAPs.push_back(&LHS);
11240b57cec5SDimitry Andric     }
11250b57cec5SDimitry Andric 
1126*0fca6ea1SDimitry Andric     if (UniqueIAPs.empty())
1127*0fca6ea1SDimitry Andric       continue;
11280b57cec5SDimitry Andric 
1129480093f4SDimitry Andric     unsigned PatternStart = PatternCount;
1130480093f4SDimitry Andric 
1131480093f4SDimitry Andric     // Insert the pattern start and opcode in the pattern list for debugging.
1132480093f4SDimitry Andric     PatternO << formatv("    // {0} - {1}\n", It->first, PatternStart);
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric     for (IAPrinter *IAP : UniqueIAPs) {
1135480093f4SDimitry Andric       // Start each condition list with a comment of the resulting pattern that
1136480093f4SDimitry Andric       // we're trying to match.
1137480093f4SDimitry Andric       unsigned CondStart = CondCount;
1138480093f4SDimitry Andric       CondO << formatv("    // {0} - {1}\n", IAP->getResult(), CondStart);
1139480093f4SDimitry Andric       for (const auto &Cond : IAP->getConds())
1140480093f4SDimitry Andric         CondO << "    {" << Cond << "},\n";
1141480093f4SDimitry Andric       CondCount += IAP->getCondCount();
1142480093f4SDimitry Andric 
1143480093f4SDimitry Andric       // After operands have been examined, re-encode the alias string with
1144480093f4SDimitry Andric       // escapes indicating how operands should be printed.
1145480093f4SDimitry Andric       uint32_t UnescapedSize = 0;
1146480093f4SDimitry Andric       std::string EncodedAsmString = IAP->formatAliasString(UnescapedSize);
1147480093f4SDimitry Andric       auto Insertion =
1148480093f4SDimitry Andric           AsmStringOffsets.insert({EncodedAsmString, AsmStringsSize});
1149480093f4SDimitry Andric       if (Insertion.second) {
1150480093f4SDimitry Andric         // If the string is new, add it to the vector.
1151480093f4SDimitry Andric         AsmStrings.push_back({AsmStringsSize, EncodedAsmString});
1152480093f4SDimitry Andric         AsmStringsSize += UnescapedSize + 1;
1153480093f4SDimitry Andric       }
1154480093f4SDimitry Andric       unsigned AsmStrOffset = Insertion.first->second;
1155480093f4SDimitry Andric 
1156480093f4SDimitry Andric       PatternO << formatv("    {{{0}, {1}, {2}, {3} },\n", AsmStrOffset,
1157480093f4SDimitry Andric                           CondStart, IAP->getNumMIOps(), IAP->getCondCount());
1158480093f4SDimitry Andric       ++PatternCount;
11590b57cec5SDimitry Andric     }
11600b57cec5SDimitry Andric 
1161480093f4SDimitry Andric     OpcodeO << formatv("    {{{0}, {1}, {2} },\n", It->first, PatternStart,
1162480093f4SDimitry Andric                        PatternCount - PatternStart);
11630b57cec5SDimitry Andric   }
11640b57cec5SDimitry Andric 
1165*0fca6ea1SDimitry Andric   if (PatternsForOpcode.empty()) {
1166*0fca6ea1SDimitry Andric     O << Header;
11670b57cec5SDimitry Andric     O << "  return false;\n";
11680b57cec5SDimitry Andric     O << "}\n\n";
11690b57cec5SDimitry Andric     O << "#endif // PRINT_ALIAS_INSTR\n";
11700b57cec5SDimitry Andric     return;
11710b57cec5SDimitry Andric   }
11720b57cec5SDimitry Andric 
1173480093f4SDimitry Andric   // Forward declare the validation method if needed.
11740b57cec5SDimitry Andric   if (!MCOpPredicates.empty())
11750b57cec5SDimitry Andric     O << "static bool " << Target.getName() << ClassName
11760b57cec5SDimitry Andric       << "ValidateMCOperand(const MCOperand &MCOp,\n"
11770b57cec5SDimitry Andric       << "                  const MCSubtargetInfo &STI,\n"
11780b57cec5SDimitry Andric       << "                  unsigned PredicateIndex);\n";
11790b57cec5SDimitry Andric 
1180*0fca6ea1SDimitry Andric   O << Header;
1181480093f4SDimitry Andric   O.indent(2) << "static const PatternsForOpcode OpToPatterns[] = {\n";
1182*0fca6ea1SDimitry Andric   O << PatternsForOpcode;
1183480093f4SDimitry Andric   O.indent(2) << "};\n\n";
1184480093f4SDimitry Andric   O.indent(2) << "static const AliasPattern Patterns[] = {\n";
1185*0fca6ea1SDimitry Andric   O << Patterns;
1186480093f4SDimitry Andric   O.indent(2) << "};\n\n";
1187480093f4SDimitry Andric   O.indent(2) << "static const AliasPatternCond Conds[] = {\n";
1188*0fca6ea1SDimitry Andric   O << Conds;
1189480093f4SDimitry Andric   O.indent(2) << "};\n\n";
1190480093f4SDimitry Andric   O.indent(2) << "static const char AsmStrings[] =\n";
1191480093f4SDimitry Andric   for (const auto &P : AsmStrings) {
1192480093f4SDimitry Andric     O.indent(4) << "/* " << P.first << " */ \"" << P.second << "\\0\"\n";
1193480093f4SDimitry Andric   }
1194480093f4SDimitry Andric 
1195480093f4SDimitry Andric   O.indent(2) << ";\n\n";
1196480093f4SDimitry Andric 
1197480093f4SDimitry Andric   // Assert that the opcode table is sorted. Use a static local constructor to
1198480093f4SDimitry Andric   // ensure that the check only happens once on first run.
1199480093f4SDimitry Andric   O << "#ifndef NDEBUG\n";
1200480093f4SDimitry Andric   O.indent(2) << "static struct SortCheck {\n";
1201480093f4SDimitry Andric   O.indent(2) << "  SortCheck(ArrayRef<PatternsForOpcode> OpToPatterns) {\n";
1202480093f4SDimitry Andric   O.indent(2) << "    assert(std::is_sorted(\n";
1203480093f4SDimitry Andric   O.indent(2) << "               OpToPatterns.begin(), OpToPatterns.end(),\n";
1204480093f4SDimitry Andric   O.indent(2) << "               [](const PatternsForOpcode &L, const "
1205480093f4SDimitry Andric                  "PatternsForOpcode &R) {\n";
1206480093f4SDimitry Andric   O.indent(2) << "                 return L.Opcode < R.Opcode;\n";
1207480093f4SDimitry Andric   O.indent(2) << "               }) &&\n";
1208480093f4SDimitry Andric   O.indent(2) << "           \"tablegen failed to sort opcode patterns\");\n";
1209480093f4SDimitry Andric   O.indent(2) << "  }\n";
1210480093f4SDimitry Andric   O.indent(2) << "} sortCheckVar(OpToPatterns);\n";
1211480093f4SDimitry Andric   O << "#endif\n\n";
1212480093f4SDimitry Andric 
1213480093f4SDimitry Andric   O.indent(2) << "AliasMatchingData M {\n";
1214bdd1243dSDimitry Andric   O.indent(2) << "  ArrayRef(OpToPatterns),\n";
1215bdd1243dSDimitry Andric   O.indent(2) << "  ArrayRef(Patterns),\n";
1216bdd1243dSDimitry Andric   O.indent(2) << "  ArrayRef(Conds),\n";
1217bdd1243dSDimitry Andric   O.indent(2) << "  StringRef(AsmStrings, std::size(AsmStrings)),\n";
1218480093f4SDimitry Andric   if (MCOpPredicates.empty())
1219480093f4SDimitry Andric     O.indent(2) << "  nullptr,\n";
1220480093f4SDimitry Andric   else
1221*0fca6ea1SDimitry Andric     O.indent(2) << "  &" << Target.getName() << ClassName
1222*0fca6ea1SDimitry Andric                 << "ValidateMCOperand,\n";
1223480093f4SDimitry Andric   O.indent(2) << "};\n";
1224480093f4SDimitry Andric 
1225480093f4SDimitry Andric   O.indent(2) << "const char *AsmString = matchAliasPatterns(MI, "
1226480093f4SDimitry Andric               << (PassSubtarget ? "&STI" : "nullptr") << ", M);\n";
1227480093f4SDimitry Andric   O.indent(2) << "if (!AsmString) return false;\n\n";
12280b57cec5SDimitry Andric 
12290b57cec5SDimitry Andric   // Code that prints the alias, replacing the operands with the ones from the
12300b57cec5SDimitry Andric   // MCInst.
12310b57cec5SDimitry Andric   O << "  unsigned I = 0;\n";
12320b57cec5SDimitry Andric   O << "  while (AsmString[I] != ' ' && AsmString[I] != '\\t' &&\n";
12330b57cec5SDimitry Andric   O << "         AsmString[I] != '$' && AsmString[I] != '\\0')\n";
12340b57cec5SDimitry Andric   O << "    ++I;\n";
12350b57cec5SDimitry Andric   O << "  OS << '\\t' << StringRef(AsmString, I);\n";
12360b57cec5SDimitry Andric 
12370b57cec5SDimitry Andric   O << "  if (AsmString[I] != '\\0') {\n";
12380b57cec5SDimitry Andric   O << "    if (AsmString[I] == ' ' || AsmString[I] == '\\t') {\n";
12390b57cec5SDimitry Andric   O << "      OS << '\\t';\n";
12400b57cec5SDimitry Andric   O << "      ++I;\n";
12410b57cec5SDimitry Andric   O << "    }\n";
12420b57cec5SDimitry Andric   O << "    do {\n";
12430b57cec5SDimitry Andric   O << "      if (AsmString[I] == '$') {\n";
12440b57cec5SDimitry Andric   O << "        ++I;\n";
12450b57cec5SDimitry Andric   O << "        if (AsmString[I] == (char)0xff) {\n";
12460b57cec5SDimitry Andric   O << "          ++I;\n";
12470b57cec5SDimitry Andric   O << "          int OpIdx = AsmString[I++] - 1;\n";
12480b57cec5SDimitry Andric   O << "          int PrintMethodIdx = AsmString[I++] - 1;\n";
12495ffd83dbSDimitry Andric   O << "          printCustomAliasOperand(MI, Address, OpIdx, PrintMethodIdx, ";
12500b57cec5SDimitry Andric   O << (PassSubtarget ? "STI, " : "");
12510b57cec5SDimitry Andric   O << "OS);\n";
12520b57cec5SDimitry Andric   O << "        } else\n";
12530b57cec5SDimitry Andric   O << "          printOperand(MI, unsigned(AsmString[I++]) - 1, ";
12540b57cec5SDimitry Andric   O << (PassSubtarget ? "STI, " : "");
12550b57cec5SDimitry Andric   O << "OS);\n";
12560b57cec5SDimitry Andric   O << "      } else {\n";
12570b57cec5SDimitry Andric   O << "        OS << AsmString[I++];\n";
12580b57cec5SDimitry Andric   O << "      }\n";
12590b57cec5SDimitry Andric   O << "    } while (AsmString[I] != '\\0');\n";
12600b57cec5SDimitry Andric   O << "  }\n\n";
12610b57cec5SDimitry Andric 
12620b57cec5SDimitry Andric   O << "  return true;\n";
12630b57cec5SDimitry Andric   O << "}\n\n";
12640b57cec5SDimitry Andric 
12650b57cec5SDimitry Andric   //////////////////////////////
12660b57cec5SDimitry Andric   // Write out the printCustomAliasOperand function
12670b57cec5SDimitry Andric   //////////////////////////////
12680b57cec5SDimitry Andric 
12690b57cec5SDimitry Andric   O << "void " << Target.getName() << ClassName << "::"
12700b57cec5SDimitry Andric     << "printCustomAliasOperand(\n"
12715ffd83dbSDimitry Andric     << "         const MCInst *MI, uint64_t Address, unsigned OpIdx,\n"
12720b57cec5SDimitry Andric     << "         unsigned PrintMethodIdx,\n"
12730b57cec5SDimitry Andric     << (PassSubtarget ? "         const MCSubtargetInfo &STI,\n" : "")
12740b57cec5SDimitry Andric     << "         raw_ostream &OS) {\n";
12750b57cec5SDimitry Andric   if (PrintMethods.empty())
12760b57cec5SDimitry Andric     O << "  llvm_unreachable(\"Unknown PrintMethod kind\");\n";
12770b57cec5SDimitry Andric   else {
12780b57cec5SDimitry Andric     O << "  switch (PrintMethodIdx) {\n"
12790b57cec5SDimitry Andric       << "  default:\n"
12800b57cec5SDimitry Andric       << "    llvm_unreachable(\"Unknown PrintMethod kind\");\n"
12810b57cec5SDimitry Andric       << "    break;\n";
12820b57cec5SDimitry Andric 
12830b57cec5SDimitry Andric     for (unsigned i = 0; i < PrintMethods.size(); ++i) {
12840b57cec5SDimitry Andric       O << "  case " << i << ":\n"
12855ffd83dbSDimitry Andric         << "    " << PrintMethods[i].first << "(MI, "
12865ffd83dbSDimitry Andric         << (PrintMethods[i].second ? "Address, " : "") << "OpIdx, "
12870b57cec5SDimitry Andric         << (PassSubtarget ? "STI, " : "") << "OS);\n"
12880b57cec5SDimitry Andric         << "    break;\n";
12890b57cec5SDimitry Andric     }
12900b57cec5SDimitry Andric     O << "  }\n";
12910b57cec5SDimitry Andric   }
12920b57cec5SDimitry Andric   O << "}\n\n";
12930b57cec5SDimitry Andric 
12940b57cec5SDimitry Andric   if (!MCOpPredicates.empty()) {
12950b57cec5SDimitry Andric     O << "static bool " << Target.getName() << ClassName
12960b57cec5SDimitry Andric       << "ValidateMCOperand(const MCOperand &MCOp,\n"
12970b57cec5SDimitry Andric       << "                  const MCSubtargetInfo &STI,\n"
12980b57cec5SDimitry Andric       << "                  unsigned PredicateIndex) {\n"
12990b57cec5SDimitry Andric       << "  switch (PredicateIndex) {\n"
13000b57cec5SDimitry Andric       << "  default:\n"
13010b57cec5SDimitry Andric       << "    llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n"
13020b57cec5SDimitry Andric       << "    break;\n";
13030b57cec5SDimitry Andric 
13040b57cec5SDimitry Andric     for (unsigned i = 0; i < MCOpPredicates.size(); ++i) {
1305*0fca6ea1SDimitry Andric       StringRef MCOpPred =
1306*0fca6ea1SDimitry Andric           MCOpPredicates[i]->getValueAsString("MCOperandPredicate");
13070b57cec5SDimitry Andric       O << "  case " << i + 1 << ": {\n"
1308e8d8bef9SDimitry Andric         << MCOpPred.data() << "\n"
13090b57cec5SDimitry Andric         << "    }\n";
13100b57cec5SDimitry Andric     }
13110b57cec5SDimitry Andric     O << "  }\n"
13120b57cec5SDimitry Andric       << "}\n\n";
13130b57cec5SDimitry Andric   }
13140b57cec5SDimitry Andric 
13150b57cec5SDimitry Andric   O << "#endif // PRINT_ALIAS_INSTR\n";
13160b57cec5SDimitry Andric }
13170b57cec5SDimitry Andric 
AsmWriterEmitter(RecordKeeper & R)13180b57cec5SDimitry Andric AsmWriterEmitter::AsmWriterEmitter(RecordKeeper &R) : Records(R), Target(R) {
13190b57cec5SDimitry Andric   Record *AsmWriter = Target.getAsmWriter();
13200b57cec5SDimitry Andric   unsigned Variant = AsmWriter->getValueAsInt("Variant");
13210b57cec5SDimitry Andric 
13220b57cec5SDimitry Andric   // Get the instruction numbering.
13230b57cec5SDimitry Andric   NumberedInstructions = Target.getInstructionsByEnumValue();
13240b57cec5SDimitry Andric 
13250b57cec5SDimitry Andric   for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
13260b57cec5SDimitry Andric     const CodeGenInstruction *I = NumberedInstructions[i];
13270b57cec5SDimitry Andric     if (!I->AsmString.empty() && I->TheDef->getName() != "PHI")
13280b57cec5SDimitry Andric       Instructions.emplace_back(*I, i, Variant);
13290b57cec5SDimitry Andric   }
13300b57cec5SDimitry Andric }
13310b57cec5SDimitry Andric 
run(raw_ostream & O)13320b57cec5SDimitry Andric void AsmWriterEmitter::run(raw_ostream &O) {
1333e8d8bef9SDimitry Andric   std::vector<std::vector<std::string>> TableDrivenOperandPrinters;
1334e8d8bef9SDimitry Andric   unsigned BitsLeft = 0;
1335e8d8bef9SDimitry Andric   unsigned AsmStrBits = 0;
13365f757f3fSDimitry Andric   emitSourceFileHeader("Assembly Writer Source Fragment", O, Records);
1337e8d8bef9SDimitry Andric   EmitGetMnemonic(O, TableDrivenOperandPrinters, BitsLeft, AsmStrBits);
1338e8d8bef9SDimitry Andric   EmitPrintInstruction(O, TableDrivenOperandPrinters, BitsLeft, AsmStrBits);
13390b57cec5SDimitry Andric   EmitGetRegisterName(O);
13400b57cec5SDimitry Andric   EmitPrintAliasInstruction(O);
13410b57cec5SDimitry Andric }
13420b57cec5SDimitry Andric 
134306c3fb27SDimitry Andric static TableGen::Emitter::OptClass<AsmWriterEmitter>
134406c3fb27SDimitry Andric     X("gen-asm-writer", "Generate assembly writer");
1345