From b0fef64dc98d32b90782360aa9480417b7ca34fd Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 26 Jul 2004 23:21:34 +0000 Subject: [PATCH] Add initial support for list slices. This currently allows you to do stuff like this: def B { list X = [10, 20, 30, 4, 1, 1231, 20] [2-4,2,2,0-6]; } ... which isn't particularly useful, but more is to come. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15247 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/FileParser.y | 60 +++++++++++++++++++++++++++---------- utils/TableGen/Record.cpp | 10 +++++++ utils/TableGen/Record.h | 11 +++++++ 3 files changed, 65 insertions(+), 16 deletions(-) diff --git a/utils/TableGen/FileParser.y b/utils/TableGen/FileParser.y index 4731674e521..bf10abc8be7 100644 --- a/utils/TableGen/FileParser.y +++ b/utils/TableGen/FileParser.y @@ -300,6 +300,14 @@ Value : INTVAL { } $$ = new DagInit(D, *$3); delete $2; delete $3; + } | Value '[' BitList ']' { + std::reverse($3->begin(), $3->end()); + $$ = $1->convertInitListSlice(*$3); + if ($$ == 0) { + err() << "Invalid list slice for value '" << *$1 << "'!\n"; + exit(1); + } + delete $3; }; OptVarName : /* empty */ { @@ -330,41 +338,61 @@ RBitList : INTVAL { $$ = new std::vector(); $$->push_back($1); } | INTVAL '-' INTVAL { - if ($1 < $3 || $1 < 0 || $3 < 0) { - err() << "Invalid bit range: " << $1 << "-" << $3 << "!\n"; + if ($1 < 0 || $3 < 0) { + err() << "Invalid range: " << $1 << "-" << $3 << "!\n"; exit(1); } $$ = new std::vector(); - for (int i = $1; i >= $3; --i) - $$->push_back(i); + if ($1 < $3) { + for (int i = $1; i <= $3; ++i) + $$->push_back(i); + } else { + for (int i = $1; i >= $3; --i) + $$->push_back(i); + } } | INTVAL INTVAL { $2 = -$2; - if ($1 < $2 || $1 < 0 || $2 < 0) { - err() << "Invalid bit range: " << $1 << "-" << $2 << "!\n"; + if ($1 < 0 || $2 < 0) { + err() << "Invalid range: " << $1 << "-" << $2 << "!\n"; exit(1); } $$ = new std::vector(); - for (int i = $1; i >= $2; --i) - $$->push_back(i); + if ($1 < $2) { + for (int i = $1; i <= $2; ++i) + $$->push_back(i); + } else { + for (int i = $1; i >= $2; --i) + $$->push_back(i); + } } | RBitList ',' INTVAL { ($$=$1)->push_back($3); } | RBitList ',' INTVAL '-' INTVAL { - if ($3 < $5 || $3 < 0 || $5 < 0) { - err() << "Invalid bit range: " << $3 << "-" << $5 << "!\n"; + if ($3 < 0 || $5 < 0) { + err() << "Invalid range: " << $3 << "-" << $5 << "!\n"; exit(1); } $$ = $1; - for (int i = $3; i >= $5; --i) - $$->push_back(i); + if ($3 < $5) { + for (int i = $3; i <= $5; ++i) + $$->push_back(i); + } else { + for (int i = $3; i >= $5; --i) + $$->push_back(i); + } } | RBitList ',' INTVAL INTVAL { $4 = -$4; - if ($3 < $4 || $3 < 0 || $4 < 0) { - err() << "Invalid bit range: " << $3 << "-" << $4 << "!\n"; + if ($3 < 0 || $4 < 0) { + err() << "Invalid range: " << $3 << "-" << $4 << "!\n"; exit(1); } $$ = $1; - for (int i = $3; i >= $4; --i) - $$->push_back(i); + if ($3 < $4) { + for (int i = $3; i <= $4; ++i) + $$->push_back(i); + } else { + for (int i = $3; i >= $4; --i) + $$->push_back(i); + } }; BitList : RBitList { $$ = $1; std::reverse($1->begin(), $1->end()); }; diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index 3fc14c59ed3..fee36b023a3 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -310,6 +310,16 @@ Init *IntInit::convertInitializerBitRange(const std::vector &Bits) { return BI; } +Init *ListInit::convertInitListSlice(const std::vector &Elements) { + std::vector Vals; + for (unsigned i = 0, e = Elements.size(); i != e; ++i) { + if (Elements[i] >= getSize()) + return 0; + Vals.push_back(getElement(Elements[i])); + } + return new ListInit(Vals); +} + void ListInit::print(std::ostream &OS) const { OS << "["; for (unsigned i = 0, e = Values.size(); i != e; ++i) { diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index 95c50aea7fe..a9ccf40468a 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -304,6 +304,15 @@ struct Init { return 0; } + /// convertInitListSlice - This method is used to implement the list slice + /// selection operator. Given an initializer, it selects the specified list + /// elements, returning them as a new init of list type. If it is not legal + /// to take a slice of this, return null. + /// + virtual Init *convertInitListSlice(const std::vector &Elements) { + return 0; + } + /// getFieldType - This method is used to implement the FieldInit class. /// Implementors of this method should return the type of the named field if /// they are of record type. @@ -466,6 +475,8 @@ public: return Values[i]; } + Init *convertInitListSlice(const std::vector &Elements); + virtual Init *convertInitializerTo(RecTy *Ty) { return Ty->convertValue(this); }