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