[llvm] r327117 - TableGen: add !isa operation

Nicolai Haehnle via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 9 04:24:07 PST 2018


Author: nha
Date: Fri Mar  9 04:24:06 2018
New Revision: 327117

URL: http://llvm.org/viewvc/llvm-project?rev=327117&view=rev
Log:
TableGen: add !isa operation

Change-Id: Iddb724c3ae706d82933a2d82c91d07e0e36b30e3

Differential revision: https://reviews.llvm.org/D44105

Added:
    llvm/trunk/test/TableGen/isa.td
Modified:
    llvm/trunk/docs/TableGen/LangIntro.rst
    llvm/trunk/docs/TableGen/LangRef.rst
    llvm/trunk/include/llvm/TableGen/Record.h
    llvm/trunk/lib/TableGen/Record.cpp
    llvm/trunk/lib/TableGen/TGLexer.cpp
    llvm/trunk/lib/TableGen/TGLexer.h
    llvm/trunk/lib/TableGen/TGParser.cpp

Modified: llvm/trunk/docs/TableGen/LangIntro.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/TableGen/LangIntro.rst?rev=327117&r1=327116&r2=327117&view=diff
==============================================================================
--- llvm/trunk/docs/TableGen/LangIntro.rst (original)
+++ llvm/trunk/docs/TableGen/LangIntro.rst Fri Mar  9 04:24:06 2018
@@ -208,6 +208,9 @@ supported include:
     is a special case in that the argument can be an int or a record. In the
     latter case, the record's name is returned.
 
+``!isa<type>(a)``
+    Returns an integer: 1 if 'a' is dynamically of the given type, 0 otherwise.
+
 ``!subst(a, b, c)``
     If 'a' and 'b' are of string type or are symbol references, substitute 'b'
     for 'a' in 'c.'  This operation is analogous to $(subst) in GNU make.

Modified: llvm/trunk/docs/TableGen/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/TableGen/LangRef.rst?rev=327117&r1=327116&r2=327117&view=diff
==============================================================================
--- llvm/trunk/docs/TableGen/LangRef.rst (original)
+++ llvm/trunk/docs/TableGen/LangRef.rst Fri Mar  9 04:24:06 2018
@@ -99,6 +99,7 @@ wide variety of meanings:
                :!add    !shl     !sra     !srl       !and
                :!or     !empty   !subst   !foreach   !strconcat
                :!cast   !listconcat       !size      !foldl
+               :!isa
 
 
 Syntax

Modified: llvm/trunk/include/llvm/TableGen/Record.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/TableGen/Record.h?rev=327117&r1=327116&r2=327117&view=diff
==============================================================================
--- llvm/trunk/include/llvm/TableGen/Record.h (original)
+++ llvm/trunk/include/llvm/TableGen/Record.h Fri Mar  9 04:24:06 2018
@@ -317,6 +317,7 @@ protected:
     IK_UnOpInit,
     IK_LastOpInit,
     IK_FoldOpInit,
+    IK_IsAOpInit,
     IK_StringInit,
     IK_VarInit,
     IK_VarListElementInit,
@@ -944,6 +945,39 @@ public:
 
   bool isComplete() const override { return false; }
 
+  Init *resolveReferences(Resolver &R) const override;
+
+  Init *getBit(unsigned Bit) const override;
+
+  std::string getAsString() const override;
+};
+
+/// !isa<type>(expr) - Dynamically determine the type of an expression.
+class IsAOpInit : public TypedInit, public FoldingSetNode {
+private:
+  RecTy *CheckType;
+  Init *Expr;
+
+  IsAOpInit(RecTy *CheckType, Init *Expr)
+      : TypedInit(IK_IsAOpInit, IntRecTy::get()), CheckType(CheckType),
+        Expr(Expr) {}
+
+public:
+  IsAOpInit(const IsAOpInit &) = delete;
+  IsAOpInit &operator=(const IsAOpInit &) = delete;
+
+  static bool classof(const Init *I) { return I->getKind() == IK_IsAOpInit; }
+
+  static IsAOpInit *get(RecTy *CheckType, Init *Expr);
+
+  void Profile(FoldingSetNodeID &ID) const;
+
+  // Fold - If possible, fold this to a simpler init.  Return this if not
+  // possible to fold.
+  Init *Fold() const;
+
+  bool isComplete() const override { return false; }
+
   Init *resolveReferences(Resolver &R) const override;
 
   Init *getBit(unsigned Bit) const override;

Modified: llvm/trunk/lib/TableGen/Record.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/Record.cpp?rev=327117&r1=327116&r2=327117&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/Record.cpp (original)
+++ llvm/trunk/lib/TableGen/Record.cpp Fri Mar  9 04:24:06 2018
@@ -1231,6 +1231,68 @@ std::string FoldOpInit::getAsString() co
       .str();
 }
 
+static void ProfileIsAOpInit(FoldingSetNodeID &ID, RecTy *CheckType,
+                             Init *Expr) {
+  ID.AddPointer(CheckType);
+  ID.AddPointer(Expr);
+}
+
+IsAOpInit *IsAOpInit::get(RecTy *CheckType, Init *Expr) {
+  static FoldingSet<IsAOpInit> ThePool;
+
+  FoldingSetNodeID ID;
+  ProfileIsAOpInit(ID, CheckType, Expr);
+
+  void *IP = nullptr;
+  if (IsAOpInit *I = ThePool.FindNodeOrInsertPos(ID, IP))
+    return I;
+
+  IsAOpInit *I = new (Allocator) IsAOpInit(CheckType, Expr);
+  ThePool.InsertNode(I, IP);
+  return I;
+}
+
+void IsAOpInit::Profile(FoldingSetNodeID &ID) const {
+  ProfileIsAOpInit(ID, CheckType, Expr);
+}
+
+Init *IsAOpInit::Fold() const {
+  if (TypedInit *TI = dyn_cast<TypedInit>(Expr)) {
+    // Is the expression type known to be (a subclass of) the desired type?
+    if (TI->getType()->typeIsConvertibleTo(CheckType))
+      return IntInit::get(1);
+
+    if (isa<RecordRecTy>(CheckType)) {
+      // If the target type is not a subclass of the expression type, or if
+      // the expression has fully resolved to a record, we know that it can't
+      // be of the required type.
+      if (!CheckType->typeIsConvertibleTo(TI->getType()) || isa<DefInit>(Expr))
+        return IntInit::get(0);
+    } else {
+      // We treat non-record types as not castable.
+      return IntInit::get(0);
+    }
+  }
+  return const_cast<IsAOpInit *>(this);
+}
+
+Init *IsAOpInit::resolveReferences(Resolver &R) const {
+  Init *NewExpr = Expr->resolveReferences(R);
+  if (Expr != NewExpr)
+    return get(CheckType, NewExpr)->Fold();
+  return const_cast<IsAOpInit *>(this);
+}
+
+Init *IsAOpInit::getBit(unsigned Bit) const {
+  return VarBitInit::get(const_cast<IsAOpInit *>(this), Bit);
+}
+
+std::string IsAOpInit::getAsString() const {
+  return (Twine("!isa<") + CheckType->getAsString() + ">(" +
+          Expr->getAsString() + ")")
+      .str();
+}
+
 RecTy *TypedInit::getFieldType(StringInit *FieldName) const {
   if (RecordRecTy *RecordType = dyn_cast<RecordRecTy>(getType())) {
     for (Record *Rec : RecordType->getClasses()) {

Modified: llvm/trunk/lib/TableGen/TGLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGLexer.cpp?rev=327117&r1=327116&r2=327117&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGLexer.cpp (original)
+++ llvm/trunk/lib/TableGen/TGLexer.cpp Fri Mar  9 04:24:06 2018
@@ -467,6 +467,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
     StringSwitch<tgtok::TokKind>(StringRef(Start, CurPtr - Start))
     .Case("eq", tgtok::XEq)
     .Case("if", tgtok::XIf)
+    .Case("isa", tgtok::XIsA)
     .Case("head", tgtok::XHead)
     .Case("tail", tgtok::XTail)
     .Case("size", tgtok::XSize)

Modified: llvm/trunk/lib/TableGen/TGLexer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGLexer.h?rev=327117&r1=327116&r2=327117&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGLexer.h (original)
+++ llvm/trunk/lib/TableGen/TGLexer.h Fri Mar  9 04:24:06 2018
@@ -48,7 +48,7 @@ namespace tgtok {
 
     // !keywords.
     XConcat, XADD, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XStrConcat, XCast,
-    XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XEq,
+    XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XEq, XIsA,
 
     // Integer value.
     IntVal,

Modified: llvm/trunk/lib/TableGen/TGParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGParser.cpp?rev=327117&r1=327116&r2=327117&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGParser.cpp (original)
+++ llvm/trunk/lib/TableGen/TGParser.cpp Fri Mar  9 04:24:06 2018
@@ -936,6 +936,33 @@ Init *TGParser::ParseOperation(Record *C
     return (UnOpInit::get(Code, LHS, Type))->Fold(CurRec, CurMultiClass);
   }
 
+  case tgtok::XIsA: {
+    // Value ::= !isa '<' Type '>' '(' Value ')'
+    Lex.Lex(); // eat the operation
+
+    RecTy *Type = ParseOperatorType();
+    if (!Type)
+      return nullptr;
+
+    if (Lex.getCode() != tgtok::l_paren) {
+      TokError("expected '(' after type of !isa");
+      return nullptr;
+    }
+    Lex.Lex(); // eat the '('
+
+    Init *LHS = ParseValue(CurRec);
+    if (!LHS)
+      return nullptr;
+
+    if (Lex.getCode() != tgtok::r_paren) {
+      TokError("expected ')' in !isa");
+      return nullptr;
+    }
+    Lex.Lex(); // eat the ')'
+
+    return (IsAOpInit::get(Type, LHS))->Fold();
+  }
+
   case tgtok::XConcat:
   case tgtok::XADD:
   case tgtok::XAND:
@@ -1696,6 +1723,7 @@ Init *TGParser::ParseSimpleValue(Record
   case tgtok::XSize:
   case tgtok::XEmpty:
   case tgtok::XCast:  // Value ::= !unop '(' Value ')'
+  case tgtok::XIsA:
   case tgtok::XConcat:
   case tgtok::XADD:
   case tgtok::XAND:

Added: llvm/trunk/test/TableGen/isa.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/isa.td?rev=327117&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/isa.td (added)
+++ llvm/trunk/test/TableGen/isa.td Fri Mar  9 04:24:06 2018
@@ -0,0 +1,39 @@
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+
+// CHECK: --- Defs ---
+
+// CHECK: def X0 {
+// CHECK:   int ret = 0;
+// CHECK: }
+
+// CHECK: def X1 {
+// CHECK:   int ret = 1;
+// CHECK: }
+
+// CHECK: def Y0 {
+// CHECK:   int ret = 0;
+// CHECK: }
+
+// CHECK: def Y1 {
+// CHECK:   int ret = 11;
+// CHECK: }
+
+class A<int dummy>;
+class B<int num> : A<num> {
+  int Num = num;
+}
+
+class X<A a> {
+  int ret = !isa<B>(a);
+}
+
+class Y<A a> {
+  int ret = !if(!isa<B>(a), !cast<B>(a).Num, 0);
+}
+
+def X0 : X<A<0>>;
+def X1 : X<B<0>>;
+
+def Y0 : Y<A<10>>;
+def Y1 : Y<B<11>>;




More information about the llvm-commits mailing list