diff options
Diffstat (limited to 'utils/TableGen/TGParser.cpp')
-rw-r--r-- | utils/TableGen/TGParser.cpp | 165 |
1 files changed, 119 insertions, 46 deletions
diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp index 8c158e0..f81aabe 100644 --- a/utils/TableGen/TGParser.cpp +++ b/utils/TableGen/TGParser.cpp @@ -1635,13 +1635,12 @@ bool TGParser::ParseObjectBody(Record *CurRec) { return ParseBody(CurRec); } - /// ParseDef - Parse and return a top level or multiclass def, return the record /// corresponding to it. This returns null on error. /// /// 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. @@ -1655,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 { @@ -1664,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; } @@ -1758,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(); @@ -1779,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(); @@ -1787,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) { @@ -1802,29 +1814,6 @@ bool TGParser::ParseTopLevelLet() { return false; } -/// ParseMultiClassDef - Parse a def in a multiclass context. -/// -/// MultiClassDef ::= DefInst -/// -bool TGParser::ParseMultiClassDef(MultiClass *CurMC) { - if (Lex.getCode() != tgtok::Def) - return TokError("expected 'def' in multiclass body"); - - 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? @@ -1885,10 +1874,18 @@ bool TGParser::ParseMultiClass() { if (Lex.Lex() == tgtok::r_brace) // eat the '{'. return TokError("multiclass must contain at least one def"); - while (Lex.getCode() != tgtok::r_brace) - if (ParseMultiClassDef(CurMultiClass)) - return true; - + while (Lex.getCode() != tgtok::r_brace) { + 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 '}'. } @@ -1900,7 +1897,7 @@ bool TGParser::ParseMultiClass() { /// /// DefMInst ::= DEFM ID ':' DefmSubClassRef ';' /// -bool TGParser::ParseDefm() { +bool TGParser::ParseDefm(MultiClass *CurMultiClass) { assert(Lex.getCode() == tgtok::Defm && "Unexpected token!"); if (Lex.Lex() != tgtok::Id) // eat the defm. return TokError("expected identifier after defm"); @@ -1910,6 +1907,12 @@ bool TGParser::ParseDefm() { if (Lex.Lex() != tgtok::colon) return TokError("expected ':' after defm identifier"); + // Keep track of the new generated record definitions. + std::vector<Record*> NewRecDefs; + + // This record also inherits from a regular class (non-multiclass)? + bool InheritFromClass = false; + // eat the colon. Lex.Lex(); @@ -1991,17 +1994,87 @@ bool TGParser::ParseDefm() { return Error(DefmPrefixLoc, "def '" + CurRec->getName() + "' already defined, instantiating defm with subdef '" + DefProto->getName() + "'"); - Records.addDef(CurRec); - CurRec->resolveReferences(); + + // Don't create a top level definition for defm inside multiclasses, + // instead, only update the prototypes and bind the template args + // with the new created definition. + if (CurMultiClass) { + for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); + i != e; ++i) { + if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) { + Error(DefmPrefixLoc, "defm '" + CurRec->getName() + + "' already defined in this multiclass!"); + return 0; + } + } + CurMultiClass->DefPrototypes.push_back(CurRec); + + // Copy the template arguments for the multiclass into the new def. + const std::vector<std::string> &TA = + CurMultiClass->Rec.getTemplateArgs(); + + for (unsigned i = 0, e = TA.size(); i != e; ++i) { + const RecordVal *RV = CurMultiClass->Rec.getValue(TA[i]); + assert(RV && "Template arg doesn't exist?"); + CurRec->addValue(*RV); + } + } else { + Records.addDef(CurRec); + } + + NewRecDefs.push_back(CurRec); } if (Lex.getCode() != tgtok::comma) break; Lex.Lex(); // eat ','. SubClassLoc = Lex.getLoc(); + + // A defm can inherit from regular classes (non-multiclass) as + // long as they come in the end of the inheritance list. + InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != 0); + + if (InheritFromClass) + break; + Ref = ParseSubClassReference(0, true); } + if (InheritFromClass) { + // Process all the classes to inherit as if they were part of a + // regular 'def' and inherit all record values. + SubClassReference SubClass = ParseSubClassReference(0, false); + while (1) { + // Check for error. + if (SubClass.Rec == 0) return true; + + // Get the expanded definition prototypes and teach them about + // the record values the current class to inherit has + for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) { + Record *CurRec = NewRecDefs[i]; + + // Add it. + if (AddSubClass(CurRec, SubClass)) + return true; + + // Process any variables on the let stack. + for (unsigned i = 0, e = LetStack.size(); i != e; ++i) + for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j) + if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name, + LetStack[i][j].Bits, LetStack[i][j].Value)) + return true; + } + + if (Lex.getCode() != tgtok::comma) break; + Lex.Lex(); // eat ','. + SubClass = ParseSubClassReference(0, false); + } + } + + if (!CurMultiClass) + for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) + NewRecDefs[i]->resolveReferences(); + if (Lex.getCode() != tgtok::semi) return TokError("expected ';' at end of defm"); Lex.Lex(); @@ -2016,12 +2089,12 @@ bool TGParser::ParseDefm() { /// 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(); } @@ -2029,9 +2102,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; |