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