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