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
This commit is contained in:
David Greene 2009-04-22 20:18:10 +00:00
parent d7b2f7ffce
commit c7cafcd815
8 changed files with 192 additions and 36 deletions

View File

@ -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>

View File

@ -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">;

View File

@ -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;

View File

@ -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() + ")";
}

View File

@ -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:

View File

@ -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");
}

View File

@ -45,8 +45,8 @@ namespace tgtok {
MultiClass, String,
// !keywords.
XConcat, XSRA, XSRL, XSHL, XStrConcat,
XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat,
// Integer value.
IntVal,

View File

@ -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);
}
}