[Mlir-commits] [mlir] 415fab6 - [TableGen] Eliminate the 'code' type
Paul C. Anagnostopoulos
llvmlistbot at llvm.org
Thu Dec 3 07:20:16 PST 2020
Author: Paul C. Anagnostopoulos
Date: 2020-12-03T10:19:11-05:00
New Revision: 415fab6f67b4db59abe533130272d55b4efbf0cb
URL: https://github.com/llvm/llvm-project/commit/415fab6f67b4db59abe533130272d55b4efbf0cb
DIFF: https://github.com/llvm/llvm-project/commit/415fab6f67b4db59abe533130272d55b4efbf0cb.diff
LOG: [TableGen] Eliminate the 'code' type
Update the documentation.
Rework various backends that relied on the code type.
Differential Revision: https://reviews.llvm.org/D92269
Added:
Modified:
clang/utils/TableGen/ClangOptionDocEmitter.cpp
llvm/docs/TableGen/BackEnds.rst
llvm/docs/TableGen/BackGuide.rst
llvm/docs/TableGen/ProgRef.rst
llvm/include/llvm/TableGen/Error.h
llvm/include/llvm/TableGen/Record.h
llvm/include/llvm/TableGen/SearchableTable.td
llvm/lib/TableGen/Error.cpp
llvm/lib/TableGen/JSONBackend.cpp
llvm/lib/TableGen/Record.cpp
llvm/lib/TableGen/TGLexer.cpp
llvm/lib/TableGen/TGLexer.h
llvm/lib/TableGen/TGParser.cpp
llvm/lib/Target/AMDGPU/MIMGInstructions.td
llvm/test/TableGen/code.td
llvm/test/TableGen/generic-tables.td
llvm/test/TableGen/interleave.td
llvm/test/TableGen/unterminated-code-block.td
llvm/utils/TableGen/AsmWriterEmitter.cpp
llvm/utils/TableGen/DFAEmitter.cpp
llvm/utils/TableGen/GICombinerEmitter.cpp
llvm/utils/TableGen/RISCVCompressInstEmitter.cpp
llvm/utils/TableGen/SearchableTableEmitter.cpp
mlir/include/mlir/TableGen/Operator.h
mlir/lib/TableGen/Attribute.cpp
mlir/lib/TableGen/Dialect.cpp
mlir/lib/TableGen/Operator.cpp
mlir/lib/TableGen/Pattern.cpp
mlir/lib/TableGen/Type.cpp
mlir/lib/TableGen/TypeDef.cpp
mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
Removed:
################################################################################
diff --git a/clang/utils/TableGen/ClangOptionDocEmitter.cpp b/clang/utils/TableGen/ClangOptionDocEmitter.cpp
index 23aa31cc732f..0e079b6b505a 100644
--- a/clang/utils/TableGen/ClangOptionDocEmitter.cpp
+++ b/clang/utils/TableGen/ClangOptionDocEmitter.cpp
@@ -217,8 +217,6 @@ std::string getRSTStringWithTextFallback(const Record *R, StringRef Primary,
StringRef Value;
if (auto *SV = dyn_cast_or_null<StringInit>(V->getValue()))
Value = SV->getValue();
- else if (auto *CV = dyn_cast_or_null<CodeInit>(V->getValue()))
- Value = CV->getValue();
if (!Value.empty())
return Field == Primary ? Value.str() : escapeRST(Value);
}
diff --git a/llvm/docs/TableGen/BackEnds.rst b/llvm/docs/TableGen/BackEnds.rst
index b4ccdf95485e..1e1a4e71a1fd 100644
--- a/llvm/docs/TableGen/BackEnds.rst
+++ b/llvm/docs/TableGen/BackEnds.rst
@@ -693,8 +693,8 @@ This class provides six fields.
table that holds the entries. If unspecified, the ``FilterClass`` name is
used.
-* ``list<string> Fields``. A list of the names of the fields in the
- collected records that contain the data for the table entries. The order of
+* ``list<string> Fields``. A list of the names of the fields *in the
+ collected records* that contain the data for the table entries. The order of
this list determines the order of the values in the C++ initializers. See
below for information about the types of these fields.
@@ -706,13 +706,26 @@ This class provides six fields.
* ``bit PrimaryKeyEarlyOut``. See the third example below.
-TableGen attempts to deduce the type of each of the table fields. It can
-deduce ``bit``, ``bits<n>``, ``string``, ``Intrinsic``, and ``Instruction``.
-These can be used in the primary key. TableGen also deduces ``code``, but it
-cannot be used in the primary key. Any other field types must be specified
+TableGen attempts to deduce the type of each of the table fields so that it
+can format the C++ initializers in the emitted table. It can deduce ``bit``,
+``bits<n>``, ``string``, ``Intrinsic``, and ``Instruction``. These can be
+used in the primary key. Any other field types must be specified
explicitly; this is done as shown in the second example below. Such fields
cannot be used in the primary key.
+One special case of the field type has to do with code. Arbitrary code is
+represented by a string, but has to be emitted as a C++ initializer without
+quotes. If the code field was defined using a code literal (``[{...}]``),
+then TableGen will know to emit it without quotes. However, if it was
+defined using a string literal or complex string expression, then TableGen
+will not know. In this case, you can force TableGen to treat the field as
+code by including the following line in the ``GenericTable`` record, where
+*xxx* is the code field name.
+
+.. code-block:: text
+
+ string TypeOf_xxx = "code";
+
Here is an example where TableGen can deduce the field types. Note that the
table entry records are anonymous; the names of entry records are
irrelevant.
@@ -793,7 +806,7 @@ pointer if no entry is found.
This example includes a field whose type TableGen cannot deduce. The ``Kind``
field uses the enumerated type ``CEnum`` defined above. To inform TableGen
-of the type, the class derived from ``GenericTable`` must include a field
+of the type, the record derived from ``GenericTable`` must include a string field
named ``TypeOf_``\ *field*, where *field* is the name of the field whose type
is required.
@@ -802,7 +815,7 @@ is required.
def CTable : GenericTable {
let FilterClass = "CEntry";
let Fields = ["Name", "Kind", "Encoding"];
- GenericEnum TypeOf_Kind = CEnum;
+ string TypeOf_Kind = "CEnum";
let PrimaryKey = ["Encoding"];
let PrimaryKeyName = "lookupCEntryByEncoding";
}
diff --git a/llvm/docs/TableGen/BackGuide.rst b/llvm/docs/TableGen/BackGuide.rst
index 515eeab2403a..f21910c56ac2 100644
--- a/llvm/docs/TableGen/BackGuide.rst
+++ b/llvm/docs/TableGen/BackGuide.rst
@@ -287,9 +287,9 @@ value. The static function ``get()`` can be used to obtain the singleton
This class, a subclass of ``Init``, acts as the parent class of the classes
that represent specific value types (except for the unset value). These
-classes include ``BitInit``, ``BitsInit``, ``CodeInit``, ``DagInit``,
-``DefInit``, ``IntInit``, ``ListInit``, and ``StringInit``. (There are
-additional derived types used by the TableGen parser.)
+classes include ``BitInit``, ``BitsInit``, ``DagInit``, ``DefInit``,
+``IntInit``, ``ListInit``, and ``StringInit``. (There are additional derived
+types used by the TableGen parser.)
This class includes a data member that specifies the ``RecTy`` type of the
value. It provides a function to get that ``RecTy`` type.
@@ -330,18 +330,6 @@ The class provides the following additional functions.
* A function that gets a bit specified by an integer index.
-``CodeInit``
-~~~~~~~~~~~~
-
-The ``CodeInit`` class is a subclass of ``TypedInit``. Its instances
-represent arbitrary-length strings produced from ``code`` literals in the
-TableGen files. It includes a data member that contains a ``StringRef`` of
-the value.
-
-The class provides the usual ``get()`` and ``getValue()`` functions. The
-latter function returns the ``StringRef``.
-
-
``DagInit``
~~~~~~~~~~~
diff --git a/llvm/docs/TableGen/ProgRef.rst b/llvm/docs/TableGen/ProgRef.rst
index c805afc8ccc1..342b91a0c437 100644
--- a/llvm/docs/TableGen/ProgRef.rst
+++ b/llvm/docs/TableGen/ProgRef.rst
@@ -167,10 +167,11 @@ TableGen has two kinds of string literals:
.. productionlist::
TokString: '"' (non-'"' characters and escapes) '"'
- TokCodeFragment: "[{" (shortest text not containing "}]") "}]"
+ TokCode: "[{" (shortest text not containing "}]") "}]"
-A :token:`TokCodeFragment` is nothing more than a multi-line string literal
-delimited by ``[{`` and ``}]``. It can break across lines.
+A :token:`TokCode` is nothing more than a multi-line string literal
+delimited by ``[{`` and ``}]``. It can break across lines and the
+line breaks are retained in the string.
The current implementation accepts the following escape sequences::
@@ -254,7 +255,7 @@ high-level types (e.g., ``dag``). This flexibility allows you to describe a
wide range of records conveniently and compactly.
.. productionlist::
- Type: "bit" | "int" | "string" | "code" | "dag"
+ Type: "bit" | "int" | "string" | "dag"
:| "bits" "<" `TokInteger` ">"
:| "list" "<" `Type` ">"
:| `ClassID`
@@ -271,11 +272,6 @@ wide range of records conveniently and compactly.
The ``string`` type represents an ordered sequence of characters of arbitrary
length.
-``code``
- The ``code`` type represents a code fragment. The values are the same as
- those for the ``string`` type; the ``code`` type is provided just to indicate
- the programmer's intention.
-
``bits<``\ *n*\ ``>``
The ``bits`` type is a fixed-sized integer of arbitrary length *n* that
is treated as separate bits. These bits can be accessed individually.
@@ -348,12 +344,12 @@ Simple values
The :token:`SimpleValue` has a number of forms.
.. productionlist::
- SimpleValue: `TokInteger` | `TokString`+ | `TokCodeFragment`
+ SimpleValue: `TokInteger` | `TokString`+ | `TokCode`
-A value can be an integer literal, a string literal, or a code fragment
-literal. Multiple adjacent string literals are concatenated as in C/C++; the
-simple value is the concatenation of the strings. Code fragments become
-strings and then are indistinguishable from them.
+A value can be an integer literal, a string literal, or a code literal.
+Multiple adjacent string literals are concatenated as in C/C++; the simple
+value is the concatenation of the strings. Code literals become strings and
+are then indistinguishable from them.
.. productionlist::
SimpleValue2: "true" | "false"
@@ -616,14 +612,15 @@ name of a multiclass.
.. productionlist::
Body: ";" | "{" `BodyItem`* "}"
- BodyItem: `Type` `TokIdentifier` ["=" `Value`] ";"
+ BodyItem: (`Type` | "code") `TokIdentifier` ["=" `Value`] ";"
:| "let" `TokIdentifier` ["{" `RangeList` "}"] "=" `Value` ";"
:| "defvar" `TokIdentifier` "=" `Value` ";"
A field definition in the body specifies a field to be included in the class
or record. If no initial value is specified, then the field's value is
uninitialized. The type must be specified; TableGen will not infer it from
-the value.
+the value. The keyword ``code`` may be used to emphasize that the field
+has a string value that is code.
The ``let`` form is used to reset a field to a new value. This can be done
for fields defined directly in the body or fields inherited from
diff --git a/llvm/include/llvm/TableGen/Error.h b/llvm/include/llvm/TableGen/Error.h
index a742e9e1606c..f63b50ad786c 100644
--- a/llvm/include/llvm/TableGen/Error.h
+++ b/llvm/include/llvm/TableGen/Error.h
@@ -22,6 +22,7 @@ namespace llvm {
void PrintNote(const Twine &Msg);
void PrintNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg);
+LLVM_ATTRIBUTE_NORETURN void PrintFatalNote(const Twine &Msg);
LLVM_ATTRIBUTE_NORETURN void PrintFatalNote(ArrayRef<SMLoc> ErrorLoc,
const Twine &Msg);
LLVM_ATTRIBUTE_NORETURN void PrintFatalNote(const Record *Rec,
@@ -37,6 +38,7 @@ 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);
LLVM_ATTRIBUTE_NORETURN void PrintFatalError(const Twine &Msg);
LLVM_ATTRIBUTE_NORETURN void PrintFatalError(ArrayRef<SMLoc> ErrorLoc,
diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h
index 20b786dc6e42..1c3ec5fb21f5 100644
--- a/llvm/include/llvm/TableGen/Record.h
+++ b/llvm/include/llvm/TableGen/Record.h
@@ -58,7 +58,6 @@ class RecTy {
enum RecTyKind {
BitRecTyKind,
BitsRecTyKind,
- CodeRecTyKind,
IntRecTyKind,
StringRecTyKind,
ListRecTyKind,
@@ -138,24 +137,6 @@ class BitsRecTy : public RecTy {
bool typeIsA(const RecTy *RHS) const override;
};
-/// 'code' - Represent a code fragment
-class CodeRecTy : public RecTy {
- static CodeRecTy Shared;
-
- CodeRecTy() : RecTy(CodeRecTyKind) {}
-
-public:
- static bool classof(const RecTy *RT) {
- return RT->getRecTyKind() == CodeRecTyKind;
- }
-
- static CodeRecTy *get() { return &Shared; }
-
- std::string getAsString() const override { return "code"; }
-
- bool typeIsConvertibleTo(const RecTy *RHS) const override;
-};
-
/// 'int' - Represent an integer value of no particular size
class IntRecTy : public RecTy {
static IntRecTy Shared;
@@ -306,7 +287,6 @@ class Init {
IK_FirstTypedInit,
IK_BitInit,
IK_BitsInit,
- IK_CodeInit,
IK_DagInit,
IK_DefInit,
IK_FieldInit,
@@ -597,16 +577,18 @@ class IntInit : public TypedInit {
/// "foo" - Represent an initialization by a string value.
class StringInit : public TypedInit {
-//// enum StringFormat {
-//// SF_String, // Format as "text"
-//// SF_Code, // Format as [{text}]
-//// };
+public:
+ enum StringFormat {
+ SF_String, // Format as "text"
+ SF_Code, // Format as [{text}]
+ };
+private:
StringRef Value;
-//// StringFormat Format;
+ StringFormat Format;
- explicit StringInit(StringRef V)
- : TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {}
+ explicit StringInit(StringRef V, StringFormat Fmt)
+ : TypedInit(IK_StringInit, StringRecTy::get()), Value(V), Format(Fmt) {}
public:
StringInit(const StringInit &) = delete;
@@ -616,48 +598,25 @@ class StringInit : public TypedInit {
return I->getKind() == IK_StringInit;
}
- static StringInit *get(StringRef);
-
- StringRef getValue() const { return Value; }
-
- Init *convertInitializerTo(RecTy *Ty) const override;
+ static StringInit *get(StringRef, StringFormat Fmt = SF_String);
- bool isConcrete() const override { return true; }
- std::string getAsString() const override { return "\"" + Value.str() + "\""; }
-
- std::string getAsUnquotedString() const override {
- return std::string(Value);
- }
-
- Init *getBit(unsigned Bit) const override {
- llvm_unreachable("Illegal bit reference off string");
- }
-};
-
-class CodeInit : public TypedInit {
- StringRef Value;
-
- explicit CodeInit(StringRef V)
- : TypedInit(IK_CodeInit, static_cast<RecTy *>(CodeRecTy::get())),
- Value(V) {}
-
-public:
- CodeInit(const StringInit &) = delete;
- CodeInit &operator=(const StringInit &) = delete;
-
- static bool classof(const Init *I) {
- return I->getKind() == IK_CodeInit;
+ static StringFormat determineFormat(StringFormat Fmt1, StringFormat Fmt2) {
+ return (Fmt1 == SF_Code || Fmt2 == SF_Code) ? SF_Code : SF_String;
}
- static CodeInit *get(StringRef);
-
StringRef getValue() const { return Value; }
+ StringFormat getFormat() const { return Format; }
+ bool hasCodeFormat() const { return Format == SF_Code; }
Init *convertInitializerTo(RecTy *Ty) const override;
bool isConcrete() const override { return true; }
+
std::string getAsString() const override {
- return "[{" + Value.str() + "}]";
+ if (Format == SF_String)
+ return "\"" + Value.str() + "\"";
+ else
+ return "[{" + Value.str() + "}]";
}
std::string getAsUnquotedString() const override {
@@ -1438,6 +1397,9 @@ class RecordVal {
/// Get the type of the field value as a RecTy.
RecTy *getType() const { return TyAndPrefix.getPointer(); }
+ /// Get the type of the field for printing purposes.
+ std::string getPrintType() const;
+
/// Get the value of the field as an Init.
Init *getValue() const { return Value; }
@@ -1675,11 +1637,6 @@ class Record {
/// not a string and llvm::Optional() if the field does not exist.
llvm::Optional<StringRef> getValueAsOptionalString(StringRef FieldName) const;
- /// This method looks up the specified field and returns
- /// its value as a string, throwing an exception if the field if the value is
- /// not a code block and llvm::Optional() if the field does not exist.
- llvm::Optional<StringRef> getValueAsOptionalCode(StringRef FieldName) const;
-
/// This method looks up the specified field and returns
/// its value as a BitsInit, throwing an exception if the field does not exist
/// or if the value is not the right type.
diff --git a/llvm/include/llvm/TableGen/SearchableTable.td b/llvm/include/llvm/TableGen/SearchableTable.td
index 32b9829aa072..61dfa5c70706 100644
--- a/llvm/include/llvm/TableGen/SearchableTable.td
+++ b/llvm/include/llvm/TableGen/SearchableTable.td
@@ -67,9 +67,13 @@ class GenericTable {
// 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++.
//
- // For each field of the table named XXX, TableGen will look for a value
- // called TypeOf_XXX and use that as a more detailed description of the
- // type of the field if present. This is required for fields whose type
+ // 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 {
@@ -85,15 +89,15 @@ class GenericTable {
// def MyTable : GenericTable {
// let FilterClass = "MyTableEntry";
// let Fields = ["V", ...];
- // GenericEnum TypeOf_V = MyEnum;
+ // string TypeOf_V = "MyEnum";
// }
//
- // Fields of type bit, bits<N>, string, Intrinsic, and Instruction (or
- // derived classes of those) are supported natively.
+ // 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":
//
- // Additionally, fields of type `code` can appear, where the value is used
- // verbatim as an initializer. However, these fields cannot be used as
- // search keys.
+ // string TypeOf_Predicate = "code";
list<string> Fields;
// (Optional) List of fields that make up the primary key.
diff --git a/llvm/lib/TableGen/Error.cpp b/llvm/lib/TableGen/Error.cpp
index 015b1d350197..eed4de67942a 100644
--- a/llvm/lib/TableGen/Error.cpp
+++ b/llvm/lib/TableGen/Error.cpp
@@ -52,6 +52,13 @@ void PrintNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg) {
// Functions to print fatal notes.
+void PrintFatalNote(const Twine &Msg) {
+ PrintNote(Msg);
+ // The following call runs the file cleanup handlers.
+ sys::RunInterruptHandlers();
+ std::exit(1);
+}
+
void PrintFatalNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg) {
PrintNote(NoteLoc, Msg);
// The following call runs the file cleanup handlers.
@@ -107,6 +114,12 @@ void PrintError(const Record *Rec, const Twine &Msg) {
PrintMessage(Rec->getLoc(), SourceMgr::DK_Error, Msg);
}
+// This method takes a RecordVal and uses the source location
+// stored in it.
+void PrintError(const RecordVal *RecVal, const Twine &Msg) {
+ PrintMessage(RecVal->getLoc(), SourceMgr::DK_Error, Msg);
+}
+
// Functions to print fatal errors.
void PrintFatalError(const Twine &Msg) {
diff --git a/llvm/lib/TableGen/JSONBackend.cpp b/llvm/lib/TableGen/JSONBackend.cpp
index 196644cda667..ea82934e5d3b 100644
--- a/llvm/lib/TableGen/JSONBackend.cpp
+++ b/llvm/lib/TableGen/JSONBackend.cpp
@@ -59,8 +59,6 @@ json::Value JSONEmitter::translateInit(const Init &I) {
return Int->getValue();
} else if (auto *Str = dyn_cast<StringInit>(&I)) {
return Str->getValue();
- } else if (auto *Code = dyn_cast<CodeInit>(&I)) {
- return Code->getValue();
} else if (auto *List = dyn_cast<ListInit>(&I)) {
json::Array array;
for (auto val : *List)
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index a8f0e19a2bbd..1e2d75f3fe8d 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -43,15 +43,11 @@ using namespace llvm;
static BumpPtrAllocator Allocator;
-STATISTIC(CodeInitsConstructed,
- "The total number of unique CodeInits constructed");
-
//===----------------------------------------------------------------------===//
// Type implementations
//===----------------------------------------------------------------------===//
BitRecTy BitRecTy::Shared;
-CodeRecTy CodeRecTy::Shared;
IntRecTy IntRecTy::Shared;
StringRecTy StringRecTy::Shared;
DagRecTy DagRecTy::Shared;
@@ -113,18 +109,13 @@ bool IntRecTy::typeIsConvertibleTo(const RecTy *RHS) const {
return kind==BitRecTyKind || kind==BitsRecTyKind || kind==IntRecTyKind;
}
-bool CodeRecTy::typeIsConvertibleTo(const RecTy *RHS) const {
- RecTyKind Kind = RHS->getRecTyKind();
- return Kind == CodeRecTyKind || Kind == StringRecTyKind;
-}
-
std::string StringRecTy::getAsString() const {
return "string";
}
bool StringRecTy::typeIsConvertibleTo(const RecTy *RHS) const {
RecTyKind Kind = RHS->getRecTyKind();
- return Kind == StringRecTyKind || Kind == CodeRecTyKind;
+ return Kind == StringRecTyKind;
}
std::string ListRecTy::getAsString() const {
@@ -514,38 +505,26 @@ IntInit::convertInitializerBitRange(ArrayRef<unsigned> Bits) const {
return BitsInit::get(NewBits);
}
-CodeInit *CodeInit::get(StringRef V) {
- static StringMap<CodeInit*, BumpPtrAllocator &> ThePool(Allocator);
+StringInit *StringInit::get(StringRef V, StringFormat Fmt) {
+ static StringMap<StringInit*, BumpPtrAllocator &> StringPool(Allocator);
+ static StringMap<StringInit*, BumpPtrAllocator &> CodePool(Allocator);
- auto &Entry = *ThePool.insert(std::make_pair(V, nullptr)).first;
- if (!Entry.second)
- Entry.second = new(Allocator) CodeInit(Entry.getKey());
- return Entry.second;
-}
-
-StringInit *StringInit::get(StringRef V) {
- static StringMap<StringInit*, BumpPtrAllocator &> ThePool(Allocator);
-
- auto &Entry = *ThePool.insert(std::make_pair(V, nullptr)).first;
- if (!Entry.second)
- Entry.second = new(Allocator) StringInit(Entry.getKey());
- return Entry.second;
+ if (Fmt == SF_String) {
+ auto &Entry = *StringPool.insert(std::make_pair(V, nullptr)).first;
+ if (!Entry.second)
+ Entry.second = new (Allocator) StringInit(Entry.getKey(), Fmt);
+ return Entry.second;
+ } else {
+ auto &Entry = *CodePool.insert(std::make_pair(V, nullptr)).first;
+ if (!Entry.second)
+ Entry.second = new (Allocator) StringInit(Entry.getKey(), Fmt);
+ return Entry.second;
+ }
}
Init *StringInit::convertInitializerTo(RecTy *Ty) const {
if (isa<StringRecTy>(Ty))
return const_cast<StringInit *>(this);
- if (isa<CodeRecTy>(Ty))
- return CodeInit::get(getValue());
-
- return nullptr;
-}
-
-Init *CodeInit::convertInitializerTo(RecTy *Ty) const {
- if (isa<CodeRecTy>(Ty))
- return const_cast<CodeInit *>(this);
- if (isa<StringRecTy>(Ty))
- return StringInit::get(getValue());
return nullptr;
}
@@ -868,7 +847,9 @@ static StringInit *ConcatStringInits(const StringInit *I0,
const StringInit *I1) {
SmallString<80> Concat(I0->getValue());
Concat.append(I1->getValue());
- return StringInit::get(Concat);
+ return StringInit::get(Concat,
+ StringInit::determineFormat(I0->getFormat(),
+ I1->getFormat()));
}
static StringInit *interleaveStringList(const ListInit *List,
@@ -876,12 +857,15 @@ static StringInit *interleaveStringList(const ListInit *List,
if (List->size() == 0)
return StringInit::get("");
SmallString<80> Result(dyn_cast<StringInit>(List->getElement(0))->getValue());
+ StringInit::StringFormat Fmt = StringInit::SF_String;
for (unsigned I = 1, E = List->size(); I < E; ++I) {
Result.append(Delim->getValue());
- Result.append(dyn_cast<StringInit>(List->getElement(I))->getValue());
+ auto *StrInit = dyn_cast<StringInit>(List->getElement(I));
+ Result.append(StrInit->getValue());
+ Fmt = StringInit::determineFormat(Fmt, StrInit->getFormat());
}
- return StringInit::get(Result);
+ return StringInit::get(Result, Fmt);
}
static StringInit *interleaveIntList(const ListInit *List,
@@ -2139,6 +2123,21 @@ StringRef RecordVal::getName() const {
return cast<StringInit>(getNameInit())->getValue();
}
+std::string RecordVal::getPrintType() const {
+ if (getType() == StringRecTy::get()) {
+ if (auto *StrInit = dyn_cast<StringInit>(Value)) {
+ if (StrInit->hasCodeFormat())
+ return "code";
+ else
+ return "string";
+ } else {
+ return "string";
+ }
+ } else {
+ return TyAndPrefix.getPointer()->getAsString();
+ }
+}
+
bool RecordVal::setValue(Init *V) {
if (V) {
Value = V->getCastTo(getType());
@@ -2193,7 +2192,7 @@ LLVM_DUMP_METHOD void RecordVal::dump() const { errs() << *this; }
void RecordVal::print(raw_ostream &OS, bool PrintSem) const {
if (getPrefix()) OS << "field ";
- OS << *getType() << " " << getNameInitAsString();
+ OS << getPrintType() << " " << getNameInitAsString();
if (getValue())
OS << " = " << *getValue();
@@ -2365,6 +2364,7 @@ StringRef Record::getValueAsString(StringRef FieldName) const {
"' does not have a field named `" + FieldName + "'!\n");
return S.getValue();
}
+
llvm::Optional<StringRef>
Record::getValueAsOptionalString(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName);
@@ -2375,28 +2375,11 @@ Record::getValueAsOptionalString(StringRef FieldName) const {
if (StringInit *SI = dyn_cast<StringInit>(R->getValue()))
return SI->getValue();
- if (CodeInit *CI = dyn_cast<CodeInit>(R->getValue()))
- return CI->getValue();
PrintFatalError(getLoc(),
"Record `" + getName() + "', ` field `" + FieldName +
"' exists but does not have a string initializer!");
}
-llvm::Optional<StringRef>
-Record::getValueAsOptionalCode(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (!R || !R->getValue())
- return llvm::Optional<StringRef>();
- if (isa<UnsetInit>(R->getValue()))
- return llvm::Optional<StringRef>();
-
- if (CodeInit *CI = dyn_cast<CodeInit>(R->getValue()))
- return CI->getValue();
-
- PrintFatalError(getLoc(),
- "Record `" + getName() + "', field `" + FieldName +
- "' exists but does not have a code initializer!");
-}
BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName);
@@ -2473,8 +2456,6 @@ Record::getValueAsListOfStrings(StringRef FieldName) const {
for (Init *I : List->getValues()) {
if (StringInit *SI = dyn_cast<StringInit>(I))
Strings.push_back(SI->getValue());
- else if (CodeInit *CI = dyn_cast<CodeInit>(I))
- Strings.push_back(CI->getValue());
else
PrintFatalError(getLoc(),
Twine("Record `") + getName() + "', field `" + FieldName +
diff --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp
index a54161c62d99..df0df96f40eb 100644
--- a/llvm/lib/TableGen/TGLexer.cpp
+++ b/llvm/lib/TableGen/TGLexer.cpp
@@ -540,7 +540,7 @@ tgtok::TokKind TGLexer::LexBracket() {
}
}
- return ReturnError(CodeStart-2, "Unterminated Code Block");
+ return ReturnError(CodeStart - 2, "Unterminated code block");
}
/// LexExclaim - Lex '!' and '![a-zA-Z]+'.
diff --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h
index 607f428c96d8..1856bef3ea9b 100644
--- a/llvm/lib/TableGen/TGLexer.h
+++ b/llvm/lib/TableGen/TGLexer.h
@@ -86,8 +86,8 @@ class TGLexer {
// Information about the current token.
const char *TokStart = nullptr;
tgtok::TokKind CurCode = tgtok::TokKind::Eof;
- std::string CurStrVal; // This is valid for ID, STRVAL, VARNAME, CODEFRAGMENT
- int64_t CurIntVal = 0; // This is valid for INTVAL.
+ std::string CurStrVal; // This is valid for Id, StrVal, VarName, CodeFragment
+ int64_t CurIntVal = 0; // This is valid for IntVal.
/// CurBuffer - This is the current buffer index we're lexing from as managed
/// by the SourceMgr object.
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 5c9cba5bc926..2671d29a7272 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -799,8 +799,8 @@ bool TGParser::ParseOptionalBitList(SmallVectorImpl<unsigned> &Ranges) {
RecTy *TGParser::ParseType() {
switch (Lex.getCode()) {
default: TokError("Unknown token when expecting a type"); return nullptr;
- case tgtok::String: Lex.Lex(); return StringRecTy::get();
- case tgtok::Code: Lex.Lex(); return CodeRecTy::get();
+ case tgtok::String:
+ case tgtok::Code: Lex.Lex(); return StringRecTy::get();
case tgtok::Bit: Lex.Lex(); return BitRecTy::get();
case tgtok::Int: Lex.Lex(); return IntRecTy::get();
case tgtok::Dag: Lex.Lex(); return DagRecTy::get();
@@ -1637,6 +1637,9 @@ RecTy *TGParser::ParseOperatorType() {
return nullptr;
}
+ if (Lex.getCode() == tgtok::Code)
+ TokError("the 'code' type is not allowed in bang operators; use 'string'");
+
Type = ParseType();
if (!Type) {
@@ -1920,7 +1923,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
break;
}
case tgtok::CodeFragment:
- R = CodeInit::get(Lex.getCurStrVal());
+ R = StringInit::get(Lex.getCurStrVal(), StringInit::SF_Code);
Lex.Lex();
break;
case tgtok::question:
diff --git a/llvm/lib/Target/AMDGPU/MIMGInstructions.td b/llvm/lib/Target/AMDGPU/MIMGInstructions.td
index 892c6dd7bd78..7baa6823d16a 100644
--- a/llvm/lib/Target/AMDGPU/MIMGInstructions.td
+++ b/llvm/lib/Target/AMDGPU/MIMGInstructions.td
@@ -51,7 +51,7 @@ def MIMGBaseOpcodesTable : GenericTable {
let Fields = ["BaseOpcode", "Store", "Atomic", "AtomicX2", "Sampler",
"Gather4", "NumExtraArgs", "Gradients", "G16", "Coordinates",
"LodOrClampOrMip", "HasD16"];
- GenericEnum TypeOf_BaseOpcode = MIMGBaseOpcode;
+ string TypeOf_BaseOpcode = "MIMGBaseOpcode";
let PrimaryKey = ["BaseOpcode"];
let PrimaryKeyName = "getMIMGBaseOpcodeInfo";
@@ -65,7 +65,7 @@ def MIMGDimInfoTable : GenericTable {
let FilterClass = "AMDGPUDimProps";
let CppTypeName = "MIMGDimInfo";
let Fields = ["Dim", "NumCoords", "NumGradients", "DA", "Encoding", "AsmSuffix"];
- GenericEnum TypeOf_Dim = MIMGDim;
+ string TypeOf_Dim = "MIMGDim";
let PrimaryKey = ["Dim"];
let PrimaryKeyName = "getMIMGDimInfo";
@@ -95,8 +95,8 @@ def MIMGLZMappingTable : GenericTable {
let FilterClass = "MIMGLZMapping";
let CppTypeName = "MIMGLZMappingInfo";
let Fields = ["L", "LZ"];
- GenericEnum TypeOf_L = MIMGBaseOpcode;
- GenericEnum TypeOf_LZ = MIMGBaseOpcode;
+ string TypeOf_L = "MIMGBaseOpcode";
+ string TypeOf_LZ = "MIMGBaseOpcode";
let PrimaryKey = ["L"];
let PrimaryKeyName = "getMIMGLZMappingInfo";
@@ -111,8 +111,8 @@ def MIMGMIPMappingTable : GenericTable {
let FilterClass = "MIMGMIPMapping";
let CppTypeName = "MIMGMIPMappingInfo";
let Fields = ["MIP", "NONMIP"];
- GenericEnum TypeOf_MIP = MIMGBaseOpcode;
- GenericEnum TypeOf_NONMIP = MIMGBaseOpcode;
+ string TypeOf_MIP = "MIMGBaseOpcode";
+ string TypeOf_NONMIP = "MIMGBaseOpcode";
let PrimaryKey = ["MIP"];
let PrimaryKeyName = "getMIMGMIPMappingInfo";
@@ -127,8 +127,8 @@ def MIMGG16MappingTable : GenericTable {
let FilterClass = "MIMGG16Mapping";
let CppTypeName = "MIMGG16MappingInfo";
let Fields = ["G", "G16"];
- GenericEnum TypeOf_G = MIMGBaseOpcode;
- GenericEnum TypeOf_G16 = MIMGBaseOpcode;
+ string TypeOf_G = "MIMGBaseOpcode";
+ string TypeOf_G16 = "MIMGBaseOpcode";
let PrimaryKey = ["G"];
let PrimaryKeyName = "getMIMGG16MappingInfo";
@@ -168,8 +168,8 @@ def MIMGInfoTable : GenericTable {
let FilterClass = "MIMG";
let CppTypeName = "MIMGInfo";
let Fields = ["Opcode", "BaseOpcode", "MIMGEncoding", "VDataDwords", "VAddrDwords"];
- GenericEnum TypeOf_BaseOpcode = MIMGBaseOpcode;
- GenericEnum TypeOf_MIMGEncoding = MIMGEncoding;
+ string TypeOf_BaseOpcode = "MIMGBaseOpcode";
+ string TypeOf_MIMGEncoding = "MIMGEncoding";
let PrimaryKey = ["BaseOpcode", "MIMGEncoding", "VDataDwords", "VAddrDwords"];
let PrimaryKeyName = "getMIMGOpcodeHelper";
@@ -926,8 +926,8 @@ def ImageDimIntrinsicTable : GenericTable {
"DMaskIndex", "VAddrStart", "GradientStart", "CoordStart", "LodIndex", "MipIndex", "VAddrEnd",
"RsrcIndex", "SampIndex", "UnormIndex", "TexFailCtrlIndex", "CachePolicyIndex",
"GradientTyArg", "CoordTyArg"];
- GenericEnum TypeOf_BaseOpcode = MIMGBaseOpcode;
- GenericEnum TypeOf_Dim = MIMGDim;
+ string TypeOf_BaseOpcode = "MIMGBaseOpcode";
+ string TypeOf_Dim = "MIMGDim";
let PrimaryKey = ["Intr"];
let PrimaryKeyName = "getImageDimIntrinsicInfo";
diff --git a/llvm/test/TableGen/code.td b/llvm/test/TableGen/code.td
index 317e3e4d3f05..d709b18855bc 100644
--- a/llvm/test/TableGen/code.td
+++ b/llvm/test/TableGen/code.td
@@ -1,22 +1,49 @@
// RUN: llvm-tblgen %s | FileCheck %s
+// RUN: not llvm-tblgen -DERROR1 %s 2>&1 | FileCheck --check-prefix=ERROR1 %s
// XFAIL: vg_leak
-// CHECK: --- Defs ---
+// CHECK: def A1
+// CHECK: code CodeCode = [{code here;}]
+// CHECK: code StringCode = [{code here;}]
-// CHECK: def A0 {
-// CHECK: code Code = [{Simple}];
-// CHECK: }
+// CHECK: def A2
+// CHECK: string CodeCode = "string here"
+// CHECK: string StringCode = "string here"
-// CHECK: def B0 {
-// CHECK: code Code = [{With paste 7}];
-// CHECK: }
+// CHECK: def B1
+// CHECK: string CodeCode = "with paste 7"
+// CHECK: string StringCode = "with paste 7"
+
+// CHECK: def C1
+// CHECK: code CodeCode = [{with concat 42}]
+// CHECK: code StringCode = [{with concat 42}]
+
+// CHECK: def D1
+// CHECK: code CodeCode = [{with concat 108!}]
+// CHECK: code StringCode = [{with concat 108!}]
class A<code c> {
- code Code = c;
+ code CodeCode = c;
+ string StringCode = c;
}
-def A0 : A<"Simple">;
+def A1 : A<[{code here;}]>;
+def A2 : A<"string here">;
+
+class B<int i> : A<"with paste " # i>;
+class C<int i> : A<!strconcat([{with concat }], !cast<string>(i))>;
+class D<int i> : A<!strconcat([{with concat }], !cast<string>(i), "!")>;
+
+def B1 : B<7>;
+def C1 : C<42>;
+def D1 : D<108>;
-class B<int i> : A<"With paste " # i>;
+#ifdef ERROR1
+
+// ERROR1: the 'code' type is not allowed
+
+def Zerror1 {
+ code Code = !cast<code>("i = 0;");
+}
-def B0 : B<7>;
+#endif
diff --git a/llvm/test/TableGen/generic-tables.td b/llvm/test/TableGen/generic-tables.td
index fefa82684294..e410159e6dfb 100644
--- a/llvm/test/TableGen/generic-tables.td
+++ b/llvm/test/TableGen/generic-tables.td
@@ -55,19 +55,26 @@ def ATable : GenericTable {
// CHECK-LABEL: GET_BTable_IMPL
+// CHECK: constexpr BTypeName BTable[] = {
+// CHECK: { "BAlice", 0xAC, },
+// CHECK: { "BBob", 0x14, Bob == 13 },
+// CHECK: { "BCharlie", 0x80, Charlie == 42 },
+// CHECK: { "BEve", 0x4C, Eve == 108 },
+// CHECK: };
// CHECK: const BTypeName *lookupBTableByName(StringRef Name) {
// CHECK: return &BTable[Idx->_index];
// CHECK: }
-class BEntry<bits<16> enc> {
+class BEntry<bits<16> enc, code test = [{}]> {
string Name = NAME;
bits<16> Encoding = enc;
+ code Test = test;
}
def BAlice : BEntry<0xac>;
-def BBob : BEntry<0x14>;
-def BCharlie : BEntry<0x80>;
-def BEve : BEntry<0x4c>;
+def BBob : BEntry<0x14, [{Bob == 13}]>;
+def BCharlie : BEntry<0x80, "Charlie == 42">;
+def BEve : BEntry<0x4c, [{Eve == }] # 108>;
def BValues : GenericEnum {
let FilterClass = "BEntry";
@@ -78,7 +85,8 @@ def BValues : GenericEnum {
def BTable : GenericTable {
let FilterClass = "BEntry";
string CppTypeName = "BTypeName";
- let Fields = ["Name", "Encoding"];
+ let Fields = ["Name", "Encoding", "Test"];
+ string TypeOf_Test = "code";
}
def lookupBTableByName : SearchIndex {
@@ -126,7 +134,7 @@ def CTable : GenericTable {
let FilterClass = "CEntry";
let Fields = ["Name", "Kind", "Encoding"];
- GenericEnum TypeOf_Kind = CEnum;
+ string TypeOf_Kind = "CEnum";
let PrimaryKey = ["Encoding"];
let PrimaryKeyName = "lookupCEntryByEncoding";
diff --git a/llvm/test/TableGen/interleave.td b/llvm/test/TableGen/interleave.td
index 7d6bfee15a56..098542ab29a1 100644
--- a/llvm/test/TableGen/interleave.td
+++ b/llvm/test/TableGen/interleave.td
@@ -28,9 +28,9 @@ def Rec1 {
}
// CHECK: def Rec2
-// CHECK: Test1 = "01234567";
-// CHECK: Test2 = "0, 1, 2, 3, 4, 5, 6, 7";
-// CHECK: Test3 = "0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 42";
+// CHECK: Test1 = "01234567";
+// CHECK: Test2 = "0, 1, 2, 3, 4, 5, 6, 7";
+// CHECK: Test3 = "0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 42";
def Rec2 {
string Test1 = !interleave(IntList, "");
@@ -39,9 +39,9 @@ def Rec2 {
}
// CHECK: def Rec3
-// CHECK: Test1 = "271";
-// CHECK: Test2 = "2, 7, 1";
-// CHECK: Test3 = "2 & 7 & 1 & 0";
+// CHECK: Test1 = "271";
+// CHECK: Test2 = "2, 7, 1";
+// CHECK: Test3 = "2 & 7 & 1 & 0";
def Rec3 {
string Test1 = !interleave(BitsList, "");
@@ -50,9 +50,9 @@ def Rec3 {
}
// CHECK: def Rec4
-// CHECK: Test1 = "01101";
-// CHECK: Test2 = "0, 1, 1, 0, 1";
-// CHECK: Test3 = "0 and 1 and 1 and 0 and 1 and 1";
+// CHECK: Test1 = "01101";
+// CHECK: Test2 = "0, 1, 1, 0, 1";
+// CHECK: Test3 = "0 and 1 and 1 and 0 and 1 and 1";
def Rec4 {
string Test1 = !interleave(BitList, "");
@@ -61,14 +61,23 @@ def Rec4 {
}
// CHECK: def Rec5
-// CHECK: Colors = ["red", "green", "yellow"];
-// CHECK: ColorList = "redify, greenify, yellowify";
+// CHECK: Colors = ["red", "green", "yellow"];
+// CHECK: ColorList = "redify, greenify, yellowify";
def Rec5 {
list<string> Colors = ["red", "green", "yellow"];
string ColorList = !interleave(Ishify<Colors>.ret, ", ");
}
+// CHECK: def Rec6
+// CHECK: code OperatorList = [{+, -, *, /, ?:, ;}];
+
+def Rec6 {
+ list<string> Operators = ["+", "-", "*", "/", "?:"];
+ code OperatorList = !interleave(!listconcat(Operators, [[{;}]]), ", ");
+}
+
+
#ifdef ERROR1
def op;
diff --git a/llvm/test/TableGen/unterminated-code-block.td b/llvm/test/TableGen/unterminated-code-block.td
index 86395abd789e..d6b6f50827a6 100644
--- a/llvm/test/TableGen/unterminated-code-block.td
+++ b/llvm/test/TableGen/unterminated-code-block.td
@@ -1,5 +1,5 @@
// RUN: not llvm-tblgen -I %p %s 2>&1 | FileCheck %s
-// CHECK: error: Unterminated Code Block
+// CHECK: error: Unterminated code block
include "unterminated-code-block-include.inc" }]>;
diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp
index f903be169476..9a5908827b4e 100644
--- a/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -1265,13 +1265,10 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
<< " break;\n";
for (unsigned i = 0; i < MCOpPredicates.size(); ++i) {
- Init *MCOpPred = MCOpPredicates[i]->getValueInit("MCOperandPredicate");
- if (CodeInit *SI = dyn_cast<CodeInit>(MCOpPred)) {
- O << " case " << i + 1 << ": {\n"
- << SI->getValue() << "\n"
- << " }\n";
- } else
- llvm_unreachable("Unexpected MCOperandPredicate field!");
+ StringRef MCOpPred = MCOpPredicates[i]->getValueAsString("MCOperandPredicate");
+ O << " case " << i + 1 << ": {\n"
+ << MCOpPred.data() << "\n"
+ << " }\n";
}
O << " }\n"
<< "}\n\n";
diff --git a/llvm/utils/TableGen/DFAEmitter.cpp b/llvm/utils/TableGen/DFAEmitter.cpp
index e87765085289..781cb0636fa1 100644
--- a/llvm/utils/TableGen/DFAEmitter.cpp
+++ b/llvm/utils/TableGen/DFAEmitter.cpp
@@ -346,8 +346,7 @@ Transition::Transition(Record *R, Automaton *Parent) {
} else if (isa<IntRecTy>(SymbolV->getType())) {
Actions.emplace_back(nullptr, R->getValueAsInt(A), "");
Types.emplace_back("unsigned");
- } else if (isa<StringRecTy>(SymbolV->getType()) ||
- isa<CodeRecTy>(SymbolV->getType())) {
+ } else if (isa<StringRecTy>(SymbolV->getType())) {
Actions.emplace_back(nullptr, 0, std::string(R->getValueAsString(A)));
Types.emplace_back("std::string");
} else {
diff --git a/llvm/utils/TableGen/GICombinerEmitter.cpp b/llvm/utils/TableGen/GICombinerEmitter.cpp
index d84d049e89f0..5f091467636d 100644
--- a/llvm/utils/TableGen/GICombinerEmitter.cpp
+++ b/llvm/utils/TableGen/GICombinerEmitter.cpp
@@ -150,7 +150,7 @@ class CombineRule {
/// A block of arbitrary C++ to finish testing the match.
/// FIXME: This is a temporary measure until we have actual pattern matching
- const CodeInit *MatchingFixupCode = nullptr;
+ const StringInit *MatchingFixupCode = nullptr;
/// The MatchData defined by the match stage and required by the apply stage.
/// This allows the plumbing of arbitrary data from C++ predicates between the
@@ -199,7 +199,7 @@ class CombineRule {
unsigned allocUID() { return UID++; }
StringRef getName() const { return TheDef.getName(); }
const Record &getDef() const { return TheDef; }
- const CodeInit *getMatchingFixupCode() const { return MatchingFixupCode; }
+ const StringInit *getMatchingFixupCode() const { return MatchingFixupCode; }
size_t getNumRoots() const { return Roots.size(); }
GIMatchDag &getMatchDag() { return MatchDag; }
@@ -514,10 +514,10 @@ bool CombineRule::parseMatcher(const CodeGenTarget &Target) {
// Parse arbitrary C++ code we have in lieu of supporting MIR matching
- if (const CodeInit *CodeI = dyn_cast<CodeInit>(Matchers->getArg(I))) {
+ if (const StringInit *StringI = dyn_cast<StringInit>(Matchers->getArg(I))) {
assert(!MatchingFixupCode &&
"Only one block of arbitrary code is currently permitted");
- MatchingFixupCode = CodeI;
+ MatchingFixupCode = StringI;
MatchDag.setHasPostMatchPredicate(true);
continue;
}
@@ -807,7 +807,7 @@ void GICombinerEmitter::generateCodeForTree(raw_ostream &OS,
}
OS << ") {\n" << Indent << " ";
- if (const CodeInit *Code = dyn_cast<CodeInit>(Applyer->getArg(0))) {
+ if (const StringInit *Code = dyn_cast<StringInit>(Applyer->getArg(0))) {
OS << CodeExpander(Code->getAsUnquotedString(), Expansions,
RuleDef.getLoc(), ShowExpansions)
<< "\n"
diff --git a/llvm/utils/TableGen/RISCVCompressInstEmitter.cpp b/llvm/utils/TableGen/RISCVCompressInstEmitter.cpp
index 200644213ca1..dcca207be7c1 100644
--- a/llvm/utils/TableGen/RISCVCompressInstEmitter.cpp
+++ b/llvm/utils/TableGen/RISCVCompressInstEmitter.cpp
@@ -533,14 +533,11 @@ static unsigned getPredicates(DenseMap<const Record *, unsigned> &PredicateMap,
static void printPredicates(std::vector<const Record *> &Predicates,
StringRef Name, raw_ostream &o) {
for (unsigned i = 0; i < Predicates.size(); ++i) {
- Init *Pred = Predicates[i]->getValueInit(Name);
- if (CodeInit *SI = dyn_cast<CodeInit>(Pred))
- o << " case " << i + 1 << ": {\n"
- << " // " << Predicates[i]->getName().str() << "\n"
- << " " << SI->getValue() << "\n"
- << " }\n";
- else
- llvm_unreachable("Unexpected predicate field!");
+ StringRef Pred = Predicates[i]->getValueAsString(Name);
+ o << " case " << i + 1 << ": {\n"
+ << " // " << Predicates[i]->getName().str() << "\n"
+ << " " << Pred.data() << "\n"
+ << " }\n";
}
}
diff --git a/llvm/utils/TableGen/SearchableTableEmitter.cpp b/llvm/utils/TableGen/SearchableTableEmitter.cpp
index 3c292f30dbcf..2e86b137ac58 100644
--- a/llvm/utils/TableGen/SearchableTableEmitter.cpp
+++ b/llvm/utils/TableGen/SearchableTableEmitter.cpp
@@ -54,6 +54,7 @@ struct GenericEnum {
struct GenericField {
std::string Name;
RecTy *RecType = nullptr;
+ bool IsCode = false;
bool IsIntrinsic = false;
bool IsInstruction = false;
GenericEnum *Enum = nullptr;
@@ -111,14 +112,15 @@ class SearchableTableEmitter {
std::string primaryRepresentation(SMLoc Loc, const GenericField &Field,
Init *I) {
- if (StringInit *SI = dyn_cast<StringInit>(I))
- return SI->getAsString();
- else if (BitsInit *BI = dyn_cast<BitsInit>(I))
+ if (StringInit *SI = dyn_cast<StringInit>(I)) {
+ if (Field.IsCode || SI->hasCodeFormat())
+ return std::string(SI->getValue());
+ else
+ return SI->getAsString();
+ } else if (BitsInit *BI = dyn_cast<BitsInit>(I))
return "0x" + utohexstr(getAsInt(BI));
else if (BitInit *BI = dyn_cast<BitInit>(I))
return BI->getValue() ? "true" : "false";
- else if (CodeInit *CI = dyn_cast<CodeInit>(I))
- return std::string(CI->getValue());
else if (Field.IsIntrinsic)
return "Intrinsic::" + getIntrinsic(I).EnumName;
else if (Field.IsInstruction)
@@ -150,10 +152,6 @@ class SearchableTableEmitter {
bool compareBy(Record *LHS, Record *RHS, const SearchIndex &Index);
- bool isIntegral(Init *I) {
- return isa<BitsInit>(I) || isa<CodeInit>(I) || isIntrinsic(I);
- }
-
std::string searchableFieldType(const GenericTable &Table,
const SearchIndex &Index,
const GenericField &Field, TypeContext Ctx) {
@@ -545,13 +543,19 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
OS << "#endif\n\n";
}
-bool SearchableTableEmitter::parseFieldType(GenericField &Field, Init *II) {
- if (auto DI = dyn_cast<DefInit>(II)) {
- Record *TypeRec = DI->getDef();
- if (TypeRec->isSubClassOf("GenericEnum")) {
- Field.Enum = EnumMap[TypeRec];
- Field.RecType = RecordRecTy::get(Field.Enum->Class);
+bool SearchableTableEmitter::parseFieldType(GenericField &Field, Init *TypeOf) {
+ if (auto Type = dyn_cast<StringInit>(TypeOf)) {
+ if (Type->getValue() == "code") {
+ Field.IsCode = true;
return true;
+ } else {
+ if (Record *TypeRec = Records.getDef(Type->getValue())) {
+ if (TypeRec->isSubClassOf("GenericEnum")) {
+ Field.Enum = EnumMap[TypeRec];
+ Field.RecType = RecordRecTy::get(Field.Enum->Class);
+ return true;
+ }
+ }
}
}
@@ -708,12 +712,14 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
for (const auto &FieldName : Fields) {
Table->Fields.emplace_back(FieldName); // Construct a GenericField.
- if (auto TypeOfVal = TableRec->getValue(("TypeOf_" + FieldName).str())) {
- if (!parseFieldType(Table->Fields.back(), TypeOfVal->getValue())) {
- PrintFatalError(TypeOfVal,
- Twine("Table '") + Table->Name +
- "' has invalid 'TypeOf_" + FieldName +
- "': " + TypeOfVal->getValue()->getAsString());
+ if (auto TypeOfRecordVal = TableRec->getValue(("TypeOf_" + FieldName).str())) {
+ if (!parseFieldType(Table->Fields.back(), TypeOfRecordVal->getValue())) {
+ PrintError(TypeOfRecordVal,
+ Twine("Table '") + Table->Name +
+ "' has invalid 'TypeOf_" + FieldName +
+ "': " + TypeOfRecordVal->getValue()->getAsString());
+ PrintFatalNote("The 'TypeOf_xxx' field must be a string naming a "
+ "GenericEnum record, or \"code\"");
}
}
}
diff --git a/mlir/include/mlir/TableGen/Operator.h b/mlir/include/mlir/TableGen/Operator.h
index d7fac87af0be..16d154b3beb0 100644
--- a/mlir/include/mlir/TableGen/Operator.h
+++ b/mlir/include/mlir/TableGen/Operator.h
@@ -28,7 +28,6 @@
#include "llvm/Support/SMLoc.h"
namespace llvm {
-class CodeInit;
class DefInit;
class Record;
class StringInit;
diff --git a/mlir/lib/TableGen/Attribute.cpp b/mlir/lib/TableGen/Attribute.cpp
index 3377ec98c229..99d9d8ab9b3a 100644
--- a/mlir/lib/TableGen/Attribute.cpp
+++ b/mlir/lib/TableGen/Attribute.cpp
@@ -18,7 +18,6 @@
using namespace mlir;
using namespace mlir::tblgen;
-using llvm::CodeInit;
using llvm::DefInit;
using llvm::Init;
using llvm::Record;
@@ -27,8 +26,6 @@ using llvm::StringInit;
// Returns the initializer's value as string if the given TableGen initializer
// is a code or string initializer. Returns the empty StringRef otherwise.
static StringRef getValueAsString(const Init *init) {
- if (const auto *code = dyn_cast<CodeInit>(init))
- return code->getValue().trim();
if (const auto *str = dyn_cast<StringInit>(init))
return str->getValue().trim();
return {};
diff --git a/mlir/lib/TableGen/Dialect.cpp b/mlir/lib/TableGen/Dialect.cpp
index c17180c20483..0c1de78ce60e 100644
--- a/mlir/lib/TableGen/Dialect.cpp
+++ b/mlir/lib/TableGen/Dialect.cpp
@@ -38,7 +38,7 @@ std::string Dialect::getCppClassName() const {
static StringRef getAsStringOrEmpty(const llvm::Record &record,
StringRef fieldName) {
if (auto valueInit = record.getValueInit(fieldName)) {
- if (llvm::isa<llvm::CodeInit, llvm::StringInit>(valueInit))
+ if (llvm::isa<llvm::StringInit>(valueInit))
return record.getValueAsString(fieldName);
}
return "";
diff --git a/mlir/lib/TableGen/Operator.cpp b/mlir/lib/TableGen/Operator.cpp
index b59ffaf8d092..ca1442f547d5 100644
--- a/mlir/lib/TableGen/Operator.cpp
+++ b/mlir/lib/TableGen/Operator.cpp
@@ -547,12 +547,12 @@ StringRef Operator::getSummary() const {
bool Operator::hasAssemblyFormat() const {
auto *valueInit = def.getValueInit("assemblyFormat");
- return isa<llvm::CodeInit, llvm::StringInit>(valueInit);
+ return isa<llvm::StringInit>(valueInit);
}
StringRef Operator::getAssemblyFormat() const {
return TypeSwitch<llvm::Init *, StringRef>(def.getValueInit("assemblyFormat"))
- .Case<llvm::StringInit, llvm::CodeInit>(
+ .Case<llvm::StringInit>(
[&](auto *init) { return init->getValue(); });
}
diff --git a/mlir/lib/TableGen/Pattern.cpp b/mlir/lib/TableGen/Pattern.cpp
index 4128936d4b7f..0dae7ff71883 100644
--- a/mlir/lib/TableGen/Pattern.cpp
+++ b/mlir/lib/TableGen/Pattern.cpp
@@ -55,7 +55,7 @@ bool DagLeaf::isEnumAttrCase() const {
}
bool DagLeaf::isStringAttr() const {
- return isa<llvm::StringInit, llvm::CodeInit>(def);
+ return isa<llvm::StringInit>(def);
}
Constraint DagLeaf::getAsConstraint() const {
diff --git a/mlir/lib/TableGen/Type.cpp b/mlir/lib/TableGen/Type.cpp
index a3d6ac6a7e88..5fe6bbbd5e83 100644
--- a/mlir/lib/TableGen/Type.cpp
+++ b/mlir/lib/TableGen/Type.cpp
@@ -46,7 +46,7 @@ Optional<StringRef> TypeConstraint::getBuilderCall() const {
if (!builderCall || !builderCall->getValue())
return llvm::None;
return TypeSwitch<llvm::Init *, Optional<StringRef>>(builderCall->getValue())
- .Case<llvm::StringInit, llvm::CodeInit>([&](auto *init) {
+ .Case<llvm::StringInit>([&](auto *init) {
StringRef value = init->getValue();
return value.empty() ? Optional<StringRef>() : value;
})
diff --git a/mlir/lib/TableGen/TypeDef.cpp b/mlir/lib/TableGen/TypeDef.cpp
index aa7f36a3626b..d8412b6b4be5 100644
--- a/mlir/lib/TableGen/TypeDef.cpp
+++ b/mlir/lib/TableGen/TypeDef.cpp
@@ -78,10 +78,10 @@ llvm::Optional<StringRef> TypeDef::getMnemonic() const {
return def->getValueAsOptionalString("mnemonic");
}
llvm::Optional<StringRef> TypeDef::getPrinterCode() const {
- return def->getValueAsOptionalCode("printer");
+ return def->getValueAsOptionalString("printer");
}
llvm::Optional<StringRef> TypeDef::getParserCode() const {
- return def->getValueAsOptionalCode("parser");
+ return def->getValueAsOptionalString("parser");
}
bool TypeDef::genAccessors() const {
return def->getValueAsBit("genAccessors");
@@ -114,7 +114,7 @@ llvm::Optional<StringRef> TypeParameter::getAllocator() const {
llvm::RecordVal *code = typeParameter->getDef()->getValue("allocator");
if (!code)
return llvm::Optional<StringRef>();
- if (llvm::CodeInit *ci = dyn_cast<llvm::CodeInit>(code->getValue()))
+ if (llvm::StringInit *ci = dyn_cast<llvm::StringInit>(code->getValue()))
return ci->getValue();
if (isa<llvm::UnsetInit>(code->getValue()))
return llvm::Optional<StringRef>();
diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
index 6ab92c040c16..c96fde648eb2 100644
--- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
@@ -137,7 +137,7 @@ static std::string replaceAllSubstrs(std::string str, const std::string &match,
static inline bool hasStringAttribute(const Record &record,
StringRef fieldName) {
auto valueInit = record.getValueInit(fieldName);
- return isa<CodeInit, StringInit>(valueInit);
+ return isa<StringInit>(valueInit);
}
static std::string getArgumentName(const Operator &op, int index) {
@@ -1796,15 +1796,15 @@ void OpEmitter::genPrinter() {
return;
auto valueInit = def.getValueInit("printer");
- CodeInit *codeInit = dyn_cast<CodeInit>(valueInit);
- if (!codeInit)
+ StringInit *stringInit = dyn_cast<StringInit>(valueInit);
+ if (!stringInit)
return;
auto *method =
opClass.addMethodAndPrune("void", "print", "::mlir::OpAsmPrinter &", "p");
FmtContext fctx;
fctx.addSubst("cppClass", opClass.getClassName());
- auto printer = codeInit->getValue().ltrim().rtrim(" \t\v\f\r");
+ auto printer = stringInit->getValue().ltrim().rtrim(" \t\v\f\r");
method->body() << " " << tgfmt(printer, &fctx);
}
@@ -1816,8 +1816,8 @@ void OpEmitter::genVerifier() {
<< "return ::mlir::failure();\n";
auto *valueInit = def.getValueInit("verifier");
- CodeInit *codeInit = dyn_cast<CodeInit>(valueInit);
- bool hasCustomVerify = codeInit && !codeInit->getValue().empty();
+ StringInit *stringInit = dyn_cast<StringInit>(valueInit);
+ bool hasCustomVerify = stringInit && !stringInit->getValue().empty();
populateSubstitutions(op, "this->getAttr", "this->getODSOperands",
"this->getODSResults", verifyCtx);
@@ -1841,7 +1841,7 @@ void OpEmitter::genVerifier() {
if (hasCustomVerify) {
FmtContext fctx;
fctx.addSubst("cppClass", opClass.getClassName());
- auto printer = codeInit->getValue().ltrim().rtrim(" \t\v\f\r");
+ auto printer = stringInit->getValue().ltrim().rtrim(" \t\v\f\r");
body << " " << tgfmt(printer, &fctx);
} else {
body << " return ::mlir::success();\n";
More information about the Mlir-commits
mailing list