aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2002-12-02 01:23:04 +0000
committerChris Lattner <sabre@nondot.org>2002-12-02 01:23:04 +0000
commite62c1185bee05facc25d1d725434f517261d308b (patch)
tree729ff6a6f25be2918a43b9a1ce8527bafb217c6a
parent24567a9202f80c217fa8cd96d68236f90b7b44e0 (diff)
Initial checkin of TableGen utility
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4843 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--support/tools/TableGen/FileLexer.l66
-rw-r--r--support/tools/TableGen/FileParser.y445
-rw-r--r--support/tools/TableGen/Makefile23
-rw-r--r--support/tools/TableGen/Record.cpp371
-rw-r--r--support/tools/TableGen/Record.h448
-rw-r--r--support/tools/TableGen/TableGen.cpp351
-rw-r--r--utils/TableGen/FileLexer.l66
-rw-r--r--utils/TableGen/FileParser.y445
-rw-r--r--utils/TableGen/Makefile23
-rw-r--r--utils/TableGen/Record.cpp371
-rw-r--r--utils/TableGen/Record.h448
-rw-r--r--utils/TableGen/TableGen.cpp351
12 files changed, 3408 insertions, 0 deletions
diff --git a/support/tools/TableGen/FileLexer.l b/support/tools/TableGen/FileLexer.l
new file mode 100644
index 0000000000..c7e4346c0f
--- /dev/null
+++ b/support/tools/TableGen/FileLexer.l
@@ -0,0 +1,66 @@
+/*===-- FileLexer.l - Scanner for TableGen Files ----------------*- C++ -*-===//
+//
+//
+//===------------------------------------------------------------------------=*/
+
+%option prefix="File"
+%option yylineno
+%option nostdinit
+%option never-interactive
+%option batch
+%option noyywrap
+%option nodefault
+%option 8bit
+%option outfile="Lexer.cpp"
+%option ecs
+%option noreject
+%option noyymore
+
+
+%{
+#include "Record.h"
+typedef std::pair<Record*, std::vector<Init*>*> SubClassRefTy;
+#include "FileParser.h"
+
+// ParseInt - This has to handle the special case of binary numbers 0b0101
+static int ParseInt(const char *Str) {
+ if (Str[0] == '0' && Str[1] == 'b')
+ return strtol(Str+2, 0, 2);
+ return strtol(Str, 0, 0);
+}
+
+%}
+
+Comment \/\/.*
+
+Identifier [a-zA-Z_][0-9a-zA-Z_]*
+Integer [-+]?[0-9]+|0x[0-9a-fA-F]+|0b[01]+
+StringVal \"[^"]*\"
+
+%%
+
+{Comment} { /* Ignore comments */ }
+
+int { return INT; }
+bit { return BIT; }
+bits { return BITS; }
+string { return STRING; }
+list { return LIST; }
+
+class { return CLASS; }
+def { return DEF; }
+field { return FIELD; }
+set { return SET; }
+in { return IN; }
+
+{Identifier} { Filelval.StrVal = new std::string(yytext, yytext+yyleng);
+ return ID; }
+
+{StringVal} { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng-1);
+ return STRVAL; }
+
+{Integer} { Filelval.IntVal = ParseInt(Filetext); return INTVAL; }
+
+[ \t\n]+ { /* Ignore whitespace */ }
+. { return Filetext[0]; }
+%%
diff --git a/support/tools/TableGen/FileParser.y b/support/tools/TableGen/FileParser.y
new file mode 100644
index 0000000000..624a797895
--- /dev/null
+++ b/support/tools/TableGen/FileParser.y
@@ -0,0 +1,445 @@
+//===-- FileParser.y - Parser for TableGen files ----------------*- C++ -*-===//
+//
+// This file implements the bison parser for Table Generator files...
+//
+//===------------------------------------------------------------------------=//
+
+%{
+#include "Record.h"
+#include <iostream>
+#include <algorithm>
+#include <string>
+#include <stdio.h>
+#define YYERROR_VERBOSE 1
+
+int yyerror(const char *ErrorMsg);
+int yylex();
+extern FILE *Filein;
+extern int Filelineno;
+int Fileparse();
+static Record *CurRec = 0;
+
+typedef std::pair<Record*, std::vector<Init*>*> SubClassRefTy;
+
+static std::vector<std::pair<std::pair<std::string, std::vector<unsigned>*>,
+ Init*> > SetStack;
+
+void ParseFile() {
+ FILE *F = stdin;
+
+ Filein = F;
+ Filelineno = 1;
+ Fileparse();
+ Filein = stdin;
+}
+
+static std::ostream &err() {
+ return std::cerr << "Parsing Line #" << Filelineno << ": ";
+}
+
+static void addValue(const RecordVal &RV) {
+ if (CurRec->getValue(RV.getName())) {
+ err() << "Value '" << RV.getName() << "' multiply defined!\n";
+ abort();
+ }
+
+ CurRec->addValue(RV);
+}
+
+static void addSuperClass(Record *SC) {
+ if (CurRec->isSubClassOf(SC)) {
+ err() << "Already subclass of '" << SC->getName() << "'!\n";
+ abort();
+ }
+ CurRec->addSuperClass(SC);
+}
+
+static void setValue(const std::string &ValName,
+ std::vector<unsigned> *BitList, Init *V) {
+ if (!V) return ;
+
+ RecordVal *RV = CurRec->getValue(ValName);
+ if (RV == 0) {
+ err() << "Value '" << ValName << "' unknown!\n";
+ abort();
+ }
+
+ // If we are assigning to a subset of the bits in the value... then we must be
+ // assigning to a field of BitsRecTy, which must have a BitsInit
+ // initializer...
+ //
+ if (BitList) {
+ BitsInit *CurVal = dynamic_cast<BitsInit*>(RV->getValue());
+ if (CurVal == 0) {
+ err() << "Value '" << ValName << "' is not a bits type!\n";
+ abort();
+ }
+
+ // Convert the incoming value to a bits type of the appropriate size...
+ Init *BI = V->convertInitializerTo(new BitsRecTy(BitList->size()));
+ if (BI == 0) {
+ V->convertInitializerTo(new BitsRecTy(BitList->size()));
+ err() << "Initializer '" << *V << "' not compatible with bit range!\n";
+ abort();
+ }
+
+ // We should have a BitsInit type now...
+ assert(dynamic_cast<BitsInit*>(BI) != 0 || &(std::cerr << *BI) == 0);
+ BitsInit *BInit = (BitsInit*)BI;
+
+ BitsInit *NewVal = new BitsInit(CurVal->getNumBits());
+
+ for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i)
+ NewVal->setBit(i, CurVal->getBit(i));
+
+ // Loop over bits, assigning values as appopriate...
+ for (unsigned i = 0, e = BitList->size(); i != e; ++i) {
+ unsigned Bit = (*BitList)[i];
+ NewVal->setBit(Bit, BInit->getBit(i));
+ }
+ V = NewVal;
+ }
+
+ if (RV->setValue(V)) {
+ err() << "Value '" << ValName << "' of type '" << *RV->getType()
+ << "' is incompatible with initializer '" << *V << "'!\n";
+ abort();
+ }
+}
+
+static void addSubClass(Record *SC, const std::vector<Init*> &TemplateArgs) {
+ // Add all of the values in the subclass into the current class...
+ const std::vector<RecordVal> &Vals = SC->getValues();
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i)
+ addValue(Vals[i]);
+
+ const std::vector<std::string> &TArgs = SC->getTemplateArgs();
+
+ // Ensure that an appropriate number of template arguments are specified...
+ if (TArgs.size() < TemplateArgs.size()) {
+ err() << "ERROR: More template args specified thang expected!\n";
+ abort();
+ } else { // This class expects template arguments...
+ // Loop over all of the template arguments, setting them to the specified
+ // value or leaving them as the default as neccesary.
+ for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+ if (i < TemplateArgs.size()) { // A value is specified for this temp-arg?
+ // Set it now.
+ setValue(TArgs[i], 0, TemplateArgs[i]);
+ } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
+ err() << "ERROR: Value not specified for template argument #"
+ << i << " (" << TArgs[i] << ") of subclass '" << SC->getName()
+ << "'!\n";
+ abort();
+ }
+ }
+ }
+
+
+ // Since everything went well, we can now set the "superclass" list for the
+ // current record.
+ const std::vector<Record*> &SCs = SC->getSuperClasses();
+ for (unsigned i = 0, e = SCs.size(); i != e; ++i)
+ addSuperClass(SCs[i]);
+ addSuperClass(SC);
+}
+
+
+%}
+
+%union {
+ std::string *StrVal;
+ int IntVal;
+ RecTy *Ty;
+ Init *Initializer;
+ std::vector<Init*> *FieldList;
+ std::vector<Record*> *RecPtr;
+ std::vector<unsigned>*BitList;
+ Record *Rec;
+ SubClassRefTy *SubClassRef;
+ std::vector<SubClassRefTy> *SubClassList;
+};
+
+%token INT BIT STRING BITS LIST CLASS DEF FIELD SET IN
+%token <IntVal> INTVAL
+%token <StrVal> ID STRVAL
+
+%type <Ty> Type
+%type <RecPtr> DefList DefListNE
+%type <Rec> ClassInst DefInst Object ObjectBody ClassID DefID
+
+%type <SubClassRef> SubClassRef
+%type <SubClassList> ClassList ClassListNE
+%type <IntVal> OptPrefix
+%type <Initializer> Value OptValue
+%type <FieldList> ValueList ValueListNE
+%type <BitList> BitList OptBitList RBitList
+%type <StrVal> Declaration
+
+%start File
+%%
+
+ClassID : ID {
+ $$ = Records.getClass(*$1);
+ if ($$ == 0) {
+ err() << "Couldn't find class '" << *$1 << "'!\n";
+ abort();
+ }
+ delete $1;
+ };
+
+DefID : ID {
+ $$ = Records.getDef(*$1);
+ if ($$ == 0) {
+ err() << "Couldn't find def '" << *$1 << "'!\n";
+ abort();
+ }
+ delete $1;
+ };
+
+
+// TableGen types...
+Type : STRING { // string type
+ $$ = new StringRecTy();
+ } | BIT { // bit type
+ $$ = new BitRecTy();
+ } | BITS '<' INTVAL '>' { // bits<x> type
+ $$ = new BitsRecTy($3);
+ } | INT { // int type
+ $$ = new IntRecTy();
+ } | LIST '<' ClassID '>' { // list<x> type
+ $$ = new ListRecTy($3);
+ } | ClassID { // Record Type
+ $$ = new RecordRecTy($1);
+ };
+
+OptPrefix : /*empty*/ { $$ = 0; } | FIELD { $$ = 1; };
+
+OptValue : /*empty*/ { $$ = 0; } | '=' Value { $$ = $2; };
+
+Value : INTVAL {
+ $$ = new IntInit($1);
+ } | STRVAL {
+ $$ = new StringInit(*$1);
+ delete $1;
+ } | '?' {
+ $$ = new UnsetInit();
+ } | '{' ValueList '}' {
+ BitsInit *Init = new BitsInit($2->size());
+ for (unsigned i = 0, e = $2->size(); i != e; ++i) {
+ struct Init *Bit = (*$2)[i]->convertInitializerTo(new BitRecTy());
+ if (Bit == 0) {
+ err() << "Element #" << i << " (" << *(*$2)[i]
+ << ") is not convertable to a bit!\n";
+ abort();
+ }
+ Init->setBit($2->size()-i-1, Bit);
+ }
+ $$ = Init;
+ delete $2;
+ } | ID {
+ if (const RecordVal *RV = CurRec->getValue(*$1)) {
+ $$ = new VarInit(*$1, RV->getType());
+ } else if (Record *D = Records.getDef(*$1)) {
+ $$ = new DefInit(D);
+ } else {
+ err() << "Variable not defined: '" << *$1 << "'!\n";
+ abort();
+ }
+
+ delete $1;
+ } | Value '{' BitList '}' {
+ $$ = $1->convertInitializerBitRange(*$3);
+ if ($$ == 0) {
+ err() << "Invalid bit range for value '" << *$1 << "'!\n";
+ abort();
+ }
+ delete $3;
+ } | '[' DefList ']' {
+ $$ = new ListInit(*$2);
+ delete $2;
+ };
+
+DefList : /*empty */ {
+ $$ = new std::vector<Record*>();
+ } | DefListNE {
+ $$ = $1;
+ };
+DefListNE : DefID {
+ $$ = new std::vector<Record*>();
+ $$->push_back($1);
+ } | DefListNE ',' DefID {
+ ($$=$1)->push_back($3);
+ };
+
+
+RBitList : INTVAL {
+ $$ = new std::vector<unsigned>();
+ $$->push_back($1);
+ } | INTVAL '-' INTVAL {
+ if ($1 < $3 || $1 < 0 || $3 < 0) {
+ err() << "Invalid bit range: " << $1 << "-" << $3 << "!\n";
+ abort();
+ }
+ $$ = new std::vector<unsigned>();
+ 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";
+ abort();
+ }
+ $$ = new std::vector<unsigned>();
+ 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";
+ abort();
+ }
+ $$ = $1;
+ 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";
+ abort();
+ }
+ $$ = $1;
+ for (int i = $3; i >= $4; --i)
+ $$->push_back(i);
+ };
+
+BitList : RBitList { $$ = $1; std::reverse($1->begin(), $1->end()); };
+
+OptBitList : /*empty*/ { $$ = 0; } | '{' BitList '}' { $$ = $2; };
+
+
+
+ValueList : /*empty*/ {
+ $$ = new std::vector<Init*>();
+ } | ValueListNE {
+ $$ = $1;
+ };
+
+ValueListNE : Value {
+ $$ = new std::vector<Init*>();
+ $$->push_back($1);
+ } | ValueListNE ',' Value {
+ ($$ = $1)->push_back($3);
+ };
+
+Declaration : OptPrefix Type ID OptValue {
+ addValue(RecordVal(*$3, $2, $1));
+ setValue(*$3, 0, $4);
+ $$ = $3;
+};
+
+BodyItem : Declaration ';' {
+ delete $1;
+} | SET ID OptBitList '=' Value ';' {
+ setValue(*$2, $3, $5);
+ delete $2;
+ delete $3;
+};
+
+BodyList : /*empty*/ | BodyList BodyItem;
+Body : ';' | '{' BodyList '}';
+
+SubClassRef : ClassID {
+ $$ = new SubClassRefTy($1, new std::vector<Init*>());
+ } | ClassID '<' ValueListNE '>' {
+ $$ = new SubClassRefTy($1, $3);
+ };
+
+ClassListNE : SubClassRef {
+ $$ = new std::vector<SubClassRefTy>();
+ $$->push_back(*$1);
+ delete $1;
+ }
+ | ClassListNE ',' SubClassRef {
+ ($$=$1)->push_back(*$3);
+ delete $3;
+ };
+
+ClassList : /*empty */ {
+ $$ = new std::vector<SubClassRefTy>();
+ }
+ | ':' ClassListNE {
+ $$ = $2;
+ };
+
+DeclListNE : Declaration {
+ CurRec->addTemplateArg(*$1);
+ delete $1;
+} | DeclListNE ',' Declaration {
+ CurRec->addTemplateArg(*$3);
+ delete $3;
+};
+
+TemplateArgList : '<' DeclListNE '>' {};
+OptTemplateArgList : /*empty*/ | TemplateArgList;
+
+ObjectBody : ID {
+ CurRec = new Record(*$1);
+ delete $1;
+ } OptTemplateArgList ClassList {
+ for (unsigned i = 0, e = $4->size(); i != e; ++i) {
+ addSubClass((*$4)[i].first, *(*$4)[i].second);
+ delete (*$4)[i].second; // Delete the template list
+ }
+ delete $4;
+
+ // Process any variables on the set stack...
+ for (unsigned i = 0, e = SetStack.size(); i != e; ++i)
+ setValue(SetStack[i].first.first, SetStack[i].first.second,
+ SetStack[i].second);
+ } Body {
+ CurRec->resolveReferences();
+ $$ = CurRec;
+ CurRec = 0;
+};
+
+ClassInst : CLASS ObjectBody {
+ if (Records.getClass($2->getName())) {
+ err() << "Class '" << $2->getName() << "' already defined!\n";
+ abort();
+ }
+ Records.addClass($$ = $2);
+};
+
+DefInst : DEF ObjectBody {
+ // TODO: If ObjectBody has template arguments, it's an error.
+ if (Records.getDef($2->getName())) {
+ err() << "Def '" << $2->getName() << "' already defined!\n";
+ abort();
+ }
+ Records.addDef($$ = $2);
+};
+
+
+Object : ClassInst | DefInst;
+
+// Support Set commands wrapping objects...
+Object : SET ID OptBitList '=' Value IN {
+ SetStack.push_back(std::make_pair(std::make_pair(*$2, $3), $5));
+ delete $2;
+ } '{' ObjectList '}' {
+ delete SetStack.back().first.second; // Delete OptBitList
+ SetStack.pop_back();
+ };
+
+ObjectList : Object {} | ObjectList Object {};
+
+File : ObjectList {};
+
+%%
+
+int yyerror(const char *ErrorMsg) {
+ err() << "Error parsing: " << ErrorMsg << "\n";
+ abort();
+}
diff --git a/support/tools/TableGen/Makefile b/support/tools/TableGen/Makefile
new file mode 100644
index 0000000000..a9c235037e
--- /dev/null
+++ b/support/tools/TableGen/Makefile
@@ -0,0 +1,23 @@
+LEVEL = ../..
+TOOLNAME = tblgen
+USEDLIBS = support.a
+
+include $(LEVEL)/Makefile.common
+
+clean::
+ -rm -f FileParser.cpp FileParser.h FileLexer.cpp CommandLine.cpp
+ -rm -f FileParser.output
+
+test::
+ $(TOOLEXENAME_G) < X86.td
+ # -parse
+
+ @echo "enum {"
+ @$(TOOLEXENAME_G) < X86.td -class=Register
+ @echo
+ @echo "};"
+
+ @echo "enum {"
+ @$(TOOLEXENAME_G) < X86.td -class=Instruction
+ @echo
+ @echo "};"
diff --git a/support/tools/TableGen/Record.cpp b/support/tools/TableGen/Record.cpp
new file mode 100644
index 0000000000..8324bad5c1
--- /dev/null
+++ b/support/tools/TableGen/Record.cpp
@@ -0,0 +1,371 @@
+//===- Record.cpp - Record implementation ---------------------------------===//
+//
+//
+//===----------------------------------------------------------------------===//
+
+#include "Record.h"
+
+//===----------------------------------------------------------------------===//
+// Type implementations
+//===----------------------------------------------------------------------===//
+
+void RecTy::dump() const { print(std::cerr); }
+
+Init *BitRecTy::convertValue(BitsInit *BI) {
+ if (BI->getNumBits() != 1) return 0; // Only accept if just one bit!
+ return BI->getBit(0);
+}
+
+Init *BitRecTy::convertValue(IntInit *II) {
+ int Val = II->getValue();
+ if (Val != 0 && Val != 1) return 0; // Only accept 0 or 1 for a bit!
+ delete II;
+
+ return new BitInit(Val != 0);
+}
+
+Init *BitRecTy::convertValue(VarInit *VI) {
+ if (dynamic_cast<BitRecTy*>(VI->getType()))
+ return VI; // Accept variable if it is already of bit type!
+ return 0;
+}
+
+Init *BitsRecTy::convertValue(UnsetInit *UI) {
+ BitsInit *Ret = new BitsInit(Size);
+
+ for (unsigned i = 0; i != Size; ++i)
+ Ret->setBit(i, new UnsetInit());
+ return Ret;
+}
+
+Init *BitsRecTy::convertValue(BitInit *UI) {
+ if (Size != 1) return 0; // Can only convert single bit...
+ BitsInit *Ret = new BitsInit(1);
+ Ret->setBit(0, UI);
+ return Ret;
+}
+
+// convertValue from Int initializer to bits type: Split the integer up into the
+// appropriate bits...
+//
+Init *BitsRecTy::convertValue(IntInit *II) {
+ int Value = II->getValue();
+ delete II;
+
+ BitsInit *Ret = new BitsInit(Size);
+ for (unsigned i = 0; i != Size; ++i)
+ Ret->setBit(i, new BitInit(Value & (1 << i)));
+ return Ret;
+}
+
+Init *BitsRecTy::convertValue(BitsInit *BI) {
+ // If the number of bits is right, return it. Otherwise we need to expand or
+ // truncate...
+ if (BI->getNumBits() == Size) return BI;
+ return 0;
+}
+
+Init *BitsRecTy::convertValue(VarInit *VI) {
+ if (BitsRecTy *BRT = dynamic_cast<BitsRecTy*>(VI->getType()))
+ if (BRT->Size == Size) {
+ BitsInit *Ret = new BitsInit(Size);
+ for (unsigned i = 0; i != Size; ++i)
+ Ret->setBit(i, new VarBitInit(VI, i));
+ return Ret;
+ }
+ if (Size == 1 && dynamic_cast<BitRecTy*>(VI->getType())) {
+ BitsInit *Ret = new BitsInit(1);
+ Ret->setBit(0, VI);
+ return Ret;
+ }
+
+ return 0;
+}
+
+
+Init *IntRecTy::convertValue(BitsInit *BI) {
+ int Result = 0;
+ for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
+ if (BitInit *Bit = dynamic_cast<BitInit*>(BI->getBit(i))) {
+ Result |= Bit->getValue() << i;
+ } else {
+ return 0;
+ }
+ return new IntInit(Result);
+}
+
+Init *IntRecTy::convertValue(VarInit *VI) {
+ if (dynamic_cast<IntRecTy*>(VI->getType()))
+ return VI; // Accept variable if already of the right type!
+ return 0;
+}
+
+Init *StringRecTy::convertValue(VarInit *VI) {
+ if (dynamic_cast<StringRecTy*>(VI->getType()))
+ return VI; // Accept variable if already of the right type!
+ return 0;
+}
+
+void ListRecTy::print(std::ostream &OS) const {
+ OS << "list<" << Class->getName() << ">";
+}
+
+Init *ListRecTy::convertValue(ListInit *LI) {
+ // Verify that all of the elements of the list are subclasses of the
+ // appopriate class!
+ for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
+ if (!LI->getElement(i)->isSubClassOf(Class))
+ return 0;
+ return LI;
+}
+
+void RecordRecTy::print(std::ostream &OS) const {
+ OS << Rec->getName();
+}
+
+Init *RecordRecTy::convertValue(DefInit *DI) {
+ // Ensure that DI is a subclass of Rec.
+ if (!DI->getDef()->isSubClassOf(Rec))
+ return 0;
+ return DI;
+}
+
+//===----------------------------------------------------------------------===//
+// Initializer implementations
+//===----------------------------------------------------------------------===//
+
+void Init::dump() const { return print(std::cerr); }
+
+Init *BitsInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
+ BitsInit *BI = new BitsInit(Bits.size());
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ if (Bits[i] >= getNumBits()) {
+ delete BI;
+ return 0;
+ }
+ BI->setBit(i, getBit(Bits[i]));
+ }
+ return BI;
+}
+
+void BitsInit::print(std::ostream &OS) const {
+ //if (!printInHex(OS)) return;
+ if (!printAsVariable(OS)) return;
+ if (!printAsUnset(OS)) return;
+
+ OS << "{ ";
+ for (unsigned i = 0, e = getNumBits(); i != e; ++i) {
+ if (i) OS << ", ";
+ getBit(e-i-1)->print(OS);
+ }
+ OS << " }";
+}
+
+bool BitsInit::printInHex(std::ostream &OS) const {
+ // First, attempt to convert the value into an integer value...
+ int Result = 0;
+ for (unsigned i = 0, e = getNumBits(); i != e; ++i)
+ if (BitInit *Bit = dynamic_cast<BitInit*>(getBit(i))) {
+ Result |= Bit->getValue() << i;
+ } else {
+ return true;
+ }
+
+ OS << "0x" << std::hex << Result << std::dec;
+ return false;
+}
+
+bool BitsInit::printAsVariable(std::ostream &OS) const {
+ // Get the variable that we may be set equal to...
+ assert(getNumBits() != 0);
+ VarBitInit *FirstBit = dynamic_cast<VarBitInit*>(getBit(0));
+ if (FirstBit == 0) return true;
+ VarInit *Var = FirstBit->getVariable();
+
+ // Check to make sure the types are compatible.
+ BitsRecTy *Ty = dynamic_cast<BitsRecTy*>(Var->getType());
+ if (Ty == 0) return true;
+ if (Ty->getNumBits() != getNumBits()) return true; // Incompatible types!
+
+ // Check to make sure all bits are referring to the right bits in the variable
+ for (unsigned i = 0, e = getNumBits(); i != e; ++i) {
+ VarBitInit *Bit = dynamic_cast<VarBitInit*>(getBit(i));
+ if (Bit == 0 || Bit->getVariable() != Var || Bit->getBitNum() != i)
+ return true;
+ }
+
+ OS << Var->getName();
+ return false;
+}
+
+bool BitsInit::printAsUnset(std::ostream &OS) const {
+ for (unsigned i = 0, e = getNumBits(); i != e; ++i)
+ if (!dynamic_cast<UnsetInit*>(getBit(i)))
+ return true;
+ OS << "?";
+ return false;
+}
+
+Init *IntInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
+ BitsInit *BI = new BitsInit(Bits.size());
+
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ if (Bits[i] >= 32) {
+ delete BI;
+ return 0;
+ }
+ BI->setBit(i, new BitInit(Value & (1 << Bits[i])));
+ }
+ return BI;
+}
+
+void ListInit::print(std::ostream &OS) const {
+ OS << "[";
+ for (unsigned i = 0, e = Records.size(); i != e; ++i) {
+ if (i) OS << ", ";
+ OS << Records[i]->getName();
+ }
+ OS << "]";
+}
+
+Init *VarInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
+ BitsRecTy *T = dynamic_cast<BitsRecTy*>(Ty);
+ if (T == 0) return 0; // Cannot subscript a non-bits variable...
+ unsigned NumBits = T->getNumBits();
+
+ BitsInit *BI = new BitsInit(Bits.size());
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ if (Bits[i] >= NumBits) {
+ delete BI;
+ return 0;
+ }
+ BI->setBit(i, new VarBitInit(this, Bits[i]));
+ }
+ return BI;
+}
+
+Init *BitsInit::resolveReferences(Record &R) {
+ bool Changed = false;
+ BitsInit *New = new BitsInit(getNumBits());
+
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ Init *B;
+ New->setBit(i, getBit(i));
+ do {
+ B = New->getBit(i);
+ New->setBit(i, B->resolveReferences(R));
+ Changed |= B != New->getBit(i);
+ } while (B != New->getBit(i));
+ }
+
+ if (Changed)
+ return New;
+ delete New;
+ return this;
+}
+
+
+
+Init *VarBitInit::resolveReferences(Record &R) {
+ if (R.isTemplateArg(getVariable()->getName()))
+ return this;
+
+ RecordVal *RV = R.getValue(getVariable()->getName());
+ assert(RV && "Reference to a non-existant variable?");
+ assert(dynamic_cast<BitsInit*>(RV->getValue()));
+ BitsInit *BI = (BitsInit*)RV->getValue();
+
+ assert(getBitNum() < BI->getNumBits() && "Bit reference out of range!");
+ Init *B = BI->getBit(getBitNum());
+
+ if (!dynamic_cast<UnsetInit*>(B)) // If the bit is not set...
+ return B; // Replace the VarBitInit with it.
+ return this;
+}
+
+void DefInit::print(std::ostream &OS) const {
+ OS << Def->getName();
+}
+
+//===----------------------------------------------------------------------===//
+// Other implementations
+//===----------------------------------------------------------------------===//
+
+RecordVal::RecordVal(const std::string &N, RecTy *T, unsigned P)
+ : Name(N), Ty(T), Prefix(P) {
+ Value = Ty->convertValue(new UnsetInit());
+ assert(Value && "Cannot create unset value for current type!");
+}
+
+void RecordVal::dump() const { std::cerr << *this; }
+
+void RecordVal::print(std::ostream &OS, bool PrintSem) const {
+ if (getPrefix()) OS << "field ";
+ OS << *getType() << " " << getName();
+ if (getValue()) {
+ OS << " = " << *getValue();
+ }
+ if (PrintSem) OS << ";\n";
+}
+
+// resolveReferences - If there are any field references that refer to fields
+// that have been filled in, we can propagate the values now.
+//
+void Record::resolveReferences() {
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ Values[i].setValue(Values[i].getValue()->resolveReferences(*this));
+}
+
+void Record::dump() const { std::cerr << *this; }
+
+std::ostream &operator<<(std::ostream &OS, const Record &R) {
+ OS << R.getName();
+
+ const std::vector<std::string> &TArgs = R.getTemplateArgs();
+ if (!TArgs.empty()) {
+ OS << "<";
+ for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+ if (i) OS << ", ";
+ const RecordVal *RV = R.getValue(TArgs[i]);
+ assert(RV && "Template argument record not found??");
+ RV->print(OS, false);
+ }
+ OS << ">";
+ }
+
+ OS << " {";
+ const std::vector<Record*> &SC = R.getSuperClasses();
+ if (!SC.empty()) {
+ OS << "\t//";
+ for (unsigned i = 0, e = SC.size(); i != e; ++i)
+ OS << " " << SC[i]->getName();
+ }
+ OS << "\n";
+
+ const std::vector<RecordVal> &Vals = R.getValues();
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i)
+ if (Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName()))
+ OS << Vals[i];
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i)
+ if (!Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName()))
+ OS << Vals[i];
+
+ return OS << "}\n";
+}
+
+void RecordKeeper::dump() const { std::cerr << *this; }
+
+std::ostream &operator<<(std::ostream &OS, const RecordKeeper &RK) {
+ OS << "------------- Classes -----------------\n";
+ const std::map<std::string, Record*> &Classes = RK.getClasses();
+ for (std::map<std::string, Record*>::const_iterator I = Classes.begin(),
+ E = Classes.end(); I != E; ++I)
+ OS << "class " << *I->second;
+
+ OS << "------------- Defs -----------------\n";
+ const std::map<std::string, Record*> &Defs = RK.getDefs();
+ for (std::map<std::string, Record*>::const_iterator I = Defs.begin(),
+ E = Defs.end(); I != E; ++I)
+ OS << "def " << *I->second;
+ return OS;
+}
diff --git a/support/tools/TableGen/Record.h b/support/tools/TableGen/Record.h
new file mode 100644
index 0000000000..a3f8c0bd85
--- /dev/null
+++ b/support/tools/TableGen/Record.h
@@ -0,0 +1,448 @@
+//===- Record.h - Classes to represent Table Records ------------*- C++ -*-===//
+//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef RECORD_H
+#define RECORD_H
+
+#include <string>
+#include <vector>
+#include <map>
+#include <iostream>
+class Init;
+class UnsetInit;
+class BitInit;
+class BitsInit;
+class IntInit;
+class StringInit;
+class ListInit;
+class VarInit;
+class VarBitInit;
+class DefInit;
+class Record;
+
+//===----------------------------------------------------------------------===//
+// Type Classes
+//===----------------------------------------------------------------------===//
+
+struct RecTy {
+ virtual ~RecTy() {}
+
+ virtual Init *convertValue( UnsetInit *UI) { return 0; }
+ virtual Init *convertValue( BitInit *BI) { return 0; }
+ virtual Init *convertValue( BitsInit *BI) { return 0; }
+ virtual Init *convertValue( IntInit *II) { return 0; }
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( VarInit *VI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+
+ virtual void print(std::ostream &OS) const = 0;
+ void dump() const;
+};
+
+inline std::ostream &operator<<(std::ostream &OS, const RecTy &Ty) {
+ Ty.print(OS);
+ return OS;
+}
+
+struct BitRecTy : public RecTy {
+ Init *convertValue(UnsetInit *UI) { return (Init*)UI; }
+ Init *convertValue(BitInit *BI) { return (Init*)BI; }
+ Init *convertValue(BitsInit *BI);
+ Init *convertValue(IntInit *II);
+ Init *convertValue(VarInit *VI);
+
+ void print(std::ostream &OS) const { OS << "bit"; }
+};
+
+class BitsRecTy : public RecTy {
+ unsigned Size;
+public:
+ BitsRecTy(unsigned Sz) : Size(Sz) {}
+
+ unsigned getNumBits() const { return Size; }
+
+ Init *convertValue(UnsetInit *UI);
+ Init *convertValue(BitInit *UI);
+ Init *convertValue(BitsInit *BI);
+ Init *convertValue(IntInit *II);
+ Init *convertValue(VarInit *VI);
+
+ void print(std::ostream &OS) const { OS << "bits<" << Size << ">"; }
+};
+
+struct IntRecTy : public RecTy {
+ Init *convertValue(UnsetInit *UI) { return (Init*)UI; }
+ Init *convertValue(IntInit *II) { return (Init*)II; }
+ Init *convertValue(BitsInit *BI);
+ Init *convertValue(VarInit *VI);
+
+ void print