llvm.org GIT mirror llvm / bf70e59
[Docs] Add tablegen backend for target opcode documentation This is a tablegen backend to generate documentation for the opcodes that exist for each target. For each opcode, it lists the assembly string, the names and types of all operands, and the flags and predicates that apply to the opcode. Differential revision: https://reviews.llvm.org/D31025 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@318155 91177308-0d34-0410-b5e6-96231b3b80d8 Oliver Stannard 1 year, 11 months ago
4 changed file(s) with 240 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
2525 GlobalISelEmitter.cpp
2626 InfoByHwMode.cpp
2727 InstrInfoEmitter.cpp
28 InstrDocsEmitter.cpp
2829 IntrinsicEmitter.cpp
2930 OptParserEmitter.cpp
3031 PseudoLoweringEmitter.cpp
0 //===- InstrDocsEmitter.cpp - Opcode Documentation Generator --------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // InstrDocsEmitter generates restructured text documentation for the opcodes
10 // that can be used by MachineInstr. For each opcode, the documentation lists:
11 // * Opcode name
12 // * Assembly string
13 // * Flags (e.g. mayLoad, isBranch, ...)
14 // * Operands, including type and name
15 // * Operand constraints
16 // * Implicit register uses & defs
17 // * Predicates
18 //
19 //===----------------------------------------------------------------------===//
20
21 #include "CodeGenDAGPatterns.h"
22 #include "CodeGenInstruction.h"
23 #include "CodeGenTarget.h"
24 #include "TableGenBackends.h"
25 #include "llvm/TableGen/Record.h"
26 #include
27 #include
28
29 using namespace llvm;
30
31 namespace llvm {
32
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";
36 }
37
38 void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') {
39 OS << Str << "\n" << std::string(Str.size(), Kind) << "\n";
40 }
41
42 std::string escapeForRST(StringRef Str) {
43 std::string Result;
44 Result.reserve(Str.size() + 4);
45 for (char C : Str) {
46 switch (C) {
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;
52 default: Result += C;
53 }
54 }
55 return Result;
56 }
57
58 void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) {
59 CodeGenDAGPatterns CDP(RK);
60 CodeGenTarget &Target = CDP.getTargetInfo();
61 unsigned VariantCount = Target.getAsmParserVariantCount();
62
63 // Page title.
64 std::string Title = Target.getName();
65 Title += " Instructions";
66 writeTitle(Title, OS);
67 OS << "\n";
68
69 for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) {
70 Record *Inst = II->TheDef;
71
72 // Don't print the target-independent instructions.
73 if (II->Namespace == "TargetOpcode")
74 continue;
75
76 // Heading (instruction name).
77 writeHeader(escapeForRST(Inst->getName()), OS, '=');
78 OS << "\n";
79
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(" "))
92 << "``\n\n";
93 }
94 }
95
96 // Boolean flags.
97 std::vector FlagStrings;
98 #define xstr(s) str(s)
99 #define str(s) #s
100 #define FLAG(f) if (II->f) { FlagStrings.push_back(str(f)); }
101 FLAG(isReturn)
102 FLAG(isBranch)
103 FLAG(isIndirectBranch)
104 FLAG(isCompare)
105 FLAG(isMoveImm)
106 FLAG(isBitcast)
107 FLAG(isSelect)
108 FLAG(isBarrier)
109 FLAG(isCall)
110 FLAG(isAdd)
111 FLAG(canFoldAsLoad)
112 FLAG(mayLoad)
113 //FLAG(mayLoad_Unset) // Deliberately omitted.
114 FLAG(mayStore)
115 //FLAG(mayStore_Unset) // Deliberately omitted.
116 FLAG(isPredicable)
117 FLAG(isConvertibleToThreeAddress)
118 FLAG(isCommutable)
119 FLAG(isTerminator)
120 FLAG(isReMaterializable)
121 FLAG(hasDelaySlot)
122 FLAG(usesCustomInserter)
123 FLAG(hasPostISelHook)
124 FLAG(hasCtrlDep)
125 FLAG(isNotDuplicable)
126 FLAG(hasSideEffects)
127 //FLAG(hasSideEffects_Unset) // Deliberately omitted.
128 FLAG(isAsCheapAsAMove)
129 FLAG(hasExtraSrcRegAllocReq)
130 FLAG(hasExtraDefRegAllocReq)
131 FLAG(isCodeGenOnly)
132 FLAG(isPseudo)
133 FLAG(isRegSequence)
134 FLAG(isExtractSubreg)
135 FLAG(isInsertSubreg)
136 FLAG(isConvergent)
137 FLAG(hasNoSchedulingInfo)
138 if (!FlagStrings.empty()) {
139 OS << "Flags: ";
140 bool IsFirst = true;
141 for (auto FlagString : FlagStrings) {
142 if (!IsFirst)
143 OS << ", ";
144 OS << "``" << FlagString << "``";
145 IsFirst = false;
146 }
147 OS << "\n\n";
148 }
149
150 // Operands.
151 for (unsigned i = 0; i < II->Operands.size(); ++i) {
152 bool IsDef = i < II->Operands.NumDefs;
153 auto Op = II->Operands[i];
154
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
159 // contains.
160 for (unsigned SubOpIdx = 0; SubOpIdx < Op.MINumOperands; ++SubOpIdx) {
161 Record *SubRec =
162 cast(Op.MIOperandInfo->getArg(SubOpIdx))->getDef();
163 StringRef SubOpName = Op.MIOperandInfo->getArgNameStr(SubOpIdx);
164 StringRef SubOpTypeName = SubRec->getName();
165
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;
171 else
172 OS << SubOpName;
173 OS << "``\n\n";
174 }
175 } else {
176 // The operand corresponds to only one MachineInstruction operand.
177 OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName()
178 << ":$" << Op.Name << "``\n\n";
179 }
180 }
181
182 // Constraints.
183 StringRef Constraints = Inst->getValueAsString("Constraints");
184 if (!Constraints.empty()) {
185 OS << "Constraints: ``" << Constraints << "``\n\n";
186 }
187
188 // Implicit definitions.
189 if (!II->ImplicitDefs.empty()) {
190 OS << "Implicit defs: ";
191 bool IsFirst = true;
192 for (Record *Def : II->ImplicitDefs) {
193 if (!IsFirst)
194 OS << ", ";
195 OS << "``" << Def->getName() << "``";
196 IsFirst = false;
197 }
198 OS << "\n\n";
199 }
200
201 // Implicit uses.
202 if (!II->ImplicitUses.empty()) {
203 OS << "Implicit uses: ";
204 bool IsFirst = true;
205 for (Record *Use : II->ImplicitUses) {
206 if (!IsFirst)
207 OS << ", ";
208 OS << "``" << Use->getName() << "``";
209 IsFirst = false;
210 }
211 OS << "\n\n";
212 }
213
214 // Predicates.
215 std::vector Predicates =
216 II->TheDef->getValueAsListOfDefs("Predicates");
217 if (!Predicates.empty()) {
218 OS << "Predicates: ";
219 bool IsFirst = true;
220 for (Record *P : Predicates) {
221 if (!IsFirst)
222 OS << ", ";
223 OS << "``" << P->getName() << "``";
224 IsFirst = false;
225 }
226 OS << "\n\n";
227 }
228 }
229 }
230
231 } // end llvm namespace
2727 GenEmitter,
2828 GenRegisterInfo,
2929 GenInstrInfo,
30 GenInstrDocs,
3031 GenAsmWriter,
3132 GenAsmMatcher,
3233 GenDisassembler,
6162 "Generate registers and register classes info"),
6263 clEnumValN(GenInstrInfo, "gen-instr-info",
6364 "Generate instruction descriptions"),
65 clEnumValN(GenInstrDocs, "gen-instr-docs",
66 "Generate instruction documentation"),
6467 clEnumValN(GenCallingConv, "gen-callingconv",
6568 "Generate calling convention descriptions"),
6669 clEnumValN(GenAsmWriter, "gen-asm-writer",
123126 case GenInstrInfo:
124127 EmitInstrInfo(Records, OS);
125128 break;
129 case GenInstrDocs:
130 EmitInstrDocs(Records, OS);
131 break;
126132 case GenCallingConv:
127133 EmitCallingConv(Records, OS);
128134 break;
7171 void EmitDisassembler(RecordKeeper &RK, raw_ostream &OS);
7272 void EmitFastISel(RecordKeeper &RK, raw_ostream &OS);
7373 void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS);
74 void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS);
7475 void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS);
7576 void EmitRegisterInfo(RecordKeeper &RK, raw_ostream &OS);
7677 void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS);