1//===- InstrDocsEmitter.cpp - Opcode Documentation Generator --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// InstrDocsEmitter generates restructured text documentation for the opcodes
10// that can be used by MachineInstr. For each opcode, the documentation lists:
11// * Opcode name
12// * Assembly string
13// * Flags (e.g. mayLoad, isBranch, ...)
14// * Operands, including type and name
15// * Operand constraints
16// * Implicit register uses & defs
17// * Predicates
18//
19//===----------------------------------------------------------------------===//
20
21#include "CodeGenDAGPatterns.h"
22#include "CodeGenInstruction.h"
23#include "CodeGenTarget.h"
24#include "TableGenBackends.h"
25#include "llvm/TableGen/Record.h"
26#include <string>
27#include <vector>
28
29using namespace llvm;
30
31namespace llvm {
32
33void writeTitle(StringRef Str, raw_ostream &OS, char Kind = '-') {
34  OS << std::string(Str.size(), Kind) << "\n" << Str << "\n"
35     << std::string(Str.size(), Kind) << "\n";
36}
37
38void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') {
39  OS << Str << "\n" << std::string(Str.size(), Kind) << "\n";
40}
41
42std::string escapeForRST(StringRef Str) {
43  std::string Result;
44  Result.reserve(Str.size() + 4);
45  for (char C : Str) {
46    switch (C) {
47    // We want special characters to be shown as their C escape codes.
48    case '\n': Result += "\\n"; break;
49    case '\t': Result += "\\t"; break;
50    // Underscore at the end of a line has a special meaning in rst.
51    case '_': Result += "\\_"; break;
52    default: Result += C;
53    }
54  }
55  return Result;
56}
57
58void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) {
59  CodeGenDAGPatterns CDP(RK);
60  CodeGenTarget &Target = CDP.getTargetInfo();
61  unsigned VariantCount = Target.getAsmParserVariantCount();
62
63  // Page title.
64  std::string Title = Target.getName();
65  Title += " Instructions";
66  writeTitle(Title, OS);
67  OS << "\n";
68
69  for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) {
70    Record *Inst = II->TheDef;
71
72    // Don't print the target-independent instructions.
73    if (II->Namespace == "TargetOpcode")
74      continue;
75
76    // Heading (instruction name).
77    writeHeader(escapeForRST(Inst->getName()), OS, '=');
78    OS << "\n";
79
80    // Assembly string(s).
81    if (!II->AsmString.empty()) {
82      for (unsigned VarNum = 0; VarNum < VariantCount; ++VarNum) {
83        Record *AsmVariant = Target.getAsmParserVariant(VarNum);
84        OS << "Assembly string";
85        if (VariantCount != 1)
86          OS << " (" << AsmVariant->getValueAsString("Name") << ")";
87        std::string AsmString =
88            CodeGenInstruction::FlattenAsmStringVariants(II->AsmString, VarNum);
89        // We trim spaces at each end of the asm string because rst needs the
90        // formatting backticks to be next to a non-whitespace character.
91        OS << ": ``" << escapeForRST(StringRef(AsmString).trim(" "))
92           << "``\n\n";
93      }
94    }
95
96    // Boolean flags.
97    std::vector<const char *> FlagStrings;
98#define xstr(s) str(s)
99#define str(s) #s
100#define FLAG(f) if (II->f) { FlagStrings.push_back(str(f)); }
101    FLAG(isReturn)
102    FLAG(isEHScopeReturn)
103    FLAG(isBranch)
104    FLAG(isIndirectBranch)
105    FLAG(isCompare)
106    FLAG(isMoveImm)
107    FLAG(isBitcast)
108    FLAG(isSelect)
109    FLAG(isBarrier)
110    FLAG(isCall)
111    FLAG(isAdd)
112    FLAG(isTrap)
113    FLAG(canFoldAsLoad)
114    FLAG(mayLoad)
115    //FLAG(mayLoad_Unset) // Deliberately omitted.
116    FLAG(mayStore)
117    //FLAG(mayStore_Unset) // Deliberately omitted.
118    FLAG(isPredicable)
119    FLAG(isConvertibleToThreeAddress)
120    FLAG(isCommutable)
121    FLAG(isTerminator)
122    FLAG(isReMaterializable)
123    FLAG(hasDelaySlot)
124    FLAG(usesCustomInserter)
125    FLAG(hasPostISelHook)
126    FLAG(hasCtrlDep)
127    FLAG(isNotDuplicable)
128    FLAG(hasSideEffects)
129    //FLAG(hasSideEffects_Unset) // Deliberately omitted.
130    FLAG(isAsCheapAsAMove)
131    FLAG(hasExtraSrcRegAllocReq)
132    FLAG(hasExtraDefRegAllocReq)
133    FLAG(isCodeGenOnly)
134    FLAG(isPseudo)
135    FLAG(isRegSequence)
136    FLAG(isExtractSubreg)
137    FLAG(isInsertSubreg)
138    FLAG(isConvergent)
139    FLAG(hasNoSchedulingInfo)
140    FLAG(variadicOpsAreDefs)
141    FLAG(isAuthenticated)
142    if (!FlagStrings.empty()) {
143      OS << "Flags: ";
144      bool IsFirst = true;
145      for (auto FlagString : FlagStrings) {
146        if (!IsFirst)
147          OS << ", ";
148        OS << "``" << FlagString << "``";
149        IsFirst = false;
150      }
151      OS << "\n\n";
152    }
153
154    // Operands.
155    for (unsigned i = 0; i < II->Operands.size(); ++i) {
156      bool IsDef = i < II->Operands.NumDefs;
157      auto Op = II->Operands[i];
158
159      if (Op.MINumOperands > 1) {
160        // This operand corresponds to multiple operands on the
161        // MachineInstruction, so print all of them, showing the types and
162        // names of both the compound operand and the basic operands it
163        // contains.
164        for (unsigned SubOpIdx = 0; SubOpIdx < Op.MINumOperands; ++SubOpIdx) {
165          Record *SubRec =
166              cast<DefInit>(Op.MIOperandInfo->getArg(SubOpIdx))->getDef();
167          StringRef SubOpName = Op.MIOperandInfo->getArgNameStr(SubOpIdx);
168          StringRef SubOpTypeName = SubRec->getName();
169
170          OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName()
171             << "/" << SubOpTypeName << ":$" << Op.Name << ".";
172          // Not all sub-operands are named, make up a name for these.
173          if (SubOpName.empty())
174            OS << "anon" << SubOpIdx;
175          else
176            OS << SubOpName;
177          OS << "``\n\n";
178        }
179      } else {
180        // The operand corresponds to only one MachineInstruction operand.
181        OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName()
182           << ":$" << Op.Name << "``\n\n";
183      }
184    }
185
186    // Constraints.
187    StringRef Constraints = Inst->getValueAsString("Constraints");
188    if (!Constraints.empty()) {
189      OS << "Constraints: ``" << Constraints << "``\n\n";
190    }
191
192    // Implicit definitions.
193    if (!II->ImplicitDefs.empty()) {
194      OS << "Implicit defs: ";
195      bool IsFirst = true;
196      for (Record *Def : II->ImplicitDefs) {
197        if (!IsFirst)
198          OS << ", ";
199        OS << "``" << Def->getName() << "``";
200        IsFirst = false;
201      }
202      OS << "\n\n";
203    }
204
205    // Implicit uses.
206    if (!II->ImplicitUses.empty()) {
207      OS << "Implicit uses: ";
208      bool IsFirst = true;
209      for (Record *Use : II->ImplicitUses) {
210        if (!IsFirst)
211          OS << ", ";
212        OS << "``" << Use->getName() << "``";
213        IsFirst = false;
214      }
215      OS << "\n\n";
216    }
217
218    // Predicates.
219    std::vector<Record *> Predicates =
220        II->TheDef->getValueAsListOfDefs("Predicates");
221    if (!Predicates.empty()) {
222      OS << "Predicates: ";
223      bool IsFirst = true;
224      for (Record *P : Predicates) {
225        if (!IsFirst)
226          OS << ", ";
227        OS << "``" << P->getName() << "``";
228        IsFirst = false;
229      }
230      OS << "\n\n";
231    }
232  }
233}
234
235} // end namespace llvm
236