You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
13
external/llvm/lib/TableGen/CMakeLists.txt
vendored
13
external/llvm/lib/TableGen/CMakeLists.txt
vendored
@ -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
|
||||
)
|
84
external/llvm/lib/TableGen/Error.cpp
vendored
84
external/llvm/lib/TableGen/Error.cpp
vendored
@ -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
|
22
external/llvm/lib/TableGen/LLVMBuild.txt
vendored
22
external/llvm/lib/TableGen/LLVMBuild.txt
vendored
@ -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
|
118
external/llvm/lib/TableGen/Main.cpp
vendored
118
external/llvm/lib/TableGen/Main.cpp
vendored
@ -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;
|
||||
}
|
1916
external/llvm/lib/TableGen/Record.cpp
vendored
1916
external/llvm/lib/TableGen/Record.cpp
vendored
File diff suppressed because it is too large
Load Diff
334
external/llvm/lib/TableGen/SetTheory.cpp
vendored
334
external/llvm/lib/TableGen/SetTheory.cpp
vendored
@ -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;
|
||||
}
|
157
external/llvm/lib/TableGen/StringMatcher.cpp
vendored
157
external/llvm/lib/TableGen/StringMatcher.cpp
vendored
@ -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";
|
||||
}
|
488
external/llvm/lib/TableGen/TGLexer.cpp
vendored
488
external/llvm/lib/TableGen/TGLexer.cpp
vendored
@ -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");
|
||||
}
|
140
external/llvm/lib/TableGen/TGLexer.h
vendored
140
external/llvm/lib/TableGen/TGLexer.h
vendored
@ -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
|
2693
external/llvm/lib/TableGen/TGParser.cpp
vendored
2693
external/llvm/lib/TableGen/TGParser.cpp
vendored
File diff suppressed because it is too large
Load Diff
189
external/llvm/lib/TableGen/TGParser.h
vendored
189
external/llvm/lib/TableGen/TGParser.h
vendored
@ -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
|
53
external/llvm/lib/TableGen/TableGenBackend.cpp
vendored
53
external/llvm/lib/TableGen/TableGenBackend.cpp
vendored
@ -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';
|
||||
}
|
Reference in New Issue
Block a user