1 //===- InstrDocsEmitter.cpp - Opcode Documentation Generator --------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 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 "Common/CodeGenDAGPatterns.h" 22 #include "Common/CodeGenInstruction.h" 23 #include "Common/CodeGenTarget.h" 24 #include "llvm/TableGen/Record.h" 25 #include "llvm/TableGen/TableGenBackend.h" 26 #include <string> 27 #include <vector> 28 29 using namespace llvm; 30 31 static void writeTitle(StringRef Str, raw_ostream &OS, char Kind = '-') { 32 OS << std::string(Str.size(), Kind) << "\n" 33 << Str << "\n" 34 << std::string(Str.size(), Kind) << "\n"; 35 } 36 37 static void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') { 38 OS << Str << "\n" << std::string(Str.size(), Kind) << "\n"; 39 } 40 41 static std::string escapeForRST(StringRef Str) { 42 std::string Result; 43 Result.reserve(Str.size() + 4); 44 for (char C : Str) { 45 switch (C) { 46 // We want special characters to be shown as their C escape codes. 47 case '\n': 48 Result += "\\n"; 49 break; 50 case '\t': 51 Result += "\\t"; 52 break; 53 // Underscore at the end of a line has a special meaning in rst. 54 case '_': 55 Result += "\\_"; 56 break; 57 default: 58 Result += C; 59 } 60 } 61 return Result; 62 } 63 64 static void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) { 65 CodeGenDAGPatterns CDP(RK); 66 CodeGenTarget &Target = CDP.getTargetInfo(); 67 unsigned VariantCount = Target.getAsmParserVariantCount(); 68 69 // Page title. 70 std::string Title = std::string(Target.getName()); 71 Title += " Instructions"; 72 writeTitle(Title, OS); 73 OS << "\n"; 74 75 for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) { 76 Record *Inst = II->TheDef; 77 78 // Don't print the target-independent instructions. 79 if (II->Namespace == "TargetOpcode") 80 continue; 81 82 // Heading (instruction name). 83 writeHeader(escapeForRST(Inst->getName()), OS, '='); 84 OS << "\n"; 85 86 // Assembly string(s). 87 if (!II->AsmString.empty()) { 88 for (unsigned VarNum = 0; VarNum < VariantCount; ++VarNum) { 89 Record *AsmVariant = Target.getAsmParserVariant(VarNum); 90 OS << "Assembly string"; 91 if (VariantCount != 1) 92 OS << " (" << AsmVariant->getValueAsString("Name") << ")"; 93 std::string AsmString = 94 CodeGenInstruction::FlattenAsmStringVariants(II->AsmString, VarNum); 95 // We trim spaces at each end of the asm string because rst needs the 96 // formatting backticks to be next to a non-whitespace character. 97 OS << ": ``" << escapeForRST(StringRef(AsmString).trim(" ")) 98 << "``\n\n"; 99 } 100 } 101 102 // Boolean flags. 103 std::vector<const char *> FlagStrings; 104 #define xstr(s) str(s) 105 #define str(s) #s 106 #define FLAG(f) \ 107 if (II->f) { \ 108 FlagStrings.push_back(str(f)); \ 109 } 110 FLAG(isReturn) 111 FLAG(isEHScopeReturn) 112 FLAG(isBranch) 113 FLAG(isIndirectBranch) 114 FLAG(isCompare) 115 FLAG(isMoveImm) 116 FLAG(isBitcast) 117 FLAG(isSelect) 118 FLAG(isBarrier) 119 FLAG(isCall) 120 FLAG(isAdd) 121 FLAG(isTrap) 122 FLAG(canFoldAsLoad) 123 FLAG(mayLoad) 124 // FLAG(mayLoad_Unset) // Deliberately omitted. 125 FLAG(mayStore) 126 // FLAG(mayStore_Unset) // Deliberately omitted. 127 FLAG(isPredicable) 128 FLAG(isConvertibleToThreeAddress) 129 FLAG(isCommutable) 130 FLAG(isTerminator) 131 FLAG(isReMaterializable) 132 FLAG(hasDelaySlot) 133 FLAG(usesCustomInserter) 134 FLAG(hasPostISelHook) 135 FLAG(hasCtrlDep) 136 FLAG(isNotDuplicable) 137 FLAG(hasSideEffects) 138 // FLAG(hasSideEffects_Unset) // Deliberately omitted. 139 FLAG(isAsCheapAsAMove) 140 FLAG(hasExtraSrcRegAllocReq) 141 FLAG(hasExtraDefRegAllocReq) 142 FLAG(isCodeGenOnly) 143 FLAG(isPseudo) 144 FLAG(isRegSequence) 145 FLAG(isExtractSubreg) 146 FLAG(isInsertSubreg) 147 FLAG(isConvergent) 148 FLAG(hasNoSchedulingInfo) 149 FLAG(variadicOpsAreDefs) 150 FLAG(isAuthenticated) 151 if (!FlagStrings.empty()) { 152 OS << "Flags: "; 153 ListSeparator LS; 154 for (auto FlagString : FlagStrings) 155 OS << LS << "``" << FlagString << "``"; 156 OS << "\n\n"; 157 } 158 159 // Operands. 160 for (unsigned i = 0; i < II->Operands.size(); ++i) { 161 bool IsDef = i < II->Operands.NumDefs; 162 auto Op = II->Operands[i]; 163 164 if (Op.MINumOperands > 1) { 165 // This operand corresponds to multiple operands on the 166 // MachineInstruction, so print all of them, showing the types and 167 // names of both the compound operand and the basic operands it 168 // contains. 169 for (unsigned SubOpIdx = 0; SubOpIdx < Op.MINumOperands; ++SubOpIdx) { 170 Record *SubRec = 171 cast<DefInit>(Op.MIOperandInfo->getArg(SubOpIdx))->getDef(); 172 StringRef SubOpName = Op.MIOperandInfo->getArgNameStr(SubOpIdx); 173 StringRef SubOpTypeName = SubRec->getName(); 174 175 OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName() 176 << "/" << SubOpTypeName << ":$" << Op.Name << "."; 177 // Not all sub-operands are named, make up a name for these. 178 if (SubOpName.empty()) 179 OS << "anon" << SubOpIdx; 180 else 181 OS << SubOpName; 182 OS << "``\n\n"; 183 } 184 } else { 185 // The operand corresponds to only one MachineInstruction operand. 186 OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName() 187 << ":$" << Op.Name << "``\n\n"; 188 } 189 } 190 191 // Constraints. 192 StringRef Constraints = Inst->getValueAsString("Constraints"); 193 if (!Constraints.empty()) { 194 OS << "Constraints: ``" << Constraints << "``\n\n"; 195 } 196 197 // Implicit definitions. 198 if (!II->ImplicitDefs.empty()) { 199 OS << "Implicit defs: "; 200 ListSeparator LS; 201 for (Record *Def : II->ImplicitDefs) 202 OS << LS << "``" << Def->getName() << "``"; 203 OS << "\n\n"; 204 } 205 206 // Implicit uses. 207 if (!II->ImplicitUses.empty()) { 208 OS << "Implicit uses: "; 209 ListSeparator LS; 210 for (Record *Use : II->ImplicitUses) 211 OS << LS << "``" << Use->getName() << "``"; 212 OS << "\n\n"; 213 } 214 215 // Predicates. 216 std::vector<Record *> Predicates = 217 II->TheDef->getValueAsListOfDefs("Predicates"); 218 if (!Predicates.empty()) { 219 OS << "Predicates: "; 220 ListSeparator LS; 221 for (Record *P : Predicates) 222 OS << LS << "``" << P->getName() << "``"; 223 OS << "\n\n"; 224 } 225 } 226 } 227 228 static TableGen::Emitter::Opt X("gen-instr-docs", EmitInstrDocs, 229 "Generate instruction documentation"); 230