Home | History | Annotate | Download | only in TableGen
      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 
     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 
     39 void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') {
     40   OS << Str << "\n" << std::string(Str.size(), Kind) << "\n";
     41 }
     42 
     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 
     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