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 "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.
47 case '\n': Result
+= "\\n"; break;
48 case '\t': Result
+= "\\t"; break;
49 // Underscore at the end of a line has a special meaning in rst.
50 case '_': Result
+= "\\_"; break;
57 static void EmitInstrDocs(RecordKeeper
&RK
, raw_ostream
&OS
) {
58 CodeGenDAGPatterns
CDP(RK
);
59 CodeGenTarget
&Target
= CDP
.getTargetInfo();
60 unsigned VariantCount
= Target
.getAsmParserVariantCount();
63 std::string Title
= std::string(Target
.getName());
64 Title
+= " Instructions";
65 writeTitle(Title
, OS
);
68 for (const CodeGenInstruction
*II
: Target
.getInstructionsByEnumValue()) {
69 Record
*Inst
= II
->TheDef
;
71 // Don't print the target-independent instructions.
72 if (II
->Namespace
== "TargetOpcode")
75 // Heading (instruction name).
76 writeHeader(escapeForRST(Inst
->getName()), OS
, '=');
79 // Assembly string(s).
80 if (!II
->AsmString
.empty()) {
81 for (unsigned VarNum
= 0; VarNum
< VariantCount
; ++VarNum
) {
82 Record
*AsmVariant
= Target
.getAsmParserVariant(VarNum
);
83 OS
<< "Assembly string";
84 if (VariantCount
!= 1)
85 OS
<< " (" << AsmVariant
->getValueAsString("Name") << ")";
86 std::string AsmString
=
87 CodeGenInstruction::FlattenAsmStringVariants(II
->AsmString
, VarNum
);
88 // We trim spaces at each end of the asm string because rst needs the
89 // formatting backticks to be next to a non-whitespace character.
90 OS
<< ": ``" << escapeForRST(StringRef(AsmString
).trim(" "))
96 std::vector
<const char *> FlagStrings
;
97 #define xstr(s) str(s)
99 #define FLAG(f) if (II->f) { FlagStrings.push_back(str(f)); }
101 FLAG(isEHScopeReturn
)
103 FLAG(isIndirectBranch
)
114 //FLAG(mayLoad_Unset) // Deliberately omitted.
116 //FLAG(mayStore_Unset) // Deliberately omitted.
118 FLAG(isConvertibleToThreeAddress
)
121 FLAG(isReMaterializable
)
123 FLAG(usesCustomInserter
)
124 FLAG(hasPostISelHook
)
126 FLAG(isNotDuplicable
)
128 //FLAG(hasSideEffects_Unset) // Deliberately omitted.
129 FLAG(isAsCheapAsAMove
)
130 FLAG(hasExtraSrcRegAllocReq
)
131 FLAG(hasExtraDefRegAllocReq
)
135 FLAG(isExtractSubreg
)
138 FLAG(hasNoSchedulingInfo
)
139 FLAG(variadicOpsAreDefs
)
140 FLAG(isAuthenticated
)
141 if (!FlagStrings
.empty()) {
144 for (auto FlagString
: FlagStrings
)
145 OS
<< LS
<< "``" << FlagString
<< "``";
150 for (unsigned i
= 0; i
< II
->Operands
.size(); ++i
) {
151 bool IsDef
= i
< II
->Operands
.NumDefs
;
152 auto Op
= II
->Operands
[i
];
154 if (Op
.MINumOperands
> 1) {
155 // This operand corresponds to multiple operands on the
156 // MachineInstruction, so print all of them, showing the types and
157 // names of both the compound operand and the basic operands it
159 for (unsigned SubOpIdx
= 0; SubOpIdx
< Op
.MINumOperands
; ++SubOpIdx
) {
161 cast
<DefInit
>(Op
.MIOperandInfo
->getArg(SubOpIdx
))->getDef();
162 StringRef SubOpName
= Op
.MIOperandInfo
->getArgNameStr(SubOpIdx
);
163 StringRef SubOpTypeName
= SubRec
->getName();
165 OS
<< "* " << (IsDef
? "DEF" : "USE") << " ``" << Op
.Rec
->getName()
166 << "/" << SubOpTypeName
<< ":$" << Op
.Name
<< ".";
167 // Not all sub-operands are named, make up a name for these.
168 if (SubOpName
.empty())
169 OS
<< "anon" << SubOpIdx
;
175 // The operand corresponds to only one MachineInstruction operand.
176 OS
<< "* " << (IsDef
? "DEF" : "USE") << " ``" << Op
.Rec
->getName()
177 << ":$" << Op
.Name
<< "``\n\n";
182 StringRef Constraints
= Inst
->getValueAsString("Constraints");
183 if (!Constraints
.empty()) {
184 OS
<< "Constraints: ``" << Constraints
<< "``\n\n";
187 // Implicit definitions.
188 if (!II
->ImplicitDefs
.empty()) {
189 OS
<< "Implicit defs: ";
191 for (Record
*Def
: II
->ImplicitDefs
)
192 OS
<< LS
<< "``" << Def
->getName() << "``";
197 if (!II
->ImplicitUses
.empty()) {
198 OS
<< "Implicit uses: ";
200 for (Record
*Use
: II
->ImplicitUses
)
201 OS
<< LS
<< "``" << Use
->getName() << "``";
206 std::vector
<Record
*> Predicates
=
207 II
->TheDef
->getValueAsListOfDefs("Predicates");
208 if (!Predicates
.empty()) {
209 OS
<< "Predicates: ";
211 for (Record
*P
: Predicates
)
212 OS
<< LS
<< "``" << P
->getName() << "``";
218 static TableGen::Emitter::Opt
X("gen-instr-docs", EmitInstrDocs
,
219 "Generate instruction documentation");