summaryrefslogtreecommitdiffstats
path: root/utils/TableGen/TGParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/TableGen/TGParser.cpp')
-rw-r--r--utils/TableGen/TGParser.cpp2152
1 files changed, 0 insertions, 2152 deletions
diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp
deleted file mode 100644
index 59097f9..0000000
--- a/utils/TableGen/TGParser.cpp
+++ /dev/null
@@ -1,2152 +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(new BitsRecTy(BitList.size()));
- if (BI == 0) {
- V->convertInitializerTo(new BitsRecTy(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);
-
- BitsInit *NewVal = new BitsInit(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))
- return Error(Loc, "Cannot set bit #" + utostr(Bit) + " of value '" +
- ValName + "' more than once");
- NewVal->setBit(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));
-
- V = NewVal;
- }
-
- 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 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::Id:
- if (Record *R = ParseClassID()) return new RecordRecTy(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 new BitsRecTy(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 new ListRecTy(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 new VarInit(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());
- }
- }
-
- 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());
- }
- }
-
- if (Record *D = Records.getDef(Name))
- return new DefInit(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 = 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::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 = new ListRecTy(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 (new UnOpInit(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 = new DagRecTy(); break;
- case tgtok::XSRA: Code = BinOpInit::SRA; Type = new IntRecTy(); break;
- case tgtok::XSRL: Code = BinOpInit::SRL; Type = new IntRecTy(); break;
- case tgtok::XSHL: Code = BinOpInit::SHL; Type = new IntRecTy(); break;
- case tgtok::XEq: Code = BinOpInit::EQ; Type = new BitRecTy(); break;
- case tgtok::XStrConcat:
- Code = BinOpInit::STRCONCAT;
- Type = new StringRecTy();
- 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 = (new BinOpInit(Code, InitList.back(), RHS, Type))
- ->Fold(CurRec, CurMultiClass);
- InitList.back() = RHS;
- }
- }
-
- if (InitList.size() == 2)
- return (new BinOpInit(Code, InitList[0], InitList[1], Type))
- ->Fold(CurRec, CurMultiClass);
-
- Error(OpLoc, "expected two operands to operator");
- return 0;
- }
-
- case tgtok::XIf:
- 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 = new BitRecTy();
- break;
- } else {
- BitInit *MHSbit = dynamic_cast<BitInit*>(MHS);
- BitInit *RHSbit = dynamic_cast<BitInit*>(RHS);
-
- if (MHSbit && RHSbit) {
- Type = new BitRecTy();
- break;
- }
- }
- } else if (MHSt != 0 && RHSt != 0) {
- MHSTy = MHSt->getType();
- RHSTy = RHSt->getType();
- }
-
- if (!MHSTy || !RHSTy) {
- TokError("could not get type for !if");
- return 0;
- }
-
- if (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 (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() {
- 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 = new IntInit(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);
- break;
- }
- case tgtok::CodeFragment:
- R = new CodeInit(Lex.getCurStrVal());
- Lex.Lex();
- break;
- case tgtok::question:
- R = new UnsetInit();
- Lex.Lex();
- break;
- case tgtok::Id: {
- SMLoc NameLoc = Lex.getLoc();
- std::string Name = Lex.getCurStrVal();
- 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;
- }
-
- // This is a CLASS<initvalslist> expression. This is supposed to synthesize
- // a new anonymous definition, deriving from CLASS<initvalslist> with no
- // body.
- Record *Class = Records.getClass(Name);
- if (!Class) {
- Error(NameLoc, "Expected a class name, got '" + Name + "'");
- return 0;
- }
-
- std::vector<Init*> 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,
- Records);
- SubClassReference SCRef;
- SCRef.RefLoc = NameLoc;
- SCRef.Rec = Class;
- SCRef.TemplateArgs = ValueList;
- // Add info about the subclass to NewRec.
- if (AddSubClass(NewRec, SCRef))
- return 0;
- NewRec->resolveReferences();
- Records.addDef(NewRec);
-
- // The result of the expression is a reference to the new record.
- return new DefInit(NewRec);
- }
- case tgtok::l_brace: { // Value ::= '{' ValueList '}'
- SMLoc BraceLoc = Lex.getLoc();
- Lex.Lex(); // eat the '{'
- std::vector<Init*> Vals;
-
- if (Lex.getCode() != tgtok::r_brace) {
- Vals = ParseValueList(CurRec);
- if (Vals.empty()) return 0;
- }
- if (Lex.getCode() != tgtok::r_brace) {
- TokError("expected '}' at end of bit list value");
- return 0;
- }
- Lex.Lex(); // eat the '}'
-
- BitsInit *Result = new BitsInit(Vals.size());
- for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
- Init *Bit = Vals[i]->convertInitializerTo(new BitRecTy());
- 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);
- }
- return Result;
- }
- case tgtok::l_square: { // Value ::= '[' ValueList ']'
- Lex.Lex(); // eat the '['
- std::vector<Init*> Vals;
-
- RecTy *DeducedEltTy = 0;
- ListRecTy *GivenListTy = 0;
-
- if (ItemType != 0) {
- ListRecTy *ListType = dynamic_cast<ListRecTy*>(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, 0,
- GivenListTy ? GivenListTy->getElementType() : 0);
- if (Vals.empty()) return 0;
- }
- if (Lex.getCode() != tgtok::r_square) {
- TokError("expected ']' at end of list value");
- return 0;
- }
- Lex.Lex(); // eat the ']'
-
- 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<Init *>::iterator i = Vals.begin(), ie = Vals.end();
- i != ie;
- ++i) {
- TypedInit *TArg = dynamic_cast<TypedInit*>(*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 '('
- if (Lex.getCode() != tgtok::Id && Lex.getCode() != tgtok::XCast) {
- TokError("expected identifier in dag init");
- return 0;
- }
-
- Init *Operator = ParseValue(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<std::pair<llvm::Init*, std::string> > 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);
- }
-
- case tgtok::XHead:
- case tgtok::XTail:
- case tgtok::XEmpty:
- case tgtok::XCast: // Value ::= !unop '(' Value ')'
- case tgtok::XConcat:
- case tgtok::XSRA:
- case tgtok::XSRL:
- case tgtok::XSHL:
- case tgtok::XEq:
- case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')'
- case tgtok::XIf:
- case tgtok::XForEach:
- case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
- return ParseOperation(CurRec);
- }
- }
-
- return R;
-}
-
-/// ParseValue - Parse a tblgen value. This returns null on error.
-///
-/// Value ::= SimpleValue ValueSuffix*
-/// ValueSuffix ::= '{' BitList '}'
-/// ValueSuffix ::= '[' BitList ']'
-/// ValueSuffix ::= '.' ID
-///
-Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType) {
- 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: {
- SMLoc CurlyLoc = Lex.getLoc();
- Lex.Lex(); // eat the '{'
- std::vector<unsigned> Ranges = ParseRangeList();
- if (Ranges.empty()) return 0;
-
- // Reverse the bitlist.
- std::reverse(Ranges.begin(), Ranges.end());
- Result = Result->convertInitializerBitRange(Ranges);
- if (Result == 0) {
- 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");
- return 0;
- }
- Lex.Lex();
- break;
- }
- case tgtok::l_square: {
- SMLoc SquareLoc = Lex.getLoc();
- Lex.Lex(); // eat the '['
- std::vector<unsigned> 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");
- return 0;
- }
- Lex.Lex();
- break;
- }
- case tgtok::period:
- if (Lex.Lex() != tgtok::Id) { // eat the .
- TokError("expected field identifier after '.'");
- return 0;
- }
- if (!Result->getFieldType(Lex.getCurStrVal())) {
- TokError("Cannot access field '" + Lex.getCurStrVal() + "' of value '" +
- Result->getAsString() + "'");
- return 0;
- }
- Result = new FieldInit(Result, Lex.getCurStrVal());
- Lex.Lex(); // eat field name
- break;
- }
- }
-}
-
-/// ParseDagArgList - Parse the argument list for a dag literal expression.
-///
-/// ParseDagArgList ::= Value (':' VARNAME)?
-/// ParseDagArgList ::= ParseDagArgList ',' Value (':' VARNAME)?
-std::vector<std::pair<llvm::Init*, std::string> >
-TGParser::ParseDagArgList(Record *CurRec) {
- std::vector<std::pair<llvm::Init*, std::string> > Result;
-
- while (1) {
- Init *Val = ParseValue(CurRec);
- if (Val == 0) return std::vector<std::pair<llvm::Init*, std::string> >();
-
- // 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<std::pair<llvm::Init*, std::string> >();
- }
- 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 ','
- }
-
- return Result;
-}
-
-
-/// ParseValueList - Parse a comma separated list of values, returning them as a
-/// vector. Note that this always expects to be able to parse at least one
-/// value. It returns an empty list if this is not possible.
-///
-/// ValueList ::= Value (',' Value)
-///
-std::vector<Init*> TGParser::ParseValueList(Record *CurRec, Record *ArgsRec,
- RecTy *EltTy) {
- std::vector<Init*> Result;
- RecTy *ItemType = EltTy;
- unsigned int ArgN = 0;
- if (ArgsRec != 0 && EltTy == 0) {
- const std::vector<std::string> &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<Init*>();
-
- while (Lex.getCode() == tgtok::comma) {
- Lex.Lex(); // Eat the comma
-
- if (ArgsRec != 0 && EltTy == 0) {
- const std::vector<std::string> &TArgs = ArgsRec->getTemplateArgs();
- if (ArgN >= TArgs.size()) {
- TokError("too many template arguments");
- return std::vector<Init*>();
- }
- 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<Init*>();
- }
-
- 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
-/// CurRec will be non-null) and within the template args for a multiclass (in
-/// which case CurRec will be null, but CurMultiClass will be set). This can
-/// also happen within a def that is within a multiclass, which will set both
-/// CurRec and CurMultiClass.
-///
-/// Declaration ::= FIELD? Type ID ('=' Value)?
-///
-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 "";
- }
-
- SMLoc IdLoc = Lex.getLoc();
- std::string DeclName = Lex.getCurStrVal();
- Lex.Lex();
-
- if (ParsingTemplateArgs) {
- if (CurRec) {
- DeclName = CurRec->getName() + ":" + DeclName;
- } else {
- assert(CurMultiClass);
- }
- 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();
- SMLoc ValLoc = Lex.getLoc();
- Init *Val = ParseValue(CurRec, Type);
- if (Val == 0 ||
- SetValue(CurRec, ValLoc, DeclName, std::vector<unsigned>(), Val))
- return "";
- }
-
- return DeclName;
-}
-
-/// ParseTemplateArgList - Read a template argument list, which is a non-empty
-/// sequence of template-declarations in <>'s. If CurRec is non-null, these are
-/// template args for a def, which may or may not be in a multiclass. If null,
-/// 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 '>'.
- return false;
-}
-
-
-/// ParseBodyItem - Parse a single item at within the body of a def or class.
-///
-/// BodyItem ::= Declaration ';'
-/// BodyItem ::= LET ID OptionalBitList '=' Value ';'
-bool TGParser::ParseBodyItem(Record *CurRec) {
- if (Lex.getCode() != tgtok::Let) {
- if (ParseDeclaration(CurRec, false).empty())
- return true;
-
- if (Lex.getCode() != tgtok::semi)
- return TokError("expected ';' after declaration");
- Lex.Lex();
- return false;
- }
-
- // LET ID OptionalRangeList '=' Value ';'
- if (Lex.Lex() != tgtok::Id)
- return TokError("expected field identifier after let");
-
- SMLoc IdLoc = Lex.getLoc();
- std::string FieldName = Lex.getCurStrVal();
- Lex.Lex(); // eat the field name.
-
- std::vector<unsigned> 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 '='.
-
- 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)
- return TokError("expected ';' after let expression");
- Lex.Lex();
-
- return SetValue(CurRec, IdLoc, FieldName, BitList, Val);
-}
-
-/// ParseBody - Read the body of a class or def. Return true on error, false on
-/// success.
-///
-/// Body ::= ';'
-/// Body ::= '{' BodyList '}'
-/// BodyList BodyItem*
-///
-bool TGParser::ParseBody(Record *CurRec) {
- // If this is a null definition, just eat the semi and return.
- if (Lex.getCode() == tgtok::semi) {
- 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;
-
- // Eat the '}'.
- Lex.Lex();
- return false;
-}
-
-/// ParseObjectBody - Parse the body of a def or class. This consists of an
-/// optional ClassList followed by a Body. CurRec is the current def or class
-/// that is being parsed.
-///
-/// ObjectBody ::= BaseClassList Body
-/// BaseClassList ::= /*empty*/
-/// BaseClassList ::= ':' BaseClassListNE
-/// BaseClassListNE ::= SubClassRef (',' SubClassRef)*
-///
-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);
- }
- }
-
- // 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;
-
- 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
-///
-bool TGParser::ParseDef(MultiClass *CurMultiClass) {
- SMLoc DefLoc = Lex.getLoc();
- assert(Lex.getCode() == tgtok::Def && "Unknown tok");
- Lex.Lex(); // Eat the 'def' token.
-
- // Parse ObjectName and make a record for it.
- Record *CurRec = new Record(ParseObjectName(), DefLoc, 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 true;
- }
- Records.addDef(CurRec);
- } else {
- // Otherwise, a def inside a multiclass, add it to the multiclass.
- for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); i != e; ++i)
- if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
- Error(DefLoc, "def '" + CurRec->getName() +
- "' already defined in this multiclass!");
- return true;
- }
- CurMultiClass->DefPrototypes.push_back(CurRec);
- }
-
- if (ParseObjectBody(CurRec))
- 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?");
-
- if (CurMultiClass) {
- // Copy the template arguments for the multiclass into the def.
- const std::vector<std::string> &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;
-}
-
-
-/// ParseClass - Parse a tblgen class definition.
-///
-/// ClassInst ::= CLASS ID TemplateArgList? ObjectBody
-///
-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.
- if (!CurRec->getValues().empty() ||
- !CurRec->getSuperClasses().empty() ||
- !CurRec->getTemplateArgs().empty())
- 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(), Records);
- Records.addClass(CurRec);
- }
- Lex.Lex(); // eat the name.
-
- // If there are template args, parse them.
- if (Lex.getCode() == tgtok::less)
- if (ParseTemplateArgList(CurRec))
- return true;
-
- // Finally, parse the object body.
- return ParseObjectBody(CurRec);
-}
-
-/// ParseLetList - Parse a non-empty list of assignment expressions into a list
-/// of LetRecords.
-///
-/// LetList ::= LetItem (',' LetItem)*
-/// LetItem ::= ID OptionalRangeList '=' Value
-///
-std::vector<LetRecord> TGParser::ParseLetList() {
- std::vector<LetRecord> Result;
-
- while (1) {
- if (Lex.getCode() != tgtok::Id) {
- TokError("expected identifier in let definition");
- return std::vector<LetRecord>();
- }
- std::string Name = Lex.getCurStrVal();
- SMLoc NameLoc = Lex.getLoc();
- Lex.Lex(); // Eat the identifier.
-
- // Check for an optional RangeList.
- std::vector<unsigned> Bits;
- if (ParseOptionalRangeList(Bits))
- return std::vector<LetRecord>();
- std::reverse(Bits.begin(), Bits.end());
-
- if (Lex.getCode() != tgtok::equal) {
- TokError("expected '=' in let expression");
- return std::vector<LetRecord>();
- }
- Lex.Lex(); // eat the '='.
-
- Init *Val = ParseValue(0);
- if (Val == 0) return std::vector<LetRecord>();
-
- // 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.
- }
-}
-
-/// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of
-/// different related productions. This works inside multiclasses too.
-///
-/// Object ::= LET LetList IN '{' ObjectList '}'
-/// Object ::= LET LetList IN Object
-///
-bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
- assert(Lex.getCode() == tgtok::Let && "Unexpected token");
- Lex.Lex();
-
- // Add this entry to the let stack.
- std::vector<LetRecord> LetInfo = ParseLetList();
- if (LetInfo.empty()) return true;
- LetStack.push_back(LetInfo);
-
- 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(CurMultiClass))
- return true;
- } else { // Object ::= LETCommand '{' ObjectList '}'
- SMLoc BraceLoc = Lex.getLoc();
- // Otherwise, this is a group let.
- Lex.Lex(); // eat the '{'.
-
- // Parse the object list.
- 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;
-}
-
-/// ParseMultiClass - Parse a multiclass definition.
-///
-/// MultiClassInst ::= MULTICLASS ID TemplateArgList?
-/// ':' BaseMultiClassList '{' MultiClassDef+ '}'
-///
-bool TGParser::ParseMultiClass() {
- assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token");
- Lex.Lex(); // Eat the multiclass token.
-
- 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(), Records);
- Lex.Lex(); // Eat the identifier.
-
- // If there are template args, parse them.
- if (Lex.getCode() == tgtok::less)
- if (ParseTemplateArgList(0))
- return true;
-
- bool inherits = false;
-
- // If there are submulticlasses, parse them.
- if (Lex.getCode() == tgtok::colon) {
- inherits = true;
-
- 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) {
- 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;
-}
-
-/// ParseDefm - Parse the instantiation of a multiclass.
-///
-/// DefMInst ::= DEFM ID ':' DefmSubClassRef ';'
-///
-bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
- assert(Lex.getCode() == tgtok::Defm && "Unexpected token!");
-
- 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<Record*> NewRecDefs;
-
- // This record also inherits from a regular class (non-multiclass)?
- bool InheritFromClass = false;
-
- // eat the colon.
- Lex.Lex();
-
- SMLoc SubClassLoc = Lex.getLoc();
- SubClassReference Ref = ParseSubClassReference(0, true);
-
- 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<Init*> &TemplateVals = Ref.TemplateArgs;
-
- // Verify that the correct number of template arguments were specified.
- const std::vector<std::string> &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. 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();
- 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, Records);
-
- 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<unsigned>(),
- 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() + "'");
- }
- }
-
- // 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() + "'");
-
- // 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<std::string> &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;
-}
-
-/// ParseObject
-/// Object ::= ClassInst
-/// Object ::= DefInst
-/// Object ::= MultiClassInst
-/// Object ::= DefMInst
-/// Object ::= LETCommand '{' ObjectList '}'
-/// Object ::= LETCommand Object
-bool TGParser::ParseObject(MultiClass *MC) {
- switch (Lex.getCode()) {
- 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();
- }
-}
-
-/// ParseObjectList
-/// ObjectList :== Object*
-bool TGParser::ParseObjectList(MultiClass *MC) {
- while (isObjectStart(Lex.getCode())) {
- 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");
-}
-
OpenPOWER on IntegriCloud