aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Greene <greened@obbligato.org>2009-04-22 20:18:10 +0000
committerDavid Greene <greened@obbligato.org>2009-04-22 20:18:10 +0000
commitc7cafcd815519b06318629b424abe746437e1389 (patch)
treecb53439bdde7bbb4e94db441f65f2b420ca48052
parentd7b2f7ffcecee2809cf75d71374319dc0e73a71b (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.html10
-rw-r--r--test/TableGen/nameconcat.td76
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp2
-rw-r--r--utils/TableGen/Record.cpp44
-rw-r--r--utils/TableGen/Record.h13
-rw-r--r--utils/TableGen/TGLexer.cpp11
-rw-r--r--utils/TableGen/TGLexer.h4
-rw-r--r--utils/TableGen/TGParser.cpp68
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);
}
}