109467b48Spatrick //===- InstrDocsEmitter.cpp - Opcode Documentation Generator --------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // InstrDocsEmitter generates restructured text documentation for the opcodes
1009467b48Spatrick // that can be used by MachineInstr. For each opcode, the documentation lists:
1109467b48Spatrick // * Opcode name
1209467b48Spatrick // * Assembly string
1309467b48Spatrick // * Flags (e.g. mayLoad, isBranch, ...)
1409467b48Spatrick // * Operands, including type and name
1509467b48Spatrick // * Operand constraints
1609467b48Spatrick // * Implicit register uses & defs
1709467b48Spatrick // * Predicates
1809467b48Spatrick //
1909467b48Spatrick //===----------------------------------------------------------------------===//
2009467b48Spatrick 
2109467b48Spatrick #include "CodeGenDAGPatterns.h"
2209467b48Spatrick #include "CodeGenInstruction.h"
2309467b48Spatrick #include "CodeGenTarget.h"
2409467b48Spatrick #include "TableGenBackends.h"
2509467b48Spatrick #include "llvm/TableGen/Record.h"
2609467b48Spatrick #include <string>
2709467b48Spatrick #include <vector>
2809467b48Spatrick 
2909467b48Spatrick using namespace llvm;
3009467b48Spatrick 
3109467b48Spatrick namespace llvm {
3209467b48Spatrick 
writeTitle(StringRef Str,raw_ostream & OS,char Kind='-')3309467b48Spatrick void writeTitle(StringRef Str, raw_ostream &OS, char Kind = '-') {
3409467b48Spatrick   OS << std::string(Str.size(), Kind) << "\n" << Str << "\n"
3509467b48Spatrick      << std::string(Str.size(), Kind) << "\n";
3609467b48Spatrick }
3709467b48Spatrick 
writeHeader(StringRef Str,raw_ostream & OS,char Kind='-')3809467b48Spatrick void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') {
3909467b48Spatrick   OS << Str << "\n" << std::string(Str.size(), Kind) << "\n";
4009467b48Spatrick }
4109467b48Spatrick 
escapeForRST(StringRef Str)4209467b48Spatrick std::string escapeForRST(StringRef Str) {
4309467b48Spatrick   std::string Result;
4409467b48Spatrick   Result.reserve(Str.size() + 4);
4509467b48Spatrick   for (char C : Str) {
4609467b48Spatrick     switch (C) {
4709467b48Spatrick     // We want special characters to be shown as their C escape codes.
4809467b48Spatrick     case '\n': Result += "\\n"; break;
4909467b48Spatrick     case '\t': Result += "\\t"; break;
5009467b48Spatrick     // Underscore at the end of a line has a special meaning in rst.
5109467b48Spatrick     case '_': Result += "\\_"; break;
5209467b48Spatrick     default: Result += C;
5309467b48Spatrick     }
5409467b48Spatrick   }
5509467b48Spatrick   return Result;
5609467b48Spatrick }
5709467b48Spatrick 
EmitInstrDocs(RecordKeeper & RK,raw_ostream & OS)5809467b48Spatrick void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) {
5909467b48Spatrick   CodeGenDAGPatterns CDP(RK);
6009467b48Spatrick   CodeGenTarget &Target = CDP.getTargetInfo();
6109467b48Spatrick   unsigned VariantCount = Target.getAsmParserVariantCount();
6209467b48Spatrick 
6309467b48Spatrick   // Page title.
64097a140dSpatrick   std::string Title = std::string(Target.getName());
6509467b48Spatrick   Title += " Instructions";
6609467b48Spatrick   writeTitle(Title, OS);
6709467b48Spatrick   OS << "\n";
6809467b48Spatrick 
6909467b48Spatrick   for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) {
7009467b48Spatrick     Record *Inst = II->TheDef;
7109467b48Spatrick 
7209467b48Spatrick     // Don't print the target-independent instructions.
7309467b48Spatrick     if (II->Namespace == "TargetOpcode")
7409467b48Spatrick       continue;
7509467b48Spatrick 
7609467b48Spatrick     // Heading (instruction name).
7709467b48Spatrick     writeHeader(escapeForRST(Inst->getName()), OS, '=');
7809467b48Spatrick     OS << "\n";
7909467b48Spatrick 
8009467b48Spatrick     // Assembly string(s).
8109467b48Spatrick     if (!II->AsmString.empty()) {
8209467b48Spatrick       for (unsigned VarNum = 0; VarNum < VariantCount; ++VarNum) {
8309467b48Spatrick         Record *AsmVariant = Target.getAsmParserVariant(VarNum);
8409467b48Spatrick         OS << "Assembly string";
8509467b48Spatrick         if (VariantCount != 1)
8609467b48Spatrick           OS << " (" << AsmVariant->getValueAsString("Name") << ")";
8709467b48Spatrick         std::string AsmString =
8809467b48Spatrick             CodeGenInstruction::FlattenAsmStringVariants(II->AsmString, VarNum);
8909467b48Spatrick         // We trim spaces at each end of the asm string because rst needs the
9009467b48Spatrick         // formatting backticks to be next to a non-whitespace character.
9109467b48Spatrick         OS << ": ``" << escapeForRST(StringRef(AsmString).trim(" "))
9209467b48Spatrick            << "``\n\n";
9309467b48Spatrick       }
9409467b48Spatrick     }
9509467b48Spatrick 
9609467b48Spatrick     // Boolean flags.
9709467b48Spatrick     std::vector<const char *> FlagStrings;
9809467b48Spatrick #define xstr(s) str(s)
9909467b48Spatrick #define str(s) #s
10009467b48Spatrick #define FLAG(f) if (II->f) { FlagStrings.push_back(str(f)); }
10109467b48Spatrick     FLAG(isReturn)
10209467b48Spatrick     FLAG(isEHScopeReturn)
10309467b48Spatrick     FLAG(isBranch)
10409467b48Spatrick     FLAG(isIndirectBranch)
10509467b48Spatrick     FLAG(isCompare)
10609467b48Spatrick     FLAG(isMoveImm)
10709467b48Spatrick     FLAG(isBitcast)
10809467b48Spatrick     FLAG(isSelect)
10909467b48Spatrick     FLAG(isBarrier)
11009467b48Spatrick     FLAG(isCall)
11109467b48Spatrick     FLAG(isAdd)
11209467b48Spatrick     FLAG(isTrap)
11309467b48Spatrick     FLAG(canFoldAsLoad)
11409467b48Spatrick     FLAG(mayLoad)
11509467b48Spatrick     //FLAG(mayLoad_Unset) // Deliberately omitted.
11609467b48Spatrick     FLAG(mayStore)
11709467b48Spatrick     //FLAG(mayStore_Unset) // Deliberately omitted.
11809467b48Spatrick     FLAG(isPredicable)
11909467b48Spatrick     FLAG(isConvertibleToThreeAddress)
12009467b48Spatrick     FLAG(isCommutable)
12109467b48Spatrick     FLAG(isTerminator)
12209467b48Spatrick     FLAG(isReMaterializable)
12309467b48Spatrick     FLAG(hasDelaySlot)
12409467b48Spatrick     FLAG(usesCustomInserter)
12509467b48Spatrick     FLAG(hasPostISelHook)
12609467b48Spatrick     FLAG(hasCtrlDep)
12709467b48Spatrick     FLAG(isNotDuplicable)
12809467b48Spatrick     FLAG(hasSideEffects)
12909467b48Spatrick     //FLAG(hasSideEffects_Unset) // Deliberately omitted.
13009467b48Spatrick     FLAG(isAsCheapAsAMove)
13109467b48Spatrick     FLAG(hasExtraSrcRegAllocReq)
13209467b48Spatrick     FLAG(hasExtraDefRegAllocReq)
13309467b48Spatrick     FLAG(isCodeGenOnly)
13409467b48Spatrick     FLAG(isPseudo)
13509467b48Spatrick     FLAG(isRegSequence)
13609467b48Spatrick     FLAG(isExtractSubreg)
13709467b48Spatrick     FLAG(isInsertSubreg)
13809467b48Spatrick     FLAG(isConvergent)
13909467b48Spatrick     FLAG(hasNoSchedulingInfo)
14009467b48Spatrick     FLAG(variadicOpsAreDefs)
14109467b48Spatrick     FLAG(isAuthenticated)
14209467b48Spatrick     if (!FlagStrings.empty()) {
14309467b48Spatrick       OS << "Flags: ";
144*73471bf0Spatrick       ListSeparator LS;
145*73471bf0Spatrick       for (auto FlagString : FlagStrings)
146*73471bf0Spatrick         OS << LS << "``" << FlagString << "``";
14709467b48Spatrick       OS << "\n\n";
14809467b48Spatrick     }
14909467b48Spatrick 
15009467b48Spatrick     // Operands.
15109467b48Spatrick     for (unsigned i = 0; i < II->Operands.size(); ++i) {
15209467b48Spatrick       bool IsDef = i < II->Operands.NumDefs;
15309467b48Spatrick       auto Op = II->Operands[i];
15409467b48Spatrick 
15509467b48Spatrick       if (Op.MINumOperands > 1) {
15609467b48Spatrick         // This operand corresponds to multiple operands on the
15709467b48Spatrick         // MachineInstruction, so print all of them, showing the types and
15809467b48Spatrick         // names of both the compound operand and the basic operands it
15909467b48Spatrick         // contains.
16009467b48Spatrick         for (unsigned SubOpIdx = 0; SubOpIdx < Op.MINumOperands; ++SubOpIdx) {
16109467b48Spatrick           Record *SubRec =
16209467b48Spatrick               cast<DefInit>(Op.MIOperandInfo->getArg(SubOpIdx))->getDef();
16309467b48Spatrick           StringRef SubOpName = Op.MIOperandInfo->getArgNameStr(SubOpIdx);
16409467b48Spatrick           StringRef SubOpTypeName = SubRec->getName();
16509467b48Spatrick 
16609467b48Spatrick           OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName()
16709467b48Spatrick              << "/" << SubOpTypeName << ":$" << Op.Name << ".";
16809467b48Spatrick           // Not all sub-operands are named, make up a name for these.
16909467b48Spatrick           if (SubOpName.empty())
17009467b48Spatrick             OS << "anon" << SubOpIdx;
17109467b48Spatrick           else
17209467b48Spatrick             OS << SubOpName;
17309467b48Spatrick           OS << "``\n\n";
17409467b48Spatrick         }
17509467b48Spatrick       } else {
17609467b48Spatrick         // The operand corresponds to only one MachineInstruction operand.
17709467b48Spatrick         OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName()
17809467b48Spatrick            << ":$" << Op.Name << "``\n\n";
17909467b48Spatrick       }
18009467b48Spatrick     }
18109467b48Spatrick 
18209467b48Spatrick     // Constraints.
18309467b48Spatrick     StringRef Constraints = Inst->getValueAsString("Constraints");
18409467b48Spatrick     if (!Constraints.empty()) {
18509467b48Spatrick       OS << "Constraints: ``" << Constraints << "``\n\n";
18609467b48Spatrick     }
18709467b48Spatrick 
18809467b48Spatrick     // Implicit definitions.
18909467b48Spatrick     if (!II->ImplicitDefs.empty()) {
19009467b48Spatrick       OS << "Implicit defs: ";
191*73471bf0Spatrick       ListSeparator LS;
192*73471bf0Spatrick       for (Record *Def : II->ImplicitDefs)
193*73471bf0Spatrick         OS << LS << "``" << Def->getName() << "``";
19409467b48Spatrick       OS << "\n\n";
19509467b48Spatrick     }
19609467b48Spatrick 
19709467b48Spatrick     // Implicit uses.
19809467b48Spatrick     if (!II->ImplicitUses.empty()) {
19909467b48Spatrick       OS << "Implicit uses: ";
200*73471bf0Spatrick       ListSeparator LS;
201*73471bf0Spatrick       for (Record *Use : II->ImplicitUses)
202*73471bf0Spatrick         OS << LS << "``" << Use->getName() << "``";
20309467b48Spatrick       OS << "\n\n";
20409467b48Spatrick     }
20509467b48Spatrick 
20609467b48Spatrick     // Predicates.
20709467b48Spatrick     std::vector<Record *> Predicates =
20809467b48Spatrick         II->TheDef->getValueAsListOfDefs("Predicates");
20909467b48Spatrick     if (!Predicates.empty()) {
21009467b48Spatrick       OS << "Predicates: ";
211*73471bf0Spatrick       ListSeparator LS;
212*73471bf0Spatrick       for (Record *P : Predicates)
213*73471bf0Spatrick         OS << LS << "``" << P->getName() << "``";
21409467b48Spatrick       OS << "\n\n";
21509467b48Spatrick     }
21609467b48Spatrick   }
21709467b48Spatrick }
21809467b48Spatrick 
21909467b48Spatrick } // end namespace llvm
220