mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-26 07:34:06 +00:00
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:
parent
d7b2f7ffce
commit
c7cafcd815
@ -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>
|
||||
|
76
test/TableGen/nameconcat.td
Normal file
76
test/TableGen/nameconcat.td
Normal 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">;
|
@ -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;
|
||||
|
@ -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() + ")";
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -45,8 +45,8 @@ namespace tgtok {
|
||||
MultiClass, String,
|
||||
|
||||
// !keywords.
|
||||
XConcat, XSRA, XSRL, XSHL, XStrConcat,
|
||||
|
||||
XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat,
|
||||
|
||||
// Integer value.
|
||||
IntVal,
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user