mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-23 01:24:30 +00:00
Teach tablegen to allow "let" expressions inside multiclasses,
providing more ways to factor out commonality from the records. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@105776 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -798,6 +798,32 @@ examples:</p>
|
|||||||
need to be added to several records, and the records do not otherwise need to be
|
need to be added to several records, and the records do not otherwise need to be
|
||||||
opened, as in the case with the <tt>CALL*</tt> instructions above.</p>
|
opened, as in the case with the <tt>CALL*</tt> instructions above.</p>
|
||||||
|
|
||||||
|
<p>It's also possible to use "let" expressions inside multiclasses, providing
|
||||||
|
more ways to factor out commonality from the records, specially if using
|
||||||
|
several levels of multiclass instanciations. This also avoids the need of using
|
||||||
|
"let" expressions within subsequent records inside a multiclass.</p>
|
||||||
|
|
||||||
|
<div class="doc_code">
|
||||||
|
<pre>
|
||||||
|
<b>multiclass </b>basic_r<bits<4> opc> {
|
||||||
|
<b>let </b>Predicates = [HasSSE2] in {
|
||||||
|
<b>def </b>rr : Instruction<opc, "rr">;
|
||||||
|
<b>def </b>rm : Instruction<opc, "rm">;
|
||||||
|
}
|
||||||
|
<b>let </b>Predicates = [HasSSE3] in
|
||||||
|
<b>def </b>rx : Instruction<opc, "rx">;
|
||||||
|
}
|
||||||
|
|
||||||
|
<b>multiclass </b>basic_ss<bits<4> opc> {
|
||||||
|
<b>let </b>IsDouble = 0 in
|
||||||
|
<b>defm </b>SS : basic_r<opc>;
|
||||||
|
|
||||||
|
<b>let </b>IsDouble = 1 in
|
||||||
|
<b>defm </b>SD : basic_r<opc>;
|
||||||
|
}
|
||||||
|
|
||||||
|
<b>defm </b>ADD : basic_ss<0xf>;
|
||||||
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- *********************************************************************** -->
|
<!-- *********************************************************************** -->
|
||||||
|
29
test/TableGen/LetInsideMultiClasses.td
Normal file
29
test/TableGen/LetInsideMultiClasses.td
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// RUN: tblgen %s | grep "bit IsDouble = 1;" | count 3
|
||||||
|
// XFAIL: vg_leak
|
||||||
|
|
||||||
|
class Instruction<bits<4> opc, string Name> {
|
||||||
|
bits<4> opcode = opc;
|
||||||
|
string name = Name;
|
||||||
|
bit IsDouble = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
multiclass basic_r<bits<4> opc> {
|
||||||
|
let name = "newname" in {
|
||||||
|
def rr : Instruction<opc, "rr">;
|
||||||
|
def rm : Instruction<opc, "rm">;
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = "othername" in
|
||||||
|
def rx : Instruction<opc, "rx">;
|
||||||
|
}
|
||||||
|
|
||||||
|
multiclass basic_ss<bits<4> opc> {
|
||||||
|
let IsDouble = 0 in
|
||||||
|
defm SS : basic_r<opc>;
|
||||||
|
|
||||||
|
let IsDouble = 1 in
|
||||||
|
defm SD : basic_r<opc>;
|
||||||
|
}
|
||||||
|
|
||||||
|
defm ADD : basic_ss<0xf>;
|
||||||
|
|
@ -1640,7 +1640,7 @@ bool TGParser::ParseObjectBody(Record *CurRec) {
|
|||||||
///
|
///
|
||||||
/// DefInst ::= DEF ObjectName ObjectBody
|
/// DefInst ::= DEF ObjectName ObjectBody
|
||||||
///
|
///
|
||||||
llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
|
bool TGParser::ParseDef(MultiClass *CurMultiClass) {
|
||||||
SMLoc DefLoc = Lex.getLoc();
|
SMLoc DefLoc = Lex.getLoc();
|
||||||
assert(Lex.getCode() == tgtok::Def && "Unknown tok");
|
assert(Lex.getCode() == tgtok::Def && "Unknown tok");
|
||||||
Lex.Lex(); // Eat the 'def' token.
|
Lex.Lex(); // Eat the 'def' token.
|
||||||
@ -1654,7 +1654,7 @@ llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
|
|||||||
// Ensure redefinition doesn't happen.
|
// Ensure redefinition doesn't happen.
|
||||||
if (Records.getDef(CurRec->getName())) {
|
if (Records.getDef(CurRec->getName())) {
|
||||||
Error(DefLoc, "def '" + CurRec->getName() + "' already defined");
|
Error(DefLoc, "def '" + CurRec->getName() + "' already defined");
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
Records.addDef(CurRec);
|
Records.addDef(CurRec);
|
||||||
} else {
|
} else {
|
||||||
@ -1663,20 +1663,33 @@ llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
|
|||||||
if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
|
if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
|
||||||
Error(DefLoc, "def '" + CurRec->getName() +
|
Error(DefLoc, "def '" + CurRec->getName() +
|
||||||
"' already defined in this multiclass!");
|
"' already defined in this multiclass!");
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
CurMultiClass->DefPrototypes.push_back(CurRec);
|
CurMultiClass->DefPrototypes.push_back(CurRec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ParseObjectBody(CurRec))
|
if (ParseObjectBody(CurRec))
|
||||||
return 0;
|
return true;
|
||||||
|
|
||||||
if (CurMultiClass == 0) // Def's in multiclasses aren't really defs.
|
if (CurMultiClass == 0) // Def's in multiclasses aren't really defs.
|
||||||
CurRec->resolveReferences();
|
CurRec->resolveReferences();
|
||||||
|
|
||||||
// If ObjectBody has template arguments, it's an error.
|
// If ObjectBody has template arguments, it's an error.
|
||||||
assert(CurRec->getTemplateArgs().empty() && "How'd this get template args?");
|
assert(CurRec->getTemplateArgs().empty() && "How'd this get template args?");
|
||||||
return CurRec;
|
|
||||||
|
if (CurMultiClass) {
|
||||||
|
// Copy the template arguments for the multiclass into the def.
|
||||||
|
const std::vector<std::string> &TArgs =
|
||||||
|
CurMultiClass->Rec.getTemplateArgs();
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
|
||||||
|
const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]);
|
||||||
|
assert(RV && "Template arg doesn't exist?");
|
||||||
|
CurRec->addValue(*RV);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1757,12 +1770,12 @@ std::vector<LetRecord> TGParser::ParseLetList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of
|
/// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of
|
||||||
/// different related productions.
|
/// different related productions. This works inside multiclasses too.
|
||||||
///
|
///
|
||||||
/// Object ::= LET LetList IN '{' ObjectList '}'
|
/// Object ::= LET LetList IN '{' ObjectList '}'
|
||||||
/// Object ::= LET LetList IN Object
|
/// Object ::= LET LetList IN Object
|
||||||
///
|
///
|
||||||
bool TGParser::ParseTopLevelLet() {
|
bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
|
||||||
assert(Lex.getCode() == tgtok::Let && "Unexpected token");
|
assert(Lex.getCode() == tgtok::Let && "Unexpected token");
|
||||||
Lex.Lex();
|
Lex.Lex();
|
||||||
|
|
||||||
@ -1778,7 +1791,7 @@ bool TGParser::ParseTopLevelLet() {
|
|||||||
// If this is a scalar let, just handle it now
|
// If this is a scalar let, just handle it now
|
||||||
if (Lex.getCode() != tgtok::l_brace) {
|
if (Lex.getCode() != tgtok::l_brace) {
|
||||||
// LET LetList IN Object
|
// LET LetList IN Object
|
||||||
if (ParseObject())
|
if (ParseObject(CurMultiClass))
|
||||||
return true;
|
return true;
|
||||||
} else { // Object ::= LETCommand '{' ObjectList '}'
|
} else { // Object ::= LETCommand '{' ObjectList '}'
|
||||||
SMLoc BraceLoc = Lex.getLoc();
|
SMLoc BraceLoc = Lex.getLoc();
|
||||||
@ -1786,7 +1799,7 @@ bool TGParser::ParseTopLevelLet() {
|
|||||||
Lex.Lex(); // eat the '{'.
|
Lex.Lex(); // eat the '{'.
|
||||||
|
|
||||||
// Parse the object list.
|
// Parse the object list.
|
||||||
if (ParseObjectList())
|
if (ParseObjectList(CurMultiClass))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (Lex.getCode() != tgtok::r_brace) {
|
if (Lex.getCode() != tgtok::r_brace) {
|
||||||
@ -1801,27 +1814,6 @@ bool TGParser::ParseTopLevelLet() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ParseMultiClassDef - Parse a def in a multiclass context.
|
|
||||||
///
|
|
||||||
/// MultiClassDef ::= DefInst
|
|
||||||
///
|
|
||||||
bool TGParser::ParseMultiClassDef(MultiClass *CurMC) {
|
|
||||||
|
|
||||||
Record *D = ParseDef(CurMC);
|
|
||||||
if (D == 0) return true;
|
|
||||||
|
|
||||||
// Copy the template arguments for the multiclass into the def.
|
|
||||||
const std::vector<std::string> &TArgs = CurMC->Rec.getTemplateArgs();
|
|
||||||
|
|
||||||
for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
|
|
||||||
const RecordVal *RV = CurMC->Rec.getValue(TArgs[i]);
|
|
||||||
assert(RV && "Template arg doesn't exist?");
|
|
||||||
D->addValue(*RV);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ParseMultiClass - Parse a multiclass definition.
|
/// ParseMultiClass - Parse a multiclass definition.
|
||||||
///
|
///
|
||||||
/// MultiClassInst ::= MULTICLASS ID TemplateArgList?
|
/// MultiClassInst ::= MULTICLASS ID TemplateArgList?
|
||||||
@ -1883,18 +1875,17 @@ bool TGParser::ParseMultiClass() {
|
|||||||
return TokError("multiclass must contain at least one def");
|
return TokError("multiclass must contain at least one def");
|
||||||
|
|
||||||
while (Lex.getCode() != tgtok::r_brace) {
|
while (Lex.getCode() != tgtok::r_brace) {
|
||||||
if (Lex.getCode() != tgtok::Defm && Lex.getCode() != tgtok::Def)
|
switch (Lex.getCode()) {
|
||||||
return TokError("expected 'def' or 'defm' in multiclass body");
|
default:
|
||||||
|
return TokError("expected 'let', 'def' or 'defm' in multiclass body");
|
||||||
if (Lex.getCode() == tgtok::Def)
|
case tgtok::Let:
|
||||||
if (ParseMultiClassDef(CurMultiClass))
|
case tgtok::Def:
|
||||||
return true;
|
case tgtok::Defm:
|
||||||
|
if (ParseObject(CurMultiClass))
|
||||||
if (Lex.getCode() == tgtok::Defm)
|
|
||||||
if (ParseDefm(CurMultiClass))
|
|
||||||
return true;
|
return true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Lex.Lex(); // eat the '}'.
|
Lex.Lex(); // eat the '}'.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2048,12 +2039,12 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
|
|||||||
/// Object ::= DefMInst
|
/// Object ::= DefMInst
|
||||||
/// Object ::= LETCommand '{' ObjectList '}'
|
/// Object ::= LETCommand '{' ObjectList '}'
|
||||||
/// Object ::= LETCommand Object
|
/// Object ::= LETCommand Object
|
||||||
bool TGParser::ParseObject() {
|
bool TGParser::ParseObject(MultiClass *MC) {
|
||||||
switch (Lex.getCode()) {
|
switch (Lex.getCode()) {
|
||||||
default: assert(0 && "This is not an object");
|
default: assert(0 && "This is not an object");
|
||||||
case tgtok::Let: return ParseTopLevelLet();
|
case tgtok::Let: return ParseTopLevelLet(MC);
|
||||||
case tgtok::Def: return ParseDef(0) == 0;
|
case tgtok::Def: return ParseDef(MC);
|
||||||
case tgtok::Defm: return ParseDefm();
|
case tgtok::Defm: return ParseDefm(MC);
|
||||||
case tgtok::Class: return ParseClass();
|
case tgtok::Class: return ParseClass();
|
||||||
case tgtok::MultiClass: return ParseMultiClass();
|
case tgtok::MultiClass: return ParseMultiClass();
|
||||||
}
|
}
|
||||||
@ -2061,9 +2052,9 @@ bool TGParser::ParseObject() {
|
|||||||
|
|
||||||
/// ParseObjectList
|
/// ParseObjectList
|
||||||
/// ObjectList :== Object*
|
/// ObjectList :== Object*
|
||||||
bool TGParser::ParseObjectList() {
|
bool TGParser::ParseObjectList(MultiClass *MC) {
|
||||||
while (isObjectStart(Lex.getCode())) {
|
while (isObjectStart(Lex.getCode())) {
|
||||||
if (ParseObject())
|
if (ParseObject(MC))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -69,16 +69,15 @@ private: // Semantic analysis methods.
|
|||||||
SubMultiClassReference &SubMultiClass);
|
SubMultiClassReference &SubMultiClass);
|
||||||
|
|
||||||
private: // Parser methods.
|
private: // Parser methods.
|
||||||
bool ParseObjectList();
|
bool ParseObjectList(MultiClass *MC = 0);
|
||||||
bool ParseObject();
|
bool ParseObject(MultiClass *MC);
|
||||||
bool ParseClass();
|
bool ParseClass();
|
||||||
bool ParseMultiClass();
|
bool ParseMultiClass();
|
||||||
bool ParseMultiClassDef(MultiClass *CurMC);
|
bool ParseDefm(MultiClass *CurMultiClass);
|
||||||
bool ParseDefm(MultiClass *CurMultiClass = 0);
|
bool ParseDef(MultiClass *CurMultiClass);
|
||||||
bool ParseTopLevelLet();
|
bool ParseTopLevelLet(MultiClass *CurMultiClass);
|
||||||
std::vector<LetRecord> ParseLetList();
|
std::vector<LetRecord> ParseLetList();
|
||||||
|
|
||||||
Record *ParseDef(MultiClass *CurMultiClass);
|
|
||||||
bool ParseObjectBody(Record *CurRec);
|
bool ParseObjectBody(Record *CurRec);
|
||||||
bool ParseBody(Record *CurRec);
|
bool ParseBody(Record *CurRec);
|
||||||
bool ParseBodyItem(Record *CurRec);
|
bool ParseBodyItem(Record *CurRec);
|
||||||
|
Reference in New Issue
Block a user