diff options
author | David Greene <greened@obbligato.org> | 2009-04-22 20:18:10 +0000 |
---|---|---|
committer | David Greene <greened@obbligato.org> | 2009-04-22 20:18:10 +0000 |
commit | c7cafcd815519b06318629b424abe746437e1389 (patch) | |
tree | cb53439bdde7bbb4e94db441f65f2b420ca48052 | |
parent | d7b2f7ffcecee2809cf75d71374319dc0e73a71b (diff) |
Implement !nameconcat to concatenate strings and look up the resulting
name in the symbol table, returning an object.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@69822 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | docs/TableGenFundamentals.html | 10 | ||||
-rw-r--r-- | test/TableGen/nameconcat.td | 76 | ||||
-rw-r--r-- | utils/TableGen/CodeGenInstruction.cpp | 2 | ||||
-rw-r--r-- | utils/TableGen/Record.cpp | 44 | ||||
-rw-r--r-- | utils/TableGen/Record.h | 13 | ||||
-rw-r--r-- | utils/TableGen/TGLexer.cpp | 11 | ||||
-rw-r--r-- | utils/TableGen/TGLexer.h | 4 | ||||
-rw-r--r-- | utils/TableGen/TGParser.cpp | 68 |
8 files changed, 192 insertions, 36 deletions
diff --git a/docs/TableGenFundamentals.html b/docs/TableGenFundamentals.html index e9915cb029..42839176cb 100644 --- a/docs/TableGenFundamentals.html +++ b/docs/TableGenFundamentals.html @@ -398,6 +398,11 @@ supported include:</p> <dt><tt>!strconcat(a, b)</tt></dt> <dd>A string value that is the result of concatenating the 'a' and 'b' strings.</dd> +<dt><tt>!nameconcat(a, b)</tt></dt> + <dd>A value that is the result of concatenating the 'a' and 'b' + strings and looking up the resulting name in the symbol table. The symbol type + determines the type of the resulting value. If the symbol is not found, + TableGen emits an error and aborts.</dd> </dl> <p>Note that all of the values have rules specifying how they convert to values @@ -627,8 +632,9 @@ Here is an example TableGen fragment that shows this idea: <p>The name of the resultant definitions has the multidef fragment names appended to them, so this defines <tt>ADD_rr</tt>, <tt>ADD_ri</tt>, - <tt>SUB_rr</tt>, etc. Using a multiclass this way is exactly equivalent to - instantiating the classes multiple times yourself, e.g. by writing:</p> + <tt>SUB_rr</tt>, etc. Using a multiclass this way is exactly + equivalent to instantiating the classes multiple times yourself, + e.g. by writing:</p> <div class="doc_code"> <pre> diff --git a/test/TableGen/nameconcat.td b/test/TableGen/nameconcat.td new file mode 100644 index 0000000000..8dbc4b87d9 --- /dev/null +++ b/test/TableGen/nameconcat.td @@ -0,0 +1,76 @@ +// RUN: tblgen %s | grep {add_ps} | count 2 + +class ValueType<int size, int value> { + int Size = size; + int Value = value; +} + +def v2i64 : ValueType<128, 22>; // 2 x i64 vector value +def v2f64 : ValueType<128, 28>; // 2 x f64 vector value + +class Intrinsic<string name> { + string Name = name; +} + +class Inst<bits<8> opcode, dag oopnds, dag iopnds, string asmstr, + list<dag> pattern> { + bits<8> Opcode = opcode; + dag OutOperands = oopnds; + dag InOperands = iopnds; + string AssemblyString = asmstr; + list<dag> Pattern = pattern; +} + +def ops; +def outs; +def ins; + +def set; + +// Define registers +class Register<string n> { + string Name = n; +} + +class RegisterClass<list<ValueType> regTypes, list<Register> regList> { + list<ValueType> RegTypes = regTypes; + list<Register> MemberList = regList; +} + +def XMM0: Register<"xmm0">; +def XMM1: Register<"xmm1">; +def XMM2: Register<"xmm2">; +def XMM3: Register<"xmm3">; +def XMM4: Register<"xmm4">; +def XMM5: Register<"xmm5">; +def XMM6: Register<"xmm6">; +def XMM7: Register<"xmm7">; +def XMM8: Register<"xmm8">; +def XMM9: Register<"xmm9">; +def XMM10: Register<"xmm10">; +def XMM11: Register<"xmm11">; +def XMM12: Register<"xmm12">; +def XMM13: Register<"xmm13">; +def XMM14: Register<"xmm14">; +def XMM15: Register<"xmm15">; + +def VR128 : RegisterClass<[v2i64, v2f64], + [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, + XMM12, XMM13, XMM14, XMM15]>; + +// Define intrinsics +def int_x86_sse2_add_ps : Intrinsic<"addps">; +def int_x86_sse2_add_pd : Intrinsic<"addpd">; + +multiclass arith<bits<8> opcode, string asmstr, string Intr> { + def PS : Inst<opcode, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + !strconcat(asmstr, "\t$dst, $src1, $src2"), + [(set VR128:$dst, (!nameconcat(Intr, "_ps") VR128:$src1, VR128:$src2))]>; + + def PD : Inst<opcode, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + !strconcat(asmstr, "\t$dst, $src1, $src2"), + [(set VR128:$dst, (!nameconcat(Intr, "_pd") VR128:$src1, VR128:$src2))]>; +} + +defm ADD : arith<0x58, "add", "int_x86_sse2_add">; diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 185db01418..b505871dee 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -127,7 +127,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) OperandList.clear(); return; } - DI = (DagInit*)(new BinOpInit(BinOpInit::CONCAT, DI, IDI))->Fold(); + DI = (DagInit*)(new BinOpInit(BinOpInit::CONCAT, DI, IDI))->Fold(R, 0); unsigned MIOperandNo = 0; std::set<std::string> OperandNames; diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index e2d9657c4d..b244219995 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -395,7 +395,7 @@ std::string ListInit::getAsString() const { return Result + "]"; } -Init *BinOpInit::Fold() { +Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { switch (getOpcode()) { default: assert(0 && "Unknown binop"); case CONCAT: { @@ -437,6 +437,43 @@ Init *BinOpInit::Fold() { return new StringInit(LHSs->getValue() + RHSs->getValue()); break; } + case NAMECONCAT: { + StringInit *LHSs = dynamic_cast<StringInit*>(LHS); + StringInit *RHSs = dynamic_cast<StringInit*>(RHS); + if (LHSs && RHSs) { + std::string Name(LHSs->getValue() + RHSs->getValue()); + + // From TGParser::ParseIDValue + if (CurRec) { + if (const RecordVal *RV = CurRec->getValue(Name)) + return new VarInit(Name, RV->getType()); + + std::string TemplateArgName = CurRec->getName()+":"+Name; + if (CurRec->isTemplateArg(TemplateArgName)) { + const RecordVal *RV = CurRec->getValue(TemplateArgName); + assert(RV && "Template arg doesn't exist??"); + return new VarInit(TemplateArgName, RV->getType()); + } + } + + if (CurMultiClass) { + std::string MCName = CurMultiClass->Rec.getName()+"::"+Name; + if (CurMultiClass->Rec.isTemplateArg(MCName)) { + const RecordVal *RV = CurMultiClass->Rec.getValue(MCName); + assert(RV && "Template arg doesn't exist??"); + return new VarInit(MCName, RV->getType()); + } + } + + if (Record *D = Records.getDef(Name)) + return new DefInit(D); + + cerr << "Variable not defined: '" + Name + "'\n"; + assert(0 && "Variable not found"); + return 0; + } + break; + } case SHL: case SRA: case SRL: { @@ -464,8 +501,8 @@ Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) { Init *rhs = RHS->resolveReferences(R, RV); if (LHS != lhs || RHS != rhs) - return (new BinOpInit(getOpcode(), lhs, rhs))->Fold(); - return Fold(); + return (new BinOpInit(getOpcode(), lhs, rhs))->Fold(&R, 0); + return Fold(&R, 0); } std::string BinOpInit::getAsString() const { @@ -476,6 +513,7 @@ std::string BinOpInit::getAsString() const { case SRA: Result = "!sra"; break; case SRL: Result = "!srl"; break; case STRCONCAT: Result = "!strconcat"; break; + case NAMECONCAT: Result = "!nameconcat"; break; } return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")"; } diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index 32172ef12a..b408452f3d 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -53,6 +53,7 @@ class VarListElementInit; // Other classes. class Record; class RecordVal; +class MultiClass; //===----------------------------------------------------------------------===// // Type Classes @@ -659,7 +660,7 @@ public: /// class BinOpInit : public Init { public: - enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT }; + enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, NAMECONCAT }; private: BinaryOp Opc; Init *LHS, *RHS; @@ -673,7 +674,7 @@ public: // Fold - If possible, fold this to a simpler init. Return this if not // possible to fold. - Init *Fold(); + Init *Fold(Record *CurRec, MultiClass *CurMultiClass); virtual Init *convertInitializerTo(RecTy *Ty) { return Ty->convertValue(this); @@ -1124,6 +1125,14 @@ public: std::ostream &operator<<(std::ostream &OS, const Record &R); +struct MultiClass { + Record Rec; // Placeholder for template args and Name. + typedef std::vector<Record*> RecordVector; + RecordVector DefPrototypes; + + MultiClass(const std::string &Name, TGLoc Loc) : Rec(Name, Loc) {} +}; + class RecordKeeper { std::map<std::string, Record*> Classes, Defs; public: diff --git a/utils/TableGen/TGLexer.cpp b/utils/TableGen/TGLexer.cpp index 79982aa05f..f2ea7a1517 100644 --- a/utils/TableGen/TGLexer.cpp +++ b/utils/TableGen/TGLexer.cpp @@ -429,11 +429,12 @@ tgtok::TokKind TGLexer::LexExclaim() { // Check to see which operator this is. unsigned Len = CurPtr-Start; - if (Len == 3 && !memcmp(Start, "con", 3)) return tgtok::XConcat; - if (Len == 3 && !memcmp(Start, "sra", 3)) return tgtok::XSRA; - if (Len == 3 && !memcmp(Start, "srl", 3)) return tgtok::XSRL; - if (Len == 3 && !memcmp(Start, "shl", 3)) return tgtok::XSHL; - if (Len == 9 && !memcmp(Start, "strconcat", 9)) return tgtok::XStrConcat; + if (Len == 3 && !memcmp(Start, "con", 3)) return tgtok::XConcat; + if (Len == 3 && !memcmp(Start, "sra", 3)) return tgtok::XSRA; + if (Len == 3 && !memcmp(Start, "srl", 3)) return tgtok::XSRL; + if (Len == 3 && !memcmp(Start, "shl", 3)) return tgtok::XSHL; + if (Len == 9 && !memcmp(Start, "strconcat", 9)) return tgtok::XStrConcat; + if (Len == 10 && !memcmp(Start, "nameconcat", 10)) return tgtok::XNameConcat; return ReturnError(Start-1, "Unknown operator"); } diff --git a/utils/TableGen/TGLexer.h b/utils/TableGen/TGLexer.h index 245dd41461..734dc2651e 100644 --- a/utils/TableGen/TGLexer.h +++ b/utils/TableGen/TGLexer.h @@ -45,8 +45,8 @@ namespace tgtok { MultiClass, String, // !keywords. - XConcat, XSRA, XSRL, XSHL, XStrConcat, - + XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat, + // Integer value. IntVal, diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp index ddaf55803f..45ad5792f9 100644 --- a/utils/TableGen/TGParser.cpp +++ b/utils/TableGen/TGParser.cpp @@ -23,14 +23,6 @@ using namespace llvm; //===----------------------------------------------------------------------===// namespace llvm { -struct MultiClass { - Record Rec; // Placeholder for template args and Name. - typedef std::vector<Record*> RecordVector; - RecordVector DefPrototypes; - - MultiClass(const std::string &Name, TGLoc Loc) : Rec(Name, Loc) {} -}; - struct SubClassReference { TGLoc RefLoc; Record *Rec; @@ -777,14 +769,47 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { } case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')' Lex.Lex(); // eat the '(' - if (Lex.getCode() != tgtok::Id) { + if (Lex.getCode() != tgtok::Id + && Lex.getCode() != tgtok::XNameConcat) { TokError("expected identifier in dag init"); return 0; } - Init *Operator = ParseIDValue(CurRec); - if (Operator == 0) return 0; - + Init *Operator = 0; + if (Lex.getCode() == tgtok::Id) { + Operator = ParseIDValue(CurRec); + if (Operator == 0) return 0; + } + else { + BinOpInit::BinaryOp Code = BinOpInit::NAMECONCAT; + + Lex.Lex(); // eat the operation + if (Lex.getCode() != tgtok::l_paren) { + TokError("expected '(' after binary operator"); + return 0; + } + Lex.Lex(); // eat the '(' + + Init *LHS = ParseValue(CurRec); + if (LHS == 0) return 0; + + if (Lex.getCode() != tgtok::comma) { + TokError("expected ',' in binary operator"); + return 0; + } + Lex.Lex(); // eat the ',' + + Init *RHS = ParseValue(CurRec); + if (RHS == 0) return 0; + + if (Lex.getCode() != tgtok::r_paren) { + TokError("expected ')' in binary operator"); + return 0; + } + Lex.Lex(); // eat the ')' + Operator = (new BinOpInit(Code, LHS, RHS))->Fold(CurRec, CurMultiClass); + } + // If the operator name is present, parse it. std::string OperatorName; if (Lex.getCode() == tgtok::colon) { @@ -796,7 +821,6 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { Lex.Lex(); // eat the VarName. } - std::vector<std::pair<llvm::Init*, std::string> > DagArgs; if (Lex.getCode() != tgtok::r_paren) { DagArgs = ParseDagArgList(CurRec); @@ -815,15 +839,17 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { case tgtok::XSRA: case tgtok::XSRL: case tgtok::XSHL: - case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')' + case tgtok::XStrConcat: + case tgtok::XNameConcat: { // Value ::= !binop '(' Value ',' Value ')' BinOpInit::BinaryOp Code; switch (Lex.getCode()) { default: assert(0 && "Unhandled code!"); - case tgtok::XConcat: Code = BinOpInit::CONCAT; break; - case tgtok::XSRA: Code = BinOpInit::SRA; break; - case tgtok::XSRL: Code = BinOpInit::SRL; break; - case tgtok::XSHL: Code = BinOpInit::SHL; break; - case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break; + case tgtok::XConcat: Code = BinOpInit::CONCAT; break; + case tgtok::XSRA: Code = BinOpInit::SRA; break; + case tgtok::XSRL: Code = BinOpInit::SRL; break; + case tgtok::XSHL: Code = BinOpInit::SHL; break; + case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break; + case tgtok::XNameConcat: Code = BinOpInit::NAMECONCAT; break; } Lex.Lex(); // eat the operation if (Lex.getCode() != tgtok::l_paren) { @@ -831,7 +857,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { return 0; } Lex.Lex(); // eat the '(' - + Init *LHS = ParseValue(CurRec); if (LHS == 0) return 0; @@ -849,7 +875,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { return 0; } Lex.Lex(); // eat the ')' - return (new BinOpInit(Code, LHS, RHS))->Fold(); + return (new BinOpInit(Code, LHS, RHS))->Fold(CurRec, CurMultiClass); } } |