]> granicus.if.org Git - llvm/commitdiff
TableGen: promote "code" type from syntactic sugar.
authorTim Northover <tnorthover@apple.com>
Tue, 5 Jul 2016 21:22:55 +0000 (21:22 +0000)
committerTim Northover <tnorthover@apple.com>
Tue, 5 Jul 2016 21:22:55 +0000 (21:22 +0000)
It's being immediately converted to a "string", but being able to tell what
type the field was originally can be useful in backends.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@274575 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/TableGen/Record.h
lib/TableGen/Record.cpp
lib/TableGen/TGParser.cpp
utils/TableGen/AsmWriterEmitter.cpp

index 43b1af086d24a170e8fa11d1c3c774a5c6c45959..019e217718dbc48b0fd23f1be5179a811443954d 100644 (file)
@@ -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<RecTy *>(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
index c98c5d3f0d7fd8ee80e358b16a7bac1ab4c42d5d..9ee77816744b964136eb3e223f59367af19562f5 100644 (file)
@@ -82,6 +82,7 @@ template<> struct DenseMapInfo<TableGenStringKey> {
 //===----------------------------------------------------------------------===//
 
 BitRecTy BitRecTy::Shared;
+CodeRecTy CodeRecTy::Shared;
 IntRecTy IntRecTy::Shared;
 StringRecTy StringRecTy::Shared;
 DagRecTy DagRecTy::Shared;
@@ -453,6 +454,14 @@ IntInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) const {
   return BitsInit::get(NewBits);
 }
 
+CodeInit *CodeInit::get(StringRef V) {
+  static StringMap<std::unique_ptr<CodeInit>> ThePool;
+
+  std::unique_ptr<CodeInit> &I = ThePool[V];
+  if (!I) I.reset(new CodeInit(V));
+  return I.get();
+}
+
 StringInit *StringInit::get(StringRef V) {
   static StringMap<std::unique_ptr<StringInit>> ThePool;
 
@@ -468,6 +477,13 @@ Init *StringInit::convertInitializerTo(RecTy *Ty) const {
   return nullptr;
 }
 
+Init *CodeInit::convertInitializerTo(RecTy *Ty) const {
+  if (isa<CodeRecTy>(Ty))
+    return const_cast<CodeInit *>(this);
+
+  return nullptr;
+}
+
 static void ProfileListInit(FoldingSetNodeID &ID,
                             ArrayRef<Init *> Range,
                             RecTy *EltTy) {
@@ -1158,6 +1174,12 @@ TypedInit::convertInitializerTo(RecTy *Ty) const {
     return nullptr;
   }
 
+  if (isa<CodeRecTy>(Ty)) {
+    if (isa<CodeRecTy>(getType()))
+      return const_cast<TypedInit *>(this);
+    return nullptr;
+  }
+
   if (isa<BitRecTy>(Ty)) {
     // Accept variable if it is already of bit type!
     if (isa<BitRecTy>(getType()))
@@ -1744,6 +1766,9 @@ std::string Record::getValueAsString(StringRef FieldName) const {
 
   if (StringInit *SI = dyn_cast<StringInit>(R->getValue()))
     return SI->getValue();
+  if (CodeInit *CI = dyn_cast<CodeInit>(R->getValue()))
+    return CI->getValue();
+
   PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
     FieldName + "' does not have a string initializer!");
 }
index 4239628498b10f258b8a6abe8d9dce1c14f507fa..34e90925e929dd6ae4e71b43ce080c53a50bcc9c 100644 (file)
@@ -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:
index 395ecc4386541a3dffb2df65cd21e6c771748e82..fc2138f7e8ea36a6106f533fcb72988df7f976bf 100644 (file)
@@ -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<StringInit>(MCOpPred)) {
+      if (CodeInit *SI = dyn_cast<CodeInit>(MCOpPred)) {
         O << "  case " << i + 1 << ": {\n"
           << SI->getValue() << "\n"
           << "    }\n";