Initial Commit

This commit is contained in:
Sajid
2024-09-07 18:00:09 +06:00
commit 0f9a53f75a
3352 changed files with 1563708 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
//===- Automaton.td ----------------------------------------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the key top-level classes needed to produce a reasonably
// generic finite-state automaton.
//
//===----------------------------------------------------------------------===//
// Define a record inheriting from GenericAutomaton to generate a reasonably
// generic finite-state automaton over a set of actions and states.
//
// This automaton is defined by:
// 1) a state space (explicit, always bits<32>).
// 2) a set of input symbols (actions, explicit) and
// 3) a transition function from state + action -> state.
//
// A theoretical automaton is defined by <Q, S, d, q0, F>:
// Q: A set of possible states.
// S: (sigma) The input alphabet.
// d: (delta) The transition function f(q in Q, s in S) -> q' in Q.
// F: The set of final (accepting) states.
//
// Because generating all possible states is tedious, we instead define the
// transition function only and crawl all reachable states starting from the
// initial state with all inputs under all transitions until termination.
//
// We define F = S, that is, all valid states are accepting.
//
// To ensure the generation of the automaton terminates, the state transitions
// are defined as a lattice (meaning every transitioned-to state is more
// specific than the transitioned-from state, for some definition of specificity).
// Concretely a transition may set one or more bits in the state that were
// previously zero to one. If any bit was not zero, the transition is invalid.
//
// Instead of defining all possible states (which would be cumbersome), the user
// provides a set of possible Transitions from state A, consuming an input
// symbol A to state B. The Transition object transforms state A to state B and
// acts as a predicate. This means the state space can be discovered by crawling
// all the possible transitions until none are valid.
//
// This automaton is considered to be nondeterministic, meaning that multiple
// transitions can occur from any (state, action) pair. The generated automaton
// is determinized, meaning that is executes in O(k) time where k is the input
// sequence length.
//
// In addition to a generated automaton that determines if a sequence of inputs
// is accepted or not, a table is emitted that allows determining a plausible
// sequence of states traversed to accept that input.
class GenericAutomaton {
// Name of a class that inherits from Transition. All records inheriting from
// this class will be considered when constructing the automaton.
string TransitionClass;
// Names of fields within TransitionClass that define the action symbol. This
// defines the action as an N-tuple.
//
// Each symbol field can be of class, int, string or code type.
// If the type of a field is a class, the Record's name is used verbatim
// in C++ and the class name is used as the C++ type name.
// If the type of a field is a string, code or int, that is also used
// verbatim in C++.
//
// To override the C++ type name for field F, define a field called TypeOf_F.
// This should be a string that will be used verbatim in C++.
//
// As an example, to define a 2-tuple with an enum and a string, one might:
// def MyTransition : Transition {
// MyEnum S1;
// int S2;
// }
// def MyAutomaton : GenericAutomaton }{
// let TransitionClass = "Transition";
// let SymbolFields = ["S1", "S2"];
// let TypeOf_S1 = "MyEnumInCxxKind";
// }
list<string> SymbolFields;
}
// All transitions inherit from Transition.
class Transition {
// A transition S' = T(S) is valid if, for every set bit in NewState, the
// corresponding bit in S is clear. That is:
// def T(S):
// S' = S | NewState
// return S' if S' != S else Failure
//
// The automaton generator uses this property to crawl the set of possible
// transitions from a starting state of 0b0.
bits<32> NewState;
}

View File

@@ -0,0 +1,207 @@
#ifndef LLVM_TABLEGEN_DIRECTIVEEMITTER_H
#define LLVM_TABLEGEN_DIRECTIVEEMITTER_H
#include "llvm/ADT/StringExtras.h"
#include "llvm/TableGen/Record.h"
namespace llvm {
// Wrapper class that contains DirectiveLanguage's information defined in
// DirectiveBase.td and provides helper methods for accessing it.
class DirectiveLanguage {
public:
explicit DirectiveLanguage(const llvm::RecordKeeper &Records)
: Records(Records) {
const auto &DirectiveLanguages = getDirectiveLanguages();
Def = DirectiveLanguages[0];
}
StringRef getName() const { return Def->getValueAsString("name"); }
StringRef getCppNamespace() const {
return Def->getValueAsString("cppNamespace");
}
StringRef getDirectivePrefix() const {
return Def->getValueAsString("directivePrefix");
}
StringRef getClausePrefix() const {
return Def->getValueAsString("clausePrefix");
}
StringRef getClauseEnumSetClass() const {
return Def->getValueAsString("clauseEnumSetClass");
}
StringRef getFlangClauseBaseClass() const {
return Def->getValueAsString("flangClauseBaseClass");
}
bool hasMakeEnumAvailableInNamespace() const {
return Def->getValueAsBit("makeEnumAvailableInNamespace");
}
bool hasEnableBitmaskEnumInNamespace() const {
return Def->getValueAsBit("enableBitmaskEnumInNamespace");
}
std::vector<Record *> getDirectives() const {
return Records.getAllDerivedDefinitions("Directive");
}
std::vector<Record *> getClauses() const {
return Records.getAllDerivedDefinitions("Clause");
}
bool HasValidityErrors() const;
private:
const llvm::Record *Def;
const llvm::RecordKeeper &Records;
std::vector<Record *> getDirectiveLanguages() const {
return Records.getAllDerivedDefinitions("DirectiveLanguage");
}
};
// Base record class used for Directive and Clause class defined in
// DirectiveBase.td.
class BaseRecord {
public:
explicit BaseRecord(const llvm::Record *Def) : Def(Def) {}
StringRef getName() const { return Def->getValueAsString("name"); }
StringRef getAlternativeName() const {
return Def->getValueAsString("alternativeName");
}
// Returns the name of the directive formatted for output. Whitespace are
// replaced with underscores.
std::string getFormattedName() {
StringRef Name = Def->getValueAsString("name");
std::string N = Name.str();
std::replace(N.begin(), N.end(), ' ', '_');
return N;
}
bool isDefault() const { return Def->getValueAsBit("isDefault"); }
// Returns the record name.
StringRef getRecordName() const { return Def->getName(); }
protected:
const llvm::Record *Def;
};
// Wrapper class that contains a Directive's information defined in
// DirectiveBase.td and provides helper methods for accessing it.
class Directive : public BaseRecord {
public:
explicit Directive(const llvm::Record *Def) : BaseRecord(Def) {}
std::vector<Record *> getAllowedClauses() const {
return Def->getValueAsListOfDefs("allowedClauses");
}
std::vector<Record *> getAllowedOnceClauses() const {
return Def->getValueAsListOfDefs("allowedOnceClauses");
}
std::vector<Record *> getAllowedExclusiveClauses() const {
return Def->getValueAsListOfDefs("allowedExclusiveClauses");
}
std::vector<Record *> getRequiredClauses() const {
return Def->getValueAsListOfDefs("requiredClauses");
}
};
// Wrapper class that contains Clause's information defined in DirectiveBase.td
// and provides helper methods for accessing it.
class Clause : public BaseRecord {
public:
explicit Clause(const llvm::Record *Def) : BaseRecord(Def) {}
// Optional field.
StringRef getClangClass() const {
return Def->getValueAsString("clangClass");
}
// Optional field.
StringRef getFlangClass() const {
return Def->getValueAsString("flangClass");
}
// Get the formatted name for Flang parser class. The generic formatted class
// name is constructed from the name were the first letter of each word is
// captitalized and the underscores are removed.
// ex: async -> Async
// num_threads -> NumThreads
std::string getFormattedParserClassName() {
StringRef Name = Def->getValueAsString("name");
std::string N = Name.str();
bool Cap = true;
std::transform(N.begin(), N.end(), N.begin(), [&Cap](unsigned char C) {
if (Cap == true) {
C = llvm::toUpper(C);
Cap = false;
} else if (C == '_') {
Cap = true;
}
return C;
});
llvm::erase_value(N, '_');
return N;
}
// Optional field.
StringRef getEnumName() const {
return Def->getValueAsString("enumClauseValue");
}
std::vector<Record *> getClauseVals() const {
return Def->getValueAsListOfDefs("allowedClauseValues");
}
bool isValueOptional() const { return Def->getValueAsBit("isValueOptional"); }
bool isValueList() const { return Def->getValueAsBit("isValueList"); }
StringRef getDefaultValue() const {
return Def->getValueAsString("defaultValue");
}
bool isImplicit() const { return Def->getValueAsBit("isImplicit"); }
};
// Wrapper class that contains VersionedClause's information defined in
// DirectiveBase.td and provides helper methods for accessing it.
class VersionedClause {
public:
explicit VersionedClause(const llvm::Record *Def) : Def(Def) {}
// Return the specific clause record wrapped in the Clause class.
Clause getClause() const { return Clause{Def->getValueAsDef("clause")}; }
int64_t getMinVersion() const { return Def->getValueAsInt("minVersion"); }
int64_t getMaxVersion() const { return Def->getValueAsInt("maxVersion"); }
private:
const llvm::Record *Def;
};
class ClauseVal : public BaseRecord {
public:
explicit ClauseVal(const llvm::Record *Def) : BaseRecord(Def) {}
int getValue() const { return Def->getValueAsInt("value"); }
bool isUserVisible() const { return Def->getValueAsBit("isUserValue"); }
};
} // namespace llvm
#endif

View File

@@ -0,0 +1,52 @@
//===- llvm/TableGen/Error.h - tblgen error handling helpers ----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains error handling helper routines to pretty-print diagnostic
// messages from tblgen.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TABLEGEN_ERROR_H
#define LLVM_TABLEGEN_ERROR_H
#include "llvm/Support/SourceMgr.h"
#include "llvm/TableGen/Record.h"
namespace llvm {
void PrintNote(const Twine &Msg);
void PrintNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg);
[[noreturn]] void PrintFatalNote(const Twine &Msg);
[[noreturn]] void PrintFatalNote(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg);
[[noreturn]] void PrintFatalNote(const Record *Rec, const Twine &Msg);
[[noreturn]] void PrintFatalNote(const RecordVal *RecVal, const Twine &Msg);
void PrintWarning(const Twine &Msg);
void PrintWarning(ArrayRef<SMLoc> WarningLoc, const Twine &Msg);
void PrintWarning(const char *Loc, const Twine &Msg);
void PrintError(const Twine &Msg);
void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg);
void PrintError(const char *Loc, const Twine &Msg);
void PrintError(const Record *Rec, const Twine &Msg);
void PrintError(const RecordVal *RecVal, const Twine &Msg);
[[noreturn]] void PrintFatalError(const Twine &Msg);
[[noreturn]] void PrintFatalError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg);
[[noreturn]] void PrintFatalError(const Record *Rec, const Twine &Msg);
[[noreturn]] void PrintFatalError(const RecordVal *RecVal, const Twine &Msg);
void CheckAssert(SMLoc Loc, Init *Condition, Init *Message);
extern SourceMgr SrcMgr;
extern unsigned ErrorsPrinted;
} // end namespace "llvm"
#endif

View File

@@ -0,0 +1,29 @@
//===- llvm/TableGen/Main.h - tblgen entry point ----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares the common entry point for tblgen tools.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TABLEGEN_MAIN_H
#define LLVM_TABLEGEN_MAIN_H
namespace llvm {
class raw_ostream;
class RecordKeeper;
/// Perform the action using Records, and write output to OS.
/// Returns true on error, false otherwise.
using TableGenMainFn = bool (raw_ostream &OS, RecordKeeper &Records);
int TableGenMain(const char *argv0, TableGenMainFn *MainFn);
} // end namespace llvm
#endif // LLVM_TABLEGEN_MAIN_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,139 @@
//===- SearchableTable.td ----------------------------------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the key top-level classes needed to produce a reasonably
// generic table that can be binary-searched. Three types of objects can be
// defined using the classes in this file:
//
// 1. (Generic) Enums. By instantiating the GenericEnum class once, an enum with
// the name of the def is generated. It is guarded by the preprocessor define
// GET_name_DECL, where name is the name of the def.
//
// 2. (Generic) Tables and search indices. By instantiating the GenericTable
// class once, a table with the name of the instantiating def is generated and
// guarded by the GET_name_IMPL preprocessor guard.
//
// Both a primary key and additional secondary keys / search indices can also
// be defined, which result in the generation of lookup functions. Their
// declarations and definitions are all guarded by GET_name_DECL and
// GET_name_IMPL, respectively, where name is the name of the underlying table.
//
// See AArch64SystemOperands.td and its generated header for example uses.
//
//===----------------------------------------------------------------------===//
// Define a record derived from this class to generate a generic enum.
//
// The name of the record is used as the type name of the C++ enum.
class GenericEnum {
// Name of a TableGen class. The enum will have one entry for each record
// that derives from that class.
string FilterClass;
// (Optional) Name of a field that is present in all collected records and
// contains the name of enum entries.
//
// If NameField is not set, the record names will be used instead.
string NameField;
// (Optional) Name of a field that is present in all collected records and
// contains the numerical value of enum entries.
//
// If ValueField is not set, enum values will be assigned automatically,
// starting at 0, according to a lexicographical sort of the entry names.
string ValueField;
}
// Define a record derived from this class to generate a generic table. This
// table can have a searchable primary key, and it can also be referenced by
// external search indices.
//
// The name of the record is used as the name of the global primary array of
// entries of the table in C++.
class GenericTable {
// Name of a class. The table will have one entry for each record that
// derives from that class.
string FilterClass;
// Name of the C++ struct/class type that holds table entries. The
// declaration of this type is not generated automatically.
string CppTypeName = FilterClass;
// List of the names of fields of collected records that contain the data for
// table entries, in the order that is used for initialization in C++.
//
// TableGen needs to know the type of the fields so that it can format
// the initializers correctly. It can infer the type of bit, bits, string,
// Intrinsic, and Instruction values.
//
// For each field of the table named xxx, TableGen will look for a field
// named TypeOf_xxx and use that as a more detailed description of the
// type of the field. This is required for fields whose type
// cannot be deduced automatically, such as enum fields. For example:
//
// def MyEnum : GenericEnum {
// let FilterClass = "MyEnum";
// ...
// }
//
// class MyTableEntry {
// MyEnum V;
// ...
// }
//
// def MyTable : GenericTable {
// let FilterClass = "MyTableEntry";
// let Fields = ["V", ...];
// string TypeOf_V = "MyEnum";
// }
//
// If a string field was initialized with a code literal, TableGen will
// emit the code verbatim. However, if a string field was initialized
// in some other way, but should be interpreted as code, then a TypeOf_xxx
// field is necessary, with a value of "code":
//
// string TypeOf_Predicate = "code";
list<string> Fields;
// (Optional) List of fields that make up the primary key.
list<string> PrimaryKey;
// (Optional) Name of the primary key search function.
string PrimaryKeyName;
// See SearchIndex.EarlyOut
bit PrimaryKeyEarlyOut = false;
}
// Define a record derived from this class to generate an additional search
// index for a generic table that has been defined earlier.
//
// The name of the record will be used as the name of the C++ lookup function.
class SearchIndex {
// Table that this search index refers to.
GenericTable Table;
// List of fields that make up the key.
list<string> Key;
// If true, the lookup function will check the first field of the key against
// the minimum and maximum values in the index before entering the binary
// search. This is convenient for tables that add extended data for a subset
// of a larger enum-based space, e.g. extended data about a subset of
// instructions.
//
// Can only be used when the first field is an integral (non-string) type.
bit EarlyOut = false;
}
// Legacy table type with integrated enum.
class SearchableTable {
list<string> SearchableFields;
string EnumNameField = "Name";
string EnumValueField;
}

View File

@@ -0,0 +1,144 @@
//===- SetTheory.h - Generate ordered sets from DAG expressions -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the SetTheory class that computes ordered sets of
// Records from DAG expressions. Operators for standard set operations are
// predefined, and it is possible to add special purpose set operators as well.
//
// The user may define named sets as Records of predefined classes. Set
// expanders can be added to a SetTheory instance to teach it how to find the
// elements of such a named set.
//
// These are the predefined operators. The argument lists can be individual
// elements (defs), other sets (defs of expandable classes), lists, or DAG
// expressions that are evaluated recursively.
//
// - (add S1, S2 ...) Union sets. This is also how sets are created from element
// lists.
//
// - (sub S1, S2, ...) Set difference. Every element in S1 except for the
// elements in S2, ...
//
// - (and S1, S2) Set intersection. Every element in S1 that is also in S2.
//
// - (shl S, N) Shift left. Remove the first N elements from S.
//
// - (trunc S, N) Truncate. The first N elements of S.
//
// - (rotl S, N) Rotate left. Same as (add (shl S, N), (trunc S, N)).
//
// - (rotr S, N) Rotate right.
//
// - (decimate S, N) Decimate S by picking every N'th element, starting with
// the first one. For instance, (decimate S, 2) returns the even elements of
// S.
//
// - (sequence "Format", From, To) Generate a sequence of defs with printf.
// For instance, (sequence "R%u", 0, 3) -> [ R0, R1, R2, R3 ]
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TABLEGEN_SETTHEORY_H
#define LLVM_TABLEGEN_SETTHEORY_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/SMLoc.h"
#include <map>
#include <memory>
#include <vector>
namespace llvm {
class DagInit;
class Init;
class Record;
class SetTheory {
public:
using RecVec = std::vector<Record *>;
using RecSet = SmallSetVector<Record *, 16>;
/// Operator - A callback representing a DAG operator.
class Operator {
virtual void anchor();
public:
virtual ~Operator() = default;
/// apply - Apply this operator to Expr's arguments and insert the result
/// in Elts.
virtual void apply(SetTheory&, DagInit *Expr, RecSet &Elts,
ArrayRef<SMLoc> Loc) = 0;
};
/// Expander - A callback function that can transform a Record representing a
/// set into a fully expanded list of elements. Expanders provide a way for
/// users to define named sets that can be used in DAG expressions.
class Expander {
virtual void anchor();
public:
virtual ~Expander() = default;
virtual void expand(SetTheory&, Record*, RecSet &Elts) = 0;
};
private:
// Map set defs to their fully expanded contents. This serves as a memoization
// cache and it makes it possible to return const references on queries.
using ExpandMap = std::map<Record *, RecVec>;
ExpandMap Expansions;
// Known DAG operators by name.
StringMap<std::unique_ptr<Operator>> Operators;
// Typed expanders by class name.
StringMap<std::unique_ptr<Expander>> Expanders;
public:
/// Create a SetTheory instance with only the standard operators.
SetTheory();
/// addExpander - Add an expander for Records with the named super class.
void addExpander(StringRef ClassName, std::unique_ptr<Expander>);
/// addFieldExpander - Add an expander for ClassName that simply evaluates
/// FieldName in the Record to get the set elements. That is all that is
/// needed for a class like:
///
/// class Set<dag d> {
/// dag Elts = d;
/// }
///
void addFieldExpander(StringRef ClassName, StringRef FieldName);
/// addOperator - Add a DAG operator.
void addOperator(StringRef Name, std::unique_ptr<Operator>);
/// evaluate - Evaluate Expr and append the resulting set to Elts.
void evaluate(Init *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc);
/// evaluate - Evaluate a sequence of Inits and append to Elts.
template<typename Iter>
void evaluate(Iter begin, Iter end, RecSet &Elts, ArrayRef<SMLoc> Loc) {
while (begin != end)
evaluate(*begin++, Elts, Loc);
}
/// expand - Expand a record into a set of elements if possible. Return a
/// pointer to the expanded elements, or NULL if Set cannot be expanded
/// further.
const RecVec *expand(Record *Set);
};
} // end namespace llvm
#endif // LLVM_TABLEGEN_SETTHEORY_H

View File

@@ -0,0 +1,54 @@
//===- StringMatcher.h - Generate a matcher for input strings ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the StringMatcher class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TABLEGEN_STRINGMATCHER_H
#define LLVM_TABLEGEN_STRINGMATCHER_H
#include "llvm/ADT/StringRef.h"
#include <string>
#include <utility>
#include <vector>
namespace llvm {
class raw_ostream;
/// Given a list of strings and code to execute when they match, output a
/// simple switch tree to classify the input string.
///
/// If a match is found, the code in Matches[i].second is executed; control must
/// not exit this code fragment. If nothing matches, execution falls through.
class StringMatcher {
public:
using StringPair = std::pair<std::string, std::string>;
private:
StringRef StrVariableName;
const std::vector<StringPair> &Matches;
raw_ostream &OS;
public:
StringMatcher(StringRef strVariableName,
const std::vector<StringPair> &matches, raw_ostream &os)
: StrVariableName(strVariableName), Matches(matches), OS(os) {}
void Emit(unsigned Indent = 0, bool IgnoreDuplicates = false) const;
private:
bool EmitStringMatcherForChar(const std::vector<const StringPair *> &Matches,
unsigned CharNo, unsigned IndentCount,
bool IgnoreDuplicates) const;
};
} // end namespace llvm
#endif // LLVM_TABLEGEN_STRINGMATCHER_H

View File

@@ -0,0 +1,104 @@
//===- StringToOffsetTable.h - Emit a big concatenated string ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TABLEGEN_STRINGTOOFFSETTABLE_H
#define LLVM_TABLEGEN_STRINGTOOFFSETTABLE_H
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/raw_ostream.h"
#include <cctype>
namespace llvm {
/// StringToOffsetTable - This class uniques a bunch of nul-terminated strings
/// and keeps track of their offset in a massive contiguous string allocation.
/// It can then output this string blob and use indexes into the string to
/// reference each piece.
class StringToOffsetTable {
StringMap<unsigned> StringOffset;
std::string AggregateString;
public:
bool Empty() const { return StringOffset.empty(); }
unsigned GetOrAddStringOffset(StringRef Str, bool appendZero = true) {
auto IterBool =
StringOffset.insert(std::make_pair(Str, AggregateString.size()));
if (IterBool.second) {
// Add the string to the aggregate if this is the first time found.
AggregateString.append(Str.begin(), Str.end());
if (appendZero)
AggregateString += '\0';
}
return IterBool.first->second;
}
void EmitString(raw_ostream &O) {
// Escape the string.
SmallString<256> Str;
raw_svector_ostream(Str).write_escaped(AggregateString);
AggregateString = std::string(Str.str());
O << " \"";
unsigned CharsPrinted = 0;
for (unsigned i = 0, e = AggregateString.size(); i != e; ++i) {
if (CharsPrinted > 70) {
O << "\"\n \"";
CharsPrinted = 0;
}
O << AggregateString[i];
++CharsPrinted;
// Print escape sequences all together.
if (AggregateString[i] != '\\')
continue;
assert(i + 1 < AggregateString.size() && "Incomplete escape sequence!");
if (isdigit(AggregateString[i + 1])) {
assert(isdigit(AggregateString[i + 2]) &&
isdigit(AggregateString[i + 3]) &&
"Expected 3 digit octal escape!");
O << AggregateString[++i];
O << AggregateString[++i];
O << AggregateString[++i];
CharsPrinted += 3;
} else {
O << AggregateString[++i];
++CharsPrinted;
}
}
O << "\"";
}
/// Emit the string using character literals. MSVC has a limitation that
/// string literals cannot be longer than 64K.
void EmitCharArray(raw_ostream &O) {
assert(AggregateString.find(')') == std::string::npos &&
"can't emit raw string with closing parens");
int Count = 0;
O << ' ';
for (char C : AggregateString) {
O << " \'";
O.write_escaped(StringRef(&C, 1));
O << "\',";
Count++;
if (Count > 14) {
O << "\n ";
Count = 0;
}
}
O << '\n';
}
};
} // end namespace llvm
#endif

View File

@@ -0,0 +1,29 @@
//===- llvm/TableGen/TableGenBackend.h - Backend utilities ------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Useful utilities for TableGen backends.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TABLEGEN_TABLEGENBACKEND_H
#define LLVM_TABLEGEN_TABLEGENBACKEND_H
namespace llvm {
class StringRef;
class raw_ostream;
/// emitSourceFileHeader - Output an LLVM style file header to the specified
/// raw_ostream.
void emitSourceFileHeader(StringRef Desc, raw_ostream &OS);
extern bool TimeRegions;
} // End llvm namespace
#endif