From 88403d7a840f09395e45bb1e0a757cf8362beb5a Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Tue, 5 Jul 2016 21:22:55 +0000 Subject: [PATCH] TableGen: promote "code" type from syntactic sugar. It's being immediately converted to a "string", but being able to tell what type the field was originally can be useful in backends. llvm-svn: 274575 --- llvm/include/llvm/TableGen/Record.h | 63 +++++++++++++++++++++++- llvm/lib/TableGen/Record.cpp | 25 ++++++++++ llvm/lib/TableGen/TGParser.cpp | 4 +- llvm/utils/TableGen/AsmWriterEmitter.cpp | 2 +- 4 files changed, 89 insertions(+), 5 deletions(-) diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h index 43b1af086d24..019e217718db 100644 --- a/llvm/include/llvm/TableGen/Record.h +++ b/llvm/include/llvm/TableGen/Record.h @@ -44,6 +44,7 @@ public: enum RecTyKind { BitRecTyKind, BitsRecTyKind, + CodeRecTyKind, IntRecTyKind, StringRecTyKind, ListRecTyKind, @@ -116,6 +117,22 @@ public: bool typeIsConvertibleTo(const RecTy *RHS) const override; }; +/// CodeRecTy - '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"; } +}; + /// IntRecTy - 'int' - Represent an integer value of no particular size /// class IntRecTy : public RecTy { @@ -142,7 +159,8 @@ class StringRecTy : public RecTy { public: static bool classof(const RecTy *RT) { - return RT->getRecTyKind() == StringRecTyKind; + return RT->getRecTyKind() == StringRecTyKind || + RT->getRecTyKind() == CodeRecTyKind; } static StringRecTy *get() { return &Shared; } @@ -237,6 +255,7 @@ protected: IK_BitInit, IK_FirstTypedInit, IK_BitsInit, + IK_CodeInit, IK_DagInit, IK_DefInit, IK_FieldInit, @@ -556,7 +575,7 @@ class StringInit : public TypedInit { std::string Value; explicit StringInit(StringRef V) - : TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {} + : TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {} StringInit(const StringInit &Other) = delete; StringInit &operator=(const StringInit &Other) = delete; @@ -572,6 +591,46 @@ public: Init *convertInitializerTo(RecTy *Ty) const override; std::string getAsString() const override { return "\"" + Value + "\""; } + + std::string getAsUnquotedString() const override { return Value; } + + /// resolveListElementReference - This method is used to implement + /// VarListElementInit::resolveReferences. If the list element is resolvable + /// now, we return the resolved value, otherwise we return null. + Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const override { + llvm_unreachable("Illegal element reference off string"); + } + + Init *getBit(unsigned Bit) const override { + llvm_unreachable("Illegal bit reference off string"); + } +}; + +class CodeInit : public TypedInit { + std::string Value; + + explicit CodeInit(StringRef V) + : TypedInit(IK_CodeInit, static_cast(CodeRecTy::get())), + Value(V) {} + + CodeInit(const StringInit &Other) = delete; + CodeInit &operator=(const StringInit &Other) = delete; + +public: + static bool classof(const Init *I) { + return I->getKind() == IK_CodeInit; + } + static CodeInit *get(StringRef); + + const std::string &getValue() const { return Value; } + + Init *convertInitializerTo(RecTy *Ty) const override; + + std::string getAsString() const override { + return "[{" + Value + "}]"; + } + std::string getAsUnquotedString() const override { return Value; } /// resolveListElementReference - This method is used to implement diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp index c98c5d3f0d7f..9ee77816744b 100644 --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -82,6 +82,7 @@ template<> struct DenseMapInfo { //===----------------------------------------------------------------------===// BitRecTy BitRecTy::Shared; +CodeRecTy CodeRecTy::Shared; IntRecTy IntRecTy::Shared; StringRecTy StringRecTy::Shared; DagRecTy DagRecTy::Shared; @@ -453,6 +454,14 @@ IntInit::convertInitializerBitRange(const std::vector &Bits) const { return BitsInit::get(NewBits); } +CodeInit *CodeInit::get(StringRef V) { + static StringMap> ThePool; + + std::unique_ptr &I = ThePool[V]; + if (!I) I.reset(new CodeInit(V)); + return I.get(); +} + StringInit *StringInit::get(StringRef V) { static StringMap> ThePool; @@ -468,6 +477,13 @@ Init *StringInit::convertInitializerTo(RecTy *Ty) const { return nullptr; } +Init *CodeInit::convertInitializerTo(RecTy *Ty) const { + if (isa(Ty)) + return const_cast(this); + + return nullptr; +} + static void ProfileListInit(FoldingSetNodeID &ID, ArrayRef Range, RecTy *EltTy) { @@ -1158,6 +1174,12 @@ TypedInit::convertInitializerTo(RecTy *Ty) const { return nullptr; } + if (isa(Ty)) { + if (isa(getType())) + return const_cast(this); + return nullptr; + } + if (isa(Ty)) { // Accept variable if it is already of bit type! if (isa(getType())) @@ -1744,6 +1766,9 @@ std::string Record::getValueAsString(StringRef FieldName) const { 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 + "' does not have a string initializer!"); } diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp index 4239628498b1..34e90925e929 100644 --- a/llvm/lib/TableGen/TGParser.cpp +++ b/llvm/lib/TableGen/TGParser.cpp @@ -660,7 +660,7 @@ 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 StringRecTy::get(); + case tgtok::Code: Lex.Lex(); return CodeRecTy::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(); @@ -1164,7 +1164,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, break; } case tgtok::CodeFragment: - R = StringInit::get(Lex.getCurStrVal()); + R = CodeInit::get(Lex.getCurStrVal()); Lex.Lex(); break; case tgtok::question: diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp index 395ecc438654..fc2138f7e8ea 100644 --- a/llvm/utils/TableGen/AsmWriterEmitter.cpp +++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp @@ -1078,7 +1078,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { for (unsigned i = 0; i < MCOpPredicates.size(); ++i) { Init *MCOpPred = MCOpPredicates[i]->getValueInit("MCOperandPredicate"); - if (StringInit *SI = dyn_cast(MCOpPred)) { + if (CodeInit *SI = dyn_cast(MCOpPred)) { O << " case " << i + 1 << ": {\n" << SI->getValue() << "\n" << " }\n";