From 711e5d96aa648ebe96b09483d0775f3b16283e3d Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 31 Mar 2006 21:53:49 +0000 Subject: [PATCH] Generalize the previous binary operator support and add a string concatenation 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 | 1 + utils/TableGen/FileParser.y | 22 +++------- utils/TableGen/Record.cpp | 84 ++++++++++++++++++++++++++++++------- utils/TableGen/Record.h | 40 ++++++++++++++---- 4 files changed, 109 insertions(+), 38 deletions(-) diff --git a/utils/TableGen/FileLexer.l b/utils/TableGen/FileLexer.l index 020a356b0b4..3b60099bc10 100644 --- a/utils/TableGen/FileLexer.l +++ b/utils/TableGen/FileLexer.l @@ -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); diff --git a/utils/TableGen/FileParser.y b/utils/TableGen/FileParser.y index 11fda1ded09..aa8613952f6 100644 --- a/utils/TableGen/FileParser.y +++ b/utils/TableGen/FileParser.y @@ -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 %token 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 */ { diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index 251b7a9d921..254ec784234 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -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(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(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 &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(LHS); + StringInit *RHSs = dynamic_cast(RHS); + if (LHSs && RHSs) + return new StringInit(LHSs->getValue() + RHSs->getValue()); + break; + } + case SHL: + case SRA: + case SRL: { + IntInit *LHSi = dynamic_cast(LHS); + IntInit *RHSi = dynamic_cast(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 &Bits) { BitsRecTy *T = dynamic_cast(getType()); if (T == 0) return 0; // Cannot subscript a non-bits variable... diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index 26a97013d72..f8a3c35b980 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -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 &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. -- 2.34.1