Generalize the previous binary operator support and add a string concatenation
authorChris Lattner <sabre@nondot.org>
Fri, 31 Mar 2006 21:53:49 +0000 (21:53 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 31 Mar 2006 21:53:49 +0000 (21:53 +0000)
operation.  This implements Regression/TableGen/strconcat.td.

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

utils/TableGen/FileLexer.l
utils/TableGen/FileParser.y
utils/TableGen/Record.cpp
utils/TableGen/Record.h

index 020a356b0b42d9365664dac2b11d0d5fc21a7143..3b60099bc103233fb16d77c66a652138a31c9f1d 100644 (file)
@@ -202,6 +202,7 @@ in             { return IN; }
 !sra           { return SRATOK; }
 !srl           { return SRLTOK; }
 !shl           { return SHLTOK; }
+!strconcat     { return STRCONCATTOK; }
 
 
 {Identifier}   { Filelval.StrVal = new std::string(yytext, yytext+yyleng);
index 11fda1ded09038737fb8a9385307631370afa8ab..aa8613952f65dbb190eb2e0383fa7499d18bcc16 100644 (file)
@@ -200,7 +200,7 @@ using namespace llvm;
 };
 
 %token INT BIT STRING BITS LIST CODE DAG CLASS DEF FIELD LET IN
-%token SHLTOK SRATOK SRLTOK
+%token SHLTOK SRATOK SRLTOK STRCONCATTOK
 %token <IntVal>      INTVAL
 %token <StrVal>      ID VARNAME STRVAL CODEFRAGMENT
 
@@ -352,23 +352,13 @@ Value : IDValue {
     }
     delete $3;
   } | SHLTOK '(' Value ',' Value ')' {
-    $$ = $3->getBinaryOp(Init::SHL, $5);
-    if ($$ == 0) {
-      err() << "Cannot shift values '" << *$3 << "' and '" << *$5 << "'!\n";
-      exit(1);
-    }
+    $$ = (new BinOpInit(BinOpInit::SHL, $3, $5))->Fold();
   } | SRATOK '(' Value ',' Value ')' {
-    $$ = $3->getBinaryOp(Init::SRA, $5);
-    if ($$ == 0) {
-      err() << "Cannot shift values '" << *$3 << "' and '" << *$5 << "'!\n";
-      exit(1);
-    }
+    $$ = (new BinOpInit(BinOpInit::SRA, $3, $5))->Fold();
   } | SRLTOK '(' Value ',' Value ')' {
-    $$ = $3->getBinaryOp(Init::SRL, $5);
-    if ($$ == 0) {
-      err() << "Cannot shift values '" << *$3 << "' and '" << *$5 << "'!\n";
-      exit(1);
-    }
+    $$ = (new BinOpInit(BinOpInit::SRL, $3, $5))->Fold();
+  } | STRCONCATTOK '(' Value ',' Value ')' {
+    $$ = (new BinOpInit(BinOpInit::STRCONCAT, $3, $5))->Fold();
   };
 
 OptVarName : /* empty */ {
index 251b7a9d921f8801679a4d3ebd1402b2e49bc7b6..254ec7842341dc63f1edf5047712f568a34b51e7 100644 (file)
@@ -7,6 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
+// Implement the tablegen record classes.
 //
 //===----------------------------------------------------------------------===//
 
@@ -125,6 +126,19 @@ Init *IntRecTy::convertValue(TypedInit *TI) {
   return 0;
 }
 
+Init *StringRecTy::convertValue(BinOpInit *BO) {
+  if (BO->getOpcode() == BinOpInit::STRCONCAT) {
+    Init *L = BO->getLHS()->convertInitializerTo(this);
+    Init *R = BO->getRHS()->convertInitializerTo(this);
+    if (L == 0 || R == 0) return 0;
+    if (L != BO->getLHS() || R != BO->getRHS())
+      return new BinOpInit(BinOpInit::STRCONCAT, L, R);
+    return BO;
+  }
+  return 0;
+}
+
+
 Init *StringRecTy::convertValue(TypedInit *TI) {
   if (dynamic_cast<StringRecTy*>(TI->getType()))
     return TI;  // Accept variable if already of the right type!
@@ -299,21 +313,6 @@ Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) {
   return this;
 }
 
-Init *IntInit::getBinaryOp(BinaryOp Op, Init *RHS) {
-  IntInit *RHSi = dynamic_cast<IntInit*>(RHS);
-  if (RHSi == 0) return 0;
-
-  int NewValue;
-  switch (Op) {
-  default: assert(0 && "Unknown binop");
-  case SHL: NewValue = Value << RHSi->getValue(); break;
-  case SRA: NewValue = Value >> RHSi->getValue(); break;
-  case SRL: NewValue = (unsigned)Value >> (unsigned)RHSi->getValue(); break;
-  }
-  return new IntInit(NewValue);
-}
-
-
 Init *IntInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
   BitsInit *BI = new BitsInit(Bits.size());
 
@@ -368,6 +367,61 @@ void ListInit::print(std::ostream &OS) const {
   OS << "]";
 }
 
+Init *BinOpInit::Fold() {
+  switch (getOpcode()) {
+  default: assert(0 && "Unknown binop");
+  case STRCONCAT: {
+    StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+    StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
+    if (LHSs && RHSs)
+      return new StringInit(LHSs->getValue() + RHSs->getValue());
+    break;
+  }
+  case SHL:
+  case SRA:
+  case SRL: {
+    IntInit *LHSi = dynamic_cast<IntInit*>(LHS);
+    IntInit *RHSi = dynamic_cast<IntInit*>(RHS);
+    if (LHSi && RHSi) {
+      int LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
+      int Result;
+      switch (getOpcode()) {
+      default: assert(0 && "Bad opcode!");
+      case SHL: Result = LHSv << RHSv; break;
+      case SRA: Result = LHSv >> RHSv; break;
+      case SRL: Result = (unsigned)LHSv >> (unsigned)RHSv; break;
+      }
+      return new IntInit(Result);
+    }
+    break;
+  }
+  }
+  return this;
+}
+
+Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) {
+  Init *lhs = LHS->resolveReferences(R, RV);
+  Init *rhs = RHS->resolveReferences(R, RV);
+  
+  if (LHS != lhs || RHS != rhs)
+    return (new BinOpInit(getOpcode(), lhs, rhs))->Fold();
+  return Fold();
+}
+
+void BinOpInit::print(std::ostream &OS) const {
+  switch (Opc) {
+  case SHL: OS << "!shl"; break;
+  case SRA: OS << "!sra"; break;
+  case SRL: OS << "!srl"; break;
+  case STRCONCAT: OS << "!strconcat"; break;
+  }
+  OS << "(";
+  LHS->print(OS);
+  OS << ", ";
+  RHS->print(OS);
+  OS << ")";
+}
+
 Init *TypedInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
   BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType());
   if (T == 0) return 0;  // Cannot subscript a non-bits variable...
index 26a97013d7266a1e0d975477c8cb2d92626918df..f8a3c35b98029637192abab872c5ab43d9a0c457 100644 (file)
@@ -42,6 +42,7 @@ class IntInit;
 class StringInit;
 class CodeInit;
 class ListInit;
+class BinOpInit;
 class DefInit;
 class DagInit;
 class TypedInit;
@@ -75,6 +76,7 @@ public:   // These methods should only be called from subclasses of Init
   virtual Init *convertValue(   IntInit *II) { return 0; }
   virtual Init *convertValue(StringInit *SI) { return 0; }
   virtual Init *convertValue(  ListInit *LI) { return 0; }
+  virtual Init *convertValue( BinOpInit *UI) { return 0; }
   virtual Init *convertValue(  CodeInit *CI) { return 0; }
   virtual Init *convertValue(VarBitInit *VB) { return 0; }
   virtual Init *convertValue(   DefInit *DI) { return 0; }
@@ -231,6 +233,7 @@ public:
   virtual Init *convertValue(   IntInit *II) { return 0; }
   virtual Init *convertValue(StringInit *SI) { return (Init*)SI; }
   virtual Init *convertValue(  ListInit *LI) { return 0; }
+  virtual Init *convertValue( BinOpInit *BO);
   virtual Init *convertValue(  CodeInit *CI) { return 0; }
   virtual Init *convertValue(VarBitInit *VB) { return 0; }
   virtual Init *convertValue(   DefInit *DI) { return 0; }
@@ -465,11 +468,6 @@ struct Init {
     return 0;
   }
 
-  enum BinaryOp { SHL, SRA, SRL };
-  virtual Init *getBinaryOp(BinaryOp Op, Init *RHS) {
-    return 0;
-  }
-
   /// resolveReferences - This method is used by classes that refer to other
   /// variables which may not be defined at the time they expression is formed.
   /// If a value is set for the variable later, this method will be called on
@@ -570,8 +568,6 @@ public:
   }
   virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
 
-  virtual Init *getBinaryOp(BinaryOp Op, Init *RHS);
-
   virtual void print(std::ostream &OS) const { OS << Value; }
 };
 
@@ -639,6 +635,36 @@ public:
   virtual void print(std::ostream &OS) const;
 };
 
+/// BinOpInit - !op (X, Y) - Combine two inits.
+///
+class BinOpInit : public Init {
+public:
+  enum BinaryOp { SHL, SRA, SRL, STRCONCAT };
+private:
+  BinaryOp Opc;
+  Init *LHS, *RHS;
+public:
+  BinOpInit(BinaryOp opc, Init *lhs, Init *rhs) : Opc(opc), LHS(lhs), RHS(rhs) {
+  }
+  
+  BinaryOp getOpcode() const { return Opc; }
+  Init *getLHS() const { return LHS; }
+  Init *getRHS() const { return RHS; }
+
+  // Fold - If possible, fold this to a simpler init.  Return this if not
+  // possible to fold.
+  Init *Fold();
+
+  virtual Init *convertInitializerTo(RecTy *Ty) {
+    return Ty->convertValue(this);
+  }
+  
+  virtual Init *resolveReferences(Record &R, const RecordVal *RV);
+  
+  virtual void print(std::ostream &OS) const;
+};
+
+
 
 /// TypedInit - This is the common super-class of types that have a specific,
 /// explicit, type.