summaryrefslogtreecommitdiffstats
path: root/llvm/utils/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils/TableGen')
-rw-r--r--llvm/utils/TableGen/CodeEmitterGen.cpp217
-rw-r--r--llvm/utils/TableGen/CodeEmitterGen.h24
-rw-r--r--llvm/utils/TableGen/CodeGenWrappers.cpp89
-rw-r--r--llvm/utils/TableGen/CodeGenWrappers.h56
-rw-r--r--llvm/utils/TableGen/FileLexer.l222
-rw-r--r--llvm/utils/TableGen/FileParser.y510
-rw-r--r--llvm/utils/TableGen/InstrInfoEmitter.cpp160
-rw-r--r--llvm/utils/TableGen/InstrInfoEmitter.h34
-rw-r--r--llvm/utils/TableGen/InstrSelectorEmitter.cpp1287
-rw-r--r--llvm/utils/TableGen/InstrSelectorEmitter.h387
-rw-r--r--llvm/utils/TableGen/Makefile18
-rw-r--r--llvm/utils/TableGen/Record.cpp676
-rw-r--r--llvm/utils/TableGen/Record.h849
-rw-r--r--llvm/utils/TableGen/RegisterInfoEmitter.cpp234
-rw-r--r--llvm/utils/TableGen/RegisterInfoEmitter.h29
-rw-r--r--llvm/utils/TableGen/TableGen.cpp482
-rw-r--r--llvm/utils/TableGen/TableGenBackend.cpp27
-rw-r--r--llvm/utils/TableGen/TableGenBackend.h34
18 files changed, 5335 insertions, 0 deletions
diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp
new file mode 100644
index 00000000000..98976c73363
--- /dev/null
+++ b/llvm/utils/TableGen/CodeEmitterGen.cpp
@@ -0,0 +1,217 @@
+//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
+//
+// FIXME: Document.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeEmitterGen.h"
+#include "Record.h"
+#include "Support/Debug.h"
+
+void CodeEmitterGen::run(std::ostream &o) {
+ std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
+
+ EmitSourceFileHeader("Machine Code Emitter", o);
+
+ std::string Namespace = "V9::";
+ std::string ClassName = "SparcV9CodeEmitter::";
+
+ //const std::string &Namespace = Inst->getValue("Namespace")->getName();
+ o << "unsigned " << ClassName
+ << "getBinaryCodeForInstr(MachineInstr &MI) {\n"
+ << " unsigned Value = 0;\n"
+ << " DEBUG(std::cerr << MI);\n"
+ << " switch (MI.getOpcode()) {\n";
+ for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
+ I != E; ++I) {
+ Record *R = *I;
+ o << " case " << Namespace << R->getName() << ": {\n"
+ << " DEBUG(std::cerr << \"Emitting " << R->getName() << "\\n\");\n";
+
+ BitsInit *BI = R->getValueAsBitsInit("Inst");
+
+ unsigned Value = 0;
+ const std::vector<RecordVal> &Vals = R->getValues();
+
+ DEBUG(o << " // prefilling: ");
+ // Start by filling in fixed values...
+ for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
+ if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
+ Value |= B->getValue() << (e-i-1);
+ DEBUG(o << B->getValue());
+ } else {
+ DEBUG(o << "0");
+ }
+ }
+ DEBUG(o << "\n");
+
+ DEBUG(o << " // " << *R->getValue("Inst") << "\n");
+ o << " Value = " << Value << "U;\n\n";
+
+ // Loop over all of the fields in the instruction determining which are the
+ // operands to the instruction.
+ //
+ unsigned op = 0;
+ std::map<std::string, unsigned> OpOrder;
+ std::map<std::string, bool> OpContinuous;
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
+ if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) {
+ // Is the operand continuous? If so, we can just mask and OR it in
+ // instead of doing it bit-by-bit, saving a lot in runtime cost.
+ const BitsInit *InstInit = BI;
+ int beginBitInVar = -1, endBitInVar = -1;
+ int beginBitInInst = -1, endBitInInst = -1;
+ bool continuous = true;
+
+ for (int bit = InstInit->getNumBits()-1; bit >= 0; --bit) {
+ if (VarBitInit *VBI =
+ dynamic_cast<VarBitInit*>(InstInit->getBit(bit))) {
+ TypedInit *TI = VBI->getVariable();
+ if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
+ // only process the current variable
+ if (VI->getName() != Vals[i].getName())
+ continue;
+
+ if (beginBitInVar == -1)
+ beginBitInVar = VBI->getBitNum();
+
+ if (endBitInVar == -1)
+ endBitInVar = VBI->getBitNum();
+ else {
+ if (endBitInVar == (int)VBI->getBitNum() + 1)
+ endBitInVar = VBI->getBitNum();
+ else {
+ continuous = false;
+ break;
+ }
+ }
+
+ if (beginBitInInst == -1)
+ beginBitInInst = bit;
+ if (endBitInInst == -1)
+ endBitInInst = bit;
+ else {
+ if (endBitInInst == bit + 1)
+ endBitInInst = bit;
+ else {
+ continuous = false;
+ break;
+ }
+ }
+
+ // maintain same distance between bits in field and bits in
+ // instruction. if the relative distances stay the same
+ // throughout,
+ if (beginBitInVar - (int)VBI->getBitNum() !=
+ beginBitInInst - bit) {
+ continuous = false;
+ break;
+ }
+ }
+ }
+ }
+
+ // If we have found no bit in "Inst" which comes from this field, then
+ // this is not an operand!!
+ if (beginBitInInst != -1) {
+ o << " // op" << op << ": " << Vals[i].getName() << "\n"
+ << " int64_t op" << op
+ <<" = getMachineOpValue(MI, MI.getOperand("<<op<<"));\n";
+ //<< " MachineOperand &op" << op <<" = MI.getOperand("<<op<<");\n";
+ OpOrder[Vals[i].getName()] = op++;
+
+ DEBUG(o << " // Var: begin = " << beginBitInVar
+ << ", end = " << endBitInVar
+ << "; Inst: begin = " << beginBitInInst
+ << ", end = " << endBitInInst << "\n");
+
+ if (continuous) {
+ DEBUG(o << " // continuous: op" << OpOrder[Vals[i].getName()]
+ << "\n");
+
+ // Mask off the right bits
+ // Low mask (ie. shift, if necessary)
+ assert(endBitInVar >= 0 && "Negative shift amount in masking!");
+ if (endBitInVar != 0) {
+ o << " op" << OpOrder[Vals[i].getName()]
+ << " >>= " << endBitInVar << ";\n";
+ beginBitInVar -= endBitInVar;
+ endBitInVar = 0;
+ }
+
+ // High mask
+ o << " op" << OpOrder[Vals[i].getName()]
+ << " &= (1<<" << beginBitInVar+1 << ") - 1;\n";
+
+ // Shift the value to the correct place (according to place in inst)
+ assert(endBitInInst >= 0 && "Negative shift amount in inst position!");
+ if (endBitInInst != 0)
+ o << " op" << OpOrder[Vals[i].getName()]
+ << " <<= " << endBitInInst << ";\n";
+
+ // Just OR in the result
+ o << " Value |= op" << OpOrder[Vals[i].getName()] << ";\n";
+ }
+
+ // otherwise, will be taken care of in the loop below using this
+ // value:
+ OpContinuous[Vals[i].getName()] = continuous;
+ }
+ }
+ }
+
+ for (unsigned f = 0, e = Vals.size(); f != e; ++f) {
+ if (Vals[f].getPrefix()) {
+ BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();
+
+ // Scan through the field looking for bit initializers of the current
+ // variable...
+ for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) {
+ if (BitInit *BI = dynamic_cast<BitInit*>(FieldInitializer->getBit(i)))
+ {
+ DEBUG(o << " // bit init: f: " << f << ", i: " << i << "\n");
+ } else if (UnsetInit *UI =
+ dynamic_cast<UnsetInit*>(FieldInitializer->getBit(i))) {
+ DEBUG(o << " // unset init: f: " << f << ", i: " << i << "\n");
+ } else if (VarBitInit *VBI =
+ dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) {
+ TypedInit *TI = VBI->getVariable();
+ if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
+ // If the bits of the field are laid out consecutively in the
+ // instruction, then instead of separately ORing in bits, just
+ // mask and shift the entire field for efficiency.
+ if (OpContinuous[VI->getName()]) {
+ // already taken care of in the loop above, thus there is no
+ // need to individually OR in the bits
+
+ // for debugging, output the regular version anyway, commented
+ DEBUG(o << " // Value |= getValueBit(op"
+ << OpOrder[VI->getName()] << ", " << VBI->getBitNum()
+ << ")" << " << " << i << ";\n");
+ } else {
+ o << " Value |= getValueBit(op" << OpOrder[VI->getName()]
+ << ", " << VBI->getBitNum()
+ << ")" << " << " << i << ";\n";
+ }
+ } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
+ // FIXME: implement this!
+ o << "FIELD INIT not implemented yet!\n";
+ } else {
+ o << "Error: UNIMPLEMENTED\n";
+ }
+ }
+ }
+ }
+ }
+
+ o << " break;\n"
+ << " }\n";
+ }
+
+ o << " default:\n"
+ << " std::cerr << \"Not supported instr: \" << MI << \"\\n\";\n"
+ << " abort();\n"
+ << " }\n"
+ << " return Value;\n"
+ << "}\n";
+}
diff --git a/llvm/utils/TableGen/CodeEmitterGen.h b/llvm/utils/TableGen/CodeEmitterGen.h
new file mode 100644
index 00000000000..4b87da5067e
--- /dev/null
+++ b/llvm/utils/TableGen/CodeEmitterGen.h
@@ -0,0 +1,24 @@
+//===- CodeEmitterGen.h - Code Emitter Generator ----------------*- C++ -*-===//
+//
+// FIXME: document
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEMITTERGEN_H
+#define CODEMITTERGEN_H
+
+#include "TableGenBackend.h"
+
+class CodeEmitterGen : public TableGenBackend {
+ RecordKeeper &Records;
+public:
+ CodeEmitterGen(RecordKeeper &R) : Records(R) {}
+
+ // run - Output the code emitter
+ void run(std::ostream &o);
+private:
+ void emitMachineOpEmitter(std::ostream &o, const std::string &Namespace);
+ void emitGetValueBit(std::ostream &o, const std::string &Namespace);
+};
+
+#endif
diff --git a/llvm/utils/TableGen/CodeGenWrappers.cpp b/llvm/utils/TableGen/CodeGenWrappers.cpp
new file mode 100644
index 00000000000..61c3abc2971
--- /dev/null
+++ b/llvm/utils/TableGen/CodeGenWrappers.cpp
@@ -0,0 +1,89 @@
+//===- CodeGenWrappers.cpp - Code Generation Class Wrappers -----*- C++ -*-===//
+//
+// These classes wrap target description classes used by the various code
+// generation TableGen backends. This makes it easier to access the data and
+// provides a single place that needs to check it for validity. All of these
+// classes throw exceptions on error conditions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenWrappers.h"
+#include "Record.h"
+
+/// getValueType - Return the MCV::ValueType that the specified TableGen record
+/// corresponds to.
+MVT::ValueType getValueType(Record *Rec) {
+ return (MVT::ValueType)Rec->getValueAsInt("Value");
+}
+
+std::string getName(MVT::ValueType T) {
+ switch (T) {
+ case MVT::Other: return "UNKNOWN";
+ case MVT::i1: return "i1";
+ case MVT::i8: return "i8";
+ case MVT::i16: return "i16";
+ case MVT::i32: return "i32";
+ case MVT::i64: return "i64";
+ case MVT::i128: return "i128";
+ case MVT::f32: return "f32";
+ case MVT::f64: return "f64";
+ case MVT::f80: return "f80";
+ case MVT::f128: return "f128";
+ case MVT::isVoid:return "void";
+ default: assert(0 && "ILLEGAL VALUE TYPE!"); return "";
+ }
+}
+
+std::string getEnumName(MVT::ValueType T) {
+ switch (T) {
+ case MVT::Other: return "Other";
+ case MVT::i1: return "i1";
+ case MVT::i8: return "i8";
+ case MVT::i16: return "i16";
+ case MVT::i32: return "i32";
+ case MVT::i64: return "i64";
+ case MVT::i128: return "i128";
+ case MVT::f32: return "f32";
+ case MVT::f64: return "f64";
+ case MVT::f80: return "f80";
+ case MVT::f128: return "f128";
+ case MVT::isVoid:return "isVoid";
+ default: assert(0 && "ILLEGAL VALUE TYPE!"); return "";
+ }
+}
+
+
+std::ostream &operator<<(std::ostream &OS, MVT::ValueType T) {
+ return OS << getName(T);
+}
+
+
+
+/// getTarget - Return the current instance of the Target class.
+///
+CodeGenTarget::CodeGenTarget() {
+ std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
+ if (Targets.size() != 1)
+ throw std::string("ERROR: Multiple subclasses of Target defined!");
+ TargetRec = Targets[0];
+
+ // Read in all of the CalleeSavedRegisters...
+ ListInit *LI = TargetRec->getValueAsListInit("CalleeSavedRegisters");
+ for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
+ if (DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(i)))
+ CalleeSavedRegisters.push_back(DI->getDef());
+ else
+ throw "Target: " + TargetRec->getName() +
+ " expected register definition in CalleeSavedRegisters list!";
+
+ PointerType = getValueType(TargetRec->getValueAsDef("PointerType"));
+}
+
+
+const std::string &CodeGenTarget::getName() const {
+ return TargetRec->getName();
+}
+
+Record *CodeGenTarget::getInstructionSet() const {
+ return TargetRec->getValueAsDef("InstructionSet");
+}
diff --git a/llvm/utils/TableGen/CodeGenWrappers.h b/llvm/utils/TableGen/CodeGenWrappers.h
new file mode 100644
index 00000000000..00ca3fcc603
--- /dev/null
+++ b/llvm/utils/TableGen/CodeGenWrappers.h
@@ -0,0 +1,56 @@
+//===- CodeGenWrappers.h - Code Generation Class Wrappers -------*- C++ -*-===//
+//
+// These classes wrap target description classes used by the various code
+// generation TableGen backends. This makes it easier to access the data and
+// provides a single place that needs to check it for validity. All of these
+// classes throw exceptions on error conditions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGENWRAPPERS_H
+#define CODEGENWRAPPERS_H
+
+#include "llvm/CodeGen/ValueTypes.h"
+#include <iosfwd>
+#include <string>
+#include <vector>
+class Record;
+class RecordKeeper;
+
+/// getValueType - Return the MVT::ValueType that the specified TableGen record
+/// corresponds to.
+MVT::ValueType getValueType(Record *Rec);
+
+std::ostream &operator<<(std::ostream &OS, MVT::ValueType T);
+std::string getName(MVT::ValueType T);
+std::string getEnumName(MVT::ValueType T);
+
+
+/// CodeGenTarget - This class corresponds to the Target class in the .td files.
+///
+class CodeGenTarget {
+ Record *TargetRec;
+ std::vector<Record*> CalleeSavedRegisters;
+ MVT::ValueType PointerType;
+
+public:
+ CodeGenTarget();
+
+ Record *getTargetRecord() const { return TargetRec; }
+ const std::string &getName() const;
+
+ const std::vector<Record*> &getCalleeSavedRegisters() const {
+ return CalleeSavedRegisters;
+ }
+
+ MVT::ValueType getPointerType() const { return PointerType; }
+
+ // getInstructionSet - Return the InstructionSet object...
+ Record *getInstructionSet() const;
+
+ // getInstructionSet - Return the CodeGenInstructionSet object for this
+ // target, lazily reading it from the record keeper as needed.
+ // CodeGenInstructionSet *getInstructionSet -
+};
+
+#endif
diff --git a/llvm/utils/TableGen/FileLexer.l b/llvm/utils/TableGen/FileLexer.l
new file mode 100644
index 00000000000..64ed4c625a9
--- /dev/null
+++ b/llvm/utils/TableGen/FileLexer.l
@@ -0,0 +1,222 @@
+/*===-- FileLexer.l - Scanner for TableGen Files ----------------*- C++ -*-===//
+//
+// This file defines a simple flex scanner for TableGen files. This is pretty
+// straight-forward, except for the magic to handle file inclusion.
+//
+//===----------------------------------------------------------------------===*/
+
+%option prefix="File"
+%option yylineno
+%option nostdinit
+%option never-interactive
+%option batch
+%option nodefault
+%option 8bit
+%option outfile="Lexer.cpp"
+%option ecs
+%option noreject
+%option noyymore
+
+%x comment
+
+%{
+#include "Record.h"
+typedef std::pair<Record*, std::vector<Init*>*> SubClassRefTy;
+#include "FileParser.h"
+
+// Global variable recording the location of the include directory
+std::string IncludeDirectory;
+
+// 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);
+}
+
+static int CommentDepth = 0;
+
+struct IncludeRec {
+ std::string Filename;
+ FILE *File;
+ unsigned LineNo;
+ YY_BUFFER_STATE Buffer;
+
+ IncludeRec(const std::string &FN, FILE *F)
+ : Filename(FN), File(F), LineNo(0){
+ }
+};
+
+static std::vector<IncludeRec> IncludeStack;
+
+
+std::ostream &err() {
+ if (IncludeStack.empty())
+ return std::cerr << "At end of input: ";
+
+ for (unsigned i = 0, e = IncludeStack.size()-1; i != e; ++i)
+ std::cerr << "Included from " << IncludeStack[i].Filename << ":"
+ << IncludeStack[i].LineNo << ":\n";
+ return std::cerr << "Parsing " << IncludeStack.back().Filename << ":"
+ << Filelineno << ": ";
+}
+
+
+int Fileparse();
+
+//
+// Function: ParseFile()
+//
+// Description:
+// This function begins the parsing of the specified tablegen file.
+//
+// Inputs:
+// Filename - A string containing the name of the file to parse.
+// IncludeDir - A string containing the directory from which include
+// files can be found.
+//
+void ParseFile(const std::string &Filename, const std::string & IncludeDir) {
+ FILE *F = stdin;
+ if (Filename != "-") {
+ F = fopen(Filename.c_str(), "r");
+
+ if (F == 0) {
+ std::cerr << "Could not open input file '" + Filename + "'!\n";
+ exit (1);
+ }
+ IncludeStack.push_back(IncludeRec(Filename, F));
+ } else {
+ IncludeStack.push_back(IncludeRec("<stdin>", stdin));
+ }
+
+ //
+ // Record the location of the include directory so that the lexer can find
+ // it later.
+ //
+ IncludeDirectory = IncludeDir;
+
+ Filein = F;
+ Filelineno = 1;
+ Fileparse();
+ Filein = stdin;
+}
+
+// HandleInclude - This function is called when an include directive is
+// encountered in the input stream...
+static void HandleInclude(const char *Buffer) {
+ unsigned Length = yyleng;
+ assert(Buffer[Length-1] == '"');
+ Buffer += strlen("include ");
+ Length -= strlen("include ");
+ while (*Buffer != '"') {
+ ++Buffer;
+ --Length;
+ }
+ assert(Length >= 2 && "Double quotes not found?");
+ std::string Filename(Buffer+1, Buffer+Length-1);
+ //std::cerr << "Filename = '" << Filename << "'\n";
+
+ // Save the line number and lex buffer of the includer...
+ IncludeStack.back().LineNo = Filelineno;
+ IncludeStack.back().Buffer = YY_CURRENT_BUFFER;
+
+ // Open the new input file...
+ yyin = fopen(Filename.c_str(), "r");
+ if (yyin == 0) {
+ //
+ // If we couldn't find the file in the current directory, look for it in
+ // the include directories.
+ //
+ // NOTE:
+ // Right now, there is only one directory. We need to eventually add
+ // support for more.
+ //
+ Filename = IncludeDirectory + "/" + Filename;
+ yyin = fopen(Filename.c_str(), "r");
+ if (yyin == 0) {
+ err() << "Could not find include file '" << Filename << "'!\n";
+ abort();
+ }
+ }
+
+ // Add the file to our include stack...
+ IncludeStack.push_back(IncludeRec(Filename, yyin));
+ Filelineno = 1; // Reset line numbering...
+ //yyrestart(yyin); // Start lexing the new file...
+
+ yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+}
+
+
+// yywrap - This is called when the lexer runs out of input in one of the files.
+// Switch back to an includer if an includee has run out of input.
+//
+extern "C"
+int yywrap() {
+ if (IncludeStack.back().File != stdin)
+ fclose(IncludeStack.back().File);
+ IncludeStack.pop_back();
+ if (IncludeStack.empty()) return 1; // Top-level file is done.
+
+ // Otherwise, we need to switch back to a file which included the current one.
+ Filelineno = IncludeStack.back().LineNo; // Restore current line number
+ yy_switch_to_buffer(IncludeStack.back().Buffer);
+ return 0;
+}
+
+%}
+
+Comment \/\/.*
+
+Identifier [a-zA-Z_][0-9a-zA-Z_]*
+Integer [-+]?[0-9]+|0x[0-9a-fA-F]+|0b[01]+
+CodeFragment \[\{([^}]+|\}[^\]])*\}\]
+StringVal \"[^"]*\"
+IncludeStr include[ \t\n]+\"[^"]*\"
+
+%%
+
+{Comment} { /* Ignore comments */ }
+
+{IncludeStr} { HandleInclude(yytext); }
+{CodeFragment} { Filelval.StrVal = new std::string(yytext+2, yytext+yyleng-2);
+ return CODEFRAGMENT; }
+
+int { return INT; }
+bit { return BIT; }
+bits { return BITS; }
+string { return STRING; }
+list { return LIST; }
+code { return CODE; }
+dag { return DAG; }
+
+class { return CLASS; }
+def { return DEF; }
+field { return FIELD; }
+let { return LET; }
+in { return IN; }
+
+{Identifier} { Filelval.StrVal = new std::string(yytext, yytext+yyleng);
+ return ID; }
+${Identifier} { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng);
+ return VARNAME; }
+
+{StringVal} { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng-1);
+ return STRVAL; }
+
+{Integer} { Filelval.IntVal = ParseInt(Filetext); return INTVAL; }
+
+[ \t\n]+ { /* Ignore whitespace */ }
+
+
+"/*" { BEGIN(comment); CommentDepth++; }
+<comment>[^*/]* /* eat anything that's not a '*' or '/' */
+<comment>"*"+[^*/]* /* eat up '*'s not followed by '/'s */
+<comment>"/*" { ++CommentDepth; }
+<comment>"/"+[^*]* /* eat up /'s not followed by *'s */
+<comment>"*"+"/" { if (!--CommentDepth) { BEGIN(INITIAL); } }
+<comment><<EOF>> { err() << "Unterminated comment!\n"; abort(); }
+
+. { return Filetext[0]; }
+
+%%
diff --git a/llvm/utils/TableGen/FileParser.y b/llvm/utils/TableGen/FileParser.y
new file mode 100644
index 00000000000..728fcf222c6
--- /dev/null
+++ b/llvm/utils/TableGen/FileParser.y
@@ -0,0 +1,510 @@
+//===-- FileParser.y - Parser for TableGen files ----------------*- C++ -*-===//
+//
+// This file implements the bison parser for Table Generator files...
+//
+//===------------------------------------------------------------------------=//
+
+%{
+#include "Record.h"
+#include "Support/StringExtras.h"
+#include <algorithm>
+#include <cstdio>
+#define YYERROR_VERBOSE 1
+
+int yyerror(const char *ErrorMsg);
+int yylex();
+extern int Filelineno;
+static Record *CurRec = 0;
+
+typedef std::pair<Record*, std::vector<Init*>*> SubClassRefTy;
+
+struct LetRecord {
+ std::string Name;
+ std::vector<unsigned> Bits;
+ Init *Value;
+ bool HasBits;
+ LetRecord(const std::string &N, std::vector<unsigned> *B, Init *V)
+ : Name(N), Value(V), HasBits(B != 0) {
+ if (HasBits) Bits = *B;
+ }
+};
+
+static std::vector<std::vector<LetRecord> > LetStack;
+
+
+extern std::ostream &err();
+
+static void addValue(const RecordVal &RV) {
+ if (RecordVal *ERV = CurRec->getValue(RV.getName())) {
+ // The value already exists in the class, treat this as a set...
+ if (ERV->setValue(RV.getValue())) {
+ err() << "New definition of '" << RV.getName() << "' of type '"
+ << *RV.getType() << "' is incompatible with previous "
+ << "definition of type '" << *ERV->getType() << "'!\n";
+ abort();
+ }
+ } else {
+ 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());
+
+ // Loop over bits, assigning values as appropriate...
+ for (unsigned i = 0, e = BitList->size(); i != e; ++i) {
+ unsigned Bit = (*BitList)[i];
+ if (NewVal->getBit(Bit)) {
+ err() << "Cannot set bit #" << Bit << " of value '" << ValName
+ << "' more than once!\n";
+ abort();
+ }
+ NewVal->setBit(Bit, BInit->getBit(i));
+ }
+
+ for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i)
+ if (NewVal->getBit(i) == 0)
+ NewVal->setBit(i, CurVal->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 than 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 necessary.
+ 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<unsigned>*BitList;
+ Record *Rec;
+ SubClassRefTy *SubClassRef;
+ std::vector<SubClassRefTy> *SubClassList;
+ std::vector<std::pair<Init*, std::string> > *DagValueList;
+};
+
+%token INT BIT STRING BITS LIST CODE DAG CLASS DEF FIELD LET IN
+%token <IntVal> INTVAL
+%token <StrVal> ID VARNAME STRVAL CODEFRAGMENT
+
+%type <Ty> Type
+%type <Rec> ClassInst DefInst Object ObjectBody ClassID
+
+%type <SubClassRef> SubClassRef
+%type <SubClassList> ClassList ClassListNE
+%type <IntVal> OptPrefix
+%type <Initializer> Value OptValue
+%type <DagValueList> DagArgList DagArgListNE
+%type <FieldList> ValueList ValueListNE
+%type <BitList> BitList OptBitList RBitList
+%type <StrVal> Declaration OptID OptVarName
+
+%start File
+%%
+
+ClassID : ID {
+ $$ = Records.getClass(*$1);
+ if ($$ == 0) {
+ err() << "Couldn't find class '" << *$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 '<' Type '>' { // list<x> type
+ $$ = new ListRecTy($3);
+ } | CODE { // code type
+ $$ = new CodeRecTy();
+ } | DAG { // dag type
+ $$ = new DagRecTy();
+ } | 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;
+ } | CODEFRAGMENT {
+ $$ = new CodeInit(*$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 ? CurRec->getValue(*$1) : 0)) {
+ $$ = 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;
+ } | '[' ValueList ']' {
+ $$ = new ListInit(*$2);
+ delete $2;
+ } | Value '.' ID {
+ if (!$1->getFieldType(*$3)) {
+ err() << "Cannot access field '" << *$3 << "' of value '" << *$1 << "!\n";
+ abort();
+ }
+ $$ = new FieldInit($1, *$3);
+ delete $3;
+ } | '(' ID DagArgList ')' {
+ Record *D = Records.getDef(*$2);
+ if (D == 0) {
+ err() << "Invalid def '" << *$2 << "'!\n";
+ abort();
+ }
+ $$ = new DagInit(D, *$3);
+ delete $2; delete $3;
+ };
+
+OptVarName : /* empty */ {
+ $$ = new std::string();
+ }
+ | ':' VARNAME {
+ $$ = $2;
+ };
+
+DagArgListNE : Value OptVarName {
+ $$ = new std::vector<std::pair<Init*, std::string> >();
+ $$->push_back(std::make_pair($1, *$2));
+ delete $2;
+ }
+ | DagArgListNE ',' Value OptVarName {
+ $1->push_back(std::make_pair($3, *$4));
+ delete $4;
+ $$ = $1;
+ };
+
+DagArgList : /*empty*/ {
+ $$ = new std::vector<std::pair<Init*, std::string> >();
+ }
+ | DagArgListNE { $$ = $1; };
+
+
+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;
+} | LET 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;
+
+OptID : ID { $$ = $1; } | /*empty*/ { $$ = new std::string(); };
+
+ObjectBody : OptID {
+ static unsigned AnonCounter = 0;
+ if ($1->empty())
+ *$1 = "anonymous."+utostr(AnonCounter++);
+ 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 the template arg values for the class
+ delete (*$4)[i].second;
+ }
+
+ // Process any variables on the set stack...
+ for (unsigned i = 0, e = LetStack.size(); i != e; ++i)
+ for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j)
+ setValue(LetStack[i][j].Name,
+ LetStack[i][j].HasBits ? &LetStack[i][j].Bits : 0,
+ LetStack[i][j].Value);
+ } Body {
+ CurRec->resolveReferences();
+
+ // Now that all of the references have been resolved, we can delete template
+ // arguments for superclasses, so they don't pollute our record, and so that
+ // their names won't conflict with later uses of the name...
+ for (unsigned i = 0, e = $4->size(); i != e; ++i) {
+ Record *SuperClass = (*$4)[i].first;
+ for (unsigned i = 0, e = SuperClass->getTemplateArgs().size(); i != e; ++i)
+ CurRec->removeValue(SuperClass->getTemplateArgs()[i]);
+ }
+ delete $4; // Delete the class list...
+
+ $$ = 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 {
+ if (!$2->getTemplateArgs().empty()) {
+ err() << "Def '" << $2->getName()
+ << "' is not permitted to have template arguments!\n";
+ abort();
+ }
+ // 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;
+
+LETItem : ID OptBitList '=' Value {
+ LetStack.back().push_back(LetRecord(*$1, $2, $4));
+ delete $1; delete $2;
+};
+
+LETList : LETItem | LETList ',' LETItem;
+
+// LETCommand - A 'LET' statement start...
+LETCommand : LET { LetStack.push_back(std::vector<LetRecord>()); } LETList IN;
+
+// Support Set commands wrapping objects... both with and without braces.
+Object : LETCommand '{' ObjectList '}' {
+ LetStack.pop_back();
+ }
+ | LETCommand Object {
+ LetStack.pop_back();
+ };
+
+ObjectList : Object {} | ObjectList Object {};
+
+File : ObjectList {};
+
+%%
+
+int yyerror(const char *ErrorMsg) {
+ err() << "Error parsing: " << ErrorMsg << "\n";
+ abort();
+}
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp
new file mode 100644
index 00000000000..c794cd04418
--- /dev/null
+++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -0,0 +1,160 @@
+//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===//
+//
+// This tablegen backend is responsible for emitting a description of the target
+// instruction set for the code generator.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InstrInfoEmitter.h"
+#include "CodeGenWrappers.h"
+#include "Record.h"
+
+// runEnums - Print out enum values for all of the instructions.
+void InstrInfoEmitter::runEnums(std::ostream &OS) {
+ std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
+
+ if (Insts.size() == 0)
+ throw std::string("No 'Instruction' subclasses defined!");
+
+ std::string Namespace = Insts[0]->getValueAsString("Namespace");
+
+ EmitSourceFileHeader("Target Instruction Enum Values", OS);
+
+ if (!Namespace.empty())
+ OS << "namespace " << Namespace << " {\n";
+ OS << " enum {\n";
+
+ CodeGenTarget Target;
+
+ // We must emit the PHI opcode first...
+ Record *InstrInfo = Target.getInstructionSet();
+ Record *PHI = InstrInfo->getValueAsDef("PHIInst");
+
+ OS << " " << PHI->getName() << ", \t// 0 (fixed for all targets)\n";
+
+ // Print out the rest of the instructions now...
+ for (unsigned i = 0, e = Insts.size(); i != e; ++i)
+ if (Insts[i] != PHI)
+ OS << " " << Insts[i]->getName() << ", \t// " << i+1 << "\n";
+
+ OS << " };\n";
+ if (!Namespace.empty())
+ OS << "}\n";
+}
+
+void InstrInfoEmitter::printDefList(ListInit *LI, const std::string &Name,
+ std::ostream &OS) const {
+ OS << "static const unsigned " << Name << "[] = { ";
+ for (unsigned j = 0, e = LI->getSize(); j != e; ++j)
+ if (DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(j)))
+ OS << getQualifiedName(DI->getDef()) << ", ";
+ else
+ throw "Illegal value in '" + Name + "' list!";
+ OS << "0 };\n";
+}
+
+
+// run - Emit the main instruction description records for the target...
+void InstrInfoEmitter::run(std::ostream &OS) {
+ EmitSourceFileHeader("Target Instruction Descriptors", OS);
+ CodeGenTarget Target;
+ const std::string &TargetName = Target.getName();
+ Record *InstrInfo = Target.getInstructionSet();
+ Record *PHI = InstrInfo->getValueAsDef("PHIInst");
+
+ std::vector<Record*> Instructions =
+ Records.getAllDerivedDefinitions("Instruction");
+
+ // Emit all of the instruction's implicit uses and defs...
+ for (unsigned i = 0, e = Instructions.size(); i != e; ++i) {
+ Record *Inst = Instructions[i];
+ ListInit *LI = Inst->getValueAsListInit("Uses");
+ if (LI->getSize()) printDefList(LI, Inst->getName()+"ImpUses", OS);
+ LI = Inst->getValueAsListInit("Defs");
+ if (LI->getSize()) printDefList(LI, Inst->getName()+"ImpDefs", OS);
+ }
+
+ OS << "\nstatic const TargetInstrDescriptor " << TargetName
+ << "Insts[] = {\n";
+ emitRecord(PHI, 0, InstrInfo, OS);
+
+ for (unsigned i = 0, e = Instructions.size(); i != e; ++i)
+ if (Instructions[i] != PHI)
+ emitRecord(Instructions[i], i+1, InstrInfo, OS);
+ OS << "};\n";
+}
+
+void InstrInfoEmitter::emitRecord(Record *R, unsigned Num, Record *InstrInfo,
+ std::ostream &OS) {
+ OS << " { \"" << R->getValueAsString("Name")
+ << "\",\t-1, -1, 0, false, 0, 0, 0, 0";
+
+ // Emit all of the target indepedent flags...
+ if (R->getValueAsBit("isReturn")) OS << "|M_RET_FLAG";
+ if (R->getValueAsBit("isBranch")) OS << "|M_BRANCH_FLAG";
+ if (R->getValueAsBit("isCall" )) OS << "|M_CALL_FLAG";
+ if (R->getValueAsBit("isTwoAddress")) OS << "|M_2_ADDR_FLAG";
+ if (R->getValueAsBit("isTerminator")) OS << "|M_TERMINATOR_FLAG";
+ OS << ", 0";
+
+ // Emit all of the target-specific flags...
+ ListInit *LI = InstrInfo->getValueAsListInit("TSFlagsFields");
+ ListInit *Shift = InstrInfo->getValueAsListInit("TSFlagsShifts");
+ if (LI->getSize() != Shift->getSize())
+ throw "Lengths of " + InstrInfo->getName() +
+ ":(TargetInfoFields, TargetInfoPositions) must be equal!";
+
+ for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
+ emitShiftedValue(R, dynamic_cast<StringInit*>(LI->getElement(i)),
+ dynamic_cast<IntInit*>(Shift->getElement(i)), OS);
+
+ OS << ", ";
+
+ // Emit the implicit uses and defs lists...
+ LI = R->getValueAsListInit("Uses");
+ if (!LI->getSize())
+ OS << "0, ";
+ else
+ OS << R->getName() << "ImpUses, ";
+
+ LI = R->getValueAsListInit("Defs");
+ if (!LI->getSize())
+ OS << "0 ";
+ else
+ OS << R->getName() << "ImpDefs ";
+
+ OS << " }, // Inst #" << Num << " = " << R->getName() << "\n";
+}
+
+void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val,
+ IntInit *ShiftInt, std::ostream &OS) {
+ if (Val == 0 || ShiftInt == 0)
+ throw std::string("Illegal value or shift amount in TargetInfo*!");
+ RecordVal *RV = R->getValue(Val->getValue());
+ int Shift = ShiftInt->getValue();
+
+ if (RV == 0 || RV->getValue() == 0)
+ throw R->getName() + " doesn't have a field named '" + Val->getValue()+"'!";
+
+ Init *Value = RV->getValue();
+ if (BitInit *BI = dynamic_cast<BitInit*>(Value)) {
+ if (BI->getValue()) OS << "|(1<<" << Shift << ")";
+ return;
+ } else if (BitsInit *BI = dynamic_cast<BitsInit*>(Value)) {
+ // Convert the Bits to an integer to print...
+ Init *I = BI->convertInitializerTo(new IntRecTy());
+ if (I)
+ if (IntInit *II = dynamic_cast<IntInit*>(I)) {
+ if (II->getValue())
+ OS << "|(" << II->getValue() << "<<" << Shift << ")";
+ return;
+ }
+
+ } else if (IntInit *II = dynamic_cast<IntInit*>(Value)) {
+ if (II->getValue()) OS << "|(" << II->getValue() << "<<" << Shift << ")";
+ return;
+ }
+
+ std::cerr << "Unhandled initializer: " << *Val << "\n";
+ throw "In record '" + R->getName() + "' for TSFlag emission.";
+}
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.h b/llvm/utils/TableGen/InstrInfoEmitter.h
new file mode 100644
index 00000000000..400c0db16c6
--- /dev/null
+++ b/llvm/utils/TableGen/InstrInfoEmitter.h
@@ -0,0 +1,34 @@
+//===- InstrInfoEmitter.h - Generate a Instruction Set Desc. ----*- C++ -*-===//
+//
+// This tablegen backend is responsible for emitting a description of the target
+// instruction set for the code generator.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef INSTRINFO_EMITTER_H
+#define INSTRINFO_EMITTER_H
+
+#include "TableGenBackend.h"
+class StringInit;
+class IntInit;
+class ListInit;
+
+class InstrInfoEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+public:
+ InstrInfoEmitter(RecordKeeper &R) : Records(R) {}
+
+ // run - Output the instruction set description, returning true on failure.
+ void run(std::ostream &OS);
+
+ // runEnums - Print out enum values for all of the instructions.
+ void runEnums(std::ostream &OS);
+private:
+ void printDefList(ListInit *LI, const std::string &Name,
+ std::ostream &OS) const;
+ void emitRecord(Record *R, unsigned Num, Record *InstrInfo, std::ostream &OS);
+ void emitShiftedValue(Record *R, StringInit *Val, IntInit *Shift,
+ std::ostream &OS);
+};
+
+#endif
diff --git a/llvm/utils/TableGen/InstrSelectorEmitter.cpp b/llvm/utils/TableGen/InstrSelectorEmitter.cpp
new file mode 100644
index 00000000000..a3c535cad4e
--- /dev/null
+++ b/llvm/utils/TableGen/InstrSelectorEmitter.cpp
@@ -0,0 +1,1287 @@
+//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===//
+//
+// This tablegen backend is responsible for emitting a description of the target
+// instruction set for the code generator.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InstrSelectorEmitter.h"
+#include "CodeGenWrappers.h"
+#include "Record.h"
+#include "Support/Debug.h"
+#include "Support/StringExtras.h"
+#include <set>
+
+NodeType::ArgResultTypes NodeType::Translate(Record *R) {
+ const std::string &Name = R->getName();
+ if (Name == "DNVT_any") return Any;
+ if (Name == "DNVT_void") return Void;
+ if (Name == "DNVT_val" ) return Val;
+ if (Name == "DNVT_arg0") return Arg0;
+ if (Name == "DNVT_arg1") return Arg1;
+ if (Name == "DNVT_ptr" ) return Ptr;
+ if (Name == "DNVT_i8" ) return I8;
+ throw "Unknown DagNodeValType '" + Name + "'!";
+}
+
+
+//===----------------------------------------------------------------------===//
+// TreePatternNode implementation
+//
+
+/// getValueRecord - Returns the value of this tree node as a record. For now
+/// we only allow DefInit's as our leaf values, so this is used.
+Record *TreePatternNode::getValueRecord() const {
+ DefInit *DI = dynamic_cast<DefInit*>(getValue());
+ assert(DI && "Instruction Selector does not yet support non-def leaves!");
+ return DI->getDef();
+}
+
+
+// updateNodeType - Set the node type of N to VT if VT contains information. If
+// N already contains a conflicting type, then throw an exception
+//
+bool TreePatternNode::updateNodeType(MVT::ValueType VT,
+ const std::string &RecName) {
+ if (VT == MVT::Other || getType() == VT) return false;
+ if (getType() == MVT::Other) {
+ setType(VT);
+ return true;
+ }
+
+ throw "Type inferfence contradiction found for pattern " + RecName;
+}
+
+/// InstantiateNonterminals - If this pattern refers to any nonterminals which
+/// are not themselves completely resolved, clone the nonterminal and resolve it
+/// with the using context we provide.
+///
+void TreePatternNode::InstantiateNonterminals(InstrSelectorEmitter &ISE) {
+ if (!isLeaf()) {
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ getChild(i)->InstantiateNonterminals(ISE);
+ return;
+ }
+
+ // If this is a leaf, it might be a reference to a nonterminal! Check now.
+ Record *R = getValueRecord();
+ if (R->isSubClassOf("Nonterminal")) {
+ Pattern *NT = ISE.getPattern(R);
+ if (!NT->isResolved()) {
+ // We found an unresolved nonterminal reference. Ask the ISE to clone
+ // it for us, then update our reference to the fresh, new, resolved,
+ // nonterminal.
+
+ Value = new DefInit(ISE.InstantiateNonterminal(NT, getType()));
+ }
+ }
+}
+
+
+/// clone - Make a copy of this tree and all of its children.
+///
+TreePatternNode *TreePatternNode::clone() const {
+ TreePatternNode *New;
+ if (isLeaf()) {
+ New = new TreePatternNode(Value);
+ } else {
+ std::vector<std::pair<TreePatternNode*, std::string> > CChildren;
+ CChildren.reserve(Children.size());
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ CChildren.push_back(std::make_pair(getChild(i)->clone(),getChildName(i)));
+ New = new TreePatternNode(Operator, CChildren);
+ }
+ New->setType(Type);
+ return New;
+}
+
+std::ostream &operator<<(std::ostream &OS, const TreePatternNode &N) {
+ if (N.isLeaf())
+ return OS << N.getType() << ":" << *N.getValue();
+ OS << "(" << N.getType() << ":";
+ OS << N.getOperator()->getName();
+
+ if (N.getNumChildren() != 0) {
+ OS << " " << *N.getChild(0);
+ for (unsigned i = 1, e = N.getNumChildren(); i != e; ++i)
+ OS << ", " << *N.getChild(i);
+ }
+ return OS << ")";
+}
+
+void TreePatternNode::dump() const { std::cerr << *this; }
+
+//===----------------------------------------------------------------------===//
+// Pattern implementation
+//
+
+// Parse the specified DagInit into a TreePattern which we can use.
+//
+Pattern::Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
+ InstrSelectorEmitter &ise)
+ : PTy(pty), ResultNode(0), TheRecord(TheRec), ISE(ise) {
+
+ // First, parse the pattern...
+ Tree = ParseTreePattern(RawPat);
+
+ // Run the type-inference engine...
+ InferAllTypes();
+
+ if (PTy == Instruction || PTy == Expander) {
+ // Check to make sure there is not any unset types in the tree pattern...
+ if (!isResolved()) {
+ std::cerr << "In pattern: " << *Tree << "\n";
+ error("Could not infer all types!");
+ }
+
+ // Check to see if we have a top-level (set) of a register.
+ if (Tree->getOperator()->getName() == "set") {
+ assert(Tree->getNumChildren() == 2 && "Set with != 2 arguments?");
+ if (!Tree->getChild(0)->isLeaf())
+ error("Arg #0 of set should be a register or register class!");
+ ResultNode = Tree->getChild(0);
+ ResultName = Tree->getChildName(0);
+ Tree = Tree->getChild(1);
+ }
+ }
+
+ calculateArgs(Tree, "");
+}
+
+void Pattern::error(const std::string &Msg) const {
+ std::string M = "In ";
+ switch (PTy) {
+ case Nonterminal: M += "nonterminal "; break;
+ case Instruction: M += "instruction "; break;
+ case Expander : M += "expander "; break;
+ }
+ throw M + TheRecord->getName() + ": " + Msg;
+}
+
+/// calculateArgs - Compute the list of all of the arguments to this pattern,
+/// which are the non-void leaf nodes in this pattern.
+///
+void Pattern::calculateArgs(TreePatternNode *N, const std::string &Name) {
+ if (N->isLeaf() || N->getNumChildren() == 0) {
+ if (N->getType() != MVT::isVoid)
+ Args.push_back(std::make_pair(N, Name));
+ } else {
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+ calculateArgs(N->getChild(i), N->getChildName(i));
+ }
+}
+
+/// getIntrinsicType - Check to see if the specified record has an intrinsic
+/// type which should be applied to it. This infer the type of register
+/// references from the register file information, for example.
+///
+MVT::ValueType Pattern::getIntrinsicType(Record *R) const {
+ // Check to see if this is a register or a register class...
+ if (R->isSubClassOf("RegisterClass"))
+ return getValueType(R->getValueAsDef("RegType"));
+ else if (R->isSubClassOf("Nonterminal"))
+ return ISE.ReadNonterminal(R)->getTree()->getType();
+ else if (R->isSubClassOf("Register")) {
+ std::cerr << "WARNING: Explicit registers not handled yet!\n";
+ return MVT::Other;
+ }
+
+ error("Unknown value used: " + R->getName());
+ return MVT::Other;
+}
+
+TreePatternNode *Pattern::ParseTreePattern(DagInit *Dag) {
+ Record *Operator = Dag->getNodeType();
+
+ if (Operator->isSubClassOf("ValueType")) {
+ // If the operator is a ValueType, then this must be "type cast" of a leaf
+ // node.
+ if (Dag->getNumArgs() != 1)
+ error("Type cast only valid for a leaf node!");
+
+ Init *Arg = Dag->getArg(0);
+ TreePatternNode *New;
+ if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
+ New = new TreePatternNode(DI);
+ // If it's a regclass or something else known, set the type.
+ New->setType(getIntrinsicType(DI->getDef()));
+ } else if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
+ New = ParseTreePattern(DI);
+ } else {
+ Arg->dump();
+ error("Unknown leaf value for tree pattern!");
+ return 0;
+ }
+
+ // Apply the type cast...
+ New->updateNodeType(getValueType(Operator), TheRecord->getName());
+ return New;
+ }
+
+ if (!ISE.getNodeTypes().count(Operator))
+ error("Unrecognized node '" + Operator->getName() + "'!");
+
+ std::vector<std::pair<TreePatternNode*, std::string> > Children;
+
+ for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
+ Init *Arg = Dag->getArg(i);
+ if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
+ Children.push_back(std::make_pair(ParseTreePattern(DI),
+ Dag->getArgName(i)));
+ } else if (DefInit *DefI = dynamic_cast<DefInit*>(Arg)) {
+ Record *R = DefI->getDef();
+ // Direct reference to a leaf DagNode? Turn it into a DagNode if its own.
+ if (R->isSubClassOf("DagNode")) {
+ Dag->setArg(i, new DagInit(R,
+ std::vector<std::pair<Init*, std::string> >()));
+ --i; // Revisit this node...
+ } else {
+ Children.push_back(std::make_pair(new TreePatternNode(DefI),
+ Dag->getArgName(i)));
+ // If it's a regclass or something else known, set the type.
+ Children.back().first->setType(getIntrinsicType(R));
+ }
+ } else {
+ Arg->dump();
+ error("Unknown leaf value for tree pattern!");
+ }
+ }
+
+ return new TreePatternNode(Operator, Children);
+}
+
+void Pattern::InferAllTypes() {
+ bool MadeChange, AnyUnset;
+ do {
+ MadeChange = false;
+ AnyUnset = InferTypes(Tree, MadeChange);
+ } while ((AnyUnset || MadeChange) && !(AnyUnset && !MadeChange));
+ Resolved = !AnyUnset;
+}
+
+
+// InferTypes - Perform type inference on the tree, returning true if there
+// are any remaining untyped nodes and setting MadeChange if any changes were
+// made.
+bool Pattern::InferTypes(TreePatternNode *N, bool &MadeChange) {
+ if (N->isLeaf()) return N->getType() == MVT::Other;
+
+ bool AnyUnset = false;
+ Record *Operator = N->getOperator();
+ const NodeType &NT = ISE.getNodeType(Operator);
+
+ // Check to see if we can infer anything about the argument types from the
+ // return types...
+ if (N->getNumChildren() != NT.ArgTypes.size())
+ error("Incorrect number of children for " + Operator->getName() + " node!");
+
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = N->getChild(i);
+ AnyUnset |= InferTypes(Child, MadeChange);
+
+ switch (NT.ArgTypes[i]) {
+ case NodeType::Any: break;
+ case NodeType::I8:
+ MadeChange |= Child->updateNodeType(MVT::i1, TheRecord->getName());
+ break;
+ case NodeType::Arg0:
+ MadeChange |= Child->updateNodeType(N->getChild(0)->getType(),
+ TheRecord->getName());
+ break;
+ case NodeType::Arg1:
+ MadeChange |= Child->updateNodeType(N->getChild(1)->getType(),
+ TheRecord->getName());
+ break;
+ case NodeType::Val:
+ if (Child->getType() == MVT::isVoid)
+ error("Inferred a void node in an illegal place!");
+ break;
+ case NodeType::Ptr:
+ MadeChange |= Child->updateNodeType(ISE.getTarget().getPointerType(),
+ TheRecord->getName());
+ break;
+ case NodeType::Void:
+ MadeChange |= Child->updateNodeType(MVT::isVoid, TheRecord->getName());
+ break;
+ default: assert(0 && "Invalid argument ArgType!");
+ }
+ }
+
+ // See if we can infer anything about the return type now...
+ switch (NT.ResultType) {
+ case NodeType::Any: break;
+ case NodeType::Void:
+ MadeChange |= N->updateNodeType(MVT::isVoid, TheRecord->getName());
+ break;
+ case NodeType::I8:
+ MadeChange |= N->updateNodeType(MVT::i1, TheRecord->getName());
+ break;
+ case NodeType::Arg0:
+ MadeChange |= N->updateNodeType(N->getChild(0)->getType(),
+ TheRecord->getName());
+ break;
+ case NodeType::Arg1:
+ MadeChange |= N->updateNodeType(N->getChild(1)->getType(),
+ TheRecord->getName());
+ break;
+ case NodeType::Ptr:
+ MadeChange |= N->updateNodeType(ISE.getTarget().getPointerType(),
+ TheRecord->getName());
+ break;
+ case NodeType::Val:
+ if (N->getType() == MVT::isVoid)
+ error("Inferred a void node in an illegal place!");
+ break;
+ default:
+ assert(0 && "Unhandled type constraint!");
+ break;
+ }
+
+ return AnyUnset | N->getType() == MVT::Other;
+}
+
+/// clone - This method is used to make an exact copy of the current pattern,
+/// then change the "TheRecord" instance variable to the specified record.
+///
+Pattern *Pattern::clone(Record *R) const {
+ assert(PTy == Nonterminal && "Can only clone nonterminals");
+ return new Pattern(Tree->clone(), R, Resolved, ISE);
+}
+
+
+
+std::ostream &operator<<(std::ostream &OS, const Pattern &P) {
+ switch (P.getPatternType()) {
+ case Pattern::Nonterminal: OS << "Nonterminal pattern "; break;
+ case Pattern::Instruction: OS << "Instruction pattern "; break;
+ case Pattern::Expander: OS << "Expander pattern "; break;
+ }
+
+ OS << P.getRecord()->getName() << ":\t";
+
+ if (Record *Result = P.getResult())
+ OS << Result->getName() << " = ";
+ OS << *P.getTree();
+
+ if (!P.isResolved())
+ OS << " [not completely resolved]";
+ return OS;
+}
+
+void Pattern::dump() const { std::cerr << *this; }
+
+
+
+/// getSlotName - If this is a leaf node, return the slot name that the operand
+/// will update.
+std::string Pattern::getSlotName() const {
+ if (getPatternType() == Pattern::Nonterminal) {
+ // Just use the nonterminal name, which will already include the type if
+ // it has been cloned.
+ return getRecord()->getName();
+ } else {
+ std::string SlotName;
+ if (getResult())
+ SlotName = getResult()->getName()+"_";
+ else
+ SlotName = "Void_";
+ return SlotName + getName(getTree()->getType());
+ }
+}
+
+/// getSlotName - If this is a leaf node, return the slot name that the
+/// operand will update.
+std::string Pattern::getSlotName(Record *R) {
+ if (R->isSubClassOf("Nonterminal")) {
+ // Just use the nonterminal name, which will already include the type if
+ // it has been cloned.
+ return R->getName();
+ } else if (R->isSubClassOf("RegisterClass")) {
+ MVT::ValueType Ty = getValueType(R->getValueAsDef("RegType"));
+ return R->getName() + "_" + getName(Ty);
+ } else {
+ assert(0 && "Don't know how to get a slot name for this!");
+ }
+ return "";
+}
+
+//===----------------------------------------------------------------------===//
+// PatternOrganizer implementation
+//
+
+/// addPattern - Add the specified pattern to the appropriate location in the
+/// collection.
+void PatternOrganizer::addPattern(Pattern *P) {
+ NodesForSlot &Nodes = AllPatterns[P->getSlotName()];
+ if (!P->getTree()->isLeaf())
+ Nodes[P->getTree()->getOperator()].push_back(P);
+ else {
+ // Right now we only support DefInit's with node types...
+ Nodes[P->getTree()->getValueRecord()].push_back(P);
+ }
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// InstrSelectorEmitter implementation
+//
+
+/// ReadNodeTypes - Read in all of the node types in the current RecordKeeper,
+/// turning them into the more accessible NodeTypes data structure.
+///
+void InstrSelectorEmitter::ReadNodeTypes() {
+ std::vector<Record*> Nodes = Records.getAllDerivedDefinitions("DagNode");
+ DEBUG(std::cerr << "Getting node types: ");
+ for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
+ Record *Node = Nodes[i];
+
+ // Translate the return type...
+ NodeType::ArgResultTypes RetTy =
+ NodeType::Translate(Node->getValueAsDef("RetType"));
+
+ // Translate the arguments...
+ ListInit *Args = Node->getValueAsListInit("ArgTypes");
+ std::vector<NodeType::ArgResultTypes> ArgTypes;
+
+ for (unsigned a = 0, e = Args->getSize(); a != e; ++a) {
+ if (DefInit *DI = dynamic_cast<DefInit*>(Args->getElement(a)))
+ ArgTypes.push_back(NodeType::Translate(DI->getDef()));
+ else
+ throw "In node " + Node->getName() + ", argument is not a Def!";
+
+ if (a == 0 && ArgTypes.back() == NodeType::Arg0)
+ throw "In node " + Node->getName() + ", arg 0 cannot have type 'arg0'!";
+ if (a == 1 && ArgTypes.back() == NodeType::Arg1)
+ throw "In node " + Node->getName() + ", arg 1 cannot have type 'arg1'!";
+ }
+ if ((RetTy == NodeType::Arg0 && Args->getSize() == 0) ||
+ (RetTy == NodeType::Arg1 && Args->getSize() < 2))
+ throw "In node " + Node->getName() +
+ ", invalid return type for node with this many operands!";
+
+ // Add the node type mapping now...
+ NodeTypes[Node] = NodeType(RetTy, ArgTypes);
+ DEBUG(std::cerr << Node->getName() << ", ");
+ }
+ DEBUG(std::cerr << "DONE!\n");
+}
+
+Pattern *InstrSelectorEmitter::ReadNonterminal(Record *R) {
+ Pattern *&P = Patterns[R];
+ if (P) return P; // Don't reread it!
+
+ DagInit *DI = R->getValueAsDag("Pattern");
+ P = new Pattern(Pattern::Nonterminal, DI, R, *this);
+ DEBUG(std::cerr << "Parsed " << *P << "\n");
+ return P;
+}
+
+
+// ReadNonTerminals - Read in all nonterminals and incorporate them into our
+// pattern database.
+void InstrSelectorEmitter::ReadNonterminals() {
+ std::vector<Record*> NTs = Records.getAllDerivedDefinitions("Nonterminal");
+ for (unsigned i = 0, e = NTs.size(); i != e; ++i)
+ ReadNonterminal(NTs[i]);
+}
+
+
+/// ReadInstructionPatterns - Read in all subclasses of Instruction, and process
+/// those with a useful Pattern field.
+///
+void InstrSelectorEmitter::ReadInstructionPatterns() {
+ std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
+ for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
+ Record *Inst = Insts[i];
+ if (DagInit *DI = dynamic_cast<DagInit*>(Inst->getValueInit("Pattern"))) {
+ Patterns[Inst] = new Pattern(Pattern::Instruction, DI, Inst, *this);
+ DEBUG(std::cerr << "Parsed " << *Patterns[Inst] << "\n");
+ }
+ }
+}
+
+/// ReadExpanderPatterns - Read in all expander patterns...
+///
+void InstrSelectorEmitter::ReadExpanderPatterns() {
+ std::vector<Record*> Expanders = Records.getAllDerivedDefinitions("Expander");
+ for (unsigned i = 0, e = Expanders.size(); i != e; ++i) {
+ Record *Expander = Expanders[i];
+ DagInit *DI = Expander->getValueAsDag("Pattern");
+ Patterns[Expander] = new Pattern(Pattern::Expander, DI, Expander, *this);
+ DEBUG(std::cerr << "Parsed " << *Patterns[Expander] << "\n");
+ }
+}
+
+
+// InstantiateNonterminals - Instantiate any unresolved nonterminals with
+// information from the context that they are used in.
+//
+void InstrSelectorEmitter::InstantiateNonterminals() {
+ DEBUG(std::cerr << "Instantiating nonterminals:\n");
+ for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(),
+ E = Patterns.end(); I != E; ++I)
+ if (I->second->isResolved())
+ I->second->InstantiateNonterminals();
+}
+
+/// InstantiateNonterminal - This method takes the nonterminal specified by
+/// NT, which should not be completely resolved, clones it, applies ResultTy
+/// to its root, then runs the type inference stuff on it. This should
+/// produce a newly resolved nonterminal, which we make a record for and
+/// return. To be extra fancy and efficient, this only makes one clone for
+/// each type it is instantiated with.
+Record *InstrSelectorEmitter::InstantiateNonterminal(Pattern *NT,
+ MVT::ValueType ResultTy) {
+ assert(!NT->isResolved() && "Nonterminal is already resolved!");
+
+ // Check to see if we have already instantiated this pair...
+ Record* &Slot = InstantiatedNTs[std::make_pair(NT, ResultTy)];
+ if (Slot) return Slot;
+
+ Record *New = new Record(NT->getRecord()->getName()+"_"+getName(ResultTy));
+
+ // Copy over the superclasses...
+ const std::vector<Record*> &SCs = NT->getRecord()->getSuperClasses();
+ for (unsigned i = 0, e = SCs.size(); i != e; ++i)
+ New->addSuperClass(SCs[i]);
+
+ DEBUG(std::cerr << " Nonterminal '" << NT->getRecord()->getName()
+ << "' for type '" << getName(ResultTy) << "', producing '"
+ << New->getName() << "'\n");
+
+ // Copy the pattern...
+ Pattern *NewPat = NT->clone(New);
+
+ // Apply the type to the root...
+ NewPat->getTree()->updateNodeType(ResultTy, New->getName());
+
+ // Infer types...
+ NewPat->InferAllTypes();
+
+ // Make sure everything is good to go now...
+ if (!NewPat->isResolved())
+ NewPat->error("Instantiating nonterminal did not resolve all types!");
+
+ // Add the pattern to the patterns map, add the record to the RecordKeeper,
+ // return the new record.
+ Patterns[New] = NewPat;
+ Records.addDef(New);
+ return Slot = New;
+}
+
+// CalculateComputableValues - Fill in the ComputableValues map through
+// analysis of the patterns we are playing with.
+void InstrSelectorEmitter::CalculateComputableValues() {
+ // Loop over all of the patterns, adding them to the ComputableValues map
+ for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(),
+ E = Patterns.end(); I != E; ++I)
+ if (I->second->isResolved()) {
+ // We don't want to add patterns like R32 = R32. This is a hack working
+ // around a special case of a general problem, but for now we explicitly
+ // forbid these patterns. They can never match anyway.
+ Pattern *P = I->second;
+ if (!P->getResult() || !P->getTree()->isLeaf() ||
+ P->getResult() != P->getTree()->getValueRecord())
+ ComputableValues.addPattern(P);
+ }
+}
+
+#if 0
+// MoveIdenticalPatterns - Given a tree pattern 'P', move all of the tree
+// patterns which have the same top-level structure as P from the 'From' list to
+// the 'To' list.
+static void MoveIdenticalPatterns(TreePatternNode *P,
+ std::vector<std::pair<Pattern*, TreePatternNode*> > &From,
+ std::vector<std::pair<Pattern*, TreePatternNode*> > &To) {
+ assert(!P->isLeaf() && "All leaves are identical!");
+
+ const std::vector<TreePatternNode*> &PChildren = P->getChildren();
+ for (unsigned i = 0; i != From.size(); ++i) {
+ TreePatternNode *N = From[i].second;
+ assert(P->getOperator() == N->getOperator() &&"Differing operators?");
+ assert(PChildren.size() == N->getChildren().size() &&
+ "Nodes with different arity??");
+ bool isDifferent = false;
+ for (unsigned c = 0, e = PChildren.size(); c != e; ++c) {
+ TreePatternNode *PC = PChildren[c];
+ TreePatternNode *NC = N->getChild(c);
+ if (PC->isLeaf() != NC->isLeaf()) {
+ isDifferent = true;
+ break;
+ }
+
+ if (!PC->isLeaf()) {
+ if (PC->getOperator() != NC->getOperator()) {
+ isDifferent = true;
+ break;
+ }
+ } else { // It's a leaf!
+ if (PC->getValueRecord() != NC->getValueRecord()) {
+ isDifferent = true;
+ break;
+ }
+ }
+ }
+ // If it's the same as the reference one, move it over now...
+ if (!isDifferent) {
+ To.push_back(std::make_pair(From[i].first, N));
+ From.erase(From.begin()+i);
+ --i; // Don't skip an entry...
+ }
+ }
+}
+#endif
+
+static std::string getNodeName(Record *R) {
+ RecordVal *RV = R->getValue("EnumName");
+ if (RV)
+ if (Init *I = RV->getValue())
+ if (StringInit *SI = dynamic_cast<StringInit*>(I))
+ return SI->getValue();
+ return R->getName();
+}
+
+
+static void EmitPatternPredicates(TreePatternNode *Tree,
+ const std::string &VarName, std::ostream &OS){
+ OS << " && " << VarName << "->getNodeType() == ISD::"
+ << getNodeName(Tree->getOperator());
+
+ for (unsigned c = 0, e = Tree->getNumChildren(); c != e; ++c)
+ if (!Tree->getChild(c)->isLeaf())
+ EmitPatternPredicates(Tree->getChild(c),
+ VarName + "->getUse(" + utostr(c)+")", OS);
+}
+
+static void EmitPatternCosts(TreePatternNode *Tree, const std::string &VarName,
+ std::ostream &OS) {
+ for (unsigned c = 0, e = Tree->getNumChildren(); c != e; ++c)
+ if (Tree->getChild(c)->isLeaf()) {
+ OS << " + Match_"
+ << Pattern::getSlotName(Tree->getChild(c)->getValueRecord()) << "("
+ << VarName << "->getUse(" << c << "))";
+ } else {
+ EmitPatternCosts(Tree->getChild(c),
+ VarName + "->getUse(" + utostr(c) + ")", OS);
+ }
+}
+
+
+// EmitMatchCosters - Given a list of patterns, which all have the same root
+// pattern operator, emit an efficient decision tree to decide which one to
+// pick. This is structured this way to avoid reevaluations of non-obvious
+// subexpressions.
+void InstrSelectorEmitter::EmitMatchCosters(std::ostream &OS,
+ const std::vector<std::pair<Pattern*, TreePatternNode*> > &Patterns,
+ const std::string &VarPrefix,
+ unsigned IndentAmt) {
+ assert(!Patterns.empty() && "No patterns to emit matchers for!");
+ std::string Indent(IndentAmt, ' ');
+
+ // Load all of the operands of the root node into scalars for fast access
+ const NodeType &ONT = getNodeType(Patterns[0].second->getOperator());
+ for (unsigned i = 0, e = ONT.ArgTypes.size(); i != e; ++i)
+ OS << Indent << "SelectionDAGNode *" << VarPrefix << "_Op" << i
+ << " = N->getUse(" << i << ");\n";
+
+ // Compute the costs of computing the various nonterminals/registers, which
+ // are directly used at this level.
+ OS << "\n" << Indent << "// Operand matching costs...\n";
+ std::set<std::string> ComputedValues; // Avoid duplicate computations...
+ for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
+ TreePatternNode *NParent = Patterns[i].second;
+ for (unsigned c = 0, e = NParent->getNumChildren(); c != e; ++c) {
+ TreePatternNode *N = NParent->getChild(c);
+ if (N->isLeaf()) {
+ Record *VR = N->getValueRecord();
+ const std::string &LeafName = VR->getName();
+ std::string OpName = VarPrefix + "_Op" + utostr(c);
+ std::string ValName = OpName + "_" + LeafName + "_Cost";
+ if (!ComputedValues.count(ValName)) {
+ OS << Indent << "unsigned " << ValName << " = Match_"
+ << Pattern::getSlotName(VR) << "(" << OpName << ");\n";
+ ComputedValues.insert(ValName);
+ }
+ }
+ }
+ }
+ OS << "\n";
+
+
+ std::string LocCostName = VarPrefix + "_Cost";
+ OS << Indent << "unsigned " << LocCostName << "Min = ~0U >> 1;\n"
+ << Indent << "unsigned " << VarPrefix << "_PatternMin = NoMatchPattern;\n";
+
+#if 0
+ // Separate out all of the patterns into groups based on what their top-level
+ // signature looks like...
+ std::vector<std::pair<Pattern*, TreePatternNode*> > PatternsLeft(Patterns);
+ while (!PatternsLeft.empty()) {
+ // Process all of the patterns that have the same signature as the last
+ // element...
+ std::vector<std::pair<Pattern*, TreePatternNode*> > Group;
+ MoveIdenticalPatterns(PatternsLeft.back().second, PatternsLeft, Group);
+ assert(!Group.empty() && "Didn't at least pick the source pattern?");
+
+#if 0
+ OS << "PROCESSING GROUP:\n";
+ for (unsigned i = 0, e = Group.size(); i != e; ++i)
+ OS << " " << *Group[i].first << "\n";
+ OS << "\n\n";
+#endif
+
+ OS << Indent << "{ // ";
+
+ if (Group.size() != 1) {
+ OS << Group.size() << " size group...\n";
+ OS << Indent << " unsigned " << VarPrefix << "_Pattern = NoMatch;\n";
+ } else {
+ OS << *Group[0].first << "\n";
+ OS << Indent << " unsigned " << VarPrefix << "_Pattern = "
+ << Group[0].first->getRecord()->getName() << "_Pattern;\n";
+ }
+
+ OS << Indent << " unsigned " << LocCostName << " = ";
+ if (Group.size() == 1)
+ OS << "1;\n"; // Add inst cost if at individual rec
+ else
+ OS << "0;\n";
+
+ // Loop over all of the operands, adding in their costs...
+ TreePatternNode *N = Group[0].second;
+ const std::vector<TreePatternNode*> &Children = N->getChildren();
+
+ // If necessary, emit conditionals to check for the appropriate tree
+ // structure here...
+ for (unsigned i = 0, e = Children.size(); i != e; ++i) {
+ TreePatternNode *C = Children[i];
+ if (C->isLeaf()) {
+ // We already calculated the cost for this leaf, add it in now...
+ OS << Indent << " " << LocCostName << " += "
+ << VarPrefix << "_Op" << utostr(i) << "_"
+ << C->getValueRecord()->getName() << "_Cost;\n";
+ } else {
+ // If it's not a leaf, we have to check to make sure that the current
+ // node has the appropriate structure, then recurse into it...
+ OS << Indent << " if (" << VarPrefix << "_Op" << i
+ << "->getNodeType() == ISD::" << getNodeName(C->getOperator())
+ << ") {\n";
+ std::vector<std::pair<Pattern*, TreePatternNode*> > SubPatterns;
+ for (unsigned n = 0, e = Group.size(); n != e; ++n)
+ SubPatterns.push_back(std::make_pair(Group[n].first,
+ Group[n].second->getChild(i)));
+ EmitMatchCosters(OS, SubPatterns, VarPrefix+"_Op"+utostr(i),
+ IndentAmt + 4);
+ OS << Indent << " }\n";
+ }
+ }
+
+ // If the cost for this match is less than the minimum computed cost so far,
+ // update the minimum cost and selected pattern.
+ OS << Indent << " if (" << LocCostName << " < " << LocCostName << "Min) { "
+ << LocCostName << "Min = " << LocCostName << "; " << VarPrefix
+ << "_PatternMin = " << VarPrefix << "_Pattern; }\n";
+
+ OS << Indent << "}\n";
+ }
+#endif
+
+ for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
+ Pattern *P = Patterns[i].first;
+ TreePatternNode *PTree = P->getTree();
+ unsigned PatternCost = 1;
+
+ // Check to see if there are any non-leaf elements in the pattern. If so,
+ // we need to emit a predicate for this match.
+ bool AnyNonLeaf = false;
+ for (unsigned c = 0, e = PTree->getNumChildren(); c != e; ++c)
+ if (!PTree->getChild(c)->isLeaf()) {
+ AnyNonLeaf = true;
+ break;
+ }
+
+ if (!AnyNonLeaf) { // No predicate necessary, just output a scope...
+ OS << " {// " << *P << "\n";
+ } else {
+ // We need to emit a predicate to make sure the tree pattern matches, do
+ // so now...
+ OS << " if (1";
+ for (unsigned c = 0, e = PTree->getNumChildren(); c != e; ++c)
+ if (!PTree->getChild(c)->isLeaf())
+ EmitPatternPredicates(PTree->getChild(c),
+ VarPrefix + "_Op" + utostr(c), OS);
+
+ OS << ") {\n // " << *P << "\n";
+ }
+
+ OS << " unsigned PatCost = " << PatternCost;
+
+ for (unsigned c = 0, e = PTree->getNumChildren(); c != e; ++c)
+ if (PTree->getChild(c)->isLeaf()) {
+ OS << " + " << VarPrefix << "_Op" << c << "_"
+ << PTree->getChild(c)->getValueRecord()->getName() << "_Cost";
+ } else {
+ EmitPatternCosts(PTree->getChild(c), VarPrefix + "_Op" + utostr(c), OS);
+ }
+ OS << ";\n";
+ OS << " if (PatCost < MinCost) { MinCost = PatCost; Pattern = "
+ << P->getRecord()->getName() << "_Pattern; }\n"
+ << " }\n";
+ }
+}
+
+static void ReduceAllOperands(TreePatternNode *N, const std::string &Name,
+ std::vector<std::pair<TreePatternNode*, std::string> > &Operands,
+ std::ostream &OS) {
+ if (N->isLeaf()) {
+ // If this is a leaf, register or nonterminal reference...
+ std::string SlotName = Pattern::getSlotName(N->getValueRecord());
+ OS << " ReducedValue_" << SlotName << " *" << Name << "Val = Reduce_"
+ << SlotName << "(" << Name << ", MBB);\n";
+ Operands.push_back(std::make_pair(N, Name+"Val"));
+ } else if (N->getNumChildren() == 0) {
+ // This is a reference to a leaf tree node, like an immediate or frame
+ // index.
+ if (N->getType() != MVT::isVoid) {
+ std::string SlotName =
+ getNodeName(N->getOperator()) + "_" + getName(N->getType());
+ OS << " ReducedValue_" << SlotName << " *" << Name << "Val = "
+ << Name << "->getValue<ReducedValue_" << SlotName << ">(ISD::"
+ << SlotName << "_Slot);\n";
+ Operands.push_back(std::make_pair(N, Name+"Val"));
+ }
+ } else {
+ // Otherwise this is an interior node...
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
+ std::string ChildName = Name + "_Op" + utostr(i);
+ OS << " SelectionDAGNode *" << ChildName << " = " << Name
+ << "->getUse(" << i << ");\n";
+ ReduceAllOperands(N->getChild(i), ChildName, Operands, OS);
+ }
+ }
+}
+
+/// PrintExpanderOperand - Print out Arg as part of the instruction emission
+/// process for the expander pattern P. This argument may be referencing some
+/// values defined in P, or may just be physical register references or
+/// something like that. If PrintArg is true, we are printing out arguments to
+/// the BuildMI call. If it is false, we are printing the result register
+/// name.
+void InstrSelectorEmitter::PrintExpanderOperand(Init *Arg,
+ const std::string &NameVar,
+ TreePatternNode *ArgDeclNode,
+ Pattern *P, bool PrintArg,
+ std::ostream &OS) {
+ if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
+ Record *Arg = DI->getDef();
+ if (!ArgDeclNode->isLeaf() && ArgDeclNode->getNumChildren() != 0)
+ P->error("Expected leaf node as argument!");
+ Record *ArgDecl = ArgDeclNode->isLeaf() ? ArgDeclNode->getValueRecord() :
+ ArgDeclNode->getOperator();
+ if (Arg->isSubClassOf("Register")) {
+ // This is a physical register reference... make sure that the instruction
+ // requested a register!
+ if (!ArgDecl->isSubClassOf("RegisterClass"))
+ P->error("Argument mismatch for instruction pattern!");
+
+ // FIXME: This should check to see if the register is in the specified
+ // register class!
+ if (PrintArg) OS << ".addReg(";
+ OS << getQualifiedName(Arg);
+ if (PrintArg) OS << ")";
+ return;
+ } else if (Arg->isSubClassOf("RegisterClass")) {
+ // If this is a symbolic register class reference, we must be using a
+ // named value.
+ if (NameVar.empty()) P->error("Did not specify WHICH register to pass!");
+ if (Arg != ArgDecl) P->error("Instruction pattern mismatch!");
+
+ if (PrintArg) OS << ".addReg(";
+ OS << NameVar;
+ if (PrintArg) OS << ")";
+ return;
+ } else if (Arg->getName() == "frameidx") {
+ if (!PrintArg) P->error("Cannot define a new frameidx value!");
+ OS << ".addFrameIndex(" << NameVar << ")";
+ return;
+ } else if (Arg->getName() == "basicblock") {
+ if (!PrintArg) P->error("Cannot define a new basicblock value!");
+ OS << ".addMBB(" << NameVar << ")";
+ return;
+ }
+ P->error("Unknown operand type '" + Arg->getName() + "' to expander!");
+ } else if (IntInit *II = dynamic_cast<IntInit*>(Arg)) {
+ if (!NameVar.empty())
+ P->error("Illegal to specify a name for a constant initializer arg!");
+
+ // Hack this check to allow R32 values with 0 as the initializer for memory
+ // references... FIXME!
+ if (ArgDeclNode->isLeaf() && II->getValue() == 0 &&
+ ArgDeclNode->getValueRecord()->getName() == "R32") {
+ OS << ".addReg(0)";
+ } else {
+ if (ArgDeclNode->isLeaf() || ArgDeclNode->getOperator()->getName()!="imm")
+ P->error("Illegal immediate int value '" + itostr(II->getValue()) +
+ "' operand!");
+ OS << ".addZImm(" << II->getValue() << ")";
+ }
+ return;
+ }
+ P->error("Unknown operand type to expander!");
+}
+
+static std::string getArgName(Pattern *P, const std::string &ArgName,
+ const std::vector<std::pair<TreePatternNode*, std::string> > &Operands) {
+ assert(P->getNumArgs() == Operands.size() &&"Argument computation mismatch!");
+ if (ArgName.empty()) return "";
+
+ for (unsigned i = 0, e = P->getNumArgs(); i != e; ++i)
+ if (P->getArgName(i) == ArgName)
+ return Operands[i].second + "->Val";
+
+ if (ArgName == P->getResultName())
+ return "NewReg";
+ P->error("Pattern does not define a value named $" + ArgName + "!");
+ return "";
+}
+
+
+void InstrSelectorEmitter::run(std::ostream &OS) {
+ // Type-check all of the node types to ensure we "understand" them.
+ ReadNodeTypes();
+
+ // Read in all of the nonterminals, instructions, and expanders...
+ ReadNonterminals();
+ ReadInstructionPatterns();
+ ReadExpanderPatterns();
+
+ // Instantiate any unresolved nonterminals with information from the context
+ // that they are used in.
+ InstantiateNonterminals();
+
+ // Clear InstantiatedNTs, we don't need it anymore...
+ InstantiatedNTs.clear();
+
+ DEBUG(std::cerr << "Patterns acquired:\n");
+ for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(),
+ E = Patterns.end(); I != E; ++I)
+ if (I->second->isResolved())
+ DEBUG(std::cerr << " " << *I->second << "\n");
+
+ CalculateComputableValues();
+
+ EmitSourceFileHeader("Instruction Selector for the " + Target.getName() +
+ " target", OS);
+ OS << "#include \"llvm/CodeGen/MachineInstrBuilder.h\"\n";
+
+ // Output the slot number enums...
+ OS << "\nenum { // Slot numbers...\n"
+ << " LastBuiltinSlot = ISD::NumBuiltinSlots-1, // Start numbering here\n";
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I)
+ OS << " " << I->first << "_Slot,\n";
+ OS << " NumSlots\n};\n\n// Reduction value typedefs...\n";
+
+ // Output the reduction value typedefs...
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I) {
+
+ OS << "typedef ReducedValue<unsigned, " << I->first
+ << "_Slot> ReducedValue_" << I->first << ";\n";
+ }
+
+ // Output the pattern enums...
+ OS << "\n\n"
+ << "enum { // Patterns...\n"
+ << " NotComputed = 0,\n"
+ << " NoMatchPattern, \n";
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I) {
+ OS << " // " << I->first << " patterns...\n";
+ for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(),
+ E = I->second.end(); J != E; ++J)
+ for (unsigned i = 0, e = J->second.size(); i != e; ++i)
+ OS << " " << J->second[i]->getRecord()->getName() << "_Pattern,\n";
+ }
+ OS << "};\n\n";
+
+ //===--------------------------------------------------------------------===//
+ // Emit the class definition...
+ //
+ OS << "namespace {\n"
+ << " class " << Target.getName() << "ISel {\n"
+ << " SelectionDAG &DAG;\n"
+ << " public:\n"
+ << " X86ISel(SelectionDAG &D) : DAG(D) {}\n"
+ << " void generateCode();\n"
+ << " private:\n"
+ << " unsigned makeAnotherReg(const TargetRegisterClass *RC) {\n"
+ << " return DAG.getMachineFunction().getSSARegMap()->createVirt"
+ "ualRegister(RC);\n"
+ << " }\n\n"
+ << " // DAG matching methods for classes... all of these methods"
+ " return the cost\n"
+ << " // of producing a value of the specified class and type, which"
+ " also gets\n"
+ << " // added to the DAG node.\n";
+
+ // Output all of the matching prototypes for slots...
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I)
+ OS << " unsigned Match_" << I->first << "(SelectionDAGNode *N);\n";
+ OS << "\n // DAG matching methods for DAG nodes...\n";
+
+ // Output all of the matching prototypes for slot/node pairs
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I)
+ for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(),
+ E = I->second.end(); J != E; ++J)
+ OS << " unsigned Match_" << I->first << "_" << getNodeName(J->first)
+ << "(SelectionDAGNode *N);\n";
+
+ // Output all of the dag reduction methods prototypes...
+ OS << "\n // DAG reduction methods...\n";
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I)
+ OS << " ReducedValue_" << I->first << " *Reduce_" << I->first
+ << "(SelectionDAGNode *N,\n" << std::string(27+2*I->first.size(), ' ')
+ << "MachineBasicBlock *MBB);\n";
+ OS << " };\n}\n\n";
+
+ // Emit the generateCode entry-point...
+ OS << "void X86ISel::generateCode() {\n"
+ << " SelectionDAGNode *Root = DAG.getRoot();\n"
+ << " assert(Root->getValueType() == MVT::isVoid && "
+ "\"Root of DAG produces value??\");\n\n"
+ << " std::cerr << \"\\n\";\n"
+ << " unsigned Cost = Match_Void_void(Root);\n"
+ << " if (Cost >= ~0U >> 1) {\n"
+ << " std::cerr << \"Match failed!\\n\";\n"
+ << " Root->dump();\n"
+ << " abort();\n"
+ << " }\n\n"
+ << " std::cerr << \"Total DAG Cost: \" << Cost << \"\\n\\n\";\n\n"
+ << " Reduce_Void_void(Root, 0);\n"
+ << "}\n\n"
+ << "//===" << std::string(70, '-') << "===//\n"
+ << "// Matching methods...\n"
+ << "//\n\n";
+
+ //===--------------------------------------------------------------------===//
+ // Emit all of the matcher methods...
+ //
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I) {
+ const std::string &SlotName = I->first;
+ OS << "unsigned " << Target.getName() << "ISel::Match_" << SlotName
+ << "(SelectionDAGNode *N) {\n"
+ << " assert(N->getValueType() == MVT::"
+ << getEnumName((*I->second.begin()).second[0]->getTree()->getType())
+ << ");\n" << " // If we already have a cost available for " << SlotName
+ << " use it!\n"
+ << " if (N->getPatternFor(" << SlotName << "_Slot))\n"
+ << " return N->getCostFor(" << SlotName << "_Slot);\n\n"
+ << " unsigned Cost;\n"
+ << " switch (N->getNodeType()) {\n"
+ << " default: Cost = ~0U >> 1; // Match failed\n"
+ << " N->setPatternCostFor(" << SlotName << "_Slot, NoMatchPattern, Cost, NumSlots);\n"
+ << " break;\n";
+
+ for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(),
+ E = I->second.end(); J != E; ++J)
+ if (!J->first->isSubClassOf("Nonterminal"))
+ OS << " case ISD::" << getNodeName(J->first) << ":\tCost = Match_"
+ << SlotName << "_" << getNodeName(J->first) << "(N); break;\n";
+ OS << " }\n"; // End of the switch statement
+
+ // Emit any patterns which have a nonterminal leaf as the RHS. These may
+ // match multiple root nodes, so they cannot be handled with the switch...
+ for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(),
+ E = I->second.end(); J != E; ++J)
+ if (J->first->isSubClassOf("Nonterminal")) {
+ OS << " unsigned " << J->first->getName() << "_Cost = Match_"
+ << getNodeName(J->first) << "(N);\n"
+ << " if (" << getNodeName(J->first) << "_Cost < Cost) Cost = "
+ << getNodeName(J->first) << "_Cost;\n";
+ }
+
+ OS << " return Cost;\n}\n\n";
+
+ for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(),
+ E = I->second.end(); J != E; ++J) {
+ Record *Operator = J->first;
+ bool isNonterm = Operator->isSubClassOf("Nonterminal");
+ if (!isNonterm) {
+ OS << "unsigned " << Target.getName() << "ISel::Match_";
+ if (!isNonterm) OS << SlotName << "_";
+ OS << getNodeName(Operator) << "(SelectionDAGNode *N) {\n"
+ << " unsigned Pattern = NoMatchPattern;\n"
+ << " unsigned MinCost = ~0U >> 1;\n";
+
+ std::vector<std::pair<Pattern*, TreePatternNode*> > Patterns;
+ for (unsigned i = 0, e = J->second.size(); i != e; ++i)
+ Patterns.push_back(std::make_pair(J->second[i],
+ J->second[i]->getTree()));
+ EmitMatchCosters(OS, Patterns, "N", 2);
+
+ OS << "\n N->setPatternCostFor(" << SlotName
+ << "_Slot, Pattern, MinCost, NumSlots);\n"
+ << " return MinCost;\n"
+ << "}\n";
+ }
+ }
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Emit all of the reducer methods...
+ //
+ OS << "\n\n//===" << std::string(70, '-') << "===//\n"
+ << "// Reducer methods...\n"
+ << "//\n";
+
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I) {
+ const std::string &SlotName = I->first;
+ OS << "ReducedValue_" << SlotName << " *" << Target.getName()
+ << "ISel::Reduce_" << SlotName
+ << "(SelectionDAGNode *N, MachineBasicBlock *MBB) {\n"
+ << " ReducedValue_" << SlotName << " *Val = N->hasValue<ReducedValue_"
+ << SlotName << ">(" << SlotName << "_Slot);\n"
+ << " if (Val) return Val;\n"
+ << " if (N->getBB()) MBB = N->getBB();\n\n"
+ << " switch (N->getPatternFor(" << SlotName << "_Slot)) {\n";
+
+ // Loop over all of the patterns that can produce a value for this slot...
+ PatternOrganizer::NodesForSlot &NodesForSlot = I->second;
+ for (PatternOrganizer::NodesForSlot::iterator J = NodesForSlot.begin(),
+ E = NodesForSlot.end(); J != E; ++J)
+ for (unsigned i = 0, e = J->second.size(); i != e; ++i) {
+ Pattern *P = J->second[i];
+ OS << " case " << P->getRecord()->getName() << "_Pattern: {\n"
+ << " // " << *P << "\n";
+ // Loop over the operands, reducing them...
+ std::vector<std::pair<TreePatternNode*, std::string> > Operands;
+ ReduceAllOperands(P->getTree(), "N", Operands, OS);
+
+ // Now that we have reduced all of our operands, and have the values
+ // that reduction produces, perform the reduction action for this
+ // pattern.
+ std::string Result;
+
+ // If the pattern produces a register result, generate a new register
+ // now.
+ if (Record *R = P->getResult()) {
+ assert(R->isSubClassOf("RegisterClass") &&
+ "Only handle register class results so far!");
+ OS << " unsigned NewReg = makeAnotherReg(" << Target.getName()
+ << "::" << R->getName() << "RegisterClass);\n";
+ Result = "NewReg";
+ DEBUG(OS << " std::cerr << \"%reg\" << NewReg << \" =\t\";\n");
+ } else {
+ DEBUG(OS << " std::cerr << \"\t\t\";\n");
+ Result = "0";
+ }
+
+ // Print out the pattern that matched...
+ DEBUG(OS << " std::cerr << \" " << P->getRecord()->getName() <<'"');
+ DEBUG(for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ if (Operands[i].first->isLeaf()) {
+ Record *RV = Operands[i].first->getValueRecord();
+ assert(RV->isSubClassOf("RegisterClass") &&
+ "Only handles registers here so far!");
+ OS << " << \" %reg\" << " << Operands[i].second
+ << "->Val";
+ } else {
+ OS << " << ' ' << " << Operands[i].second
+ << "->Val";
+ });
+ DEBUG(OS << " << \"\\n\";\n");
+
+ // Generate the reduction code appropriate to the particular type of
+ // pattern that this is...
+ switch (P->getPatternType()) {
+ case Pattern::Instruction:
+ // Instruction patterns just emit a single MachineInstr, using BuildMI
+ OS << " BuildMI(MBB, " << Target.getName() << "::"
+ << P->getRecord()->getName() << ", " << Operands.size();
+ if (P->getResult()) OS << ", NewReg";
+ OS << ")";
+
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ TreePatternNode *Op = Operands[i].first;
+ if (Op->isLeaf()) {
+ Record *RV = Op->getValueRecord();
+ assert(RV->isSubClassOf("RegisterClass") &&
+ "Only handles registers here so far!");
+ OS << ".addReg(" << Operands[i].second << "->Val)";
+ } else if (Op->getOperator()->getName() == "imm") {
+ OS << ".addZImm(" << Operands[i].second << "->Val)";
+ } else if (Op->getOperator()->getName() == "basicblock") {
+ OS << ".addMBB(" << Operands[i].second << "->Val)";
+ } else {
+ assert(0 && "Unknown value type!");
+ }
+ }
+ OS << ";\n";
+ break;
+ case Pattern::Expander: {
+ // Expander patterns emit one machine instr for each instruction in
+ // the list of instructions expanded to.
+ ListInit *Insts = P->getRecord()->getValueAsListInit("Result");
+ for (unsigned IN = 0, e = Insts->getSize(); IN != e; ++IN) {
+ DagInit *DIInst = dynamic_cast<DagInit*>(Insts->getElement(IN));
+ if (!DIInst) P->error("Result list must contain instructions!");
+ Record *InstRec = DIInst->getNodeType();
+ Pattern *InstPat = getPattern(InstRec);
+ if (!InstPat || InstPat->getPatternType() != Pattern::Instruction)
+ P->error("Instruction list must contain Instruction patterns!");
+
+ bool hasResult = InstPat->getResult() != 0;
+ if (InstPat->getNumArgs() != DIInst->getNumArgs()-hasResult) {
+ P->error("Incorrect number of arguments specified for inst '" +
+ InstPat->getRecord()->getName() + "' in result list!");
+ }
+
+ // Start emission of the instruction...
+ OS << " BuildMI(MBB, " << Target.getName() << "::"
+ << InstRec->getName() << ", "
+ << DIInst->getNumArgs()-hasResult;
+ // Emit register result if necessary..
+ if (hasResult) {
+ std::string ArgNameVal =
+ getArgName(P, DIInst->getArgName(0), Operands);
+ PrintExpanderOperand(DIInst->getArg(0), ArgNameVal,
+ InstPat->getResultNode(), P, false,
+ OS << ", ");
+ }
+ OS << ")";
+
+ for (unsigned i = hasResult, e = DIInst->getNumArgs(); i != e; ++i){
+ std::string ArgNameVal =
+ getArgName(P, DIInst->getArgName(i), Operands);
+
+ PrintExpanderOperand(DIInst->getArg(i), ArgNameVal,
+ InstPat->getArg(i-hasResult), P, true, OS);
+ }
+
+ OS << ";\n";
+ }
+ break;
+ }
+ default:
+ assert(0 && "Reduction of this type of pattern not implemented!");
+ }
+
+ OS << " Val = new ReducedValue_" << SlotName << "(" << Result<<");\n"
+ << " break;\n"
+ << " }\n";
+ }
+
+
+ OS << " default: assert(0 && \"Unknown " << SlotName << " pattern!\");\n"
+ << " }\n\n N->addValue(Val); // Do not ever recalculate this\n"
+ << " return Val;\n}\n\n";
+ }
+}
+
diff --git a/llvm/utils/TableGen/InstrSelectorEmitter.h b/llvm/utils/TableGen/InstrSelectorEmitter.h
new file mode 100644
index 00000000000..922aa79dfa1
--- /dev/null
+++ b/llvm/utils/TableGen/InstrSelectorEmitter.h
@@ -0,0 +1,387 @@
+//===- InstrInfoEmitter.h - Generate a Instruction Set Desc. ----*- C++ -*-===//
+//
+// This tablegen backend is responsible for emitting a description of the target
+// instruction set for the code generator.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef INSTRSELECTOR_EMITTER_H
+#define INSTRSELECTOR_EMITTER_H
+
+#include "TableGenBackend.h"
+#include "CodeGenWrappers.h"
+#include <vector>
+#include <map>
+#include <cassert>
+
+class DagInit;
+class Init;
+class InstrSelectorEmitter;
+
+/// NodeType - Represents Information parsed from the DagNode entries.
+///
+struct NodeType {
+ enum ArgResultTypes {
+ Any, // No constraint on type
+ Val, // A non-void type
+ Arg0, // Value matches the type of Arg0
+ Arg1, // Value matches the type of Arg1
+ Ptr, // Tree node is the type of the target pointer
+ I8, // Always bool
+ Void, // Tree node always returns void
+ };
+
+ ArgResultTypes ResultType;
+ std::vector<ArgResultTypes> ArgTypes;
+
+ NodeType(ArgResultTypes RT, std::vector<ArgResultTypes> &AT) : ResultType(RT){
+ AT.swap(ArgTypes);
+ }
+
+ NodeType() : ResultType(Val) {}
+ NodeType(const NodeType &N) : ResultType(N.ResultType), ArgTypes(N.ArgTypes){}
+
+ static ArgResultTypes Translate(Record *R);
+};
+
+
+
+/// TreePatternNode - Represent a node of the tree patterns.
+///
+class TreePatternNode {
+ /// Operator - The operation that this node represents... this is null if this
+ /// is a leaf.
+ Record *Operator;
+
+ /// Type - The inferred value type...
+ ///
+ MVT::ValueType Type;
+
+ /// Children - If this is not a leaf (Operator != 0), this is the subtrees
+ /// that we contain.
+ std::vector<std::pair<TreePatternNode*, std::string> > Children;
+
+ /// Value - If this node is a leaf, this indicates what the thing is.
+ ///
+ Init *Value;
+public:
+ TreePatternNode(Record *o, const std::vector<std::pair<TreePatternNode*,
+ std::string> > &c)
+ : Operator(o), Type(MVT::Other), Children(c), Value(0) {}
+ TreePatternNode(Init *V) : Operator(0), Type(MVT::Other), Value(V) {}
+
+ Record *getOperator() const {
+ assert(Operator && "This is a leaf node!");
+ return Operator;
+ }
+ MVT::ValueType getType() const { return Type; }
+ void setType(MVT::ValueType T) { Type = T; }
+
+ bool isLeaf() const { return Operator == 0; }
+
+ unsigned getNumChildren() const { return Children.size(); }
+ TreePatternNode *getChild(unsigned c) const {
+ assert(Operator != 0 && "This is a leaf node!");
+ assert(c < Children.size() && "Child access out of range!");
+ return Children[c].first;
+ }
+ const std::string &getChildName(unsigned c) const {
+ assert(Operator != 0 && "This is a leaf node!");
+ assert(c < Children.size() && "Child access out of range!");
+ return Children[c].second;
+ }
+
+ Init *getValue() const {
+ assert(Operator == 0 && "This is not a leaf node!");
+ return Value;
+ }
+
+ /// getValueRecord - Returns the value of this tree node as a record. For now
+ /// we only allow DefInit's as our leaf values, so this is used.
+ Record *getValueRecord() const;
+
+ /// clone - Make a copy of this tree and all of its children.
+ ///
+ TreePatternNode *clone() const;
+
+ void dump() const;
+
+ /// InstantiateNonterminals - If this pattern refers to any nonterminals which
+ /// are not themselves completely resolved, clone the nonterminal and resolve
+ /// it with the using context we provide.
+ void InstantiateNonterminals(InstrSelectorEmitter &ISE);
+
+ /// UpdateNodeType - Set the node type of N to VT if VT contains information.
+ /// If N already contains a conflicting type, then throw an exception. This
+ /// returns true if any information was updated.
+ ///
+ bool updateNodeType(MVT::ValueType VT, const std::string &RecName);
+};
+
+std::ostream &operator<<(std::ostream &OS, const TreePatternNode &N);
+
+
+
+/// Pattern - Represent a pattern of one form or another. Currently, three
+/// types of patterns are possible: Instruction's, Nonterminals, and Expanders.
+///
+struct Pattern {
+ enum PatternType {
+ Nonterminal, Instruction, Expander
+ };
+private:
+ /// PTy - The type of pattern this is.
+ ///
+ PatternType PTy;
+
+ /// Tree - The tree pattern which corresponds to this pattern. Note that if
+ /// there was a (set) node on the outside level that it has been stripped off.
+ ///
+ TreePatternNode *Tree;
+
+ /// Result - If this is an instruction or expander pattern, this is the
+ /// register result, specified with a (set) in the pattern.
+ ///
+ std::string ResultName; // The name of the result value...
+ TreePatternNode *ResultNode; // The leaf node for the result register...
+
+ /// TheRecord - The actual TableGen record corresponding to this pattern.
+ ///
+ Record *TheRecord;
+
+ /// Resolved - This is true of the pattern is useful in practice. In
+ /// particular, some non-terminals will have non-resolvable types. When a
+ /// user of the non-terminal is later found, they will have inferred a type
+ /// for the result of the non-terminal, which cause a clone of an unresolved
+ /// nonterminal to be made which is "resolved".
+ ///
+ bool Resolved;
+
+ /// Args - This is a list of all of the arguments to this pattern, which are
+ /// the non-void leaf nodes in this pattern.
+ std::vector<std::pair<TreePatternNode*, std::string> > Args;
+
+ /// ISE - the instruction selector emitter coordinating this madness.
+ ///
+ InstrSelectorEmitter &ISE;
+public:
+
+ /// Pattern constructor - Parse the specified DagInitializer into the current
+ /// record.
+ Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
+ InstrSelectorEmitter &ise);
+
+ /// Pattern - Constructor used for cloning nonterminal patterns
+ Pattern(TreePatternNode *tree, Record *rec, bool res,
+ InstrSelectorEmitter &ise)
+ : PTy(Nonterminal), Tree(tree), ResultNode(0), TheRecord(rec),
+ Resolved(res), ISE(ise) {
+ calculateArgs(Tree, "");
+ }
+
+ /// getPatternType - Return what flavor of Record this pattern originated from
+ ///
+ PatternType getPatternType() const { return PTy; }
+
+ /// getTree - Return the tree pattern which corresponds to this pattern.
+ ///
+ TreePatternNode *getTree() const { return Tree; }
+
+ Record *getResult() const {
+ return ResultNode ? ResultNode->getValueRecord() : 0;
+ }
+ const std::string &getResultName() const { return ResultName; }
+ TreePatternNode *getResultNode() const { return ResultNode; }
+
+ /// getRecord - Return the actual TableGen record corresponding to this
+ /// pattern.
+ ///
+ Record *getRecord() const { return TheRecord; }
+
+ unsigned getNumArgs() const { return Args.size(); }
+ TreePatternNode *getArg(unsigned i) const {
+ assert(i < Args.size() && "Argument reference out of range!");
+ return Args[i].first;
+ }
+ Record *getArgRec(unsigned i) const {
+ return getArg(i)->getValueRecord();
+ }
+ Init *getArgVal(unsigned i) const {
+ return getArg(i)->getValue();
+ }
+ const std::string &getArgName(unsigned i) const {
+ assert(i < Args.size() && "Argument reference out of range!");
+ return Args[i].second;
+ }
+
+ bool isResolved() const { return Resolved; }
+
+ /// InferAllTypes - Runs the type inference engine on the current pattern,
+ /// stopping when nothing can be inferred, then updating the Resolved field.
+ void InferAllTypes();
+
+ /// InstantiateNonterminals - If this pattern refers to any nonterminals which
+ /// are not themselves completely resolved, clone the nonterminal and resolve
+ /// it with the using context we provide.
+ void InstantiateNonterminals() {
+ Tree->InstantiateNonterminals(ISE);
+ }
+
+ /// clone - This method is used to make an exact copy of the current pattern,
+ /// then change the "TheRecord" instance variable to the specified record.
+ ///
+ Pattern *clone(Record *R) const;
+
+ /// error - Throw an exception, prefixing it with information about this
+ /// pattern.
+ void error(const std::string &Msg) const;
+
+ /// getSlotName - If this is a leaf node, return the slot name that the
+ /// operand will update.
+ std::string getSlotName() const;
+ static std::string getSlotName(Record *R);
+
+ void dump() const;
+
+private:
+ void calculateArgs(TreePatternNode *N, const std::string &Name);
+ MVT::ValueType getIntrinsicType(Record *R) const;
+ TreePatternNode *ParseTreePattern(DagInit *DI);
+ bool InferTypes(TreePatternNode *N, bool &MadeChange);
+};
+
+std::ostream &operator<<(std::ostream &OS, const Pattern &P);
+
+
+/// PatternOrganizer - This class represents all of the patterns which are
+/// useful for the instruction selector, neatly catagorized in a hierarchical
+/// structure.
+struct PatternOrganizer {
+ /// PatternsForNode - The list of patterns which can produce a value of a
+ /// particular slot type, given a particular root node in the tree. All of
+ /// the patterns in this vector produce the same value type and have the same
+ /// root DAG node.
+ typedef std::vector<Pattern*> PatternsForNode;
+
+ /// NodesForSlot - This map keeps track of all of the root DAG nodes which can
+ /// lead to the production of a value for this slot. All of the patterns in
+ /// this data structure produces values of the same slot.
+ typedef std::map<Record*, PatternsForNode> NodesForSlot;
+
+ /// AllPatterns - This data structure contains all patterns in the instruction
+ /// selector.
+ std::map<std::string, NodesForSlot> AllPatterns;
+
+ // Forwarding functions...
+ typedef std::map<std::string, NodesForSlot>::iterator iterator;
+ iterator begin() { return AllPatterns.begin(); }
+ iterator end() { return AllPatterns.end(); }
+
+
+ /// addPattern - Add the specified pattern to the appropriate location in the
+ /// collection.
+ void addPattern(Pattern *P);
+};
+
+
+/// InstrSelectorEmitter - The top-level class which coordinates construction
+/// and emission of the instruction selector.
+///
+class InstrSelectorEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ CodeGenTarget Target;
+
+ std::map<Record*, NodeType> NodeTypes;
+
+ /// Patterns - a list of all of the patterns defined by the target description
+ ///
+ std::map<Record*, Pattern*> Patterns;
+
+ /// InstantiatedNTs - A data structure to keep track of which nonterminals
+ /// have been instantiated already...
+ ///
+ std::map<std::pair<Pattern*,MVT::ValueType>, Record*> InstantiatedNTs;
+
+ /// ComputableValues - This map indicates which patterns can be used to
+ /// generate a value that is used by the selector. The keys of this map
+ /// implicitly define the values that are used by the selector.
+ ///
+ PatternOrganizer ComputableValues;
+
+public:
+ InstrSelectorEmitter(RecordKeeper &R) : Records(R) {}
+
+ // run - Output the instruction set description, returning true on failure.
+ void run(std::ostream &OS);
+
+ const CodeGenTarget &getTarget() const { return Target; }
+ std::map<Record*, NodeType> &getNodeTypes() { return NodeTypes; }
+ const NodeType &getNodeType(Record *R) const {
+ std::map<Record*, NodeType>::const_iterator I = NodeTypes.find(R);
+ assert(I != NodeTypes.end() && "Unknown node type!");
+ return I->second;
+ }
+
+ /// getPattern - return the pattern corresponding to the specified record, or
+ /// null if there is none.
+ Pattern *getPattern(Record *R) const {
+ std::map<Record*, Pattern*>::const_iterator I = Patterns.find(R);
+ return I != Patterns.end() ? I->second : 0;
+ }
+
+ /// ReadNonterminal - This method parses the specified record as a
+ /// nonterminal, but only if it hasn't been read in already.
+ Pattern *ReadNonterminal(Record *R);
+
+ /// InstantiateNonterminal - This method takes the nonterminal specified by
+ /// NT, which should not be completely resolved, clones it, applies ResultTy
+ /// to its root, then runs the type inference stuff on it. This should
+ /// produce a newly resolved nonterminal, which we make a record for and
+ /// return. To be extra fancy and efficient, this only makes one clone for
+ /// each type it is instantiated with.
+ Record *InstantiateNonterminal(Pattern *NT, MVT::ValueType ResultTy);
+
+private:
+ // ReadNodeTypes - Read in all of the node types in the current RecordKeeper,
+ // turning them into the more accessible NodeTypes data structure.
+ void ReadNodeTypes();
+
+ // ReadNonTerminals - Read in all nonterminals and incorporate them into our
+ // pattern database.
+ void ReadNonterminals();
+
+ // ReadInstructionPatterns - Read in all subclasses of Instruction, and
+ // process those with a useful Pattern field.
+ void ReadInstructionPatterns();
+
+ // ReadExpanderPatterns - Read in all of the expanded patterns.
+ void ReadExpanderPatterns();
+
+ // InstantiateNonterminals - Instantiate any unresolved nonterminals with
+ // information from the context that they are used in.
+ void InstantiateNonterminals();
+
+ // CalculateComputableValues - Fill in the ComputableValues map through
+ // analysis of the patterns we are playing with.
+ void CalculateComputableValues();
+
+ // EmitMatchCosters - Given a list of patterns, which all have the same root
+ // pattern operator, emit an efficient decision tree to decide which one to
+ // pick. This is structured this way to avoid reevaluations of non-obvious
+ // subexpressions.
+ void EmitMatchCosters(std::ostream &OS,
+ const std::vector<std::pair<Pattern*, TreePatternNode*> > &Patterns,
+ const std::string &VarPrefix, unsigned Indent);
+
+ /// PrintExpanderOperand - Print out Arg as part of the instruction emission
+ /// process for the expander pattern P. This argument may be referencing some
+ /// values defined in P, or may just be physical register references or
+ /// something like that. If PrintArg is true, we are printing out arguments
+ /// to the BuildMI call. If it is false, we are printing the result register
+ /// name.
+ void PrintExpanderOperand(Init *Arg, const std::string &NameVar,
+ TreePatternNode *ArgDecl, Pattern *P,
+ bool PrintArg, std::ostream &OS);
+};
+
+#endif
diff --git a/llvm/utils/TableGen/Makefile b/llvm/utils/TableGen/Makefile
new file mode 100644
index 00000000000..89a956d9dde
--- /dev/null
+++ b/llvm/utils/TableGen/Makefile
@@ -0,0 +1,18 @@
+LEVEL = ../..
+TOOLNAME = tblgen
+USEDLIBS = support.a
+
+.PRECIOUS: FileLexer.cpp FileParser.cpp
+
+include $(LEVEL)/Makefile.common
+
+#
+# Make the source file depend on the header file. In this way, dependencies
+# (which depend on the source file) won't get generated until bison is done
+# generating the C source and header files for the parser.
+#
+FileLexer.cpp: FileParser.h
+
+clean::
+ -rm -f FileParser.cpp FileParser.h FileLexer.cpp CommandLine.cpp
+ -rm -f FileParser.output
diff --git a/llvm/utils/TableGen/Record.cpp b/llvm/utils/TableGen/Record.cpp
new file mode 100644
index 00000000000..384005081e7
--- /dev/null
+++ b/llvm/utils/TableGen/Record.cpp
@@ -0,0 +1,676 @@
+//===- 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);
+}
+
+bool BitRecTy::baseClassOf(const BitsRecTy *RHS) const {
+ return RHS->getNumBits() == 1;
+}
+
+Init *BitRecTy::convertValue(IntInit *II) {
+ int Val = II->getValue();
+ if (Val != 0 && Val != 1) return 0; // Only accept 0 or 1 for a bit!
+
+ return new BitInit(Val != 0);
+}
+
+Init *BitRecTy::convertValue(TypedInit *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();
+ // Make sure this bitfield is large enough to hold the integer value...
+ if (Value >= 0) {
+ if (Value & ~((1 << Size)-1))
+ return 0;
+ } else {
+ if ((Value >> Size) != -1 || ((Value & (1 << Size-1)) == 0))
+ return 0;
+ }
+
+ 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(TypedInit *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(BitInit *BI) {
+ return new IntInit(BI->getValue());
+}
+
+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(TypedInit *TI) {
+ if (TI->getType()->typeIsConvertibleTo(this))
+ return TI; // Accept variable if already of the right type!
+ return 0;
+}
+
+Init *StringRecTy::convertValue(TypedInit *TI) {
+ if (dynamic_cast<StringRecTy*>(TI->getType()))
+ return TI; // Accept variable if already of the right type!
+ return 0;
+}
+
+void ListRecTy::print(std::ostream &OS) const {
+ OS << "list<" << *Ty << ">";
+}
+
+Init *ListRecTy::convertValue(ListInit *LI) {
+ std::vector<Init*> Elements;
+
+ // Verify that all of the elements of the list are subclasses of the
+ // appropriate class!
+ for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
+ if (Init *CI = LI->getElement(i)->convertInitializerTo(Ty))
+ Elements.push_back(CI);
+ else
+ return 0;
+
+ return new ListInit(Elements);
+}
+
+Init *ListRecTy::convertValue(TypedInit *TI) {
+ // Ensure that TI is compatible with our class.
+ if (ListRecTy *LRT = dynamic_cast<ListRecTy*>(TI->getType()))
+ if (LRT->getElementType()->typeIsConvertibleTo(getElementType()))
+ return TI;
+ return 0;
+}
+
+Init *CodeRecTy::convertValue(TypedInit *TI) {
+ if (TI->getType()->typeIsConvertibleTo(this))
+ return TI;
+ return 0;
+}
+
+Init *DagRecTy::convertValue(TypedInit *TI) {
+ if (TI->getType()->typeIsConvertibleTo(this))
+ return TI;
+ return 0;
+}
+
+
+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;
+}
+
+Init *RecordRecTy::convertValue(TypedInit *TI) {
+ // Ensure that TI is compatible with Rec.
+ if (RecordRecTy *RRT = dynamic_cast<RecordRecTy*>(TI->getType()))
+ if (RRT->getRecord()->isSubClassOf(getRecord()) ||
+ RRT->getRecord() == getRecord())
+ return TI;
+ return 0;
+}
+
+bool RecordRecTy::baseClassOf(const RecordRecTy *RHS) const {
+ return Rec == RHS->getRecord() || RHS->getRecord()->isSubClassOf(Rec);
+}
+
+
+//===----------------------------------------------------------------------===//
+// 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 << ", ";
+ if (Init *Bit = getBit(e-i-1))
+ Bit->print(OS);
+ else
+ 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;
+ TypedInit *Var = FirstBit->getVariable();
+
+ // Check to make sure the types are compatible.
+ BitsRecTy *Ty = dynamic_cast<BitsRecTy*>(FirstBit->getVariable()->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;
+ }
+
+ Var->print(OS);
+ 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;
+}
+
+// resolveReferences - If there are any field references that refer to fields
+// that have been filled in, we can propagate the values now.
+//
+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;
+ Init *CurBit = getBit(i);
+
+ do {
+ B = CurBit;
+ CurBit = CurBit->resolveReferences(R);
+ Changed |= B != CurBit;
+ } while (B != CurBit);
+ New->setBit(i, CurBit);
+ }
+
+ if (Changed)
+ return New;
+ delete New;
+ return this;
+}
+
+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 = Values.size(); i != e; ++i) {
+ if (i) OS << ", ";
+ OS << *Values[i];
+ }
+ OS << "]";
+}
+
+Init *VarInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
+ BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType());
+ 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 *VarInit::resolveBitReference(Record &R, unsigned Bit) {
+ if (R.isTemplateArg(getName()))
+ return this;
+
+ RecordVal *RV = R.getValue(getName());
+ assert(RV && "Reference to a non-existant variable?");
+ assert(dynamic_cast<BitsInit*>(RV->getValue()));
+ BitsInit *BI = (BitsInit*)RV->getValue();
+
+ assert(Bit < BI->getNumBits() && "Bit reference out of range!");
+ Init *B = BI->getBit(Bit);
+
+ if (!dynamic_cast<UnsetInit*>(B)) // If the bit is not set...
+ return B; // Replace the VarBitInit with it.
+ return this;
+}
+
+RecTy *VarInit::getFieldType(const std::string &FieldName) const {
+ if (RecordRecTy *RTy = dynamic_cast<RecordRecTy*>(getType()))
+ if (const RecordVal *RV = RTy->getRecord()->getValue(FieldName))
+ return RV->getType();
+ return 0;
+}
+
+Init *VarInit::getFieldInit(Record &R, const std::string &FieldName) const {
+ if (RecordRecTy *RTy = dynamic_cast<RecordRecTy*>(getType()))
+ if (const RecordVal *RV = R.getValue(VarName))
+ if (Init *I = RV->getValue()->getFieldInit(R, FieldName))
+ return I;
+ else
+ return 0;
+ 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
+/// users of the value to allow the value to propagate out.
+///
+Init *VarInit::resolveReferences(Record &R) {
+ if (RecordVal *Val = R.getValue(VarName))
+ if (!dynamic_cast<UnsetInit*>(Val->getValue()))
+ return Val->getValue();
+ return this;
+}
+
+
+Init *VarBitInit::resolveReferences(Record &R) {
+ Init *I = getVariable()->resolveBitReference(R, getBitNum());
+ if (I != getVariable())
+ return I;
+ return this;
+}
+
+RecTy *DefInit::getFieldType(const std::string &FieldName) const {
+ if (const RecordVal *RV = Def->getValue(FieldName))
+ return RV->getType();
+ return 0;
+}
+
+Init *DefInit::getFieldInit(Record &R, const std::string &FieldName) const {
+ return Def->getValue(FieldName)->getValue();
+}
+
+
+void DefInit::print(std::ostream &OS) const {
+ OS << Def->getName();
+}
+
+Init *FieldInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
+ BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType());
+ if (T == 0) return 0; // Cannot subscript a non-bits field...
+ 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 *FieldInit::resolveBitReference(Record &R, unsigned Bit) {
+ Init *BitsVal = Rec->getFieldInit(R, FieldName);
+ if (BitsVal)
+ if (BitsInit *BI = dynamic_cast<BitsInit*>(BitsVal)) {
+ assert(Bit < BI->getNumBits() && "Bit reference out of range!");
+ Init *B = BI->getBit(Bit);
+
+ if (dynamic_cast<BitInit*>(B)) // If the bit is set...
+ return B; // Replace the VarBitInit with it.
+ }
+ return this;
+}
+
+Init *FieldInit::resolveReferences(Record &R) {
+ Init *BitsVal = Rec->getFieldInit(R, FieldName);
+ if (BitsVal) {
+ Init *BVR = BitsVal->resolveReferences(R);
+ return BVR->isComplete() ? BVR : this;
+ }
+ return this;
+}
+
+
+void DagInit::print(std::ostream &OS) const {
+ OS << "(" << NodeTypeDef->getName();
+ if (Args.size()) {
+ OS << " " << *Args[0];
+ if (!ArgNames[0].empty()) OS << ":$" << ArgNames[0];
+ for (unsigned i = 1, e = Args.size(); i != e; ++i) {
+ OS << ", " << *Args[i];
+ if (!ArgNames[i].empty()) OS << ":$" << ArgNames[i];
+ }
+ }
+ OS << ")";
+}
+
+
+//===----------------------------------------------------------------------===//
+// 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";
+}
+
+/// getValueInit - Return the initializer for a value with the specified name,
+/// or throw an exception if the field does not exist.
+///
+Init *Record::getValueInit(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+ return R->getValue();
+}
+
+
+/// getValueAsString - This method looks up the specified field and returns its
+/// value as a string, throwing an exception if the field does not exist or if
+/// the value is not a string.
+///
+std::string Record::getValueAsString(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+
+ if (const StringInit *SI = dynamic_cast<const StringInit*>(R->getValue()))
+ return SI->getValue();
+ throw "Record '" + getName() + "', field '" + FieldName +
+ "' does not have a string initializer!";
+}
+
+/// getValueAsBitsInit - This method looks up the specified field and returns
+/// its value as a BitsInit, throwing an exception if the field does not exist
+/// or if the value is not the right type.
+///
+BitsInit *Record::getValueAsBitsInit(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+
+ if (BitsInit *BI = dynamic_cast<BitsInit*>(R->getValue()))
+ return BI;
+ throw "Record '" + getName() + "', field '" + FieldName +
+ "' does not have a BitsInit initializer!";
+}
+
+/// getValueAsListInit - This method looks up the specified field and returns
+/// its value as a ListInit, throwing an exception if the field does not exist
+/// or if the value is not the right type.
+///
+ListInit *Record::getValueAsListInit(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+
+ if (ListInit *LI = dynamic_cast<ListInit*>(R->getValue()))
+ return LI;
+ throw "Record '" + getName() + "', field '" + FieldName +
+ "' does not have a list initializer!";
+}
+
+/// getValueAsInt - This method looks up the specified field and returns its
+/// value as an int, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+int Record::getValueAsInt(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+
+ if (IntInit *II = dynamic_cast<IntInit*>(R->getValue()))
+ return II->getValue();
+ throw "Record '" + getName() + "', field '" + FieldName +
+ "' does not have a list initializer!";
+}
+
+/// getValueAsDef - This method looks up the specified field and returns its
+/// value as a Record, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+Record *Record::getValueAsDef(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+
+ if (DefInit *DI = dynamic_cast<DefInit*>(R->getValue()))
+ return DI->getDef();
+ throw "Record '" + getName() + "', field '" + FieldName +
+ "' does not have a list initializer!";
+}
+
+/// getValueAsBit - This method looks up the specified field and returns its
+/// value as a bit, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+bool Record::getValueAsBit(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+
+ if (BitInit *BI = dynamic_cast<BitInit*>(R->getValue()))
+ return BI->getValue();
+ throw "Record '" + getName() + "', field '" + FieldName +
+ "' does not have a bit initializer!";
+}
+
+/// getValueAsDag - This method looks up the specified field and returns its
+/// value as an Dag, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+DagInit *Record::getValueAsDag(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+
+ if (DagInit *DI = dynamic_cast<DagInit*>(R->getValue()))
+ return DI;
+ throw "Record '" + getName() + "', field '" + FieldName +
+ "' does not have a dag initializer!";
+}
+
+
+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;
+}
+
+
+/// getAllDerivedDefinitions - This method returns all concrete definitions
+/// that derive from the specified class name. If a class with the specified
+/// name does not exist, an error is printed and true is returned.
+std::vector<Record*>
+RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const {
+ Record *Class = Records.getClass(ClassName);
+ if (!Class)
+ throw "ERROR: Couldn't find the '" + ClassName + "' class!\n";
+
+ std::vector<Record*> Defs;
+ for (std::map<std::string, Record*>::const_iterator I = getDefs().begin(),
+ E = getDefs().end(); I != E; ++I)
+ if (I->second->isSubClassOf(Class))
+ Defs.push_back(I->second);
+
+ return Defs;
+}
diff --git a/llvm/utils/TableGen/Record.h b/llvm/utils/TableGen/Record.h
new file mode 100644
index 00000000000..4a2fa057cfd
--- /dev/null
+++ b/llvm/utils/TableGen/Record.h
@@ -0,0 +1,849 @@
+//===- Record.h - Classes to represent Table Records ------------*- C++ -*-===//
+//
+// This file defines the main TableGen data structures, including the TableGen
+// types, values, and high-level data structures.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef RECORD_H
+#define RECORD_H
+
+#include <string>
+#include <vector>
+#include <map>
+#include <iostream>
+#include <cassert>
+
+// RecTy subclasses...
+class BitRecTy;
+class BitsRecTy;
+class IntRecTy;
+class StringRecTy;
+class ListRecTy;
+class CodeRecTy;
+class DagRecTy;
+class RecordRecTy;
+
+// Init subclasses...
+class Init;
+class UnsetInit;
+class BitInit;
+class BitsInit;
+class IntInit;
+class StringInit;
+class CodeInit;
+class ListInit;
+class DefInit;
+class DagInit;
+class TypedInit;
+class VarInit;
+class FieldInit;
+class VarBitInit;
+
+// Other classes...
+class Record;
+
+//===----------------------------------------------------------------------===//
+// Type Classes
+//===----------------------------------------------------------------------===//
+
+struct RecTy {
+ virtual ~RecTy() {}
+
+ virtual void print(std::ostream &OS) const = 0;
+ void dump() const;
+
+ /// typeIsConvertibleTo - Return true if all values of 'this' type can be
+ /// converted to the specified type.
+ virtual bool typeIsConvertibleTo(const RecTy *RHS) const = 0;
+
+public: // These methods should only be called from subclasses of Init
+ 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( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( TypedInit *TI) { return 0; }
+ virtual Init *convertValue( VarInit *VI) {
+ return convertValue((TypedInit*)VI);
+ }
+ virtual Init *convertValue( FieldInit *FI) {
+ return convertValue((TypedInit*)FI);
+ }
+
+public: // These methods should only be called by subclasses of RecTy.
+ // baseClassOf - These virtual methods should be overloaded to return true iff
+ // all values of type 'RHS' can be converted to the 'this' type.
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+};
+
+inline std::ostream &operator<<(std::ostream &OS, const RecTy &Ty) {
+ Ty.print(OS);
+ return OS;
+}
+
+
+/// BitRecTy - 'bit' - Represent a single bit
+///
+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(TypedInit *VI);
+ Init *convertValue(VarBitInit *VB) { return (Init*)VB; }
+
+ void print(std::ostream &OS) const { OS << "bit"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const;
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
+};
+
+
+/// BitsRecTy - 'bits<n>' - Represent a fixed number of bits
+///
+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(TypedInit *VI);
+
+ void print(std::ostream &OS) const { OS << "bits<" << Size << ">"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return Size == 1; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const {
+ return RHS->Size == Size;
+ }
+};
+
+
+/// IntRecTy - 'int' - Represent an integer value of no particular size
+///
+struct IntRecTy : public RecTy {
+ Init *convertValue(UnsetInit *UI) { return (Init*)UI; }
+ Init *convertValue(IntInit *II) { return (Init*)II; }
+ Init *convertValue(BitInit *BI);
+ Init *convertValue(BitsInit *BI);
+ Init *convertValue(TypedInit *TI);
+
+ void print(std::ostream &OS) const { OS << "int"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return true; }
+};
+
+/// StringRecTy - 'string' - Represent an string value
+///
+struct StringRecTy : public RecTy {
+ Init *convertValue(UnsetInit *UI) { return (Init*)UI; }
+ Init *convertValue(StringInit *SI) { return (Init*)SI; }
+ Init *convertValue(TypedInit *TI);
+ void print(std::ostream &OS) const { OS << "string"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return true; }
+};
+
+/// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of
+/// the specified type.
+///
+class ListRecTy : public RecTy {
+ RecTy *Ty;
+public:
+ ListRecTy(RecTy *T) : Ty(T) {}
+
+ RecTy *getElementType() const { return Ty; }
+
+ Init *convertValue(UnsetInit *UI) { return (Init*)UI; }
+ Init *convertValue(ListInit *LI);
+ Init *convertValue(TypedInit *TI);
+
+ void print(std::ostream &OS) const;
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+
+ virtual bool baseClassOf(const ListRecTy *RHS) const {
+ return RHS->getElementType()->typeIsConvertibleTo(Ty);
+ }
+};
+
+/// CodeRecTy - 'code' - Represent an code fragment, function or method.
+///
+struct CodeRecTy : public RecTy {
+ Init *convertValue(UnsetInit *UI) { return (Init*)UI; }
+ Init *convertValue( CodeInit *CI) { return (Init*)CI; }
+ Init *convertValue(TypedInit *TI);
+
+ void print(std::ostream &OS) const { OS << "code"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return true; }
+};
+
+/// DagRecTy - 'dag' - Represent a dag fragment
+///
+struct DagRecTy : public RecTy {
+ Init *convertValue(UnsetInit *UI) { return (Init*)UI; }
+ Init *convertValue( DagInit *CI) { return (Init*)CI; }
+ Init *convertValue(TypedInit *TI);
+
+ void print(std::ostream &OS) const { OS << "dag"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return true; }
+};
+
+
+/// RecordRecTy - '<classname>' - Represent an instance of a class, such as:
+/// (R32 X = EAX).
+///
+class RecordRecTy : public RecTy {
+ Record *Rec;
+public:
+ RecordRecTy(Record *R) : Rec(R) {}
+
+ Record *getRecord() const { return Rec; }
+
+ Init *convertValue(UnsetInit *UI) { return (Init*)UI; }
+ Init *convertValue( DefInit *DI);
+ Init *convertValue(TypedInit *VI);
+
+ void print(std::ostream &OS) const;
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const;
+};
+
+
+
+//===----------------------------------------------------------------------===//
+// Initializer Classes
+//===----------------------------------------------------------------------===//
+
+struct Init {
+ virtual ~Init() {}
+
+ /// isComplete - This virtual method should be overridden by values that may
+ /// not be completely specified yet.
+ virtual bool isComplete() const { return true; }
+
+ /// print - Print out this value.
+ virtual void print(std::ostream &OS) const = 0;
+
+ /// dump - Debugging method that may be called through a debugger, just
+ /// invokes print on cerr.
+ void dump() const;
+
+ /// convertInitializerTo - This virtual function is a simple call-back
+ /// function that should be overridden to call the appropriate
+ /// RecTy::convertValue method.
+ ///
+ virtual Init *convertInitializerTo(RecTy *Ty) = 0;
+
+ /// convertInitializerBitRange - This method is used to implement the bitrange
+ /// selection operator. Given an initializer, it selects the specified bits
+ /// out, returning them as a new init of bits type. If it is not legal to use
+ /// the bit subscript operator on this initializer, return null.
+ ///
+ virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits) {
+ 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.
+ ///
+ virtual RecTy *getFieldType(const std::string &FieldName) const { return 0; }
+
+ /// getFieldInit - This method complements getFieldType to return the
+ /// initializer for the specified field. If getFieldType returns non-null
+ /// this method should return non-null, otherwise it returns null.
+ ///
+ virtual Init *getFieldInit(Record &R, const std::string &FieldName) const {
+ 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
+ /// users of the value to allow the value to propagate out.
+ ///
+ virtual Init *resolveReferences(Record &R) { return this; }
+};
+
+inline std::ostream &operator<<(std::ostream &OS, const Init &I) {
+ I.print(OS); return OS;
+}
+
+
+/// UnsetInit - ? - Represents an uninitialized value
+///
+struct UnsetInit : public Init {
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual bool isComplete() const { return false; }
+ virtual void print(std::ostream &OS) const { OS << "?"; }
+};
+
+
+/// BitInit - true/false - Represent a concrete initializer for a bit.
+///
+class BitInit : public Init {
+ bool Value;
+public:
+ BitInit(bool V) : Value(V) {}
+
+ bool getValue() const { return Value; }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual void print(std::ostream &OS) const { OS << (Value ? "1" : "0"); }
+};
+
+/// BitsInit - { a, b, c } - Represents an initializer for a BitsRecTy value.
+/// It contains a vector of bits, whose size is determined by the type.
+///
+class BitsInit : public Init {
+ std::vector<Init*> Bits;
+public:
+ BitsInit(unsigned Size) : Bits(Size) {}
+
+ unsigned getNumBits() const { return Bits.size(); }
+
+ Init *getBit(unsigned Bit) const {
+ assert(Bit < Bits.size() && "Bit index out of range!");
+ return Bits[Bit];
+ }
+ void setBit(unsigned Bit, Init *V) {
+ assert(Bit < Bits.size() && "Bit index out of range!");
+ assert(Bits[Bit] == 0 && "Bit already set!");
+ Bits[Bit] = V;
+ }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+ virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+
+ virtual bool isComplete() const {
+ for (unsigned i = 0; i != getNumBits(); ++i)
+ if (!getBit(i)->isComplete()) return false;
+ return true;
+ }
+ virtual void print(std::ostream &OS) const;
+
+ virtual Init *resolveReferences(Record &R);
+
+ // printXX - Print this bitstream with the specified format, returning true if
+ // it is not possible.
+ bool printInHex(std::ostream &OS) const;
+ bool printAsVariable(std::ostream &OS) const;
+ bool printAsUnset(std::ostream &OS) const;
+};
+
+
+/// IntInit - 7 - Represent an initalization by a literal integer value.
+///
+class IntInit : public Init {
+ int Value;
+public:
+ IntInit(int V) : Value(V) {}
+
+ int getValue() const { return Value; }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+ virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+
+ virtual void print(std::ostream &OS) const { OS << Value; }
+};
+
+
+/// StringInit - "foo" - Represent an initialization by a string value.
+///
+class StringInit : public Init {
+ std::string Value;
+public:
+ StringInit(const std::string &V) : Value(V) {}
+
+ const std::string &getValue() const { return Value; }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual void print(std::ostream &OS) const { OS << "\"" << Value << "\""; }
+};
+
+/// CodeInit - "[{...}]" - Represent a code fragment.
+///
+class CodeInit : public Init {
+ std::string Value;
+public:
+ CodeInit(const std::string &V) : Value(V) {}
+
+ const std::string getValue() const { return Value; }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual void print(std::ostream &OS) const { OS << "[{" << Value << "}]"; }
+};
+
+/// ListInit - [AL, AH, CL] - Represent a list of defs
+///
+class ListInit : public Init {
+ std::vector<Init*> Values;
+public:
+ ListInit(std::vector<Init*> &Vs) {
+ Values.swap(Vs);
+ }
+
+ unsigned getSize() const { return Values.size(); }
+ Init *getElement(unsigned i) const {
+ assert(i < Values.size() && "List element index out of range!");
+ return Values[i];
+ }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual void print(std::ostream &OS) const;
+};
+
+
+/// TypedInit - This is the common super-class of types that have a specific,
+/// explicit, type.
+///
+class TypedInit : public Init {
+ RecTy *Ty;
+public:
+ TypedInit(RecTy *T) : Ty(T) {}
+
+ RecTy *getType() const { return Ty; }
+
+ /// resolveBitReference - This method is used to implement
+ /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
+ /// simply return the resolved value, otherwise we return this.
+ ///
+ virtual Init *resolveBitReference(Record &R, unsigned Bit) = 0;
+};
+
+/// VarInit - 'Opcode' - Represent a reference to an entire variable object.
+///
+class VarInit : public TypedInit {
+ std::string VarName;
+public:
+ VarInit(const std::string &VN, RecTy *T) : TypedInit(T), VarName(VN) {}
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ const std::string &getName() const { return VarName; }
+
+ virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+
+ virtual Init *resolveBitReference(Record &R, unsigned Bit);
+
+ virtual RecTy *getFieldType(const std::string &FieldName) const;
+ virtual Init *getFieldInit(Record &R, const std::string &FieldName) const;
+
+ /// 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
+ /// users of the value to allow the value to propagate out.
+ ///
+ virtual Init *resolveReferences(Record &R);
+
+ virtual void print(std::ostream &OS) const { OS << VarName; }
+};
+
+
+/// VarBitInit - Opcode{0} - Represent access to one bit of a variable or field.
+///
+class VarBitInit : public Init {
+ TypedInit *TI;
+ unsigned Bit;
+public:
+ VarBitInit(TypedInit *T, unsigned B) : TI(T), Bit(B) {
+ assert(T->getType() && dynamic_cast<BitsRecTy*>(T->getType()) &&
+ ((BitsRecTy*)T->getType())->getNumBits() > B &&
+ "Illegal VarBitInit expression!");
+ }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ TypedInit *getVariable() const { return TI; }
+ unsigned getBitNum() const { return Bit; }
+
+ virtual void print(std::ostream &OS) const {
+ TI->print(OS); OS << "{" << Bit << "}";
+ }
+ virtual Init *resolveReferences(Record &R);
+};
+
+
+/// DefInit - AL - Represent a reference to a 'def' in the description
+///
+class DefInit : public Init {
+ Record *Def;
+public:
+ DefInit(Record *D) : Def(D) {}
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ Record *getDef() const { return Def; }
+
+ //virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+
+ virtual RecTy *getFieldType(const std::string &FieldName) const;
+ virtual Init *getFieldInit(Record &R, const std::string &FieldName) const;
+
+ virtual void print(std::ostream &OS) const;
+};
+
+
+/// FieldInit - X.Y - Represent a reference to a subfield of a variable
+///
+class FieldInit : public TypedInit {
+ Init *Rec; // Record we are referring to
+ std::string FieldName; // Field we are accessing
+public:
+ FieldInit(Init *R, const std::string &FN)
+ : TypedInit(R->getFieldType(FN)), Rec(R), FieldName(FN) {
+ assert(getType() && "FieldInit with non-record type!");
+ }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+
+ virtual Init *resolveBitReference(Record &R, unsigned Bit);
+
+ virtual Init *resolveReferences(Record &R);
+
+ virtual void print(std::ostream &OS) const {
+ Rec->print(OS); OS << "." << FieldName;
+ }
+};
+
+/// DagInit - (def a, b) - Represent a DAG tree value. DAG inits are required
+/// to have Records for their first value, after that, any legal Init is
+/// possible.
+///
+class DagInit : public Init {
+ Record *NodeTypeDef;
+ std::vector<Init*> Args;
+ std::vector<std::string> ArgNames;
+public:
+ DagInit(Record *D, const std::vector<std::pair<Init*, std::string> > &args)
+ : NodeTypeDef(D) {
+ Args.reserve(args.size());
+ ArgNames.reserve(args.size());
+ for (unsigned i = 0, e = args.size(); i != e; ++i) {
+ Args.push_back(args[i].first);
+ ArgNames.push_back(args[i].second);
+ }
+ }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ Record *getNodeType() const { return NodeTypeDef; }
+
+ unsigned getNumArgs() const { return Args.size(); }
+ Init *getArg(unsigned Num) const {
+ assert(Num < Args.size() && "Arg number out of range!");
+ return Args[Num];
+ }
+ const std::string &getArgName(unsigned Num) const {
+ assert(Num < ArgNames.size() && "Arg number out of range!");
+ return ArgNames[Num];
+ }
+
+ void setArg(unsigned Num, Init *I) {
+ assert(Num < Args.size() && "Arg number out of range!");
+ Args[Num] = I;
+ }
+
+ virtual void print(std::ostream &OS) const;
+};
+
+//===----------------------------------------------------------------------===//
+// High-Level Classes
+//===----------------------------------------------------------------------===//
+
+class RecordVal {
+ std::string Name;
+ RecTy *Ty;
+ unsigned Prefix;
+ Init *Value;
+public:
+ RecordVal(const std::string &N, RecTy *T, unsigned P);
+
+ const std::string &getName() const { return Name; }
+
+ unsigned getPrefix() const { return Prefix; }
+ RecTy *getType() const { return Ty; }
+ Init *getValue() const { return Value; }
+
+ bool setValue(Init *V) {
+ if (V) {
+ Value = V->convertInitializerTo(Ty);
+ return Value == 0;
+ }
+ Value = 0;
+ return false;
+ }
+
+ void dump() const;
+ void print(std::ostream &OS, bool PrintSem = true) const;
+};
+
+inline std::ostream &operator<<(std::ostream &OS, const RecordVal &RV) {
+ RV.print(OS << " ");
+ return OS;
+}
+
+struct Record {
+ const std::string Name;
+ std::vector<std::string> TemplateArgs;
+ std::vector<RecordVal> Values;
+ std::vector<Record*> SuperClasses;
+public:
+
+ Record(const std::string &N) : Name(N) {}
+ ~Record() {}
+
+ const std::string &getName() const { return Name; }
+ const std::vector<std::string> &getTemplateArgs() const {
+ return TemplateArgs;
+ }
+ const std::vector<RecordVal> &getValues() const { return Values; }
+ const std::vector<Record*> &getSuperClasses() const { return SuperClasses; }
+
+ bool isTemplateArg(const std::string &Name) const {
+ for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i)
+ if (TemplateArgs[i] == Name) return true;
+ return false;
+ }
+
+ const RecordVal *getValue(const std::string &Name) const {
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ if (Values[i].getName() == Name) return &Values[i];
+ return 0;
+ }
+ RecordVal *getValue(const std::string &Name) {
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ if (Values[i].getName() == Name) return &Values[i];
+ return 0;
+ }
+
+ void addTemplateArg(const std::string &Name) {
+ assert(!isTemplateArg(Name) && "Template arg already defined!");
+ TemplateArgs.push_back(Name);
+ }
+
+ void addValue(const RecordVal &RV) {
+ assert(getValue(RV.getName()) == 0 && "Value already added!");
+ Values.push_back(RV);
+ }
+
+ void removeValue(const std::string &Name) {
+ assert(getValue(Name) && "Cannot remove an entry that does not exist!");
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ if (Values[i].getName() == Name) {
+ Values.erase(Values.begin()+i);
+ return;
+ }
+ assert(0 && "Name does not exist in record!");
+ }
+
+ bool isSubClassOf(Record *R) const {
+ for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
+ if (SuperClasses[i] == R)
+ return true;
+ return false;
+ }
+
+ bool isSubClassOf(const std::string &Name) const {
+ for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
+ if (SuperClasses[i]->getName() == Name)
+ return true;
+ return false;
+ }
+
+ void addSuperClass(Record *R) {
+ assert(!isSubClassOf(R) && "Already subclassing record!");
+ SuperClasses.push_back(R);
+ }
+
+ // resolveReferences - If there are any field references that refer to fields
+ // that have been filled in, we can propagate the values now.
+ //
+ void resolveReferences();
+
+ void dump() const;
+
+ //===--------------------------------------------------------------------===//
+ // High-level methods useful to tablegen back-ends
+ //
+
+ /// getValueInit - Return the initializer for a value with the specified name,
+ /// or throw an exception if the field does not exist.
+ ///
+ Init *getValueInit(const std::string &FieldName) const;
+
+ /// getValueAsString - This method looks up the specified field and returns
+ /// its value as a string, throwing an exception if the field does not exist
+ /// or if the value is not a string.
+ ///
+ std::string getValueAsString(const std::string &FieldName) const;
+
+ /// getValueAsBitsInit - This method looks up the specified field and returns
+ /// its value as a BitsInit, throwing an exception if the field does not exist
+ /// or if the value is not the right type.
+ ///
+ BitsInit *getValueAsBitsInit(const std::string &FieldName) const;
+
+ /// getValueAsListInit - This method looks up the specified field and returns
+ /// its value as a ListInit, throwing an exception if the field does not exist
+ /// or if the value is not the right type.
+ ///
+ ListInit *getValueAsListInit(const std::string &FieldName) const;
+
+ /// getValueAsDef - This method looks up the specified field and returns its
+ /// value as a Record, throwing an exception if the field does not exist or if
+ /// the value is not the right type.
+ ///
+ Record *getValueAsDef(const std::string &FieldName) const;
+
+ /// getValueAsBit - This method looks up the specified field and returns its
+ /// value as a bit, throwing an exception if the field does not exist or if
+ /// the value is not the right type.
+ ///
+ bool getValueAsBit(const std::string &FieldName) const;
+
+ /// getValueAsInt - This method looks up the specified field and returns its
+ /// value as an int, throwing an exception if the field does not exist or if
+ /// the value is not the right type.
+ ///
+ int getValueAsInt(const std::string &FieldName) const;
+
+ /// getValueAsDag - This method looks up the specified field and returns its
+ /// value as an Dag, throwing an exception if the field does not exist or if
+ /// the value is not the right type.
+ ///
+ DagInit *getValueAsDag(const std::string &FieldName) const;
+};
+
+std::ostream &operator<<(std::ostream &OS, const Record &R);
+
+class RecordKeeper {
+ std::map<std::string, Record*> Classes, Defs;
+public:
+ ~RecordKeeper() {
+ for (std::map<std::string, Record*>::iterator I = Classes.begin(),
+ E = Classes.end(); I != E; ++I)
+ delete I->second;
+ for (std::map<std::string, Record*>::iterator I = Defs.begin(),
+ E = Defs.end(); I != E; ++I)
+ delete I->second;
+ }
+
+ const std::map<std::string, Record*> &getClasses() const { return Classes; }
+ const std::map<std::string, Record*> &getDefs() const { return Defs; }
+
+ Record *getClass(const std::string &Name) const {
+ std::map<std::string, Record*>::const_iterator I = Classes.find(Name);
+ return I == Classes.end() ? 0 : I->second;
+ }
+ Record *getDef(const std::string &Name) const {
+ std::map<std::string, Record*>::const_iterator I = Defs.find(Name);
+ return I == Defs.end() ? 0 : I->second;
+ }
+ void addClass(Record *R) {
+ assert(getClass(R->getName()) == 0 && "Class already exists!");
+ Classes.insert(std::make_pair(R->getName(), R));
+ }
+ void addDef(Record *R) {
+ assert(getDef(R->getName()) == 0 && "Def already exists!");
+ Defs.insert(std::make_pair(R->getName(), R));
+ }
+
+ //===--------------------------------------------------------------------===//
+ // High-level helper methods, useful for tablegen backends...
+
+ /// getAllDerivedDefinitions - This method returns all concrete definitions
+ /// that derive from the specified class name. If a class with the specified
+ /// name does not exist, an exception is thrown.
+ std::vector<Record*>
+ getAllDerivedDefinitions(const std::string &ClassName) const;
+
+
+ void dump() const;
+};
+
+std::ostream &operator<<(std::ostream &OS, const RecordKeeper &RK);
+
+extern RecordKeeper Records;
+
+#endif
diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
new file mode 100644
index 00000000000..af3efe3a9c4
--- /dev/null
+++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -0,0 +1,234 @@
+//===- RegisterInfoEmitter.cpp - Generate a Register File Desc. -*- C++ -*-===//
+//
+// This tablegen backend is responsible for emitting a description of a target
+// register file for a code generator. It uses instances of the Register,
+// RegisterAliases, and RegisterClass classes to gather this information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterInfoEmitter.h"
+#include "CodeGenWrappers.h"
+#include "Record.h"
+#include "Support/StringExtras.h"
+#include <set>
+
+// runEnums - Print out enum values for all of the registers.
+void RegisterInfoEmitter::runEnums(std::ostream &OS) {
+ std::vector<Record*> Registers = Records.getAllDerivedDefinitions("Register");
+
+ if (Registers.size() == 0)
+ throw std::string("No 'Register' subclasses defined!");
+
+ std::string Namespace = Registers[0]->getValueAsString("Namespace");
+
+ EmitSourceFileHeader("Target Register Enum Values", OS);
+
+ if (!Namespace.empty())
+ OS << "namespace " << Namespace << " {\n";
+ OS << " enum {\n NoRegister,\n";
+
+ for (unsigned i = 0, e = Registers.size(); i != e; ++i)
+ OS << " " << Registers[i]->getName() << ", \t// " << i+1 << "\n";
+
+ OS << " };\n";
+ if (!Namespace.empty())
+ OS << "}\n";
+}
+
+void RegisterInfoEmitter::runHeader(std::ostream &OS) {
+ EmitSourceFileHeader("Register Information Header Fragment", OS);
+ const std::string &TargetName = CodeGenTarget().getName();
+ std::string ClassName = TargetName + "GenRegisterInfo";
+
+ OS << "#include \"llvm/Target/MRegisterInfo.h\"\n\n";
+
+ OS << "struct " << ClassName << " : public MRegisterInfo {\n"
+ << " " << ClassName
+ << "(int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n"
+ << " const unsigned* getCalleeSaveRegs() const;\n"
+ << "};\n\n";
+
+ std::vector<Record*> RegisterClasses =
+ Records.getAllDerivedDefinitions("RegisterClass");
+
+ OS << "namespace " << TargetName << " { // Register classes\n";
+ for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
+ if (RegisterClasses[i]->getValueAsBit("isDummyClass"))
+ continue; // Ignore dummies
+
+ const std::string &Name = RegisterClasses[i]->getName();
+ if (Name.size() < 9 || Name[9] != '.') // Ignore anonymous classes
+ OS << " extern TargetRegisterClass *" << Name << "RegisterClass;\n";
+ }
+ OS << "} // end of namespace " << TargetName << "\n\n";
+}
+
+// RegisterInfoEmitter::run - Main register file description emitter.
+//
+void RegisterInfoEmitter::run(std::ostream &OS) {
+ EmitSourceFileHeader("Register Information Source Fragment", OS);
+
+ // Start out by emitting each of the register classes... to do this, we build
+ // a set of registers which belong to a register class, this is to ensure that
+ // each register is only in a single register class.
+ //
+ std::vector<Record*> RegisterClasses =
+ Records.getAllDerivedDefinitions("RegisterClass");
+
+ std::vector<Record*> Registers = Records.getAllDerivedDefinitions("Register");
+
+ std::set<Record*> RegistersFound;
+ std::vector<std::string> RegClassNames;
+
+ // Loop over all of the register classes... emitting each one.
+ OS << "namespace { // Register classes...\n";
+
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ Record *RC = RegisterClasses[rc];
+ if (RC->getValueAsBit("isDummyClass")) continue; // Ignore dummies
+
+ std::string Name = RC->getName();
+ if (Name.size() > 9 && Name[9] == '.') {
+ static unsigned AnonCounter = 0;
+ Name = "AnonRegClass_"+utostr(AnonCounter++);
+ }
+
+ RegClassNames.push_back(Name);
+
+ // Emit the register list now...
+ OS << " // " << Name << " Register Class...\n const unsigned " << Name
+ << "[] = {\n ";
+ ListInit *RegList = RC->getValueAsListInit("MemberList");
+ for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
+ DefInit *RegDef = dynamic_cast<DefInit*>(RegList->getElement(i));
+ if (!RegDef) throw "Register class member is not a record!";
+ Record *Reg = RegDef->getDef();
+ if (!Reg->isSubClassOf("Register"))
+ throw "Register Class member '" + Reg->getName() +
+ " does not derive from the Register class!";
+ if (RegistersFound.count(Reg))
+ throw "Register '" + Reg->getName() +
+ "' included in multiple register classes!";
+ RegistersFound.insert(Reg);
+ OS << getQualifiedName(Reg) << ", ";
+ }
+ OS << "\n };\n\n";
+
+ OS << " struct " << Name << "Class : public TargetRegisterClass {\n"
+ << " " << Name << "Class() : TargetRegisterClass("
+ << RC->getValueAsInt("Size")/8 << ", " << RC->getValueAsInt("Alignment")
+ << ", " << Name << ", " << Name << " + " << RegList->getSize()
+ << ") {}\n";
+
+ if (CodeInit *CI = dynamic_cast<CodeInit*>(RC->getValueInit("Methods")))
+ OS << CI->getValue();
+ else
+ throw "Expected 'code' fragment for 'Methods' value in register class '"+
+ RC->getName() + "'!";
+
+ OS << " } " << Name << "Instance;\n\n";
+ }
+
+ OS << " const TargetRegisterClass* const RegisterClasses[] = {\n";
+ for (unsigned i = 0, e = RegClassNames.size(); i != e; ++i)
+ OS << " &" << RegClassNames[i] << "Instance,\n";
+ OS << " };\n";
+
+ // Emit register class aliases...
+ std::vector<Record*> RegisterAliasesRecs =
+ Records.getAllDerivedDefinitions("RegisterAliases");
+ std::map<Record*, std::set<Record*> > RegisterAliases;
+
+ for (unsigned i = 0, e = RegisterAliasesRecs.size(); i != e; ++i) {
+ Record *AS = RegisterAliasesRecs[i];
+ Record *R = AS->getValueAsDef("Reg");
+ ListInit *LI = AS->getValueAsListInit("Aliases");
+
+ // Add information that R aliases all of the elements in the list... and
+ // that everything in the list aliases R.
+ for (unsigned j = 0, e = LI->getSize(); j != e; ++j) {
+ DefInit *Reg = dynamic_cast<DefInit*>(LI->getElement(j));
+ if (!Reg) throw "ERROR: Alias list element is not a def!";
+ if (RegisterAliases[R].count(Reg->getDef()))
+ std::cerr << "Warning: register alias between " << getQualifiedName(R)
+ << " and " << getQualifiedName(Reg->getDef())
+ << " specified multiple times!\n";
+ RegisterAliases[R].insert(Reg->getDef());
+
+ if (RegisterAliases[Reg->getDef()].count(R))
+ std::cerr << "Warning: register alias between " << getQualifiedName(R)
+ << " and " << getQualifiedName(Reg->getDef())
+ << " specified multiple times!\n";
+ RegisterAliases[Reg->getDef()].insert(R);
+ }
+ }
+
+ if (!RegisterAliases.empty())
+ OS << "\n\n // Register Alias Sets...\n";
+
+ // Loop over all of the registers which have aliases, emitting the alias list
+ // to memory.
+ for (std::map<Record*, std::set<Record*> >::iterator
+ I = RegisterAliases.begin(), E = RegisterAliases.end(); I != E; ++I) {
+ OS << " const unsigned " << I->first->getName() << "_AliasSet[] = { ";
+ for (std::set<Record*>::iterator ASI = I->second.begin(),
+ E = I->second.end(); ASI != E; ++ASI)
+ OS << getQualifiedName(*ASI) << ", ";
+ OS << "0 };\n";
+ }
+
+ OS << "\n const MRegisterDesc RegisterDescriptors[] = { // Descriptors\n";
+ OS << " { \"NOREG\",\t0,\t\t0,\t0 },\n";
+ // Now that register alias sets have been emitted, emit the register
+ // descriptors now.
+ for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
+ Record *Reg = Registers[i];
+ OS << " { \"";
+ if (!Reg->getValueAsString("Name").empty())
+ OS << Reg->getValueAsString("Name");
+ else
+ OS << Reg->getName();
+ OS << "\",\t";
+ if (RegisterAliases.count(Reg))
+ OS << Reg->getName() << "_AliasSet,\t";
+ else
+ OS << "0,\t\t";
+ OS << "0, 0 },\n";
+ }
+ OS << " };\n"; // End of register descriptors...
+ OS << "}\n\n"; // End of anonymous namespace...
+
+ CodeGenTarget Target;
+
+ OS << "namespace " << Target.getName() << " { // Register classes\n";
+ for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
+ if (RegisterClasses[i]->getValueAsBit("isDummyClass"))
+ continue; // Ignore dummies
+
+ const std::string &Name = RegisterClasses[i]->getName();
+ if (Name.size() < 9 || Name[9] != '.') // Ignore anonymous classes
+ OS << " TargetRegisterClass *" << Name << "RegisterClass = &"
+ << Name << "Instance;\n";
+ }
+ OS << "} // end of namespace " << Target.getName() << "\n\n";
+
+
+
+ std::string ClassName = Target.getName() + "GenRegisterInfo";
+
+ // Emit the constructor of the class...
+ OS << ClassName << "::" << ClassName
+ << "(int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n"
+ << " : MRegisterInfo(RegisterDescriptors, " << Registers.size()+1
+ << ", RegisterClasses, RegisterClasses+" << RegClassNames.size() << ",\n "
+ << " CallFrameSetupOpcode, CallFrameDestroyOpcode) {}\n\n";
+
+ // Emit the getCalleeSaveRegs method...
+ OS << "const unsigned* " << ClassName << "::getCalleeSaveRegs() const {\n"
+ << " static const unsigned CalleeSaveRegs[] = {\n ";
+
+ const std::vector<Record*> &CSR = Target.getCalleeSavedRegisters();
+ for (unsigned i = 0, e = CSR.size(); i != e; ++i)
+ OS << getQualifiedName(CSR[i]) << ", ";
+ OS << " 0\n };\n return CalleeSaveRegs;\n}\n\n";
+}
diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.h b/llvm/utils/TableGen/RegisterInfoEmitter.h
new file mode 100644
index 00000000000..65a03303cdd
--- /dev/null
+++ b/llvm/utils/TableGen/RegisterInfoEmitter.h
@@ -0,0 +1,29 @@
+//===- RegisterInfoEmitter.h - Generate a Register File Desc. ---*- C++ -*-===//
+//
+// This tablegen backend is responsible for emitting a description of a target
+// register file for a code generator. It uses instances of the Register,
+// RegisterAliases, and RegisterClass classes to gather this information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef REGISTER_INFO_EMITTER_H
+#define REGISTER_INFO_EMITTER_H
+
+#include "TableGenBackend.h"
+
+class RegisterInfoEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+public:
+ RegisterInfoEmitter(RecordKeeper &R) : Records(R) {}
+
+ // run - Output the register file description, returning true on failure.
+ void run(std::ostream &o);
+
+ // runHeader - Emit a header fragment for the register info emitter.
+ void runHeader(std::ostream &o);
+
+ // runEnums - Print out enum values for all of the registers.
+ void runEnums(std::ostream &o);
+};
+
+#endif
diff --git a/llvm/utils/TableGen/TableGen.cpp b/llvm/utils/TableGen/TableGen.cpp
new file mode 100644
index 00000000000..971ac9081aa
--- /dev/null
+++ b/llvm/utils/TableGen/TableGen.cpp
@@ -0,0 +1,482 @@
+//===- TableGen.cpp - Top-Level TableGen implementation -------------------===//
+//
+// TableGen is a tool which can be used to build up a description of something,
+// then invoke one or more "tablegen backends" to emit information about the
+// description in some predefined format. In practice, this is used by the LLVM
+// code generators to automate generation of a code generator through a
+// high-level description of the target.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Record.h"
+#include "Support/CommandLine.h"
+#include "Support/Signals.h"
+#include "Support/FileUtilities.h"
+#include "CodeEmitterGen.h"
+#include "RegisterInfoEmitter.h"
+#include "InstrInfoEmitter.h"
+#include "InstrSelectorEmitter.h"
+#include <algorithm>
+#include <cstdio>
+#include <fstream>
+
+enum ActionType {
+ PrintRecords,
+ GenEmitter,
+ GenRegisterEnums, GenRegister, GenRegisterHeader,
+ GenInstrEnums, GenInstrs, GenInstrSelector,
+ PrintEnums,
+ Parse,
+};
+
+namespace {
+ cl::opt<ActionType>
+ Action(cl::desc("Action to perform:"),
+ cl::values(clEnumValN(PrintRecords, "print-records",
+ "Print all records to stdout (default)"),
+ clEnumValN(GenEmitter, "gen-emitter",
+ "Generate machine code emitter"),
+ clEnumValN(GenRegisterEnums, "gen-register-enums",
+ "Generate enum values for registers"),
+ clEnumValN(GenRegister, "gen-register-desc",
+ "Generate a register info description"),
+ clEnumValN(GenRegisterHeader, "gen-register-desc-header",
+ "Generate a register info description header"),
+ clEnumValN(GenInstrEnums, "gen-instr-enums",
+ "Generate enum values for instructions"),
+ clEnumValN(GenInstrs, "gen-instr-desc",
+ "Generate instruction descriptions"),
+ clEnumValN(GenInstrSelector, "gen-instr-selector",
+ "Generate an instruction selector"),
+ clEnumValN(PrintEnums, "print-enums",
+ "Print enum values for a class"),
+ clEnumValN(Parse, "parse",
+ "Interpret machine code (testing only)"),
+ 0));
+
+ cl::opt<std::string>
+ Class("class", cl::desc("Print Enum list for this class"),
+ cl::value_desc("class name"));
+
+ cl::opt<std::string>
+ OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
+ cl::init("-"));
+
+ cl::opt<std::string>
+ InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
+
+ cl::opt<std::string>
+ IncludeDir("I", cl::desc("Directory of include files"),
+ cl::value_desc("directory"), cl::init(""));
+}
+
+
+void ParseFile(const std::string &Filename, const std::string & IncludeDir);
+
+RecordKeeper Records;
+
+static Init *getBit(Record *R, unsigned BitNo) {
+ const std::vector<RecordVal> &V = R->getValues();
+ for (unsigned i = 0, e = V.size(); i != e; ++i)
+ if (V[i].getPrefix()) {
+ assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
+ "Can only handle fields of bits<> type!");
+ BitsInit *I = (BitsInit*)V[i].getValue();
+ if (BitNo < I->getNumBits())
+ return I->getBit(BitNo);
+ BitNo -= I->getNumBits();
+ }
+
+ std::cerr << "Cannot find requested bit!\n";
+ abort();
+ return 0;
+}
+
+static unsigned getNumBits(Record *R) {
+ const std::vector<RecordVal> &V = R->getValues();
+ unsigned Num = 0;
+ for (unsigned i = 0, e = V.size(); i != e; ++i)
+ if (V[i].getPrefix()) {
+ assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
+ "Can only handle fields of bits<> type!");
+ Num += ((BitsInit*)V[i].getValue())->getNumBits();
+ }
+ return Num;
+}
+
+static bool BitsAreFixed(Record *I1, Record *I2, unsigned BitNo) {
+ return dynamic_cast<BitInit*>(getBit(I1, BitNo)) &&
+ dynamic_cast<BitInit*>(getBit(I2, BitNo));
+}
+
+static bool BitsAreEqual(Record *I1, Record *I2, unsigned BitNo) {
+ BitInit *Bit1 = dynamic_cast<BitInit*>(getBit(I1, BitNo));
+ BitInit *Bit2 = dynamic_cast<BitInit*>(getBit(I2, BitNo));
+
+ return Bit1 && Bit2 && Bit1->getValue() == Bit2->getValue();
+}
+
+static bool BitRangesEqual(Record *I1, Record *I2,
+ unsigned Start, unsigned End) {
+ for (unsigned i = Start; i != End; ++i)
+ if (!BitsAreEqual(I1, I2, i))
+ return false;
+ return true;
+}
+
+static unsigned getFirstFixedBit(Record *R, unsigned FirstFixedBit) {
+ // Look for the first bit of the pair that are required to be 0 or 1.
+ while (!dynamic_cast<BitInit*>(getBit(R, FirstFixedBit)))
+ ++FirstFixedBit;
+ return FirstFixedBit;
+}
+
+static void FindInstDifferences(Record *I1, Record *I2,
+ unsigned FirstFixedBit, unsigned MaxBits,
+ unsigned &FirstVaryingBitOverall,
+ unsigned &LastFixedBitOverall) {
+ // Compare the first instruction to the rest of the instructions, looking for
+ // fields that differ.
+ //
+ unsigned FirstVaryingBit = FirstFixedBit;
+ while (FirstVaryingBit < MaxBits && BitsAreEqual(I1, I2, FirstVaryingBit))
+ ++FirstVaryingBit;
+
+ unsigned LastFixedBit = FirstVaryingBit;
+ while (LastFixedBit < MaxBits && BitsAreFixed(I1, I2, LastFixedBit))
+ ++LastFixedBit;
+
+ if (FirstVaryingBit < FirstVaryingBitOverall)
+ FirstVaryingBitOverall = FirstVaryingBit;
+ if (LastFixedBit < LastFixedBitOverall)
+ LastFixedBitOverall = LastFixedBit;
+}
+
+static bool getBitValue(Record *R, unsigned BitNo) {
+ Init *I = getBit(R, BitNo);
+ assert(dynamic_cast<BitInit*>(I) && "Bit should be fixed!");
+ return ((BitInit*)I)->getValue();
+}
+
+struct BitComparator {
+ unsigned BitBegin, BitEnd;
+ BitComparator(unsigned B, unsigned E) : BitBegin(B), BitEnd(E) {}
+
+ bool operator()(Record *R1, Record *R2) { // Return true if R1 is less than R2
+ for (unsigned i = BitBegin; i != BitEnd; ++i) {
+ bool V1 = getBitValue(R1, i), V2 = getBitValue(R2, i);
+ if (V1 < V2)
+ return true;
+ else if (V2 < V1)
+ return false;
+ }
+ return false;
+ }
+};
+
+static void PrintRange(std::vector<Record*>::iterator I,
+ std::vector<Record*>::iterator E) {
+ while (I != E) std::cerr << **I++;
+}
+
+static bool getMemoryBit(unsigned char *M, unsigned i) {
+ return (M[i/8] & (1 << (i&7))) != 0;
+}
+
+static unsigned getFirstFixedBitInSequence(std::vector<Record*>::iterator IB,
+ std::vector<Record*>::iterator IE,
+ unsigned StartBit) {
+ unsigned FirstFixedBit = 0;
+ for (std::vector<Record*>::iterator I = IB; I != IE; ++I)
+ FirstFixedBit = std::max(FirstFixedBit, getFirstFixedBit(*I, StartBit));
+ return FirstFixedBit;
+}
+
+// ParseMachineCode - Try to split the vector of instructions (which is
+// intentionally taken by-copy) in half, narrowing down the possible
+// instructions that we may have found. Eventually, this list will get pared
+// down to zero or one instruction, in which case we have a match or failure.
+//
+static Record *ParseMachineCode(std::vector<Record*>::iterator InstsB,
+ std::vector<Record*>::iterator InstsE,
+ unsigned char *M) {
+ assert(InstsB != InstsE && "Empty range?");
+ if (InstsB+1 == InstsE) {
+ // Only a single instruction, see if we match it...
+ Record *Inst = *InstsB;
+ for (unsigned i = 0, e = getNumBits(Inst); i != e; ++i)
+ if (BitInit *BI = dynamic_cast<BitInit*>(getBit(Inst, i)))
+ if (getMemoryBit(M, i) != BI->getValue())
+ throw std::string("Parse failed!\n");
+ return Inst;
+ }
+
+ unsigned MaxBits = ~0;
+ for (std::vector<Record*>::iterator I = InstsB; I != InstsE; ++I)
+ MaxBits = std::min(MaxBits, getNumBits(*I));
+
+ unsigned FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, 0);
+ unsigned FirstVaryingBit, LastFixedBit;
+ do {
+ FirstVaryingBit = ~0;
+ LastFixedBit = ~0;
+ for (std::vector<Record*>::iterator I = InstsB+1; I != InstsE; ++I)
+ FindInstDifferences(*InstsB, *I, FirstFixedBit, MaxBits,
+ FirstVaryingBit, LastFixedBit);
+ if (FirstVaryingBit == MaxBits) {
+ std::cerr << "ERROR: Could not find bit to distinguish between "
+ << "the following entries!\n";
+ PrintRange(InstsB, InstsE);
+ }
+
+#if 0
+ std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
+ << ": " << InstsE-InstsB << "\n";
+#endif
+
+ FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, FirstVaryingBit);
+ } while (FirstVaryingBit != FirstFixedBit);
+
+ //std::cerr << "\n\nXXXXXXXXXXXXXXXXX\n\n";
+ //PrintRange(InstsB, InstsE);
+
+ // Sort the Insts list so that the entries have all of the bits in the range
+ // [FirstVaryingBit,LastFixedBit) sorted. These bits are all guaranteed to be
+ // set to either 0 or 1 (BitInit values), which simplifies things.
+ //
+ std::sort(InstsB, InstsE, BitComparator(FirstVaryingBit, LastFixedBit));
+
+ // Once the list is sorted by these bits, split the bit list into smaller
+ // lists, and recurse on each one.
+ //
+ std::vector<Record*>::iterator RangeBegin = InstsB;
+ Record *Match = 0;
+ while (RangeBegin != InstsE) {
+ std::vector<Record*>::iterator RangeEnd = RangeBegin+1;
+ while (RangeEnd != InstsE &&
+ BitRangesEqual(*RangeBegin, *RangeEnd, FirstVaryingBit, LastFixedBit))
+ ++RangeEnd;
+
+ // We just identified a range of equal instructions. If this range is the
+ // input range, we were not able to distinguish between the instructions in
+ // the set. Print an error and exit!
+ //
+ if (RangeBegin == InstsB && RangeEnd == InstsE) {
+ std::cerr << "Error: Could not distinguish among the following insts!:\n";
+ PrintRange(InstsB, InstsE);
+ abort();
+ }
+
+#if 0
+ std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
+ << ": [" << RangeEnd-RangeBegin << "] - ";
+ for (int i = LastFixedBit-1; i >= (int)FirstVaryingBit; --i)
+ std::cerr << (int)((BitInit*)getBit(*RangeBegin, i))->getValue() << " ";
+ std::cerr << "\n";
+#endif
+
+ if (Record *R = ParseMachineCode(RangeBegin, RangeEnd, M)) {
+ if (Match) {
+ std::cerr << "Error: Multiple matches found:\n";
+ PrintRange(InstsB, InstsE);
+ }
+
+ assert(Match == 0 && "Multiple matches??");
+ Match = R;
+ }
+ RangeBegin = RangeEnd;
+ }
+
+ return Match;
+}
+
+static void PrintValue(Record *I, unsigned char *Ptr, const RecordVal &Val) {
+ assert(dynamic_cast<BitsInit*>(Val.getValue()) &&
+ "Can only handle undefined bits<> types!");
+ BitsInit *BI = (BitsInit*)Val.getValue();
+ assert(BI->getNumBits() <= 32 && "Can only handle fields up to 32 bits!");
+
+ unsigned Value = 0;
+ const std::vector<RecordVal> &Vals = I->getValues();
+
+ // Start by filling in fixed values...
+ for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
+ if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(i)))
+ Value |= B->getValue() << i;
+
+ // Loop over all of the fields in the instruction adding in any
+ // contributions to this value (due to bit references).
+ //
+ unsigned Offset = 0;
+ for (unsigned f = 0, e = Vals.size(); f != e; ++f)
+ if (Vals[f].getPrefix()) {
+ BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();
+ if (&Vals[f] == &Val) {
+ // Read the bits directly now...
+ for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
+ Value |= getMemoryBit(Ptr, Offset+i) << i;
+ break;
+ }
+
+ // Scan through the field looking for bit initializers of the current
+ // variable...
+ for (unsigned i = 0, e = FieldInitializer->getNumBits(); i != e; ++i)
+ if (VarBitInit *VBI =
+ dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) {
+ TypedInit *TI = VBI->getVariable();
+ if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
+ if (VI->getName() == Val.getName())
+ Value |= getMemoryBit(Ptr, Offset+i) << VBI->getBitNum();
+ } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
+ // FIXME: implement this!
+ std::cerr << "FIELD INIT not implemented yet!\n";
+ }
+ }
+ Offset += FieldInitializer->getNumBits();
+ }
+
+ std::cout << "0x" << std::hex << Value << std::dec;
+}
+
+static void PrintInstruction(Record *I, unsigned char *Ptr) {
+ std::cout << "Inst " << getNumBits(I)/8 << " bytes: "
+ << "\t" << I->getName() << "\t" << *I->getValue("Name")->getValue()
+ << "\t";
+
+ const std::vector<RecordVal> &Vals = I->getValues();
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i)
+ if (!Vals[i].getValue()->isComplete()) {
+ std::cout << Vals[i].getName() << "=";
+ PrintValue(I, Ptr, Vals[i]);
+ std::cout << "\t";
+ }
+
+ std::cout << "\n";// << *I;
+}
+
+static void ParseMachineCode() {
+ // X86 code
+ unsigned char Buffer[] = {
+ 0x55, // push EBP
+ 0x89, 0xE5, // mov EBP, ESP
+ //0x83, 0xEC, 0x08, // sub ESP, 0x8
+ 0xE8, 1, 2, 3, 4, // call +0x04030201
+ 0x89, 0xEC, // mov ESP, EBP
+ 0x5D, // pop EBP
+ 0xC3, // ret
+ 0x90, // nop
+ 0xC9, // leave
+ 0x89, 0xF6, // mov ESI, ESI
+ 0x68, 1, 2, 3, 4, // push 0x04030201
+ 0x5e, // pop ESI
+ 0xFF, 0xD0, // call EAX
+ 0xB8, 1, 2, 3, 4, // mov EAX, 0x04030201
+ 0x85, 0xC0, // test EAX, EAX
+ 0xF4, // hlt
+ };
+
+#if 0
+ // SparcV9 code
+ unsigned char Buffer[] = { 0xbf, 0xe0, 0x20, 0x1f, 0x1, 0x0, 0x0, 0x1,
+ 0x0, 0x0, 0x0, 0x0, 0xc1, 0x0, 0x20, 0x1, 0x1,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x1,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xaf, 0xe8, 0x20, 0x17
+ };
+#endif
+
+ std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
+
+ unsigned char *BuffPtr = Buffer;
+ while (1) {
+ Record *R = ParseMachineCode(Insts.begin(), Insts.end(), BuffPtr);
+ PrintInstruction(R, BuffPtr);
+
+ unsigned Bits = getNumBits(R);
+ assert((Bits & 7) == 0 && "Instruction is not an even number of bytes!");
+ BuffPtr += Bits/8;
+ }
+}
+
+
+int main(int argc, char **argv) {
+ cl::ParseCommandLineOptions(argc, argv);
+ ParseFile(InputFilename, IncludeDir);
+
+ std::ostream *Out = &std::cout;
+ if (OutputFilename != "-") {
+ // Output to a .tmp file, because we don't actually want to overwrite the
+ // output file unless the generated file is different or the specified file
+ // does not exist.
+ Out = new std::ofstream((OutputFilename+".tmp").c_str());
+
+ if (!Out->good()) {
+ std::cerr << argv[0] << ": error opening " << OutputFilename << ".tmp!\n";
+ return 1;
+ }
+
+ // Make sure the file gets removed if *gasp* tablegen crashes...
+ RemoveFileOnSignal(OutputFilename+".tmp");
+ }
+
+ try {
+ switch (Action) {
+ case PrintRecords:
+ *Out << Records; // No argument, dump all contents
+ break;
+ case Parse:
+ ParseMachineCode();
+ break;
+ case GenEmitter:
+ CodeEmitterGen(Records).run(*Out);
+ break;
+
+ case GenRegisterEnums:
+ RegisterInfoEmitter(Records).runEnums(*Out);
+ break;
+ case GenRegister:
+ RegisterInfoEmitter(Records).run(*Out);
+ break;
+ case GenRegisterHeader:
+ RegisterInfoEmitter(Records).runHeader(*Out);
+ break;
+
+ case GenInstrEnums:
+ InstrInfoEmitter(Records).runEnums(*Out);
+ break;
+ case GenInstrs:
+ InstrInfoEmitter(Records).run(*Out);
+ break;
+ case GenInstrSelector:
+ InstrSelectorEmitter(Records).run(*Out);
+ break;
+ case PrintEnums:
+ std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
+ for (unsigned i = 0, e = Recs.size(); i != e; ++i)
+ *Out << Recs[i] << ", ";
+ *Out << "\n";
+ break;
+ }
+ } catch (const std::string &Error) {
+ std::cerr << Error << "\n";
+ if (Out != &std::cout) {
+ delete Out; // Close the file
+ std::remove(OutputFilename.c_str()); // Remove the file, it's broken
+ }
+ return 1;
+ }
+
+ if (Out != &std::cout) {
+ delete Out; // Close the file
+
+ // Now that we have generated the result, check to see if we either don't
+ // have the requested file, or if the requested file is different than the
+ // file we generated. If so, move the generated file over the requested
+ // file. Otherwise, just remove the file we just generated, so 'make'
+ // doesn't try to regenerate tons of dependencies.
+ //
+ MoveFileOverIfUpdated(OutputFilename+".tmp", OutputFilename);
+ }
+ return 0;
+}
diff --git a/llvm/utils/TableGen/TableGenBackend.cpp b/llvm/utils/TableGen/TableGenBackend.cpp
new file mode 100644
index 00000000000..b86ae72ce9d
--- /dev/null
+++ b/llvm/utils/TableGen/TableGenBackend.cpp
@@ -0,0 +1,27 @@
+//===- TableGenBackend.cpp - Base class for TableGen Backends ---*- C++ -*-===//
+//
+// This file provides useful services for TableGen backends...
+//
+//===----------------------------------------------------------------------===//
+
+#include "TableGenBackend.h"
+#include "Record.h"
+#include <iostream>
+
+void TableGenBackend::EmitSourceFileHeader(const std::string &Desc,
+ std::ostream &OS) const {
+ OS << "//===- TableGen'erated file -------------------------------------*-"
+ " C++ -*-===//\n//\n// " << Desc << "\n//\n// Automatically generate"
+ "d file, do not edit!\n//\n//===------------------------------------"
+ "----------------------------------===//\n\n";
+}
+
+/// getQualifiedName - Return the name of the specified record, with a
+/// namespace qualifier if the record contains one.
+///
+std::string TableGenBackend::getQualifiedName(Record *R) const {
+ std::string Namespace = R->getValueAsString("Namespace");
+ if (Namespace.empty()) return R->getName();
+ return Namespace + "::" + R->getName();
+}
+
diff --git a/llvm/utils/TableGen/TableGenBackend.h b/llvm/utils/TableGen/TableGenBackend.h
new file mode 100644
index 00000000000..8dfbaddad16
--- /dev/null
+++ b/llvm/utils/TableGen/TableGenBackend.h
@@ -0,0 +1,34 @@
+//===- TableGenBackend.h - Base class for TableGen Backends -----*- C++ -*-===//
+//
+// The TableGenBackend class is provided as a common interface for all TableGen
+// backends. It provides useful services and an standardized interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TABLEGENBACKEND_H
+#define TABLEGENBACKEND_H
+
+#include <string>
+#include <iosfwd>
+class Record;
+class RecordKeeper;
+
+struct TableGenBackend {
+ virtual ~TableGenBackend() {}
+
+ // run - All TableGen backends should implement the run method, which should
+ // be the main entry point.
+ virtual void run(std::ostream &OS) = 0;
+
+
+public: // Useful helper routines...
+ /// EmitSourceFileHeader - Output a LLVM style file header to the specified
+ /// ostream.
+ void EmitSourceFileHeader(const std::string &Desc, std::ostream &OS) const;
+
+ /// getQualifiedName - Return the name of the specified record, with a
+ /// namespace qualifier if the record contains one.
+ std::string getQualifiedName(Record *R) const;
+};
+
+#endif
OpenPOWER on IntegriCloud