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 "CodeGenDAGPatterns.h"
22 #include "CodeGenInstruction.h"
23 #include "CodeGenTarget.h"
24 #include "TableGenBackends.h"
25 #include "llvm/TableGen/Record.h"
33 void 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";
38 void writeHeader(StringRef Str
, raw_ostream
&OS
, char Kind
= '-') {
39 OS
<< Str
<< "\n" << std::string(Str
.size(), Kind
) << "\n";
42 std::string
escapeForRST(StringRef Str
) {
44 Result
.reserve(Str
.size() + 4);
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;
58 void EmitInstrDocs(RecordKeeper
&RK
, raw_ostream
&OS
) {
59 CodeGenDAGPatterns
CDP(RK
);
60 CodeGenTarget
&Target
= CDP
.getTargetInfo();
61 unsigned VariantCount
= Target
.getAsmParserVariantCount();
64 std::string Title
= std::string(Target
.getName());
65 Title
+= " Instructions";
66 writeTitle(Title
, OS
);
69 for (const CodeGenInstruction
*II
: Target
.getInstructionsByEnumValue()) {
70 Record
*Inst
= II
->TheDef
;
72 // Don't print the target-independent instructions.
73 if (II
->Namespace
== "TargetOpcode")
76 // Heading (instruction name).
77 writeHeader(escapeForRST(Inst
->getName()), OS
, '=');
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(" "))
97 std::vector
<const char *> FlagStrings
;
98 #define xstr(s) str(s)
100 #define FLAG(f) if (II->f) { FlagStrings.push_back(str(f)); }
102 FLAG(isEHScopeReturn
)
104 FLAG(isIndirectBranch
)
115 //FLAG(mayLoad_Unset) // Deliberately omitted.
117 //FLAG(mayStore_Unset) // Deliberately omitted.
119 FLAG(isConvertibleToThreeAddress
)
122 FLAG(isReMaterializable
)
124 FLAG(usesCustomInserter
)
125 FLAG(hasPostISelHook
)
127 FLAG(isNotDuplicable
)
129 //FLAG(hasSideEffects_Unset) // Deliberately omitted.
130 FLAG(isAsCheapAsAMove
)
131 FLAG(hasExtraSrcRegAllocReq
)
132 FLAG(hasExtraDefRegAllocReq
)
136 FLAG(isExtractSubreg
)
139 FLAG(hasNoSchedulingInfo
)
140 FLAG(variadicOpsAreDefs
)
141 FLAG(isAuthenticated
)
142 if (!FlagStrings
.empty()) {
145 for (auto FlagString
: FlagStrings
)
146 OS
<< LS
<< "``" << FlagString
<< "``";
151 for (unsigned i
= 0; i
< II
->Operands
.size(); ++i
) {
152 bool IsDef
= i
< II
->Operands
.NumDefs
;
153 auto Op
= II
->Operands
[i
];
155 if (Op
.MINumOperands
> 1) {
156 // This operand corresponds to multiple operands on the
157 // MachineInstruction, so print all of them, showing the types and
158 // names of both the compound operand and the basic operands it
160 for (unsigned SubOpIdx
= 0; SubOpIdx
< Op
.MINumOperands
; ++SubOpIdx
) {
162 cast
<DefInit
>(Op
.MIOperandInfo
->getArg(SubOpIdx
))->getDef();
163 StringRef SubOpName
= Op
.MIOperandInfo
->getArgNameStr(SubOpIdx
);
164 StringRef SubOpTypeName
= SubRec
->getName();
166 OS
<< "* " << (IsDef
? "DEF" : "USE") << " ``" << Op
.Rec
->getName()
167 << "/" << SubOpTypeName
<< ":$" << Op
.Name
<< ".";
168 // Not all sub-operands are named, make up a name for these.
169 if (SubOpName
.empty())
170 OS
<< "anon" << SubOpIdx
;
176 // The operand corresponds to only one MachineInstruction operand.
177 OS
<< "* " << (IsDef
? "DEF" : "USE") << " ``" << Op
.Rec
->getName()
178 << ":$" << Op
.Name
<< "``\n\n";
183 StringRef Constraints
= Inst
->getValueAsString("Constraints");
184 if (!Constraints
.empty()) {
185 OS
<< "Constraints: ``" << Constraints
<< "``\n\n";
188 // Implicit definitions.
189 if (!II
->ImplicitDefs
.empty()) {
190 OS
<< "Implicit defs: ";
192 for (Record
*Def
: II
->ImplicitDefs
)
193 OS
<< LS
<< "``" << Def
->getName() << "``";
198 if (!II
->ImplicitUses
.empty()) {
199 OS
<< "Implicit uses: ";
201 for (Record
*Use
: II
->ImplicitUses
)
202 OS
<< LS
<< "``" << Use
->getName() << "``";
207 std::vector
<Record
*> Predicates
=
208 II
->TheDef
->getValueAsListOfDefs("Predicates");
209 if (!Predicates
.empty()) {
210 OS
<< "Predicates: ";
212 for (Record
*P
: Predicates
)
213 OS
<< LS
<< "``" << P
->getName() << "``";
219 } // end namespace llvm