llvm.org GIT mirror llvm / ee65db3
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 Bruno Cardoso Lopes 10 years ago
4 changed file(s) with 99 addition(s) and 54 deletion(s). Raw diff Collapse all Expand all
797797 need to be added to several records, and the records do not otherwise need to be
798798 opened, as in the case with the CALL* instructions above.

799799
800

It's also possible to use "let" expressions inside multiclasses, providing

801 more ways to factor out commonality from the records, specially if using
802 several levels of multiclass instanciations. This also avoids the need of using
803 "let" expressions within subsequent records inside a multiclass.

804
805
806

                  
                
807 multiclass basic_r<bits<4> opc> {
808 let Predicates = [HasSSE2] in {
809 def rr : Instruction<opc, "rr">;
810 def rm : Instruction<opc, "rm">;
811 }
812 let Predicates = [HasSSE3] in
813 def rx : Instruction<opc, "rx">;
814 }
815
816 multiclass basic_ss<bits<4> opc> {
817 let IsDouble = 0 in
818 defm SS : basic_r<opc>;
819
820 let IsDouble = 1 in
821 defm SD : basic_r<opc>;
822 }
823
824 defm ADD : basic_ss<0xf>;
825
800826
801827
802828
0 // RUN: tblgen %s | grep "bit IsDouble = 1;" | count 3
1 // XFAIL: vg_leak
2
3 class Instruction opc, string Name> {
4 bits<4> opcode = opc;
5 string name = Name;
6 bit IsDouble = 0;
7 }
8
9 multiclass basic_r opc> {
10 let name = "newname" in {
11 def rr : Instruction;
12 def rm : Instruction;
13 }
14
15 let name = "othername" in
16 def rx : Instruction;
17 }
18
19 multiclass basic_ss opc> {
20 let IsDouble = 0 in
21 defm SS : basic_r;
22
23 let IsDouble = 1 in
24 defm SD : basic_r;
25 }
26
27 defm ADD : basic_ss<0xf>;
28
16391639 ///
16401640 /// DefInst ::= DEF ObjectName ObjectBody
16411641 ///
1642 llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
1642 bool TGParser::ParseDef(MultiClass *CurMultiClass) {
16431643 SMLoc DefLoc = Lex.getLoc();
16441644 assert(Lex.getCode() == tgtok::Def && "Unknown tok");
16451645 Lex.Lex(); // Eat the 'def' token.
16531653 // Ensure redefinition doesn't happen.
16541654 if (Records.getDef(CurRec->getName())) {
16551655 Error(DefLoc, "def '" + CurRec->getName() + "' already defined");
1656 return 0;
1656 return true;
16571657 }
16581658 Records.addDef(CurRec);
16591659 } else {
16621662 if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
16631663 Error(DefLoc, "def '" + CurRec->getName() +
16641664 "' already defined in this multiclass!");
1665 return 0;
1665 return true;
16661666 }
16671667 CurMultiClass->DefPrototypes.push_back(CurRec);
16681668 }
16691669
16701670 if (ParseObjectBody(CurRec))
1671 return 0;
1671 return true;
16721672
16731673 if (CurMultiClass == 0) // Def's in multiclasses aren't really defs.
16741674 CurRec->resolveReferences();
16751675
16761676 // If ObjectBody has template arguments, it's an error.
16771677 assert(CurRec->getTemplateArgs().empty() && "How'd this get template args?");
1678 return CurRec;
1678
1679 if (CurMultiClass) {
1680 // Copy the template arguments for the multiclass into the def.
1681 const std::vector &TArgs =
1682 CurMultiClass->Rec.getTemplateArgs();
1683
1684 for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
1685 const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]);
1686 assert(RV && "Template arg doesn't exist?");
1687 CurRec->addValue(*RV);
1688 }
1689 }
1690
1691 return false;
16791692 }
16801693
16811694
17561769 }
17571770
17581771 /// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of
1759 /// different related productions.
1772 /// different related productions. This works inside multiclasses too.
17601773 ///
17611774 /// Object ::= LET LetList IN '{' ObjectList '}'
17621775 /// Object ::= LET LetList IN Object
17631776 ///
1764 bool TGParser::ParseTopLevelLet() {
1777 bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
17651778 assert(Lex.getCode() == tgtok::Let && "Unexpected token");
17661779 Lex.Lex();
17671780
17771790 // If this is a scalar let, just handle it now
17781791 if (Lex.getCode() != tgtok::l_brace) {
17791792 // LET LetList IN Object
1780 if (ParseObject())
1793 if (ParseObject(CurMultiClass))
17811794 return true;
17821795 } else { // Object ::= LETCommand '{' ObjectList '}'
17831796 SMLoc BraceLoc = Lex.getLoc();
17851798 Lex.Lex(); // eat the '{'.
17861799
17871800 // Parse the object list.
1788 if (ParseObjectList())
1801 if (ParseObjectList(CurMultiClass))
17891802 return true;
17901803
17911804 if (Lex.getCode() != tgtok::r_brace) {
17971810
17981811 // Outside this let scope, this let block is not active.
17991812 LetStack.pop_back();
1800 return false;
1801 }
1802
1803 /// ParseMultiClassDef - Parse a def in a multiclass context.
1804 ///
1805 /// MultiClassDef ::= DefInst
1806 ///
1807 bool TGParser::ParseMultiClassDef(MultiClass *CurMC) {
1808
1809 Record *D = ParseDef(CurMC);
1810 if (D == 0) return true;
1811
1812 // Copy the template arguments for the multiclass into the def.
1813 const std::vector &TArgs = CurMC->Rec.getTemplateArgs();
1814
1815 for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
1816 const RecordVal *RV = CurMC->Rec.getValue(TArgs[i]);
1817 assert(RV && "Template arg doesn't exist?");
1818 D->addValue(*RV);
1819 }
1820
18211813 return false;
18221814 }
18231815
18821874 return TokError("multiclass must contain at least one def");
18831875
18841876 while (Lex.getCode() != tgtok::r_brace) {
1885 if (Lex.getCode() != tgtok::Defm && Lex.getCode() != tgtok::Def)
1886 return TokError("expected 'def' or 'defm' in multiclass body");
1887
1888 if (Lex.getCode() == tgtok::Def)
1889 if (ParseMultiClassDef(CurMultiClass))
1890 return true;
1891
1892 if (Lex.getCode() == tgtok::Defm)
1893 if (ParseDefm(CurMultiClass))
1894 return true;
1895 }
1896
1877 switch (Lex.getCode()) {
1878 default:
1879 return TokError("expected 'let', 'def' or 'defm' in multiclass body");
1880 case tgtok::Let:
1881 case tgtok::Def:
1882 case tgtok::Defm:
1883 if (ParseObject(CurMultiClass))
1884 return true;
1885 break;
1886 }
1887 }
18971888 Lex.Lex(); // eat the '}'.
18981889 }
18991890
20472038 /// Object ::= DefMInst
20482039 /// Object ::= LETCommand '{' ObjectList '}'
20492040 /// Object ::= LETCommand Object
2050 bool TGParser::ParseObject() {
2041 bool TGParser::ParseObject(MultiClass *MC) {
20512042 switch (Lex.getCode()) {
20522043 default: assert(0 && "This is not an object");
2053 case tgtok::Let: return ParseTopLevelLet();
2054 case tgtok::Def: return ParseDef(0) == 0;
2055 case tgtok::Defm: return ParseDefm();
2044 case tgtok::Let: return ParseTopLevelLet(MC);
2045 case tgtok::Def: return ParseDef(MC);
2046 case tgtok::Defm: return ParseDefm(MC);
20562047 case tgtok::Class: return ParseClass();
20572048 case tgtok::MultiClass: return ParseMultiClass();
20582049 }
20602051
20612052 /// ParseObjectList
20622053 /// ObjectList :== Object*
2063 bool TGParser::ParseObjectList() {
2054 bool TGParser::ParseObjectList(MultiClass *MC) {
20642055 while (isObjectStart(Lex.getCode())) {
2065 if (ParseObject())
2056 if (ParseObject(MC))
20662057 return true;
20672058 }
20682059 return false;
6868 SubMultiClassReference &SubMultiClass);
6969
7070 private: // Parser methods.
71 bool ParseObjectList();
72 bool ParseObject();
71 bool ParseObjectList(MultiClass *MC = 0);
72 bool ParseObject(MultiClass *MC);
7373 bool ParseClass();
7474 bool ParseMultiClass();
75 bool ParseMultiClassDef(MultiClass *CurMC);
76 bool ParseDefm(MultiClass *CurMultiClass = 0);
77 bool ParseTopLevelLet();
75 bool ParseDefm(MultiClass *CurMultiClass);
76 bool ParseDef(MultiClass *CurMultiClass);
77 bool ParseTopLevelLet(MultiClass *CurMultiClass);
7878 std::vector ParseLetList();
7979
80 Record *ParseDef(MultiClass *CurMultiClass);
8180 bool ParseObjectBody(Record *CurRec);
8281 bool ParseBody(Record *CurRec);
8382 bool ParseBodyItem(Record *CurRec);