| Oliver Stannard | 174fdef | 2017-11-14 15:35:15 +0000 | [diff] [blame] | 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(canFoldAsLoad) | 
|  | 113 | FLAG(mayLoad) | 
|  | 114 | //FLAG(mayLoad_Unset) // Deliberately omitted. | 
|  | 115 | FLAG(mayStore) | 
|  | 116 | //FLAG(mayStore_Unset) // Deliberately omitted. | 
|  | 117 | FLAG(isPredicable) | 
|  | 118 | FLAG(isConvertibleToThreeAddress) | 
|  | 119 | FLAG(isCommutable) | 
|  | 120 | FLAG(isTerminator) | 
|  | 121 | FLAG(isReMaterializable) | 
|  | 122 | FLAG(hasDelaySlot) | 
|  | 123 | FLAG(usesCustomInserter) | 
|  | 124 | FLAG(hasPostISelHook) | 
|  | 125 | FLAG(hasCtrlDep) | 
|  | 126 | FLAG(isNotDuplicable) | 
|  | 127 | FLAG(hasSideEffects) | 
|  | 128 | //FLAG(hasSideEffects_Unset) // Deliberately omitted. | 
|  | 129 | FLAG(isAsCheapAsAMove) | 
|  | 130 | FLAG(hasExtraSrcRegAllocReq) | 
|  | 131 | FLAG(hasExtraDefRegAllocReq) | 
|  | 132 | FLAG(isCodeGenOnly) | 
|  | 133 | FLAG(isPseudo) | 
|  | 134 | FLAG(isRegSequence) | 
|  | 135 | FLAG(isExtractSubreg) | 
|  | 136 | FLAG(isInsertSubreg) | 
|  | 137 | FLAG(isConvergent) | 
|  | 138 | FLAG(hasNoSchedulingInfo) | 
|  | 139 | if (!FlagStrings.empty()) { | 
|  | 140 | OS << "Flags: "; | 
|  | 141 | bool IsFirst = true; | 
|  | 142 | for (auto FlagString : FlagStrings) { | 
|  | 143 | if (!IsFirst) | 
|  | 144 | OS << ", "; | 
|  | 145 | OS << "``" << FlagString << "``"; | 
|  | 146 | IsFirst = false; | 
|  | 147 | } | 
|  | 148 | OS << "\n\n"; | 
|  | 149 | } | 
|  | 150 |  | 
|  | 151 | // Operands. | 
|  | 152 | for (unsigned i = 0; i < II->Operands.size(); ++i) { | 
|  | 153 | bool IsDef = i < II->Operands.NumDefs; | 
|  | 154 | auto Op = II->Operands[i]; | 
|  | 155 |  | 
|  | 156 | if (Op.MINumOperands > 1) { | 
|  | 157 | // This operand corresponds to multiple operands on the | 
|  | 158 | // MachineInstruction, so print all of them, showing the types and | 
|  | 159 | // names of both the compound operand and the basic operands it | 
|  | 160 | // contains. | 
|  | 161 | for (unsigned SubOpIdx = 0; SubOpIdx < Op.MINumOperands; ++SubOpIdx) { | 
|  | 162 | Record *SubRec = | 
|  | 163 | cast<DefInit>(Op.MIOperandInfo->getArg(SubOpIdx))->getDef(); | 
|  | 164 | StringRef SubOpName = Op.MIOperandInfo->getArgNameStr(SubOpIdx); | 
|  | 165 | StringRef SubOpTypeName = SubRec->getName(); | 
|  | 166 |  | 
|  | 167 | OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName() | 
|  | 168 | << "/" << SubOpTypeName << ":$" << Op.Name << "."; | 
|  | 169 | // Not all sub-operands are named, make up a name for these. | 
|  | 170 | if (SubOpName.empty()) | 
|  | 171 | OS << "anon" << SubOpIdx; | 
|  | 172 | else | 
|  | 173 | OS << SubOpName; | 
|  | 174 | OS << "``\n\n"; | 
|  | 175 | } | 
|  | 176 | } else { | 
|  | 177 | // The operand corresponds to only one MachineInstruction operand. | 
|  | 178 | OS << "* " << (IsDef ? "DEF" : "USE") << " ``" << Op.Rec->getName() | 
|  | 179 | << ":$" << Op.Name << "``\n\n"; | 
|  | 180 | } | 
|  | 181 | } | 
|  | 182 |  | 
|  | 183 | // Constraints. | 
|  | 184 | StringRef Constraints = Inst->getValueAsString("Constraints"); | 
|  | 185 | if (!Constraints.empty()) { | 
|  | 186 | OS << "Constraints: ``" << Constraints << "``\n\n"; | 
|  | 187 | } | 
|  | 188 |  | 
|  | 189 | // Implicit definitions. | 
|  | 190 | if (!II->ImplicitDefs.empty()) { | 
|  | 191 | OS << "Implicit defs: "; | 
|  | 192 | bool IsFirst = true; | 
|  | 193 | for (Record *Def : II->ImplicitDefs) { | 
|  | 194 | if (!IsFirst) | 
|  | 195 | OS << ", "; | 
|  | 196 | OS << "``" << Def->getName() << "``"; | 
|  | 197 | IsFirst = false; | 
|  | 198 | } | 
|  | 199 | OS << "\n\n"; | 
|  | 200 | } | 
|  | 201 |  | 
|  | 202 | // Implicit uses. | 
|  | 203 | if (!II->ImplicitUses.empty()) { | 
|  | 204 | OS << "Implicit uses: "; | 
|  | 205 | bool IsFirst = true; | 
|  | 206 | for (Record *Use : II->ImplicitUses) { | 
|  | 207 | if (!IsFirst) | 
|  | 208 | OS << ", "; | 
|  | 209 | OS << "``" << Use->getName() << "``"; | 
|  | 210 | IsFirst = false; | 
|  | 211 | } | 
|  | 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 | bool IsFirst = true; | 
|  | 221 | for (Record *P : Predicates) { | 
|  | 222 | if (!IsFirst) | 
|  | 223 | OS << ", "; | 
|  | 224 | OS << "``" << P->getName() << "``"; | 
|  | 225 | IsFirst = false; | 
|  | 226 | } | 
|  | 227 | OS << "\n\n"; | 
|  | 228 | } | 
|  | 229 | } | 
|  | 230 | } | 
|  | 231 |  | 
|  | 232 | } // end llvm namespace |