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 "CodeGenDAGPatterns.h" 22 #include "CodeGenInstruction.h" 23 #include "CodeGenTarget.h" 24 #include "TableGenBackends.h" 25 #include "llvm/TableGen/Record.h" 26 #include <string> 27 #include <vector> 28 29 using namespace llvm; 30 31 namespace llvm { 32 33 void writeTitle(StringRef Str, raw_ostream &OS, char Kind = '-') { 34 OS << std::string(Str.size(), Kind) << "\n" << Str << "\n" 35 << std::string(Str.size(), Kind) << "\n"; 36 } 37 38 void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') { 39 OS << Str << "\n" << std::string(Str.size(), Kind) << "\n"; 40 } 41 42 std::string escapeForRST(StringRef Str) { 43 std::string Result; 44 Result.reserve(Str.size() + 4); 45 for (char C : Str) { 46 switch (C) { 47 // We want special characters to be shown as their C escape codes. 48 case '\n': Result += "\\n"; break; 49 case '\t': Result += "\\t"; break; 50 // Underscore at the end of a line has a special meaning in rst. 51 case '_': Result += "\\_"; break; 52 default: Result += C; 53 } 54 } 55 return Result; 56 } 57 58 void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) { 59 CodeGenDAGPatterns CDP(RK); 60 CodeGenTarget &Target = CDP.getTargetInfo(); 61 unsigned VariantCount = Target.getAsmParserVariantCount(); 62 63 // Page title. 64 std::string Title = std::string(Target.getName()); 65 Title += " Instructions"; 66 writeTitle(Title, OS); 67 OS << "\n"; 68 69 for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) { 70 Record *Inst = II->TheDef; 71 72 // Don't print the target-independent instructions. 73 if (II->Namespace == "TargetOpcode") 74 continue; 75 76 // Heading (instruction name). 77 writeHeader(escapeForRST(Inst->getName()), OS, '='); 78 OS << "\n"; 79 80 // Assembly string(s). 81 if (!II->AsmString.empty()) { 82 for (unsigned VarNum = 0; VarNum < VariantCount; ++VarNum) { 83 Record *AsmVariant = Target.getAsmParserVariant(VarNum); 84 OS << "Assembly string"; 85 if (VariantCount != 1) 86 OS << " (" << AsmVariant->getValueAsString("Name") << ")"; 87 std::string AsmString = 88 CodeGenInstruction::FlattenAsmStringVariants(II->AsmString, VarNum); 89 // We trim spaces at each end of the asm string because rst needs the 90 // formatting backticks to be next to a non-whitespace character. 91 OS << ": ``" << escapeForRST(StringRef(AsmString).trim(" ")) 92 << "``\n\n"; 93 } 94 } 95 96 // Boolean flags. 97 std::vector<const char *> FlagStrings; 98 #define xstr(s) str(s) 99 #define str(s) #s 100 #define FLAG(f) if (II->f) { FlagStrings.push_back(str(f)); } 101 FLAG(isReturn) 102 FLAG(isEHScopeReturn) 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 FLAG(variadicOpsAreDefs) 141 FLAG(isAuthenticated) 142 if (!FlagStrings.empty()) { 143 OS << "Flags: "; 144 bool IsFirst = true; 145 for (auto FlagString : FlagStrings) { 146 if (!IsFirst) 147 OS << ", "; 148 OS << "``" << FlagString << "``"; 149 IsFirst = false; 150 } 151 OS << "\n\n"; 152 } 153 154 // Operands. 155 for (unsigned i = 0; i < II->Operands.size(); ++i) { 156 bool IsDef = i < II->Operands.NumDefs; 157 auto Op = II->Operands[i]; 158 159 if (Op.MINumOperands > 1) { 160 // This operand corresponds to multiple operands on the 161 // MachineInstruction, so print all of them, showing the types and 162 // names of both the compound operand and the basic operands it 163 // contains. 164 for (unsigned SubOpIdx = 0; SubOpIdx < Op.MINumOperands; ++SubOpIdx) { 165 Record *SubRec = 166 cast<DefInit>(Op.MIOperandInfo->getArg(SubOpIdx))->getDef(); 167 StringRef SubOpName = Op.MIOperandInfo->getArgNameStr(SubOpIdx); 168 StringRef SubOpTypeName = SubRec->getName(); 169 170 OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName() 171 << "/" << SubOpTypeName << ":$" << Op.Name << "."; 172 // Not all sub-operands are named, make up a name for these. 173 if (SubOpName.empty()) 174 OS << "anon" << SubOpIdx; 175 else 176 OS << SubOpName; 177 OS << "``\n\n"; 178 } 179 } else { 180 // The operand corresponds to only one MachineInstruction operand. 181 OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName() 182 << ":$" << Op.Name << "``\n\n"; 183 } 184 } 185 186 // Constraints. 187 StringRef Constraints = Inst->getValueAsString("Constraints"); 188 if (!Constraints.empty()) { 189 OS << "Constraints: ``" << Constraints << "``\n\n"; 190 } 191 192 // Implicit definitions. 193 if (!II->ImplicitDefs.empty()) { 194 OS << "Implicit defs: "; 195 bool IsFirst = true; 196 for (Record *Def : II->ImplicitDefs) { 197 if (!IsFirst) 198 OS << ", "; 199 OS << "``" << Def->getName() << "``"; 200 IsFirst = false; 201 } 202 OS << "\n\n"; 203 } 204 205 // Implicit uses. 206 if (!II->ImplicitUses.empty()) { 207 OS << "Implicit uses: "; 208 bool IsFirst = true; 209 for (Record *Use : II->ImplicitUses) { 210 if (!IsFirst) 211 OS << ", "; 212 OS << "``" << Use->getName() << "``"; 213 IsFirst = false; 214 } 215 OS << "\n\n"; 216 } 217 218 // Predicates. 219 std::vector<Record *> Predicates = 220 II->TheDef->getValueAsListOfDefs("Predicates"); 221 if (!Predicates.empty()) { 222 OS << "Predicates: "; 223 bool IsFirst = true; 224 for (Record *P : Predicates) { 225 if (!IsFirst) 226 OS << ", "; 227 OS << "``" << P->getName() << "``"; 228 IsFirst = false; 229 } 230 OS << "\n\n"; 231 } 232 } 233 } 234 235 } // end namespace llvm 236