Skip to content

Commit

Permalink
Teach tablegen to allow "let" expressions inside multiclasses,
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bcardosolopes committed Jun 10, 2010
1 parent 302ef83 commit ee65db3
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 53 deletions.
26 changes: 26 additions & 0 deletions docs/TableGenFundamentals.html
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,32 @@
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&lt;bits&lt;4&gt; opc&gt; {
<b>let </b>Predicates = [HasSSE2] in {
<b>def </b>rr : Instruction&lt;opc, "rr"&gt;;
<b>def </b>rm : Instruction&lt;opc, "rm"&gt;;
}
<b>let </b>Predicates = [HasSSE3] in
<b>def </b>rx : Instruction&lt;opc, "rx"&gt;;
}

<b>multiclass </b>basic_ss&lt;bits&lt;4&gt; opc&gt; {
<b>let </b>IsDouble = 0 in
<b>defm </b>SS : basic_r&lt;opc&gt;;

<b>let </b>IsDouble = 1 in
<b>defm </b>SD : basic_r&lt;opc&gt;;
}

<b>defm </b>ADD : basic_ss&lt;0xf&gt;;
</pre>
</div>

<!-- *********************************************************************** -->
Expand Down
29 changes: 29 additions & 0 deletions test/TableGen/LetInsideMultiClasses.td
Original file line number Diff line number Diff line change
@@ -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>;

85 changes: 38 additions & 47 deletions utils/TableGen/TGParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 {
Expand All @@ -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;
}


Expand Down Expand Up @@ -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();

Expand All @@ -1778,15 +1791,15 @@ 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();
// Otherwise, this is a group let.
Lex.Lex(); // eat the '{'.

// Parse the object list.
if (ParseObjectList())
if (ParseObjectList(CurMultiClass))
return true;

if (Lex.getCode() != tgtok::r_brace) {
Expand All @@ -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?
Expand Down Expand Up @@ -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 '}'.
}

Expand Down Expand Up @@ -2048,22 +2039,22 @@ 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();
}
}

/// ParseObjectList
/// ObjectList :== Object*
bool TGParser::ParseObjectList() {
bool TGParser::ParseObjectList(MultiClass *MC) {
while (isObjectStart(Lex.getCode())) {
if (ParseObject())
if (ParseObject(MC))
return true;
}
return false;
Expand Down
11 changes: 5 additions & 6 deletions utils/TableGen/TGParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,15 @@ class TGParser {
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);
Expand Down

0 comments on commit ee65db3

Please sign in to comment.