From 5f9f9ba00b85eb19da2618f393e43a6a11b5d892 Mon Sep 17 00:00:00 2001 From: David Greene Date: Thu, 14 May 2009 22:38:31 +0000 Subject: [PATCH] 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@71805 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/TableGenFundamentals.html | 6 +++ test/TableGen/lisp.td | 21 ++++++++++ utils/TableGen/Record.cpp | 38 +++++++++++++++++ utils/TableGen/Record.h | 10 +++-- utils/TableGen/TGLexer.cpp | 3 ++ utils/TableGen/TGLexer.h | 2 +- utils/TableGen/TGParser.cpp | 75 +++++++++++++++++++++++++++++++++- 7 files changed, 149 insertions(+), 6 deletions(-) create mode 100644 test/TableGen/lisp.td diff --git a/docs/TableGenFundamentals.html b/docs/TableGenFundamentals.html index 9607f9ea9ec..36798c8b8b8 100644 --- a/docs/TableGenFundamentals.html +++ b/docs/TableGenFundamentals.html @@ -411,6 +411,12 @@ aborts with an error.
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 class. This operation is analogous to $(foreach) in GNU make.
+
!car(a)
+
The first element of list 'a.'
+
!cdr(a)
+
The 2nd-N elements of list 'a.'
+
!null(a)
+
An integer {0,1} indicating whether list 'a' is empty.

Note that all of the values have rules specifying how they convert to values diff --git a/test/TableGen/lisp.td b/test/TableGen/lisp.td new file mode 100644 index 00000000000..3e392fda84f --- /dev/null +++ b/test/TableGen/lisp.td @@ -0,0 +1,21 @@ +// RUN: tblgen %s | grep {} + +class List n> { + list names = n; +} + +class CAR { + string element = e; +} + +class CDR r, int n> { + list rest = r; + int null = n; +} + +class NameList Names> : + List, CAR, CDR; + +def Three : NameList<["Tom", "Dick", "Harry"]>; + +def One : NameList<["Jeffrey Sinclair"]>; diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index ade17026fbf..ae2c2f3ea40 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -520,6 +520,41 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { } break; } + case CAR: { + ListInit *LHSl = dynamic_cast(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(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(LHS); + if (LHSl) { + if (LHSl->getSize() == 0) { + return new IntInit(1); + } + else { + return new IntInit(0); + } + } + break; + } } return this; } @@ -536,6 +571,9 @@ std::string UnOpInit::getAsString() const { std::string Result; switch (Opc) { 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() + ")"; } diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index c37f6e62071..c2549dab73a 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -690,9 +690,14 @@ public: class ListInit : public Init { std::vector Values; public: + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + explicit ListInit(std::vector &Vs) { Values.swap(Vs); } + explicit ListInit(iterator Start, iterator End) + : Values(Start, End) {} unsigned getSize() const { return Values.size(); } Init *getElement(unsigned i) const { @@ -717,9 +722,6 @@ public: virtual std::string getAsString() const; - typedef std::vector::iterator iterator; - typedef std::vector::const_iterator const_iterator; - inline iterator begin() { return Values.begin(); } inline const_iterator begin() const { return Values.begin(); } inline iterator end () { return Values.end(); } @@ -761,7 +763,7 @@ public: /// class UnOpInit : public OpInit { public: - enum UnaryOp { CAST }; + enum UnaryOp { CAST, CAR, CDR, LNULL }; private: UnaryOp Opc; Init *LHS; diff --git a/utils/TableGen/TGLexer.cpp b/utils/TableGen/TGLexer.cpp index 6215a7267fb..faf1e75a684 100644 --- a/utils/TableGen/TGLexer.cpp +++ b/utils/TableGen/TGLexer.cpp @@ -450,6 +450,9 @@ tgtok::TokKind TGLexer::LexExclaim() { if (Len == 5 && !memcmp(Start, "subst", 5)) return tgtok::XSubst; if (Len == 7 && !memcmp(Start, "foreach", 7)) return tgtok::XForEach; 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"); } diff --git a/utils/TableGen/TGLexer.h b/utils/TableGen/TGLexer.h index 3993e89d64e..3d27e5e8edb 100644 --- a/utils/TableGen/TGLexer.h +++ b/utils/TableGen/TGLexer.h @@ -46,7 +46,7 @@ namespace tgtok { // !keywords. XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat, XCast, XSubst, - XForEach, + XForEach, XCar, XCdr, XNull, // Integer value. IntVal, diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp index bc5d65eea59..8ff25a6186b 100644 --- a/utils/TableGen/TGParser.cpp +++ b/utils/TableGen/TGParser.cpp @@ -680,6 +680,9 @@ Init *TGParser::ParseOperation(Record *CurRec) { TokError("unknown operation"); return 0; break; + case tgtok::XCar: + case tgtok::XCdr: + case tgtok::XNull: case tgtok::XCast: { // Value ::= !unop '(' Value ')' UnOpInit::UnaryOp Code; RecTy *Type = 0; @@ -693,10 +696,23 @@ Init *TGParser::ParseOperation(Record *CurRec) { Type = ParseOperatorType(); if (Type == 0) { - TokError("did not get type for binary operator"); + TokError("did not get type for unary operator"); 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; } if (Lex.getCode() != tgtok::l_paren) { @@ -708,6 +724,60 @@ Init *TGParser::ParseOperation(Record *CurRec) { Init *LHS = ParseValue(CurRec); if (LHS == 0) return 0; + if (Code == UnOpInit::CAR + || Code == UnOpInit::CDR + || Code == UnOpInit::LNULL) { + ListInit *LHSl = dynamic_cast(LHS); + TypedInit *LHSt = dynamic_cast(LHS); + if (LHSl == 0 && LHSt == 0) { + TokError("expected list type argument in unary operator"); + return 0; + } + if (LHSt) { + ListRecTy *LType = dynamic_cast(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(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(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) { TokError("expected ')' in unary operator"); return 0; @@ -1072,6 +1142,9 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { break; } + case tgtok::XCar: + case tgtok::XCdr: + case tgtok::XNull: case tgtok::XCast: // Value ::= !unop '(' Value ')' case tgtok::XConcat: case tgtok::XSRA: -- 2.34.1