mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
Graduate LLVM to the big leagues by embedding a LISP processor into TableGen.
Ok, not really, but do support some common LISP functions: * car * cdr * null llvm-svn: 71805
This commit is contained in:
parent
fab0ee79db
commit
70881bc6ae
@ -411,6 +411,12 @@ aborts with an error. </dd>
|
|||||||
<dd>For each member 'b' of dag or list 'a' apply operator 'c.' 'b' is a
|
<dd>For each member 'b' of dag or list 'a' apply operator 'c.' 'b' is a
|
||||||
dummy variable that should be declared as a member variable of an instantiated
|
dummy variable that should be declared as a member variable of an instantiated
|
||||||
class. This operation is analogous to $(foreach) in GNU make.</dd>
|
class. This operation is analogous to $(foreach) in GNU make.</dd>
|
||||||
|
<dt><tt>!car(a)</tt></dt>
|
||||||
|
<dd>The first element of list 'a.'</dd>
|
||||||
|
<dt><tt>!cdr(a)</tt></dt>
|
||||||
|
<dd>The 2nd-N elements of list 'a.'</dd>
|
||||||
|
<dt><tt>!null(a)</tt></dt>
|
||||||
|
<dd>An integer {0,1} indicating whether list 'a' is empty.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<p>Note that all of the values have rules specifying how they convert to values
|
<p>Note that all of the values have rules specifying how they convert to values
|
||||||
|
21
test/TableGen/lisp.td
Normal file
21
test/TableGen/lisp.td
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// RUN: tblgen %s | grep {}
|
||||||
|
|
||||||
|
class List<list<string> n> {
|
||||||
|
list<string> names = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CAR<string e> {
|
||||||
|
string element = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CDR<list<string> r, int n> {
|
||||||
|
list<string> rest = r;
|
||||||
|
int null = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NameList<list<string> Names> :
|
||||||
|
List<Names>, CAR<!car(Names)>, CDR<!cdr(Names), !null(!cdr(Names))>;
|
||||||
|
|
||||||
|
def Three : NameList<["Tom", "Dick", "Harry"]>;
|
||||||
|
|
||||||
|
def One : NameList<["Jeffrey Sinclair"]>;
|
@ -520,6 +520,41 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CAR: {
|
||||||
|
ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
|
||||||
|
if (LHSl) {
|
||||||
|
if (LHSl->getSize() == 0) {
|
||||||
|
assert(0 && "Empty list in car");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return LHSl->getElement(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CDR: {
|
||||||
|
ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
|
||||||
|
if (LHSl) {
|
||||||
|
if (LHSl->getSize() == 0) {
|
||||||
|
assert(0 && "Empty list in cdr");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ListInit *Result = new ListInit(LHSl->begin()+1, LHSl->end());
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LNULL: {
|
||||||
|
ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
|
||||||
|
if (LHSl) {
|
||||||
|
if (LHSl->getSize() == 0) {
|
||||||
|
return new IntInit(1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new IntInit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -536,6 +571,9 @@ std::string UnOpInit::getAsString() const {
|
|||||||
std::string Result;
|
std::string Result;
|
||||||
switch (Opc) {
|
switch (Opc) {
|
||||||
case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break;
|
case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break;
|
||||||
|
case CAR: Result = "!car"; break;
|
||||||
|
case CDR: Result = "!cdr"; break;
|
||||||
|
case LNULL: Result = "!null"; break;
|
||||||
}
|
}
|
||||||
return Result + "(" + LHS->getAsString() + ")";
|
return Result + "(" + LHS->getAsString() + ")";
|
||||||
}
|
}
|
||||||
|
@ -690,9 +690,14 @@ public:
|
|||||||
class ListInit : public Init {
|
class ListInit : public Init {
|
||||||
std::vector<Init*> Values;
|
std::vector<Init*> Values;
|
||||||
public:
|
public:
|
||||||
|
typedef std::vector<Init*>::iterator iterator;
|
||||||
|
typedef std::vector<Init*>::const_iterator const_iterator;
|
||||||
|
|
||||||
explicit ListInit(std::vector<Init*> &Vs) {
|
explicit ListInit(std::vector<Init*> &Vs) {
|
||||||
Values.swap(Vs);
|
Values.swap(Vs);
|
||||||
}
|
}
|
||||||
|
explicit ListInit(iterator Start, iterator End)
|
||||||
|
: Values(Start, End) {}
|
||||||
|
|
||||||
unsigned getSize() const { return Values.size(); }
|
unsigned getSize() const { return Values.size(); }
|
||||||
Init *getElement(unsigned i) const {
|
Init *getElement(unsigned i) const {
|
||||||
@ -717,9 +722,6 @@ public:
|
|||||||
|
|
||||||
virtual std::string getAsString() const;
|
virtual std::string getAsString() const;
|
||||||
|
|
||||||
typedef std::vector<Init*>::iterator iterator;
|
|
||||||
typedef std::vector<Init*>::const_iterator const_iterator;
|
|
||||||
|
|
||||||
inline iterator begin() { return Values.begin(); }
|
inline iterator begin() { return Values.begin(); }
|
||||||
inline const_iterator begin() const { return Values.begin(); }
|
inline const_iterator begin() const { return Values.begin(); }
|
||||||
inline iterator end () { return Values.end(); }
|
inline iterator end () { return Values.end(); }
|
||||||
@ -761,7 +763,7 @@ public:
|
|||||||
///
|
///
|
||||||
class UnOpInit : public OpInit {
|
class UnOpInit : public OpInit {
|
||||||
public:
|
public:
|
||||||
enum UnaryOp { CAST };
|
enum UnaryOp { CAST, CAR, CDR, LNULL };
|
||||||
private:
|
private:
|
||||||
UnaryOp Opc;
|
UnaryOp Opc;
|
||||||
Init *LHS;
|
Init *LHS;
|
||||||
|
@ -450,6 +450,9 @@ tgtok::TokKind TGLexer::LexExclaim() {
|
|||||||
if (Len == 5 && !memcmp(Start, "subst", 5)) return tgtok::XSubst;
|
if (Len == 5 && !memcmp(Start, "subst", 5)) return tgtok::XSubst;
|
||||||
if (Len == 7 && !memcmp(Start, "foreach", 7)) return tgtok::XForEach;
|
if (Len == 7 && !memcmp(Start, "foreach", 7)) return tgtok::XForEach;
|
||||||
if (Len == 4 && !memcmp(Start, "cast", 4)) return tgtok::XCast;
|
if (Len == 4 && !memcmp(Start, "cast", 4)) return tgtok::XCast;
|
||||||
|
if (Len == 3 && !memcmp(Start, "car", 3)) return tgtok::XCar;
|
||||||
|
if (Len == 3 && !memcmp(Start, "cdr", 3)) return tgtok::XCdr;
|
||||||
|
if (Len == 4 && !memcmp(Start, "null", 4)) return tgtok::XNull;
|
||||||
|
|
||||||
return ReturnError(Start-1, "Unknown operator");
|
return ReturnError(Start-1, "Unknown operator");
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ namespace tgtok {
|
|||||||
|
|
||||||
// !keywords.
|
// !keywords.
|
||||||
XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat, XCast, XSubst,
|
XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat, XCast, XSubst,
|
||||||
XForEach,
|
XForEach, XCar, XCdr, XNull,
|
||||||
|
|
||||||
// Integer value.
|
// Integer value.
|
||||||
IntVal,
|
IntVal,
|
||||||
|
@ -680,6 +680,9 @@ Init *TGParser::ParseOperation(Record *CurRec) {
|
|||||||
TokError("unknown operation");
|
TokError("unknown operation");
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
|
case tgtok::XCar:
|
||||||
|
case tgtok::XCdr:
|
||||||
|
case tgtok::XNull:
|
||||||
case tgtok::XCast: { // Value ::= !unop '(' Value ')'
|
case tgtok::XCast: { // Value ::= !unop '(' Value ')'
|
||||||
UnOpInit::UnaryOp Code;
|
UnOpInit::UnaryOp Code;
|
||||||
RecTy *Type = 0;
|
RecTy *Type = 0;
|
||||||
@ -693,10 +696,23 @@ Init *TGParser::ParseOperation(Record *CurRec) {
|
|||||||
Type = ParseOperatorType();
|
Type = ParseOperatorType();
|
||||||
|
|
||||||
if (Type == 0) {
|
if (Type == 0) {
|
||||||
TokError("did not get type for binary operator");
|
TokError("did not get type for unary operator");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case tgtok::XCar:
|
||||||
|
Lex.Lex(); // eat the operation
|
||||||
|
Code = UnOpInit::CAR;
|
||||||
|
break;
|
||||||
|
case tgtok::XCdr:
|
||||||
|
Lex.Lex(); // eat the operation
|
||||||
|
Code = UnOpInit::CDR;
|
||||||
|
break;
|
||||||
|
case tgtok::XNull:
|
||||||
|
Lex.Lex(); // eat the operation
|
||||||
|
Code = UnOpInit::LNULL;
|
||||||
|
Type = new IntRecTy;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (Lex.getCode() != tgtok::l_paren) {
|
if (Lex.getCode() != tgtok::l_paren) {
|
||||||
@ -708,6 +724,60 @@ Init *TGParser::ParseOperation(Record *CurRec) {
|
|||||||
Init *LHS = ParseValue(CurRec);
|
Init *LHS = ParseValue(CurRec);
|
||||||
if (LHS == 0) return 0;
|
if (LHS == 0) return 0;
|
||||||
|
|
||||||
|
if (Code == UnOpInit::CAR
|
||||||
|
|| Code == UnOpInit::CDR
|
||||||
|
|| Code == UnOpInit::LNULL) {
|
||||||
|
ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
|
||||||
|
TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS);
|
||||||
|
if (LHSl == 0 && LHSt == 0) {
|
||||||
|
TokError("expected list type argument in unary operator");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (LHSt) {
|
||||||
|
ListRecTy *LType = dynamic_cast<ListRecTy*>(LHSt->getType());
|
||||||
|
if (LType == 0) {
|
||||||
|
TokError("expected list type argumnet in unary operator");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Code == UnOpInit::CAR
|
||||||
|
|| Code == UnOpInit::CDR) {
|
||||||
|
if (LHSl && LHSl->getSize() == 0) {
|
||||||
|
TokError("empty list argument in unary operator");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (LHSl) {
|
||||||
|
Init *Item = LHSl->getElement(0);
|
||||||
|
TypedInit *Itemt = dynamic_cast<TypedInit*>(Item);
|
||||||
|
if (Itemt == 0) {
|
||||||
|
TokError("untyped list element in unary operator");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (Code == UnOpInit::CAR) {
|
||||||
|
Type = Itemt->getType();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Type = new ListRecTy(Itemt->getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(LHSt && "expected list type argument in unary operator");
|
||||||
|
ListRecTy *LType = dynamic_cast<ListRecTy*>(LHSt->getType());
|
||||||
|
if (LType == 0) {
|
||||||
|
TokError("expected list type argumnet in unary operator");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (Code == UnOpInit::CAR) {
|
||||||
|
Type = LType->getElementType();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Type = LType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Lex.getCode() != tgtok::r_paren) {
|
if (Lex.getCode() != tgtok::r_paren) {
|
||||||
TokError("expected ')' in unary operator");
|
TokError("expected ')' in unary operator");
|
||||||
return 0;
|
return 0;
|
||||||
@ -1072,6 +1142,9 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case tgtok::XCar:
|
||||||
|
case tgtok::XCdr:
|
||||||
|
case tgtok::XNull:
|
||||||
case tgtok::XCast: // Value ::= !unop '(' Value ')'
|
case tgtok::XCast: // Value ::= !unop '(' Value ')'
|
||||||
case tgtok::XConcat:
|
case tgtok::XConcat:
|
||||||
case tgtok::XSRA:
|
case tgtok::XSRA:
|
||||||
|
Loading…
Reference in New Issue
Block a user