1 //===- InstrDocsEmitter.cpp - Opcode Documentation Generator --------------===//
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
7 //===----------------------------------------------------------------------===//
9 // InstrDocsEmitter generates restructured text documentation for the opcodes
10 // that can be used by MachineInstr. For each opcode, the documentation lists:
13 // * Flags (e.g. mayLoad, isBranch, ...)
14 // * Operands, including type and name
15 // * Operand constraints
16 // * Implicit register uses & defs
19 //===----------------------------------------------------------------------===//
21 #include "Common/CodeGenDAGPatterns.h"
22 #include "Common/CodeGenInstruction.h"
23 #include "Common/CodeGenTarget.h"
24 #include "llvm/TableGen/Record.h"
25 #include "llvm/TableGen/TableGenBackend.h"
31 static void writeTitle(StringRef Str
, raw_ostream
&OS
, char Kind
= '-') {
32 OS
<< std::string(Str
.size(), Kind
) << "\n"
34 << std::string(Str
.size(), Kind
) << "\n";
37 static void writeHeader(StringRef Str
, raw_ostream
&OS
, char Kind
= '-') {
38 OS
<< Str
<< "\n" << std::string(Str
.size(), Kind
) << "\n";
41 static std::string
escapeForRST(StringRef Str
) {
43 Result
.reserve(Str
.size() + 4);
46 // We want special characters to be shown as their C escape codes.
53 // Underscore at the end of a line has a special meaning in rst.
64 static void EmitInstrDocs(const RecordKeeper
&RK
, raw_ostream
&OS
) {
65 const CodeGenDAGPatterns
CDP(RK
);
66 const CodeGenTarget
&Target
= CDP
.getTargetInfo();
67 unsigned VariantCount
= Target
.getAsmParserVariantCount();
70 std::string Title
= std::string(Target
.getName());
71 Title
+= " Instructions";
72 writeTitle(Title
, OS
);
75 for (const CodeGenInstruction
*II
: Target
.getInstructionsByEnumValue()) {
76 const Record
*Inst
= II
->TheDef
;
78 // Don't print the target-independent instructions.
79 if (II
->Namespace
== "TargetOpcode")
82 // Heading (instruction name).
83 writeHeader(escapeForRST(Inst
->getName()), OS
, '=');
86 // Assembly string(s).
87 if (!II
->AsmString
.empty()) {
88 for (unsigned VarNum
= 0; VarNum
< VariantCount
; ++VarNum
) {
89 const Record
*AsmVariant
= Target
.getAsmParserVariant(VarNum
);
90 OS
<< "Assembly string";
91 if (VariantCount
!= 1)
92 OS
<< " (" << AsmVariant
->getValueAsString("Name") << ")";
93 std::string AsmString
=
94 CodeGenInstruction::FlattenAsmStringVariants(II
->AsmString
, VarNum
);
95 // We trim spaces at each end of the asm string because rst needs the
96 // formatting backticks to be next to a non-whitespace character.
97 OS
<< ": ``" << escapeForRST(StringRef(AsmString
).trim(" "))
103 std::vector
<const char *> FlagStrings
;
104 #define xstr(s) str(s)
108 FlagStrings.push_back(str(f)); \
111 FLAG(isEHScopeReturn
)
113 FLAG(isIndirectBranch
)
124 // FLAG(mayLoad_Unset) // Deliberately omitted.
126 // FLAG(mayStore_Unset) // Deliberately omitted.
128 FLAG(isConvertibleToThreeAddress
)
131 FLAG(isReMaterializable
)
133 FLAG(usesCustomInserter
)
134 FLAG(hasPostISelHook
)
136 FLAG(isNotDuplicable
)
138 // FLAG(hasSideEffects_Unset) // Deliberately omitted.
139 FLAG(isAsCheapAsAMove
)
140 FLAG(hasExtraSrcRegAllocReq
)
141 FLAG(hasExtraDefRegAllocReq
)
145 FLAG(isExtractSubreg
)
148 FLAG(hasNoSchedulingInfo
)
149 FLAG(variadicOpsAreDefs
)
150 FLAG(isAuthenticated
)
151 if (!FlagStrings
.empty()) {
154 for (auto FlagString
: FlagStrings
)
155 OS
<< LS
<< "``" << FlagString
<< "``";
160 for (unsigned i
= 0; i
< II
->Operands
.size(); ++i
) {
161 bool IsDef
= i
< II
->Operands
.NumDefs
;
162 auto Op
= II
->Operands
[i
];
164 if (Op
.MINumOperands
> 1) {
165 // This operand corresponds to multiple operands on the
166 // MachineInstruction, so print all of them, showing the types and
167 // names of both the compound operand and the basic operands it
169 for (unsigned SubOpIdx
= 0; SubOpIdx
< Op
.MINumOperands
; ++SubOpIdx
) {
170 const Record
*SubRec
=
171 cast
<DefInit
>(Op
.MIOperandInfo
->getArg(SubOpIdx
))->getDef();
172 StringRef SubOpName
= Op
.MIOperandInfo
->getArgNameStr(SubOpIdx
);
173 StringRef SubOpTypeName
= SubRec
->getName();
175 OS
<< "* " << (IsDef
? "DEF" : "USE") << " ``" << Op
.Rec
->getName()
176 << "/" << SubOpTypeName
<< ":$" << Op
.Name
<< ".";
177 // Not all sub-operands are named, make up a name for these.
178 if (SubOpName
.empty())
179 OS
<< "anon" << SubOpIdx
;
185 // The operand corresponds to only one MachineInstruction operand.
186 OS
<< "* " << (IsDef
? "DEF" : "USE") << " ``" << Op
.Rec
->getName()
187 << ":$" << Op
.Name
<< "``\n\n";
192 StringRef Constraints
= Inst
->getValueAsString("Constraints");
193 if (!Constraints
.empty()) {
194 OS
<< "Constraints: ``" << Constraints
<< "``\n\n";
197 // Implicit definitions.
198 if (!II
->ImplicitDefs
.empty()) {
199 OS
<< "Implicit defs: ";
201 for (const Record
*Def
: II
->ImplicitDefs
)
202 OS
<< LS
<< "``" << Def
->getName() << "``";
207 if (!II
->ImplicitUses
.empty()) {
208 OS
<< "Implicit uses: ";
210 for (const Record
*Use
: II
->ImplicitUses
)
211 OS
<< LS
<< "``" << Use
->getName() << "``";
216 std::vector
<const Record
*> Predicates
=
217 II
->TheDef
->getValueAsListOfDefs("Predicates");
218 if (!Predicates
.empty()) {
219 OS
<< "Predicates: ";
221 for (const Record
*P
: Predicates
)
222 OS
<< LS
<< "``" << P
->getName() << "``";
228 static TableGen::Emitter::Opt
X("gen-instr-docs", EmitInstrDocs
,
229 "Generate instruction documentation");