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,13 +0,0 @@
add_llvm_library(LLVMTableGen
Error.cpp
Main.cpp
Record.cpp
SetTheory.cpp
StringMatcher.cpp
TableGenBackend.cpp
TGLexer.cpp
TGParser.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/TableGen
)

View File

@ -1,84 +0,0 @@
//===- Error.cpp - tblgen error handling helper routines --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains error handling helper routines to pretty-print diagnostic
// messages from tblgen.
//
//===----------------------------------------------------------------------===//
#include "llvm/TableGen/Error.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
namespace llvm {
SourceMgr SrcMgr;
unsigned ErrorsPrinted = 0;
static void PrintMessage(ArrayRef<SMLoc> Loc, SourceMgr::DiagKind Kind,
const Twine &Msg) {
// Count the total number of errors printed.
// This is used to exit with an error code if there were any errors.
if (Kind == SourceMgr::DK_Error)
++ErrorsPrinted;
SMLoc NullLoc;
if (Loc.empty())
Loc = NullLoc;
SrcMgr.PrintMessage(Loc.front(), Kind, Msg);
for (unsigned i = 1; i < Loc.size(); ++i)
SrcMgr.PrintMessage(Loc[i], SourceMgr::DK_Note,
"instantiated from multiclass");
}
void PrintNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg) {
PrintMessage(NoteLoc, SourceMgr::DK_Note, Msg);
}
void PrintWarning(ArrayRef<SMLoc> WarningLoc, const Twine &Msg) {
PrintMessage(WarningLoc, SourceMgr::DK_Warning, Msg);
}
void PrintWarning(const char *Loc, const Twine &Msg) {
SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), SourceMgr::DK_Warning, Msg);
}
void PrintWarning(const Twine &Msg) {
errs() << "warning:" << Msg << "\n";
}
void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg) {
PrintMessage(ErrorLoc, SourceMgr::DK_Error, Msg);
}
void PrintError(const char *Loc, const Twine &Msg) {
SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), SourceMgr::DK_Error, Msg);
}
void PrintError(const Twine &Msg) {
errs() << "error:" << Msg << "\n";
}
void PrintFatalError(const Twine &Msg) {
PrintError(Msg);
// The following call runs the file cleanup handlers.
sys::RunInterruptHandlers();
std::exit(1);
}
void PrintFatalError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg) {
PrintError(ErrorLoc, Msg);
// The following call runs the file cleanup handlers.
sys::RunInterruptHandlers();
std::exit(1);
}
} // end namespace llvm

View File

@ -1,22 +0,0 @@
;===- ./lib/TableGen/LLVMBuild.txt -----------------------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[component_0]
type = Library
name = TableGen
parent = Libraries
required_libraries = Support

View File

@ -1,118 +0,0 @@
//===- Main.cpp - Top-Level TableGen implementation -----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// TableGen is a tool which can be used to build up a description of something,
// then invoke one or more "tablegen backends" to emit information about the
// description in some predefined format. In practice, this is used by the LLVM
// code generators to automate generation of a code generator through a
// high-level description of the target.
//
//===----------------------------------------------------------------------===//
#include "llvm/TableGen/Main.h"
#include "TGParser.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include <algorithm>
#include <cstdio>
#include <system_error>
using namespace llvm;
static cl::opt<std::string>
OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
cl::init("-"));
static cl::opt<std::string>
DependFilename("d",
cl::desc("Dependency filename"),
cl::value_desc("filename"),
cl::init(""));
static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
static cl::list<std::string>
IncludeDirs("I", cl::desc("Directory of include files"),
cl::value_desc("directory"), cl::Prefix);
static int reportError(const char *ProgName, Twine Msg) {
errs() << ProgName << ": " << Msg;
errs().flush();
return 1;
}
/// \brief Create a dependency file for `-d` option.
///
/// This functionality is really only for the benefit of the build system.
/// It is similar to GCC's `-M*` family of options.
static int createDependencyFile(const TGParser &Parser, const char *argv0) {
if (OutputFilename == "-")
return reportError(argv0, "the option -d must be used together with -o\n");
std::error_code EC;
ToolOutputFile DepOut(DependFilename, EC, sys::fs::F_Text);
if (EC)
return reportError(argv0, "error opening " + DependFilename + ":" +
EC.message() + "\n");
DepOut.os() << OutputFilename << ":";
for (const auto &Dep : Parser.getDependencies()) {
DepOut.os() << ' ' << Dep.first;
}
DepOut.os() << "\n";
DepOut.keep();
return 0;
}
int llvm::TableGenMain(char *argv0, TableGenMainFn *MainFn) {
RecordKeeper Records;
// Parse the input file.
ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
MemoryBuffer::getFileOrSTDIN(InputFilename);
if (std::error_code EC = FileOrErr.getError())
return reportError(argv0, "Could not open input file '" + InputFilename +
"': " + EC.message() + "\n");
// Tell SrcMgr about this buffer, which is what TGParser will pick up.
SrcMgr.AddNewSourceBuffer(std::move(*FileOrErr), SMLoc());
// Record the location of the include directory so that the lexer can find
// it later.
SrcMgr.setIncludeDirs(IncludeDirs);
TGParser Parser(SrcMgr, Records);
if (Parser.ParseFile())
return 1;
std::error_code EC;
ToolOutputFile Out(OutputFilename, EC, sys::fs::F_Text);
if (EC)
return reportError(argv0, "error opening " + OutputFilename + ":" +
EC.message() + "\n");
if (!DependFilename.empty()) {
if (int Ret = createDependencyFile(Parser, argv0))
return Ret;
}
if (MainFn(Out.os(), Records))
return 1;
if (ErrorsPrinted > 0)
return reportError(argv0, Twine(ErrorsPrinted) + " errors.\n");
// Declare success.
Out.keep();
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,334 +0,0 @@
//===- SetTheory.cpp - Generate ordered sets from DAG expressions ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the SetTheory class that computes ordered sets of
// Records from DAG expressions.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/SetTheory.h"
#include <algorithm>
#include <cstdint>
#include <string>
#include <utility>
using namespace llvm;
// Define the standard operators.
namespace {
using RecSet = SetTheory::RecSet;
using RecVec = SetTheory::RecVec;
// (add a, b, ...) Evaluate and union all arguments.
struct AddOp : public SetTheory::Operator {
void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
ArrayRef<SMLoc> Loc) override {
ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts, Loc);
}
};
// (sub Add, Sub, ...) Set difference.
struct SubOp : public SetTheory::Operator {
void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
ArrayRef<SMLoc> Loc) override {
if (Expr->arg_size() < 2)
PrintFatalError(Loc, "Set difference needs at least two arguments: " +
Expr->getAsString());
RecSet Add, Sub;
ST.evaluate(*Expr->arg_begin(), Add, Loc);
ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Sub, Loc);
for (RecSet::iterator I = Add.begin(), E = Add.end(); I != E; ++I)
if (!Sub.count(*I))
Elts.insert(*I);
}
};
// (and S1, S2) Set intersection.
struct AndOp : public SetTheory::Operator {
void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
ArrayRef<SMLoc> Loc) override {
if (Expr->arg_size() != 2)
PrintFatalError(Loc, "Set intersection requires two arguments: " +
Expr->getAsString());
RecSet S1, S2;
ST.evaluate(Expr->arg_begin()[0], S1, Loc);
ST.evaluate(Expr->arg_begin()[1], S2, Loc);
for (RecSet::iterator I = S1.begin(), E = S1.end(); I != E; ++I)
if (S2.count(*I))
Elts.insert(*I);
}
};
// SetIntBinOp - Abstract base class for (Op S, N) operators.
struct SetIntBinOp : public SetTheory::Operator {
virtual void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N,
RecSet &Elts, ArrayRef<SMLoc> Loc) = 0;
void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
ArrayRef<SMLoc> Loc) override {
if (Expr->arg_size() != 2)
PrintFatalError(Loc, "Operator requires (Op Set, Int) arguments: " +
Expr->getAsString());
RecSet Set;
ST.evaluate(Expr->arg_begin()[0], Set, Loc);
IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[1]);
if (!II)
PrintFatalError(Loc, "Second argument must be an integer: " +
Expr->getAsString());
apply2(ST, Expr, Set, II->getValue(), Elts, Loc);
}
};
// (shl S, N) Shift left, remove the first N elements.
struct ShlOp : public SetIntBinOp {
void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N,
RecSet &Elts, ArrayRef<SMLoc> Loc) override {
if (N < 0)
PrintFatalError(Loc, "Positive shift required: " +
Expr->getAsString());
if (unsigned(N) < Set.size())
Elts.insert(Set.begin() + N, Set.end());
}
};
// (trunc S, N) Truncate after the first N elements.
struct TruncOp : public SetIntBinOp {
void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N,
RecSet &Elts, ArrayRef<SMLoc> Loc) override {
if (N < 0)
PrintFatalError(Loc, "Positive length required: " +
Expr->getAsString());
if (unsigned(N) > Set.size())
N = Set.size();
Elts.insert(Set.begin(), Set.begin() + N);
}
};
// Left/right rotation.
struct RotOp : public SetIntBinOp {
const bool Reverse;
RotOp(bool Rev) : Reverse(Rev) {}
void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N,
RecSet &Elts, ArrayRef<SMLoc> Loc) override {
if (Reverse)
N = -N;
// N > 0 -> rotate left, N < 0 -> rotate right.
if (Set.empty())
return;
if (N < 0)
N = Set.size() - (-N % Set.size());
else
N %= Set.size();
Elts.insert(Set.begin() + N, Set.end());
Elts.insert(Set.begin(), Set.begin() + N);
}
};
// (decimate S, N) Pick every N'th element of S.
struct DecimateOp : public SetIntBinOp {
void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N,
RecSet &Elts, ArrayRef<SMLoc> Loc) override {
if (N <= 0)
PrintFatalError(Loc, "Positive stride required: " +
Expr->getAsString());
for (unsigned I = 0; I < Set.size(); I += N)
Elts.insert(Set[I]);
}
};
// (interleave S1, S2, ...) Interleave elements of the arguments.
struct InterleaveOp : public SetTheory::Operator {
void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
ArrayRef<SMLoc> Loc) override {
// Evaluate the arguments individually.
SmallVector<RecSet, 4> Args(Expr->getNumArgs());
unsigned MaxSize = 0;
for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) {
ST.evaluate(Expr->getArg(i), Args[i], Loc);
MaxSize = std::max(MaxSize, unsigned(Args[i].size()));
}
// Interleave arguments into Elts.
for (unsigned n = 0; n != MaxSize; ++n)
for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i)
if (n < Args[i].size())
Elts.insert(Args[i][n]);
}
};
// (sequence "Format", From, To) Generate a sequence of records by name.
struct SequenceOp : public SetTheory::Operator {
void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
ArrayRef<SMLoc> Loc) override {
int Step = 1;
if (Expr->arg_size() > 4)
PrintFatalError(Loc, "Bad args to (sequence \"Format\", From, To): " +
Expr->getAsString());
else if (Expr->arg_size() == 4) {
if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[3])) {
Step = II->getValue();
} else
PrintFatalError(Loc, "Stride must be an integer: " +
Expr->getAsString());
}
std::string Format;
if (StringInit *SI = dyn_cast<StringInit>(Expr->arg_begin()[0]))
Format = SI->getValue();
else
PrintFatalError(Loc, "Format must be a string: " + Expr->getAsString());
int64_t From, To;
if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[1]))
From = II->getValue();
else
PrintFatalError(Loc, "From must be an integer: " + Expr->getAsString());
if (From < 0 || From >= (1 << 30))
PrintFatalError(Loc, "From out of range");
if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[2]))
To = II->getValue();
else
PrintFatalError(Loc, "To must be an integer: " + Expr->getAsString());
if (To < 0 || To >= (1 << 30))
PrintFatalError(Loc, "To out of range");
RecordKeeper &Records =
cast<DefInit>(Expr->getOperator())->getDef()->getRecords();
Step *= From <= To ? 1 : -1;
while (true) {
if (Step > 0 && From > To)
break;
else if (Step < 0 && From < To)
break;
std::string Name;
raw_string_ostream OS(Name);
OS << format(Format.c_str(), unsigned(From));
Record *Rec = Records.getDef(OS.str());
if (!Rec)
PrintFatalError(Loc, "No def named '" + Name + "': " +
Expr->getAsString());
// Try to reevaluate Rec in case it is a set.
if (const RecVec *Result = ST.expand(Rec))
Elts.insert(Result->begin(), Result->end());
else
Elts.insert(Rec);
From += Step;
}
}
};
// Expand a Def into a set by evaluating one of its fields.
struct FieldExpander : public SetTheory::Expander {
StringRef FieldName;
FieldExpander(StringRef fn) : FieldName(fn) {}
void expand(SetTheory &ST, Record *Def, RecSet &Elts) override {
ST.evaluate(Def->getValueInit(FieldName), Elts, Def->getLoc());
}
};
} // end anonymous namespace
// Pin the vtables to this file.
void SetTheory::Operator::anchor() {}
void SetTheory::Expander::anchor() {}
SetTheory::SetTheory() {
addOperator("add", llvm::make_unique<AddOp>());
addOperator("sub", llvm::make_unique<SubOp>());
addOperator("and", llvm::make_unique<AndOp>());
addOperator("shl", llvm::make_unique<ShlOp>());
addOperator("trunc", llvm::make_unique<TruncOp>());
addOperator("rotl", llvm::make_unique<RotOp>(false));
addOperator("rotr", llvm::make_unique<RotOp>(true));
addOperator("decimate", llvm::make_unique<DecimateOp>());
addOperator("interleave", llvm::make_unique<InterleaveOp>());
addOperator("sequence", llvm::make_unique<SequenceOp>());
}
void SetTheory::addOperator(StringRef Name, std::unique_ptr<Operator> Op) {
Operators[Name] = std::move(Op);
}
void SetTheory::addExpander(StringRef ClassName, std::unique_ptr<Expander> E) {
Expanders[ClassName] = std::move(E);
}
void SetTheory::addFieldExpander(StringRef ClassName, StringRef FieldName) {
addExpander(ClassName, llvm::make_unique<FieldExpander>(FieldName));
}
void SetTheory::evaluate(Init *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) {
// A def in a list can be a just an element, or it may expand.
if (DefInit *Def = dyn_cast<DefInit>(Expr)) {
if (const RecVec *Result = expand(Def->getDef()))
return Elts.insert(Result->begin(), Result->end());
Elts.insert(Def->getDef());
return;
}
// Lists simply expand.
if (ListInit *LI = dyn_cast<ListInit>(Expr))
return evaluate(LI->begin(), LI->end(), Elts, Loc);
// Anything else must be a DAG.
DagInit *DagExpr = dyn_cast<DagInit>(Expr);
if (!DagExpr)
PrintFatalError(Loc, "Invalid set element: " + Expr->getAsString());
DefInit *OpInit = dyn_cast<DefInit>(DagExpr->getOperator());
if (!OpInit)
PrintFatalError(Loc, "Bad set expression: " + Expr->getAsString());
auto I = Operators.find(OpInit->getDef()->getName());
if (I == Operators.end())
PrintFatalError(Loc, "Unknown set operator: " + Expr->getAsString());
I->second->apply(*this, DagExpr, Elts, Loc);
}
const RecVec *SetTheory::expand(Record *Set) {
// Check existing entries for Set and return early.
ExpandMap::iterator I = Expansions.find(Set);
if (I != Expansions.end())
return &I->second;
// This is the first time we see Set. Find a suitable expander.
ArrayRef<std::pair<Record *, SMRange>> SC = Set->getSuperClasses();
for (const auto &SCPair : SC) {
// Skip unnamed superclasses.
if (!isa<StringInit>(SCPair.first->getNameInit()))
continue;
auto I = Expanders.find(SCPair.first->getName());
if (I != Expanders.end()) {
// This breaks recursive definitions.
RecVec &EltVec = Expansions[Set];
RecSet Elts;
I->second->expand(*this, Set, Elts);
EltVec.assign(Elts.begin(), Elts.end());
return &EltVec;
}
}
// Set is not expandable.
return nullptr;
}

View File

@ -1,157 +0,0 @@
//===- StringMatcher.cpp - Generate a matcher for input strings -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the StringMatcher class.
//
//===----------------------------------------------------------------------===//
#include "llvm/TableGen/StringMatcher.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <map>
#include <string>
#include <utility>
#include <vector>
using namespace llvm;
/// FindFirstNonCommonLetter - Find the first character in the keys of the
/// string pairs that is not shared across the whole set of strings. All
/// strings are assumed to have the same length.
static unsigned
FindFirstNonCommonLetter(const std::vector<const
StringMatcher::StringPair*> &Matches) {
assert(!Matches.empty());
for (unsigned i = 0, e = Matches[0]->first.size(); i != e; ++i) {
// Check to see if letter i is the same across the set.
char Letter = Matches[0]->first[i];
for (unsigned str = 0, e = Matches.size(); str != e; ++str)
if (Matches[str]->first[i] != Letter)
return i;
}
return Matches[0]->first.size();
}
/// EmitStringMatcherForChar - Given a set of strings that are known to be the
/// same length and whose characters leading up to CharNo are the same, emit
/// code to verify that CharNo and later are the same.
///
/// \return - True if control can leave the emitted code fragment.
bool StringMatcher::EmitStringMatcherForChar(
const std::vector<const StringPair *> &Matches, unsigned CharNo,
unsigned IndentCount, bool IgnoreDuplicates) const {
assert(!Matches.empty() && "Must have at least one string to match!");
std::string Indent(IndentCount * 2 + 4, ' ');
// If we have verified that the entire string matches, we're done: output the
// matching code.
if (CharNo == Matches[0]->first.size()) {
if (Matches.size() > 1 && !IgnoreDuplicates)
report_fatal_error("Had duplicate keys to match on");
// If the to-execute code has \n's in it, indent each subsequent line.
StringRef Code = Matches[0]->second;
std::pair<StringRef, StringRef> Split = Code.split('\n');
OS << Indent << Split.first << "\t // \"" << Matches[0]->first << "\"\n";
Code = Split.second;
while (!Code.empty()) {
Split = Code.split('\n');
OS << Indent << Split.first << "\n";
Code = Split.second;
}
return false;
}
// Bucket the matches by the character we are comparing.
std::map<char, std::vector<const StringPair*>> MatchesByLetter;
for (unsigned i = 0, e = Matches.size(); i != e; ++i)
MatchesByLetter[Matches[i]->first[CharNo]].push_back(Matches[i]);
// If we have exactly one bucket to match, see how many characters are common
// across the whole set and match all of them at once.
if (MatchesByLetter.size() == 1) {
unsigned FirstNonCommonLetter = FindFirstNonCommonLetter(Matches);
unsigned NumChars = FirstNonCommonLetter-CharNo;
// Emit code to break out if the prefix doesn't match.
if (NumChars == 1) {
// Do the comparison with if (Str[1] != 'f')
// FIXME: Need to escape general characters.
OS << Indent << "if (" << StrVariableName << "[" << CharNo << "] != '"
<< Matches[0]->first[CharNo] << "')\n";
OS << Indent << " break;\n";
} else {
// Do the comparison with if memcmp(Str.data()+1, "foo", 3).
// FIXME: Need to escape general strings.
OS << Indent << "if (memcmp(" << StrVariableName << ".data()+" << CharNo
<< ", \"" << Matches[0]->first.substr(CharNo, NumChars) << "\", "
<< NumChars << ") != 0)\n";
OS << Indent << " break;\n";
}
return EmitStringMatcherForChar(Matches, FirstNonCommonLetter, IndentCount,
IgnoreDuplicates);
}
// Otherwise, we have multiple possible things, emit a switch on the
// character.
OS << Indent << "switch (" << StrVariableName << "[" << CharNo << "]) {\n";
OS << Indent << "default: break;\n";
for (std::map<char, std::vector<const StringPair*>>::iterator LI =
MatchesByLetter.begin(), E = MatchesByLetter.end(); LI != E; ++LI) {
// TODO: escape hard stuff (like \n) if we ever care about it.
OS << Indent << "case '" << LI->first << "':\t // "
<< LI->second.size() << " string";
if (LI->second.size() != 1) OS << 's';
OS << " to match.\n";
if (EmitStringMatcherForChar(LI->second, CharNo + 1, IndentCount + 1,
IgnoreDuplicates))
OS << Indent << " break;\n";
}
OS << Indent << "}\n";
return true;
}
/// Emit - Top level entry point.
///
void StringMatcher::Emit(unsigned Indent, bool IgnoreDuplicates) const {
// If nothing to match, just fall through.
if (Matches.empty()) return;
// First level categorization: group strings by length.
std::map<unsigned, std::vector<const StringPair*>> MatchesByLength;
for (unsigned i = 0, e = Matches.size(); i != e; ++i)
MatchesByLength[Matches[i].first.size()].push_back(&Matches[i]);
// Output a switch statement on length and categorize the elements within each
// bin.
OS.indent(Indent*2+2) << "switch (" << StrVariableName << ".size()) {\n";
OS.indent(Indent*2+2) << "default: break;\n";
for (std::map<unsigned, std::vector<const StringPair*>>::iterator LI =
MatchesByLength.begin(), E = MatchesByLength.end(); LI != E; ++LI) {
OS.indent(Indent*2+2) << "case " << LI->first << ":\t // "
<< LI->second.size()
<< " string" << (LI->second.size() == 1 ? "" : "s") << " to match.\n";
if (EmitStringMatcherForChar(LI->second, 0, Indent, IgnoreDuplicates))
OS.indent(Indent*2+4) << "break;\n";
}
OS.indent(Indent*2+2) << "}\n";
}

View File

@ -1,488 +0,0 @@
//===- TGLexer.cpp - Lexer for TableGen -----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implement the Lexer for TableGen.
//
//===----------------------------------------------------------------------===//
#include "TGLexer.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/config.h" // for strtoull()/strtoll() define
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/TableGen/Error.h"
#include <cctype>
#include <cerrno>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace llvm;
TGLexer::TGLexer(SourceMgr &SM) : SrcMgr(SM) {
CurBuffer = SrcMgr.getMainFileID();
CurBuf = SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer();
CurPtr = CurBuf.begin();
TokStart = nullptr;
}
SMLoc TGLexer::getLoc() const {
return SMLoc::getFromPointer(TokStart);
}
/// ReturnError - Set the error to the specified string at the specified
/// location. This is defined to always return tgtok::Error.
tgtok::TokKind TGLexer::ReturnError(const char *Loc, const Twine &Msg) {
PrintError(Loc, Msg);
return tgtok::Error;
}
int TGLexer::getNextChar() {
char CurChar = *CurPtr++;
switch (CurChar) {
default:
return (unsigned char)CurChar;
case 0: {
// A nul character in the stream is either the end of the current buffer or
// a random nul in the file. Disambiguate that here.
if (CurPtr-1 != CurBuf.end())
return 0; // Just whitespace.
// If this is the end of an included file, pop the parent file off the
// include stack.
SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
if (ParentIncludeLoc != SMLoc()) {
CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
CurBuf = SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer();
CurPtr = ParentIncludeLoc.getPointer();
return getNextChar();
}
// Otherwise, return end of file.
--CurPtr; // Another call to lex will return EOF again.
return EOF;
}
case '\n':
case '\r':
// Handle the newline character by ignoring it and incrementing the line
// count. However, be careful about 'dos style' files with \n\r in them.
// Only treat a \n\r or \r\n as a single line.
if ((*CurPtr == '\n' || (*CurPtr == '\r')) &&
*CurPtr != CurChar)
++CurPtr; // Eat the two char newline sequence.
return '\n';
}
}
int TGLexer::peekNextChar(int Index) {
return *(CurPtr + Index);
}
tgtok::TokKind TGLexer::LexToken() {
TokStart = CurPtr;
// This always consumes at least one character.
int CurChar = getNextChar();
switch (CurChar) {
default:
// Handle letters: [a-zA-Z_]
if (isalpha(CurChar) || CurChar == '_')
return LexIdentifier();
// Unknown character, emit an error.
return ReturnError(TokStart, "Unexpected character");
case EOF: return tgtok::Eof;
case ':': return tgtok::colon;
case ';': return tgtok::semi;
case '.': return tgtok::period;
case ',': return tgtok::comma;
case '<': return tgtok::less;
case '>': return tgtok::greater;
case ']': return tgtok::r_square;
case '{': return tgtok::l_brace;
case '}': return tgtok::r_brace;
case '(': return tgtok::l_paren;
case ')': return tgtok::r_paren;
case '=': return tgtok::equal;
case '?': return tgtok::question;
case '#': return tgtok::paste;
case 0:
case ' ':
case '\t':
case '\n':
case '\r':
// Ignore whitespace.
return LexToken();
case '/':
// If this is the start of a // comment, skip until the end of the line or
// the end of the buffer.
if (*CurPtr == '/')
SkipBCPLComment();
else if (*CurPtr == '*') {
if (SkipCComment())
return tgtok::Error;
} else // Otherwise, this is an error.
return ReturnError(TokStart, "Unexpected character");
return LexToken();
case '-': case '+':
case '0': case '1': case '2': case '3': case '4': case '5': case '6':
case '7': case '8': case '9': {
int NextChar = 0;
if (isdigit(CurChar)) {
// Allow identifiers to start with a number if it is followed by
// an identifier. This can happen with paste operations like
// foo#8i.
int i = 0;
do {
NextChar = peekNextChar(i++);
} while (isdigit(NextChar));
if (NextChar == 'x' || NextChar == 'b') {
// If this is [0-9]b[01] or [0-9]x[0-9A-fa-f] this is most
// likely a number.
int NextNextChar = peekNextChar(i);
switch (NextNextChar) {
default:
break;
case '0': case '1':
if (NextChar == 'b')
return LexNumber();
LLVM_FALLTHROUGH;
case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
if (NextChar == 'x')
return LexNumber();
break;
}
}
}
if (isalpha(NextChar) || NextChar == '_')
return LexIdentifier();
return LexNumber();
}
case '"': return LexString();
case '$': return LexVarName();
case '[': return LexBracket();
case '!': return LexExclaim();
}
}
/// LexString - Lex "[^"]*"
tgtok::TokKind TGLexer::LexString() {
const char *StrStart = CurPtr;
CurStrVal = "";
while (*CurPtr != '"') {
// If we hit the end of the buffer, report an error.
if (*CurPtr == 0 && CurPtr == CurBuf.end())
return ReturnError(StrStart, "End of file in string literal");
if (*CurPtr == '\n' || *CurPtr == '\r')
return ReturnError(StrStart, "End of line in string literal");
if (*CurPtr != '\\') {
CurStrVal += *CurPtr++;
continue;
}
++CurPtr;
switch (*CurPtr) {
case '\\': case '\'': case '"':
// These turn into their literal character.
CurStrVal += *CurPtr++;
break;
case 't':
CurStrVal += '\t';
++CurPtr;
break;
case 'n':
CurStrVal += '\n';
++CurPtr;
break;
case '\n':
case '\r':
return ReturnError(CurPtr, "escaped newlines not supported in tblgen");
// If we hit the end of the buffer, report an error.
case '\0':
if (CurPtr == CurBuf.end())
return ReturnError(StrStart, "End of file in string literal");
LLVM_FALLTHROUGH;
default:
return ReturnError(CurPtr, "invalid escape in string literal");
}
}
++CurPtr;
return tgtok::StrVal;
}
tgtok::TokKind TGLexer::LexVarName() {
if (!isalpha(CurPtr[0]) && CurPtr[0] != '_')
return ReturnError(TokStart, "Invalid variable name");
// Otherwise, we're ok, consume the rest of the characters.
const char *VarNameStart = CurPtr++;
while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
++CurPtr;
CurStrVal.assign(VarNameStart, CurPtr);
return tgtok::VarName;
}
tgtok::TokKind TGLexer::LexIdentifier() {
// The first letter is [a-zA-Z_#].
const char *IdentStart = TokStart;
// Match the rest of the identifier regex: [0-9a-zA-Z_#]*
while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
++CurPtr;
// Check to see if this identifier is a keyword.
StringRef Str(IdentStart, CurPtr-IdentStart);
if (Str == "include") {
if (LexInclude()) return tgtok::Error;
return Lex();
}
tgtok::TokKind Kind = StringSwitch<tgtok::TokKind>(Str)
.Case("int", tgtok::Int)
.Case("bit", tgtok::Bit)
.Case("bits", tgtok::Bits)
.Case("string", tgtok::String)
.Case("list", tgtok::List)
.Case("code", tgtok::Code)
.Case("dag", tgtok::Dag)
.Case("class", tgtok::Class)
.Case("def", tgtok::Def)
.Case("foreach", tgtok::Foreach)
.Case("defm", tgtok::Defm)
.Case("multiclass", tgtok::MultiClass)
.Case("field", tgtok::Field)
.Case("let", tgtok::Let)
.Case("in", tgtok::In)
.Default(tgtok::Id);
if (Kind == tgtok::Id)
CurStrVal.assign(Str.begin(), Str.end());
return Kind;
}
/// LexInclude - We just read the "include" token. Get the string token that
/// comes next and enter the include.
bool TGLexer::LexInclude() {
// The token after the include must be a string.
tgtok::TokKind Tok = LexToken();
if (Tok == tgtok::Error) return true;
if (Tok != tgtok::StrVal) {
PrintError(getLoc(), "Expected filename after include");
return true;
}
// Get the string.
std::string Filename = CurStrVal;
std::string IncludedFile;
CurBuffer = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr),
IncludedFile);
if (!CurBuffer) {
PrintError(getLoc(), "Could not find include file '" + Filename + "'");
return true;
}
DependenciesMapTy::const_iterator Found = Dependencies.find(IncludedFile);
if (Found != Dependencies.end()) {
PrintError(getLoc(),
"File '" + IncludedFile + "' has already been included.");
SrcMgr.PrintMessage(Found->second, SourceMgr::DK_Note,
"previously included here");
return true;
}
Dependencies.insert(std::make_pair(IncludedFile, getLoc()));
// Save the line number and lex buffer of the includer.
CurBuf = SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer();
CurPtr = CurBuf.begin();
return false;
}
void TGLexer::SkipBCPLComment() {
++CurPtr; // skip the second slash.
while (true) {
switch (*CurPtr) {
case '\n':
case '\r':
return; // Newline is end of comment.
case 0:
// If this is the end of the buffer, end the comment.
if (CurPtr == CurBuf.end())
return;
break;
}
// Otherwise, skip the character.
++CurPtr;
}
}
/// SkipCComment - This skips C-style /**/ comments. The only difference from C
/// is that we allow nesting.
bool TGLexer::SkipCComment() {
++CurPtr; // skip the star.
unsigned CommentDepth = 1;
while (true) {
int CurChar = getNextChar();
switch (CurChar) {
case EOF:
PrintError(TokStart, "Unterminated comment!");
return true;
case '*':
// End of the comment?
if (CurPtr[0] != '/') break;
++CurPtr; // End the */.
if (--CommentDepth == 0)
return false;
break;
case '/':
// Start of a nested comment?
if (CurPtr[0] != '*') break;
++CurPtr;
++CommentDepth;
break;
}
}
}
/// LexNumber - Lex:
/// [-+]?[0-9]+
/// 0x[0-9a-fA-F]+
/// 0b[01]+
tgtok::TokKind TGLexer::LexNumber() {
if (CurPtr[-1] == '0') {
if (CurPtr[0] == 'x') {
++CurPtr;
const char *NumStart = CurPtr;
while (isxdigit(CurPtr[0]))
++CurPtr;
// Requires at least one hex digit.
if (CurPtr == NumStart)
return ReturnError(TokStart, "Invalid hexadecimal number");
errno = 0;
CurIntVal = strtoll(NumStart, nullptr, 16);
if (errno == EINVAL)
return ReturnError(TokStart, "Invalid hexadecimal number");
if (errno == ERANGE) {
errno = 0;
CurIntVal = (int64_t)strtoull(NumStart, nullptr, 16);
if (errno == EINVAL)
return ReturnError(TokStart, "Invalid hexadecimal number");
if (errno == ERANGE)
return ReturnError(TokStart, "Hexadecimal number out of range");
}
return tgtok::IntVal;
} else if (CurPtr[0] == 'b') {
++CurPtr;
const char *NumStart = CurPtr;
while (CurPtr[0] == '0' || CurPtr[0] == '1')
++CurPtr;
// Requires at least one binary digit.
if (CurPtr == NumStart)
return ReturnError(CurPtr-2, "Invalid binary number");
CurIntVal = strtoll(NumStart, nullptr, 2);
return tgtok::BinaryIntVal;
}
}
// Check for a sign without a digit.
if (!isdigit(CurPtr[0])) {
if (CurPtr[-1] == '-')
return tgtok::minus;
else if (CurPtr[-1] == '+')
return tgtok::plus;
}
while (isdigit(CurPtr[0]))
++CurPtr;
CurIntVal = strtoll(TokStart, nullptr, 10);
return tgtok::IntVal;
}
/// LexBracket - We just read '['. If this is a code block, return it,
/// otherwise return the bracket. Match: '[' and '[{ ( [^}]+ | }[^]] )* }]'
tgtok::TokKind TGLexer::LexBracket() {
if (CurPtr[0] != '{')
return tgtok::l_square;
++CurPtr;
const char *CodeStart = CurPtr;
while (true) {
int Char = getNextChar();
if (Char == EOF) break;
if (Char != '}') continue;
Char = getNextChar();
if (Char == EOF) break;
if (Char == ']') {
CurStrVal.assign(CodeStart, CurPtr-2);
return tgtok::CodeFragment;
}
}
return ReturnError(CodeStart-2, "Unterminated Code Block");
}
/// LexExclaim - Lex '!' and '![a-zA-Z]+'.
tgtok::TokKind TGLexer::LexExclaim() {
if (!isalpha(*CurPtr))
return ReturnError(CurPtr - 1, "Invalid \"!operator\"");
const char *Start = CurPtr++;
while (isalpha(*CurPtr))
++CurPtr;
// Check to see which operator this is.
tgtok::TokKind Kind =
StringSwitch<tgtok::TokKind>(StringRef(Start, CurPtr - Start))
.Case("eq", tgtok::XEq)
.Case("if", tgtok::XIf)
.Case("head", tgtok::XHead)
.Case("tail", tgtok::XTail)
.Case("con", tgtok::XConcat)
.Case("add", tgtok::XADD)
.Case("and", tgtok::XAND)
.Case("or", tgtok::XOR)
.Case("shl", tgtok::XSHL)
.Case("sra", tgtok::XSRA)
.Case("srl", tgtok::XSRL)
.Case("cast", tgtok::XCast)
.Case("empty", tgtok::XEmpty)
.Case("subst", tgtok::XSubst)
.Case("foreach", tgtok::XForEach)
.Case("listconcat", tgtok::XListConcat)
.Case("strconcat", tgtok::XStrConcat)
.Default(tgtok::Error);
return Kind != tgtok::Error ? Kind : ReturnError(Start-1, "Unknown operator");
}

View File

@ -1,140 +0,0 @@
//===- TGLexer.h - Lexer for TableGen Files ---------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class represents the Lexer for tablegen files.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TABLEGEN_TGLEXER_H
#define LLVM_LIB_TABLEGEN_TGLEXER_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/SMLoc.h"
#include <cassert>
#include <map>
#include <string>
namespace llvm {
class SourceMgr;
class SMLoc;
class Twine;
namespace tgtok {
enum TokKind {
// Markers
Eof, Error,
// Tokens with no info.
minus, plus, // - +
l_square, r_square, // [ ]
l_brace, r_brace, // { }
l_paren, r_paren, // ( )
less, greater, // < >
colon, semi, // : ;
comma, period, // , .
equal, question, // = ?
paste, // #
// Keywords.
Bit, Bits, Class, Code, Dag, Def, Foreach, Defm, Field, In, Int, Let, List,
MultiClass, String,
// !keywords.
XConcat, XADD, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XStrConcat, XCast,
XSubst, XForEach, XHead, XTail, XEmpty, XIf, XEq,
// Integer value.
IntVal,
// Binary constant. Note that these are sized according to the number of
// bits given.
BinaryIntVal,
// String valued tokens.
Id, StrVal, VarName, CodeFragment
};
}
/// TGLexer - TableGen Lexer class.
class TGLexer {
SourceMgr &SrcMgr;
const char *CurPtr;
StringRef CurBuf;
// Information about the current token.
const char *TokStart;
tgtok::TokKind CurCode;
std::string CurStrVal; // This is valid for ID, STRVAL, VARNAME, CODEFRAGMENT
int64_t CurIntVal; // This is valid for INTVAL.
/// CurBuffer - This is the current buffer index we're lexing from as managed
/// by the SourceMgr object.
unsigned CurBuffer;
public:
typedef std::map<std::string, SMLoc> DependenciesMapTy;
private:
/// Dependencies - This is the list of all included files.
DependenciesMapTy Dependencies;
public:
TGLexer(SourceMgr &SrcMgr);
tgtok::TokKind Lex() {
return CurCode = LexToken();
}
const DependenciesMapTy &getDependencies() const {
return Dependencies;
}
tgtok::TokKind getCode() const { return CurCode; }
const std::string &getCurStrVal() const {
assert((CurCode == tgtok::Id || CurCode == tgtok::StrVal ||
CurCode == tgtok::VarName || CurCode == tgtok::CodeFragment) &&
"This token doesn't have a string value");
return CurStrVal;
}
int64_t getCurIntVal() const {
assert(CurCode == tgtok::IntVal && "This token isn't an integer");
return CurIntVal;
}
std::pair<int64_t, unsigned> getCurBinaryIntVal() const {
assert(CurCode == tgtok::BinaryIntVal &&
"This token isn't a binary integer");
return std::make_pair(CurIntVal, (CurPtr - TokStart)-2);
}
SMLoc getLoc() const;
private:
/// LexToken - Read the next token and return its code.
tgtok::TokKind LexToken();
tgtok::TokKind ReturnError(const char *Loc, const Twine &Msg);
int getNextChar();
int peekNextChar(int Index);
void SkipBCPLComment();
bool SkipCComment();
tgtok::TokKind LexIdentifier();
bool LexInclude();
tgtok::TokKind LexString();
tgtok::TokKind LexVarName();
tgtok::TokKind LexNumber();
tgtok::TokKind LexBracket();
tgtok::TokKind LexExclaim();
};
} // end namespace llvm
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,189 +0,0 @@
//===- TGParser.h - Parser for TableGen Files -------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class represents the Parser for tablegen files.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TABLEGEN_TGPARSER_H
#define LLVM_LIB_TABLEGEN_TGPARSER_H
#include "TGLexer.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include <map>
namespace llvm {
class Record;
class RecordVal;
class RecordKeeper;
class RecTy;
class Init;
struct MultiClass;
struct SubClassReference;
struct SubMultiClassReference;
struct LetRecord {
StringInit *Name;
std::vector<unsigned> Bits;
Init *Value;
SMLoc Loc;
LetRecord(StringInit *N, ArrayRef<unsigned> B, Init *V, SMLoc L)
: Name(N), Bits(B), Value(V), Loc(L) {
}
};
/// ForeachLoop - Record the iteration state associated with a for loop.
/// This is used to instantiate items in the loop body.
struct ForeachLoop {
VarInit *IterVar;
ListInit *ListValue;
ForeachLoop(VarInit *IVar, ListInit *LValue)
: IterVar(IVar), ListValue(LValue) {}
};
class TGParser {
TGLexer Lex;
std::vector<SmallVector<LetRecord, 4>> LetStack;
std::map<std::string, std::unique_ptr<MultiClass>> MultiClasses;
/// Loops - Keep track of any foreach loops we are within.
///
typedef std::vector<ForeachLoop> LoopVector;
LoopVector Loops;
/// CurMultiClass - If we are parsing a 'multiclass' definition, this is the
/// current value.
MultiClass *CurMultiClass;
// Record tracker
RecordKeeper &Records;
unsigned AnonCounter;
// A "named boolean" indicating how to parse identifiers. Usually
// identifiers map to some existing object but in special cases
// (e.g. parsing def names) no such object exists yet because we are
// in the middle of creating in. For those situations, allow the
// parser to ignore missing object errors.
enum IDParseMode {
ParseValueMode, // We are parsing a value we expect to look up.
ParseNameMode, // We are parsing a name of an object that does not yet
// exist.
ParseForeachMode // We are parsing a foreach init.
};
public:
TGParser(SourceMgr &SrcMgr, RecordKeeper &records)
: Lex(SrcMgr), CurMultiClass(nullptr), Records(records), AnonCounter(0) {}
/// ParseFile - Main entrypoint for parsing a tblgen file. These parser
/// routines return true on error, or false on success.
bool ParseFile();
bool Error(SMLoc L, const Twine &Msg) const {
PrintError(L, Msg);
return true;
}
bool TokError(const Twine &Msg) const {
return Error(Lex.getLoc(), Msg);
}
const TGLexer::DependenciesMapTy &getDependencies() const {
return Lex.getDependencies();
}
private: // Semantic analysis methods.
bool AddValue(Record *TheRec, SMLoc Loc, const RecordVal &RV);
bool SetValue(Record *TheRec, SMLoc Loc, Init *ValName,
ArrayRef<unsigned> BitList, Init *V,
bool AllowSelfAssignment = false);
bool AddSubClass(Record *Rec, SubClassReference &SubClass);
bool AddSubMultiClass(MultiClass *CurMC,
SubMultiClassReference &SubMultiClass);
Init *GetNewAnonymousName();
// IterRecord: Map an iterator name to a value.
struct IterRecord {
VarInit *IterVar;
Init *IterValue;
IterRecord(VarInit *Var, Init *Val) : IterVar(Var), IterValue(Val) {}
};
// IterSet: The set of all iterator values at some point in the
// iteration space.
typedef std::vector<IterRecord> IterSet;
bool ProcessForeachDefs(Record *CurRec, SMLoc Loc);
bool ProcessForeachDefs(Record *CurRec, SMLoc Loc, IterSet &IterVals);
private: // Parser methods.
bool ParseObjectList(MultiClass *MC = nullptr);
bool ParseObject(MultiClass *MC);
bool ParseClass();
bool ParseMultiClass();
Record *InstantiateMulticlassDef(MultiClass &MC, Record *DefProto,
Init *&DefmPrefix, SMRange DefmPrefixRange,
ArrayRef<Init *> TArgs,
ArrayRef<Init *> TemplateVals);
bool ResolveMulticlassDefArgs(MultiClass &MC, Record *DefProto,
SMLoc DefmPrefixLoc, SMLoc SubClassLoc,
ArrayRef<Init *> TArgs,
ArrayRef<Init *> TemplateVals, bool DeleteArgs);
bool ResolveMulticlassDef(MultiClass &MC,
Record *CurRec,
Record *DefProto,
SMLoc DefmPrefixLoc);
bool ParseDefm(MultiClass *CurMultiClass);
bool ParseDef(MultiClass *CurMultiClass);
bool ParseForeach(MultiClass *CurMultiClass);
bool ParseTopLevelLet(MultiClass *CurMultiClass);
void ParseLetList(SmallVectorImpl<LetRecord> &Result);
bool ParseObjectBody(Record *CurRec);
bool ParseBody(Record *CurRec);
bool ParseBodyItem(Record *CurRec);
bool ParseTemplateArgList(Record *CurRec);
Init *ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs);
VarInit *ParseForeachDeclaration(ListInit *&ForeachListValue);
SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm);
SubMultiClassReference ParseSubMultiClassReference(MultiClass *CurMC);
Init *ParseIDValue(Record *CurRec, StringInit *Name, SMLoc NameLoc,
IDParseMode Mode = ParseValueMode);
Init *ParseSimpleValue(Record *CurRec, RecTy *ItemType = nullptr,
IDParseMode Mode = ParseValueMode);
Init *ParseValue(Record *CurRec, RecTy *ItemType = nullptr,
IDParseMode Mode = ParseValueMode);
void ParseValueList(SmallVectorImpl<llvm::Init*> &Result, Record *CurRec,
Record *ArgsRec = nullptr, RecTy *EltTy = nullptr);
void ParseDagArgList(
SmallVectorImpl<std::pair<llvm::Init*, StringInit*>> &Result,
Record *CurRec);
bool ParseOptionalRangeList(SmallVectorImpl<unsigned> &Ranges);
bool ParseOptionalBitList(SmallVectorImpl<unsigned> &Ranges);
void ParseRangeList(SmallVectorImpl<unsigned> &Result);
bool ParseRangePiece(SmallVectorImpl<unsigned> &Ranges);
RecTy *ParseType();
Init *ParseOperation(Record *CurRec, RecTy *ItemType);
RecTy *ParseOperatorType();
Init *ParseObjectName(MultiClass *CurMultiClass);
Record *ParseClassID();
MultiClass *ParseMultiClassID();
bool ApplyLetStack(Record *CurRec);
};
} // end namespace llvm
#endif

View File

@ -1,53 +0,0 @@
//===- TableGenBackend.cpp - Utilities for TableGen Backends ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides useful services for TableGen backends...
//
//===----------------------------------------------------------------------===//
#include "llvm/TableGen/TableGenBackend.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
const size_t MAX_LINE_LEN = 80U;
static void printLine(raw_ostream &OS, const Twine &Prefix, char Fill,
StringRef Suffix) {
size_t Pos = (size_t)OS.tell();
assert((Prefix.str().size() + Suffix.size() <= MAX_LINE_LEN) &&
"header line exceeds max limit");
OS << Prefix;
for (size_t i = (size_t)OS.tell() - Pos, e = MAX_LINE_LEN - Suffix.size();
i < e; ++i)
OS << Fill;
OS << Suffix << '\n';
}
void llvm::emitSourceFileHeader(StringRef Desc, raw_ostream &OS) {
printLine(OS, "/*===- TableGen'erated file ", '-', "*- C++ -*-===*\\");
StringRef Prefix("|* ");
StringRef Suffix(" *|");
printLine(OS, Prefix, ' ', Suffix);
size_t PSLen = Prefix.size() + Suffix.size();
assert(PSLen < MAX_LINE_LEN);
size_t Pos = 0U;
do {
size_t Length = std::min(Desc.size() - Pos, MAX_LINE_LEN - PSLen);
printLine(OS, Prefix + Desc.substr(Pos, Length), ' ', Suffix);
Pos += Length;
} while (Pos < Desc.size());
printLine(OS, Prefix, ' ', Suffix);
printLine(OS, Prefix + "Automatically generated file, do not edit!", ' ',
Suffix);
printLine(OS, Prefix, ' ', Suffix);
printLine(OS, "\\*===", '-', "===*/");
OS << '\n';
}