1174fdef4SOliver Stannard //===- InstrDocsEmitter.cpp - Opcode Documentation Generator --------------===//
2174fdef4SOliver Stannard //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6174fdef4SOliver Stannard //
7174fdef4SOliver Stannard //===----------------------------------------------------------------------===//
8174fdef4SOliver Stannard //
9174fdef4SOliver Stannard // InstrDocsEmitter generates restructured text documentation for the opcodes
10174fdef4SOliver Stannard // that can be used by MachineInstr. For each opcode, the documentation lists:
11174fdef4SOliver Stannard // * Opcode name
12174fdef4SOliver Stannard // * Assembly string
13174fdef4SOliver Stannard // * Flags (e.g. mayLoad, isBranch, ...)
14174fdef4SOliver Stannard // * Operands, including type and name
15174fdef4SOliver Stannard // * Operand constraints
16174fdef4SOliver Stannard // * Implicit register uses & defs
17174fdef4SOliver Stannard // * Predicates
18174fdef4SOliver Stannard //
19174fdef4SOliver Stannard //===----------------------------------------------------------------------===//
20174fdef4SOliver Stannard 
21174fdef4SOliver Stannard #include "CodeGenDAGPatterns.h"
22174fdef4SOliver Stannard #include "CodeGenInstruction.h"
23174fdef4SOliver Stannard #include "CodeGenTarget.h"
24174fdef4SOliver Stannard #include "TableGenBackends.h"
25174fdef4SOliver Stannard #include "llvm/TableGen/Record.h"
26174fdef4SOliver Stannard #include <string>
27174fdef4SOliver Stannard #include <vector>
28174fdef4SOliver Stannard 
29174fdef4SOliver Stannard using namespace llvm;
30174fdef4SOliver Stannard 
31174fdef4SOliver Stannard namespace llvm {
32174fdef4SOliver Stannard 
writeTitle(StringRef Str,raw_ostream & OS,char Kind='-')33174fdef4SOliver Stannard void writeTitle(StringRef Str, raw_ostream &OS, char Kind = '-') {
34174fdef4SOliver Stannard   OS << std::string(Str.size(), Kind) << "\n" << Str << "\n"
35174fdef4SOliver Stannard      << std::string(Str.size(), Kind) << "\n";
36174fdef4SOliver Stannard }
37174fdef4SOliver Stannard 
writeHeader(StringRef Str,raw_ostream & OS,char Kind='-')38174fdef4SOliver Stannard void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') {
39174fdef4SOliver Stannard   OS << Str << "\n" << std::string(Str.size(), Kind) << "\n";
40174fdef4SOliver Stannard }
41174fdef4SOliver Stannard 
escapeForRST(StringRef Str)42174fdef4SOliver Stannard std::string escapeForRST(StringRef Str) {
43174fdef4SOliver Stannard   std::string Result;
44174fdef4SOliver Stannard   Result.reserve(Str.size() + 4);
45174fdef4SOliver Stannard   for (char C : Str) {
46174fdef4SOliver Stannard     switch (C) {
47174fdef4SOliver Stannard     // We want special characters to be shown as their C escape codes.
48174fdef4SOliver Stannard     case '\n': Result += "\\n"; break;
49174fdef4SOliver Stannard     case '\t': Result += "\\t"; break;
50174fdef4SOliver Stannard     // Underscore at the end of a line has a special meaning in rst.
51174fdef4SOliver Stannard     case '_': Result += "\\_"; break;
52174fdef4SOliver Stannard     default: Result += C;
53174fdef4SOliver Stannard     }
54174fdef4SOliver Stannard   }
55174fdef4SOliver Stannard   return Result;
56174fdef4SOliver Stannard }
57174fdef4SOliver Stannard 
EmitInstrDocs(RecordKeeper & RK,raw_ostream & OS)58174fdef4SOliver Stannard void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) {
59174fdef4SOliver Stannard   CodeGenDAGPatterns CDP(RK);
60174fdef4SOliver Stannard   CodeGenTarget &Target = CDP.getTargetInfo();
61174fdef4SOliver Stannard   unsigned VariantCount = Target.getAsmParserVariantCount();
62174fdef4SOliver Stannard 
63174fdef4SOliver Stannard   // Page title.
64adcd0268SBenjamin Kramer   std::string Title = std::string(Target.getName());
65174fdef4SOliver Stannard   Title += " Instructions";
66174fdef4SOliver Stannard   writeTitle(Title, OS);
67174fdef4SOliver Stannard   OS << "\n";
68174fdef4SOliver Stannard 
69174fdef4SOliver Stannard   for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) {
70174fdef4SOliver Stannard     Record *Inst = II->TheDef;
71174fdef4SOliver Stannard 
72174fdef4SOliver Stannard     // Don't print the target-independent instructions.
73174fdef4SOliver Stannard     if (II->Namespace == "TargetOpcode")
74174fdef4SOliver Stannard       continue;
75174fdef4SOliver Stannard 
76174fdef4SOliver Stannard     // Heading (instruction name).
77174fdef4SOliver Stannard     writeHeader(escapeForRST(Inst->getName()), OS, '=');
78174fdef4SOliver Stannard     OS << "\n";
79174fdef4SOliver Stannard 
80174fdef4SOliver Stannard     // Assembly string(s).
81174fdef4SOliver Stannard     if (!II->AsmString.empty()) {
82174fdef4SOliver Stannard       for (unsigned VarNum = 0; VarNum < VariantCount; ++VarNum) {
83174fdef4SOliver Stannard         Record *AsmVariant = Target.getAsmParserVariant(VarNum);
84174fdef4SOliver Stannard         OS << "Assembly string";
85174fdef4SOliver Stannard         if (VariantCount != 1)
86174fdef4SOliver Stannard           OS << " (" << AsmVariant->getValueAsString("Name") << ")";
87174fdef4SOliver Stannard         std::string AsmString =
88174fdef4SOliver Stannard             CodeGenInstruction::FlattenAsmStringVariants(II->AsmString, VarNum);
89174fdef4SOliver Stannard         // We trim spaces at each end of the asm string because rst needs the
90174fdef4SOliver Stannard         // formatting backticks to be next to a non-whitespace character.
91174fdef4SOliver Stannard         OS << ": ``" << escapeForRST(StringRef(AsmString).trim(" "))
92174fdef4SOliver Stannard            << "``\n\n";
93174fdef4SOliver Stannard       }
94174fdef4SOliver Stannard     }
95174fdef4SOliver Stannard 
96174fdef4SOliver Stannard     // Boolean flags.
97174fdef4SOliver Stannard     std::vector<const char *> FlagStrings;
98174fdef4SOliver Stannard #define xstr(s) str(s)
99174fdef4SOliver Stannard #define str(s) #s
100174fdef4SOliver Stannard #define FLAG(f) if (II->f) { FlagStrings.push_back(str(f)); }
101174fdef4SOliver Stannard     FLAG(isReturn)
102ed5e06b0SHeejin Ahn     FLAG(isEHScopeReturn)
103174fdef4SOliver Stannard     FLAG(isBranch)
104174fdef4SOliver Stannard     FLAG(isIndirectBranch)
105174fdef4SOliver Stannard     FLAG(isCompare)
106174fdef4SOliver Stannard     FLAG(isMoveImm)
107174fdef4SOliver Stannard     FLAG(isBitcast)
108174fdef4SOliver Stannard     FLAG(isSelect)
109174fdef4SOliver Stannard     FLAG(isBarrier)
110174fdef4SOliver Stannard     FLAG(isCall)
111174fdef4SOliver Stannard     FLAG(isAdd)
11206e7e579SJoel Galenson     FLAG(isTrap)
113174fdef4SOliver Stannard     FLAG(canFoldAsLoad)
114174fdef4SOliver Stannard     FLAG(mayLoad)
115174fdef4SOliver Stannard     //FLAG(mayLoad_Unset) // Deliberately omitted.
116174fdef4SOliver Stannard     FLAG(mayStore)
117174fdef4SOliver Stannard     //FLAG(mayStore_Unset) // Deliberately omitted.
118174fdef4SOliver Stannard     FLAG(isPredicable)
119174fdef4SOliver Stannard     FLAG(isConvertibleToThreeAddress)
120174fdef4SOliver Stannard     FLAG(isCommutable)
121174fdef4SOliver Stannard     FLAG(isTerminator)
122174fdef4SOliver Stannard     FLAG(isReMaterializable)
123174fdef4SOliver Stannard     FLAG(hasDelaySlot)
124174fdef4SOliver Stannard     FLAG(usesCustomInserter)
125174fdef4SOliver Stannard     FLAG(hasPostISelHook)
126174fdef4SOliver Stannard     FLAG(hasCtrlDep)
127174fdef4SOliver Stannard     FLAG(isNotDuplicable)
128174fdef4SOliver Stannard     FLAG(hasSideEffects)
129174fdef4SOliver Stannard     //FLAG(hasSideEffects_Unset) // Deliberately omitted.
130174fdef4SOliver Stannard     FLAG(isAsCheapAsAMove)
131174fdef4SOliver Stannard     FLAG(hasExtraSrcRegAllocReq)
132174fdef4SOliver Stannard     FLAG(hasExtraDefRegAllocReq)
133174fdef4SOliver Stannard     FLAG(isCodeGenOnly)
134174fdef4SOliver Stannard     FLAG(isPseudo)
135174fdef4SOliver Stannard     FLAG(isRegSequence)
136174fdef4SOliver Stannard     FLAG(isExtractSubreg)
137174fdef4SOliver Stannard     FLAG(isInsertSubreg)
138174fdef4SOliver Stannard     FLAG(isConvergent)
139174fdef4SOliver Stannard     FLAG(hasNoSchedulingInfo)
1404cf35b4aSOliver Stannard     FLAG(variadicOpsAreDefs)
141a9052b4dSVedant Kumar     FLAG(isAuthenticated)
142174fdef4SOliver Stannard     if (!FlagStrings.empty()) {
143174fdef4SOliver Stannard       OS << "Flags: ";
144*094fc4d5SKazu Hirata       ListSeparator LS;
145*094fc4d5SKazu Hirata       for (auto FlagString : FlagStrings)
146*094fc4d5SKazu Hirata         OS << LS << "``" << FlagString << "``";
147174fdef4SOliver Stannard       OS << "\n\n";
148174fdef4SOliver Stannard     }
149174fdef4SOliver Stannard 
150174fdef4SOliver Stannard     // Operands.
151174fdef4SOliver Stannard     for (unsigned i = 0; i < II->Operands.size(); ++i) {
152174fdef4SOliver Stannard       bool IsDef = i < II->Operands.NumDefs;
153174fdef4SOliver Stannard       auto Op = II->Operands[i];
154174fdef4SOliver Stannard 
155174fdef4SOliver Stannard       if (Op.MINumOperands > 1) {
156174fdef4SOliver Stannard         // This operand corresponds to multiple operands on the
157174fdef4SOliver Stannard         // MachineInstruction, so print all of them, showing the types and
158174fdef4SOliver Stannard         // names of both the compound operand and the basic operands it
159174fdef4SOliver Stannard         // contains.
160174fdef4SOliver Stannard         for (unsigned SubOpIdx = 0; SubOpIdx < Op.MINumOperands; ++SubOpIdx) {
161174fdef4SOliver Stannard           Record *SubRec =
162174fdef4SOliver Stannard               cast<DefInit>(Op.MIOperandInfo->getArg(SubOpIdx))->getDef();
163174fdef4SOliver Stannard           StringRef SubOpName = Op.MIOperandInfo->getArgNameStr(SubOpIdx);
164174fdef4SOliver Stannard           StringRef SubOpTypeName = SubRec->getName();
165174fdef4SOliver Stannard 
166174fdef4SOliver Stannard           OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName()
167174fdef4SOliver Stannard              << "/" << SubOpTypeName << ":$" << Op.Name << ".";
168174fdef4SOliver Stannard           // Not all sub-operands are named, make up a name for these.
169174fdef4SOliver Stannard           if (SubOpName.empty())
170174fdef4SOliver Stannard             OS << "anon" << SubOpIdx;
171174fdef4SOliver Stannard           else
172174fdef4SOliver Stannard             OS << SubOpName;
173174fdef4SOliver Stannard           OS << "``\n\n";
174174fdef4SOliver Stannard         }
175174fdef4SOliver Stannard       } else {
176174fdef4SOliver Stannard         // The operand corresponds to only one MachineInstruction operand.
177174fdef4SOliver Stannard         OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName()
178174fdef4SOliver Stannard            << ":$" << Op.Name << "``\n\n";
179174fdef4SOliver Stannard       }
180174fdef4SOliver Stannard     }
181174fdef4SOliver Stannard 
182174fdef4SOliver Stannard     // Constraints.
183174fdef4SOliver Stannard     StringRef Constraints = Inst->getValueAsString("Constraints");
184174fdef4SOliver Stannard     if (!Constraints.empty()) {
185174fdef4SOliver Stannard       OS << "Constraints: ``" << Constraints << "``\n\n";
186174fdef4SOliver Stannard     }
187174fdef4SOliver Stannard 
188174fdef4SOliver Stannard     // Implicit definitions.
189174fdef4SOliver Stannard     if (!II->ImplicitDefs.empty()) {
190174fdef4SOliver Stannard       OS << "Implicit defs: ";
191*094fc4d5SKazu Hirata       ListSeparator LS;
192*094fc4d5SKazu Hirata       for (Record *Def : II->ImplicitDefs)
193*094fc4d5SKazu Hirata         OS << LS << "``" << Def->getName() << "``";
194174fdef4SOliver Stannard       OS << "\n\n";
195174fdef4SOliver Stannard     }
196174fdef4SOliver Stannard 
197174fdef4SOliver Stannard     // Implicit uses.
198174fdef4SOliver Stannard     if (!II->ImplicitUses.empty()) {
199174fdef4SOliver Stannard       OS << "Implicit uses: ";
200*094fc4d5SKazu Hirata       ListSeparator LS;
201*094fc4d5SKazu Hirata       for (Record *Use : II->ImplicitUses)
202*094fc4d5SKazu Hirata         OS << LS << "``" << Use->getName() << "``";
203174fdef4SOliver Stannard       OS << "\n\n";
204174fdef4SOliver Stannard     }
205174fdef4SOliver Stannard 
206174fdef4SOliver Stannard     // Predicates.
207174fdef4SOliver Stannard     std::vector<Record *> Predicates =
208174fdef4SOliver Stannard         II->TheDef->getValueAsListOfDefs("Predicates");
209174fdef4SOliver Stannard     if (!Predicates.empty()) {
210174fdef4SOliver Stannard       OS << "Predicates: ";
211*094fc4d5SKazu Hirata       ListSeparator LS;
212*094fc4d5SKazu Hirata       for (Record *P : Predicates)
213*094fc4d5SKazu Hirata         OS << LS << "``" << P->getName() << "``";
214174fdef4SOliver Stannard       OS << "\n\n";
215174fdef4SOliver Stannard     }
216174fdef4SOliver Stannard   }
217174fdef4SOliver Stannard }
218174fdef4SOliver Stannard 
2196bd3a9eaSBjorn Pettersson } // end namespace llvm
220