X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FTGParser.cpp;h=ba480e6e926b5d2192e48998c40d94b1d052fb05;hb=a4b048668418f74dfb2399421dc54db1d999c9cd;hp=d6515e8b384ce10cb6df2430da00e8ee31c4fa71;hpb=f460165a4c1bf4bc762f9b3f12b9ed284b89cc99;p=oota-llvm.git diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp index d6515e8b384..ba480e6e926 100644 --- a/utils/TableGen/TGParser.cpp +++ b/utils/TableGen/TGParser.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by Chris Lattner and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -14,6 +14,8 @@ #include "TGParser.h" #include "Record.h" #include "llvm/ADT/StringExtras.h" +#include +#include using namespace llvm; //===----------------------------------------------------------------------===// @@ -21,25 +23,42 @@ using namespace llvm; //===----------------------------------------------------------------------===// namespace llvm { -struct MultiClass { - Record Rec; // Placeholder for template args and Name. - std::vector DefPrototypes; - - MultiClass(const std::string &Name) : Rec(Name) {} -}; - struct SubClassReference { - TGParser::LocTy RefLoc; + SMLoc RefLoc; Record *Rec; std::vector TemplateArgs; - SubClassReference() : RefLoc(0), Rec(0) {} - + SubClassReference() : Rec(0) {} + bool isInvalid() const { return Rec == 0; } }; - + +struct SubMultiClassReference { + SMLoc RefLoc; + MultiClass *MC; + std::vector TemplateArgs; + SubMultiClassReference() : MC(0) {} + + bool isInvalid() const { return MC == 0; } + void dump() const; +}; + +void SubMultiClassReference::dump() const { + errs() << "Multiclass:\n"; + + MC->dump(); + + errs() << "Template args:\n"; + for (std::vector::const_iterator i = TemplateArgs.begin(), + iend = TemplateArgs.end(); + i != iend; + ++i) { + (*i)->dump(); + } +} + } // end namespace llvm -bool TGParser::AddValue(Record *CurRec, LocTy Loc, const RecordVal &RV) { +bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) { if (CurRec == 0) CurRec = &CurMultiClass->Rec; @@ -58,7 +77,7 @@ bool TGParser::AddValue(Record *CurRec, LocTy Loc, const RecordVal &RV) { /// SetValue - /// Return true on error, false on success. -bool TGParser::SetValue(Record *CurRec, LocTy Loc, const std::string &ValName, +bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName, const std::vector &BitList, Init *V) { if (!V) return false; @@ -116,13 +135,13 @@ bool TGParser::SetValue(Record *CurRec, LocTy Loc, const std::string &ValName, if (RV->setValue(V)) return Error(Loc, "Value '" + ValName + "' of type '" + RV->getType()->getAsString() + - "' is incompatible with initializer ''"); // FIXME: Add init! + "' is incompatible with initializer '" + V->getAsString() +"'"); return false; } /// AddSubClass - Add SubClass as a subclass to CurRec, resolving its template /// args as SubClass's template arguments. -bool TGParser::AddSubClass(Record *CurRec, class SubClassReference &SubClass) { +bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { Record *SC = SubClass.Rec; // Add all of the values in the subclass into the current class. const std::vector &Vals = SC->getValues(); @@ -175,6 +194,96 @@ bool TGParser::AddSubClass(Record *CurRec, class SubClassReference &SubClass) { return false; } +/// AddSubMultiClass - Add SubMultiClass as a subclass to +/// CurMC, resolving its template args as SubMultiClass's +/// template arguments. +bool TGParser::AddSubMultiClass(MultiClass *CurMC, + SubMultiClassReference &SubMultiClass) { + MultiClass *SMC = SubMultiClass.MC; + Record *CurRec = &CurMC->Rec; + + const std::vector &MCVals = CurRec->getValues(); + + // 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])) + return true; + + int newDefStart = CurMC->DefPrototypes.size(); + + // Add all of the defs in the subclass into the current multiclass. + for (MultiClass::RecordVector::const_iterator i = SMC->DefPrototypes.begin(), + iend = SMC->DefPrototypes.end(); + i != iend; + ++i) { + // Clone the def and add it to the current multiclass + Record *NewDef = new Record(**i); + + // 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])) + return true; + + CurMC->DefPrototypes.push_back(NewDef); + } + + const std::vector &SMCTArgs = SMC->Rec.getTemplateArgs(); + + // Ensure that an appropriate number of template arguments are + // specified. + if (SMCTArgs.size() < SubMultiClass.TemplateArgs.size()) + return Error(SubMultiClass.RefLoc, + "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 = SMCTArgs.size(); i != e; ++i) { + 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], + std::vector(), + SubMultiClass.TemplateArgs[i])) + return true; + + // Resolve it next. + CurRec->resolveReferencesTo(CurRec->getValue(SMCTArgs[i])); + + // Now remove it. + CurRec->removeValue(SMCTArgs[i]); + + // If a value is specified for this template arg, set it in the + // new defs now. + for (MultiClass::RecordVector::iterator j = + CurMC->DefPrototypes.begin() + newDefStart, + jend = CurMC->DefPrototypes.end(); + j != jend; + ++j) { + Record *Def = *j; + + if (SetValue(Def, SubMultiClass.RefLoc, SMCTArgs[i], + std::vector(), + SubMultiClass.TemplateArgs[i])) + return true; + + // Resolve it next. + Def->resolveReferencesTo(Def->getValue(SMCTArgs[i])); + + // Now remove it + Def->removeValue(SMCTArgs[i]); + } + } else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) { + return Error(SubMultiClass.RefLoc, + "Value not specified for template argument #" + + utostr(i) + " (" + SMCTArgs[i] + ") of subclass '" + + SMC->Rec.getName() + "'!"); + } + } + + return false; +} + //===----------------------------------------------------------------------===// // Parser Code //===----------------------------------------------------------------------===// @@ -221,6 +330,25 @@ Record *TGParser::ParseClassID() { return Result; } +/// ParseMultiClassID - Parse and resolve a reference to a multiclass name. +/// This returns null on error. +/// +/// MultiClassID ::= ID +/// +MultiClass *TGParser::ParseMultiClassID() { + if (Lex.getCode() != tgtok::Id) { + TokError("expected name for ClassID"); + 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"); @@ -267,7 +395,7 @@ ParseSubClassReference(Record *CurRec, bool isDefm) { return Result; } - Result.TemplateArgs = ParseValueList(CurRec); + Result.TemplateArgs = ParseValueList(CurRec, Result.Rec); if (Result.TemplateArgs.empty()) { Result.Rec = 0; // Error parsing value list. return Result; @@ -283,14 +411,59 @@ ParseSubClassReference(Record *CurRec, bool isDefm) { return Result; } +/// ParseSubMultiClassReference - Parse a reference to a subclass or to a +/// templated submulticlass. This returns a SubMultiClassRefTy with a null +/// Record* on error. +/// +/// SubMultiClassRef ::= MultiClassID +/// SubMultiClassRef ::= MultiClassID '<' ValueList '>' +/// +SubMultiClassReference TGParser:: +ParseSubMultiClassReference(MultiClass *CurMC) { + SubMultiClassReference Result; + Result.RefLoc = 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) + return Result; + Lex.Lex(); // Eat the '<' + + if (Lex.getCode() == tgtok::greater) { + TokError("subclass reference requires a non-empty list of template values"); + Result.MC = 0; + return Result; + } + + Result.TemplateArgs = ParseValueList(&CurMC->Rec, &Result.MC->Rec); + if (Result.TemplateArgs.empty()) { + Result.MC = 0; // Error parsing value list. + return Result; + } + + if (Lex.getCode() != tgtok::greater) { + TokError("expected '>' in template value list"); + Result.MC = 0; + return Result; + } + Lex.Lex(); + + return Result; +} + /// ParseRangePiece - Parse a bit/value range. /// RangePiece ::= INTVAL /// RangePiece ::= INTVAL '-' INTVAL /// RangePiece ::= INTVAL INTVAL bool TGParser::ParseRangePiece(std::vector &Ranges) { - assert(Lex.getCode() == tgtok::IntVal && "Invalid range"); - int Start = Lex.getCurIntVal(); - int End; + if (Lex.getCode() != tgtok::IntVal) { + TokError("expected integer or bitrange"); + return true; + } + int64_t Start = Lex.getCurIntVal(); + int64_t End; if (Start < 0) return TokError("invalid range, cannot be negative"); @@ -352,7 +525,7 @@ bool TGParser::ParseOptionalRangeList(std::vector &Ranges) { if (Lex.getCode() != tgtok::less) return false; - LocTy StartLoc = Lex.getLoc(); + SMLoc StartLoc = Lex.getLoc(); Lex.Lex(); // eat the '<' // Parse the range list. @@ -374,7 +547,7 @@ bool TGParser::ParseOptionalBitList(std::vector &Ranges) { if (Lex.getCode() != tgtok::l_brace) return false; - LocTy StartLoc = Lex.getLoc(); + SMLoc StartLoc = Lex.getLoc(); Lex.Lex(); // eat the '{' // Parse the range list. @@ -421,7 +594,7 @@ RecTy *TGParser::ParseType() { TokError("expected integer in bits type"); return 0; } - unsigned Val = Lex.getCurIntVal(); + uint64_t Val = Lex.getCurIntVal(); if (Lex.Lex() != tgtok::greater) { // Eat count. TokError("expected '>' at end of bits type"); return 0; @@ -459,7 +632,7 @@ RecTy *TGParser::ParseType() { Init *TGParser::ParseIDValue(Record *CurRec) { assert(Lex.getCode() == tgtok::Id && "Expected ID in ParseIDValue"); std::string Name = Lex.getCurStrVal(); - LocTy Loc = Lex.getLoc(); + SMLoc Loc = Lex.getLoc(); Lex.Lex(); return ParseIDValue(CurRec, Name, Loc); } @@ -467,7 +640,7 @@ Init *TGParser::ParseIDValue(Record *CurRec) { /// ParseIDValue - This is just like ParseIDValue above, but it assumes the ID /// has already been read. Init *TGParser::ParseIDValue(Record *CurRec, - const std::string &Name, LocTy NameLoc) { + const std::string &Name, SMLoc NameLoc) { if (CurRec) { if (const RecordVal *RV = CurRec->getValue(Name)) return new VarInit(Name, RV->getType()); @@ -496,11 +669,342 @@ Init *TGParser::ParseIDValue(Record *CurRec, return 0; } +/// ParseOperation - Parse an operator. This returns null on error. +/// +/// Operation ::= XOperator ['<' Type '>'] '(' Args ')' +/// +Init *TGParser::ParseOperation(Record *CurRec) { + switch (Lex.getCode()) { + default: + TokError("unknown operation"); + return 0; + break; + case tgtok::XCar: + case tgtok::XCdr: + case tgtok::XNull: + case tgtok::XCast: { // Value ::= !unop '(' Value ')' + UnOpInit::UnaryOp Code; + RecTy *Type = 0; + + switch (Lex.getCode()) { + default: assert(0 && "Unhandled code!"); + case tgtok::XCast: + Lex.Lex(); // eat the operation + Code = UnOpInit::CAST; + + Type = ParseOperatorType(); + + if (Type == 0) { + TokError("did not get type for unary operator"); + return 0; + } + + break; + case tgtok::XCar: + Lex.Lex(); // eat the operation + Code = UnOpInit::CAR; + break; + case tgtok::XCdr: + Lex.Lex(); // eat the operation + Code = UnOpInit::CDR; + break; + case tgtok::XNull: + Lex.Lex(); // eat the operation + Code = UnOpInit::LNULL; + Type = new IntRecTy; + break; + } + if (Lex.getCode() != tgtok::l_paren) { + TokError("expected '(' after unary operator"); + return 0; + } + Lex.Lex(); // eat the '(' + + Init *LHS = ParseValue(CurRec); + if (LHS == 0) return 0; + + if (Code == UnOpInit::CAR + || Code == UnOpInit::CDR + || Code == UnOpInit::LNULL) { + ListInit *LHSl = dynamic_cast(LHS); + StringInit *LHSs = dynamic_cast(LHS); + TypedInit *LHSt = dynamic_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()); + if (LType == 0 && SType == 0) { + TokError("expected list or string type argumnet in unary operator"); + return 0; + } + } + + if (Code == UnOpInit::CAR + || Code == UnOpInit::CDR) { + if (LHSl == 0 && LHSt == 0) { + TokError("expected list type argumnet in unary operator"); + return 0; + } + + if (LHSl && LHSl->getSize() == 0) { + TokError("empty list argument in unary operator"); + return 0; + } + if (LHSl) { + Init *Item = LHSl->getElement(0); + TypedInit *Itemt = dynamic_cast(Item); + if (Itemt == 0) { + TokError("untyped list element in unary operator"); + return 0; + } + if (Code == UnOpInit::CAR) { + Type = Itemt->getType(); + } + else { + Type = new ListRecTy(Itemt->getType()); + } + } + else { + assert(LHSt && "expected list type argument in unary operator"); + ListRecTy *LType = dynamic_cast(LHSt->getType()); + if (LType == 0) { + TokError("expected list type argumnet in unary operator"); + return 0; + } + if (Code == UnOpInit::CAR) { + Type = LType->getElementType(); + } + else { + Type = LType; + } + } + } + } + + if (Lex.getCode() != tgtok::r_paren) { + TokError("expected ')' in unary operator"); + return 0; + } + Lex.Lex(); // eat the ')' + return (new UnOpInit(Code, LHS, Type))->Fold(CurRec, CurMultiClass); + } + + case tgtok::XConcat: + case tgtok::XSRA: + case tgtok::XSRL: + case tgtok::XSHL: + case tgtok::XStrConcat: + case tgtok::XNameConcat: { // Value ::= !binop '(' Value ',' Value ')' + BinOpInit::BinaryOp Code; + RecTy *Type = 0; + + + switch (Lex.getCode()) { + 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::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; + + if (Lex.getCode() != tgtok::comma) { + TokError("expected ',' in binary operator"); + return 0; + } + Lex.Lex(); // eat the ',' + + Init *RHS = ParseValue(CurRec); + if (RHS == 0) return 0; + + if (Lex.getCode() != tgtok::r_paren) { + TokError("expected ')' in binary operator"); + return 0; + } + Lex.Lex(); // eat the ')' + return (new BinOpInit(Code, LHS, RHS, Type))->Fold(CurRec, CurMultiClass); + } + + case tgtok::XIf: + case tgtok::XForEach: + case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')' + TernOpInit::TernaryOp Code; + RecTy *Type = 0; + + + tgtok::TokKind LexCode = Lex.getCode(); + Lex.Lex(); // eat the operation + switch (LexCode) { + default: assert(0 && "Unhandled code!"); + case tgtok::XIf: + Code = TernOpInit::IF; + break; + case tgtok::XForEach: + Code = TernOpInit::FOREACH; + break; + case tgtok::XSubst: + Code = TernOpInit::SUBST; + break; + } + if (Lex.getCode() != tgtok::l_paren) { + TokError("expected '(' after ternary operator"); + return 0; + } + Lex.Lex(); // eat the '(' + + Init *LHS = ParseValue(CurRec); + if (LHS == 0) return 0; + + if (Lex.getCode() != tgtok::comma) { + TokError("expected ',' in ternary operator"); + return 0; + } + Lex.Lex(); // eat the ',' + + Init *MHS = ParseValue(CurRec); + if (MHS == 0) return 0; + + if (Lex.getCode() != tgtok::comma) { + TokError("expected ',' in ternary operator"); + return 0; + } + Lex.Lex(); // eat the ',' + + Init *RHS = ParseValue(CurRec); + if (RHS == 0) return 0; + + if (Lex.getCode() != tgtok::r_paren) { + TokError("expected ')' in binary operator"); + return 0; + } + Lex.Lex(); // eat the ')' + + 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) { + 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(); + } + else { + TokError("inconsistent types for !if"); + return 0; + } + break; + } + case tgtok::XForEach: { + TypedInit *MHSt = dynamic_cast(MHS); + if (MHSt == 0) { + TokError("could not get type for !foreach"); + return 0; + } + Type = MHSt->getType(); + break; + } + case tgtok::XSubst: { + TypedInit *RHSt = dynamic_cast(RHS); + if (RHSt == 0) { + TokError("could not get type for !subst"); + return 0; + } + Type = RHSt->getType(); + break; + } + } + return (new TernOpInit(Code, LHS, MHS, RHS, Type))->Fold(CurRec, CurMultiClass); + } + } + TokError("could not parse operation"); + return 0; +} + +/// ParseOperatorType - Parse a type for an operator. This returns +/// null on error. +/// +/// OperatorType ::= '<' Type '>' +/// +RecTy *TGParser::ParseOperatorType(void) { + RecTy *Type = 0; + + if (Lex.getCode() != tgtok::less) { + TokError("expected type name for operator"); + return 0; + } + Lex.Lex(); // eat the < + + Type = ParseType(); + + if (Type == 0) { + TokError("expected type name for operator"); + return 0; + } + + if (Lex.getCode() != tgtok::greater) { + TokError("expected type name for operator"); + return 0; + } + Lex.Lex(); // eat the > + + return Type; +} + + /// ParseSimpleValue - Parse a tblgen value. This returns null on error. /// /// SimpleValue ::= IDValue /// SimpleValue ::= INTVAL -/// SimpleValue ::= STRVAL +/// SimpleValue ::= STRVAL+ /// SimpleValue ::= CODEFRAGMENT /// SimpleValue ::= '?' /// SimpleValue ::= '{' ValueList '}' @@ -513,17 +1017,29 @@ Init *TGParser::ParseIDValue(Record *CurRec, /// SimpleValue ::= SRLTOK '(' Value ',' Value ')' /// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')' /// -Init *TGParser::ParseSimpleValue(Record *CurRec) { +Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { Init *R = 0; switch (Lex.getCode()) { default: TokError("Unknown token when parsing a value"); break; case tgtok::IntVal: R = new IntInit(Lex.getCurIntVal()); Lex.Lex(); break; - case tgtok::StrVal: R = new StringInit(Lex.getCurStrVal()); Lex.Lex(); break; + case tgtok::StrVal: { + std::string Val = Lex.getCurStrVal(); + Lex.Lex(); + + // Handle multiple consecutive concatenated strings. + while (Lex.getCode() == tgtok::StrVal) { + Val += Lex.getCurStrVal(); + Lex.Lex(); + } + + R = new StringInit(Val); + break; + } case tgtok::CodeFragment: R = new CodeInit(Lex.getCurStrVal()); Lex.Lex(); break; case tgtok::question: R = new UnsetInit(); Lex.Lex(); break; case tgtok::Id: { - LocTy NameLoc = Lex.getLoc(); + SMLoc NameLoc = Lex.getLoc(); std::string Name = Lex.getCurStrVal(); if (Lex.Lex() != tgtok::less) // consume the Id. return ParseIDValue(CurRec, Name, NameLoc); // Value ::= IDValue @@ -533,15 +1049,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { TokError("expected non-empty value list"); return 0; } - std::vector ValueList = ParseValueList(CurRec); - if (ValueList.empty()) return 0; - - if (Lex.getCode() != tgtok::greater) { - TokError("expected '>' at end of value list"); - return 0; - } - Lex.Lex(); // eat the '>' - + // This is a CLASS expression. This is supposed to synthesize // a new anonymous definition, deriving from CLASS with no // body. @@ -550,10 +1058,19 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { Error(NameLoc, "Expected a class name, got '" + Name + "'"); return 0; } + + std::vector ValueList = ParseValueList(CurRec, Class); + if (ValueList.empty()) return 0; + + if (Lex.getCode() != tgtok::greater) { + TokError("expected '>' at end of value list"); + return 0; + } + Lex.Lex(); // eat the '>' // Create the new record, set it as CurRec temporarily. static unsigned AnonCounter = 0; - Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++)); + Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++),NameLoc); SubClassReference SCRef; SCRef.RefLoc = NameLoc; SCRef.Rec = Class; @@ -568,7 +1085,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { return new DefInit(NewRec); } case tgtok::l_brace: { // Value ::= '{' ValueList '}' - LocTy BraceLoc = Lex.getLoc(); + SMLoc BraceLoc = Lex.getLoc(); Lex.Lex(); // eat the '{' std::vector Vals; @@ -586,9 +1103,8 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { for (unsigned i = 0, e = Vals.size(); i != e; ++i) { Init *Bit = Vals[i]->convertInitializerTo(new BitRecTy()); if (Bit == 0) { - // FIXME: Include value in error. - Error(BraceLoc, "Element #" + utostr(i) + " ("/* << *Vals[i] - <<*/ ") is not convertable to a bit"); + Error(BraceLoc, "Element #" + utostr(i) + " (" + Vals[i]->getAsString()+ + ") is not convertable to a bit"); return 0; } Result->setBit(Vals.size()-i-1, Bit); @@ -599,8 +1115,22 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { Lex.Lex(); // eat the '[' std::vector Vals; + RecTy *DeducedEltTy = 0; + ListRecTy *GivenListTy = 0; + + if (ItemType != 0) { + ListRecTy *ListType = dynamic_cast(ItemType); + if (ListType == 0) { + std::stringstream s; + s << "Type mismatch for list, expected list type, got " + << ItemType->getAsString(); + TokError(s.str()); + } + GivenListTy = ListType; + } + if (Lex.getCode() != tgtok::r_square) { - Vals = ParseValueList(CurRec); + Vals = ParseValueList(CurRec, 0, GivenListTy ? GivenListTy->getElementType() : 0); if (Vals.empty()) return 0; } if (Lex.getCode() != tgtok::r_square) { @@ -608,12 +1138,107 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { return 0; } Lex.Lex(); // eat the ']' - return new ListInit(Vals); + + RecTy *GivenEltTy = 0; + if (Lex.getCode() == tgtok::less) { + // Optional list element type + Lex.Lex(); // eat the '<' + + GivenEltTy = ParseType(); + if (GivenEltTy == 0) { + // Couldn't parse element type + return 0; + } + + if (Lex.getCode() != tgtok::greater) { + TokError("expected '>' at end of list element type"); + return 0; + } + Lex.Lex(); // eat the '>' + } + + // Check elements + RecTy *EltTy = 0; + for (std::vector::iterator i = Vals.begin(), ie = Vals.end(); + i != ie; + ++i) { + TypedInit *TArg = dynamic_cast(*i); + if (TArg == 0) { + TokError("Untyped list element"); + return 0; + } + if (EltTy != 0) { + EltTy = resolveTypes(EltTy, TArg->getType()); + if (EltTy == 0) { + TokError("Incompatible types in list elements"); + return 0; + } + } + else { + EltTy = TArg->getType(); + } + } + + if (GivenEltTy != 0) { + if (EltTy != 0) { + // Verify consistency + if (!EltTy->typeIsConvertibleTo(GivenEltTy)) { + TokError("Incompatible types in list elements"); + return 0; + } + } + EltTy = GivenEltTy; + } + + if (EltTy == 0) { + if (ItemType == 0) { + TokError("No type for list"); + return 0; + } + DeducedEltTy = GivenListTy->getElementType(); + } + else { + // Make sure the deduced type is compatible with the given type + if (GivenListTy) { + if (!EltTy->typeIsConvertibleTo(GivenListTy->getElementType())) { + TokError("Element type mismatch for list"); + return 0; + } + } + DeducedEltTy = EltTy; + } + + return new ListInit(Vals, DeducedEltTy); } case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')' Lex.Lex(); // eat the '(' - Init *Operator = ParseIDValue(CurRec); - if (Operator == 0) return 0; + if (Lex.getCode() != tgtok::Id + && Lex.getCode() != tgtok::XCast + && Lex.getCode() != tgtok::XNameConcat) { + 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; + } + + // If the operator name is present, parse it. + std::string OperatorName; + if (Lex.getCode() == tgtok::colon) { + if (Lex.Lex() != tgtok::VarName) { // eat the ':' + TokError("expected variable name in dag operator"); + return 0; + } + OperatorName = Lex.getCurStrVal(); + Lex.Lex(); // eat the VarName. + } std::vector > DagArgs; if (Lex.getCode() != tgtok::r_paren) { @@ -627,47 +1252,25 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { } Lex.Lex(); // eat the ')' - return new DagInit(Operator, DagArgs); + return new DagInit(Operator, OperatorName, DagArgs); + break; } + + case tgtok::XCar: + case tgtok::XCdr: + case tgtok::XNull: + case tgtok::XCast: // Value ::= !unop '(' Value ')' case tgtok::XConcat: case tgtok::XSRA: case tgtok::XSRL: case tgtok::XSHL: - case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')' - BinOpInit::BinaryOp Code; - switch (Lex.getCode()) { - default: assert(0 && "Unhandled code!"); - case tgtok::XConcat: Code = BinOpInit::CONCAT; break; - case tgtok::XSRA: Code = BinOpInit::SRA; break; - case tgtok::XSRL: Code = BinOpInit::SRL; break; - case tgtok::XSHL: Code = BinOpInit::SHL; break; - case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break; - } - Lex.Lex(); // eat the operation - 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; - - if (Lex.getCode() != tgtok::comma) { - TokError("expected ',' in binary operator"); - return 0; - } - Lex.Lex(); // eat the ',' - - Init *RHS = ParseValue(CurRec); - if (RHS == 0) return 0; - - if (Lex.getCode() != tgtok::r_paren) { - TokError("expected ')' in binary operator"); - return 0; - } - Lex.Lex(); // eat the ')' - return (new BinOpInit(Code, LHS, RHS))->Fold(); + case tgtok::XStrConcat: + case tgtok::XNameConcat: // Value ::= !binop '(' Value ',' Value ')' + case tgtok::XIf: + case tgtok::XForEach: + case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')' + return ParseOperation(CurRec); + break; } } @@ -681,8 +1284,8 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { /// ValueSuffix ::= '[' BitList ']' /// ValueSuffix ::= '.' ID /// -Init *TGParser::ParseValue(Record *CurRec) { - Init *Result = ParseSimpleValue(CurRec); +Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType) { + Init *Result = ParseSimpleValue(CurRec, ItemType); if (Result == 0) return 0; // Parse the suffixes now if present. @@ -690,7 +1293,7 @@ Init *TGParser::ParseValue(Record *CurRec) { switch (Lex.getCode()) { default: return Result; case tgtok::l_brace: { - LocTy CurlyLoc = Lex.getLoc(); + SMLoc CurlyLoc = Lex.getLoc(); Lex.Lex(); // eat the '{' std::vector Ranges = ParseRangeList(); if (Ranges.empty()) return 0; @@ -712,7 +1315,7 @@ Init *TGParser::ParseValue(Record *CurRec) { break; } case tgtok::l_square: { - LocTy SquareLoc = Lex.getLoc(); + SMLoc SquareLoc = Lex.getLoc(); Lex.Lex(); // eat the '[' std::vector Ranges = ParseRangeList(); if (Ranges.empty()) return 0; @@ -737,9 +1340,8 @@ Init *TGParser::ParseValue(Record *CurRec) { return 0; } if (!Result->getFieldType(Lex.getCurStrVal())) { - // FIXME INCLUDE VALUE IN ERROR. TokError("Cannot access field '" + Lex.getCurStrVal() + "' of value '" + - /*<< *$1 <<*/ "'"); + Result->getAsString() + "'"); return 0; } Result = new FieldInit(Result, Lex.getCurStrVal()); @@ -788,15 +1390,35 @@ TGParser::ParseDagArgList(Record *CurRec) { /// /// ValueList ::= Value (',' Value) /// -std::vector TGParser::ParseValueList(Record *CurRec) { +std::vector TGParser::ParseValueList(Record *CurRec, Record *ArgsRec, RecTy *EltTy) { std::vector Result; - Result.push_back(ParseValue(CurRec)); + RecTy *ItemType = EltTy; + unsigned int ArgN = 0; + if (ArgsRec != 0 && EltTy == 0) { + const std::vector &TArgs = ArgsRec->getTemplateArgs(); + const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]); + assert(RV && "Template argument record not found??"); + ItemType = RV->getType(); + ++ArgN; + } + Result.push_back(ParseValue(CurRec, ItemType)); if (Result.back() == 0) return std::vector(); while (Lex.getCode() == tgtok::comma) { Lex.Lex(); // Eat the comma - Result.push_back(ParseValue(CurRec)); + if (ArgsRec != 0 && EltTy == 0) { + const std::vector &TArgs = ArgsRec->getTemplateArgs(); + if (ArgN >= TArgs.size()) { + TokError("too many template arguments"); + return std::vector(); + } + const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]); + assert(RV && "Template argument record not found??"); + ItemType = RV->getType(); + ++ArgN; + } + Result.push_back(ParseValue(CurRec, ItemType)); if (Result.back() == 0) return std::vector(); } @@ -829,7 +1451,7 @@ std::string TGParser::ParseDeclaration(Record *CurRec, return ""; } - LocTy IdLoc = Lex.getLoc(); + SMLoc IdLoc = Lex.getLoc(); std::string DeclName = Lex.getCurStrVal(); Lex.Lex(); @@ -850,8 +1472,8 @@ std::string TGParser::ParseDeclaration(Record *CurRec, // If a value is present, parse it. if (Lex.getCode() == tgtok::equal) { Lex.Lex(); - LocTy ValLoc = Lex.getLoc(); - Init *Val = ParseValue(CurRec); + SMLoc ValLoc = Lex.getLoc(); + Init *Val = ParseValue(CurRec, Type); if (Val == 0 || SetValue(CurRec, ValLoc, DeclName, std::vector(), Val)) return ""; @@ -916,7 +1538,7 @@ bool TGParser::ParseBodyItem(Record *CurRec) { if (Lex.Lex() != tgtok::Id) return TokError("expected field identifier after let"); - LocTy IdLoc = Lex.getLoc(); + SMLoc IdLoc = Lex.getLoc(); std::string FieldName = Lex.getCurStrVal(); Lex.Lex(); // eat the field name. @@ -929,7 +1551,13 @@ bool TGParser::ParseBodyItem(Record *CurRec) { return TokError("expected '=' in let expression"); Lex.Lex(); // eat the '='. - Init *Val = ParseValue(CurRec); + RecordVal *Field = CurRec->getValue(FieldName); + if (Field == 0) + return TokError("Value '" + FieldName + "' unknown!"); + + RecTy *Type = Field->getType(); + + Init *Val = ParseValue(CurRec, Type); if (Val == 0) return true; if (Lex.getCode() != tgtok::semi) @@ -1014,12 +1642,12 @@ bool TGParser::ParseObjectBody(Record *CurRec) { /// DefInst ::= DEF ObjectName ObjectBody /// llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) { - LocTy DefLoc = Lex.getLoc(); + 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()); + Record *CurRec = new Record(ParseObjectName(), DefLoc); if (!CurMultiClass) { // Top-level def definition. @@ -1073,7 +1701,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()); + CurRec = new Record(Lex.getCurStrVal(), Lex.getLoc()); Records.addClass(CurRec); } Lex.Lex(); // eat the name. @@ -1102,7 +1730,7 @@ std::vector TGParser::ParseLetList() { return std::vector(); } std::string Name = Lex.getCurStrVal(); - LocTy NameLoc = Lex.getLoc(); + SMLoc NameLoc = Lex.getLoc(); Lex.Lex(); // Eat the identifier. // Check for an optional RangeList. @@ -1154,7 +1782,7 @@ bool TGParser::ParseTopLevelLet() { if (ParseObject()) return true; } else { // Object ::= LETCommand '{' ObjectList '}' - LocTy BraceLoc = Lex.getLoc(); + SMLoc BraceLoc = Lex.getLoc(); // Otherwise, this is a group let. Lex.Lex(); // eat the '{'. @@ -1199,7 +1827,8 @@ bool TGParser::ParseMultiClassDef(MultiClass *CurMC) { /// ParseMultiClass - Parse a multiclass definition. /// -/// MultiClassInst ::= MULTICLASS ID TemplateArgList? '{' MultiClassDef+ '}' +/// MultiClassInst ::= MULTICLASS ID TemplateArgList? +/// ':' BaseMultiClassList '{' MultiClassDef+ '}' /// bool TGParser::ParseMultiClass() { assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token"); @@ -1212,7 +1841,7 @@ bool TGParser::ParseMultiClass() { if (MultiClasses.count(Name)) return TokError("multiclass '" + Name + "' already defined"); - CurMultiClass = MultiClasses[Name] = new MultiClass(Name); + CurMultiClass = MultiClasses[Name] = new MultiClass(Name, Lex.getLoc()); Lex.Lex(); // Eat the identifier. // If there are template args, parse them. @@ -1220,17 +1849,50 @@ bool TGParser::ParseMultiClass() { if (ParseTemplateArgList(0)) return true; - if (Lex.getCode() != tgtok::l_brace) - return TokError("expected '{' in multiclass definition"); + bool inherits = false; + + // If there are submulticlasses, parse them. + if (Lex.getCode() == tgtok::colon) { + inherits = true; - if (Lex.Lex() == tgtok::r_brace) // eat the '{'. - return TokError("multiclass must contain at least one def"); + Lex.Lex(); + + // Read all of the submulticlasses. + SubMultiClassReference SubMultiClass = + ParseSubMultiClassReference(CurMultiClass); + while (1) { + // Check for error. + if (SubMultiClass.MC == 0) return true; + + // Add it. + if (AddSubMultiClass(CurMultiClass, SubMultiClass)) + return true; + + if (Lex.getCode() != tgtok::comma) break; + Lex.Lex(); // eat ','. + SubMultiClass = ParseSubMultiClassReference(CurMultiClass); + } + } + + if (Lex.getCode() != tgtok::l_brace) { + if (!inherits) + return TokError("expected '{' in multiclass definition"); + else + if (Lex.getCode() != tgtok::semi) + return TokError("expected ';' in multiclass definition"); + else + Lex.Lex(); // eat the ';'. + } + else { + 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) + if (ParseMultiClassDef(CurMultiClass)) + return true; - Lex.Lex(); // eat the '}'. + Lex.Lex(); // eat the '}'. + } CurMultiClass = 0; return false; @@ -1245,7 +1907,7 @@ bool TGParser::ParseDefm() { if (Lex.Lex() != tgtok::Id) // eat the defm. return TokError("expected identifier after defm"); - LocTy DefmPrefixLoc = Lex.getLoc(); + SMLoc DefmPrefixLoc = Lex.getLoc(); std::string DefmPrefix = Lex.getCurStrVal(); if (Lex.Lex() != tgtok::colon) return TokError("expected ':' after defm identifier"); @@ -1253,79 +1915,99 @@ bool TGParser::ParseDefm() { // eat the colon. Lex.Lex(); - LocTy SubClassLoc = Lex.getLoc(); + SMLoc SubClassLoc = Lex.getLoc(); SubClassReference Ref = ParseSubClassReference(0, true); - if (Ref.Rec == 0) return true; - - if (Lex.getCode() != tgtok::semi) - return TokError("expected ';' at end of defm"); - Lex.Lex(); - - // To instantiate a multiclass, we need to first get the multiclass, then - // instantiate each def contained in the multiclass with the SubClassRef - // template parameters. - MultiClass *MC = MultiClasses[Ref.Rec->getName()]; - assert(MC && "Didn't lookup multiclass correctly?"); - std::vector &TemplateVals = Ref.TemplateArgs; - - // Verify that the correct number of template arguments were specified. - const std::vector &TArgs = MC->Rec.getTemplateArgs(); - if (TArgs.size() < TemplateVals.size()) - return Error(SubClassLoc, - "more template args specified than multiclass expects"); - - // Loop over all the def's in the multiclass, instantiating each one. - for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) { - Record *DefProto = MC->DefPrototypes[i]; - - // Add the suffix to the defm name to get the new name. - Record *CurRec = new Record(DefmPrefix + DefProto->getName()); - - SubClassReference Ref; - Ref.RefLoc = DefmPrefixLoc; - Ref.Rec = DefProto; - AddSubClass(CurRec, Ref); - - // 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 < TemplateVals.size()) { // A value is specified for this temp-arg? - // Set it now. - if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector(), - TemplateVals[i])) - return true; - - // Resolve it next. - CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i])); - - // Now remove it. - CurRec->removeValue(TArgs[i]); - - } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { - return Error(SubClassLoc, "value not specified for template argument #"+ - utostr(i) + " (" + TArgs[i] + ") of multiclassclass '" + - MC->Rec.getName() + "'"); + + while (1) { + if (Ref.Rec == 0) return true; + + // To instantiate a multiclass, we need to first get the multiclass, then + // instantiate each def contained in the multiclass with the SubClassRef + // template parameters. + MultiClass *MC = MultiClasses[Ref.Rec->getName()]; + assert(MC && "Didn't lookup multiclass correctly?"); + std::vector &TemplateVals = Ref.TemplateArgs; + + // Verify that the correct number of template arguments were specified. + const std::vector &TArgs = MC->Rec.getTemplateArgs(); + if (TArgs.size() < TemplateVals.size()) + return Error(SubClassLoc, + "more template args specified than multiclass expects"); + + // Loop over all the def's in the multiclass, instantiating each one. + for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) { + Record *DefProto = MC->DefPrototypes[i]; + + // Add in the defm name + std::string DefName = DefProto->getName(); + std::string::size_type idx = DefName.find("#NAME#"); + if (idx != std::string::npos) { + DefName.replace(idx, 6, DefmPrefix); } - } - - // 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)) { - Error(DefmPrefixLoc, "when instantiating this defm"); - return true; + else { + // Add the suffix to the defm name to get the new name. + DefName = DefmPrefix + DefName; + } + + Record *CurRec = new Record(DefName, DefmPrefixLoc); + + SubClassReference Ref; + Ref.RefLoc = DefmPrefixLoc; + Ref.Rec = DefProto; + AddSubClass(CurRec, Ref); + + // 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) { + // Check if a value is specified for this temp-arg. + if (i < TemplateVals.size()) { + // Set it now. + if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector(), + TemplateVals[i])) + return true; + + // Resolve it next. + CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i])); + + // Now remove it. + CurRec->removeValue(TArgs[i]); + + } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { + return Error(SubClassLoc, + "value not specified for template argument #"+ + utostr(i) + " (" + TArgs[i] + ") of multiclassclass '" + + MC->Rec.getName() + "'"); } - - - // Ensure redefinition doesn't happen. - if (Records.getDef(CurRec->getName())) - return Error(DefmPrefixLoc, "def '" + CurRec->getName() + - "' already defined, instantiating defm with subdef '" + - DefProto->getName() + "'"); - Records.addDef(CurRec); - CurRec->resolveReferences(); + } + + // 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)) { + Error(DefmPrefixLoc, "when instantiating this defm"); + return true; + } + + // Ensure redefinition doesn't happen. + if (Records.getDef(CurRec->getName())) + return Error(DefmPrefixLoc, "def '" + CurRec->getName() + + "' already defined, instantiating defm with subdef '" + + DefProto->getName() + "'"); + Records.addDef(CurRec); + CurRec->resolveReferences(); + } + + if (Lex.getCode() != tgtok::comma) break; + Lex.Lex(); // eat ','. + + SubClassLoc = Lex.getLoc(); + Ref = ParseSubClassReference(0, true); } + + if (Lex.getCode() != tgtok::semi) + return TokError("expected ';' at end of defm"); + Lex.Lex(); return false; }