You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
232
external/llvm/utils/TableGen/InstrDocsEmitter.cpp
vendored
232
external/llvm/utils/TableGen/InstrDocsEmitter.cpp
vendored
@ -1,232 +0,0 @@
|
||||
//===- InstrDocsEmitter.cpp - Opcode Documentation Generator --------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 = 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(isBranch)
|
||||
FLAG(isIndirectBranch)
|
||||
FLAG(isCompare)
|
||||
FLAG(isMoveImm)
|
||||
FLAG(isBitcast)
|
||||
FLAG(isSelect)
|
||||
FLAG(isBarrier)
|
||||
FLAG(isCall)
|
||||
FLAG(isAdd)
|
||||
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)
|
||||
if (!FlagStrings.empty()) {
|
||||
OS << "Flags: ";
|
||||
bool IsFirst = true;
|
||||
for (auto FlagString : FlagStrings) {
|
||||
if (!IsFirst)
|
||||
OS << ", ";
|
||||
OS << "``" << FlagString << "``";
|
||||
IsFirst = false;
|
||||
}
|
||||
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: ";
|
||||
bool IsFirst = true;
|
||||
for (Record *Def : II->ImplicitDefs) {
|
||||
if (!IsFirst)
|
||||
OS << ", ";
|
||||
OS << "``" << Def->getName() << "``";
|
||||
IsFirst = false;
|
||||
}
|
||||
OS << "\n\n";
|
||||
}
|
||||
|
||||
// Implicit uses.
|
||||
if (!II->ImplicitUses.empty()) {
|
||||
OS << "Implicit uses: ";
|
||||
bool IsFirst = true;
|
||||
for (Record *Use : II->ImplicitUses) {
|
||||
if (!IsFirst)
|
||||
OS << ", ";
|
||||
OS << "``" << Use->getName() << "``";
|
||||
IsFirst = false;
|
||||
}
|
||||
OS << "\n\n";
|
||||
}
|
||||
|
||||
// Predicates.
|
||||
std::vector<Record *> Predicates =
|
||||
II->TheDef->getValueAsListOfDefs("Predicates");
|
||||
if (!Predicates.empty()) {
|
||||
OS << "Predicates: ";
|
||||
bool IsFirst = true;
|
||||
for (Record *P : Predicates) {
|
||||
if (!IsFirst)
|
||||
OS << ", ";
|
||||
OS << "``" << P->getName() << "``";
|
||||
IsFirst = false;
|
||||
}
|
||||
OS << "\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end llvm namespace
|
Reference in New Issue
Block a user