diff --git a/clang/utils/TableGen/ClangOptionDocEmitter.cpp b/clang/utils/TableGen/ClangOptionDocEmitter.cpp --- a/clang/utils/TableGen/ClangOptionDocEmitter.cpp +++ b/clang/utils/TableGen/ClangOptionDocEmitter.cpp @@ -217,8 +217,6 @@ StringRef Value; if (auto *SV = dyn_cast_or_null(V->getValue())) Value = SV->getValue(); - else if (auto *CV = dyn_cast_or_null(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 --- a/llvm/docs/TableGen/BackEnds.rst +++ b/llvm/docs/TableGen/BackEnds.rst @@ -693,8 +693,8 @@ table that holds the entries. If unspecified, the ``FilterClass`` name is used. -* ``list 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 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 @@ * ``bit PrimaryKeyEarlyOut``. See the third example below. -TableGen attempts to deduce the type of each of the table fields. It can -deduce ``bit``, ``bits``, ``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``, ``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 @@ 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 @@ 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 --- a/llvm/docs/TableGen/BackGuide.rst +++ b/llvm/docs/TableGen/BackGuide.rst @@ -287,9 +287,9 @@ 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 @@ * 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 --- a/llvm/docs/TableGen/ProgRef.rst +++ b/llvm/docs/TableGen/ProgRef.rst @@ -167,10 +167,11 @@ .. 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 @@ 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 @@ 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 @@ 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 @@ .. 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 --- a/llvm/include/llvm/TableGen/Error.h +++ b/llvm/include/llvm/TableGen/Error.h @@ -22,6 +22,7 @@ void PrintNote(const Twine &Msg); void PrintNote(ArrayRef NoteLoc, const Twine &Msg); +LLVM_ATTRIBUTE_NORETURN void PrintFatalNote(const Twine &Msg); LLVM_ATTRIBUTE_NORETURN void PrintFatalNote(ArrayRef ErrorLoc, const Twine &Msg); LLVM_ATTRIBUTE_NORETURN void PrintFatalNote(const Record *Rec, @@ -37,6 +38,7 @@ void PrintError(ArrayRef 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 ErrorLoc, diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h --- a/llvm/include/llvm/TableGen/Record.h +++ b/llvm/include/llvm/TableGen/Record.h @@ -58,7 +58,6 @@ enum RecTyKind { BitRecTyKind, BitsRecTyKind, - CodeRecTyKind, IntRecTyKind, StringRecTyKind, ListRecTyKind, @@ -138,24 +137,6 @@ 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 @@ IK_FirstTypedInit, IK_BitInit, IK_BitsInit, - IK_CodeInit, IK_DagInit, IK_DefInit, IK_FieldInit, @@ -597,16 +577,18 @@ /// "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 @@ 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(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 @@ /// 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 @@ /// not a string and llvm::Optional() if the field does not exist. llvm::Optional 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 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 --- a/llvm/include/llvm/TableGen/SearchableTable.td +++ b/llvm/include/llvm/TableGen/SearchableTable.td @@ -67,9 +67,13 @@ // 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 @@ // def MyTable : GenericTable { // let FilterClass = "MyTableEntry"; // let Fields = ["V", ...]; - // GenericEnum TypeOf_V = MyEnum; + // string TypeOf_V = "MyEnum"; // } // - // Fields of type bit, bits, 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 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 --- a/llvm/lib/TableGen/Error.cpp +++ b/llvm/lib/TableGen/Error.cpp @@ -52,6 +52,13 @@ // 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 NoteLoc, const Twine &Msg) { PrintNote(NoteLoc, Msg); // The following call runs the file cleanup handlers. @@ -107,6 +114,12 @@ 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 --- a/llvm/lib/TableGen/JSONBackend.cpp +++ b/llvm/lib/TableGen/JSONBackend.cpp @@ -59,8 +59,6 @@ return Int->getValue(); } else if (auto *Str = dyn_cast(&I)) { return Str->getValue(); - } else if (auto *Code = dyn_cast(&I)) { - return Code->getValue(); } else if (auto *List = dyn_cast(&I)) { json::Array array; for (auto val : *List) diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -43,15 +43,11 @@ 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 @@ 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 @@ return BitsInit::get(NewBits); } -CodeInit *CodeInit::get(StringRef V) { - static StringMap ThePool(Allocator); +StringInit *StringInit::get(StringRef V, StringFormat Fmt) { + static StringMap StringPool(Allocator); + static StringMap 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 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(Ty)) return const_cast(this); - if (isa(Ty)) - return CodeInit::get(getValue()); - - return nullptr; -} - -Init *CodeInit::convertInitializerTo(RecTy *Ty) const { - if (isa(Ty)) - return const_cast(this); - if (isa(Ty)) - return StringInit::get(getValue()); return nullptr; } @@ -868,7 +847,9 @@ 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 @@ if (List->size() == 0) return StringInit::get(""); SmallString<80> Result(dyn_cast(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(List->getElement(I))->getValue()); + auto *StrInit = dyn_cast(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 @@ return cast(getNameInit())->getValue(); } +std::string RecordVal::getPrintType() const { + if (getType() == StringRecTy::get()) { + if (auto *StrInit = dyn_cast(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 @@ 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 @@ "' does not have a field named `" + FieldName + "'!\n"); return S.getValue(); } + llvm::Optional Record::getValueAsOptionalString(StringRef FieldName) const { const RecordVal *R = getValue(FieldName); @@ -2375,28 +2375,11 @@ if (StringInit *SI = dyn_cast(R->getValue())) return SI->getValue(); - if (CodeInit *CI = dyn_cast(R->getValue())) - return CI->getValue(); PrintFatalError(getLoc(), "Record `" + getName() + "', ` field `" + FieldName + "' exists but does not have a string initializer!"); } -llvm::Optional -Record::getValueAsOptionalCode(StringRef FieldName) const { - const RecordVal *R = getValue(FieldName); - if (!R || !R->getValue()) - return llvm::Optional(); - if (isa(R->getValue())) - return llvm::Optional(); - - if (CodeInit *CI = dyn_cast(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 @@ for (Init *I : List->getValues()) { if (StringInit *SI = dyn_cast(I)) Strings.push_back(SI->getValue()); - else if (CodeInit *CI = dyn_cast(I)) - Strings.push_back(CI->getValue()); else PrintFatalError(getLoc(), Twine("Record `") + getName() + "', field `" + FieldName + diff --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h --- a/llvm/lib/TableGen/TGLexer.h +++ b/llvm/lib/TableGen/TGLexer.h @@ -86,8 +86,8 @@ // 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/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp --- a/llvm/lib/TableGen/TGLexer.cpp +++ b/llvm/lib/TableGen/TGLexer.cpp @@ -540,7 +540,7 @@ } } - 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/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp --- a/llvm/lib/TableGen/TGParser.cpp +++ b/llvm/lib/TableGen/TGParser.cpp @@ -799,8 +799,8 @@ 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 @@ 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 @@ 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 --- a/llvm/lib/Target/AMDGPU/MIMGInstructions.td +++ b/llvm/lib/Target/AMDGPU/MIMGInstructions.td @@ -51,7 +51,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ "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 --- 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 Code = c; + code CodeCode = c; + string StringCode = c; } -def A0 : A<"Simple">; +def A1 : A<[{code here;}]>; +def A2 : A<"string here">; + +class B : A<"with paste " # i>; +class C : A(i))>; +class D : A(i), "!")>; + +def B1 : B<7>; +def C1 : C<42>; +def D1 : D<108>; -class B : A<"With paste " # i>; +#ifdef ERROR1 + +// ERROR1: the 'code' type is not allowed + +def Zerror1 { + code Code = !cast("i = 0;"); +} -def B0 : B<7>; +#endif diff --git a/llvm/test/TableGen/generic-tables.td b/llvm/test/TableGen/generic-tables.td --- a/llvm/test/TableGen/generic-tables.td +++ b/llvm/test/TableGen/generic-tables.td @@ -55,19 +55,26 @@ // 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 enc> { +class BEntry 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 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 @@ 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 --- a/llvm/test/TableGen/interleave.td +++ b/llvm/test/TableGen/interleave.td @@ -28,9 +28,9 @@ } // 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 @@ } // 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 @@ } // 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 @@ } // 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 Colors = ["red", "green", "yellow"]; string ColorList = !interleave(Ishify.ret, ", "); } +// CHECK: def Rec6 +// CHECK: code OperatorList = [{+, -, *, /, ?:, ;}]; + +def Rec6 { + list 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 --- 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 --- a/llvm/utils/TableGen/AsmWriterEmitter.cpp +++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp @@ -1265,13 +1265,10 @@ << " break;\n"; for (unsigned i = 0; i < MCOpPredicates.size(); ++i) { - Init *MCOpPred = MCOpPredicates[i]->getValueInit("MCOperandPredicate"); - if (CodeInit *SI = dyn_cast(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 --- a/llvm/utils/TableGen/DFAEmitter.cpp +++ b/llvm/utils/TableGen/DFAEmitter.cpp @@ -346,8 +346,7 @@ } else if (isa(SymbolV->getType())) { Actions.emplace_back(nullptr, R->getValueAsInt(A), ""); Types.emplace_back("unsigned"); - } else if (isa(SymbolV->getType()) || - isa(SymbolV->getType())) { + } else if (isa(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 --- a/llvm/utils/TableGen/GICombinerEmitter.cpp +++ b/llvm/utils/TableGen/GICombinerEmitter.cpp @@ -150,7 +150,7 @@ /// 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 @@ 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 @@ // Parse arbitrary C++ code we have in lieu of supporting MIR matching - if (const CodeInit *CodeI = dyn_cast(Matchers->getArg(I))) { + if (const StringInit *StringI = dyn_cast(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 @@ } OS << ") {\n" << Indent << " "; - if (const CodeInit *Code = dyn_cast(Applyer->getArg(0))) { + if (const StringInit *Code = dyn_cast(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 --- a/llvm/utils/TableGen/RISCVCompressInstEmitter.cpp +++ b/llvm/utils/TableGen/RISCVCompressInstEmitter.cpp @@ -533,14 +533,11 @@ static void printPredicates(std::vector &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(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 --- a/llvm/utils/TableGen/SearchableTableEmitter.cpp +++ b/llvm/utils/TableGen/SearchableTableEmitter.cpp @@ -54,6 +54,7 @@ struct GenericField { std::string Name; RecTy *RecType = nullptr; + bool IsCode = false; bool IsIntrinsic = false; bool IsInstruction = false; GenericEnum *Enum = nullptr; @@ -111,14 +112,15 @@ std::string primaryRepresentation(SMLoc Loc, const GenericField &Field, Init *I) { - if (StringInit *SI = dyn_cast(I)) - return SI->getAsString(); - else if (BitsInit *BI = dyn_cast(I)) + if (StringInit *SI = dyn_cast(I)) { + if (Field.IsCode || SI->hasCodeFormat()) + return std::string(SI->getValue()); + else + return SI->getAsString(); + } else if (BitsInit *BI = dyn_cast(I)) return "0x" + utohexstr(getAsInt(BI)); else if (BitInit *BI = dyn_cast(I)) return BI->getValue() ? "true" : "false"; - else if (CodeInit *CI = dyn_cast(I)) - return std::string(CI->getValue()); else if (Field.IsIntrinsic) return "Intrinsic::" + getIntrinsic(I).EnumName; else if (Field.IsInstruction) @@ -150,10 +152,6 @@ bool compareBy(Record *LHS, Record *RHS, const SearchIndex &Index); - bool isIntegral(Init *I) { - return isa(I) || isa(I) || isIntrinsic(I); - } - std::string searchableFieldType(const GenericTable &Table, const SearchIndex &Index, const GenericField &Field, TypeContext Ctx) { @@ -545,13 +543,19 @@ OS << "#endif\n\n"; } -bool SearchableTableEmitter::parseFieldType(GenericField &Field, Init *II) { - if (auto DI = dyn_cast(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(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 @@ 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 --- 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 --- 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 @@ // 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(init)) - return code->getValue().trim(); if (const auto *str = dyn_cast(init)) return str->getValue().trim(); return {}; diff --git a/mlir/lib/TableGen/Dialect.cpp b/mlir/lib/TableGen/Dialect.cpp --- a/mlir/lib/TableGen/Dialect.cpp +++ b/mlir/lib/TableGen/Dialect.cpp @@ -38,7 +38,7 @@ static StringRef getAsStringOrEmpty(const llvm::Record &record, StringRef fieldName) { if (auto valueInit = record.getValueInit(fieldName)) { - if (llvm::isa(valueInit)) + if (llvm::isa(valueInit)) return record.getValueAsString(fieldName); } return ""; diff --git a/mlir/lib/TableGen/Operator.cpp b/mlir/lib/TableGen/Operator.cpp --- a/mlir/lib/TableGen/Operator.cpp +++ b/mlir/lib/TableGen/Operator.cpp @@ -547,12 +547,12 @@ bool Operator::hasAssemblyFormat() const { auto *valueInit = def.getValueInit("assemblyFormat"); - return isa(valueInit); + return isa(valueInit); } StringRef Operator::getAssemblyFormat() const { return TypeSwitch(def.getValueInit("assemblyFormat")) - .Case( + .Case( [&](auto *init) { return init->getValue(); }); } diff --git a/mlir/lib/TableGen/Pattern.cpp b/mlir/lib/TableGen/Pattern.cpp --- a/mlir/lib/TableGen/Pattern.cpp +++ b/mlir/lib/TableGen/Pattern.cpp @@ -55,7 +55,7 @@ } bool DagLeaf::isStringAttr() const { - return isa(def); + return isa(def); } Constraint DagLeaf::getAsConstraint() const { diff --git a/mlir/lib/TableGen/Type.cpp b/mlir/lib/TableGen/Type.cpp --- a/mlir/lib/TableGen/Type.cpp +++ b/mlir/lib/TableGen/Type.cpp @@ -46,7 +46,7 @@ if (!builderCall || !builderCall->getValue()) return llvm::None; return TypeSwitch>(builderCall->getValue()) - .Case([&](auto *init) { + .Case([&](auto *init) { StringRef value = init->getValue(); return value.empty() ? Optional() : value; }) diff --git a/mlir/lib/TableGen/TypeDef.cpp b/mlir/lib/TableGen/TypeDef.cpp --- a/mlir/lib/TableGen/TypeDef.cpp +++ b/mlir/lib/TableGen/TypeDef.cpp @@ -78,10 +78,10 @@ return def->getValueAsOptionalString("mnemonic"); } llvm::Optional TypeDef::getPrinterCode() const { - return def->getValueAsOptionalCode("printer"); + return def->getValueAsOptionalString("printer"); } llvm::Optional TypeDef::getParserCode() const { - return def->getValueAsOptionalCode("parser"); + return def->getValueAsOptionalString("parser"); } bool TypeDef::genAccessors() const { return def->getValueAsBit("genAccessors"); @@ -114,7 +114,7 @@ llvm::RecordVal *code = typeParameter->getDef()->getValue("allocator"); if (!code) return llvm::Optional(); - if (llvm::CodeInit *ci = dyn_cast(code->getValue())) + if (llvm::StringInit *ci = dyn_cast(code->getValue())) return ci->getValue(); if (isa(code->getValue())) return llvm::Optional(); diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp --- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp +++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp @@ -137,7 +137,7 @@ static inline bool hasStringAttribute(const Record &record, StringRef fieldName) { auto valueInit = record.getValueInit(fieldName); - return isa(valueInit); + return isa(valueInit); } static std::string getArgumentName(const Operator &op, int index) { @@ -1796,15 +1796,15 @@ return; auto valueInit = def.getValueInit("printer"); - CodeInit *codeInit = dyn_cast(valueInit); - if (!codeInit) + StringInit *stringInit = dyn_cast(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 @@ << "return ::mlir::failure();\n"; auto *valueInit = def.getValueInit("verifier"); - CodeInit *codeInit = dyn_cast(valueInit); - bool hasCustomVerify = codeInit && !codeInit->getValue().empty(); + StringInit *stringInit = dyn_cast(valueInit); + bool hasCustomVerify = stringInit && !stringInit->getValue().empty(); populateSubstitutions(op, "this->getAttr", "this->getODSOperands", "this->getODSResults", verifyCtx); @@ -1841,7 +1841,7 @@ 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";