X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FTGParser.cpp;h=59097f986f79b573e883845d3d29689f2cd25586;hb=eef965f04bab483a7d2fd46a7d51559197eda5cf;hp=8c158e0e4ee85b0c3d5cbeb680c90b966ffc1d0b;hpb=6786d5e18387465d6106eaef0b7923526ef0bc10;p=oota-llvm.git diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp index 8c158e0e4ee..59097f986f7 100644 --- a/utils/TableGen/TGParser.cpp +++ b/utils/TableGen/TGParser.cpp @@ -16,6 +16,8 @@ #include "llvm/ADT/StringExtras.h" #include #include +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -294,20 +296,23 @@ static bool isObjectStart(tgtok::TokKind K) { K == tgtok::Defm || K == tgtok::Let || K == tgtok::MultiClass; } +static std::string GetNewAnonymousName() { + static unsigned AnonCounter = 0; + return "anonymous."+utostr(AnonCounter++); +} + /// ParseObjectName - If an object name is specified, return it. Otherwise, /// return an anonymous name. /// ObjectName ::= ID /// ObjectName ::= /*empty*/ /// std::string TGParser::ParseObjectName() { - if (Lex.getCode() == tgtok::Id) { - std::string Ret = Lex.getCurStrVal(); - Lex.Lex(); - return Ret; - } + if (Lex.getCode() != tgtok::Id) + return GetNewAnonymousName(); - static unsigned AnonCounter = 0; - return "anonymous."+utostr(AnonCounter++); + std::string Ret = Lex.getCurStrVal(); + Lex.Lex(); + return Ret; } @@ -678,9 +683,9 @@ Init *TGParser::ParseOperation(Record *CurRec) { TokError("unknown operation"); return 0; break; - case tgtok::XCar: - case tgtok::XCdr: - case tgtok::XNull: + case tgtok::XHead: + case tgtok::XTail: + case tgtok::XEmpty: case tgtok::XCast: { // Value ::= !unop '(' Value ')' UnOpInit::UnaryOp Code; RecTy *Type = 0; @@ -699,17 +704,17 @@ Init *TGParser::ParseOperation(Record *CurRec) { } break; - case tgtok::XCar: + case tgtok::XHead: Lex.Lex(); // eat the operation - Code = UnOpInit::CAR; + Code = UnOpInit::HEAD; break; - case tgtok::XCdr: + case tgtok::XTail: Lex.Lex(); // eat the operation - Code = UnOpInit::CDR; + Code = UnOpInit::TAIL; break; - case tgtok::XNull: + case tgtok::XEmpty: Lex.Lex(); // eat the operation - Code = UnOpInit::LNULL; + Code = UnOpInit::EMPTY; Type = new IntRecTy; break; } @@ -722,9 +727,9 @@ Init *TGParser::ParseOperation(Record *CurRec) { Init *LHS = ParseValue(CurRec); if (LHS == 0) return 0; - if (Code == UnOpInit::CAR - || Code == UnOpInit::CDR - || Code == UnOpInit::LNULL) { + 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); @@ -741,8 +746,8 @@ Init *TGParser::ParseOperation(Record *CurRec) { } } - if (Code == UnOpInit::CAR - || Code == UnOpInit::CDR) { + if (Code == UnOpInit::HEAD + || Code == UnOpInit::TAIL) { if (LHSl == 0 && LHSt == 0) { TokError("expected list type argumnet in unary operator"); return 0; @@ -759,7 +764,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { TokError("untyped list element in unary operator"); return 0; } - if (Code == UnOpInit::CAR) { + if (Code == UnOpInit::HEAD) { Type = Itemt->getType(); } else { Type = new ListRecTy(Itemt->getType()); @@ -771,7 +776,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { TokError("expected list type argumnet in unary operator"); return 0; } - if (Code == UnOpInit::CAR) { + if (Code == UnOpInit::HEAD) { Type = LType->getElementType(); } else { Type = LType; @@ -793,81 +798,68 @@ Init *TGParser::ParseOperation(Record *CurRec) { case tgtok::XSRL: case tgtok::XSHL: case tgtok::XEq: - case tgtok::XStrConcat: - case tgtok::XNameConcat: { // Value ::= !binop '(' Value ',' Value ')' + case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')' + tgtok::TokKind OpTok = Lex.getCode(); + SMLoc OpLoc = Lex.getLoc(); + Lex.Lex(); // eat the operation + BinOpInit::BinaryOp Code; RecTy *Type = 0; - - switch (Lex.getCode()) { + switch (OpTok) { default: assert(0 && "Unhandled code!"); - case tgtok::XConcat: - Lex.Lex(); // eat the operation - Code = BinOpInit::CONCAT; - Type = new DagRecTy(); - break; - case tgtok::XSRA: - Lex.Lex(); // eat the operation - Code = BinOpInit::SRA; - Type = new IntRecTy(); - break; - case tgtok::XSRL: - Lex.Lex(); // eat the operation - Code = BinOpInit::SRL; - Type = new IntRecTy(); - break; - case tgtok::XSHL: - Lex.Lex(); // eat the operation - Code = BinOpInit::SHL; - Type = new IntRecTy(); - break; - case tgtok::XEq: - Lex.Lex(); // eat the operation - Code = BinOpInit::EQ; - Type = new IntRecTy(); - break; + case tgtok::XConcat: Code = BinOpInit::CONCAT; Type = new DagRecTy(); break; + case tgtok::XSRA: Code = BinOpInit::SRA; Type = new IntRecTy(); break; + case tgtok::XSRL: Code = BinOpInit::SRL; Type = new IntRecTy(); break; + case tgtok::XSHL: Code = BinOpInit::SHL; Type = new IntRecTy(); break; + case tgtok::XEq: Code = BinOpInit::EQ; Type = new BitRecTy(); break; case tgtok::XStrConcat: - Lex.Lex(); // eat the operation Code = BinOpInit::STRCONCAT; Type = new StringRecTy(); - break; - case tgtok::XNameConcat: - Lex.Lex(); // eat the operation - Code = BinOpInit::NAMECONCAT; - - Type = ParseOperatorType(); - - if (Type == 0) { - TokError("did not get type for binary operator"); - return 0; - } - break; } + if (Lex.getCode() != tgtok::l_paren) { TokError("expected '(' after binary operator"); return 0; } Lex.Lex(); // eat the '(' - Init *LHS = ParseValue(CurRec); - if (LHS == 0) return 0; + SmallVector InitList; - if (Lex.getCode() != tgtok::comma) { - TokError("expected ',' in binary operator"); - return 0; - } - Lex.Lex(); // eat the ',' + InitList.push_back(ParseValue(CurRec)); + if (InitList.back() == 0) return 0; - Init *RHS = ParseValue(CurRec); - if (RHS == 0) return 0; + while (Lex.getCode() == tgtok::comma) { + Lex.Lex(); // eat the ',' + + InitList.push_back(ParseValue(CurRec)); + if (InitList.back() == 0) return 0; + } if (Lex.getCode() != tgtok::r_paren) { - TokError("expected ')' in binary operator"); + TokError("expected ')' in operator"); return 0; } Lex.Lex(); // eat the ')' - return (new BinOpInit(Code, LHS, RHS, Type))->Fold(CurRec, CurMultiClass); + + // We allow multiple operands to associative operators like !strconcat as + // shorthand for nesting them. + if (Code == BinOpInit::STRCONCAT) { + while (InitList.size() > 2) { + Init *RHS = InitList.pop_back_val(); + RHS = (new BinOpInit(Code, InitList.back(), RHS, Type)) + ->Fold(CurRec, CurMultiClass); + InitList.back() = RHS; + } + } + + if (InitList.size() == 2) + return (new BinOpInit(Code, InitList[0], InitList[1], Type)) + ->Fold(CurRec, CurMultiClass); + + Error(OpLoc, "expected two operands to operator"); + return 0; } case tgtok::XIf: @@ -876,7 +868,6 @@ Init *TGParser::ParseOperation(Record *CurRec) { TernOpInit::TernaryOp Code; RecTy *Type = 0; - tgtok::TokKind LexCode = Lex.getCode(); Lex.Lex(); // eat the operation switch (LexCode) { @@ -927,16 +918,45 @@ Init *TGParser::ParseOperation(Record *CurRec) { switch (LexCode) { default: assert(0 && "Unhandled code!"); case tgtok::XIf: { - TypedInit *MHSt = dynamic_cast(MHS); - TypedInit *RHSt = dynamic_cast(RHS); - if (MHSt == 0 || RHSt == 0) { + // 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 = new BitRecTy(); + break; + } else { + BitInit *MHSbit = dynamic_cast(MHS); + BitInit *RHSbit = dynamic_cast(RHS); + + if (MHSbit && RHSbit) { + Type = new BitRecTy(); + break; + } + } + } else if (MHSt != 0 && RHSt != 0) { + MHSTy = MHSt->getType(); + RHSTy = RHSt->getType(); + } + + if (!MHSTy || !RHSTy) { TokError("could not get type for !if"); return 0; } - if (MHSt->getType()->typeIsConvertibleTo(RHSt->getType())) { - Type = RHSt->getType(); - } else if (RHSt->getType()->typeIsConvertibleTo(MHSt->getType())) { - Type = MHSt->getType(); + + if (MHSTy->typeIsConvertibleTo(RHSTy)) { + Type = RHSTy; + } else if (RHSTy->typeIsConvertibleTo(MHSTy)) { + Type = MHSTy; } else { TokError("inconsistent types for !if"); return 0; @@ -1037,8 +1057,13 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { break; } case tgtok::CodeFragment: - R = new CodeInit(Lex.getCurStrVal()); Lex.Lex(); break; - case tgtok::question: R = new UnsetInit(); Lex.Lex(); break; + R = new CodeInit(Lex.getCurStrVal()); + Lex.Lex(); + break; + case tgtok::question: + R = new UnsetInit(); + Lex.Lex(); + break; case tgtok::Id: { SMLoc NameLoc = Lex.getLoc(); std::string Name = Lex.getCurStrVal(); @@ -1071,7 +1096,9 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { // Create the new record, set it as CurRec temporarily. static unsigned AnonCounter = 0; - Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++),NameLoc); + Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++), + NameLoc, + Records); SubClassReference SCRef; SCRef.RefLoc = NameLoc; SCRef.Rec = Class; @@ -1126,6 +1153,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { s << "Type mismatch for list, expected list type, got " << ItemType->getAsString(); TokError(s.str()); + return 0; } GivenListTy = ListType; } @@ -1212,21 +1240,13 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { } case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')' Lex.Lex(); // eat the '(' - if (Lex.getCode() != tgtok::Id - && Lex.getCode() != tgtok::XCast - && Lex.getCode() != tgtok::XNameConcat) { + if (Lex.getCode() != tgtok::Id && Lex.getCode() != tgtok::XCast) { TokError("expected identifier in dag init"); return 0; } - Init *Operator = 0; - if (Lex.getCode() == tgtok::Id) { - Operator = ParseIDValue(CurRec); - if (Operator == 0) return 0; - } else { - Operator = ParseOperation(CurRec); - if (Operator == 0) return 0; - } + Init *Operator = ParseValue(CurRec); + if (Operator == 0) return 0; // If the operator name is present, parse it. std::string OperatorName; @@ -1252,25 +1272,22 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { Lex.Lex(); // eat the ')' return new DagInit(Operator, OperatorName, DagArgs); - break; } - case tgtok::XCar: - case tgtok::XCdr: - case tgtok::XNull: + case tgtok::XHead: + case tgtok::XTail: + case tgtok::XEmpty: case tgtok::XCast: // Value ::= !unop '(' Value ')' case tgtok::XConcat: case tgtok::XSRA: case tgtok::XSRL: case tgtok::XSHL: case tgtok::XEq: - case tgtok::XStrConcat: - case tgtok::XNameConcat: // Value ::= !binop '(' Value ',' Value ')' + case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')' case tgtok::XIf: case tgtok::XForEach: case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')' return ParseOperation(CurRec); - break; } } @@ -1635,19 +1652,18 @@ 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. // Parse ObjectName and make a record for it. - Record *CurRec = new Record(ParseObjectName(), DefLoc); + Record *CurRec = new Record(ParseObjectName(), DefLoc, Records); if (!CurMultiClass) { // Top-level def definition. @@ -1655,7 +1671,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 +1680,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 &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; } @@ -1701,7 +1730,7 @@ bool TGParser::ParseClass() { return TokError("Class '" + CurRec->getName() + "' already defined"); } else { // If this is the first reference to this class, create and add it. - CurRec = new Record(Lex.getCurStrVal(), Lex.getLoc()); + CurRec = new Record(Lex.getCurStrVal(), Lex.getLoc(), Records); Records.addClass(CurRec); } Lex.Lex(); // eat the name. @@ -1758,12 +1787,12 @@ std::vector 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 +1808,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 +1816,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 +1831,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 &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? @@ -1841,7 +1847,8 @@ bool TGParser::ParseMultiClass() { if (MultiClasses.count(Name)) return TokError("multiclass '" + Name + "' already defined"); - CurMultiClass = MultiClasses[Name] = new MultiClass(Name, Lex.getLoc()); + CurMultiClass = MultiClasses[Name] = new MultiClass(Name, + Lex.getLoc(), Records); Lex.Lex(); // Eat the identifier. // If there are template args, parse them. @@ -1885,10 +1892,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,16 +1915,25 @@ 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"); + + std::string DefmPrefix; + if (Lex.Lex() == tgtok::Id) { // eat the defm. + DefmPrefix = Lex.getCurStrVal(); + Lex.Lex(); // Eat the defm prefix. + } SMLoc DefmPrefixLoc = Lex.getLoc(); - std::string DefmPrefix = Lex.getCurStrVal(); - if (Lex.Lex() != tgtok::colon) + if (Lex.getCode() != tgtok::colon) return TokError("expected ':' after defm identifier"); + // Keep track of the new generated record definitions. + std::vector NewRecDefs; + + // This record also inherits from a regular class (non-multiclass)? + bool InheritFromClass = false; + // eat the colon. Lex.Lex(); @@ -1936,17 +1960,24 @@ bool TGParser::ParseDefm() { for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) { Record *DefProto = MC->DefPrototypes[i]; - // Add in the defm name + // Add in the defm name. If the defm prefix is empty, give each + // instantiated def a unique name. Otherwise, if "#NAME#" exists in the + // name, substitute the prefix for #NAME#. Otherwise, use the defm name + // as a prefix. std::string DefName = DefProto->getName(); - std::string::size_type idx = DefName.find("#NAME#"); - if (idx != std::string::npos) { - DefName.replace(idx, 6, DefmPrefix); + if (DefmPrefix.empty()) { + DefName = GetNewAnonymousName(); } else { - // Add the suffix to the defm name to get the new name. - DefName = DefmPrefix + DefName; + std::string::size_type idx = DefName.find("#NAME#"); + if (idx != std::string::npos) { + DefName.replace(idx, 6, DefmPrefix); + } else { + // Add the suffix to the defm name to get the new name. + DefName = DefmPrefix + DefName; + } } - Record *CurRec = new Record(DefName, DefmPrefixLoc); + Record *CurRec = new Record(DefName, DefmPrefixLoc, Records); SubClassReference Ref; Ref.RefLoc = DefmPrefixLoc; @@ -1991,17 +2022,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 &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 +2117,13 @@ 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(); + default: + return TokError("Expected class, def, defm, multiclass or let definition"); + 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 +2131,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;