[TableGen] Eliminate the 'code' type
Update the documentation. Rework various backends that relied on the code type. Differential Revision: https://reviews.llvm.org/D92269
This commit is contained in:
parent
1365718778
commit
415fab6f67
|
@ -217,8 +217,6 @@ std::string getRSTStringWithTextFallback(const Record *R, StringRef Primary,
|
||||||
StringRef Value;
|
StringRef Value;
|
||||||
if (auto *SV = dyn_cast_or_null<StringInit>(V->getValue()))
|
if (auto *SV = dyn_cast_or_null<StringInit>(V->getValue()))
|
||||||
Value = SV->getValue();
|
Value = SV->getValue();
|
||||||
else if (auto *CV = dyn_cast_or_null<CodeInit>(V->getValue()))
|
|
||||||
Value = CV->getValue();
|
|
||||||
if (!Value.empty())
|
if (!Value.empty())
|
||||||
return Field == Primary ? Value.str() : escapeRST(Value);
|
return Field == Primary ? Value.str() : escapeRST(Value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -693,8 +693,8 @@ This class provides six fields.
|
||||||
table that holds the entries. If unspecified, the ``FilterClass`` name is
|
table that holds the entries. If unspecified, the ``FilterClass`` name is
|
||||||
used.
|
used.
|
||||||
|
|
||||||
* ``list<string> Fields``. A list of the names of the fields in the
|
* ``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
|
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
|
this list determines the order of the values in the C++ initializers. See
|
||||||
below for information about the types of these fields.
|
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.
|
* ``bit PrimaryKeyEarlyOut``. See the third example below.
|
||||||
|
|
||||||
TableGen attempts to deduce the type of each of the table fields. It can
|
TableGen attempts to deduce the type of each of the table fields so that it
|
||||||
deduce ``bit``, ``bits<n>``, ``string``, ``Intrinsic``, and ``Instruction``.
|
can format the C++ initializers in the emitted table. It can deduce ``bit``,
|
||||||
These can be used in the primary key. TableGen also deduces ``code``, but it
|
``bits<n>``, ``string``, ``Intrinsic``, and ``Instruction``. These can be
|
||||||
cannot be used in the primary key. Any other field types must be specified
|
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
|
explicitly; this is done as shown in the second example below. Such fields
|
||||||
cannot be used in the primary key.
|
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
|
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
|
table entry records are anonymous; the names of entry records are
|
||||||
irrelevant.
|
irrelevant.
|
||||||
|
@ -793,7 +806,7 @@ pointer if no entry is found.
|
||||||
|
|
||||||
This example includes a field whose type TableGen cannot deduce. The ``Kind``
|
This example includes a field whose type TableGen cannot deduce. The ``Kind``
|
||||||
field uses the enumerated type ``CEnum`` defined above. To inform TableGen
|
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
|
named ``TypeOf_``\ *field*, where *field* is the name of the field whose type
|
||||||
is required.
|
is required.
|
||||||
|
|
||||||
|
@ -802,7 +815,7 @@ is required.
|
||||||
def CTable : GenericTable {
|
def CTable : GenericTable {
|
||||||
let FilterClass = "CEntry";
|
let FilterClass = "CEntry";
|
||||||
let Fields = ["Name", "Kind", "Encoding"];
|
let Fields = ["Name", "Kind", "Encoding"];
|
||||||
GenericEnum TypeOf_Kind = CEnum;
|
string TypeOf_Kind = "CEnum";
|
||||||
let PrimaryKey = ["Encoding"];
|
let PrimaryKey = ["Encoding"];
|
||||||
let PrimaryKeyName = "lookupCEntryByEncoding";
|
let PrimaryKeyName = "lookupCEntryByEncoding";
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
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
|
that represent specific value types (except for the unset value). These
|
||||||
classes include ``BitInit``, ``BitsInit``, ``CodeInit``, ``DagInit``,
|
classes include ``BitInit``, ``BitsInit``, ``DagInit``, ``DefInit``,
|
||||||
``DefInit``, ``IntInit``, ``ListInit``, and ``StringInit``. (There are
|
``IntInit``, ``ListInit``, and ``StringInit``. (There are additional derived
|
||||||
additional derived types used by the TableGen parser.)
|
types used by the TableGen parser.)
|
||||||
|
|
||||||
This class includes a data member that specifies the ``RecTy`` type of the
|
This class includes a data member that specifies the ``RecTy`` type of the
|
||||||
value. It provides a function to get that ``RecTy`` type.
|
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.
|
* 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``
|
``DagInit``
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -167,10 +167,11 @@ TableGen has two kinds of string literals:
|
||||||
|
|
||||||
.. productionlist::
|
.. productionlist::
|
||||||
TokString: '"' (non-'"' characters and escapes) '"'
|
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
|
A :token:`TokCode` is nothing more than a multi-line string literal
|
||||||
delimited by ``[{`` and ``}]``. It can break across lines.
|
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::
|
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.
|
wide range of records conveniently and compactly.
|
||||||
|
|
||||||
.. productionlist::
|
.. productionlist::
|
||||||
Type: "bit" | "int" | "string" | "code" | "dag"
|
Type: "bit" | "int" | "string" | "dag"
|
||||||
:| "bits" "<" `TokInteger` ">"
|
:| "bits" "<" `TokInteger` ">"
|
||||||
:| "list" "<" `Type` ">"
|
:| "list" "<" `Type` ">"
|
||||||
:| `ClassID`
|
:| `ClassID`
|
||||||
|
@ -271,11 +272,6 @@ wide range of records conveniently and compactly.
|
||||||
The ``string`` type represents an ordered sequence of characters of arbitrary
|
The ``string`` type represents an ordered sequence of characters of arbitrary
|
||||||
length.
|
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*\ ``>``
|
``bits<``\ *n*\ ``>``
|
||||||
The ``bits`` type is a fixed-sized integer of arbitrary length *n* that
|
The ``bits`` type is a fixed-sized integer of arbitrary length *n* that
|
||||||
is treated as separate bits. These bits can be accessed individually.
|
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.
|
The :token:`SimpleValue` has a number of forms.
|
||||||
|
|
||||||
.. productionlist::
|
.. productionlist::
|
||||||
SimpleValue: `TokInteger` | `TokString`+ | `TokCodeFragment`
|
SimpleValue: `TokInteger` | `TokString`+ | `TokCode`
|
||||||
|
|
||||||
A value can be an integer literal, a string literal, or a code fragment
|
A value can be an integer literal, a string literal, or a code literal.
|
||||||
literal. Multiple adjacent string literals are concatenated as in C/C++; the
|
Multiple adjacent string literals are concatenated as in C/C++; the simple
|
||||||
simple value is the concatenation of the strings. Code fragments become
|
value is the concatenation of the strings. Code literals become strings and
|
||||||
strings and then are indistinguishable from them.
|
are then indistinguishable from them.
|
||||||
|
|
||||||
.. productionlist::
|
.. productionlist::
|
||||||
SimpleValue2: "true" | "false"
|
SimpleValue2: "true" | "false"
|
||||||
|
@ -616,14 +612,15 @@ name of a multiclass.
|
||||||
|
|
||||||
.. productionlist::
|
.. productionlist::
|
||||||
Body: ";" | "{" `BodyItem`* "}"
|
Body: ";" | "{" `BodyItem`* "}"
|
||||||
BodyItem: `Type` `TokIdentifier` ["=" `Value`] ";"
|
BodyItem: (`Type` | "code") `TokIdentifier` ["=" `Value`] ";"
|
||||||
:| "let" `TokIdentifier` ["{" `RangeList` "}"] "=" `Value` ";"
|
:| "let" `TokIdentifier` ["{" `RangeList` "}"] "=" `Value` ";"
|
||||||
:| "defvar" `TokIdentifier` "=" `Value` ";"
|
:| "defvar" `TokIdentifier` "=" `Value` ";"
|
||||||
|
|
||||||
A field definition in the body specifies a field to be included in the class
|
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
|
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
|
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
|
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
|
for fields defined directly in the body or fields inherited from
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace llvm {
|
||||||
void PrintNote(const Twine &Msg);
|
void PrintNote(const Twine &Msg);
|
||||||
void PrintNote(ArrayRef<SMLoc> NoteLoc, 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,
|
LLVM_ATTRIBUTE_NORETURN void PrintFatalNote(ArrayRef<SMLoc> ErrorLoc,
|
||||||
const Twine &Msg);
|
const Twine &Msg);
|
||||||
LLVM_ATTRIBUTE_NORETURN void PrintFatalNote(const Record *Rec,
|
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(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg);
|
||||||
void PrintError(const char *Loc, const Twine &Msg);
|
void PrintError(const char *Loc, const Twine &Msg);
|
||||||
void PrintError(const Record *Rec, 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(const Twine &Msg);
|
||||||
LLVM_ATTRIBUTE_NORETURN void PrintFatalError(ArrayRef<SMLoc> ErrorLoc,
|
LLVM_ATTRIBUTE_NORETURN void PrintFatalError(ArrayRef<SMLoc> ErrorLoc,
|
||||||
|
|
|
@ -58,7 +58,6 @@ public:
|
||||||
enum RecTyKind {
|
enum RecTyKind {
|
||||||
BitRecTyKind,
|
BitRecTyKind,
|
||||||
BitsRecTyKind,
|
BitsRecTyKind,
|
||||||
CodeRecTyKind,
|
|
||||||
IntRecTyKind,
|
IntRecTyKind,
|
||||||
StringRecTyKind,
|
StringRecTyKind,
|
||||||
ListRecTyKind,
|
ListRecTyKind,
|
||||||
|
@ -138,24 +137,6 @@ public:
|
||||||
bool typeIsA(const RecTy *RHS) const override;
|
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
|
/// 'int' - Represent an integer value of no particular size
|
||||||
class IntRecTy : public RecTy {
|
class IntRecTy : public RecTy {
|
||||||
static IntRecTy Shared;
|
static IntRecTy Shared;
|
||||||
|
@ -306,7 +287,6 @@ protected:
|
||||||
IK_FirstTypedInit,
|
IK_FirstTypedInit,
|
||||||
IK_BitInit,
|
IK_BitInit,
|
||||||
IK_BitsInit,
|
IK_BitsInit,
|
||||||
IK_CodeInit,
|
|
||||||
IK_DagInit,
|
IK_DagInit,
|
||||||
IK_DefInit,
|
IK_DefInit,
|
||||||
IK_FieldInit,
|
IK_FieldInit,
|
||||||
|
@ -597,16 +577,18 @@ public:
|
||||||
|
|
||||||
/// "foo" - Represent an initialization by a string value.
|
/// "foo" - Represent an initialization by a string value.
|
||||||
class StringInit : public TypedInit {
|
class StringInit : public TypedInit {
|
||||||
//// enum StringFormat {
|
public:
|
||||||
//// SF_String, // Format as "text"
|
enum StringFormat {
|
||||||
//// SF_Code, // Format as [{text}]
|
SF_String, // Format as "text"
|
||||||
//// };
|
SF_Code, // Format as [{text}]
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
StringRef Value;
|
StringRef Value;
|
||||||
//// StringFormat Format;
|
StringFormat Format;
|
||||||
|
|
||||||
explicit StringInit(StringRef V)
|
explicit StringInit(StringRef V, StringFormat Fmt)
|
||||||
: TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {}
|
: TypedInit(IK_StringInit, StringRecTy::get()), Value(V), Format(Fmt) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StringInit(const StringInit &) = delete;
|
StringInit(const StringInit &) = delete;
|
||||||
|
@ -616,47 +598,24 @@ public:
|
||||||
return I->getKind() == IK_StringInit;
|
return I->getKind() == IK_StringInit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static StringInit *get(StringRef);
|
static StringInit *get(StringRef, StringFormat Fmt = SF_String);
|
||||||
|
|
||||||
|
static StringFormat determineFormat(StringFormat Fmt1, StringFormat Fmt2) {
|
||||||
|
return (Fmt1 == SF_Code || Fmt2 == SF_Code) ? SF_Code : SF_String;
|
||||||
|
}
|
||||||
|
|
||||||
StringRef getValue() const { return Value; }
|
StringRef getValue() const { return Value; }
|
||||||
|
StringFormat getFormat() const { return Format; }
|
||||||
|
bool hasCodeFormat() const { return Format == SF_Code; }
|
||||||
|
|
||||||
Init *convertInitializerTo(RecTy *Ty) const override;
|
Init *convertInitializerTo(RecTy *Ty) const override;
|
||||||
|
|
||||||
bool isConcrete() const override { return true; }
|
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 CodeInit *get(StringRef);
|
|
||||||
|
|
||||||
StringRef getValue() const { return Value; }
|
|
||||||
|
|
||||||
Init *convertInitializerTo(RecTy *Ty) const override;
|
|
||||||
|
|
||||||
bool isConcrete() const override { return true; }
|
|
||||||
std::string getAsString() const override {
|
std::string getAsString() const override {
|
||||||
|
if (Format == SF_String)
|
||||||
|
return "\"" + Value.str() + "\"";
|
||||||
|
else
|
||||||
return "[{" + Value.str() + "}]";
|
return "[{" + Value.str() + "}]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1438,6 +1397,9 @@ public:
|
||||||
/// Get the type of the field value as a RecTy.
|
/// Get the type of the field value as a RecTy.
|
||||||
RecTy *getType() const { return TyAndPrefix.getPointer(); }
|
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.
|
/// Get the value of the field as an Init.
|
||||||
Init *getValue() const { return Value; }
|
Init *getValue() const { return Value; }
|
||||||
|
|
||||||
|
@ -1675,11 +1637,6 @@ public:
|
||||||
/// not a string and llvm::Optional() if the field does not exist.
|
/// not a string and llvm::Optional() if the field does not exist.
|
||||||
llvm::Optional<StringRef> getValueAsOptionalString(StringRef FieldName) const;
|
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
|
/// This method looks up the specified field and returns
|
||||||
/// its value as a BitsInit, throwing an exception if the field does not exist
|
/// its value as a BitsInit, throwing an exception if the field does not exist
|
||||||
/// or if the value is not the right type.
|
/// or if the value is not the right type.
|
||||||
|
|
|
@ -67,9 +67,13 @@ class GenericTable {
|
||||||
// List of the names of fields of collected records that contain the data for
|
// 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++.
|
// 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
|
// TableGen needs to know the type of the fields so that it can format
|
||||||
// called TypeOf_XXX and use that as a more detailed description of the
|
// the initializers correctly. It can infer the type of bit, bits, string,
|
||||||
// type of the field if present. This is required for fields whose type
|
// 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:
|
// cannot be deduced automatically, such as enum fields. For example:
|
||||||
//
|
//
|
||||||
// def MyEnum : GenericEnum {
|
// def MyEnum : GenericEnum {
|
||||||
|
@ -85,15 +89,15 @@ class GenericTable {
|
||||||
// def MyTable : GenericTable {
|
// def MyTable : GenericTable {
|
||||||
// let FilterClass = "MyTableEntry";
|
// let FilterClass = "MyTableEntry";
|
||||||
// let Fields = ["V", ...];
|
// let Fields = ["V", ...];
|
||||||
// GenericEnum TypeOf_V = MyEnum;
|
// string TypeOf_V = "MyEnum";
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Fields of type bit, bits<N>, string, Intrinsic, and Instruction (or
|
// If a string field was initialized with a code literal, TableGen will
|
||||||
// derived classes of those) are supported natively.
|
// 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
|
// string TypeOf_Predicate = "code";
|
||||||
// verbatim as an initializer. However, these fields cannot be used as
|
|
||||||
// search keys.
|
|
||||||
list<string> Fields;
|
list<string> Fields;
|
||||||
|
|
||||||
// (Optional) List of fields that make up the primary key.
|
// (Optional) List of fields that make up the primary key.
|
||||||
|
|
|
@ -52,6 +52,13 @@ void PrintNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg) {
|
||||||
|
|
||||||
// Functions to print fatal notes.
|
// 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) {
|
void PrintFatalNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg) {
|
||||||
PrintNote(NoteLoc, Msg);
|
PrintNote(NoteLoc, Msg);
|
||||||
// The following call runs the file cleanup handlers.
|
// 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);
|
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.
|
// Functions to print fatal errors.
|
||||||
|
|
||||||
void PrintFatalError(const Twine &Msg) {
|
void PrintFatalError(const Twine &Msg) {
|
||||||
|
|
|
@ -59,8 +59,6 @@ json::Value JSONEmitter::translateInit(const Init &I) {
|
||||||
return Int->getValue();
|
return Int->getValue();
|
||||||
} else if (auto *Str = dyn_cast<StringInit>(&I)) {
|
} else if (auto *Str = dyn_cast<StringInit>(&I)) {
|
||||||
return Str->getValue();
|
return Str->getValue();
|
||||||
} else if (auto *Code = dyn_cast<CodeInit>(&I)) {
|
|
||||||
return Code->getValue();
|
|
||||||
} else if (auto *List = dyn_cast<ListInit>(&I)) {
|
} else if (auto *List = dyn_cast<ListInit>(&I)) {
|
||||||
json::Array array;
|
json::Array array;
|
||||||
for (auto val : *List)
|
for (auto val : *List)
|
||||||
|
|
|
@ -43,15 +43,11 @@ using namespace llvm;
|
||||||
|
|
||||||
static BumpPtrAllocator Allocator;
|
static BumpPtrAllocator Allocator;
|
||||||
|
|
||||||
STATISTIC(CodeInitsConstructed,
|
|
||||||
"The total number of unique CodeInits constructed");
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Type implementations
|
// Type implementations
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
BitRecTy BitRecTy::Shared;
|
BitRecTy BitRecTy::Shared;
|
||||||
CodeRecTy CodeRecTy::Shared;
|
|
||||||
IntRecTy IntRecTy::Shared;
|
IntRecTy IntRecTy::Shared;
|
||||||
StringRecTy StringRecTy::Shared;
|
StringRecTy StringRecTy::Shared;
|
||||||
DagRecTy DagRecTy::Shared;
|
DagRecTy DagRecTy::Shared;
|
||||||
|
@ -113,18 +109,13 @@ bool IntRecTy::typeIsConvertibleTo(const RecTy *RHS) const {
|
||||||
return kind==BitRecTyKind || kind==BitsRecTyKind || kind==IntRecTyKind;
|
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 {
|
std::string StringRecTy::getAsString() const {
|
||||||
return "string";
|
return "string";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StringRecTy::typeIsConvertibleTo(const RecTy *RHS) const {
|
bool StringRecTy::typeIsConvertibleTo(const RecTy *RHS) const {
|
||||||
RecTyKind Kind = RHS->getRecTyKind();
|
RecTyKind Kind = RHS->getRecTyKind();
|
||||||
return Kind == StringRecTyKind || Kind == CodeRecTyKind;
|
return Kind == StringRecTyKind;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ListRecTy::getAsString() const {
|
std::string ListRecTy::getAsString() const {
|
||||||
|
@ -514,38 +505,26 @@ IntInit::convertInitializerBitRange(ArrayRef<unsigned> Bits) const {
|
||||||
return BitsInit::get(NewBits);
|
return BitsInit::get(NewBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeInit *CodeInit::get(StringRef V) {
|
StringInit *StringInit::get(StringRef V, StringFormat Fmt) {
|
||||||
static StringMap<CodeInit*, BumpPtrAllocator &> ThePool(Allocator);
|
static StringMap<StringInit*, BumpPtrAllocator &> StringPool(Allocator);
|
||||||
|
static StringMap<StringInit*, BumpPtrAllocator &> CodePool(Allocator);
|
||||||
|
|
||||||
auto &Entry = *ThePool.insert(std::make_pair(V, nullptr)).first;
|
if (Fmt == SF_String) {
|
||||||
|
auto &Entry = *StringPool.insert(std::make_pair(V, nullptr)).first;
|
||||||
if (!Entry.second)
|
if (!Entry.second)
|
||||||
Entry.second = new(Allocator) CodeInit(Entry.getKey());
|
Entry.second = new (Allocator) StringInit(Entry.getKey(), Fmt);
|
||||||
return Entry.second;
|
return Entry.second;
|
||||||
}
|
} else {
|
||||||
|
auto &Entry = *CodePool.insert(std::make_pair(V, nullptr)).first;
|
||||||
StringInit *StringInit::get(StringRef V) {
|
|
||||||
static StringMap<StringInit*, BumpPtrAllocator &> ThePool(Allocator);
|
|
||||||
|
|
||||||
auto &Entry = *ThePool.insert(std::make_pair(V, nullptr)).first;
|
|
||||||
if (!Entry.second)
|
if (!Entry.second)
|
||||||
Entry.second = new(Allocator) StringInit(Entry.getKey());
|
Entry.second = new (Allocator) StringInit(Entry.getKey(), Fmt);
|
||||||
return Entry.second;
|
return Entry.second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Init *StringInit::convertInitializerTo(RecTy *Ty) const {
|
Init *StringInit::convertInitializerTo(RecTy *Ty) const {
|
||||||
if (isa<StringRecTy>(Ty))
|
if (isa<StringRecTy>(Ty))
|
||||||
return const_cast<StringInit *>(this);
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -868,7 +847,9 @@ static StringInit *ConcatStringInits(const StringInit *I0,
|
||||||
const StringInit *I1) {
|
const StringInit *I1) {
|
||||||
SmallString<80> Concat(I0->getValue());
|
SmallString<80> Concat(I0->getValue());
|
||||||
Concat.append(I1->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,
|
static StringInit *interleaveStringList(const ListInit *List,
|
||||||
|
@ -876,12 +857,15 @@ static StringInit *interleaveStringList(const ListInit *List,
|
||||||
if (List->size() == 0)
|
if (List->size() == 0)
|
||||||
return StringInit::get("");
|
return StringInit::get("");
|
||||||
SmallString<80> Result(dyn_cast<StringInit>(List->getElement(0))->getValue());
|
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) {
|
for (unsigned I = 1, E = List->size(); I < E; ++I) {
|
||||||
Result.append(Delim->getValue());
|
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,
|
static StringInit *interleaveIntList(const ListInit *List,
|
||||||
|
@ -2139,6 +2123,21 @@ StringRef RecordVal::getName() const {
|
||||||
return cast<StringInit>(getNameInit())->getValue();
|
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) {
|
bool RecordVal::setValue(Init *V) {
|
||||||
if (V) {
|
if (V) {
|
||||||
Value = V->getCastTo(getType());
|
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 {
|
void RecordVal::print(raw_ostream &OS, bool PrintSem) const {
|
||||||
if (getPrefix()) OS << "field ";
|
if (getPrefix()) OS << "field ";
|
||||||
OS << *getType() << " " << getNameInitAsString();
|
OS << getPrintType() << " " << getNameInitAsString();
|
||||||
|
|
||||||
if (getValue())
|
if (getValue())
|
||||||
OS << " = " << *getValue();
|
OS << " = " << *getValue();
|
||||||
|
@ -2365,6 +2364,7 @@ StringRef Record::getValueAsString(StringRef FieldName) const {
|
||||||
"' does not have a field named `" + FieldName + "'!\n");
|
"' does not have a field named `" + FieldName + "'!\n");
|
||||||
return S.getValue();
|
return S.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Optional<StringRef>
|
llvm::Optional<StringRef>
|
||||||
Record::getValueAsOptionalString(StringRef FieldName) const {
|
Record::getValueAsOptionalString(StringRef FieldName) const {
|
||||||
const RecordVal *R = getValue(FieldName);
|
const RecordVal *R = getValue(FieldName);
|
||||||
|
@ -2375,28 +2375,11 @@ Record::getValueAsOptionalString(StringRef FieldName) const {
|
||||||
|
|
||||||
if (StringInit *SI = dyn_cast<StringInit>(R->getValue()))
|
if (StringInit *SI = dyn_cast<StringInit>(R->getValue()))
|
||||||
return SI->getValue();
|
return SI->getValue();
|
||||||
if (CodeInit *CI = dyn_cast<CodeInit>(R->getValue()))
|
|
||||||
return CI->getValue();
|
|
||||||
|
|
||||||
PrintFatalError(getLoc(),
|
PrintFatalError(getLoc(),
|
||||||
"Record `" + getName() + "', ` field `" + FieldName +
|
"Record `" + getName() + "', ` field `" + FieldName +
|
||||||
"' exists but does not have a string initializer!");
|
"' 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 {
|
BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const {
|
||||||
const RecordVal *R = getValue(FieldName);
|
const RecordVal *R = getValue(FieldName);
|
||||||
|
@ -2473,8 +2456,6 @@ Record::getValueAsListOfStrings(StringRef FieldName) const {
|
||||||
for (Init *I : List->getValues()) {
|
for (Init *I : List->getValues()) {
|
||||||
if (StringInit *SI = dyn_cast<StringInit>(I))
|
if (StringInit *SI = dyn_cast<StringInit>(I))
|
||||||
Strings.push_back(SI->getValue());
|
Strings.push_back(SI->getValue());
|
||||||
else if (CodeInit *CI = dyn_cast<CodeInit>(I))
|
|
||||||
Strings.push_back(CI->getValue());
|
|
||||||
else
|
else
|
||||||
PrintFatalError(getLoc(),
|
PrintFatalError(getLoc(),
|
||||||
Twine("Record `") + getName() + "', field `" + FieldName +
|
Twine("Record `") + getName() + "', field `" + FieldName +
|
||||||
|
|
|
@ -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]+'.
|
/// LexExclaim - Lex '!' and '![a-zA-Z]+'.
|
||||||
|
|
|
@ -86,8 +86,8 @@ class TGLexer {
|
||||||
// Information about the current token.
|
// Information about the current token.
|
||||||
const char *TokStart = nullptr;
|
const char *TokStart = nullptr;
|
||||||
tgtok::TokKind CurCode = tgtok::TokKind::Eof;
|
tgtok::TokKind CurCode = tgtok::TokKind::Eof;
|
||||||
std::string CurStrVal; // This is valid for ID, STRVAL, VARNAME, CODEFRAGMENT
|
std::string CurStrVal; // This is valid for Id, StrVal, VarName, CodeFragment
|
||||||
int64_t CurIntVal = 0; // This is valid for INTVAL.
|
int64_t CurIntVal = 0; // This is valid for IntVal.
|
||||||
|
|
||||||
/// CurBuffer - This is the current buffer index we're lexing from as managed
|
/// CurBuffer - This is the current buffer index we're lexing from as managed
|
||||||
/// by the SourceMgr object.
|
/// by the SourceMgr object.
|
||||||
|
|
|
@ -799,8 +799,8 @@ bool TGParser::ParseOptionalBitList(SmallVectorImpl<unsigned> &Ranges) {
|
||||||
RecTy *TGParser::ParseType() {
|
RecTy *TGParser::ParseType() {
|
||||||
switch (Lex.getCode()) {
|
switch (Lex.getCode()) {
|
||||||
default: TokError("Unknown token when expecting a type"); return nullptr;
|
default: TokError("Unknown token when expecting a type"); return nullptr;
|
||||||
case tgtok::String: Lex.Lex(); return StringRecTy::get();
|
case tgtok::String:
|
||||||
case tgtok::Code: Lex.Lex(); return CodeRecTy::get();
|
case tgtok::Code: Lex.Lex(); return StringRecTy::get();
|
||||||
case tgtok::Bit: Lex.Lex(); return BitRecTy::get();
|
case tgtok::Bit: Lex.Lex(); return BitRecTy::get();
|
||||||
case tgtok::Int: Lex.Lex(); return IntRecTy::get();
|
case tgtok::Int: Lex.Lex(); return IntRecTy::get();
|
||||||
case tgtok::Dag: Lex.Lex(); return DagRecTy::get();
|
case tgtok::Dag: Lex.Lex(); return DagRecTy::get();
|
||||||
|
@ -1637,6 +1637,9 @@ RecTy *TGParser::ParseOperatorType() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Lex.getCode() == tgtok::Code)
|
||||||
|
TokError("the 'code' type is not allowed in bang operators; use 'string'");
|
||||||
|
|
||||||
Type = ParseType();
|
Type = ParseType();
|
||||||
|
|
||||||
if (!Type) {
|
if (!Type) {
|
||||||
|
@ -1920,7 +1923,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tgtok::CodeFragment:
|
case tgtok::CodeFragment:
|
||||||
R = CodeInit::get(Lex.getCurStrVal());
|
R = StringInit::get(Lex.getCurStrVal(), StringInit::SF_Code);
|
||||||
Lex.Lex();
|
Lex.Lex();
|
||||||
break;
|
break;
|
||||||
case tgtok::question:
|
case tgtok::question:
|
||||||
|
|
|
@ -51,7 +51,7 @@ def MIMGBaseOpcodesTable : GenericTable {
|
||||||
let Fields = ["BaseOpcode", "Store", "Atomic", "AtomicX2", "Sampler",
|
let Fields = ["BaseOpcode", "Store", "Atomic", "AtomicX2", "Sampler",
|
||||||
"Gather4", "NumExtraArgs", "Gradients", "G16", "Coordinates",
|
"Gather4", "NumExtraArgs", "Gradients", "G16", "Coordinates",
|
||||||
"LodOrClampOrMip", "HasD16"];
|
"LodOrClampOrMip", "HasD16"];
|
||||||
GenericEnum TypeOf_BaseOpcode = MIMGBaseOpcode;
|
string TypeOf_BaseOpcode = "MIMGBaseOpcode";
|
||||||
|
|
||||||
let PrimaryKey = ["BaseOpcode"];
|
let PrimaryKey = ["BaseOpcode"];
|
||||||
let PrimaryKeyName = "getMIMGBaseOpcodeInfo";
|
let PrimaryKeyName = "getMIMGBaseOpcodeInfo";
|
||||||
|
@ -65,7 +65,7 @@ def MIMGDimInfoTable : GenericTable {
|
||||||
let FilterClass = "AMDGPUDimProps";
|
let FilterClass = "AMDGPUDimProps";
|
||||||
let CppTypeName = "MIMGDimInfo";
|
let CppTypeName = "MIMGDimInfo";
|
||||||
let Fields = ["Dim", "NumCoords", "NumGradients", "DA", "Encoding", "AsmSuffix"];
|
let Fields = ["Dim", "NumCoords", "NumGradients", "DA", "Encoding", "AsmSuffix"];
|
||||||
GenericEnum TypeOf_Dim = MIMGDim;
|
string TypeOf_Dim = "MIMGDim";
|
||||||
|
|
||||||
let PrimaryKey = ["Dim"];
|
let PrimaryKey = ["Dim"];
|
||||||
let PrimaryKeyName = "getMIMGDimInfo";
|
let PrimaryKeyName = "getMIMGDimInfo";
|
||||||
|
@ -95,8 +95,8 @@ def MIMGLZMappingTable : GenericTable {
|
||||||
let FilterClass = "MIMGLZMapping";
|
let FilterClass = "MIMGLZMapping";
|
||||||
let CppTypeName = "MIMGLZMappingInfo";
|
let CppTypeName = "MIMGLZMappingInfo";
|
||||||
let Fields = ["L", "LZ"];
|
let Fields = ["L", "LZ"];
|
||||||
GenericEnum TypeOf_L = MIMGBaseOpcode;
|
string TypeOf_L = "MIMGBaseOpcode";
|
||||||
GenericEnum TypeOf_LZ = MIMGBaseOpcode;
|
string TypeOf_LZ = "MIMGBaseOpcode";
|
||||||
|
|
||||||
let PrimaryKey = ["L"];
|
let PrimaryKey = ["L"];
|
||||||
let PrimaryKeyName = "getMIMGLZMappingInfo";
|
let PrimaryKeyName = "getMIMGLZMappingInfo";
|
||||||
|
@ -111,8 +111,8 @@ def MIMGMIPMappingTable : GenericTable {
|
||||||
let FilterClass = "MIMGMIPMapping";
|
let FilterClass = "MIMGMIPMapping";
|
||||||
let CppTypeName = "MIMGMIPMappingInfo";
|
let CppTypeName = "MIMGMIPMappingInfo";
|
||||||
let Fields = ["MIP", "NONMIP"];
|
let Fields = ["MIP", "NONMIP"];
|
||||||
GenericEnum TypeOf_MIP = MIMGBaseOpcode;
|
string TypeOf_MIP = "MIMGBaseOpcode";
|
||||||
GenericEnum TypeOf_NONMIP = MIMGBaseOpcode;
|
string TypeOf_NONMIP = "MIMGBaseOpcode";
|
||||||
|
|
||||||
let PrimaryKey = ["MIP"];
|
let PrimaryKey = ["MIP"];
|
||||||
let PrimaryKeyName = "getMIMGMIPMappingInfo";
|
let PrimaryKeyName = "getMIMGMIPMappingInfo";
|
||||||
|
@ -127,8 +127,8 @@ def MIMGG16MappingTable : GenericTable {
|
||||||
let FilterClass = "MIMGG16Mapping";
|
let FilterClass = "MIMGG16Mapping";
|
||||||
let CppTypeName = "MIMGG16MappingInfo";
|
let CppTypeName = "MIMGG16MappingInfo";
|
||||||
let Fields = ["G", "G16"];
|
let Fields = ["G", "G16"];
|
||||||
GenericEnum TypeOf_G = MIMGBaseOpcode;
|
string TypeOf_G = "MIMGBaseOpcode";
|
||||||
GenericEnum TypeOf_G16 = MIMGBaseOpcode;
|
string TypeOf_G16 = "MIMGBaseOpcode";
|
||||||
|
|
||||||
let PrimaryKey = ["G"];
|
let PrimaryKey = ["G"];
|
||||||
let PrimaryKeyName = "getMIMGG16MappingInfo";
|
let PrimaryKeyName = "getMIMGG16MappingInfo";
|
||||||
|
@ -168,8 +168,8 @@ def MIMGInfoTable : GenericTable {
|
||||||
let FilterClass = "MIMG";
|
let FilterClass = "MIMG";
|
||||||
let CppTypeName = "MIMGInfo";
|
let CppTypeName = "MIMGInfo";
|
||||||
let Fields = ["Opcode", "BaseOpcode", "MIMGEncoding", "VDataDwords", "VAddrDwords"];
|
let Fields = ["Opcode", "BaseOpcode", "MIMGEncoding", "VDataDwords", "VAddrDwords"];
|
||||||
GenericEnum TypeOf_BaseOpcode = MIMGBaseOpcode;
|
string TypeOf_BaseOpcode = "MIMGBaseOpcode";
|
||||||
GenericEnum TypeOf_MIMGEncoding = MIMGEncoding;
|
string TypeOf_MIMGEncoding = "MIMGEncoding";
|
||||||
|
|
||||||
let PrimaryKey = ["BaseOpcode", "MIMGEncoding", "VDataDwords", "VAddrDwords"];
|
let PrimaryKey = ["BaseOpcode", "MIMGEncoding", "VDataDwords", "VAddrDwords"];
|
||||||
let PrimaryKeyName = "getMIMGOpcodeHelper";
|
let PrimaryKeyName = "getMIMGOpcodeHelper";
|
||||||
|
@ -926,8 +926,8 @@ def ImageDimIntrinsicTable : GenericTable {
|
||||||
"DMaskIndex", "VAddrStart", "GradientStart", "CoordStart", "LodIndex", "MipIndex", "VAddrEnd",
|
"DMaskIndex", "VAddrStart", "GradientStart", "CoordStart", "LodIndex", "MipIndex", "VAddrEnd",
|
||||||
"RsrcIndex", "SampIndex", "UnormIndex", "TexFailCtrlIndex", "CachePolicyIndex",
|
"RsrcIndex", "SampIndex", "UnormIndex", "TexFailCtrlIndex", "CachePolicyIndex",
|
||||||
"GradientTyArg", "CoordTyArg"];
|
"GradientTyArg", "CoordTyArg"];
|
||||||
GenericEnum TypeOf_BaseOpcode = MIMGBaseOpcode;
|
string TypeOf_BaseOpcode = "MIMGBaseOpcode";
|
||||||
GenericEnum TypeOf_Dim = MIMGDim;
|
string TypeOf_Dim = "MIMGDim";
|
||||||
|
|
||||||
let PrimaryKey = ["Intr"];
|
let PrimaryKey = ["Intr"];
|
||||||
let PrimaryKeyName = "getImageDimIntrinsicInfo";
|
let PrimaryKeyName = "getImageDimIntrinsicInfo";
|
||||||
|
|
|
@ -1,22 +1,49 @@
|
||||||
// RUN: llvm-tblgen %s | FileCheck %s
|
// RUN: llvm-tblgen %s | FileCheck %s
|
||||||
|
// RUN: not llvm-tblgen -DERROR1 %s 2>&1 | FileCheck --check-prefix=ERROR1 %s
|
||||||
// XFAIL: vg_leak
|
// XFAIL: vg_leak
|
||||||
|
|
||||||
// CHECK: --- Defs ---
|
// CHECK: def A1
|
||||||
|
// CHECK: code CodeCode = [{code here;}]
|
||||||
|
// CHECK: code StringCode = [{code here;}]
|
||||||
|
|
||||||
// CHECK: def A0 {
|
// CHECK: def A2
|
||||||
// CHECK: code Code = [{Simple}];
|
// CHECK: string CodeCode = "string here"
|
||||||
// CHECK: }
|
// CHECK: string StringCode = "string here"
|
||||||
|
|
||||||
// CHECK: def B0 {
|
// CHECK: def B1
|
||||||
// CHECK: code Code = [{With paste 7}];
|
// CHECK: string CodeCode = "with paste 7"
|
||||||
// CHECK: }
|
// 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> {
|
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 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 B0 : B<7>;
|
def B1 : B<7>;
|
||||||
|
def C1 : C<42>;
|
||||||
|
def D1 : D<108>;
|
||||||
|
|
||||||
|
#ifdef ERROR1
|
||||||
|
|
||||||
|
// ERROR1: the 'code' type is not allowed
|
||||||
|
|
||||||
|
def Zerror1 {
|
||||||
|
code Code = !cast<code>("i = 0;");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -55,19 +55,26 @@ def ATable : GenericTable {
|
||||||
|
|
||||||
|
|
||||||
// CHECK-LABEL: GET_BTable_IMPL
|
// 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: const BTypeName *lookupBTableByName(StringRef Name) {
|
||||||
// CHECK: return &BTable[Idx->_index];
|
// CHECK: return &BTable[Idx->_index];
|
||||||
// CHECK: }
|
// CHECK: }
|
||||||
|
|
||||||
class BEntry<bits<16> enc> {
|
class BEntry<bits<16> enc, code test = [{}]> {
|
||||||
string Name = NAME;
|
string Name = NAME;
|
||||||
bits<16> Encoding = enc;
|
bits<16> Encoding = enc;
|
||||||
|
code Test = test;
|
||||||
}
|
}
|
||||||
|
|
||||||
def BAlice : BEntry<0xac>;
|
def BAlice : BEntry<0xac>;
|
||||||
def BBob : BEntry<0x14>;
|
def BBob : BEntry<0x14, [{Bob == 13}]>;
|
||||||
def BCharlie : BEntry<0x80>;
|
def BCharlie : BEntry<0x80, "Charlie == 42">;
|
||||||
def BEve : BEntry<0x4c>;
|
def BEve : BEntry<0x4c, [{Eve == }] # 108>;
|
||||||
|
|
||||||
def BValues : GenericEnum {
|
def BValues : GenericEnum {
|
||||||
let FilterClass = "BEntry";
|
let FilterClass = "BEntry";
|
||||||
|
@ -78,7 +85,8 @@ def BValues : GenericEnum {
|
||||||
def BTable : GenericTable {
|
def BTable : GenericTable {
|
||||||
let FilterClass = "BEntry";
|
let FilterClass = "BEntry";
|
||||||
string CppTypeName = "BTypeName";
|
string CppTypeName = "BTypeName";
|
||||||
let Fields = ["Name", "Encoding"];
|
let Fields = ["Name", "Encoding", "Test"];
|
||||||
|
string TypeOf_Test = "code";
|
||||||
}
|
}
|
||||||
|
|
||||||
def lookupBTableByName : SearchIndex {
|
def lookupBTableByName : SearchIndex {
|
||||||
|
@ -126,7 +134,7 @@ def CTable : GenericTable {
|
||||||
let FilterClass = "CEntry";
|
let FilterClass = "CEntry";
|
||||||
let Fields = ["Name", "Kind", "Encoding"];
|
let Fields = ["Name", "Kind", "Encoding"];
|
||||||
|
|
||||||
GenericEnum TypeOf_Kind = CEnum;
|
string TypeOf_Kind = "CEnum";
|
||||||
|
|
||||||
let PrimaryKey = ["Encoding"];
|
let PrimaryKey = ["Encoding"];
|
||||||
let PrimaryKeyName = "lookupCEntryByEncoding";
|
let PrimaryKeyName = "lookupCEntryByEncoding";
|
||||||
|
|
|
@ -69,6 +69,15 @@ def Rec5 {
|
||||||
string ColorList = !interleave(Ishify<Colors>.ret, ", ");
|
string ColorList = !interleave(Ishify<Colors>.ret, ", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CHECK: def Rec6
|
||||||
|
// CHECK: code OperatorList = [{+, -, *, /, ?:, ;}];
|
||||||
|
|
||||||
|
def Rec6 {
|
||||||
|
list<string> Operators = ["+", "-", "*", "/", "?:"];
|
||||||
|
code OperatorList = !interleave(!listconcat(Operators, [[{;}]]), ", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef ERROR1
|
#ifdef ERROR1
|
||||||
def op;
|
def op;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// RUN: not llvm-tblgen -I %p %s 2>&1 | FileCheck %s
|
// 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" }]>;
|
include "unterminated-code-block-include.inc" }]>;
|
||||||
|
|
|
@ -1265,13 +1265,10 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
|
||||||
<< " break;\n";
|
<< " break;\n";
|
||||||
|
|
||||||
for (unsigned i = 0; i < MCOpPredicates.size(); ++i) {
|
for (unsigned i = 0; i < MCOpPredicates.size(); ++i) {
|
||||||
Init *MCOpPred = MCOpPredicates[i]->getValueInit("MCOperandPredicate");
|
StringRef MCOpPred = MCOpPredicates[i]->getValueAsString("MCOperandPredicate");
|
||||||
if (CodeInit *SI = dyn_cast<CodeInit>(MCOpPred)) {
|
|
||||||
O << " case " << i + 1 << ": {\n"
|
O << " case " << i + 1 << ": {\n"
|
||||||
<< SI->getValue() << "\n"
|
<< MCOpPred.data() << "\n"
|
||||||
<< " }\n";
|
<< " }\n";
|
||||||
} else
|
|
||||||
llvm_unreachable("Unexpected MCOperandPredicate field!");
|
|
||||||
}
|
}
|
||||||
O << " }\n"
|
O << " }\n"
|
||||||
<< "}\n\n";
|
<< "}\n\n";
|
||||||
|
|
|
@ -346,8 +346,7 @@ Transition::Transition(Record *R, Automaton *Parent) {
|
||||||
} else if (isa<IntRecTy>(SymbolV->getType())) {
|
} else if (isa<IntRecTy>(SymbolV->getType())) {
|
||||||
Actions.emplace_back(nullptr, R->getValueAsInt(A), "");
|
Actions.emplace_back(nullptr, R->getValueAsInt(A), "");
|
||||||
Types.emplace_back("unsigned");
|
Types.emplace_back("unsigned");
|
||||||
} else if (isa<StringRecTy>(SymbolV->getType()) ||
|
} else if (isa<StringRecTy>(SymbolV->getType())) {
|
||||||
isa<CodeRecTy>(SymbolV->getType())) {
|
|
||||||
Actions.emplace_back(nullptr, 0, std::string(R->getValueAsString(A)));
|
Actions.emplace_back(nullptr, 0, std::string(R->getValueAsString(A)));
|
||||||
Types.emplace_back("std::string");
|
Types.emplace_back("std::string");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -150,7 +150,7 @@ protected:
|
||||||
|
|
||||||
/// A block of arbitrary C++ to finish testing the match.
|
/// A block of arbitrary C++ to finish testing the match.
|
||||||
/// FIXME: This is a temporary measure until we have actual pattern matching
|
/// 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.
|
/// 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
|
/// This allows the plumbing of arbitrary data from C++ predicates between the
|
||||||
|
@ -199,7 +199,7 @@ public:
|
||||||
unsigned allocUID() { return UID++; }
|
unsigned allocUID() { return UID++; }
|
||||||
StringRef getName() const { return TheDef.getName(); }
|
StringRef getName() const { return TheDef.getName(); }
|
||||||
const Record &getDef() const { return TheDef; }
|
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(); }
|
size_t getNumRoots() const { return Roots.size(); }
|
||||||
|
|
||||||
GIMatchDag &getMatchDag() { return MatchDag; }
|
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
|
// 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 &&
|
assert(!MatchingFixupCode &&
|
||||||
"Only one block of arbitrary code is currently permitted");
|
"Only one block of arbitrary code is currently permitted");
|
||||||
MatchingFixupCode = CodeI;
|
MatchingFixupCode = StringI;
|
||||||
MatchDag.setHasPostMatchPredicate(true);
|
MatchDag.setHasPostMatchPredicate(true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -807,7 +807,7 @@ void GICombinerEmitter::generateCodeForTree(raw_ostream &OS,
|
||||||
}
|
}
|
||||||
OS << ") {\n" << Indent << " ";
|
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,
|
OS << CodeExpander(Code->getAsUnquotedString(), Expansions,
|
||||||
RuleDef.getLoc(), ShowExpansions)
|
RuleDef.getLoc(), ShowExpansions)
|
||||||
<< "\n"
|
<< "\n"
|
||||||
|
|
|
@ -533,14 +533,11 @@ static unsigned getPredicates(DenseMap<const Record *, unsigned> &PredicateMap,
|
||||||
static void printPredicates(std::vector<const Record *> &Predicates,
|
static void printPredicates(std::vector<const Record *> &Predicates,
|
||||||
StringRef Name, raw_ostream &o) {
|
StringRef Name, raw_ostream &o) {
|
||||||
for (unsigned i = 0; i < Predicates.size(); ++i) {
|
for (unsigned i = 0; i < Predicates.size(); ++i) {
|
||||||
Init *Pred = Predicates[i]->getValueInit(Name);
|
StringRef Pred = Predicates[i]->getValueAsString(Name);
|
||||||
if (CodeInit *SI = dyn_cast<CodeInit>(Pred))
|
|
||||||
o << " case " << i + 1 << ": {\n"
|
o << " case " << i + 1 << ": {\n"
|
||||||
<< " // " << Predicates[i]->getName().str() << "\n"
|
<< " // " << Predicates[i]->getName().str() << "\n"
|
||||||
<< " " << SI->getValue() << "\n"
|
<< " " << Pred.data() << "\n"
|
||||||
<< " }\n";
|
<< " }\n";
|
||||||
else
|
|
||||||
llvm_unreachable("Unexpected predicate field!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,7 @@ struct GenericEnum {
|
||||||
struct GenericField {
|
struct GenericField {
|
||||||
std::string Name;
|
std::string Name;
|
||||||
RecTy *RecType = nullptr;
|
RecTy *RecType = nullptr;
|
||||||
|
bool IsCode = false;
|
||||||
bool IsIntrinsic = false;
|
bool IsIntrinsic = false;
|
||||||
bool IsInstruction = false;
|
bool IsInstruction = false;
|
||||||
GenericEnum *Enum = nullptr;
|
GenericEnum *Enum = nullptr;
|
||||||
|
@ -111,14 +112,15 @@ private:
|
||||||
|
|
||||||
std::string primaryRepresentation(SMLoc Loc, const GenericField &Field,
|
std::string primaryRepresentation(SMLoc Loc, const GenericField &Field,
|
||||||
Init *I) {
|
Init *I) {
|
||||||
if (StringInit *SI = dyn_cast<StringInit>(I))
|
if (StringInit *SI = dyn_cast<StringInit>(I)) {
|
||||||
|
if (Field.IsCode || SI->hasCodeFormat())
|
||||||
|
return std::string(SI->getValue());
|
||||||
|
else
|
||||||
return SI->getAsString();
|
return SI->getAsString();
|
||||||
else if (BitsInit *BI = dyn_cast<BitsInit>(I))
|
} else if (BitsInit *BI = dyn_cast<BitsInit>(I))
|
||||||
return "0x" + utohexstr(getAsInt(BI));
|
return "0x" + utohexstr(getAsInt(BI));
|
||||||
else if (BitInit *BI = dyn_cast<BitInit>(I))
|
else if (BitInit *BI = dyn_cast<BitInit>(I))
|
||||||
return BI->getValue() ? "true" : "false";
|
return BI->getValue() ? "true" : "false";
|
||||||
else if (CodeInit *CI = dyn_cast<CodeInit>(I))
|
|
||||||
return std::string(CI->getValue());
|
|
||||||
else if (Field.IsIntrinsic)
|
else if (Field.IsIntrinsic)
|
||||||
return "Intrinsic::" + getIntrinsic(I).EnumName;
|
return "Intrinsic::" + getIntrinsic(I).EnumName;
|
||||||
else if (Field.IsInstruction)
|
else if (Field.IsInstruction)
|
||||||
|
@ -150,10 +152,6 @@ private:
|
||||||
|
|
||||||
bool compareBy(Record *LHS, Record *RHS, const SearchIndex &Index);
|
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,
|
std::string searchableFieldType(const GenericTable &Table,
|
||||||
const SearchIndex &Index,
|
const SearchIndex &Index,
|
||||||
const GenericField &Field, TypeContext Ctx) {
|
const GenericField &Field, TypeContext Ctx) {
|
||||||
|
@ -545,15 +543,21 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
|
||||||
OS << "#endif\n\n";
|
OS << "#endif\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SearchableTableEmitter::parseFieldType(GenericField &Field, Init *II) {
|
bool SearchableTableEmitter::parseFieldType(GenericField &Field, Init *TypeOf) {
|
||||||
if (auto DI = dyn_cast<DefInit>(II)) {
|
if (auto Type = dyn_cast<StringInit>(TypeOf)) {
|
||||||
Record *TypeRec = DI->getDef();
|
if (Type->getValue() == "code") {
|
||||||
|
Field.IsCode = true;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (Record *TypeRec = Records.getDef(Type->getValue())) {
|
||||||
if (TypeRec->isSubClassOf("GenericEnum")) {
|
if (TypeRec->isSubClassOf("GenericEnum")) {
|
||||||
Field.Enum = EnumMap[TypeRec];
|
Field.Enum = EnumMap[TypeRec];
|
||||||
Field.RecType = RecordRecTy::get(Field.Enum->Class);
|
Field.RecType = RecordRecTy::get(Field.Enum->Class);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -708,12 +712,14 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
|
||||||
for (const auto &FieldName : Fields) {
|
for (const auto &FieldName : Fields) {
|
||||||
Table->Fields.emplace_back(FieldName); // Construct a GenericField.
|
Table->Fields.emplace_back(FieldName); // Construct a GenericField.
|
||||||
|
|
||||||
if (auto TypeOfVal = TableRec->getValue(("TypeOf_" + FieldName).str())) {
|
if (auto TypeOfRecordVal = TableRec->getValue(("TypeOf_" + FieldName).str())) {
|
||||||
if (!parseFieldType(Table->Fields.back(), TypeOfVal->getValue())) {
|
if (!parseFieldType(Table->Fields.back(), TypeOfRecordVal->getValue())) {
|
||||||
PrintFatalError(TypeOfVal,
|
PrintError(TypeOfRecordVal,
|
||||||
Twine("Table '") + Table->Name +
|
Twine("Table '") + Table->Name +
|
||||||
"' has invalid 'TypeOf_" + FieldName +
|
"' has invalid 'TypeOf_" + FieldName +
|
||||||
"': " + TypeOfVal->getValue()->getAsString());
|
"': " + TypeOfRecordVal->getValue()->getAsString());
|
||||||
|
PrintFatalNote("The 'TypeOf_xxx' field must be a string naming a "
|
||||||
|
"GenericEnum record, or \"code\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
#include "llvm/Support/SMLoc.h"
|
#include "llvm/Support/SMLoc.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class CodeInit;
|
|
||||||
class DefInit;
|
class DefInit;
|
||||||
class Record;
|
class Record;
|
||||||
class StringInit;
|
class StringInit;
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
using namespace mlir;
|
using namespace mlir;
|
||||||
using namespace mlir::tblgen;
|
using namespace mlir::tblgen;
|
||||||
|
|
||||||
using llvm::CodeInit;
|
|
||||||
using llvm::DefInit;
|
using llvm::DefInit;
|
||||||
using llvm::Init;
|
using llvm::Init;
|
||||||
using llvm::Record;
|
using llvm::Record;
|
||||||
|
@ -27,8 +26,6 @@ using llvm::StringInit;
|
||||||
// Returns the initializer's value as string if the given TableGen initializer
|
// Returns the initializer's value as string if the given TableGen initializer
|
||||||
// is a code or string initializer. Returns the empty StringRef otherwise.
|
// is a code or string initializer. Returns the empty StringRef otherwise.
|
||||||
static StringRef getValueAsString(const Init *init) {
|
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))
|
if (const auto *str = dyn_cast<StringInit>(init))
|
||||||
return str->getValue().trim();
|
return str->getValue().trim();
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -38,7 +38,7 @@ std::string Dialect::getCppClassName() const {
|
||||||
static StringRef getAsStringOrEmpty(const llvm::Record &record,
|
static StringRef getAsStringOrEmpty(const llvm::Record &record,
|
||||||
StringRef fieldName) {
|
StringRef fieldName) {
|
||||||
if (auto valueInit = record.getValueInit(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 record.getValueAsString(fieldName);
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -547,12 +547,12 @@ StringRef Operator::getSummary() const {
|
||||||
|
|
||||||
bool Operator::hasAssemblyFormat() const {
|
bool Operator::hasAssemblyFormat() const {
|
||||||
auto *valueInit = def.getValueInit("assemblyFormat");
|
auto *valueInit = def.getValueInit("assemblyFormat");
|
||||||
return isa<llvm::CodeInit, llvm::StringInit>(valueInit);
|
return isa<llvm::StringInit>(valueInit);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef Operator::getAssemblyFormat() const {
|
StringRef Operator::getAssemblyFormat() const {
|
||||||
return TypeSwitch<llvm::Init *, StringRef>(def.getValueInit("assemblyFormat"))
|
return TypeSwitch<llvm::Init *, StringRef>(def.getValueInit("assemblyFormat"))
|
||||||
.Case<llvm::StringInit, llvm::CodeInit>(
|
.Case<llvm::StringInit>(
|
||||||
[&](auto *init) { return init->getValue(); });
|
[&](auto *init) { return init->getValue(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ bool DagLeaf::isEnumAttrCase() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DagLeaf::isStringAttr() const {
|
bool DagLeaf::isStringAttr() const {
|
||||||
return isa<llvm::StringInit, llvm::CodeInit>(def);
|
return isa<llvm::StringInit>(def);
|
||||||
}
|
}
|
||||||
|
|
||||||
Constraint DagLeaf::getAsConstraint() const {
|
Constraint DagLeaf::getAsConstraint() const {
|
||||||
|
|
|
@ -46,7 +46,7 @@ Optional<StringRef> TypeConstraint::getBuilderCall() const {
|
||||||
if (!builderCall || !builderCall->getValue())
|
if (!builderCall || !builderCall->getValue())
|
||||||
return llvm::None;
|
return llvm::None;
|
||||||
return TypeSwitch<llvm::Init *, Optional<StringRef>>(builderCall->getValue())
|
return TypeSwitch<llvm::Init *, Optional<StringRef>>(builderCall->getValue())
|
||||||
.Case<llvm::StringInit, llvm::CodeInit>([&](auto *init) {
|
.Case<llvm::StringInit>([&](auto *init) {
|
||||||
StringRef value = init->getValue();
|
StringRef value = init->getValue();
|
||||||
return value.empty() ? Optional<StringRef>() : value;
|
return value.empty() ? Optional<StringRef>() : value;
|
||||||
})
|
})
|
||||||
|
|
|
@ -78,10 +78,10 @@ llvm::Optional<StringRef> TypeDef::getMnemonic() const {
|
||||||
return def->getValueAsOptionalString("mnemonic");
|
return def->getValueAsOptionalString("mnemonic");
|
||||||
}
|
}
|
||||||
llvm::Optional<StringRef> TypeDef::getPrinterCode() const {
|
llvm::Optional<StringRef> TypeDef::getPrinterCode() const {
|
||||||
return def->getValueAsOptionalCode("printer");
|
return def->getValueAsOptionalString("printer");
|
||||||
}
|
}
|
||||||
llvm::Optional<StringRef> TypeDef::getParserCode() const {
|
llvm::Optional<StringRef> TypeDef::getParserCode() const {
|
||||||
return def->getValueAsOptionalCode("parser");
|
return def->getValueAsOptionalString("parser");
|
||||||
}
|
}
|
||||||
bool TypeDef::genAccessors() const {
|
bool TypeDef::genAccessors() const {
|
||||||
return def->getValueAsBit("genAccessors");
|
return def->getValueAsBit("genAccessors");
|
||||||
|
@ -114,7 +114,7 @@ llvm::Optional<StringRef> TypeParameter::getAllocator() const {
|
||||||
llvm::RecordVal *code = typeParameter->getDef()->getValue("allocator");
|
llvm::RecordVal *code = typeParameter->getDef()->getValue("allocator");
|
||||||
if (!code)
|
if (!code)
|
||||||
return llvm::Optional<StringRef>();
|
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();
|
return ci->getValue();
|
||||||
if (isa<llvm::UnsetInit>(code->getValue()))
|
if (isa<llvm::UnsetInit>(code->getValue()))
|
||||||
return llvm::Optional<StringRef>();
|
return llvm::Optional<StringRef>();
|
||||||
|
|
|
@ -137,7 +137,7 @@ static std::string replaceAllSubstrs(std::string str, const std::string &match,
|
||||||
static inline bool hasStringAttribute(const Record &record,
|
static inline bool hasStringAttribute(const Record &record,
|
||||||
StringRef fieldName) {
|
StringRef fieldName) {
|
||||||
auto valueInit = record.getValueInit(fieldName);
|
auto valueInit = record.getValueInit(fieldName);
|
||||||
return isa<CodeInit, StringInit>(valueInit);
|
return isa<StringInit>(valueInit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string getArgumentName(const Operator &op, int index) {
|
static std::string getArgumentName(const Operator &op, int index) {
|
||||||
|
@ -1796,15 +1796,15 @@ void OpEmitter::genPrinter() {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto valueInit = def.getValueInit("printer");
|
auto valueInit = def.getValueInit("printer");
|
||||||
CodeInit *codeInit = dyn_cast<CodeInit>(valueInit);
|
StringInit *stringInit = dyn_cast<StringInit>(valueInit);
|
||||||
if (!codeInit)
|
if (!stringInit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto *method =
|
auto *method =
|
||||||
opClass.addMethodAndPrune("void", "print", "::mlir::OpAsmPrinter &", "p");
|
opClass.addMethodAndPrune("void", "print", "::mlir::OpAsmPrinter &", "p");
|
||||||
FmtContext fctx;
|
FmtContext fctx;
|
||||||
fctx.addSubst("cppClass", opClass.getClassName());
|
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);
|
method->body() << " " << tgfmt(printer, &fctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1816,8 +1816,8 @@ void OpEmitter::genVerifier() {
|
||||||
<< "return ::mlir::failure();\n";
|
<< "return ::mlir::failure();\n";
|
||||||
|
|
||||||
auto *valueInit = def.getValueInit("verifier");
|
auto *valueInit = def.getValueInit("verifier");
|
||||||
CodeInit *codeInit = dyn_cast<CodeInit>(valueInit);
|
StringInit *stringInit = dyn_cast<StringInit>(valueInit);
|
||||||
bool hasCustomVerify = codeInit && !codeInit->getValue().empty();
|
bool hasCustomVerify = stringInit && !stringInit->getValue().empty();
|
||||||
populateSubstitutions(op, "this->getAttr", "this->getODSOperands",
|
populateSubstitutions(op, "this->getAttr", "this->getODSOperands",
|
||||||
"this->getODSResults", verifyCtx);
|
"this->getODSResults", verifyCtx);
|
||||||
|
|
||||||
|
@ -1841,7 +1841,7 @@ void OpEmitter::genVerifier() {
|
||||||
if (hasCustomVerify) {
|
if (hasCustomVerify) {
|
||||||
FmtContext fctx;
|
FmtContext fctx;
|
||||||
fctx.addSubst("cppClass", opClass.getClassName());
|
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);
|
body << " " << tgfmt(printer, &fctx);
|
||||||
} else {
|
} else {
|
||||||
body << " return ::mlir::success();\n";
|
body << " return ::mlir::success();\n";
|
||||||
|
|
Loading…
Reference in New Issue