Imported Upstream version 5.18.0.167

Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-10-20 08:25:10 +00:00
parent e19d552987
commit b084638f15
28489 changed files with 184 additions and 3866856 deletions

View File

@ -1 +0,0 @@
f2d304bfcf5b76c4e27073b71197a6abbedde6e8

File diff suppressed because it is too large Load Diff

View File

@ -1,197 +0,0 @@
//===- AsmWriterInst.h - Classes encapsulating a printable inst -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// These classes implement a parser for assembly strings.
//
//===----------------------------------------------------------------------===//
#include "AsmWriterInst.h"
#include "CodeGenTarget.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
using namespace llvm;
static bool isIdentChar(char C) {
return (C >= 'a' && C <= 'z') ||
(C >= 'A' && C <= 'Z') ||
(C >= '0' && C <= '9') ||
C == '_';
}
std::string AsmWriterOperand::getCode(bool PassSubtarget) const {
if (OperandType == isLiteralTextOperand) {
if (Str.size() == 1)
return "O << '" + Str + "';";
return "O << \"" + Str + "\";";
}
if (OperandType == isLiteralStatementOperand)
return Str;
std::string Result = Str + "(MI";
if (MIOpNo != ~0U)
Result += ", " + utostr(MIOpNo);
if (PassSubtarget)
Result += ", STI";
Result += ", O";
if (!MiModifier.empty())
Result += ", \"" + MiModifier + '"';
return Result + ");";
}
/// ParseAsmString - Parse the specified Instruction's AsmString into this
/// AsmWriterInst.
///
AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
unsigned Variant)
: CGI(&CGI), CGIIndex(CGIIndex) {
// NOTE: Any extensions to this code need to be mirrored in the
// AsmPrinter::printInlineAsm code that executes as compile time (assuming
// that inline asm strings should also get the new feature)!
std::string AsmString = CGI.FlattenAsmStringVariants(CGI.AsmString, Variant);
std::string::size_type LastEmitted = 0;
while (LastEmitted != AsmString.size()) {
std::string::size_type DollarPos =
AsmString.find_first_of("$\\", LastEmitted);
if (DollarPos == std::string::npos) DollarPos = AsmString.size();
// Emit a constant string fragment.
if (DollarPos != LastEmitted) {
for (; LastEmitted != DollarPos; ++LastEmitted)
switch (AsmString[LastEmitted]) {
case '\n':
AddLiteralString("\\n");
break;
case '\t':
AddLiteralString("\\t");
break;
case '"':
AddLiteralString("\\\"");
break;
case '\\':
AddLiteralString("\\\\");
break;
default:
AddLiteralString(std::string(1, AsmString[LastEmitted]));
break;
}
} else if (AsmString[DollarPos] == '\\') {
if (DollarPos+1 != AsmString.size()) {
if (AsmString[DollarPos+1] == 'n') {
AddLiteralString("\\n");
} else if (AsmString[DollarPos+1] == 't') {
AddLiteralString("\\t");
} else if (std::string("${|}\\").find(AsmString[DollarPos+1])
!= std::string::npos) {
AddLiteralString(std::string(1, AsmString[DollarPos+1]));
} else {
PrintFatalError("Non-supported escaped character found in instruction '" +
CGI.TheDef->getName() + "'!");
}
LastEmitted = DollarPos+2;
continue;
}
} else if (DollarPos+1 != AsmString.size() &&
AsmString[DollarPos+1] == '$') {
AddLiteralString("$"); // "$$" -> $
LastEmitted = DollarPos+2;
} else {
// Get the name of the variable.
std::string::size_type VarEnd = DollarPos+1;
// handle ${foo}bar as $foo by detecting whether the character following
// the dollar sign is a curly brace. If so, advance VarEnd and DollarPos
// so the variable name does not contain the leading curly brace.
bool hasCurlyBraces = false;
if (VarEnd < AsmString.size() && '{' == AsmString[VarEnd]) {
hasCurlyBraces = true;
++DollarPos;
++VarEnd;
}
while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
++VarEnd;
StringRef VarName(AsmString.data()+DollarPos+1, VarEnd-DollarPos-1);
// Modifier - Support ${foo:modifier} syntax, where "modifier" is passed
// into printOperand. Also support ${:feature}, which is passed into
// PrintSpecial.
std::string Modifier;
// In order to avoid starting the next string at the terminating curly
// brace, advance the end position past it if we found an opening curly
// brace.
if (hasCurlyBraces) {
if (VarEnd >= AsmString.size())
PrintFatalError("Reached end of string before terminating curly brace in '"
+ CGI.TheDef->getName() + "'");
// Look for a modifier string.
if (AsmString[VarEnd] == ':') {
++VarEnd;
if (VarEnd >= AsmString.size())
PrintFatalError("Reached end of string before terminating curly brace in '"
+ CGI.TheDef->getName() + "'");
std::string::size_type ModifierStart = VarEnd;
while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
++VarEnd;
Modifier = std::string(AsmString.begin()+ModifierStart,
AsmString.begin()+VarEnd);
if (Modifier.empty())
PrintFatalError("Bad operand modifier name in '"+ CGI.TheDef->getName() + "'");
}
if (AsmString[VarEnd] != '}')
PrintFatalError("Variable name beginning with '{' did not end with '}' in '"
+ CGI.TheDef->getName() + "'");
++VarEnd;
}
if (VarName.empty() && Modifier.empty())
PrintFatalError("Stray '$' in '" + CGI.TheDef->getName() +
"' asm string, maybe you want $$?");
if (VarName.empty()) {
// Just a modifier, pass this into PrintSpecial.
Operands.emplace_back("PrintSpecial", ~0U, Modifier);
} else {
// Otherwise, normal operand.
unsigned OpNo = CGI.Operands.getOperandNamed(VarName);
CGIOperandList::OperandInfo OpInfo = CGI.Operands[OpNo];
unsigned MIOp = OpInfo.MIOperandNo;
Operands.emplace_back(OpInfo.PrinterMethodName, MIOp, Modifier);
}
LastEmitted = VarEnd;
}
}
Operands.emplace_back("return;", AsmWriterOperand::isLiteralStatementOperand);
}
/// MatchesAllButOneOp - If this instruction is exactly identical to the
/// specified instruction except for one differing operand, return the differing
/// operand number. If more than one operand mismatches, return ~1, otherwise
/// if the instructions are identical return ~0.
unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{
if (Operands.size() != Other.Operands.size()) return ~1;
unsigned MismatchOperand = ~0U;
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
if (Operands[i] != Other.Operands[i]) {
if (MismatchOperand != ~0U) // Already have one mismatch?
return ~1U;
MismatchOperand = i;
}
}
return MismatchOperand;
}

View File

@ -1,106 +0,0 @@
//===- AsmWriterInst.h - Classes encapsulating a printable inst -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// These classes implement a parser for assembly strings. The parser splits
// the string into operands, which can be literal strings (the constant bits of
// the string), actual operands (i.e., operands from the MachineInstr), and
// dynamically-generated text, specified by raw C++ code.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_UTILS_TABLEGEN_ASMWRITERINST_H
#define LLVM_UTILS_TABLEGEN_ASMWRITERINST_H
#include <string>
#include <vector>
namespace llvm {
class CodeGenInstruction;
class Record;
struct AsmWriterOperand {
enum OpType {
// Output this text surrounded by quotes to the asm.
isLiteralTextOperand,
// This is the name of a routine to call to print the operand.
isMachineInstrOperand,
// Output this text verbatim to the asm writer. It is code that
// will output some text to the asm.
isLiteralStatementOperand
} OperandType;
/// MiOpNo - For isMachineInstrOperand, this is the operand number of the
/// machine instruction.
unsigned MIOpNo;
/// Str - For isLiteralTextOperand, this IS the literal text. For
/// isMachineInstrOperand, this is the PrinterMethodName for the operand..
/// For isLiteralStatementOperand, this is the code to insert verbatim
/// into the asm writer.
std::string Str;
/// MiModifier - For isMachineInstrOperand, this is the modifier string for
/// an operand, specified with syntax like ${opname:modifier}.
std::string MiModifier;
// To make VS STL happy
AsmWriterOperand(OpType op = isLiteralTextOperand):OperandType(op) {}
AsmWriterOperand(const std::string &LitStr,
OpType op = isLiteralTextOperand)
: OperandType(op), Str(LitStr) {}
AsmWriterOperand(const std::string &Printer,
unsigned _MIOpNo,
const std::string &Modifier,
OpType op = isMachineInstrOperand)
: OperandType(op), MIOpNo(_MIOpNo), Str(Printer), MiModifier(Modifier) {}
bool operator!=(const AsmWriterOperand &Other) const {
if (OperandType != Other.OperandType || Str != Other.Str) return true;
if (OperandType == isMachineInstrOperand)
return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier;
return false;
}
bool operator==(const AsmWriterOperand &Other) const {
return !operator!=(Other);
}
/// getCode - Return the code that prints this operand.
std::string getCode(bool PassSubtarget) const;
};
class AsmWriterInst {
public:
std::vector<AsmWriterOperand> Operands;
const CodeGenInstruction *CGI;
unsigned CGIIndex;
AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
unsigned Variant);
/// MatchesAllButOneOp - If this instruction is exactly identical to the
/// specified instruction except for one differing operand, return the
/// differing operand number. Otherwise return ~0.
unsigned MatchesAllButOneOp(const AsmWriterInst &Other) const;
private:
void AddLiteralString(const std::string &Str) {
// If the last operand was already a literal text string, append this to
// it, otherwise add a new operand.
if (!Operands.empty() &&
Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand)
Operands.back().Str.append(Str);
else
Operands.push_back(AsmWriterOperand(Str));
}
};
}
#endif

View File

@ -1,177 +0,0 @@
//===- Attributes.cpp - Generate attributes -------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/TableGen/Record.h"
#include <algorithm>
#include <string>
#include <vector>
using namespace llvm;
#define DEBUG_TYPE "attr-enum"
namespace {
class Attributes {
public:
Attributes(RecordKeeper &R) : Records(R) {}
void emit(raw_ostream &OS);
private:
void emitTargetIndependentEnums(raw_ostream &OS);
void emitConversionFn(raw_ostream &OS);
void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr);
void printEnumAttrClasses(raw_ostream &OS,
const std::vector<Record *> &Records);
void printStrBoolAttrClasses(raw_ostream &OS,
const std::vector<Record *> &Records);
RecordKeeper &Records;
};
} // End anonymous namespace.
void Attributes::emitTargetIndependentEnums(raw_ostream &OS) {
OS << "#ifdef GET_ATTR_ENUM\n";
OS << "#undef GET_ATTR_ENUM\n";
std::vector<Record*> Attrs =
Records.getAllDerivedDefinitions("EnumAttr");
for (auto A : Attrs)
OS << A->getName() << ",\n";
OS << "#endif\n";
}
void Attributes::emitConversionFn(raw_ostream &OS) {
OS << "#ifdef GET_ATTR_KIND_FROM_NAME\n";
OS << "#undef GET_ATTR_KIND_FROM_NAME\n";
std::vector<Record*> Attrs =
Records.getAllDerivedDefinitions("EnumAttr");
OS << "static Attribute::AttrKind getAttrKindFromName(StringRef AttrName) {\n";
OS << " return StringSwitch<Attribute::AttrKind>(AttrName)\n";
for (auto A : Attrs) {
OS << " .Case(\"" << A->getValueAsString("AttrString");
OS << "\", Attribute::" << A->getName() << ")\n";
}
OS << " .Default(Attribute::None);\n";
OS << "}\n\n";
OS << "#endif\n";
}
void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
OS << "#ifdef GET_ATTR_COMPAT_FUNC\n";
OS << "#undef GET_ATTR_COMPAT_FUNC\n";
OS << "struct EnumAttr {\n";
OS << " static bool isSet(const Function &Fn,\n";
OS << " Attribute::AttrKind Kind) {\n";
OS << " return Fn.hasFnAttribute(Kind);\n";
OS << " }\n\n";
OS << " static void set(Function &Fn,\n";
OS << " Attribute::AttrKind Kind, bool Val) {\n";
OS << " if (Val)\n";
OS << " Fn.addFnAttr(Kind);\n";
OS << " else\n";
OS << " Fn.removeFnAttr(Kind);\n";
OS << " }\n";
OS << "};\n\n";
OS << "struct StrBoolAttr {\n";
OS << " static bool isSet(const Function &Fn,\n";
OS << " StringRef Kind) {\n";
OS << " auto A = Fn.getFnAttribute(Kind);\n";
OS << " return A.getValueAsString().equals(\"true\");\n";
OS << " }\n\n";
OS << " static void set(Function &Fn,\n";
OS << " StringRef Kind, bool Val) {\n";
OS << " Fn.addFnAttr(Kind, Val ? \"true\" : \"false\");\n";
OS << " }\n";
OS << "};\n\n";
printEnumAttrClasses(OS ,Records.getAllDerivedDefinitions("EnumAttr"));
printStrBoolAttrClasses(OS , Records.getAllDerivedDefinitions("StrBoolAttr"));
OS << "static inline bool hasCompatibleFnAttrs(const Function &Caller,\n"
<< " const Function &Callee) {\n";
OS << " bool Ret = true;\n\n";
std::vector<Record *> CompatRules =
Records.getAllDerivedDefinitions("CompatRule");
for (auto *Rule : CompatRules) {
StringRef FuncName = Rule->getValueAsString("CompatFunc");
OS << " Ret &= " << FuncName << "(Caller, Callee);\n";
}
OS << "\n";
OS << " return Ret;\n";
OS << "}\n\n";
std::vector<Record *> MergeRules =
Records.getAllDerivedDefinitions("MergeRule");
OS << "static inline void mergeFnAttrs(Function &Caller,\n"
<< " const Function &Callee) {\n";
for (auto *Rule : MergeRules) {
StringRef FuncName = Rule->getValueAsString("MergeFunc");
OS << " " << FuncName << "(Caller, Callee);\n";
}
OS << "}\n\n";
OS << "#endif\n";
}
void Attributes::printEnumAttrClasses(raw_ostream &OS,
const std::vector<Record *> &Records) {
OS << "// EnumAttr classes\n";
for (const auto *R : Records) {
OS << "struct " << R->getName() << "Attr : EnumAttr {\n";
OS << " static enum Attribute::AttrKind getKind() {\n";
OS << " return llvm::Attribute::" << R->getName() << ";\n";
OS << " }\n";
OS << "};\n";
}
OS << "\n";
}
void Attributes::printStrBoolAttrClasses(raw_ostream &OS,
const std::vector<Record *> &Records) {
OS << "// StrBoolAttr classes\n";
for (const auto *R : Records) {
OS << "struct " << R->getName() << "Attr : StrBoolAttr {\n";
OS << " static StringRef getKind() {\n";
OS << " return \"" << R->getValueAsString("AttrString") << "\";\n";
OS << " }\n";
OS << "};\n";
}
OS << "\n";
}
void Attributes::emit(raw_ostream &OS) {
emitTargetIndependentEnums(OS);
emitConversionFn(OS);
emitFnAttrCompatCheck(OS, false);
}
namespace llvm {
void EmitAttributes(RecordKeeper &RK, raw_ostream &OS) {
Attributes(RK).emit(OS);
}
} // End llvm namespace.

View File

@ -1,48 +0,0 @@
set(LLVM_LINK_COMPONENTS Support)
add_tablegen(llvm-tblgen LLVM
AsmMatcherEmitter.cpp
AsmWriterEmitter.cpp
AsmWriterInst.cpp
Attributes.cpp
CallingConvEmitter.cpp
CodeEmitterGen.cpp
CodeGenDAGPatterns.cpp
CodeGenHwModes.cpp
CodeGenInstruction.cpp
CodeGenMapTable.cpp
CodeGenRegisters.cpp
CodeGenSchedule.cpp
CodeGenTarget.cpp
DAGISelEmitter.cpp
DAGISelMatcherEmitter.cpp
DAGISelMatcherGen.cpp
DAGISelMatcherOpt.cpp
DAGISelMatcher.cpp
DFAPacketizerEmitter.cpp
DisassemblerEmitter.cpp
FastISelEmitter.cpp
FixedLenDecoderEmitter.cpp
GlobalISelEmitter.cpp
InfoByHwMode.cpp
InstrInfoEmitter.cpp
InstrDocsEmitter.cpp
IntrinsicEmitter.cpp
OptParserEmitter.cpp
PseudoLoweringEmitter.cpp
RegisterBankEmitter.cpp
RegisterInfoEmitter.cpp
SDNodeProperties.cpp
SearchableTableEmitter.cpp
SubtargetEmitter.cpp
SubtargetFeatureInfo.cpp
TableGen.cpp
Types.cpp
X86DisassemblerTables.cpp
X86EVEX2VEXTablesEmitter.cpp
X86FoldTablesEmitter.cpp
X86ModRMFilters.cpp
X86RecognizableInstr.cpp
CTagsEmitter.cpp
)
set_target_properties(llvm-tblgen PROPERTIES FOLDER "Tablegenning")

View File

@ -1,87 +0,0 @@
//===- CTagsEmitter.cpp - Generate ctags-compatible index ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend emits an index of definitions in ctags(1) format.
// A helper script, utils/TableGen/tdtags, provides an easier-to-use
// interface; run 'tdtags -H' for documentation.
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include <algorithm>
#include <string>
#include <vector>
using namespace llvm;
#define DEBUG_TYPE "ctags-emitter"
namespace {
class Tag {
private:
const std::string *Id;
SMLoc Loc;
public:
Tag(const std::string &Name, const SMLoc Location)
: Id(&Name), Loc(Location) {}
int operator<(const Tag &B) const { return *Id < *B.Id; }
void emit(raw_ostream &OS) const {
const MemoryBuffer *CurMB =
SrcMgr.getMemoryBuffer(SrcMgr.FindBufferContainingLoc(Loc));
auto BufferName = CurMB->getBufferIdentifier();
std::pair<unsigned, unsigned> LineAndColumn = SrcMgr.getLineAndColumn(Loc);
OS << *Id << "\t" << BufferName << "\t" << LineAndColumn.first << "\n";
}
};
class CTagsEmitter {
private:
RecordKeeper &Records;
public:
CTagsEmitter(RecordKeeper &R) : Records(R) {}
void run(raw_ostream &OS);
private:
static SMLoc locate(const Record *R);
};
} // End anonymous namespace.
SMLoc CTagsEmitter::locate(const Record *R) {
ArrayRef<SMLoc> Locs = R->getLoc();
return !Locs.empty() ? Locs.front() : SMLoc();
}
void CTagsEmitter::run(raw_ostream &OS) {
const auto &Classes = Records.getClasses();
const auto &Defs = Records.getDefs();
std::vector<Tag> Tags;
// Collect tags.
Tags.reserve(Classes.size() + Defs.size());
for (const auto &C : Classes)
Tags.push_back(Tag(C.first, locate(C.second.get())));
for (const auto &D : Defs)
Tags.push_back(Tag(D.first, locate(D.second.get())));
// Emit tags.
std::sort(Tags.begin(), Tags.end());
OS << "!_TAG_FILE_FORMAT\t1\t/original ctags format/\n";
OS << "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted, 2=foldcase/\n";
for (const Tag &T : Tags)
T.emit(OS);
}
namespace llvm {
void EmitCTags(RecordKeeper &RK, raw_ostream &OS) { CTagsEmitter(RK).run(OS); }
} // End llvm namespace.

View File

@ -1,284 +0,0 @@
//===- CallingConvEmitter.cpp - Generate calling conventions --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting descriptions of the calling
// conventions supported by this target.
//
//===----------------------------------------------------------------------===//
#include "CodeGenTarget.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <cassert>
using namespace llvm;
namespace {
class CallingConvEmitter {
RecordKeeper &Records;
public:
explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {}
void run(raw_ostream &o);
private:
void EmitCallingConv(Record *CC, raw_ostream &O);
void EmitAction(Record *Action, unsigned Indent, raw_ostream &O);
unsigned Counter;
};
} // End anonymous namespace
void CallingConvEmitter::run(raw_ostream &O) {
std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv");
// Emit prototypes for all of the non-custom CC's so that they can forward ref
// each other.
for (Record *CC : CCs) {
if (!CC->getValueAsBit("Custom")) {
O << "static bool " << CC->getName()
<< "(unsigned ValNo, MVT ValVT,\n"
<< std::string(CC->getName().size() + 13, ' ')
<< "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
<< std::string(CC->getName().size() + 13, ' ')
<< "ISD::ArgFlagsTy ArgFlags, CCState &State);\n";
}
}
// Emit each non-custom calling convention description in full.
for (Record *CC : CCs) {
if (!CC->getValueAsBit("Custom"))
EmitCallingConv(CC, O);
}
}
void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) {
ListInit *CCActions = CC->getValueAsListInit("Actions");
Counter = 0;
O << "\n\nstatic bool " << CC->getName()
<< "(unsigned ValNo, MVT ValVT,\n"
<< std::string(CC->getName().size()+13, ' ')
<< "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
<< std::string(CC->getName().size()+13, ' ')
<< "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n";
// Emit all of the actions, in order.
for (unsigned i = 0, e = CCActions->size(); i != e; ++i) {
O << "\n";
EmitAction(CCActions->getElementAsRecord(i), 2, O);
}
O << "\n return true; // CC didn't match.\n";
O << "}\n";
}
void CallingConvEmitter::EmitAction(Record *Action,
unsigned Indent, raw_ostream &O) {
std::string IndentStr = std::string(Indent, ' ');
if (Action->isSubClassOf("CCPredicateAction")) {
O << IndentStr << "if (";
if (Action->isSubClassOf("CCIfType")) {
ListInit *VTs = Action->getValueAsListInit("VTs");
for (unsigned i = 0, e = VTs->size(); i != e; ++i) {
Record *VT = VTs->getElementAsRecord(i);
if (i != 0) O << " ||\n " << IndentStr;
O << "LocVT == " << getEnumName(getValueType(VT));
}
} else if (Action->isSubClassOf("CCIf")) {
O << Action->getValueAsString("Predicate");
} else {
errs() << *Action;
PrintFatalError("Unknown CCPredicateAction!");
}
O << ") {\n";
EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O);
O << IndentStr << "}\n";
} else {
if (Action->isSubClassOf("CCDelegateTo")) {
Record *CC = Action->getValueAsDef("CC");
O << IndentStr << "if (!" << CC->getName()
<< "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n"
<< IndentStr << " return false;\n";
} else if (Action->isSubClassOf("CCAssignToReg")) {
ListInit *RegList = Action->getValueAsListInit("RegList");
if (RegList->size() == 1) {
O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n";
} else {
O << IndentStr << "static const MCPhysReg RegList" << ++Counter
<< "[] = {\n";
O << IndentStr << " ";
for (unsigned i = 0, e = RegList->size(); i != e; ++i) {
if (i != 0) O << ", ";
O << getQualifiedName(RegList->getElementAsRecord(i));
}
O << "\n" << IndentStr << "};\n";
O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
<< Counter << ")) {\n";
}
O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
<< "Reg, LocVT, LocInfo));\n";
O << IndentStr << " return false;\n";
O << IndentStr << "}\n";
} else if (Action->isSubClassOf("CCAssignToRegWithShadow")) {
ListInit *RegList = Action->getValueAsListInit("RegList");
ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size())
PrintFatalError("Invalid length of list of shadowed registers");
if (RegList->size() == 1) {
O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
O << getQualifiedName(RegList->getElementAsRecord(0));
O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0));
O << ")) {\n";
} else {
unsigned RegListNumber = ++Counter;
unsigned ShadowRegListNumber = ++Counter;
O << IndentStr << "static const MCPhysReg RegList" << RegListNumber
<< "[] = {\n";
O << IndentStr << " ";
for (unsigned i = 0, e = RegList->size(); i != e; ++i) {
if (i != 0) O << ", ";
O << getQualifiedName(RegList->getElementAsRecord(i));
}
O << "\n" << IndentStr << "};\n";
O << IndentStr << "static const MCPhysReg RegList"
<< ShadowRegListNumber << "[] = {\n";
O << IndentStr << " ";
for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) {
if (i != 0) O << ", ";
O << getQualifiedName(ShadowRegList->getElementAsRecord(i));
}
O << "\n" << IndentStr << "};\n";
O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
<< RegListNumber << ", " << "RegList" << ShadowRegListNumber
<< ")) {\n";
}
O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
<< "Reg, LocVT, LocInfo));\n";
O << IndentStr << " return false;\n";
O << IndentStr << "}\n";
} else if (Action->isSubClassOf("CCAssignToStack")) {
int Size = Action->getValueAsInt("Size");
int Align = Action->getValueAsInt("Align");
O << IndentStr << "unsigned Offset" << ++Counter
<< " = State.AllocateStack(";
if (Size)
O << Size << ", ";
else
O << "\n" << IndentStr
<< " State.getMachineFunction().getDataLayout()."
"getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"
" ";
if (Align)
O << Align;
else
O << "\n" << IndentStr
<< " State.getMachineFunction().getDataLayout()."
"getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()"
"))";
O << ");\n" << IndentStr
<< "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
<< Counter << ", LocVT, LocInfo));\n";
O << IndentStr << "return false;\n";
} else if (Action->isSubClassOf("CCAssignToStackWithShadow")) {
int Size = Action->getValueAsInt("Size");
int Align = Action->getValueAsInt("Align");
ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
unsigned ShadowRegListNumber = ++Counter;
O << IndentStr << "static const MCPhysReg ShadowRegList"
<< ShadowRegListNumber << "[] = {\n";
O << IndentStr << " ";
for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) {
if (i != 0) O << ", ";
O << getQualifiedName(ShadowRegList->getElementAsRecord(i));
}
O << "\n" << IndentStr << "};\n";
O << IndentStr << "unsigned Offset" << ++Counter
<< " = State.AllocateStack("
<< Size << ", " << Align << ", "
<< "ShadowRegList" << ShadowRegListNumber << ");\n";
O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
<< Counter << ", LocVT, LocInfo));\n";
O << IndentStr << "return false;\n";
} else if (Action->isSubClassOf("CCPromoteToType")) {
Record *DestTy = Action->getValueAsDef("DestTy");
MVT::SimpleValueType DestVT = getValueType(DestTy);
O << IndentStr << "LocVT = " << getEnumName(DestVT) <<";\n";
if (MVT(DestVT).isFloatingPoint()) {
O << IndentStr << "LocInfo = CCValAssign::FPExt;\n";
} else {
O << IndentStr << "if (ArgFlags.isSExt())\n"
<< IndentStr << IndentStr << "LocInfo = CCValAssign::SExt;\n"
<< IndentStr << "else if (ArgFlags.isZExt())\n"
<< IndentStr << IndentStr << "LocInfo = CCValAssign::ZExt;\n"
<< IndentStr << "else\n"
<< IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n";
}
} else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) {
Record *DestTy = Action->getValueAsDef("DestTy");
MVT::SimpleValueType DestVT = getValueType(DestTy);
O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n";
if (MVT(DestVT).isFloatingPoint()) {
PrintFatalError("CCPromoteToUpperBitsInType does not handle floating "
"point");
} else {
O << IndentStr << "if (ArgFlags.isSExt())\n"
<< IndentStr << IndentStr << "LocInfo = CCValAssign::SExtUpper;\n"
<< IndentStr << "else if (ArgFlags.isZExt())\n"
<< IndentStr << IndentStr << "LocInfo = CCValAssign::ZExtUpper;\n"
<< IndentStr << "else\n"
<< IndentStr << IndentStr << "LocInfo = CCValAssign::AExtUpper;\n";
}
} else if (Action->isSubClassOf("CCBitConvertToType")) {
Record *DestTy = Action->getValueAsDef("DestTy");
O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
O << IndentStr << "LocInfo = CCValAssign::BCvt;\n";
} else if (Action->isSubClassOf("CCPassIndirect")) {
Record *DestTy = Action->getValueAsDef("DestTy");
O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
O << IndentStr << "LocInfo = CCValAssign::Indirect;\n";
} else if (Action->isSubClassOf("CCPassByVal")) {
int Size = Action->getValueAsInt("Size");
int Align = Action->getValueAsInt("Align");
O << IndentStr
<< "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, "
<< Size << ", " << Align << ", ArgFlags);\n";
O << IndentStr << "return false;\n";
} else if (Action->isSubClassOf("CCCustom")) {
O << IndentStr
<< "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, "
<< "LocVT, LocInfo, ArgFlags, State))\n";
O << IndentStr << IndentStr << "return false;\n";
} else {
errs() << *Action;
PrintFatalError("Unknown CCAction!");
}
}
}
namespace llvm {
void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS) {
emitSourceFileHeader("Calling Convention Implementation Fragment", OS);
CallingConvEmitter(RK).run(OS);
}
} // End llvm namespace

View File

@ -1,394 +0,0 @@
//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// CodeEmitterGen uses the descriptions of instructions and their fields to
// construct an automated code emitter: a function that, given a MachineInstr,
// returns the (currently, 32-bit unsigned) value of the instruction.
//
//===----------------------------------------------------------------------===//
#include "CodeGenInstruction.h"
#include "CodeGenTarget.h"
#include "SubtargetFeatureInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <cassert>
#include <cstdint>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>
using namespace llvm;
namespace {
class CodeEmitterGen {
RecordKeeper &Records;
public:
CodeEmitterGen(RecordKeeper &R) : Records(R) {}
void run(raw_ostream &o);
private:
int getVariableBit(const std::string &VarName, BitsInit *BI, int bit);
std::string getInstructionCase(Record *R, CodeGenTarget &Target);
void AddCodeToMergeInOperand(Record *R, BitsInit *BI,
const std::string &VarName,
unsigned &NumberedOp,
std::set<unsigned> &NamedOpIndices,
std::string &Case, CodeGenTarget &Target);
};
// If the VarBitInit at position 'bit' matches the specified variable then
// return the variable bit position. Otherwise return -1.
int CodeEmitterGen::getVariableBit(const std::string &VarName,
BitsInit *BI, int bit) {
if (VarBitInit *VBI = dyn_cast<VarBitInit>(BI->getBit(bit))) {
if (VarInit *VI = dyn_cast<VarInit>(VBI->getBitVar()))
if (VI->getName() == VarName)
return VBI->getBitNum();
} else if (VarInit *VI = dyn_cast<VarInit>(BI->getBit(bit))) {
if (VI->getName() == VarName)
return 0;
}
return -1;
}
void CodeEmitterGen::
AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
unsigned &NumberedOp,
std::set<unsigned> &NamedOpIndices,
std::string &Case, CodeGenTarget &Target) {
CodeGenInstruction &CGI = Target.getInstruction(R);
// Determine if VarName actually contributes to the Inst encoding.
int bit = BI->getNumBits()-1;
// Scan for a bit that this contributed to.
for (; bit >= 0; ) {
if (getVariableBit(VarName, BI, bit) != -1)
break;
--bit;
}
// If we found no bits, ignore this value, otherwise emit the call to get the
// operand encoding.
if (bit < 0) return;
// If the operand matches by name, reference according to that
// operand number. Non-matching operands are assumed to be in
// order.
unsigned OpIdx;
if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) {
// Get the machine operand number for the indicated operand.
OpIdx = CGI.Operands[OpIdx].MIOperandNo;
assert(!CGI.Operands.isFlatOperandNotEmitted(OpIdx) &&
"Explicitly used operand also marked as not emitted!");
} else {
unsigned NumberOps = CGI.Operands.size();
/// If this operand is not supposed to be emitted by the
/// generated emitter, skip it.
while (NumberedOp < NumberOps &&
(CGI.Operands.isFlatOperandNotEmitted(NumberedOp) ||
(!NamedOpIndices.empty() && NamedOpIndices.count(
CGI.Operands.getSubOperandNumber(NumberedOp).first)))) {
++NumberedOp;
if (NumberedOp >= CGI.Operands.back().MIOperandNo +
CGI.Operands.back().MINumOperands) {
errs() << "Too few operands in record " << R->getName() <<
" (no match for variable " << VarName << "):\n";
errs() << *R;
errs() << '\n';
return;
}
}
OpIdx = NumberedOp++;
}
std::pair<unsigned, unsigned> SO = CGI.Operands.getSubOperandNumber(OpIdx);
std::string &EncoderMethodName = CGI.Operands[SO.first].EncoderMethodName;
// If the source operand has a custom encoder, use it. This will
// get the encoding for all of the suboperands.
if (!EncoderMethodName.empty()) {
// A custom encoder has all of the information for the
// sub-operands, if there are more than one, so only
// query the encoder once per source operand.
if (SO.second == 0) {
Case += " // op: " + VarName + "\n" +
" op = " + EncoderMethodName + "(MI, " + utostr(OpIdx);
Case += ", Fixups, STI";
Case += ");\n";
}
} else {
Case += " // op: " + VarName + "\n" +
" op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
Case += ", Fixups, STI";
Case += ");\n";
}
for (; bit >= 0; ) {
int varBit = getVariableBit(VarName, BI, bit);
// If this bit isn't from a variable, skip it.
if (varBit == -1) {
--bit;
continue;
}
// Figure out the consecutive range of bits covered by this operand, in
// order to generate better encoding code.
int beginInstBit = bit;
int beginVarBit = varBit;
int N = 1;
for (--bit; bit >= 0;) {
varBit = getVariableBit(VarName, BI, bit);
if (varBit == -1 || varBit != (beginVarBit - N)) break;
++N;
--bit;
}
uint64_t opMask = ~(uint64_t)0 >> (64-N);
int opShift = beginVarBit - N + 1;
opMask <<= opShift;
opShift = beginInstBit - beginVarBit;
if (opShift > 0) {
Case += " Value |= (op & UINT64_C(" + utostr(opMask) + ")) << " +
itostr(opShift) + ";\n";
} else if (opShift < 0) {
Case += " Value |= (op & UINT64_C(" + utostr(opMask) + ")) >> " +
itostr(-opShift) + ";\n";
} else {
Case += " Value |= op & UINT64_C(" + utostr(opMask) + ");\n";
}
}
}
std::string CodeEmitterGen::getInstructionCase(Record *R,
CodeGenTarget &Target) {
std::string Case;
BitsInit *BI = R->getValueAsBitsInit("Inst");
unsigned NumberedOp = 0;
std::set<unsigned> NamedOpIndices;
// Collect the set of operand indices that might correspond to named
// operand, and skip these when assigning operands based on position.
if (Target.getInstructionSet()->
getValueAsBit("noNamedPositionallyEncodedOperands")) {
CodeGenInstruction &CGI = Target.getInstruction(R);
for (const RecordVal &RV : R->getValues()) {
unsigned OpIdx;
if (!CGI.Operands.hasOperandNamed(RV.getName(), OpIdx))
continue;
NamedOpIndices.insert(OpIdx);
}
}
// Loop over all of the fields in the instruction, determining which are the
// operands to the instruction.
for (const RecordVal &RV : R->getValues()) {
// Ignore fixed fields in the record, we're looking for values like:
// bits<5> RST = { ?, ?, ?, ?, ? };
if (RV.getPrefix() || RV.getValue()->isComplete())
continue;
AddCodeToMergeInOperand(R, BI, RV.getName(), NumberedOp,
NamedOpIndices, Case, Target);
}
StringRef PostEmitter = R->getValueAsString("PostEncoderMethod");
if (!PostEmitter.empty()) {
Case += " Value = ";
Case += PostEmitter;
Case += "(MI, Value";
Case += ", STI";
Case += ");\n";
}
return Case;
}
void CodeEmitterGen::run(raw_ostream &o) {
CodeGenTarget Target(Records);
std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
// For little-endian instruction bit encodings, reverse the bit order
Target.reverseBitsForLittleEndianEncoding();
ArrayRef<const CodeGenInstruction*> NumberedInstructions =
Target.getInstructionsByEnumValue();
// Emit function declaration
o << "uint64_t " << Target.getName();
o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
<< " SmallVectorImpl<MCFixup> &Fixups,\n"
<< " const MCSubtargetInfo &STI) const {\n";
// Emit instruction base values
o << " static const uint64_t InstBits[] = {\n";
for (const CodeGenInstruction *CGI : NumberedInstructions) {
Record *R = CGI->TheDef;
if (R->getValueAsString("Namespace") == "TargetOpcode" ||
R->getValueAsBit("isPseudo")) {
o << " UINT64_C(0),\n";
continue;
}
BitsInit *BI = R->getValueAsBitsInit("Inst");
// Start by filling in fixed values.
uint64_t Value = 0;
for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
if (BitInit *B = dyn_cast<BitInit>(BI->getBit(e-i-1)))
Value |= (uint64_t)B->getValue() << (e-i-1);
}
o << " UINT64_C(" << Value << ")," << '\t' << "// " << R->getName() << "\n";
}
o << " UINT64_C(0)\n };\n";
// Map to accumulate all the cases.
std::map<std::string, std::vector<std::string>> CaseMap;
// Construct all cases statement for each opcode
for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end();
IC != EC; ++IC) {
Record *R = *IC;
if (R->getValueAsString("Namespace") == "TargetOpcode" ||
R->getValueAsBit("isPseudo"))
continue;
std::string InstName =
(R->getValueAsString("Namespace") + "::" + R->getName()).str();
std::string Case = getInstructionCase(R, Target);
CaseMap[Case].push_back(std::move(InstName));
}
// Emit initial function code
o << " const unsigned opcode = MI.getOpcode();\n"
<< " uint64_t Value = InstBits[opcode];\n"
<< " uint64_t op = 0;\n"
<< " (void)op; // suppress warning\n"
<< " switch (opcode) {\n";
// Emit each case statement
std::map<std::string, std::vector<std::string>>::iterator IE, EE;
for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) {
const std::string &Case = IE->first;
std::vector<std::string> &InstList = IE->second;
for (int i = 0, N = InstList.size(); i < N; i++) {
if (i) o << "\n";
o << " case " << InstList[i] << ":";
}
o << " {\n";
o << Case;
o << " break;\n"
<< " }\n";
}
// Default case: unhandled opcode
o << " default:\n"
<< " std::string msg;\n"
<< " raw_string_ostream Msg(msg);\n"
<< " Msg << \"Not supported instr: \" << MI;\n"
<< " report_fatal_error(Msg.str());\n"
<< " }\n"
<< " return Value;\n"
<< "}\n\n";
const auto &All = SubtargetFeatureInfo::getAll(Records);
std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;
SubtargetFeatures.insert(All.begin(), All.end());
o << "#ifdef ENABLE_INSTR_PREDICATE_VERIFIER\n"
<< "#undef ENABLE_INSTR_PREDICATE_VERIFIER\n"
<< "#include <sstream>\n\n";
// Emit the subtarget feature enumeration.
SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(SubtargetFeatures,
o);
// Emit the name table for error messages.
o << "#ifndef NDEBUG\n";
SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, o);
o << "#endif // NDEBUG\n";
// Emit the available features compute function.
SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
Target.getName(), "MCCodeEmitter", "computeAvailableFeatures",
SubtargetFeatures, o);
// Emit the predicate verifier.
o << "void " << Target.getName()
<< "MCCodeEmitter::verifyInstructionPredicates(\n"
<< " const MCInst &Inst, uint64_t AvailableFeatures) const {\n"
<< "#ifndef NDEBUG\n"
<< " static uint64_t RequiredFeatures[] = {\n";
unsigned InstIdx = 0;
for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
o << " ";
for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) {
const auto &I = SubtargetFeatures.find(Predicate);
if (I != SubtargetFeatures.end())
o << I->second.getEnumName() << " | ";
}
o << "0, // " << Inst->TheDef->getName() << " = " << InstIdx << "\n";
InstIdx++;
}
o << " };\n\n";
o << " assert(Inst.getOpcode() < " << InstIdx << ");\n";
o << " uint64_t MissingFeatures =\n"
<< " (AvailableFeatures & RequiredFeatures[Inst.getOpcode()]) ^\n"
<< " RequiredFeatures[Inst.getOpcode()];\n"
<< " if (MissingFeatures) {\n"
<< " std::ostringstream Msg;\n"
<< " Msg << \"Attempting to emit \" << "
"MCII.getName(Inst.getOpcode()).str()\n"
<< " << \" instruction but the \";\n"
<< " for (unsigned i = 0; i < 8 * sizeof(MissingFeatures); ++i)\n"
<< " if (MissingFeatures & (1ULL << i))\n"
<< " Msg << SubtargetFeatureNames[i] << \" \";\n"
<< " Msg << \"predicate(s) are not met\";\n"
<< " report_fatal_error(Msg.str());\n"
<< " }\n"
<< "#else\n"
<< "// Silence unused variable warning on targets that don't use MCII for "
"other purposes (e.g. BPF).\n"
<< "(void)MCII;\n"
<< "#endif // NDEBUG\n";
o << "}\n";
o << "#endif\n";
}
} // end anonymous namespace
namespace llvm {
void EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS) {
emitSourceFileHeader("Machine Code Emitter", OS);
CodeEmitterGen(RK).run(OS);
}
} // end namespace llvm

View File

@ -1 +0,0 @@
493066ec234b229cecb5d2c07515298a0f676b6e

File diff suppressed because it is too large Load Diff

View File

@ -1,114 +0,0 @@
//===--- CodeGenHwModes.cpp -----------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Classes to parse and store HW mode information for instruction selection
//===----------------------------------------------------------------------===//
#include "CodeGenHwModes.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
using namespace llvm;
StringRef CodeGenHwModes::DefaultModeName = "DefaultMode";
HwMode::HwMode(Record *R) {
Name = R->getName();
Features = R->getValueAsString("Features");
}
LLVM_DUMP_METHOD
void HwMode::dump() const {
dbgs() << Name << ": " << Features << '\n';
}
HwModeSelect::HwModeSelect(Record *R, CodeGenHwModes &CGH) {
std::vector<Record*> Modes = R->getValueAsListOfDefs("Modes");
std::vector<Record*> Objects = R->getValueAsListOfDefs("Objects");
if (Modes.size() != Objects.size()) {
PrintError(R->getLoc(), "in record " + R->getName() +
" derived from HwModeSelect: the lists Modes and Objects should "
"have the same size");
report_fatal_error("error in target description.");
}
for (unsigned i = 0, e = Modes.size(); i != e; ++i) {
unsigned ModeId = CGH.getHwModeId(Modes[i]->getName());
Items.push_back(std::make_pair(ModeId, Objects[i]));
}
}
LLVM_DUMP_METHOD
void HwModeSelect::dump() const {
dbgs() << '{';
for (const PairType &P : Items)
dbgs() << " (" << P.first << ',' << P.second->getName() << ')';
dbgs() << " }\n";
}
CodeGenHwModes::CodeGenHwModes(RecordKeeper &RK) : Records(RK) {
std::vector<Record*> MRs = Records.getAllDerivedDefinitions("HwMode");
// The default mode needs a definition in the .td sources for TableGen
// to accept references to it. We need to ignore the definition here.
for (auto I = MRs.begin(), E = MRs.end(); I != E; ++I) {
if ((*I)->getName() != DefaultModeName)
continue;
MRs.erase(I);
break;
}
for (Record *R : MRs) {
Modes.emplace_back(R);
unsigned NewId = Modes.size();
ModeIds.insert(std::make_pair(Modes[NewId-1].Name, NewId));
}
std::vector<Record*> MSs = Records.getAllDerivedDefinitions("HwModeSelect");
for (Record *R : MSs) {
auto P = ModeSelects.emplace(std::make_pair(R, HwModeSelect(R, *this)));
assert(P.second);
(void)P;
}
}
unsigned CodeGenHwModes::getHwModeId(StringRef Name) const {
if (Name == DefaultModeName)
return DefaultMode;
auto F = ModeIds.find(Name);
assert(F != ModeIds.end() && "Unknown mode name");
return F->second;
}
const HwModeSelect &CodeGenHwModes::getHwModeSelect(Record *R) const {
auto F = ModeSelects.find(R);
assert(F != ModeSelects.end() && "Record is not a \"mode select\"");
return F->second;
}
LLVM_DUMP_METHOD
void CodeGenHwModes::dump() const {
dbgs() << "Modes: {\n";
for (const HwMode &M : Modes) {
dbgs() << " ";
M.dump();
}
dbgs() << "}\n";
dbgs() << "ModeIds: {\n";
for (const auto &P : ModeIds)
dbgs() << " " << P.first() << " -> " << P.second << '\n';
dbgs() << "}\n";
dbgs() << "ModeSelects: {\n";
for (const auto &P : ModeSelects) {
dbgs() << " " << P.first->getName() << " -> ";
P.second.dump();
}
dbgs() << "}\n";
}

View File

@ -1,64 +0,0 @@
//===--- CodeGenHwModes.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Classes to parse and store HW mode information for instruction selection.
//===----------------------------------------------------------------------===//
#ifndef LLVM_UTILS_TABLEGEN_CODEGENHWMODES_H
#define LLVM_UTILS_TABLEGEN_CODEGENHWMODES_H
#include "llvm/ADT/StringMap.h"
#include <map>
#include <string>
#include <vector>
// HwModeId -> list of predicates (definition)
namespace llvm {
class Record;
class RecordKeeper;
struct CodeGenHwModes;
struct HwMode {
HwMode(Record *R);
StringRef Name;
std::string Features;
void dump() const;
};
struct HwModeSelect {
HwModeSelect(Record *R, CodeGenHwModes &CGH);
typedef std::pair<unsigned, Record*> PairType;
std::vector<PairType> Items;
void dump() const;
};
struct CodeGenHwModes {
enum : unsigned { DefaultMode = 0 };
static StringRef DefaultModeName;
CodeGenHwModes(RecordKeeper &R);
unsigned getHwModeId(StringRef Name) const;
const HwMode &getMode(unsigned Id) const {
assert(Id != 0 && "Mode id of 0 is reserved for the default mode");
return Modes[Id-1];
}
const HwModeSelect &getHwModeSelect(Record *R) const;
unsigned getNumModeIds() const { return Modes.size()+1; }
void dump() const;
private:
RecordKeeper &Records;
StringMap<unsigned> ModeIds; // HwMode (string) -> HwModeId
std::vector<HwMode> Modes;
std::map<Record*,HwModeSelect> ModeSelects;
};
}
#endif // LLVM_UTILS_TABLEGEN_CODEGENHWMODES_H

File diff suppressed because it is too large Load Diff

View File

@ -1,361 +0,0 @@
//===- CodeGenInstruction.h - Instruction Class Wrapper ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a wrapper class for the 'Instruction' TableGen class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H
#define LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/Support/SMLoc.h"
#include <string>
#include <utility>
#include <vector>
namespace llvm {
template <typename T> class ArrayRef;
class Record;
class DagInit;
class CodeGenTarget;
class CGIOperandList {
public:
class ConstraintInfo {
enum { None, EarlyClobber, Tied } Kind;
unsigned OtherTiedOperand;
public:
ConstraintInfo() : Kind(None) {}
static ConstraintInfo getEarlyClobber() {
ConstraintInfo I;
I.Kind = EarlyClobber;
I.OtherTiedOperand = 0;
return I;
}
static ConstraintInfo getTied(unsigned Op) {
ConstraintInfo I;
I.Kind = Tied;
I.OtherTiedOperand = Op;
return I;
}
bool isNone() const { return Kind == None; }
bool isEarlyClobber() const { return Kind == EarlyClobber; }
bool isTied() const { return Kind == Tied; }
unsigned getTiedOperand() const {
assert(isTied());
return OtherTiedOperand;
}
};
/// OperandInfo - The information we keep track of for each operand in the
/// operand list for a tablegen instruction.
struct OperandInfo {
/// Rec - The definition this operand is declared as.
///
Record *Rec;
/// Name - If this operand was assigned a symbolic name, this is it,
/// otherwise, it's empty.
std::string Name;
/// PrinterMethodName - The method used to print operands of this type in
/// the asmprinter.
std::string PrinterMethodName;
/// EncoderMethodName - The method used to get the machine operand value
/// for binary encoding. "getMachineOpValue" by default.
std::string EncoderMethodName;
/// OperandType - A value from MCOI::OperandType representing the type of
/// the operand.
std::string OperandType;
/// MIOperandNo - Currently (this is meant to be phased out), some logical
/// operands correspond to multiple MachineInstr operands. In the X86
/// target for example, one address operand is represented as 4
/// MachineOperands. Because of this, the operand number in the
/// OperandList may not match the MachineInstr operand num. Until it
/// does, this contains the MI operand index of this operand.
unsigned MIOperandNo;
unsigned MINumOperands; // The number of operands.
/// DoNotEncode - Bools are set to true in this vector for each operand in
/// the DisableEncoding list. These should not be emitted by the code
/// emitter.
std::vector<bool> DoNotEncode;
/// MIOperandInfo - Default MI operand type. Note an operand may be made
/// up of multiple MI operands.
DagInit *MIOperandInfo;
/// Constraint info for this operand. This operand can have pieces, so we
/// track constraint info for each.
std::vector<ConstraintInfo> Constraints;
OperandInfo(Record *R, const std::string &N, const std::string &PMN,
const std::string &EMN, const std::string &OT, unsigned MION,
unsigned MINO, DagInit *MIOI)
: Rec(R), Name(N), PrinterMethodName(PMN), EncoderMethodName(EMN),
OperandType(OT), MIOperandNo(MION), MINumOperands(MINO),
MIOperandInfo(MIOI) {}
/// getTiedOperand - If this operand is tied to another one, return the
/// other operand number. Otherwise, return -1.
int getTiedRegister() const {
for (unsigned j = 0, e = Constraints.size(); j != e; ++j) {
const CGIOperandList::ConstraintInfo &CI = Constraints[j];
if (CI.isTied()) return CI.getTiedOperand();
}
return -1;
}
};
CGIOperandList(Record *D);
Record *TheDef; // The actual record containing this OperandList.
/// NumDefs - Number of def operands declared, this is the number of
/// elements in the instruction's (outs) list.
///
unsigned NumDefs;
/// OperandList - The list of declared operands, along with their declared
/// type (which is a record).
std::vector<OperandInfo> OperandList;
// Information gleaned from the operand list.
bool isPredicable;
bool hasOptionalDef;
bool isVariadic;
// Provide transparent accessors to the operand list.
bool empty() const { return OperandList.empty(); }
unsigned size() const { return OperandList.size(); }
const OperandInfo &operator[](unsigned i) const { return OperandList[i]; }
OperandInfo &operator[](unsigned i) { return OperandList[i]; }
OperandInfo &back() { return OperandList.back(); }
const OperandInfo &back() const { return OperandList.back(); }
typedef std::vector<OperandInfo>::iterator iterator;
typedef std::vector<OperandInfo>::const_iterator const_iterator;
iterator begin() { return OperandList.begin(); }
const_iterator begin() const { return OperandList.begin(); }
iterator end() { return OperandList.end(); }
const_iterator end() const { return OperandList.end(); }
/// getOperandNamed - Return the index of the operand with the specified
/// non-empty name. If the instruction does not have an operand with the
/// specified name, abort.
unsigned getOperandNamed(StringRef Name) const;
/// hasOperandNamed - Query whether the instruction has an operand of the
/// given name. If so, return true and set OpIdx to the index of the
/// operand. Otherwise, return false.
bool hasOperandNamed(StringRef Name, unsigned &OpIdx) const;
/// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar",
/// where $foo is a whole operand and $foo.bar refers to a suboperand.
/// This aborts if the name is invalid. If AllowWholeOp is true, references
/// to operands with suboperands are allowed, otherwise not.
std::pair<unsigned,unsigned> ParseOperandName(const std::string &Op,
bool AllowWholeOp = true);
/// getFlattenedOperandNumber - Flatten a operand/suboperand pair into a
/// flat machineinstr operand #.
unsigned getFlattenedOperandNumber(std::pair<unsigned,unsigned> Op) const {
return OperandList[Op.first].MIOperandNo + Op.second;
}
/// getSubOperandNumber - Unflatten a operand number into an
/// operand/suboperand pair.
std::pair<unsigned,unsigned> getSubOperandNumber(unsigned Op) const {
for (unsigned i = 0; ; ++i) {
assert(i < OperandList.size() && "Invalid flat operand #");
if (OperandList[i].MIOperandNo+OperandList[i].MINumOperands > Op)
return std::make_pair(i, Op-OperandList[i].MIOperandNo);
}
}
/// isFlatOperandNotEmitted - Return true if the specified flat operand #
/// should not be emitted with the code emitter.
bool isFlatOperandNotEmitted(unsigned FlatOpNo) const {
std::pair<unsigned,unsigned> Op = getSubOperandNumber(FlatOpNo);
if (OperandList[Op.first].DoNotEncode.size() > Op.second)
return OperandList[Op.first].DoNotEncode[Op.second];
return false;
}
void ProcessDisableEncoding(std::string Value);
};
class CodeGenInstruction {
public:
Record *TheDef; // The actual record defining this instruction.
StringRef Namespace; // The namespace the instruction is in.
/// AsmString - The format string used to emit a .s file for the
/// instruction.
std::string AsmString;
/// Operands - This is information about the (ins) and (outs) list specified
/// to the instruction.
CGIOperandList Operands;
/// ImplicitDefs/ImplicitUses - These are lists of registers that are
/// implicitly defined and used by the instruction.
std::vector<Record*> ImplicitDefs, ImplicitUses;
// Various boolean values we track for the instruction.
bool isReturn : 1;
bool isBranch : 1;
bool isIndirectBranch : 1;
bool isCompare : 1;
bool isMoveImm : 1;
bool isBitcast : 1;
bool isSelect : 1;
bool isBarrier : 1;
bool isCall : 1;
bool isAdd : 1;
bool canFoldAsLoad : 1;
bool mayLoad : 1;
bool mayLoad_Unset : 1;
bool mayStore : 1;
bool mayStore_Unset : 1;
bool isPredicable : 1;
bool isConvertibleToThreeAddress : 1;
bool isCommutable : 1;
bool isTerminator : 1;
bool isReMaterializable : 1;
bool hasDelaySlot : 1;
bool usesCustomInserter : 1;
bool hasPostISelHook : 1;
bool hasCtrlDep : 1;
bool isNotDuplicable : 1;
bool hasSideEffects : 1;
bool hasSideEffects_Unset : 1;
bool isAsCheapAsAMove : 1;
bool hasExtraSrcRegAllocReq : 1;
bool hasExtraDefRegAllocReq : 1;
bool isCodeGenOnly : 1;
bool isPseudo : 1;
bool isRegSequence : 1;
bool isExtractSubreg : 1;
bool isInsertSubreg : 1;
bool isConvergent : 1;
bool hasNoSchedulingInfo : 1;
std::string DeprecatedReason;
bool HasComplexDeprecationPredicate;
/// Are there any undefined flags?
bool hasUndefFlags() const {
return mayLoad_Unset || mayStore_Unset || hasSideEffects_Unset;
}
// The record used to infer instruction flags, or NULL if no flag values
// have been inferred.
Record *InferredFrom;
CodeGenInstruction(Record *R);
/// HasOneImplicitDefWithKnownVT - If the instruction has at least one
/// implicit def and it has a known VT, return the VT, otherwise return
/// MVT::Other.
MVT::SimpleValueType
HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const;
/// FlattenAsmStringVariants - Flatten the specified AsmString to only
/// include text from the specified variant, returning the new string.
static std::string FlattenAsmStringVariants(StringRef AsmString,
unsigned Variant);
// Is the specified operand in a generic instruction implicitly a pointer.
// This can be used on intructions that use typeN or ptypeN to identify
// operands that should be considered as pointers even though SelectionDAG
// didn't make a distinction between integer and pointers.
bool isOperandAPointer(unsigned i) const;
};
/// CodeGenInstAlias - This represents an InstAlias definition.
class CodeGenInstAlias {
public:
Record *TheDef; // The actual record defining this InstAlias.
/// AsmString - The format string used to emit a .s file for the
/// instruction.
std::string AsmString;
/// Result - The result instruction.
DagInit *Result;
/// ResultInst - The instruction generated by the alias (decoded from
/// Result).
CodeGenInstruction *ResultInst;
struct ResultOperand {
private:
std::string Name;
Record *R;
int64_t Imm;
public:
enum {
K_Record,
K_Imm,
K_Reg
} Kind;
ResultOperand(std::string N, Record *r)
: Name(std::move(N)), R(r), Kind(K_Record) {}
ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {}
ResultOperand(Record *r) : R(r), Kind(K_Reg) {}
bool isRecord() const { return Kind == K_Record; }
bool isImm() const { return Kind == K_Imm; }
bool isReg() const { return Kind == K_Reg; }
StringRef getName() const { assert(isRecord()); return Name; }
Record *getRecord() const { assert(isRecord()); return R; }
int64_t getImm() const { assert(isImm()); return Imm; }
Record *getRegister() const { assert(isReg()); return R; }
unsigned getMINumOperands() const;
};
/// ResultOperands - The decoded operands for the result instruction.
std::vector<ResultOperand> ResultOperands;
/// ResultInstOperandIndex - For each operand, this vector holds a pair of
/// indices to identify the corresponding operand in the result
/// instruction. The first index specifies the operand and the second
/// index specifies the suboperand. If there are no suboperands or if all
/// of them are matched by the operand, the second value should be -1.
std::vector<std::pair<unsigned, int> > ResultInstOperandIndex;
CodeGenInstAlias(Record *R, unsigned Variant, CodeGenTarget &T);
bool tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
Record *InstOpRec, bool hasSubOps, ArrayRef<SMLoc> Loc,
CodeGenTarget &T, ResultOperand &ResOp);
};
}
#endif

View File

@ -1,170 +0,0 @@
//===- CodeGenIntrinsic.h - Intrinsic Class Wrapper ------------*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a wrapper class for the 'Intrinsic' TableGen class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H
#define LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H
#include "SDNodeProperties.h"
#include "llvm/CodeGen/MachineValueType.h"
#include <string>
#include <vector>
namespace llvm {
class Record;
class RecordKeeper;
class CodeGenTarget;
struct CodeGenIntrinsic {
Record *TheDef; // The actual record defining this intrinsic.
std::string Name; // The name of the LLVM function "llvm.bswap.i32"
std::string EnumName; // The name of the enum "bswap_i32"
std::string GCCBuiltinName; // Name of the corresponding GCC builtin, or "".
std::string MSBuiltinName; // Name of the corresponding MS builtin, or "".
std::string TargetPrefix; // Target prefix, e.g. "ppc" for t-s intrinsics.
/// This structure holds the return values and parameter values of an
/// intrinsic. If the number of return values is > 1, then the intrinsic
/// implicitly returns a first-class aggregate. The numbering of the types
/// starts at 0 with the first return value and continues from there through
/// the parameter list. This is useful for "matching" types.
struct IntrinsicSignature {
/// The MVT::SimpleValueType for each return type. Note that this list is
/// only populated when in the context of a target .td file. When building
/// Intrinsics.td, this isn't available, because we don't know the target
/// pointer size.
std::vector<MVT::SimpleValueType> RetVTs;
/// The records for each return type.
std::vector<Record *> RetTypeDefs;
/// The MVT::SimpleValueType for each parameter type. Note that this list is
/// only populated when in the context of a target .td file. When building
/// Intrinsics.td, this isn't available, because we don't know the target
/// pointer size.
std::vector<MVT::SimpleValueType> ParamVTs;
/// The records for each parameter type.
std::vector<Record *> ParamTypeDefs;
};
IntrinsicSignature IS;
/// Bit flags describing the type (ref/mod) and location of memory
/// accesses that may be performed by the intrinsics. Analogous to
/// \c FunctionModRefBehaviour.
enum ModRefBits {
/// The intrinsic may access memory that is otherwise inaccessible via
/// LLVM IR.
MR_InaccessibleMem = 1,
/// The intrinsic may access memory through pointer arguments.
/// LLVM IR.
MR_ArgMem = 2,
/// The intrinsic may access memory anywhere, i.e. it is not restricted
/// to access through pointer arguments.
MR_Anywhere = 4 | MR_ArgMem | MR_InaccessibleMem,
/// The intrinsic may read memory.
MR_Ref = 8,
/// The intrinsic may write memory.
MR_Mod = 16,
/// The intrinsic may both read and write memory.
MR_ModRef = MR_Ref | MR_Mod,
};
/// Memory mod/ref behavior of this intrinsic, corresponding to intrinsic
/// properties (IntrReadMem, IntrArgMemOnly, etc.).
enum ModRefBehavior {
NoMem = 0,
ReadArgMem = MR_Ref | MR_ArgMem,
ReadInaccessibleMem = MR_Ref | MR_InaccessibleMem,
ReadInaccessibleMemOrArgMem = MR_Ref | MR_ArgMem | MR_InaccessibleMem,
ReadMem = MR_Ref | MR_Anywhere,
WriteArgMem = MR_Mod | MR_ArgMem,
WriteInaccessibleMem = MR_Mod | MR_InaccessibleMem,
WriteInaccessibleMemOrArgMem = MR_Mod | MR_ArgMem | MR_InaccessibleMem,
WriteMem = MR_Mod | MR_Anywhere,
ReadWriteArgMem = MR_ModRef | MR_ArgMem,
ReadWriteInaccessibleMem = MR_ModRef | MR_InaccessibleMem,
ReadWriteInaccessibleMemOrArgMem = MR_ModRef | MR_ArgMem |
MR_InaccessibleMem,
ReadWriteMem = MR_ModRef | MR_Anywhere,
};
ModRefBehavior ModRef;
/// SDPatternOperator Properties applied to the intrinsic.
unsigned Properties;
/// This is set to true if the intrinsic is overloaded by its argument
/// types.
bool isOverloaded;
/// True if the intrinsic is commutative.
bool isCommutative;
/// True if the intrinsic can throw.
bool canThrow;
/// True if the intrinsic is marked as noduplicate.
bool isNoDuplicate;
/// True if the intrinsic is no-return.
bool isNoReturn;
/// True if the intrinsic is marked as convergent.
bool isConvergent;
/// True if the intrinsic has side effects that aren't captured by any
/// of the other flags.
bool hasSideEffects;
// True if the intrinsic is marked as speculatable.
bool isSpeculatable;
enum ArgAttribute { NoCapture, Returned, ReadOnly, WriteOnly, ReadNone };
std::vector<std::pair<unsigned, ArgAttribute>> ArgumentAttributes;
bool hasProperty(enum SDNP Prop) const {
return Properties & (1 << Prop);
}
CodeGenIntrinsic(Record *R);
};
class CodeGenIntrinsicTable {
std::vector<CodeGenIntrinsic> Intrinsics;
public:
struct TargetSet {
std::string Name;
size_t Offset;
size_t Count;
};
std::vector<TargetSet> Targets;
explicit CodeGenIntrinsicTable(const RecordKeeper &RC, bool TargetOnly);
CodeGenIntrinsicTable() = default;
bool empty() const { return Intrinsics.empty(); }
size_t size() const { return Intrinsics.size(); }
CodeGenIntrinsic &operator[](size_t Pos) { return Intrinsics[Pos]; }
const CodeGenIntrinsic &operator[](size_t Pos) const {
return Intrinsics[Pos];
}
};
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More