forked from OSchip/llvm-project
Teach tablegen to allow "let" expressions inside multiclasses,
providing more ways to factor out commonality from the records. llvm-svn: 105776
This commit is contained in:
parent
38f6560461
commit
5f2adccc1b
|
@ -798,6 +798,32 @@ examples:</p>
|
|||
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>
|
||||
|
||||
<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>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
|
|
|
@ -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
|
||||
///
|
||||
llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
|
||||
bool TGParser::ParseDef(MultiClass *CurMultiClass) {
|
||||
SMLoc DefLoc = Lex.getLoc();
|
||||
assert(Lex.getCode() == tgtok::Def && "Unknown tok");
|
||||
Lex.Lex(); // Eat the 'def' token.
|
||||
|
@ -1654,7 +1654,7 @@ llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
|
|||
// Ensure redefinition doesn't happen.
|
||||
if (Records.getDef(CurRec->getName())) {
|
||||
Error(DefLoc, "def '" + CurRec->getName() + "' already defined");
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
Records.addDef(CurRec);
|
||||
} else {
|
||||
|
@ -1663,20 +1663,33 @@ llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
|
|||
if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
|
||||
Error(DefLoc, "def '" + CurRec->getName() +
|
||||
"' already defined in this multiclass!");
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
CurMultiClass->DefPrototypes.push_back(CurRec);
|
||||
}
|
||||
|
||||
if (ParseObjectBody(CurRec))
|
||||
return 0;
|
||||
return true;
|
||||
|
||||
if (CurMultiClass == 0) // Def's in multiclasses aren't really defs.
|
||||
CurRec->resolveReferences();
|
||||
|
||||
// If ObjectBody has template arguments, it's an error.
|
||||
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
|
||||
/// different related productions.
|
||||
/// different related productions. This works inside multiclasses too.
|
||||
///
|
||||
/// Object ::= LET LetList IN '{' ObjectList '}'
|
||||
/// Object ::= LET LetList IN Object
|
||||
///
|
||||
bool TGParser::ParseTopLevelLet() {
|
||||
bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
|
||||
assert(Lex.getCode() == tgtok::Let && "Unexpected token");
|
||||
Lex.Lex();
|
||||
|
||||
|
@ -1778,7 +1791,7 @@ bool TGParser::ParseTopLevelLet() {
|
|||
// If this is a scalar let, just handle it now
|
||||
if (Lex.getCode() != tgtok::l_brace) {
|
||||
// LET LetList IN Object
|
||||
if (ParseObject())
|
||||
if (ParseObject(CurMultiClass))
|
||||
return true;
|
||||
} else { // Object ::= LETCommand '{' ObjectList '}'
|
||||
SMLoc BraceLoc = Lex.getLoc();
|
||||
|
@ -1786,7 +1799,7 @@ bool TGParser::ParseTopLevelLet() {
|
|||
Lex.Lex(); // eat the '{'.
|
||||
|
||||
// Parse the object list.
|
||||
if (ParseObjectList())
|
||||
if (ParseObjectList(CurMultiClass))
|
||||
return true;
|
||||
|
||||
if (Lex.getCode() != tgtok::r_brace) {
|
||||
|
@ -1801,27 +1814,6 @@ bool TGParser::ParseTopLevelLet() {
|
|||
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.
|
||||
///
|
||||
/// MultiClassInst ::= MULTICLASS ID TemplateArgList?
|
||||
|
@ -1883,18 +1875,17 @@ bool TGParser::ParseMultiClass() {
|
|||
return TokError("multiclass must contain at least one def");
|
||||
|
||||
while (Lex.getCode() != tgtok::r_brace) {
|
||||
if (Lex.getCode() != tgtok::Defm && Lex.getCode() != tgtok::Def)
|
||||
return TokError("expected 'def' or 'defm' in multiclass body");
|
||||
|
||||
if (Lex.getCode() == tgtok::Def)
|
||||
if (ParseMultiClassDef(CurMultiClass))
|
||||
return true;
|
||||
|
||||
if (Lex.getCode() == tgtok::Defm)
|
||||
if (ParseDefm(CurMultiClass))
|
||||
return true;
|
||||
switch (Lex.getCode()) {
|
||||
default:
|
||||
return TokError("expected 'let', 'def' or 'defm' in multiclass body");
|
||||
case tgtok::Let:
|
||||
case tgtok::Def:
|
||||
case tgtok::Defm:
|
||||
if (ParseObject(CurMultiClass))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Lex.Lex(); // eat the '}'.
|
||||
}
|
||||
|
||||
|
@ -2048,12 +2039,12 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
|
|||
/// Object ::= DefMInst
|
||||
/// Object ::= LETCommand '{' ObjectList '}'
|
||||
/// Object ::= LETCommand Object
|
||||
bool TGParser::ParseObject() {
|
||||
bool TGParser::ParseObject(MultiClass *MC) {
|
||||
switch (Lex.getCode()) {
|
||||
default: assert(0 && "This is not an object");
|
||||
case tgtok::Let: return ParseTopLevelLet();
|
||||
case tgtok::Def: return ParseDef(0) == 0;
|
||||
case tgtok::Defm: return ParseDefm();
|
||||
case tgtok::Let: return ParseTopLevelLet(MC);
|
||||
case tgtok::Def: return ParseDef(MC);
|
||||
case tgtok::Defm: return ParseDefm(MC);
|
||||
case tgtok::Class: return ParseClass();
|
||||
case tgtok::MultiClass: return ParseMultiClass();
|
||||
}
|
||||
|
@ -2061,9 +2052,9 @@ bool TGParser::ParseObject() {
|
|||
|
||||
/// ParseObjectList
|
||||
/// ObjectList :== Object*
|
||||
bool TGParser::ParseObjectList() {
|
||||
bool TGParser::ParseObjectList(MultiClass *MC) {
|
||||
while (isObjectStart(Lex.getCode())) {
|
||||
if (ParseObject())
|
||||
if (ParseObject(MC))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -69,16 +69,15 @@ private: // Semantic analysis methods.
|
|||
SubMultiClassReference &SubMultiClass);
|
||||
|
||||
private: // Parser methods.
|
||||
bool ParseObjectList();
|
||||
bool ParseObject();
|
||||
bool ParseObjectList(MultiClass *MC = 0);
|
||||
bool ParseObject(MultiClass *MC);
|
||||
bool ParseClass();
|
||||
bool ParseMultiClass();
|
||||
bool ParseMultiClassDef(MultiClass *CurMC);
|
||||
bool ParseDefm(MultiClass *CurMultiClass = 0);
|
||||
bool ParseTopLevelLet();
|
||||
bool ParseDefm(MultiClass *CurMultiClass);
|
||||
bool ParseDef(MultiClass *CurMultiClass);
|
||||
bool ParseTopLevelLet(MultiClass *CurMultiClass);
|
||||
std::vector<LetRecord> ParseLetList();
|
||||
|
||||
Record *ParseDef(MultiClass *CurMultiClass);
|
||||
bool ParseObjectBody(Record *CurRec);
|
||||
bool ParseBody(Record *CurRec);
|
||||
bool ParseBodyItem(Record *CurRec);
|
||||
|
|
Loading…
Reference in New Issue