From a9c6c5d39bd577a25801c39ca38b38ea4f68ce45 Mon Sep 17 00:00:00 2001 From: David Greene Date: Wed, 22 Apr 2009 20:18:10 +0000 Subject: [PATCH] Implement !nameconcat to concatenate strings and look up the resulting name in the symbol table, returning an object. llvm-svn: 69822 --- llvm/docs/TableGenFundamentals.html | 10 ++- llvm/test/TableGen/nameconcat.td | 76 ++++++++++++++++++++++ llvm/utils/TableGen/CodeGenInstruction.cpp | 2 +- llvm/utils/TableGen/Record.cpp | 44 ++++++++++++- llvm/utils/TableGen/Record.h | 13 +++- llvm/utils/TableGen/TGLexer.cpp | 11 ++-- llvm/utils/TableGen/TGLexer.h | 4 +- llvm/utils/TableGen/TGParser.cpp | 68 +++++++++++++------ 8 files changed, 192 insertions(+), 36 deletions(-) create mode 100644 llvm/test/TableGen/nameconcat.td diff --git a/llvm/docs/TableGenFundamentals.html b/llvm/docs/TableGenFundamentals.html index e9915cb0294b..42839176cbf0 100644 --- a/llvm/docs/TableGenFundamentals.html +++ b/llvm/docs/TableGenFundamentals.html @@ -398,6 +398,11 @@ supported include:

!strconcat(a, b)
A string value that is the result of concatenating the 'a' and 'b' strings.
+
!nameconcat(a, b)
+
A value that is the result of concatenating the 'a' and 'b' + strings and looking up the resulting name in the symbol table. The symbol type + determines the type of the resulting value. If the symbol is not found, + TableGen emits an error and aborts.

Note that all of the values have rules specifying how they convert to values @@ -627,8 +632,9 @@ Here is an example TableGen fragment that shows this idea:

The name of the resultant definitions has the multidef fragment names appended to them, so this defines ADD_rr, ADD_ri, - SUB_rr, etc. Using a multiclass this way is exactly equivalent to - instantiating the classes multiple times yourself, e.g. by writing:

+ SUB_rr, etc. Using a multiclass this way is exactly + equivalent to instantiating the classes multiple times yourself, + e.g. by writing:

diff --git a/llvm/test/TableGen/nameconcat.td b/llvm/test/TableGen/nameconcat.td
new file mode 100644
index 000000000000..8dbc4b87d9e6
--- /dev/null
+++ b/llvm/test/TableGen/nameconcat.td
@@ -0,0 +1,76 @@
+// RUN: tblgen %s | grep {add_ps} | count 2
+
+class ValueType {
+  int Size = size;
+  int Value = value;
+}
+
+def v2i64  : ValueType<128, 22>;   //  2 x i64 vector value
+def v2f64  : ValueType<128, 28>;   //  2 x f64 vector value
+
+class Intrinsic {
+  string Name = name;
+}
+
+class Inst opcode, dag oopnds, dag iopnds, string asmstr, 
+           list pattern> {
+  bits<8> Opcode = opcode;
+  dag OutOperands = oopnds;
+  dag InOperands = iopnds;
+  string AssemblyString = asmstr;
+  list Pattern = pattern;
+}
+
+def ops;
+def outs;
+def ins;
+
+def set;
+
+// Define registers
+class Register {
+  string Name = n;
+}
+
+class RegisterClass regTypes, list regList> {
+  list RegTypes = regTypes;
+  list MemberList = regList;
+}
+
+def XMM0: Register<"xmm0">;
+def XMM1: Register<"xmm1">;
+def XMM2: Register<"xmm2">;
+def XMM3: Register<"xmm3">;
+def XMM4: Register<"xmm4">;
+def XMM5: Register<"xmm5">;
+def XMM6: Register<"xmm6">;
+def XMM7: Register<"xmm7">;
+def XMM8:  Register<"xmm8">;
+def XMM9:  Register<"xmm9">;
+def XMM10: Register<"xmm10">;
+def XMM11: Register<"xmm11">;
+def XMM12: Register<"xmm12">;
+def XMM13: Register<"xmm13">;
+def XMM14: Register<"xmm14">;
+def XMM15: Register<"xmm15">;
+
+def VR128 : RegisterClass<[v2i64, v2f64],
+                          [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
+                           XMM8, XMM9, XMM10, XMM11,
+                           XMM12, XMM13, XMM14, XMM15]>;
+
+// Define intrinsics
+def int_x86_sse2_add_ps : Intrinsic<"addps">;
+def int_x86_sse2_add_pd : Intrinsic<"addpd">;
+
+multiclass arith opcode, string asmstr, string Intr> {
+  def PS : Inst;
+
+  def PD : Inst;
+}
+
+defm ADD : arith<0x58, "add", "int_x86_sse2_add">;
diff --git a/llvm/utils/TableGen/CodeGenInstruction.cpp b/llvm/utils/TableGen/CodeGenInstruction.cpp
index 185db01418b0..b505871dee29 100644
--- a/llvm/utils/TableGen/CodeGenInstruction.cpp
+++ b/llvm/utils/TableGen/CodeGenInstruction.cpp
@@ -127,7 +127,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
     OperandList.clear();
     return;
   }
-  DI = (DagInit*)(new BinOpInit(BinOpInit::CONCAT, DI, IDI))->Fold();
+  DI = (DagInit*)(new BinOpInit(BinOpInit::CONCAT, DI, IDI))->Fold(R, 0);
 
   unsigned MIOperandNo = 0;
   std::set OperandNames;
diff --git a/llvm/utils/TableGen/Record.cpp b/llvm/utils/TableGen/Record.cpp
index e2d9657c4d24..b24421999559 100644
--- a/llvm/utils/TableGen/Record.cpp
+++ b/llvm/utils/TableGen/Record.cpp
@@ -395,7 +395,7 @@ std::string ListInit::getAsString() const {
   return Result + "]";
 }
 
-Init *BinOpInit::Fold() {
+Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
   switch (getOpcode()) {
   default: assert(0 && "Unknown binop");
   case CONCAT: {
@@ -437,6 +437,43 @@ Init *BinOpInit::Fold() {
       return new StringInit(LHSs->getValue() + RHSs->getValue());
     break;
   }
+  case NAMECONCAT: {
+    StringInit *LHSs = dynamic_cast(LHS);
+    StringInit *RHSs = dynamic_cast(RHS);
+    if (LHSs && RHSs) {
+      std::string Name(LHSs->getValue() + RHSs->getValue());
+
+      // From TGParser::ParseIDValue
+      if (CurRec) {
+        if (const RecordVal *RV = CurRec->getValue(Name))
+          return new VarInit(Name, RV->getType());
+
+        std::string TemplateArgName = CurRec->getName()+":"+Name;
+        if (CurRec->isTemplateArg(TemplateArgName)) {
+          const RecordVal *RV = CurRec->getValue(TemplateArgName);
+          assert(RV && "Template arg doesn't exist??");
+          return new VarInit(TemplateArgName, RV->getType());
+        }
+      }
+
+      if (CurMultiClass) {
+        std::string MCName = CurMultiClass->Rec.getName()+"::"+Name;
+        if (CurMultiClass->Rec.isTemplateArg(MCName)) {
+          const RecordVal *RV = CurMultiClass->Rec.getValue(MCName);
+          assert(RV && "Template arg doesn't exist??");
+          return new VarInit(MCName, RV->getType());
+        }
+      }
+
+      if (Record *D = Records.getDef(Name))
+        return new DefInit(D);
+
+      cerr << "Variable not defined: '" + Name + "'\n";
+      assert(0 && "Variable not found");
+      return 0;
+    }
+    break;
+  }
   case SHL:
   case SRA:
   case SRL: {
@@ -464,8 +501,8 @@ Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) {
   Init *rhs = RHS->resolveReferences(R, RV);
   
   if (LHS != lhs || RHS != rhs)
-    return (new BinOpInit(getOpcode(), lhs, rhs))->Fold();
-  return Fold();
+    return (new BinOpInit(getOpcode(), lhs, rhs))->Fold(&R, 0);
+  return Fold(&R, 0);
 }
 
 std::string BinOpInit::getAsString() const {
@@ -476,6 +513,7 @@ std::string BinOpInit::getAsString() const {
   case SRA: Result = "!sra"; break;
   case SRL: Result = "!srl"; break;
   case STRCONCAT: Result = "!strconcat"; break;
+  case NAMECONCAT: Result = "!nameconcat"; break;
   }
   return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")";
 }
diff --git a/llvm/utils/TableGen/Record.h b/llvm/utils/TableGen/Record.h
index 32172ef12ae6..b408452f3d1a 100644
--- a/llvm/utils/TableGen/Record.h
+++ b/llvm/utils/TableGen/Record.h
@@ -53,6 +53,7 @@ class VarListElementInit;
 // Other classes.
 class Record;
 class RecordVal;
+class MultiClass;
 
 //===----------------------------------------------------------------------===//
 //  Type Classes
@@ -659,7 +660,7 @@ public:
 ///
 class BinOpInit : public Init {
 public:
-  enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT };
+  enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, NAMECONCAT };
 private:
   BinaryOp Opc;
   Init *LHS, *RHS;
@@ -673,7 +674,7 @@ public:
 
   // Fold - If possible, fold this to a simpler init.  Return this if not
   // possible to fold.
-  Init *Fold();
+  Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
 
   virtual Init *convertInitializerTo(RecTy *Ty) {
     return Ty->convertValue(this);
@@ -1124,6 +1125,14 @@ public:
 
 std::ostream &operator<<(std::ostream &OS, const Record &R);
 
+struct MultiClass {
+  Record Rec;  // Placeholder for template args and Name.
+  typedef std::vector RecordVector;
+  RecordVector DefPrototypes;
+    
+  MultiClass(const std::string &Name, TGLoc Loc) : Rec(Name, Loc) {}
+};
+
 class RecordKeeper {
   std::map Classes, Defs;
 public:
diff --git a/llvm/utils/TableGen/TGLexer.cpp b/llvm/utils/TableGen/TGLexer.cpp
index 79982aa05f52..f2ea7a151715 100644
--- a/llvm/utils/TableGen/TGLexer.cpp
+++ b/llvm/utils/TableGen/TGLexer.cpp
@@ -429,11 +429,12 @@ tgtok::TokKind TGLexer::LexExclaim() {
   // Check to see which operator this is.
   unsigned Len = CurPtr-Start;
   
-  if (Len == 3 && !memcmp(Start, "con", 3)) return tgtok::XConcat;
-  if (Len == 3 && !memcmp(Start, "sra", 3)) return tgtok::XSRA;
-  if (Len == 3 && !memcmp(Start, "srl", 3)) return tgtok::XSRL;
-  if (Len == 3 && !memcmp(Start, "shl", 3)) return tgtok::XSHL;
-  if (Len == 9 && !memcmp(Start, "strconcat", 9)) return tgtok::XStrConcat;
+  if (Len == 3  && !memcmp(Start, "con", 3)) return tgtok::XConcat;
+  if (Len == 3  && !memcmp(Start, "sra", 3)) return tgtok::XSRA;
+  if (Len == 3  && !memcmp(Start, "srl", 3)) return tgtok::XSRL;
+  if (Len == 3  && !memcmp(Start, "shl", 3)) return tgtok::XSHL;
+  if (Len == 9  && !memcmp(Start, "strconcat", 9))   return tgtok::XStrConcat;
+  if (Len == 10 && !memcmp(Start, "nameconcat", 10)) return tgtok::XNameConcat;
   
   return ReturnError(Start-1, "Unknown operator");
 }
diff --git a/llvm/utils/TableGen/TGLexer.h b/llvm/utils/TableGen/TGLexer.h
index 245dd4146158..734dc2651e33 100644
--- a/llvm/utils/TableGen/TGLexer.h
+++ b/llvm/utils/TableGen/TGLexer.h
@@ -45,8 +45,8 @@ namespace tgtok {
     MultiClass, String,
     
     // !keywords.
-    XConcat, XSRA, XSRL, XSHL, XStrConcat,
-    
+    XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat,
+
     // Integer value.
     IntVal,
     
diff --git a/llvm/utils/TableGen/TGParser.cpp b/llvm/utils/TableGen/TGParser.cpp
index ddaf55803fdf..45ad5792f98a 100644
--- a/llvm/utils/TableGen/TGParser.cpp
+++ b/llvm/utils/TableGen/TGParser.cpp
@@ -23,14 +23,6 @@ using namespace llvm;
 //===----------------------------------------------------------------------===//
 
 namespace llvm {
-struct MultiClass {
-  Record Rec;  // Placeholder for template args and Name.
-  typedef std::vector RecordVector;
-  RecordVector DefPrototypes;
-    
-  MultiClass(const std::string &Name, TGLoc Loc) : Rec(Name, Loc) {}
-};
-  
 struct SubClassReference {
   TGLoc RefLoc;
   Record *Rec;
@@ -777,14 +769,47 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) {
   }
   case tgtok::l_paren: {         // Value ::= '(' IDValue DagArgList ')'
     Lex.Lex();   // eat the '('
-    if (Lex.getCode() != tgtok::Id) {
+    if (Lex.getCode() != tgtok::Id
+        && Lex.getCode() != tgtok::XNameConcat) {
       TokError("expected identifier in dag init");
       return 0;
     }
     
-    Init *Operator = ParseIDValue(CurRec);
-    if (Operator == 0) return 0;
-    
+    Init *Operator = 0;
+    if (Lex.getCode() == tgtok::Id) {
+      Operator = ParseIDValue(CurRec);
+      if (Operator == 0) return 0;
+    }
+    else {
+      BinOpInit::BinaryOp Code = BinOpInit::NAMECONCAT;
+ 
+      Lex.Lex();  // eat the operation
+      if (Lex.getCode() != tgtok::l_paren) {
+        TokError("expected '(' after binary operator");
+        return 0;
+      }
+      Lex.Lex();  // eat the '('
+
+      Init *LHS = ParseValue(CurRec);
+      if (LHS == 0) return 0;
+
+      if (Lex.getCode() != tgtok::comma) {
+        TokError("expected ',' in binary operator");
+        return 0;
+      }
+      Lex.Lex();  // eat the ','
+
+      Init *RHS = ParseValue(CurRec);
+       if (RHS == 0) return 0;
+
+       if (Lex.getCode() != tgtok::r_paren) {
+         TokError("expected ')' in binary operator");
+         return 0;
+       }
+       Lex.Lex();  // eat the ')'
+       Operator = (new BinOpInit(Code, LHS, RHS))->Fold(CurRec, CurMultiClass);
+    }
+
     // If the operator name is present, parse it.
     std::string OperatorName;
     if (Lex.getCode() == tgtok::colon) {
@@ -796,7 +821,6 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) {
       Lex.Lex();  // eat the VarName.
     }
     
-    
     std::vector > DagArgs;
     if (Lex.getCode() != tgtok::r_paren) {
       DagArgs = ParseDagArgList(CurRec);
@@ -815,15 +839,17 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) {
   case tgtok::XSRA: 
   case tgtok::XSRL:
   case tgtok::XSHL:
-  case tgtok::XStrConcat: {  // Value ::= !binop '(' Value ',' Value ')'
+  case tgtok::XStrConcat:
+  case tgtok::XNameConcat: {  // Value ::= !binop '(' Value ',' Value ')'
     BinOpInit::BinaryOp Code;
     switch (Lex.getCode()) {
     default: assert(0 && "Unhandled code!");
-    case tgtok::XConcat:    Code = BinOpInit::CONCAT; break;
-    case tgtok::XSRA:       Code = BinOpInit::SRA; break;
-    case tgtok::XSRL:       Code = BinOpInit::SRL; break;
-    case tgtok::XSHL:       Code = BinOpInit::SHL; break;
-    case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break;
+    case tgtok::XConcat:     Code = BinOpInit::CONCAT; break;
+    case tgtok::XSRA:        Code = BinOpInit::SRA; break;
+    case tgtok::XSRL:        Code = BinOpInit::SRL; break;
+    case tgtok::XSHL:        Code = BinOpInit::SHL; break;
+    case tgtok::XStrConcat:  Code = BinOpInit::STRCONCAT; break;
+    case tgtok::XNameConcat: Code = BinOpInit::NAMECONCAT; break;
     }
     Lex.Lex();  // eat the operation
     if (Lex.getCode() != tgtok::l_paren) {
@@ -831,7 +857,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) {
       return 0;
     }
     Lex.Lex();  // eat the '('
-    
+
     Init *LHS = ParseValue(CurRec);
     if (LHS == 0) return 0;
 
@@ -849,7 +875,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) {
       return 0;
     }
     Lex.Lex();  // eat the ')'
-    return (new BinOpInit(Code, LHS, RHS))->Fold();
+    return (new BinOpInit(Code, LHS, RHS))->Fold(CurRec, CurMultiClass);
   }
   }