• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- 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 
30 using namespace llvm;
31 
32 namespace llvm {
33 
writeTitle(StringRef Str,raw_ostream & OS,char Kind='-')34 void 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 
writeHeader(StringRef Str,raw_ostream & OS,char Kind='-')39 void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') {
40   OS << Str << "\n" << std::string(Str.size(), Kind) << "\n";
41 }
42 
escapeForRST(StringRef Str)43 std::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 
EmitInstrDocs(RecordKeeper & RK,raw_ostream & OS)59 void 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(isTrap)
113     FLAG(canFoldAsLoad)
114     FLAG(mayLoad)
115     //FLAG(mayLoad_Unset) // Deliberately omitted.
116     FLAG(mayStore)
117     //FLAG(mayStore_Unset) // Deliberately omitted.
118     FLAG(isPredicable)
119     FLAG(isConvertibleToThreeAddress)
120     FLAG(isCommutable)
121     FLAG(isTerminator)
122     FLAG(isReMaterializable)
123     FLAG(hasDelaySlot)
124     FLAG(usesCustomInserter)
125     FLAG(hasPostISelHook)
126     FLAG(hasCtrlDep)
127     FLAG(isNotDuplicable)
128     FLAG(hasSideEffects)
129     //FLAG(hasSideEffects_Unset) // Deliberately omitted.
130     FLAG(isAsCheapAsAMove)
131     FLAG(hasExtraSrcRegAllocReq)
132     FLAG(hasExtraDefRegAllocReq)
133     FLAG(isCodeGenOnly)
134     FLAG(isPseudo)
135     FLAG(isRegSequence)
136     FLAG(isExtractSubreg)
137     FLAG(isInsertSubreg)
138     FLAG(isConvergent)
139     FLAG(hasNoSchedulingInfo)
140     if (!FlagStrings.empty()) {
141       OS << "Flags: ";
142       bool IsFirst = true;
143       for (auto FlagString : FlagStrings) {
144         if (!IsFirst)
145           OS << ", ";
146         OS << "``" << FlagString << "``";
147         IsFirst = false;
148       }
149       OS << "\n\n";
150     }
151 
152     // Operands.
153     for (unsigned i = 0; i < II->Operands.size(); ++i) {
154       bool IsDef = i < II->Operands.NumDefs;
155       auto Op = II->Operands[i];
156 
157       if (Op.MINumOperands > 1) {
158         // This operand corresponds to multiple operands on the
159         // MachineInstruction, so print all of them, showing the types and
160         // names of both the compound operand and the basic operands it
161         // contains.
162         for (unsigned SubOpIdx = 0; SubOpIdx < Op.MINumOperands; ++SubOpIdx) {
163           Record *SubRec =
164               cast<DefInit>(Op.MIOperandInfo->getArg(SubOpIdx))->getDef();
165           StringRef SubOpName = Op.MIOperandInfo->getArgNameStr(SubOpIdx);
166           StringRef SubOpTypeName = SubRec->getName();
167 
168           OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName()
169              << "/" << SubOpTypeName << ":$" << Op.Name << ".";
170           // Not all sub-operands are named, make up a name for these.
171           if (SubOpName.empty())
172             OS << "anon" << SubOpIdx;
173           else
174             OS << SubOpName;
175           OS << "``\n\n";
176         }
177       } else {
178         // The operand corresponds to only one MachineInstruction operand.
179         OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName()
180            << ":$" << Op.Name << "``\n\n";
181       }
182     }
183 
184     // Constraints.
185     StringRef Constraints = Inst->getValueAsString("Constraints");
186     if (!Constraints.empty()) {
187       OS << "Constraints: ``" << Constraints << "``\n\n";
188     }
189 
190     // Implicit definitions.
191     if (!II->ImplicitDefs.empty()) {
192       OS << "Implicit defs: ";
193       bool IsFirst = true;
194       for (Record *Def : II->ImplicitDefs) {
195         if (!IsFirst)
196           OS << ", ";
197         OS << "``" << Def->getName() << "``";
198         IsFirst = false;
199       }
200       OS << "\n\n";
201     }
202 
203     // Implicit uses.
204     if (!II->ImplicitUses.empty()) {
205       OS << "Implicit uses: ";
206       bool IsFirst = true;
207       for (Record *Use : II->ImplicitUses) {
208         if (!IsFirst)
209           OS << ", ";
210         OS << "``" << Use->getName() << "``";
211         IsFirst = false;
212       }
213       OS << "\n\n";
214     }
215 
216     // Predicates.
217     std::vector<Record *> Predicates =
218         II->TheDef->getValueAsListOfDefs("Predicates");
219     if (!Predicates.empty()) {
220       OS << "Predicates: ";
221       bool IsFirst = true;
222       for (Record *P : Predicates) {
223         if (!IsFirst)
224           OS << ", ";
225         OS << "``" << P->getName() << "``";
226         IsFirst = false;
227       }
228       OS << "\n\n";
229     }
230   }
231 }
232 
233 } // end llvm namespace
234