X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FTGParser.cpp;h=0cfc2c5c2858b33eead1ba5d3f2f27a6259b4099;hb=dcd35c797d458d8b1dbc36cf7f1504166d5b2f16;hp=b4d448b1e8c087af0a97e1eea85b6e87750e98fe;hpb=938c8ab0a0f4a52d7d6ddc975abe9de08fee06d5;p=oota-llvm.git diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp index b4d448b1e8c..0cfc2c5c285 100644 --- a/utils/TableGen/TGParser.cpp +++ b/utils/TableGen/TGParser.cpp @@ -11,12 +11,13 @@ // //===----------------------------------------------------------------------===// -#include - #include "TGParser.h" #include "Record.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/Streams.h" +#include +#include +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -25,18 +26,18 @@ using namespace llvm; namespace llvm { struct SubClassReference { - TGLoc RefLoc; + SMLoc RefLoc; Record *Rec; - std::vector TemplateArgs; + std::vector TemplateArgs; SubClassReference() : Rec(0) {} bool isInvalid() const { return Rec == 0; } }; struct SubMultiClassReference { - TGLoc RefLoc; + SMLoc RefLoc; MultiClass *MC; - std::vector TemplateArgs; + std::vector TemplateArgs; SubMultiClassReference() : MC(0) {} bool isInvalid() const { return MC == 0; } @@ -44,12 +45,12 @@ struct SubMultiClassReference { }; void SubMultiClassReference::dump() const { - cerr << "Multiclass:\n"; - + errs() << "Multiclass:\n"; + MC->dump(); - - cerr << "Template args:\n"; - for (std::vector::const_iterator i = TemplateArgs.begin(), + + errs() << "Template args:\n"; + for (std::vector::const_iterator i = TemplateArgs.begin(), iend = TemplateArgs.end(); i != iend; ++i) { @@ -59,16 +60,16 @@ void SubMultiClassReference::dump() const { } // end namespace llvm -bool TGParser::AddValue(Record *CurRec, TGLoc Loc, const RecordVal &RV) { +bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) { if (CurRec == 0) CurRec = &CurMultiClass->Rec; - + if (RecordVal *ERV = CurRec->getValue(RV.getName())) { // The value already exists in the class, treat this as a set. if (ERV->setValue(RV.getValue())) return Error(Loc, "New definition of '" + RV.getName() + "' of type '" + RV.getType()->getAsString() + "' is incompatible with " + - "previous definition of type '" + + "previous definition of type '" + ERV->getType()->getAsString() + "'"); } else { CurRec->addValue(RV); @@ -78,8 +79,8 @@ bool TGParser::AddValue(Record *CurRec, TGLoc Loc, const RecordVal &RV) { /// SetValue - /// Return true on error, false on success. -bool TGParser::SetValue(Record *CurRec, TGLoc Loc, const std::string &ValName, - const std::vector &BitList, Init *V) { +bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName, + const std::vector &BitList, const Init *V) { if (!V) return false; if (CurRec == 0) CurRec = &CurMultiClass->Rec; @@ -91,51 +92,51 @@ bool TGParser::SetValue(Record *CurRec, TGLoc Loc, const std::string &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 (const VarInit *VI = dynamic_cast(V)) if (VI->getName() == ValName) return false; - + // If we are assigning to a subset of the bits in the value... then we must be // assigning to a field of BitsRecTy, which must have a BitsInit // initializer. // if (!BitList.empty()) { - BitsInit *CurVal = dynamic_cast(RV->getValue()); + const BitsInit *CurVal = dynamic_cast(RV->getValue()); if (CurVal == 0) return Error(Loc, "Value '" + ValName + "' is not a bits type"); // Convert the incoming value to a bits type of the appropriate size... - Init *BI = V->convertInitializerTo(new BitsRecTy(BitList.size())); + const Init *BI = V->convertInitializerTo(BitsRecTy::get(BitList.size())); if (BI == 0) { - V->convertInitializerTo(new BitsRecTy(BitList.size())); + 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); + const BitsInit *BInit = dynamic_cast(BI); assert(BInit != 0); - BitsInit *NewVal = new BitsInit(CurVal->getNumBits()); + SmallVector NewBits(CurVal->getNumBits()); // Loop over bits, assigning values as appropriate. for (unsigned i = 0, e = BitList.size(); i != e; ++i) { unsigned Bit = BitList[i]; - if (NewVal->getBit(Bit)) + if (NewBits[Bit]) return Error(Loc, "Cannot set bit #" + utostr(Bit) + " of value '" + ValName + "' more than once"); - NewVal->setBit(Bit, BInit->getBit(i)); + NewBits[Bit] = BInit->getBit(i); } for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i) - if (NewVal->getBit(i) == 0) - NewVal->setBit(i, CurVal->getBit(i)); + if (NewBits[i] == 0) + NewBits[i] = CurVal->getBit(i); - V = NewVal; + V = BitsInit::get(NewBits); } if (RV->setValue(V)) - return Error(Loc, "Value '" + ValName + "' of type '" + - RV->getType()->getAsString() + + return Error(Loc, "Value '" + ValName + "' of type '" + + RV->getType()->getAsString() + "' is incompatible with initializer '" + V->getAsString() +"'"); return false; } @@ -155,25 +156,25 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { // 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"); - + // 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(), + if (SetValue(CurRec, SubClass.RefLoc, TArgs[i], std::vector(), SubClass.TemplateArgs[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(SubClass.RefLoc,"Value not specified for template argument #" - + utostr(i) + " (" + TArgs[i] + ") of subclass '" + + + utostr(i) + " (" + TArgs[i] + ") of subclass '" + SC->getName() + "'!"); } } @@ -187,7 +188,7 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { "Already subclass of '" + SCs[i]->getName() + "'!\n"); CurRec->addSuperClass(SCs[i]); } - + if (CurRec->isSubClassOf(SC)) return Error(SubClass.RefLoc, "Already subclass of '" + SC->getName() + "'!\n"); @@ -292,7 +293,12 @@ 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; +} + +static std::string GetNewAnonymousName() { + static unsigned AnonCounter = 0; + return "anonymous."+utostr(AnonCounter++); } /// ParseObjectName - If an object name is specified, return it. Otherwise, @@ -301,14 +307,12 @@ static bool isObjectStart(tgtok::TokKind K) { /// ObjectName ::= /*empty*/ /// std::string TGParser::ParseObjectName() { - if (Lex.getCode() == tgtok::Id) { - std::string Ret = Lex.getCurStrVal(); - Lex.Lex(); - return Ret; - } - - static unsigned AnonCounter = 0; - return "anonymous."+utostr(AnonCounter++); + if (Lex.getCode() != tgtok::Id) + return GetNewAnonymousName(); + + std::string Ret = Lex.getCurStrVal(); + Lex.Lex(); + return Ret; } @@ -322,11 +326,11 @@ Record *TGParser::ParseClassID() { TokError("expected name for ClassID"); return 0; } - + Record *Result = Records.getClass(Lex.getCurStrVal()); if (Result == 0) TokError("Couldn't find class '" + Lex.getCurStrVal() + "'"); - + Lex.Lex(); return Result; } @@ -355,17 +359,16 @@ Record *TGParser::ParseDefmID() { 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; -} - +} /// ParseSubClassReference - Parse a reference to a subclass or to a templated @@ -378,37 +381,37 @@ SubClassReference TGParser:: ParseSubClassReference(Record *CurRec, bool isDefm) { SubClassReference Result; Result.RefLoc = Lex.getLoc(); - + if (isDefm) Result.Rec = ParseDefmID(); 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) return Result; Lex.Lex(); // Eat the '<' - + if (Lex.getCode() == tgtok::greater) { TokError("subclass reference requires a non-empty list of template values"); Result.Rec = 0; 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; } - + if (Lex.getCode() != tgtok::greater) { TokError("expected '>' in template value list"); Result.Rec = 0; return Result; } Lex.Lex(); - + return Result; } @@ -438,7 +441,7 @@ ParseSubMultiClassReference(MultiClass *CurMC) { return Result; } - Result.TemplateArgs = ParseValueList(&CurMC->Rec); + Result.TemplateArgs = ParseValueList(&CurMC->Rec, &Result.MC->Rec); if (Result.TemplateArgs.empty()) { Result.MC = 0; // Error parsing value list. return Result; @@ -465,12 +468,12 @@ bool TGParser::ParseRangePiece(std::vector &Ranges) { } int64_t Start = Lex.getCurIntVal(); int64_t End; - + if (Start < 0) return TokError("invalid range, cannot be negative"); - + switch (Lex.Lex()) { // eat first character. - default: + default: Ranges.push_back(Start); return false; case tgtok::minus: @@ -484,10 +487,10 @@ bool TGParser::ParseRangePiece(std::vector &Ranges) { End = -Lex.getCurIntVal(); break; } - if (End < 0) + if (End < 0) return TokError("invalid range, cannot be negative"); Lex.Lex(); - + // Add to the range. if (Start < End) { for (; Start <= End; ++Start) @@ -505,7 +508,7 @@ bool TGParser::ParseRangePiece(std::vector &Ranges) { /// std::vector TGParser::ParseRangeList() { std::vector Result; - + // Parse the first piece. if (ParseRangePiece(Result)) return std::vector(); @@ -525,14 +528,14 @@ std::vector TGParser::ParseRangeList() { bool TGParser::ParseOptionalRangeList(std::vector &Ranges) { if (Lex.getCode() != tgtok::less) return false; - - TGLoc StartLoc = Lex.getLoc(); + + SMLoc StartLoc = Lex.getLoc(); Lex.Lex(); // eat the '<' - + // Parse the range list. Ranges = ParseRangeList(); if (Ranges.empty()) return true; - + if (Lex.getCode() != tgtok::greater) { TokError("expected '>' at end of range list"); return Error(StartLoc, "to match this '<'"); @@ -547,14 +550,14 @@ bool TGParser::ParseOptionalRangeList(std::vector &Ranges) { bool TGParser::ParseOptionalBitList(std::vector &Ranges) { if (Lex.getCode() != tgtok::l_brace) return false; - - TGLoc StartLoc = Lex.getLoc(); + + SMLoc StartLoc = Lex.getLoc(); Lex.Lex(); // eat the '{' - + // Parse the range list. Ranges = ParseRangeList(); if (Ranges.empty()) return true; - + if (Lex.getCode() != tgtok::r_brace) { TokError("expected '}' at end of bit list"); return Error(StartLoc, "to match this '{'"); @@ -578,13 +581,13 @@ bool TGParser::ParseOptionalBitList(std::vector &Ranges) { RecTy *TGParser::ParseType() { switch (Lex.getCode()) { default: TokError("Unknown token when expecting a type"); return 0; - case tgtok::String: Lex.Lex(); return new StringRecTy(); - case tgtok::Bit: Lex.Lex(); return new BitRecTy(); - case tgtok::Int: Lex.Lex(); return new IntRecTy(); - case tgtok::Code: Lex.Lex(); return new CodeRecTy(); - case tgtok::Dag: Lex.Lex(); return new DagRecTy(); + case tgtok::String: Lex.Lex(); return StringRecTy::get(); + case tgtok::Bit: Lex.Lex(); return BitRecTy::get(); + case tgtok::Int: Lex.Lex(); return IntRecTy::get(); + case tgtok::Code: Lex.Lex(); return CodeRecTy::get(); + case tgtok::Dag: Lex.Lex(); return DagRecTy::get(); case tgtok::Id: - if (Record *R = ParseClassID()) return new RecordRecTy(R); + if (Record *R = ParseClassID()) return RecordRecTy::get(R); return 0; case tgtok::Bits: { if (Lex.Lex() != tgtok::less) { // Eat 'bits' @@ -601,7 +604,7 @@ RecTy *TGParser::ParseType() { return 0; } Lex.Lex(); // Eat '>' - return new BitsRecTy(Val); + return BitsRecTy::get(Val); } case tgtok::List: { if (Lex.Lex() != tgtok::less) { // Eat 'bits' @@ -611,15 +614,15 @@ RecTy *TGParser::ParseType() { Lex.Lex(); // Eat '<' RecTy *SubType = ParseType(); if (SubType == 0) return 0; - + if (Lex.getCode() != tgtok::greater) { TokError("expected '>' at end of list type"); return 0; } Lex.Lex(); // Eat '>' - return new ListRecTy(SubType); + return ListRecTy::get(SubType); + } } - } } /// ParseIDValue - Parse an ID as a value and decode what it means. @@ -630,41 +633,41 @@ RecTy *TGParser::ParseType() { /// IDValue ::= ID [multiclass template argument] /// IDValue ::= ID [def name] /// -Init *TGParser::ParseIDValue(Record *CurRec) { +const Init *TGParser::ParseIDValue(Record *CurRec) { assert(Lex.getCode() == tgtok::Id && "Expected ID in ParseIDValue"); std::string Name = Lex.getCurStrVal(); - TGLoc Loc = Lex.getLoc(); + SMLoc Loc = Lex.getLoc(); Lex.Lex(); return ParseIDValue(CurRec, Name, Loc); } /// 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, TGLoc NameLoc) { +const Init *TGParser::ParseIDValue(Record *CurRec, + const std::string &Name, SMLoc NameLoc) { if (CurRec) { if (const RecordVal *RV = CurRec->getValue(Name)) - return new VarInit(Name, RV->getType()); - + return VarInit::get(Name, RV->getType()); + std::string TemplateArgName = CurRec->getName()+":"+Name; if (CurRec->isTemplateArg(TemplateArgName)) { const RecordVal *RV = CurRec->getValue(TemplateArgName); assert(RV && "Template arg doesn't exist??"); - return new VarInit(TemplateArgName, RV->getType()); + return VarInit::get(TemplateArgName, RV->getType()); } } - + if (CurMultiClass) { std::string MCName = CurMultiClass->Rec.getName()+"::"+Name; if (CurMultiClass->Rec.isTemplateArg(MCName)) { const RecordVal *RV = CurMultiClass->Rec.getValue(MCName); assert(RV && "Template arg doesn't exist??"); - return new VarInit(MCName, RV->getType()); + return VarInit::get(MCName, RV->getType()); } } - + if (Record *D = Records.getDef(Name)) - return new DefInit(D); + return DefInit::get(D); Error(NameLoc, "Variable not defined: '" + Name + "'"); return 0; @@ -674,15 +677,15 @@ Init *TGParser::ParseIDValue(Record *CurRec, /// /// Operation ::= XOperator ['<' Type '>'] '(' Args ')' /// -Init *TGParser::ParseOperation(Record *CurRec) { +const 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::XHead: + case tgtok::XTail: + case tgtok::XEmpty: case tgtok::XCast: { // Value ::= !unop '(' Value ')' UnOpInit::UnaryOp Code; RecTy *Type = 0; @@ -701,18 +704,18 @@ 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; - Type = new IntRecTy; + Code = UnOpInit::EMPTY; + Type = IntRecTy::get(); break; } if (Lex.getCode() != tgtok::l_paren) { @@ -721,57 +724,61 @@ Init *TGParser::ParseOperation(Record *CurRec) { } Lex.Lex(); // eat the '(' - Init *LHS = ParseValue(CurRec); + const Init *LHS = ParseValue(CurRec); if (LHS == 0) return 0; - if (Code == UnOpInit::CAR - || Code == UnOpInit::CDR - || Code == UnOpInit::LNULL) { - ListInit *LHSl = dynamic_cast(LHS); - TypedInit *LHSt = dynamic_cast(LHS); - if (LHSl == 0 && LHSt == 0) { - TokError("expected list type argument in unary operator"); + if (Code == UnOpInit::HEAD + || Code == UnOpInit::TAIL + || Code == UnOpInit::EMPTY) { + const ListInit *LHSl = dynamic_cast(LHS); + const StringInit *LHSs = dynamic_cast(LHS); + const 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()); - if (LType == 0) { - TokError("expected list type argumnet in unary operator"); + 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 (Code == UnOpInit::HEAD + || Code == UnOpInit::TAIL) { + 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); + const Init *Item = LHSl->getElement(0); + const TypedInit *Itemt = dynamic_cast(Item); if (Itemt == 0) { TokError("untyped list element in unary operator"); return 0; } - if (Code == UnOpInit::CAR) { + if (Code == UnOpInit::HEAD) { Type = Itemt->getType(); + } else { + Type = ListRecTy::get(Itemt->getType()); } - else { - Type = new ListRecTy(Itemt->getType()); - } - } - else { + } 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) { + if (Code == UnOpInit::HEAD) { Type = LType->getElementType(); - } - else { + } else { Type = LType; } } @@ -783,89 +790,76 @@ Init *TGParser::ParseOperation(Record *CurRec) { return 0; } Lex.Lex(); // eat the ')' - return (new UnOpInit(Code, LHS, Type))->Fold(CurRec, CurMultiClass); + return (UnOpInit::get(Code, LHS, Type))->Fold(CurRec, CurMultiClass); } case tgtok::XConcat: - case tgtok::XSRA: + case tgtok::XSRA: case tgtok::XSRL: case tgtok::XSHL: - case tgtok::XStrConcat: - case tgtok::XRegMatch: - case tgtok::XNameConcat: { // Value ::= !binop '(' Value ',' Value ')' + case tgtok::XEq: + 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::XStrConcat: - Lex.Lex(); // eat the operation + 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; + case tgtok::XSHL: Code = BinOpInit::SHL; Type = IntRecTy::get(); break; + case tgtok::XEq: Code = BinOpInit::EQ; Type = BitRecTy::get(); break; + case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; - Type = new StringRecTy(); - break; - case tgtok::XRegMatch: - Lex.Lex(); // eat the operation - Code = BinOpInit::REGMATCH; - Type = new IntRecTy(); - 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; - } - + Type = StringRecTy::get(); 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; + InitList.push_back(ParseValue(CurRec)); + if (InitList.back() == 0) return 0; + + while (Lex.getCode() == tgtok::comma) { + Lex.Lex(); // eat the ',' + + InitList.push_back(ParseValue(CurRec)); + if (InitList.back() == 0) 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"); + 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) { + const Init *RHS = InitList.pop_back_val(); + RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type)) + ->Fold(CurRec, CurMultiClass); + InitList.back() = RHS; + } + } + + if (InitList.size() == 2) + return (BinOpInit::get(Code, InitList[0], InitList[1], Type)) + ->Fold(CurRec, CurMultiClass); + + Error(OpLoc, "expected two operands to operator"); + return 0; } case tgtok::XIf: @@ -874,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) { @@ -895,7 +888,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { } Lex.Lex(); // eat the '(' - Init *LHS = ParseValue(CurRec); + const Init *LHS = ParseValue(CurRec); if (LHS == 0) return 0; if (Lex.getCode() != tgtok::comma) { @@ -903,8 +896,8 @@ Init *TGParser::ParseOperation(Record *CurRec) { return 0; } Lex.Lex(); // eat the ',' - - Init *MHS = ParseValue(CurRec); + + const Init *MHS = ParseValue(CurRec); if (MHS == 0) return 0; if (Lex.getCode() != tgtok::comma) { @@ -912,8 +905,8 @@ Init *TGParser::ParseOperation(Record *CurRec) { return 0; } Lex.Lex(); // eat the ',' - - Init *RHS = ParseValue(CurRec); + + const Init *RHS = ParseValue(CurRec); if (RHS == 0) return 0; if (Lex.getCode() != tgtok::r_paren) { @@ -925,26 +918,53 @@ 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. + const TypedInit *MHSt = dynamic_cast(MHS); + const TypedInit *RHSt = dynamic_cast(RHS); + + RecTy *MHSTy = 0; + RecTy *RHSTy = 0; + + if (MHSt == 0 && RHSt == 0) { + const BitsInit *MHSbits = dynamic_cast(MHS); + const BitsInit *RHSbits = dynamic_cast(RHS); + + if (MHSbits && RHSbits && + MHSbits->getNumBits() == RHSbits->getNumBits()) { + Type = BitRecTy::get(); + break; + } else { + const BitInit *MHSbit = dynamic_cast(MHS); + const BitInit *RHSbit = dynamic_cast(RHS); + + if (MHSbit && RHSbit) { + Type = BitRecTy::get(); + 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(); - } - else { + + if (MHSTy->typeIsConvertibleTo(RHSTy)) { + Type = RHSTy; + } else if (RHSTy->typeIsConvertibleTo(MHSTy)) { + Type = MHSTy; + } else { TokError("inconsistent types for !if"); return 0; } break; } case tgtok::XForEach: { - TypedInit *MHSt = dynamic_cast(MHS); + const TypedInit *MHSt = dynamic_cast(MHS); if (MHSt == 0) { TokError("could not get type for !foreach"); return 0; @@ -953,7 +973,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { break; } case tgtok::XSubst: { - TypedInit *RHSt = dynamic_cast(RHS); + const TypedInit *RHSt = dynamic_cast(RHS); if (RHSt == 0) { TokError("could not get type for !subst"); return 0; @@ -962,7 +982,8 @@ Init *TGParser::ParseOperation(Record *CurRec) { break; } } - return (new TernOpInit(Code, LHS, MHS, RHS, Type))->Fold(CurRec, CurMultiClass); + return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec, + CurMultiClass); } } TokError("could not parse operation"); @@ -974,7 +995,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { /// /// OperatorType ::= '<' Type '>' /// -RecTy *TGParser::ParseOperatorType(void) { +RecTy *TGParser::ParseOperatorType() { RecTy *Type = 0; if (Lex.getCode() != tgtok::less) { @@ -1017,47 +1038,44 @@ RecTy *TGParser::ParseOperatorType(void) { /// SimpleValue ::= SRLTOK '(' Value ',' Value ')' /// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')' /// -Init *TGParser::ParseSimpleValue(Record *CurRec) { - Init *R = 0; +const Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { + const 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::IntVal: R = IntInit::get(Lex.getCurIntVal()); 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); + + R = StringInit::get(Val); break; } case tgtok::CodeFragment: - R = new CodeInit(Lex.getCurStrVal()); Lex.Lex(); break; - case tgtok::question: R = new UnsetInit(); Lex.Lex(); break; + R = CodeInit::get(Lex.getCurStrVal()); + Lex.Lex(); + break; + case tgtok::question: + R = UnsetInit::get(); + Lex.Lex(); + break; case tgtok::Id: { - TGLoc 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 - + // Value ::= ID '<' ValueListNE '>' if (Lex.Lex() == tgtok::greater) { 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. @@ -1066,10 +1084,21 @@ 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++),NameLoc); + Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++), + NameLoc, + Records); SubClassReference SCRef; SCRef.RefLoc = NameLoc; SCRef.Rec = Class; @@ -1079,15 +1108,15 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { return 0; NewRec->resolveReferences(); Records.addDef(NewRec); - + // The result of the expression is a reference to the new record. - return new DefInit(NewRec); - } + return DefInit::get(NewRec); + } case tgtok::l_brace: { // Value ::= '{' ValueList '}' - TGLoc BraceLoc = Lex.getLoc(); + SMLoc BraceLoc = Lex.getLoc(); Lex.Lex(); // eat the '{' - std::vector Vals; - + std::vector Vals; + if (Lex.getCode() != tgtok::r_brace) { Vals = ParseValueList(CurRec); if (Vals.empty()) return 0; @@ -1097,25 +1126,42 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { return 0; } Lex.Lex(); // eat the '}' - - BitsInit *Result = new BitsInit(Vals.size()); + + SmallVector NewBits(Vals.size()); + for (unsigned i = 0, e = Vals.size(); i != e; ++i) { - Init *Bit = Vals[i]->convertInitializerTo(new BitRecTy()); + const Init *Bit = Vals[i]->convertInitializerTo(BitRecTy::get()); if (Bit == 0) { Error(BraceLoc, "Element #" + utostr(i) + " (" + Vals[i]->getAsString()+ ") is not convertable to a bit"); return 0; } - Result->setBit(Vals.size()-i-1, Bit); + NewBits[Vals.size()-i-1] = Bit; } - return Result; + return BitsInit::get(NewBits); } case tgtok::l_square: { // Value ::= '[' ValueList ']' Lex.Lex(); // eat the '[' - std::vector Vals; - + 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()); + return 0; + } + 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) { @@ -1123,26 +1169,85 @@ 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) { + const 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 ListInit::get(Vals, DeducedEltTy); } 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; - } + + const Init *Operator = ParseValue(CurRec); + if (Operator == 0) return 0; // If the operator name is present, parse it. std::string OperatorName; @@ -1154,42 +1259,39 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { OperatorName = Lex.getCurStrVal(); Lex.Lex(); // eat the VarName. } - - std::vector > DagArgs; + + std::vector > DagArgs; if (Lex.getCode() != tgtok::r_paren) { DagArgs = ParseDagArgList(CurRec); if (DagArgs.empty()) return 0; } - + if (Lex.getCode() != tgtok::r_paren) { TokError("expected ')' in dag init"); return 0; } Lex.Lex(); // eat the ')' - - return new DagInit(Operator, OperatorName, DagArgs); - break; + + return DagInit::get(Operator, OperatorName, DagArgs); } - - 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::XSRA: case tgtok::XSRL: case tgtok::XSHL: - case tgtok::XStrConcat: - case tgtok::XRegMatch: - case tgtok::XNameConcat: // Value ::= !binop '(' Value ',' Value ')' + case tgtok::XEq: + 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; } } - + return R; } @@ -1200,20 +1302,20 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { /// ValueSuffix ::= '[' BitList ']' /// ValueSuffix ::= '.' ID /// -Init *TGParser::ParseValue(Record *CurRec) { - Init *Result = ParseSimpleValue(CurRec); +const Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType) { + const Init *Result = ParseSimpleValue(CurRec, ItemType); if (Result == 0) return 0; - + // Parse the suffixes now if present. while (1) { switch (Lex.getCode()) { default: return Result; case tgtok::l_brace: { - TGLoc CurlyLoc = Lex.getLoc(); + SMLoc CurlyLoc = Lex.getLoc(); Lex.Lex(); // eat the '{' std::vector Ranges = ParseRangeList(); if (Ranges.empty()) return 0; - + // Reverse the bitlist. std::reverse(Ranges.begin(), Ranges.end()); Result = Result->convertInitializerBitRange(Ranges); @@ -1221,7 +1323,7 @@ Init *TGParser::ParseValue(Record *CurRec) { Error(CurlyLoc, "Invalid bit range for value"); return 0; } - + // Eat the '}'. if (Lex.getCode() != tgtok::r_brace) { TokError("expected '}' at end of bit range list"); @@ -1231,17 +1333,17 @@ Init *TGParser::ParseValue(Record *CurRec) { break; } case tgtok::l_square: { - TGLoc SquareLoc = Lex.getLoc(); + SMLoc SquareLoc = Lex.getLoc(); Lex.Lex(); // eat the '[' std::vector Ranges = ParseRangeList(); if (Ranges.empty()) return 0; - + Result = Result->convertInitListSlice(Ranges); if (Result == 0) { Error(SquareLoc, "Invalid range for list slice"); return 0; } - + // Eat the ']'. if (Lex.getCode() != tgtok::r_square) { TokError("expected ']' at end of list slice"); @@ -1260,7 +1362,7 @@ Init *TGParser::ParseValue(Record *CurRec) { Result->getAsString() + "'"); return 0; } - Result = new FieldInit(Result, Lex.getCurStrVal()); + Result = FieldInit::get(Result, Lex.getCurStrVal()); Lex.Lex(); // eat field name break; } @@ -1271,31 +1373,31 @@ Init *TGParser::ParseValue(Record *CurRec) { /// /// ParseDagArgList ::= Value (':' VARNAME)? /// ParseDagArgList ::= ParseDagArgList ',' Value (':' VARNAME)? -std::vector > +std::vector > TGParser::ParseDagArgList(Record *CurRec) { - std::vector > Result; - + std::vector > Result; + while (1) { - Init *Val = ParseValue(CurRec); - if (Val == 0) return std::vector >(); - + const 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"); - return std::vector >(); + 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 ',' + Lex.Lex(); // eat the ',' } - + return Result; } @@ -1306,23 +1408,43 @@ TGParser::ParseDagArgList(Record *CurRec) { /// /// ValueList ::= Value (',' Value) /// -std::vector TGParser::ParseValueList(Record *CurRec) { - std::vector Result; - Result.push_back(ParseValue(CurRec)); - if (Result.back() == 0) return std::vector(); - +std::vector TGParser::ParseValueList(Record *CurRec, Record *ArgsRec, + RecTy *EltTy) { + std::vector Result; + 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 (Result.back() == 0) return std::vector(); + + 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(); } - + return Result; } - /// ParseDeclaration - Read a declaration, returning the name of field ID, or an /// empty string on error. This can happen in a number of different context's, /// including within a def or in the template args for a def (which which case @@ -1333,24 +1455,24 @@ std::vector TGParser::ParseValueList(Record *CurRec) { /// /// Declaration ::= FIELD? Type ID ('=' Value)? /// -std::string TGParser::ParseDeclaration(Record *CurRec, +std::string TGParser::ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs) { // Read the field prefix if present. bool HasField = Lex.getCode() == tgtok::Field; if (HasField) Lex.Lex(); - + RecTy *Type = ParseType(); if (Type == 0) return ""; - + if (Lex.getCode() != tgtok::Id) { TokError("Expected identifier in declaration"); return ""; } - - TGLoc IdLoc = Lex.getLoc(); + + SMLoc IdLoc = Lex.getLoc(); std::string DeclName = Lex.getCurStrVal(); Lex.Lex(); - + if (ParsingTemplateArgs) { if (CurRec) { DeclName = CurRec->getName() + ":" + DeclName; @@ -1360,21 +1482,21 @@ std::string TGParser::ParseDeclaration(Record *CurRec, if (CurMultiClass) DeclName = CurMultiClass->Rec.getName() + "::" + DeclName; } - + // Add the value. if (AddValue(CurRec, IdLoc, RecordVal(DeclName, Type, HasField))) return ""; - + // If a value is present, parse it. if (Lex.getCode() == tgtok::equal) { Lex.Lex(); - TGLoc ValLoc = Lex.getLoc(); - Init *Val = ParseValue(CurRec); + SMLoc ValLoc = Lex.getLoc(); + const Init *Val = ParseValue(CurRec, Type); if (Val == 0 || SetValue(CurRec, ValLoc, DeclName, std::vector(), Val)) return ""; } - + return DeclName; } @@ -1384,30 +1506,30 @@ std::string TGParser::ParseDeclaration(Record *CurRec, /// these are the template args for a multiclass. /// /// TemplateArgList ::= '<' Declaration (',' Declaration)* '>' -/// +/// bool TGParser::ParseTemplateArgList(Record *CurRec) { assert(Lex.getCode() == tgtok::less && "Not a template arg list!"); Lex.Lex(); // eat the '<' - + Record *TheRecToAddTo = CurRec ? CurRec : &CurMultiClass->Rec; - + // Read the first declaration. std::string TemplArg = ParseDeclaration(CurRec, true/*templateargs*/); if (TemplArg.empty()) return true; - + TheRecToAddTo->addTemplateArg(TemplArg); - + while (Lex.getCode() == tgtok::comma) { Lex.Lex(); // eat the ',' - + // Read the following declarations. TemplArg = ParseDeclaration(CurRec, true/*templateargs*/); if (TemplArg.empty()) return true; TheRecToAddTo->addTemplateArg(TemplArg); } - + if (Lex.getCode() != tgtok::greater) return TokError("expected '>' at end of template argument list"); Lex.Lex(); // eat the '>'. @@ -1421,9 +1543,9 @@ bool TGParser::ParseTemplateArgList(Record *CurRec) { /// BodyItem ::= LET ID OptionalBitList '=' Value ';' bool TGParser::ParseBodyItem(Record *CurRec) { if (Lex.getCode() != tgtok::Let) { - if (ParseDeclaration(CurRec, false).empty()) + if (ParseDeclaration(CurRec, false).empty()) return true; - + if (Lex.getCode() != tgtok::semi) return TokError("expected ';' after declaration"); Lex.Lex(); @@ -1433,27 +1555,33 @@ bool TGParser::ParseBodyItem(Record *CurRec) { // LET ID OptionalRangeList '=' Value ';' if (Lex.Lex() != tgtok::Id) return TokError("expected field identifier after let"); - - TGLoc IdLoc = Lex.getLoc(); + + SMLoc IdLoc = Lex.getLoc(); std::string FieldName = Lex.getCurStrVal(); Lex.Lex(); // eat the field name. - + std::vector BitList; - if (ParseOptionalBitList(BitList)) + if (ParseOptionalBitList(BitList)) return true; std::reverse(BitList.begin(), BitList.end()); - + if (Lex.getCode() != tgtok::equal) 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(); + + const Init *Val = ParseValue(CurRec, Type); if (Val == 0) return true; - + if (Lex.getCode() != tgtok::semi) return TokError("expected ';' after let expression"); Lex.Lex(); - + return SetValue(CurRec, IdLoc, FieldName, BitList, Val); } @@ -1470,12 +1598,12 @@ bool TGParser::ParseBody(Record *CurRec) { Lex.Lex(); return false; } - + if (Lex.getCode() != tgtok::l_brace) return TokError("Expected ';' or '{' to start body"); // Eat the '{'. Lex.Lex(); - + while (Lex.getCode() != tgtok::r_brace) if (ParseBodyItem(CurRec)) return true; @@ -1498,17 +1626,17 @@ bool TGParser::ParseObjectBody(Record *CurRec) { // If there is a baseclass list, read it. if (Lex.getCode() == tgtok::colon) { Lex.Lex(); - + // Read all of the subclasses. SubClassReference SubClass = ParseSubClassReference(CurRec, false); while (1) { // Check for error. if (SubClass.Rec == 0) return true; - + // Add it. if (AddSubClass(CurRec, SubClass)) return true; - + if (Lex.getCode() != tgtok::comma) break; Lex.Lex(); // eat ','. SubClass = ParseSubClassReference(CurRec, false); @@ -1521,31 +1649,30 @@ bool TGParser::ParseObjectBody(Record *CurRec) { if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name, LetStack[i][j].Bits, LetStack[i][j].Value)) return true; - + 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) { - TGLoc DefLoc = Lex.getLoc(); +bool TGParser::ParseDef(MultiClass *CurMultiClass) { + SMLoc DefLoc = Lex.getLoc(); assert(Lex.getCode() == tgtok::Def && "Unknown tok"); - Lex.Lex(); // Eat the 'def' token. + 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. - + // 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 { @@ -1554,20 +1681,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; } @@ -1578,10 +1718,10 @@ llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) { bool TGParser::ParseClass() { assert(Lex.getCode() == tgtok::Class && "Unexpected token!"); Lex.Lex(); - + if (Lex.getCode() != tgtok::Id) return TokError("expected class name after 'class' keyword"); - + Record *CurRec = Records.getClass(Lex.getCurStrVal()); if (CurRec) { // If the body was previously defined, this is an error. @@ -1591,11 +1731,11 @@ 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. - + // If there are template args, parse them. if (Lex.getCode() == tgtok::less) if (ParseTemplateArgList(CurRec)) @@ -1613,50 +1753,50 @@ bool TGParser::ParseClass() { /// std::vector TGParser::ParseLetList() { std::vector Result; - + while (1) { if (Lex.getCode() != tgtok::Id) { TokError("expected identifier in let definition"); return std::vector(); } std::string Name = Lex.getCurStrVal(); - TGLoc NameLoc = Lex.getLoc(); - Lex.Lex(); // Eat the identifier. + SMLoc NameLoc = Lex.getLoc(); + Lex.Lex(); // Eat the identifier. // Check for an optional RangeList. std::vector Bits; - if (ParseOptionalRangeList(Bits)) + if (ParseOptionalRangeList(Bits)) return std::vector(); std::reverse(Bits.begin(), Bits.end()); - + if (Lex.getCode() != tgtok::equal) { TokError("expected '=' in let expression"); return std::vector(); } Lex.Lex(); // eat the '='. - - Init *Val = ParseValue(0); + + const Init *Val = ParseValue(0); if (Val == 0) return std::vector(); - + // Now that we have everything, add the record. Result.push_back(LetRecord(Name, Bits, Val, NameLoc)); - + if (Lex.getCode() != tgtok::comma) return Result; - Lex.Lex(); // eat the comma. + Lex.Lex(); // eat the comma. } } /// 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(); - + // Add this entry to the let stack. std::vector LetInfo = ParseLetList(); if (LetInfo.empty()) return true; @@ -1665,56 +1805,33 @@ bool TGParser::ParseTopLevelLet() { if (Lex.getCode() != tgtok::In) return TokError("expected 'in' at end of top-level 'let'"); Lex.Lex(); - + // 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 '}' - TGLoc BraceLoc = Lex.getLoc(); + SMLoc BraceLoc = Lex.getLoc(); // Otherwise, this is a group let. Lex.Lex(); // eat the '{'. - + // Parse the object list. - if (ParseObjectList()) + if (ParseObjectList(CurMultiClass)) return true; - + if (Lex.getCode() != tgtok::r_brace) { TokError("expected '}' at end of top level let command"); return Error(BraceLoc, "to match this '{'"); } Lex.Lex(); } - + // Outside this let scope, this let block is not active. LetStack.pop_back(); 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? @@ -1727,13 +1844,14 @@ bool TGParser::ParseMultiClass() { if (Lex.getCode() != tgtok::Id) return TokError("expected identifier after multiclass for name"); std::string Name = Lex.getCurStrVal(); - + 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. if (Lex.getCode() == tgtok::less) if (ParseTemplateArgList(0)) @@ -1767,23 +1885,29 @@ bool TGParser::ParseMultiClass() { 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 - if (Lex.getCode() != tgtok::semi) - return TokError("expected ';' in multiclass definition"); - else - Lex.Lex(); // eat the ';'. - } - 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) { + 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 '}'. } - + CurMultiClass = 0; return false; } @@ -1792,20 +1916,29 @@ 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"); - - TGLoc DefmPrefixLoc = Lex.getLoc(); - std::string DefmPrefix = Lex.getCurStrVal(); - if (Lex.Lex() != tgtok::colon) + + std::string DefmPrefix; + if (Lex.Lex() == tgtok::Id) { // eat the defm. + DefmPrefix = Lex.getCurStrVal(); + Lex.Lex(); // Eat the defm prefix. + } + + SMLoc DefmPrefixLoc = Lex.getLoc(); + 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(); - TGLoc SubClassLoc = Lex.getLoc(); + SMLoc SubClassLoc = Lex.getLoc(); SubClassReference Ref = ParseSubClassReference(0, true); while (1) { @@ -1816,7 +1949,7 @@ bool TGParser::ParseDefm() { // template parameters. MultiClass *MC = MultiClasses[Ref.Rec->getName()]; assert(MC && "Didn't lookup multiclass correctly?"); - std::vector &TemplateVals = Ref.TemplateArgs; + std::vector &TemplateVals = Ref.TemplateArgs; // Verify that the correct number of template arguments were specified. const std::vector &TArgs = MC->Rec.getTemplateArgs(); @@ -1828,18 +1961,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); - } - else { - // Add the suffix to the defm name to get the new name. - DefName = DefmPrefix + DefName; + if (DefmPrefix.empty()) { + DefName = GetNewAnonymousName(); + } else { + 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; @@ -1881,24 +2020,94 @@ bool TGParser::ParseDefm() { // Ensure redefinition doesn't happen. if (Records.getDef(CurRec->getName())) - return Error(DefmPrefixLoc, "def '" + CurRec->getName() + - "' already defined, instantiating defm with subdef '" + + 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(); - + return false; } @@ -1909,12 +2118,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(); } @@ -1922,23 +2132,22 @@ 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; } - bool TGParser::ParseFile() { Lex.Lex(); // Prime the lexer. if (ParseObjectList()) return true; - + // If we have unread input at the end of the file, report it. if (Lex.getCode() == tgtok::Eof) return false; - + return TokError("Unexpected input at top level"); }