diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2011-10-01 16:41:13 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2011-10-01 16:41:13 +0000 |
commit | 7c788888872233748da10a8177a9a1eb176c1bc8 (patch) | |
tree | 2a813c66793364aeb39020c96c9510bb1c4f9cee /utils/TableGen/TGParser.cpp | |
parent | 2e6b97bbf86d0825a060e190189fae7f884c79c9 (diff) |
Move TableGen's parser and entry point into a library
This is the first step towards splitting LLVM and Clang's tblgen executables.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140951 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/TableGen/TGParser.cpp')
-rw-r--r-- | utils/TableGen/TGParser.cpp | 2163 |
1 files changed, 0 insertions, 2163 deletions
diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp deleted file mode 100644 index f734b984e1..0000000000 --- a/utils/TableGen/TGParser.cpp +++ /dev/null @@ -1,2163 +0,0 @@ -//===- TGParser.cpp - Parser for TableGen Files ---------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Implement the Parser for TableGen. -// -//===----------------------------------------------------------------------===// - -#include "TGParser.h" -#include "Record.h" -#include "llvm/ADT/StringExtras.h" -#include <algorithm> -#include <sstream> -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/CommandLine.h" -using namespace llvm; - -//===----------------------------------------------------------------------===// -// Support Code for the Semantic Actions. -//===----------------------------------------------------------------------===// - -namespace llvm { -struct SubClassReference { - SMLoc RefLoc; - Record *Rec; - std::vector<Init*> TemplateArgs; - SubClassReference() : Rec(0) {} - - bool isInvalid() const { return Rec == 0; } -}; - -struct SubMultiClassReference { - SMLoc RefLoc; - MultiClass *MC; - std::vector<Init*> 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<Init *>::const_iterator i = TemplateArgs.begin(), - iend = TemplateArgs.end(); - i != iend; - ++i) { - (*i)->dump(); - } -} - -} // end namespace llvm - -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 '" + - ERV->getType()->getAsString() + "'"); - } else { - CurRec->addValue(RV); - } - return false; -} - -/// SetValue - -/// Return true on error, false on success. -bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName, - const std::vector<unsigned> &BitList, Init *V) { - if (!V) return false; - - if (CurRec == 0) CurRec = &CurMultiClass->Rec; - - RecordVal *RV = CurRec->getValue(ValName); - if (RV == 0) - return Error(Loc, "Value '" + ValName + "' unknown!"); - - // 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<VarInit*>(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<BitsInit*>(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(BitsRecTy::get(BitList.size())); - if (BI == 0) { - V->convertInitializerTo(BitsRecTy::get(BitList.size())); - return Error(Loc, "Initializer is not compatible with bit range"); - } - - // We should have a BitsInit type now. - BitsInit *BInit = dynamic_cast<BitsInit*>(BI); - assert(BInit != 0); - - SmallVector<Init *, 16> 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 (NewBits[Bit]) - return Error(Loc, "Cannot set bit #" + utostr(Bit) + " of value '" + - ValName + "' more than once"); - NewBits[Bit] = BInit->getBit(i); - } - - for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i) - if (NewBits[i] == 0) - NewBits[i] = CurVal->getBit(i); - - V = BitsInit::get(NewBits); - } - - if (RV->setValue(V)) - return Error(Loc, "Value '" + ValName + "' of type '" + - RV->getType()->getAsString() + - "' 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, SubClassReference &SubClass) { - Record *SC = SubClass.Rec; - // Add all of the values in the subclass into the current class. - const std::vector<RecordVal> &Vals = SC->getValues(); - for (unsigned i = 0, e = Vals.size(); i != e; ++i) - if (AddValue(CurRec, SubClass.RefLoc, Vals[i])) - return true; - - const std::vector<std::string> &TArgs = SC->getTemplateArgs(); - - // Ensure that an appropriate number of template arguments are specified. - if (TArgs.size() < SubClass.TemplateArgs.size()) - return Error(SubClass.RefLoc, "More template args specified than expected"); - - // 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<unsigned>(), - 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 '" + - SC->getName() + "'!"); - } - } - - // Since everything went well, we can now set the "superclass" list for the - // current record. - const std::vector<Record*> &SCs = SC->getSuperClasses(); - for (unsigned i = 0, e = SCs.size(); i != e; ++i) { - if (CurRec->isSubClassOf(SCs[i])) - return Error(SubClass.RefLoc, - "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"); - CurRec->addSuperClass(SC); - 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<RecordVal> &MCVals = CurRec->getValues(); - - // Add all of the values in the subclass into the current class. - const std::vector<RecordVal> &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<std::string> &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<unsigned>(), - 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<unsigned>(), - 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 -//===----------------------------------------------------------------------===// - -/// 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; -} - -static std::string GetNewAnonymousName() { - static unsigned AnonCounter = 0; - return "anonymous."+utostr(AnonCounter++); -} - -/// ParseObjectName - If an object name is specified, return it. Otherwise, -/// return an anonymous name. -/// ObjectName ::= ID -/// ObjectName ::= /*empty*/ -/// -std::string TGParser::ParseObjectName() { - if (Lex.getCode() != tgtok::Id) - return GetNewAnonymousName(); - - std::string Ret = Lex.getCurStrVal(); - Lex.Lex(); - return Ret; -} - - -/// ParseClassID - Parse and resolve a reference to a class name. This returns -/// null on error. -/// -/// ClassID ::= ID -/// -Record *TGParser::ParseClassID() { - if (Lex.getCode() != tgtok::Id) { - 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; -} - -/// 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"); - 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 -/// subclass. This returns a SubClassRefTy with a null Record* on error. -/// -/// SubClassRef ::= ClassID -/// SubClassRef ::= ClassID '<' ValueList '>' -/// -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.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; -} - -/// 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<unsigned> &Ranges) { - 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"); - - switch (Lex.Lex()) { // eat first character. - default: - Ranges.push_back(Start); - return false; - case tgtok::minus: - if (Lex.Lex() != tgtok::IntVal) { - TokError("expected integer value as end of range"); - return true; - } - End = Lex.getCurIntVal(); - break; - case tgtok::IntVal: - End = -Lex.getCurIntVal(); - break; - } - if (End < 0) - return TokError("invalid range, cannot be negative"); - Lex.Lex(); - - // Add to the range. - if (Start < End) { - for (; Start <= End; ++Start) - Ranges.push_back(Start); - } else { - for (; Start >= End; --Start) - Ranges.push_back(Start); - } - return false; -} - -/// ParseRangeList - Parse a list of scalars and ranges into scalar values. -/// -/// RangeList ::= RangePiece (',' RangePiece)* -/// -std::vector<unsigned> TGParser::ParseRangeList() { - std::vector<unsigned> Result; - - // Parse the first piece. - if (ParseRangePiece(Result)) - return std::vector<unsigned>(); - while (Lex.getCode() == tgtok::comma) { - Lex.Lex(); // Eat the comma. - - // Parse the next range piece. - if (ParseRangePiece(Result)) - return std::vector<unsigned>(); - } - return Result; -} - -/// ParseOptionalRangeList - Parse either a range list in <>'s or nothing. -/// OptionalRangeList ::= '<' RangeList '>' -/// OptionalRangeList ::= /*empty*/ -bool TGParser::ParseOptionalRangeList(std::vector<unsigned> &Ranges) { - if (Lex.getCode() != tgtok::less) - return false; - - 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 '<'"); - } - Lex.Lex(); // eat the '>'. - return false; -} - -/// ParseOptionalBitList - Parse either a bit list in {}'s or nothing. -/// OptionalBitList ::= '{' RangeList '}' -/// OptionalBitList ::= /*empty*/ -bool TGParser::ParseOptionalBitList(std::vector<unsigned> &Ranges) { - if (Lex.getCode() != tgtok::l_brace) - return false; - - 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 '{'"); - } - Lex.Lex(); // eat the '}'. - return false; -} - - -/// ParseType - Parse and return a tblgen type. This returns null on error. -/// -/// Type ::= STRING // string type -/// Type ::= BIT // bit type -/// Type ::= BITS '<' INTVAL '>' // bits<x> type -/// Type ::= INT // int type -/// Type ::= LIST '<' Type '>' // list<x> type -/// Type ::= CODE // code type -/// Type ::= DAG // dag type -/// Type ::= ClassID // Record Type -/// -RecTy *TGParser::ParseType() { - switch (Lex.getCode()) { - default: TokError("Unknown token when expecting a type"); return 0; - 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 RecordRecTy::get(R); - return 0; - case tgtok::Bits: { - if (Lex.Lex() != tgtok::less) { // Eat 'bits' - TokError("expected '<' after bits type"); - return 0; - } - if (Lex.Lex() != tgtok::IntVal) { // Eat '<' - TokError("expected integer in bits<n> type"); - return 0; - } - uint64_t Val = Lex.getCurIntVal(); - if (Lex.Lex() != tgtok::greater) { // Eat count. - TokError("expected '>' at end of bits<n> type"); - return 0; - } - Lex.Lex(); // Eat '>' - return BitsRecTy::get(Val); - } - case tgtok::List: { - if (Lex.Lex() != tgtok::less) { // Eat 'bits' - TokError("expected '<' after list type"); - return 0; - } - Lex.Lex(); // Eat '<' - RecTy *SubType = ParseType(); - if (SubType == 0) return 0; - - if (Lex.getCode() != tgtok::greater) { - TokError("expected '>' at end of list<ty> type"); - return 0; - } - Lex.Lex(); // Eat '>' - return ListRecTy::get(SubType); - } - } -} - -/// ParseIDValue - Parse an ID as a value and decode what it means. -/// -/// IDValue ::= ID [def local value] -/// IDValue ::= ID [def template arg] -/// IDValue ::= ID [multiclass local value] -/// IDValue ::= ID [multiclass template argument] -/// IDValue ::= ID [def name] -/// -Init *TGParser::ParseIDValue(Record *CurRec) { - assert(Lex.getCode() == tgtok::Id && "Expected ID in ParseIDValue"); - std::string Name = Lex.getCurStrVal(); - 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, SMLoc NameLoc) { - if (CurRec) { - if (const RecordVal *RV = CurRec->getValue(Name)) - 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 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 VarInit::get(MCName, RV->getType()); - } - } - - if (Record *D = Records.getDef(Name)) - return DefInit::get(D); - - Error(NameLoc, "Variable not defined: '" + Name + "'"); - 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::XHead: - case tgtok::XTail: - case tgtok::XEmpty: - 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::XHead: - Lex.Lex(); // eat the operation - Code = UnOpInit::HEAD; - break; - case tgtok::XTail: - Lex.Lex(); // eat the operation - Code = UnOpInit::TAIL; - break; - case tgtok::XEmpty: - Lex.Lex(); // eat the operation - Code = UnOpInit::EMPTY; - Type = IntRecTy::get(); - 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::HEAD - || Code == UnOpInit::TAIL - || Code == UnOpInit::EMPTY) { - ListInit *LHSl = dynamic_cast<ListInit*>(LHS); - StringInit *LHSs = dynamic_cast<StringInit*>(LHS); - TypedInit *LHSt = dynamic_cast<TypedInit*>(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<ListRecTy*>(LHSt->getType()); - StringRecTy *SType = dynamic_cast<StringRecTy*>(LHSt->getType()); - if (LType == 0 && SType == 0) { - TokError("expected list or string type argumnet in unary operator"); - return 0; - } - } - - 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<TypedInit*>(Item); - if (Itemt == 0) { - TokError("untyped list element in unary operator"); - return 0; - } - if (Code == UnOpInit::HEAD) { - Type = Itemt->getType(); - } else { - Type = ListRecTy::get(Itemt->getType()); - } - } else { - assert(LHSt && "expected list type argument in unary operator"); - ListRecTy *LType = dynamic_cast<ListRecTy*>(LHSt->getType()); - if (LType == 0) { - TokError("expected list type argumnet in unary operator"); - return 0; - } - if (Code == UnOpInit::HEAD) { - Type = LType->getElementType(); - } else { - Type = LType; - } - } - } - } - - if (Lex.getCode() != tgtok::r_paren) { - TokError("expected ')' in unary operator"); - return 0; - } - Lex.Lex(); // eat the ')' - return (UnOpInit::get(Code, LHS, Type))->Fold(CurRec, CurMultiClass); - } - - case tgtok::XConcat: - case tgtok::XSRA: - case tgtok::XSRL: - case tgtok::XSHL: - 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 (OpTok) { - default: assert(0 && "Unhandled code!"); - case tgtok::XConcat: Code = BinOpInit::CONCAT;Type = DagRecTy::get(); break; - case tgtok::XSRA: Code = BinOpInit::SRA; Type = IntRecTy::get(); break; - case tgtok::XSRL: Code = BinOpInit::SRL; Type = IntRecTy::get(); break; - 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 = StringRecTy::get(); - break; - } - - if (Lex.getCode() != tgtok::l_paren) { - TokError("expected '(' after binary operator"); - return 0; - } - Lex.Lex(); // eat the '(' - - SmallVector<Init*, 2> InitList; - - 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; - } - - if (Lex.getCode() != tgtok::r_paren) { - TokError("expected ')' in operator"); - return 0; - } - Lex.Lex(); // eat the ')' - - // We allow multiple operands to associative operators like !strconcat as - // shorthand for nesting them. - if (Code == BinOpInit::STRCONCAT) { - while (InitList.size() > 2) { - Init *RHS = InitList.pop_back_val(); - RHS = (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: - 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: { - // FIXME: The `!if' operator doesn't handle non-TypedInit well at - // all. This can be made much more robust. - TypedInit *MHSt = dynamic_cast<TypedInit*>(MHS); - TypedInit *RHSt = dynamic_cast<TypedInit*>(RHS); - - RecTy *MHSTy = 0; - RecTy *RHSTy = 0; - - if (MHSt == 0 && RHSt == 0) { - BitsInit *MHSbits = dynamic_cast<BitsInit*>(MHS); - BitsInit *RHSbits = dynamic_cast<BitsInit*>(RHS); - - if (MHSbits && RHSbits && - MHSbits->getNumBits() == RHSbits->getNumBits()) { - Type = BitRecTy::get(); - break; - } else { - BitInit *MHSbit = dynamic_cast<BitInit*>(MHS); - BitInit *RHSbit = dynamic_cast<BitInit*>(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 (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<TypedInit *>(MHS); - if (MHSt == 0) { - TokError("could not get type for !foreach"); - return 0; - } - Type = MHSt->getType(); - break; - } - case tgtok::XSubst: { - TypedInit *RHSt = dynamic_cast<TypedInit *>(RHS); - if (RHSt == 0) { - TokError("could not get type for !subst"); - return 0; - } - Type = RHSt->getType(); - break; - } - } - return (TernOpInit::get(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() { - 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 ::= CODEFRAGMENT -/// SimpleValue ::= '?' -/// SimpleValue ::= '{' ValueList '}' -/// SimpleValue ::= ID '<' ValueListNE '>' -/// SimpleValue ::= '[' ValueList ']' -/// SimpleValue ::= '(' IDValue DagArgList ')' -/// SimpleValue ::= CONCATTOK '(' Value ',' Value ')' -/// SimpleValue ::= SHLTOK '(' Value ',' Value ')' -/// SimpleValue ::= SRATOK '(' Value ',' Value ')' -/// SimpleValue ::= SRLTOK '(' Value ',' Value ')' -/// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')' -/// -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 = 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 = StringInit::get(Val); - break; - } - case tgtok::CodeFragment: - R = CodeInit::get |