X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTableGen%2FTGParser.cpp;h=e5875ad7957ed8ec15a76bd341a2d3c5c8bc31b5;hb=22bd64173981bf1251c4b3bfc684207340534ba3;hp=0f64f4bcdac33c34698ffff37722ab2fd26282d5;hpb=1d5013992f8ecf5cc670ab8a1a599db4722c2f5d;p=oota-llvm.git diff --git a/lib/TableGen/TGParser.cpp b/lib/TableGen/TGParser.cpp index 0f64f4bcdac..e5875ad7957 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; //===----------------------------------------------------------------------===// @@ -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()); @@ -289,6 +288,84 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC, return false; } +/// ProcessForeachDefs - Given a record, apply all of the variable +/// values in all surrounding foreach loops, creating new records for +/// each combination of values. +bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc) { + if (Loops.empty()) + return false; + + // We want to instantiate a new copy of CurRec for each combination + // of nested loop iterator values. We don't want top instantiate + // any copies until we have values for each loop iterator. + IterSet IterVals; + return ProcessForeachDefs(CurRec, Loc, IterVals); +} + +/// ProcessForeachDefs - Given a record, a loop and a loop iterator, +/// apply each of the variable values in this loop and then process +/// subloops. +bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc, IterSet &IterVals){ + // Recursively build a tuple of iterator values. + if (IterVals.size() != Loops.size()) { + assert(IterVals.size() < Loops.size()); + ForeachLoop &CurLoop = Loops[IterVals.size()]; + ListInit *List = dyn_cast(CurLoop.ListValue); + if (List == 0) { + Error(Loc, "Loop list is not a list"); + return true; + } + + // Process each value. + for (int64_t i = 0; i < List->getSize(); ++i) { + Init *ItemVal = List->resolveListElementReference(*CurRec, 0, i); + IterVals.push_back(IterRecord(CurLoop.IterVar, ItemVal)); + if (ProcessForeachDefs(CurRec, Loc, IterVals)) + return true; + IterVals.pop_back(); + } + return false; + } + + // This is the bottom of the recursion. We have all of the iterator values + // for this point in the iteration space. Instantiate a new record to + // reflect this combination of values. + Record *IterRec = new Record(*CurRec); + + // Set the iterator values now. + for (unsigned i = 0, e = IterVals.size(); i != e; ++i) { + VarInit *IterVar = IterVals[i].IterVar; + TypedInit *IVal = dyn_cast(IterVals[i].IterValue); + if (IVal == 0) { + Error(Loc, "foreach iterator value is untyped"); + return true; + } + + IterRec->addValue(RecordVal(IterVar->getName(), IVal->getType(), false)); + + if (SetValue(IterRec, Loc, IterVar->getName(), + std::vector(), IVal)) { + Error(Loc, "when instantiating this def"); + return true; + } + + // Resolve it next. + IterRec->resolveReferencesTo(IterRec->getValue(IterVar->getName())); + + // Remove it. + IterRec->removeValue(IterVar->getName()); + } + + if (Records.getDef(IterRec->getNameInitAsString())) { + Error(Loc, "def already exists: " + IterRec->getNameInitAsString()); + return true; + } + + Records.addDef(IterRec); + IterRec->resolveReferences(); + return false; +} + //===----------------------------------------------------------------------===// // Parser Code //===----------------------------------------------------------------------===// @@ -296,7 +373,8 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC, /// isObjectStart - Return true if this is a valid first token for an Object. static bool isObjectStart(tgtok::TokKind K) { return K == tgtok::Class || K == tgtok::Def || - K == tgtok::Defm || K == tgtok::Let || K == tgtok::MultiClass; + K == tgtok::Defm || K == tgtok::Let || + K == tgtok::MultiClass || K == tgtok::Foreach; } static std::string GetNewAnonymousName() { @@ -328,8 +406,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; @@ -698,6 +775,15 @@ Init *TGParser::ParseIDValue(Record *CurRec, } } + // If this is in a foreach loop, make sure it's not a loop iterator + for (LoopVector::iterator i = Loops.begin(), iend = Loops.end(); + i != iend; + ++i) { + VarInit *IterVar = dyn_cast(i->IterVar); + if (IterVar && IterVar->getName() == Name) + return IterVar; + } + if (Mode == ParseNameMode) return StringInit::get(Name); @@ -729,7 +815,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { RecTy *Type = 0; switch (Lex.getCode()) { - default: assert(0 && "Unhandled code!"); + default: llvm_unreachable("Unhandled code!"); case tgtok::XCast: Lex.Lex(); // eat the operation Code = UnOpInit::CAST; @@ -768,16 +854,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; @@ -797,7 +883,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; @@ -809,7 +895,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; @@ -845,7 +931,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { RecTy *Type = 0; switch (OpTok) { - default: assert(0 && "Unhandled code!"); + default: llvm_unreachable("Unhandled code!"); case tgtok::XConcat: Code = BinOpInit::CONCAT;Type = DagRecTy::get(); break; case tgtok::XSRA: Code = BinOpInit::SRA; Type = IntRecTy::get(); break; case tgtok::XSRL: Code = BinOpInit::SRL; Type = IntRecTy::get(); break; @@ -909,7 +995,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { tgtok::TokKind LexCode = Lex.getCode(); Lex.Lex(); // eat the operation switch (LexCode) { - default: assert(0 && "Unhandled code!"); + default: llvm_unreachable("Unhandled code!"); case tgtok::XIf: Code = TernOpInit::IF; break; @@ -954,37 +1040,30 @@ Init *TGParser::ParseOperation(Record *CurRec) { Lex.Lex(); // eat the ')' switch (LexCode) { - default: assert(0 && "Unhandled code!"); + 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"); @@ -1002,7 +1081,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; @@ -1011,7 +1090,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; @@ -1190,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 " @@ -1235,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; @@ -1353,7 +1432,7 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) { switch (Lex.getCode()) { default: return Result; case tgtok::l_brace: { - if (Mode == ParseNameMode) + if (Mode == ParseNameMode || Mode == ParseForeachMode) // This is the beginning of the object body. return Result; @@ -1418,7 +1497,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; @@ -1445,7 +1524,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; @@ -1605,6 +1684,85 @@ Init *TGParser::ParseDeclaration(Record *CurRec, return DeclName; } +/// ParseForeachDeclaration - Read a foreach declaration, returning +/// the name of the declared object or a NULL Init on error. Return +/// the name of the parsed initializer list through ForeachListName. +/// +/// ForeachDeclaration ::= ID '=' '[' ValueList ']' +/// ForeachDeclaration ::= ID '=' '{' RangeList '}' +/// ForeachDeclaration ::= ID '=' RangePiece +/// +VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) { + if (Lex.getCode() != tgtok::Id) { + TokError("Expected identifier in foreach declaration"); + return 0; + } + + Init *DeclName = StringInit::get(Lex.getCurStrVal()); + Lex.Lex(); + + // If a value is present, parse it. + if (Lex.getCode() != tgtok::equal) { + TokError("Expected '=' in foreach declaration"); + return 0; + } + Lex.Lex(); // Eat the '=' + + RecTy *IterType = 0; + std::vector Ranges; + + 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; + } + + case tgtok::IntVal: { // RangePiece. + if (ParseRangePiece(Ranges)) + return 0; + break; + } + + 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); + } + + if (!IterType) + return 0; + + return VarInit::get(DeclName, IterType); +} + /// ParseTemplateArgList - Read a template argument list, which is a non-empty /// sequence of template-declarations in <>'s. If CurRec is non-null, these are /// template args for a def, which may or may not be in a multiclass. If null, @@ -1771,7 +1929,7 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { // Parse ObjectName and make a record for it. Record *CurRec = new Record(ParseObjectName(CurMultiClass), DefLoc, Records); - if (!CurMultiClass) { + if (!CurMultiClass && Loops.empty()) { // Top-level def definition. // Ensure redefinition doesn't happen. @@ -1781,7 +1939,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() @@ -1817,6 +1975,63 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { } } + if (ProcessForeachDefs(CurRec, DefLoc)) { + Error(DefLoc, + "Could not process loops for def" + CurRec->getNameInitAsString()); + return true; + } + + return false; +} + +/// ParseForeach - Parse a for statement. Return the record corresponding +/// to it. This returns true on error. +/// +/// Foreach ::= FOREACH Declaration IN '{ ObjectList '}' +/// Foreach ::= FOREACH Declaration IN Object +/// +bool TGParser::ParseForeach(MultiClass *CurMultiClass) { + assert(Lex.getCode() == tgtok::Foreach && "Unknown tok"); + Lex.Lex(); // Eat the 'for' token. + + // Make a temporary object to record items associated with the for + // loop. + ListInit *ListValue = 0; + VarInit *IterName = ParseForeachDeclaration(ListValue); + if (IterName == 0) + return TokError("expected declaration in for"); + + if (Lex.getCode() != tgtok::In) + return TokError("Unknown tok"); + Lex.Lex(); // Eat the in + + // Create a loop object and remember it. + Loops.push_back(ForeachLoop(IterName, ListValue)); + + if (Lex.getCode() != tgtok::l_brace) { + // FOREACH Declaration IN Object + if (ParseObject(CurMultiClass)) + return true; + } + else { + SMLoc BraceLoc = Lex.getLoc(); + // Otherwise, this is a group foreach. + Lex.Lex(); // eat the '{'. + + // Parse the object list. + if (ParseObjectList(CurMultiClass)) + return true; + + if (Lex.getCode() != tgtok::r_brace) { + TokError("expected '}' at end of foreach command"); + return Error(BraceLoc, "to match this '{'"); + } + Lex.Lex(); // Eat the } + } + + // We've processed everything in this loop. + Loops.pop_back(); + return false; } @@ -2010,6 +2225,7 @@ bool TGParser::ParseMultiClass() { case tgtok::Let: case tgtok::Def: case tgtok::Defm: + case tgtok::Foreach: if (ParseObject(CurMultiClass)) return true; break; @@ -2040,7 +2256,7 @@ InstantiateMulticlassDef(MultiClass &MC, 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 @@ -2052,30 +2268,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, DefmPrefixLoc); + Locs.append(DefProto->getLoc().begin(), DefProto->getLoc().end()); + Record *CurRec = new Record(DefName, Locs, Records); SubClassReference Ref; Ref.RefLoc = DefmPrefixLoc; 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.RefLoc, "NAME", std::vector(), + DefmPrefix)) { + Error(DefmPrefixLoc, "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 @@ -2177,7 +2406,11 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { Init *DefmPrefix = 0; - if (Lex.Lex() == tgtok::Id) { // eat the defm. + Lex.Lex(); // eat the defm. + + // Note that tgtok::paste is here to allow starting with #NAME. + if (Lex.getCode() == tgtok::Id || + Lex.getCode() == tgtok::paste) { DefmPrefix = ParseObjectName(CurMultiClass); } @@ -2305,6 +2538,7 @@ bool TGParser::ParseObject(MultiClass *MC) { return TokError("Expected class, def, defm, multiclass or let definition"); case tgtok::Let: return ParseTopLevelLet(MC); case tgtok::Def: return ParseDef(MC); + case tgtok::Foreach: return ParseForeach(MC); case tgtok::Defm: return ParseDefm(MC); case tgtok::Class: return ParseClass(); case tgtok::MultiClass: return ParseMultiClass();