123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- //===- InstrDocsEmitter.cpp - Opcode Documentation Generator --------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // InstrDocsEmitter generates restructured text documentation for the opcodes
- // that can be used by MachineInstr. For each opcode, the documentation lists:
- // * Opcode name
- // * Assembly string
- // * Flags (e.g. mayLoad, isBranch, ...)
- // * Operands, including type and name
- // * Operand constraints
- // * Implicit register uses & defs
- // * Predicates
- //
- //===----------------------------------------------------------------------===//
- #include "CodeGenDAGPatterns.h"
- #include "CodeGenInstruction.h"
- #include "CodeGenTarget.h"
- #include "TableGenBackends.h"
- #include "llvm/TableGen/Record.h"
- #include <string>
- #include <vector>
- using namespace llvm;
- namespace llvm {
- void writeTitle(StringRef Str, raw_ostream &OS, char Kind = '-') {
- OS << std::string(Str.size(), Kind) << "\n" << Str << "\n"
- << std::string(Str.size(), Kind) << "\n";
- }
- void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') {
- OS << Str << "\n" << std::string(Str.size(), Kind) << "\n";
- }
- std::string escapeForRST(StringRef Str) {
- std::string Result;
- Result.reserve(Str.size() + 4);
- for (char C : Str) {
- switch (C) {
- // We want special characters to be shown as their C escape codes.
- case '\n': Result += "\\n"; break;
- case '\t': Result += "\\t"; break;
- // Underscore at the end of a line has a special meaning in rst.
- case '_': Result += "\\_"; break;
- default: Result += C;
- }
- }
- return Result;
- }
- void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) {
- CodeGenDAGPatterns CDP(RK);
- CodeGenTarget &Target = CDP.getTargetInfo();
- unsigned VariantCount = Target.getAsmParserVariantCount();
- // Page title.
- std::string Title = std::string(Target.getName());
- Title += " Instructions";
- writeTitle(Title, OS);
- OS << "\n";
- for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) {
- Record *Inst = II->TheDef;
- // Don't print the target-independent instructions.
- if (II->Namespace == "TargetOpcode")
- continue;
- // Heading (instruction name).
- writeHeader(escapeForRST(Inst->getName()), OS, '=');
- OS << "\n";
- // Assembly string(s).
- if (!II->AsmString.empty()) {
- for (unsigned VarNum = 0; VarNum < VariantCount; ++VarNum) {
- Record *AsmVariant = Target.getAsmParserVariant(VarNum);
- OS << "Assembly string";
- if (VariantCount != 1)
- OS << " (" << AsmVariant->getValueAsString("Name") << ")";
- std::string AsmString =
- CodeGenInstruction::FlattenAsmStringVariants(II->AsmString, VarNum);
- // We trim spaces at each end of the asm string because rst needs the
- // formatting backticks to be next to a non-whitespace character.
- OS << ": ``" << escapeForRST(StringRef(AsmString).trim(" "))
- << "``\n\n";
- }
- }
- // Boolean flags.
- std::vector<const char *> FlagStrings;
- #define xstr(s) str(s)
- #define str(s) #s
- #define FLAG(f) if (II->f) { FlagStrings.push_back(str(f)); }
- FLAG(isReturn)
- FLAG(isEHScopeReturn)
- FLAG(isBranch)
- FLAG(isIndirectBranch)
- FLAG(isCompare)
- FLAG(isMoveImm)
- FLAG(isBitcast)
- FLAG(isSelect)
- FLAG(isBarrier)
- FLAG(isCall)
- FLAG(isAdd)
- FLAG(isTrap)
- FLAG(canFoldAsLoad)
- FLAG(mayLoad)
- //FLAG(mayLoad_Unset) // Deliberately omitted.
- FLAG(mayStore)
- //FLAG(mayStore_Unset) // Deliberately omitted.
- FLAG(isPredicable)
- FLAG(isConvertibleToThreeAddress)
- FLAG(isCommutable)
- FLAG(isTerminator)
- FLAG(isReMaterializable)
- FLAG(hasDelaySlot)
- FLAG(usesCustomInserter)
- FLAG(hasPostISelHook)
- FLAG(hasCtrlDep)
- FLAG(isNotDuplicable)
- FLAG(hasSideEffects)
- //FLAG(hasSideEffects_Unset) // Deliberately omitted.
- FLAG(isAsCheapAsAMove)
- FLAG(hasExtraSrcRegAllocReq)
- FLAG(hasExtraDefRegAllocReq)
- FLAG(isCodeGenOnly)
- FLAG(isPseudo)
- FLAG(isRegSequence)
- FLAG(isExtractSubreg)
- FLAG(isInsertSubreg)
- FLAG(isConvergent)
- FLAG(hasNoSchedulingInfo)
- FLAG(variadicOpsAreDefs)
- FLAG(isAuthenticated)
- if (!FlagStrings.empty()) {
- OS << "Flags: ";
- ListSeparator LS;
- for (auto FlagString : FlagStrings)
- OS << LS << "``" << FlagString << "``";
- OS << "\n\n";
- }
- // Operands.
- for (unsigned i = 0; i < II->Operands.size(); ++i) {
- bool IsDef = i < II->Operands.NumDefs;
- auto Op = II->Operands[i];
- if (Op.MINumOperands > 1) {
- // This operand corresponds to multiple operands on the
- // MachineInstruction, so print all of them, showing the types and
- // names of both the compound operand and the basic operands it
- // contains.
- for (unsigned SubOpIdx = 0; SubOpIdx < Op.MINumOperands; ++SubOpIdx) {
- Record *SubRec =
- cast<DefInit>(Op.MIOperandInfo->getArg(SubOpIdx))->getDef();
- StringRef SubOpName = Op.MIOperandInfo->getArgNameStr(SubOpIdx);
- StringRef SubOpTypeName = SubRec->getName();
- OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName()
- << "/" << SubOpTypeName << ":$" << Op.Name << ".";
- // Not all sub-operands are named, make up a name for these.
- if (SubOpName.empty())
- OS << "anon" << SubOpIdx;
- else
- OS << SubOpName;
- OS << "``\n\n";
- }
- } else {
- // The operand corresponds to only one MachineInstruction operand.
- OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName()
- << ":$" << Op.Name << "``\n\n";
- }
- }
- // Constraints.
- StringRef Constraints = Inst->getValueAsString("Constraints");
- if (!Constraints.empty()) {
- OS << "Constraints: ``" << Constraints << "``\n\n";
- }
- // Implicit definitions.
- if (!II->ImplicitDefs.empty()) {
- OS << "Implicit defs: ";
- ListSeparator LS;
- for (Record *Def : II->ImplicitDefs)
- OS << LS << "``" << Def->getName() << "``";
- OS << "\n\n";
- }
- // Implicit uses.
- if (!II->ImplicitUses.empty()) {
- OS << "Implicit uses: ";
- ListSeparator LS;
- for (Record *Use : II->ImplicitUses)
- OS << LS << "``" << Use->getName() << "``";
- OS << "\n\n";
- }
- // Predicates.
- std::vector<Record *> Predicates =
- II->TheDef->getValueAsListOfDefs("Predicates");
- if (!Predicates.empty()) {
- OS << "Predicates: ";
- ListSeparator LS;
- for (Record *P : Predicates)
- OS << LS << "``" << P->getName() << "``";
- OS << "\n\n";
- }
- }
- }
- } // end namespace llvm
|