X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTableGen%2FTGParser.cpp;h=86ad2a6e3c09c6899d0d534baa5c72654d8d3b6e;hb=627190ed78c9c2752dfe7be6ea426690863d54e4;hp=68d9ef4c092eecf2a60e461407ab7980a691f3d5;hpb=8e5286e18ffbe4716ef92cd1de8901942d685e1b;p=oota-llvm.git diff --git a/lib/TableGen/TGParser.cpp b/lib/TableGen/TGParser.cpp index 68d9ef4c092..86ad2a6e3c0 100644 --- a/lib/TableGen/TGParser.cpp +++ b/lib/TableGen/TGParser.cpp @@ -12,12 +12,12 @@ //===----------------------------------------------------------------------===// #include "TGParser.h" -#include "llvm/TableGen/Record.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TableGen/Record.h" #include #include -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/CommandLine.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -26,7 +26,7 @@ using namespace llvm; namespace llvm { struct SubClassReference { - SMLoc RefLoc; + SMRange RefRange; Record *Rec; std::vector TemplateArgs; SubClassReference() : Rec(0) {} @@ -35,7 +35,7 @@ struct SubClassReference { }; struct SubMultiClassReference { - SMLoc RefLoc; + SMRange RefRange; MultiClass *MC; std::vector TemplateArgs; SubMultiClassReference() : MC(0) {} @@ -93,7 +93,7 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName, // Do not allow assignments like 'X = X'. This will just cause infinite loops // in the resolution machinery. if (BitList.empty()) - if (VarInit *VI = dynamic_cast(V)) + if (VarInit *VI = dyn_cast(V)) if (VI->getNameInit() == ValName) return false; @@ -102,7 +102,7 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName, // initializer. // if (!BitList.empty()) { - BitsInit *CurVal = dynamic_cast(RV->getValue()); + BitsInit *CurVal = dyn_cast(RV->getValue()); if (CurVal == 0) return Error(Loc, "Value '" + ValName->getAsUnquotedString() + "' is not a bits type"); @@ -110,12 +110,11 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName, // Convert the incoming value to a bits type of the appropriate size... Init *BI = V->convertInitializerTo(BitsRecTy::get(BitList.size())); if (BI == 0) { - V->convertInitializerTo(BitsRecTy::get(BitList.size())); return Error(Loc, "Initializer is not compatible with bit range"); } // We should have a BitsInit type now. - BitsInit *BInit = dynamic_cast(BI); + BitsInit *BInit = dyn_cast(BI); assert(BInit != 0); SmallVector NewBits(CurVal->getNumBits()); @@ -151,22 +150,23 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { // Add all of the values in the subclass into the current class. const std::vector &Vals = SC->getValues(); for (unsigned i = 0, e = Vals.size(); i != e; ++i) - if (AddValue(CurRec, SubClass.RefLoc, Vals[i])) + if (AddValue(CurRec, SubClass.RefRange.Start, Vals[i])) return true; const std::vector &TArgs = SC->getTemplateArgs(); // Ensure that an appropriate number of template arguments are specified. if (TArgs.size() < SubClass.TemplateArgs.size()) - return Error(SubClass.RefLoc, "More template args specified than expected"); + return Error(SubClass.RefRange.Start, + "More template args specified than expected"); // Loop over all of the template arguments, setting them to the specified // value or leaving them as the default if necessary. for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { if (i < SubClass.TemplateArgs.size()) { // If a value is specified for this template arg, set it now. - if (SetValue(CurRec, SubClass.RefLoc, TArgs[i], std::vector(), - SubClass.TemplateArgs[i])) + if (SetValue(CurRec, SubClass.RefRange.Start, TArgs[i], + std::vector(), SubClass.TemplateArgs[i])) return true; // Resolve it next. @@ -176,7 +176,8 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { CurRec->removeValue(TArgs[i]); } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { - return Error(SubClass.RefLoc,"Value not specified for template argument #" + return Error(SubClass.RefRange.Start, + "Value not specified for template argument #" + utostr(i) + " (" + TArgs[i]->getAsUnquotedString() + ") of subclass '" + SC->getNameInitAsString() + "'!"); } @@ -185,17 +186,18 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { // Since everything went well, we can now set the "superclass" list for the // current record. const std::vector &SCs = SC->getSuperClasses(); + ArrayRef SCRanges = SC->getSuperClassRanges(); for (unsigned i = 0, e = SCs.size(); i != e; ++i) { if (CurRec->isSubClassOf(SCs[i])) - return Error(SubClass.RefLoc, + return Error(SubClass.RefRange.Start, "Already subclass of '" + SCs[i]->getName() + "'!\n"); - CurRec->addSuperClass(SCs[i]); + CurRec->addSuperClass(SCs[i], SCRanges[i]); } if (CurRec->isSubClassOf(SC)) - return Error(SubClass.RefLoc, + return Error(SubClass.RefRange.Start, "Already subclass of '" + SC->getName() + "'!\n"); - CurRec->addSuperClass(SC); + CurRec->addSuperClass(SC, SubClass.RefRange); return false; } @@ -212,7 +214,7 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC, // Add all of the values in the subclass into the current class. const std::vector &SMCVals = SMC->Rec.getValues(); for (unsigned i = 0, e = SMCVals.size(); i != e; ++i) - if (AddValue(CurRec, SubMultiClass.RefLoc, SMCVals[i])) + if (AddValue(CurRec, SubMultiClass.RefRange.Start, SMCVals[i])) return true; int newDefStart = CurMC->DefPrototypes.size(); @@ -227,7 +229,7 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC, // Add all of the values in the superclass into the current def. for (unsigned i = 0, e = MCVals.size(); i != e; ++i) - if (AddValue(NewDef, SubMultiClass.RefLoc, MCVals[i])) + if (AddValue(NewDef, SubMultiClass.RefRange.Start, MCVals[i])) return true; CurMC->DefPrototypes.push_back(NewDef); @@ -238,7 +240,7 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC, // Ensure that an appropriate number of template arguments are // specified. if (SMCTArgs.size() < SubMultiClass.TemplateArgs.size()) - return Error(SubMultiClass.RefLoc, + return Error(SubMultiClass.RefRange.Start, "More template args specified than expected"); // Loop over all of the template arguments, setting them to the specified @@ -247,7 +249,7 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC, if (i < SubMultiClass.TemplateArgs.size()) { // If a value is specified for this template arg, set it in the // superclass now. - if (SetValue(CurRec, SubMultiClass.RefLoc, SMCTArgs[i], + if (SetValue(CurRec, SubMultiClass.RefRange.Start, SMCTArgs[i], std::vector(), SubMultiClass.TemplateArgs[i])) return true; @@ -267,7 +269,7 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC, ++j) { Record *Def = *j; - if (SetValue(Def, SubMultiClass.RefLoc, SMCTArgs[i], + if (SetValue(Def, SubMultiClass.RefRange.Start, SMCTArgs[i], std::vector(), SubMultiClass.TemplateArgs[i])) return true; @@ -279,7 +281,7 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC, Def->removeValue(SMCTArgs[i]); } } else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) { - return Error(SubMultiClass.RefLoc, + return Error(SubMultiClass.RefRange.Start, "Value not specified for template argument #" + utostr(i) + " (" + SMCTArgs[i]->getAsUnquotedString() + ") of subclass '" + SMC->Rec.getNameInitAsString() + "'!"); @@ -311,7 +313,7 @@ bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc, IterSet &IterVals){ if (IterVals.size() != Loops.size()) { assert(IterVals.size() < Loops.size()); ForeachLoop &CurLoop = Loops[IterVals.size()]; - ListInit *List = dynamic_cast(CurLoop.ListValue); + ListInit *List = dyn_cast(CurLoop.ListValue); if (List == 0) { Error(Loc, "Loop list is not a list"); return true; @@ -336,7 +338,7 @@ bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc, IterSet &IterVals){ // Set the iterator values now. for (unsigned i = 0, e = IterVals.size(); i != e; ++i) { VarInit *IterVar = IterVals[i].IterVar; - TypedInit *IVal = dynamic_cast(IterVals[i].IterValue); + TypedInit *IVal = dyn_cast(IterVals[i].IterValue); if (IVal == 0) { Error(Loc, "foreach iterator value is untyped"); return true; @@ -380,11 +382,12 @@ static bool isObjectStart(tgtok::TokKind K) { static std::string GetNewAnonymousName() { static unsigned AnonCounter = 0; - return "anonymous."+utostr(AnonCounter++); + unsigned Tmp = AnonCounter++; // MSVC2012 ICEs without this. + return "anonymous." + utostr(Tmp); } /// ParseObjectName - If an object name is specified, return it. Otherwise, -/// return an anonymous name. +/// return 0. /// ObjectName ::= Value [ '#' Value ]* /// ObjectName ::= /*empty*/ /// @@ -396,7 +399,7 @@ Init *TGParser::ParseObjectName(MultiClass *CurMultiClass) { // These are all of the tokens that can begin an object body. // Some of these can also begin values but we disallow those cases // because they are unlikely to be useful. - return StringInit::get(GetNewAnonymousName()); + return 0; default: break; } @@ -407,8 +410,7 @@ Init *TGParser::ParseObjectName(MultiClass *CurMultiClass) { RecTy *Type = 0; if (CurRec) { - const TypedInit *CurRecName = - dynamic_cast(CurRec->getNameInit()); + const TypedInit *CurRecName = dyn_cast(CurRec->getNameInit()); if (!CurRecName) { TokError("Record name is not typed!"); return 0; @@ -445,35 +447,18 @@ Record *TGParser::ParseClassID() { /// MultiClass *TGParser::ParseMultiClassID() { if (Lex.getCode() != tgtok::Id) { - TokError("expected name for ClassID"); + TokError("expected name for MultiClassID"); return 0; } MultiClass *Result = MultiClasses[Lex.getCurStrVal()]; if (Result == 0) - TokError("Couldn't find class '" + Lex.getCurStrVal() + "'"); - - Lex.Lex(); - return Result; -} - -Record *TGParser::ParseDefmID() { - if (Lex.getCode() != tgtok::Id) { - TokError("expected multiclass name"); - return 0; - } - - MultiClass *MC = MultiClasses[Lex.getCurStrVal()]; - if (MC == 0) { TokError("Couldn't find multiclass '" + Lex.getCurStrVal() + "'"); - return 0; - } Lex.Lex(); - return &MC->Rec; + return Result; } - /// ParseSubClassReference - Parse a reference to a subclass or to a templated /// subclass. This returns a SubClassRefTy with a null Record* on error. /// @@ -483,17 +468,21 @@ Record *TGParser::ParseDefmID() { SubClassReference TGParser:: ParseSubClassReference(Record *CurRec, bool isDefm) { SubClassReference Result; - Result.RefLoc = Lex.getLoc(); + Result.RefRange.Start = Lex.getLoc(); - if (isDefm) - Result.Rec = ParseDefmID(); - else + if (isDefm) { + if (MultiClass *MC = ParseMultiClassID()) + Result.Rec = &MC->Rec; + } else { Result.Rec = ParseClassID(); + } if (Result.Rec == 0) return Result; // If there is no template arg list, we're done. - if (Lex.getCode() != tgtok::less) + if (Lex.getCode() != tgtok::less) { + Result.RefRange.End = Lex.getLoc(); return Result; + } Lex.Lex(); // Eat the '<' if (Lex.getCode() == tgtok::greater) { @@ -514,6 +503,7 @@ ParseSubClassReference(Record *CurRec, bool isDefm) { return Result; } Lex.Lex(); + Result.RefRange.End = Lex.getLoc(); return Result; } @@ -528,14 +518,16 @@ ParseSubClassReference(Record *CurRec, bool isDefm) { SubMultiClassReference TGParser:: ParseSubMultiClassReference(MultiClass *CurMC) { SubMultiClassReference Result; - Result.RefLoc = Lex.getLoc(); + Result.RefRange.Start = Lex.getLoc(); Result.MC = ParseMultiClassID(); if (Result.MC == 0) return Result; // If there is no template arg list, we're done. - if (Lex.getCode() != tgtok::less) + if (Lex.getCode() != tgtok::less) { + Result.RefRange.End = Lex.getLoc(); return Result; + } Lex.Lex(); // Eat the '<' if (Lex.getCode() == tgtok::greater) { @@ -556,6 +548,7 @@ ParseSubMultiClassReference(MultiClass *CurMC) { return Result; } Lex.Lex(); + Result.RefRange.End = Lex.getLoc(); return Result; } @@ -781,7 +774,7 @@ Init *TGParser::ParseIDValue(Record *CurRec, for (LoopVector::iterator i = Loops.begin(), iend = Loops.end(); i != iend; ++i) { - VarInit *IterVar = dynamic_cast(i->IterVar); + VarInit *IterVar = dyn_cast(i->IterVar); if (IterVar && IterVar->getName() == Name) return IterVar; } @@ -856,16 +849,16 @@ Init *TGParser::ParseOperation(Record *CurRec) { if (Code == UnOpInit::HEAD || Code == UnOpInit::TAIL || Code == UnOpInit::EMPTY) { - ListInit *LHSl = dynamic_cast(LHS); - StringInit *LHSs = dynamic_cast(LHS); - TypedInit *LHSt = dynamic_cast(LHS); + ListInit *LHSl = dyn_cast(LHS); + StringInit *LHSs = dyn_cast(LHS); + TypedInit *LHSt = dyn_cast(LHS); if (LHSl == 0 && LHSs == 0 && LHSt == 0) { TokError("expected list or string type argument in unary operator"); return 0; } if (LHSt) { - ListRecTy *LType = dynamic_cast(LHSt->getType()); - StringRecTy *SType = dynamic_cast(LHSt->getType()); + ListRecTy *LType = dyn_cast(LHSt->getType()); + StringRecTy *SType = dyn_cast(LHSt->getType()); if (LType == 0 && SType == 0) { TokError("expected list or string type argumnet in unary operator"); return 0; @@ -885,7 +878,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { } if (LHSl) { Init *Item = LHSl->getElement(0); - TypedInit *Itemt = dynamic_cast(Item); + TypedInit *Itemt = dyn_cast(Item); if (Itemt == 0) { TokError("untyped list element in unary operator"); return 0; @@ -897,7 +890,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { } } else { assert(LHSt && "expected list type argument in unary operator"); - ListRecTy *LType = dynamic_cast(LHSt->getType()); + ListRecTy *LType = dyn_cast(LHSt->getType()); if (LType == 0) { TokError("expected list type argumnet in unary operator"); return 0; @@ -920,6 +913,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { } case tgtok::XConcat: + case tgtok::XADD: case tgtok::XSRA: case tgtok::XSRL: case tgtok::XSHL: @@ -935,6 +929,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { switch (OpTok) { default: llvm_unreachable("Unhandled code!"); case tgtok::XConcat: Code = BinOpInit::CONCAT;Type = DagRecTy::get(); break; + case tgtok::XADD: Code = BinOpInit::ADD; Type = IntRecTy::get(); break; case tgtok::XSRA: Code = BinOpInit::SRA; Type = IntRecTy::get(); break; case tgtok::XSRL: Code = BinOpInit::SRL; Type = IntRecTy::get(); break; case tgtok::XSHL: Code = BinOpInit::SHL; Type = IntRecTy::get(); break; @@ -1044,35 +1039,28 @@ Init *TGParser::ParseOperation(Record *CurRec) { switch (LexCode) { default: llvm_unreachable("Unhandled code!"); case tgtok::XIf: { - // FIXME: The `!if' operator doesn't handle non-TypedInit well at - // all. This can be made much more robust. - TypedInit *MHSt = dynamic_cast(MHS); - TypedInit *RHSt = dynamic_cast(RHS); - RecTy *MHSTy = 0; RecTy *RHSTy = 0; - if (MHSt == 0 && RHSt == 0) { - BitsInit *MHSbits = dynamic_cast(MHS); - BitsInit *RHSbits = dynamic_cast(RHS); - - if (MHSbits && RHSbits && - MHSbits->getNumBits() == RHSbits->getNumBits()) { - Type = BitRecTy::get(); - break; - } else { - BitInit *MHSbit = dynamic_cast(MHS); - BitInit *RHSbit = dynamic_cast(RHS); - - if (MHSbit && RHSbit) { - Type = BitRecTy::get(); - break; - } - } - } else if (MHSt != 0 && RHSt != 0) { + if (TypedInit *MHSt = dyn_cast(MHS)) MHSTy = MHSt->getType(); + if (BitsInit *MHSbits = dyn_cast(MHS)) + MHSTy = BitsRecTy::get(MHSbits->getNumBits()); + if (isa(MHS)) + MHSTy = BitRecTy::get(); + + if (TypedInit *RHSt = dyn_cast(RHS)) RHSTy = RHSt->getType(); - } + if (BitsInit *RHSbits = dyn_cast(RHS)) + RHSTy = BitsRecTy::get(RHSbits->getNumBits()); + if (isa(RHS)) + RHSTy = BitRecTy::get(); + + // For UnsetInit, it's typed from the other hand. + if (isa(MHS)) + MHSTy = RHSTy; + if (isa(RHS)) + RHSTy = MHSTy; if (!MHSTy || !RHSTy) { TokError("could not get type for !if"); @@ -1090,7 +1078,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { break; } case tgtok::XForEach: { - TypedInit *MHSt = dynamic_cast(MHS); + TypedInit *MHSt = dyn_cast(MHS); if (MHSt == 0) { TokError("could not get type for !foreach"); return 0; @@ -1099,7 +1087,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { break; } case tgtok::XSubst: { - TypedInit *RHSt = dynamic_cast(RHS); + TypedInit *RHSt = dyn_cast(RHS); if (RHSt == 0) { TokError("could not get type for !subst"); return 0; @@ -1157,6 +1145,7 @@ RecTy *TGParser::ParseOperatorType() { /// SimpleValue ::= '[' ValueList ']' /// SimpleValue ::= '(' IDValue DagArgList ')' /// SimpleValue ::= CONCATTOK '(' Value ',' Value ')' +/// SimpleValue ::= ADDTOK '(' Value ',' Value ')' /// SimpleValue ::= SHLTOK '(' Value ',' Value ')' /// SimpleValue ::= SRATOK '(' Value ',' Value ')' /// SimpleValue ::= SRLTOK '(' Value ',' Value ')' @@ -1223,14 +1212,16 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, return 0; } Lex.Lex(); // eat the '>' + SMLoc EndLoc = Lex.getLoc(); // Create the new record, set it as CurRec temporarily. static unsigned AnonCounter = 0; Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++), NameLoc, - Records); + Records, + /*IsAnonymous=*/true); SubClassReference SCRef; - SCRef.RefLoc = NameLoc; + SCRef.RefRange = SMRange(NameLoc, EndLoc); SCRef.Rec = Class; SCRef.TemplateArgs = ValueList; // Add info about the subclass to NewRec. @@ -1278,7 +1269,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, ListRecTy *GivenListTy = 0; if (ItemType != 0) { - ListRecTy *ListType = dynamic_cast(ItemType); + ListRecTy *ListType = dyn_cast(ItemType); if (ListType == 0) { std::stringstream s; s << "Type mismatch for list, expected list type, got " @@ -1323,7 +1314,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, for (std::vector::iterator i = Vals.begin(), ie = Vals.end(); i != ie; ++i) { - TypedInit *TArg = dynamic_cast(*i); + TypedInit *TArg = dyn_cast(*i); if (TArg == 0) { TokError("Untyped list element"); return 0; @@ -1410,6 +1401,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, case tgtok::XEmpty: case tgtok::XCast: // Value ::= !unop '(' Value ')' case tgtok::XConcat: + case tgtok::XADD: case tgtok::XSRA: case tgtok::XSRL: case tgtok::XSHL: @@ -1506,7 +1498,7 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) { // Create a !strconcat() operation, first casting each operand to // a string if necessary. - TypedInit *LHS = dynamic_cast(Result); + TypedInit *LHS = dyn_cast(Result); if (!LHS) { Error(PasteLoc, "LHS of paste is not typed!"); return 0; @@ -1533,7 +1525,7 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) { default: Init *RHSResult = ParseValue(CurRec, ItemType, ParseNameMode); - RHS = dynamic_cast(RHSResult); + RHS = dyn_cast(RHSResult); if (!RHS) { Error(PasteLoc, "RHS of paste is not typed!"); return 0; @@ -1555,29 +1547,39 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) { /// ParseDagArgList - Parse the argument list for a dag literal expression. /// -/// ParseDagArgList ::= Value (':' VARNAME)? -/// ParseDagArgList ::= ParseDagArgList ',' Value (':' VARNAME)? +/// DagArg ::= Value (':' VARNAME)? +/// DagArg ::= VARNAME +/// DagArgList ::= DagArg +/// DagArgList ::= DagArgList ',' DagArg std::vector > TGParser::ParseDagArgList(Record *CurRec) { std::vector > Result; while (1) { - Init *Val = ParseValue(CurRec); - if (Val == 0) return std::vector >(); - - // If the variable name is present, add it. - std::string VarName; - if (Lex.getCode() == tgtok::colon) { - if (Lex.Lex() != tgtok::VarName) { // eat the ':' - TokError("expected variable name in dag literal"); + // DagArg ::= VARNAME + if (Lex.getCode() == tgtok::VarName) { + // A missing value is treated like '?'. + Result.push_back(std::make_pair(UnsetInit::get(), Lex.getCurStrVal())); + Lex.Lex(); + } else { + // DagArg ::= Value (':' VARNAME)? + Init *Val = ParseValue(CurRec); + if (Val == 0) return std::vector >(); - } - VarName = Lex.getCurStrVal(); - Lex.Lex(); // eat the VarName. - } - Result.push_back(std::make_pair(Val, VarName)); + // If the variable name is present, add it. + std::string VarName; + if (Lex.getCode() == tgtok::colon) { + if (Lex.Lex() != tgtok::VarName) { // eat the ':' + TokError("expected variable name in dag literal"); + return std::vector >(); + } + VarName = Lex.getCurStrVal(); + Lex.Lex(); // eat the VarName. + } + Result.push_back(std::make_pair(Val, VarName)); + } if (Lex.getCode() != tgtok::comma) break; Lex.Lex(); // eat the ',' } @@ -1697,7 +1699,9 @@ Init *TGParser::ParseDeclaration(Record *CurRec, /// the name of the declared object or a NULL Init on error. Return /// the name of the parsed initializer list through ForeachListName. /// -/// ForeachDeclaration ::= ID '=' Value +/// ForeachDeclaration ::= ID '=' '[' ValueList ']' +/// ForeachDeclaration ::= ID '=' '{' RangeList '}' +/// ForeachDeclaration ::= ID '=' RangePiece /// VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) { if (Lex.getCode() != tgtok::Id) { @@ -1715,26 +1719,59 @@ VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) { } Lex.Lex(); // Eat the '=' - // Expect a list initializer. - Init *List = ParseSimpleValue(0, 0, ParseForeachMode); + RecTy *IterType = 0; + std::vector Ranges; - ForeachListValue = dynamic_cast(List); - if (ForeachListValue == 0) { - TokError("Expected a Value list"); - return 0; + switch (Lex.getCode()) { + default: TokError("Unknown token when expecting a range list"); return 0; + case tgtok::l_square: { // '[' ValueList ']' + Init *List = ParseSimpleValue(0, 0, ParseForeachMode); + ForeachListValue = dyn_cast(List); + if (ForeachListValue == 0) { + TokError("Expected a Value list"); + return 0; + } + RecTy *ValueType = ForeachListValue->getType(); + ListRecTy *ListType = dyn_cast(ValueType); + if (ListType == 0) { + TokError("Value list is not of list type"); + return 0; + } + IterType = ListType->getElementType(); + break; } - RecTy *ValueType = ForeachListValue->getType(); - ListRecTy *ListType = dynamic_cast(ValueType); - if (ListType == 0) { - TokError("Value list is not of list type"); - return 0; + case tgtok::IntVal: { // RangePiece. + if (ParseRangePiece(Ranges)) + return 0; + break; } - RecTy *IterType = ListType->getElementType(); - VarInit *IterVar = VarInit::get(DeclName, IterType); + case tgtok::l_brace: { // '{' RangeList '}' + Lex.Lex(); // eat the '{' + Ranges = ParseRangeList(); + if (Lex.getCode() != tgtok::r_brace) { + TokError("expected '}' at end of bit range list"); + return 0; + } + Lex.Lex(); + break; + } + } + + if (!Ranges.empty()) { + assert(!IterType && "Type already initialized?"); + IterType = IntRecTy::get(); + std::vector Values; + for (unsigned i = 0, e = Ranges.size(); i != e; ++i) + Values.push_back(IntInit::get(Ranges[i])); + ForeachListValue = ListInit::get(Values, IterType); + } - return IterVar; + if (!IterType) + return 0; + + return VarInit::get(DeclName, IterType); } /// ParseTemplateArgList - Read a template argument list, which is a non-empty @@ -1850,6 +1887,17 @@ bool TGParser::ParseBody(Record *CurRec) { return false; } +/// \brief Apply the current let bindings to \a CurRec. +/// \returns true on error, false otherwise. +bool TGParser::ApplyLetStack(Record *CurRec) { + 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; + return false; +} + /// ParseObjectBody - Parse the body of a def or class. This consists of an /// optional ClassList followed by a Body. CurRec is the current def or class /// that is being parsed. @@ -1880,12 +1928,8 @@ bool TGParser::ParseObjectBody(Record *CurRec) { } } - // 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 (ApplyLetStack(CurRec)) + return true; return ParseBody(CurRec); } @@ -1901,9 +1945,15 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { Lex.Lex(); // Eat the 'def' token. // Parse ObjectName and make a record for it. - Record *CurRec = new Record(ParseObjectName(CurMultiClass), DefLoc, Records); + Record *CurRec; + Init *Name = ParseObjectName(CurMultiClass); + if (Name) + CurRec = new Record(Name, DefLoc, Records); + else + CurRec = new Record(GetNewAnonymousName(), DefLoc, Records, + /*IsAnonymous=*/true); - if (!CurMultiClass) { + if (!CurMultiClass && Loops.empty()) { // Top-level def definition. // Ensure redefinition doesn't happen. @@ -1913,7 +1963,7 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { return true; } Records.addDef(CurRec); - } else { + } else if (CurMultiClass) { // Otherwise, a def inside a multiclass, add it to the multiclass. for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); i != e; ++i) if (CurMultiClass->DefPrototypes[i]->getNameInit() @@ -2134,7 +2184,12 @@ bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) { /// ParseMultiClass - Parse a multiclass definition. /// /// MultiClassInst ::= MULTICLASS ID TemplateArgList? -/// ':' BaseMultiClassList '{' MultiClassDef+ '}' +/// ':' BaseMultiClassList '{' MultiClassObject+ '}' +/// MultiClassObject ::= DefInst +/// MultiClassObject ::= MultiClassInst +/// MultiClassObject ::= DefMInst +/// MultiClassObject ::= LETCommand '{' ObjectList '}' +/// MultiClassObject ::= LETCommand Object /// bool TGParser::ParseMultiClass() { assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token"); @@ -2216,7 +2271,7 @@ Record *TGParser:: InstantiateMulticlassDef(MultiClass &MC, Record *DefProto, Init *DefmPrefix, - SMLoc DefmPrefixLoc) { + SMRange DefmPrefixRange) { // We need to preserve DefProto so it can be reused for later // instantiations, so create a new Record to inherit from it. @@ -2225,12 +2280,15 @@ InstantiateMulticlassDef(MultiClass &MC, // name, substitute the prefix for #NAME#. Otherwise, use the defm name // as a prefix. - if (DefmPrefix == 0) + bool IsAnonymous = false; + if (DefmPrefix == 0) { DefmPrefix = StringInit::get(GetNewAnonymousName()); + IsAnonymous = true; + } Init *DefName = DefProto->getNameInit(); - StringInit *DefNameString = dynamic_cast(DefName); + StringInit *DefNameString = dyn_cast(DefName); if (DefNameString != 0) { // We have a fully expanded string so there are no operators to @@ -2242,30 +2300,43 @@ InstantiateMulticlassDef(MultiClass &MC, DefName, StringRecTy::get())->Fold(DefProto, &MC); } - Record *CurRec = new Record(DefName, DefmPrefixLoc, Records); + // Make a trail of SMLocs from the multiclass instantiations. + SmallVector Locs(1, DefmPrefixRange.Start); + Locs.append(DefProto->getLoc().begin(), DefProto->getLoc().end()); + Record *CurRec = new Record(DefName, Locs, Records, IsAnonymous); SubClassReference Ref; - Ref.RefLoc = DefmPrefixLoc; + Ref.RefRange = DefmPrefixRange; Ref.Rec = DefProto; AddSubClass(CurRec, Ref); - if (DefNameString == 0) { - // We must resolve references to NAME. - if (SetValue(CurRec, Ref.RefLoc, "NAME", std::vector(), - DefmPrefix)) { - Error(DefmPrefixLoc, "Could not resolve " - + CurRec->getNameInitAsString() + ":NAME to '" - + DefmPrefix->getAsUnquotedString() + "'"); - return 0; - } + // Set the value for NAME. We don't resolve references to it 'til later, + // though, so that uses in nested multiclass names don't get + // confused. + if (SetValue(CurRec, Ref.RefRange.Start, "NAME", std::vector(), + DefmPrefix)) { + Error(DefmPrefixRange.Start, "Could not resolve " + + CurRec->getNameInitAsString() + ":NAME to '" + + DefmPrefix->getAsUnquotedString() + "'"); + return 0; + } + // If the DefNameString didn't resolve, we probably have a reference to + // NAME and need to replace it. We need to do at least this much greedily, + // otherwise nested multiclasses will end up with incorrect NAME expansions. + if (DefNameString == 0) { RecordVal *DefNameRV = CurRec->getValue("NAME"); CurRec->resolveReferencesTo(DefNameRV); } if (!CurMultiClass) { - // We do this after resolving NAME because before resolution, many - // multiclass defs will have the same name expression. If we are + // Now that we're at the top level, resolve all NAME references + // in the resultant defs that weren't in the def names themselves. + RecordVal *DefNameRV = CurRec->getValue("NAME"); + CurRec->resolveReferencesTo(DefNameRV); + + // Now that NAME references are resolved and we're at the top level of + // any multiclass expansions, add the record to the RecordKeeper. If we are // currently in a multiclass, it means this defm appears inside a // multiclass and its name won't be fully resolvable until we see // the top-level defm. Therefore, we don't add this to the @@ -2275,7 +2346,7 @@ InstantiateMulticlassDef(MultiClass &MC, // Ensure redefinition doesn't happen. if (Records.getDef(CurRec->getNameInitAsString())) { - Error(DefmPrefixLoc, "def '" + CurRec->getNameInitAsString() + + Error(DefmPrefixRange.Start, "def '" + CurRec->getNameInitAsString() + "' already defined, instantiating defm with subdef '" + DefProto->getNameInitAsString() + "'"); return 0; @@ -2326,33 +2397,30 @@ bool TGParser::ResolveMulticlassDef(MultiClass &MC, Record *DefProto, SMLoc DefmPrefixLoc) { // If the mdef is inside a 'let' expression, add to each def. - 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 Error(DefmPrefixLoc, "when instantiating this defm"); + if (ApplyLetStack(CurRec)) + return Error(DefmPrefixLoc, "when instantiating this defm"); // 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]->getNameInit() - == CurRec->getNameInit()) - return Error(DefmPrefixLoc, "defm '" + CurRec->getNameInitAsString() + - "' already defined in this multiclass!"); - CurMultiClass->DefPrototypes.push_back(CurRec); + if (!CurMultiClass) + return false; + for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); + i != e; ++i) + if (CurMultiClass->DefPrototypes[i]->getNameInit() + == CurRec->getNameInit()) + return Error(DefmPrefixLoc, "defm '" + CurRec->getNameInitAsString() + + "' already defined in this multiclass!"); + CurMultiClass->DefPrototypes.push_back(CurRec); - // Copy the template arguments for the multiclass into the new def. - const std::vector &TA = - CurMultiClass->Rec.getTemplateArgs(); + // Copy the template arguments for the multiclass into the new def. + const std::vector &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); - } + 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); } return false; @@ -2364,14 +2432,14 @@ bool TGParser::ResolveMulticlassDef(MultiClass &MC, /// bool TGParser::ParseDefm(MultiClass *CurMultiClass) { assert(Lex.getCode() == tgtok::Defm && "Unexpected token!"); - + SMLoc DefmLoc = Lex.getLoc(); Init *DefmPrefix = 0; if (Lex.Lex() == tgtok::Id) { // eat the defm. DefmPrefix = ParseObjectName(CurMultiClass); } - SMLoc DefmPrefixLoc = Lex.getLoc(); + SMLoc DefmPrefixEndLoc = Lex.getLoc(); if (Lex.getCode() != tgtok::colon) return TokError("expected ':' after defm identifier"); @@ -2407,15 +2475,17 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) { Record *DefProto = MC->DefPrototypes[i]; - Record *CurRec = InstantiateMulticlassDef(*MC, DefProto, DefmPrefix, DefmPrefixLoc); + Record *CurRec = InstantiateMulticlassDef(*MC, DefProto, DefmPrefix, + SMRange(DefmLoc, + DefmPrefixEndLoc)); if (!CurRec) return true; - if (ResolveMulticlassDefArgs(*MC, CurRec, DefmPrefixLoc, SubClassLoc, + if (ResolveMulticlassDefArgs(*MC, CurRec, DefmLoc, SubClassLoc, TArgs, TemplateVals, true/*Delete args*/)) return Error(SubClassLoc, "could not instantiate def"); - if (ResolveMulticlassDef(*MC, CurRec, DefProto, DefmPrefixLoc)) + if (ResolveMulticlassDef(*MC, CurRec, DefProto, DefmLoc)) return Error(SubClassLoc, "could not instantiate def"); NewRecDefs.push_back(CurRec); @@ -2454,12 +2524,8 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { 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 (ApplyLetStack(CurRec)) + return true; } if (Lex.getCode() != tgtok::comma) break;