diff options
Diffstat (limited to 'contrib/llvm/lib/TableGen')
-rw-r--r-- | contrib/llvm/lib/TableGen/Error.cpp | 4 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/Record.cpp | 173 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/TGLexer.cpp | 57 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/TGLexer.h | 6 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/TGParser.cpp | 554 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/TGParser.h | 73 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/TableGenAction.cpp | 15 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/TableGenBackend.cpp | 4 |
8 files changed, 706 insertions, 180 deletions
diff --git a/contrib/llvm/lib/TableGen/Error.cpp b/contrib/llvm/lib/TableGen/Error.cpp index 5b2cbbf..5071ee7 100644 --- a/contrib/llvm/lib/TableGen/Error.cpp +++ b/contrib/llvm/lib/TableGen/Error.cpp @@ -21,11 +21,11 @@ namespace llvm { SourceMgr SrcMgr; void PrintError(SMLoc ErrorLoc, const Twine &Msg) { - SrcMgr.PrintMessage(ErrorLoc, Msg, "error"); + SrcMgr.PrintMessage(ErrorLoc, SourceMgr::DK_Error, Msg); } void PrintError(const char *Loc, const Twine &Msg) { - SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error"); + SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), SourceMgr::DK_Error, Msg); } void PrintError(const Twine &Msg) { diff --git a/contrib/llvm/lib/TableGen/Record.cpp b/contrib/llvm/lib/TableGen/Record.cpp index b7c51ca..93eed24 100644 --- a/contrib/llvm/lib/TableGen/Record.cpp +++ b/contrib/llvm/lib/TableGen/Record.cpp @@ -18,6 +18,7 @@ #include "llvm/Support/Format.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" @@ -29,6 +30,8 @@ using namespace llvm; // std::string wrapper for DenseMap purposes //===----------------------------------------------------------------------===// +namespace llvm { + /// TableGenStringKey - This is a wrapper for std::string suitable for /// using as a key to a DenseMap. Because there isn't a particularly /// good way to indicate tombstone or empty keys for strings, we want @@ -43,14 +46,16 @@ public: TableGenStringKey(const char *str) : data(str) {} const std::string &str() const { return data; } - + + friend hash_code hash_value(const TableGenStringKey &Value) { + using llvm::hash_value; + return hash_value(Value.str()); + } private: std::string data; }; /// Specialize DenseMapInfo for TableGenStringKey. -namespace llvm { - template<> struct DenseMapInfo<TableGenStringKey> { static inline TableGenStringKey getEmptyKey() { TableGenStringKey Empty("<<<EMPTY KEY>>>"); @@ -61,7 +66,8 @@ template<> struct DenseMapInfo<TableGenStringKey> { return Tombstone; } static unsigned getHashValue(const TableGenStringKey& Val) { - return HashString(Val.str()); + using llvm::hash_value; + return hash_value(Val); } static bool isEqual(const TableGenStringKey& LHS, const TableGenStringKey& RHS) { @@ -69,7 +75,7 @@ template<> struct DenseMapInfo<TableGenStringKey> { } }; -} +} // namespace llvm //===----------------------------------------------------------------------===// // Type implementations @@ -78,9 +84,9 @@ template<> struct DenseMapInfo<TableGenStringKey> { BitRecTy BitRecTy::Shared; IntRecTy IntRecTy::Shared; StringRecTy StringRecTy::Shared; -CodeRecTy CodeRecTy::Shared; DagRecTy DagRecTy::Shared; +void RecTy::anchor() { } void RecTy::dump() const { print(errs()); } ListRecTy *RecTy::getListTy() { @@ -315,12 +321,6 @@ Init *ListRecTy::convertValue(TypedInit *TI) { return 0; } -Init *CodeRecTy::convertValue(TypedInit *TI) { - if (TI->getType()->typeIsConvertibleTo(this)) - return TI; - return 0; -} - Init *DagRecTy::convertValue(TypedInit *TI) { if (TI->getType()->typeIsConvertibleTo(this)) return TI; @@ -444,13 +444,18 @@ RecTy *llvm::resolveTypes(RecTy *T1, RecTy *T2) { // Initializer implementations //===----------------------------------------------------------------------===// +void Init::anchor() { } void Init::dump() const { return print(errs()); } +void UnsetInit::anchor() { } + UnsetInit *UnsetInit::get() { static UnsetInit TheInit; return &TheInit; } +void BitInit::anchor() { } + BitInit *BitInit::get(bool V) { static BitInit True(true); static BitInit False(false); @@ -565,7 +570,9 @@ IntInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) const { return BitsInit::get(NewBits); } -StringInit *StringInit::get(const std::string &V) { +void StringInit::anchor() { } + +StringInit *StringInit::get(StringRef V) { typedef StringMap<StringInit *> Pool; static Pool ThePool; @@ -574,15 +581,6 @@ StringInit *StringInit::get(const std::string &V) { return I; } -CodeInit *CodeInit::get(const std::string &V) { - typedef StringMap<CodeInit *> Pool; - static Pool ThePool; - - CodeInit *&I = ThePool[V]; - if (!I) I = new CodeInit(V); - return I; -} - static void ProfileListInit(FoldingSetNodeID &ID, ArrayRef<Init *> Range, RecTy *EltTy) { @@ -735,7 +733,6 @@ UnOpInit *UnOpInit::get(UnaryOp opc, Init *lhs, RecTy *Type) { Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { switch (getOpcode()) { - default: assert(0 && "Unknown unop"); case CAST: { if (getType()->getAsString() == "string") { StringInit *LHSs = dynamic_cast<StringInit*>(LHS); @@ -747,6 +744,11 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { if (LHSd) { return StringInit::get(LHSd->getDef()->getName()); } + + IntInit *LHSi = dynamic_cast<IntInit*>(LHS); + if (LHSi) { + return StringInit::get(LHSi->getAsString()); + } } else { StringInit *LHSs = dynamic_cast<StringInit*>(LHS); if (LHSs) { @@ -760,7 +762,9 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { return VarInit::get(Name, RV->getType()); } - std::string TemplateArgName = CurRec->getName()+":"+Name; + Init *TemplateArgName = QualifyName(*CurRec, CurMultiClass, Name, + ":"); + if (CurRec->isTemplateArg(TemplateArgName)) { const RecordVal *RV = CurRec->getValue(TemplateArgName); assert(RV && "Template arg doesn't exist??"); @@ -773,7 +777,8 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { } if (CurMultiClass) { - std::string MCName = CurMultiClass->Rec.getName()+"::"+Name; + Init *MCName = QualifyName(CurMultiClass->Rec, CurMultiClass, Name, "::"); + if (CurMultiClass->Rec.isTemplateArg(MCName)) { const RecordVal *RV = CurMultiClass->Rec.getValue(MCName); assert(RV && "Template arg doesn't exist??"); @@ -885,7 +890,6 @@ BinOpInit *BinOpInit::get(BinaryOp opc, Init *lhs, Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { switch (getOpcode()) { - default: assert(0 && "Unknown binop"); case CONCAT: { DagInit *LHSs = dynamic_cast<DagInit*>(LHS); DagInit *RHSs = dynamic_cast<DagInit*>(RHS); @@ -944,7 +948,7 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue(); int64_t Result; switch (getOpcode()) { - default: assert(0 && "Bad opcode!"); + default: llvm_unreachable("Bad opcode!"); case SHL: Result = LHSv << RHSv; break; case SRA: Result = LHSv >> RHSv; break; case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break; @@ -1134,7 +1138,6 @@ static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { switch (getOpcode()) { - default: assert(0 && "Unknown binop"); case SUBST: { DefInit *LHSd = dynamic_cast<DefInit*>(LHS); VarInit *LHSv = dynamic_cast<VarInit*>(LHS); @@ -1298,7 +1301,12 @@ TypedInit::convertInitListSlice(const std::vector<unsigned> &Elements) const { VarInit *VarInit::get(const std::string &VN, RecTy *T) { - typedef std::pair<RecTy *, TableGenStringKey> Key; + Init *Value = StringInit::get(VN); + return VarInit::get(Value, T); +} + +VarInit *VarInit::get(Init *VN, RecTy *T) { + typedef std::pair<RecTy *, Init *> Key; typedef DenseMap<Key, VarInit *> Pool; static Pool ThePool; @@ -1309,12 +1317,19 @@ VarInit *VarInit::get(const std::string &VN, RecTy *T) { return I; } +const std::string &VarInit::getName() const { + StringInit *NameString = + dynamic_cast<StringInit *>(getNameInit()); + assert(NameString && "VarInit name is not a string!"); + return NameString->getValue(); +} + Init *VarInit::resolveBitReference(Record &R, const RecordVal *IRV, unsigned Bit) const { - if (R.isTemplateArg(getName())) return 0; - if (IRV && IRV->getName() != getName()) return 0; + if (R.isTemplateArg(getNameInit())) return 0; + if (IRV && IRV->getNameInit() != getNameInit()) return 0; - RecordVal *RV = R.getValue(getName()); + RecordVal *RV = R.getValue(getNameInit()); assert(RV && "Reference to a non-existent variable?"); assert(dynamic_cast<BitsInit*>(RV->getValue())); BitsInit *BI = (BitsInit*)RV->getValue(); @@ -1333,10 +1348,10 @@ Init *VarInit::resolveBitReference(Record &R, const RecordVal *IRV, Init *VarInit::resolveListElementReference(Record &R, const RecordVal *IRV, unsigned Elt) const { - if (R.isTemplateArg(getName())) return 0; - if (IRV && IRV->getName() != getName()) return 0; + if (R.isTemplateArg(getNameInit())) return 0; + if (IRV && IRV->getNameInit() != getNameInit()) return 0; - RecordVal *RV = R.getValue(getName()); + RecordVal *RV = R.getValue(getNameInit()); assert(RV && "Reference to a non-existent variable?"); ListInit *LI = dynamic_cast<ListInit*>(RV->getValue()); if (!LI) { @@ -1659,7 +1674,7 @@ void RecordVal::dump() const { errs() << *this; } void RecordVal::print(raw_ostream &OS, bool PrintSem) const { if (getPrefix()) OS << "field "; - OS << *getType() << " " << getName(); + OS << *getType() << " " << getNameInitAsString(); if (getValue()) OS << " = " << *getValue(); @@ -1669,13 +1684,22 @@ void RecordVal::print(raw_ostream &OS, bool PrintSem) const { unsigned Record::LastID = 0; +void Record::init() { + checkName(); + + // Every record potentially has a def at the top. This value is + // replaced with the top-level def name at instantiation time. + RecordVal DN("NAME", StringRecTy::get(), 0); + addValue(DN); +} + void Record::checkName() { // Ensure the record name has string type. const TypedInit *TypedName = dynamic_cast<const TypedInit *>(Name); assert(TypedName && "Record name is not typed!"); RecTy *Type = TypedName->getType(); if (dynamic_cast<StringRecTy *>(Type) == 0) { - llvm_unreachable("Record name is not a string!"); + throw "Record name is not a string!"; } } @@ -1695,20 +1719,13 @@ const std::string &Record::getName() const { void Record::setName(Init *NewName) { if (TrackedRecords.getDef(Name->getAsUnquotedString()) == this) { TrackedRecords.removeDef(Name->getAsUnquotedString()); - Name = NewName; TrackedRecords.addDef(this); - } else { + } else if (TrackedRecords.getClass(Name->getAsUnquotedString()) == this) { TrackedRecords.removeClass(Name->getAsUnquotedString()); - Name = NewName; TrackedRecords.addClass(this); - } + } // Otherwise this isn't yet registered. + Name = NewName; checkName(); - // Since the Init for the name was changed, see if we can resolve - // any of it using members of the Record. - Init *ComputedName = Name->resolveReferences(*this, 0); - if (ComputedName != Name) { - setName(ComputedName); - } // DO NOT resolve record values to the name at this point because // there might be default values for arguments of this def. Those // arguments might not have been resolved yet so we don't want to @@ -1731,17 +1748,25 @@ void Record::setName(const std::string &Name) { /// references. void Record::resolveReferencesTo(const RecordVal *RV) { for (unsigned i = 0, e = Values.size(); i != e; ++i) { + if (RV == &Values[i]) // Skip resolve the same field as the given one + continue; if (Init *V = Values[i].getValue()) Values[i].setValue(V->resolveReferences(*this, RV)); } + Init *OldName = getNameInit(); + Init *NewName = Name->resolveReferences(*this, RV); + if (NewName != OldName) { + // Re-register with RecordKeeper. + setName(NewName); + } } void Record::dump() const { errs() << *this; } raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) { - OS << R.getName(); + OS << R.getNameInitAsString(); - const std::vector<std::string> &TArgs = R.getTemplateArgs(); + const std::vector<Init *> &TArgs = R.getTemplateArgs(); if (!TArgs.empty()) { OS << "<"; for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { @@ -1758,7 +1783,7 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) { if (!SC.empty()) { OS << "\t//"; for (unsigned i = 0, e = SC.size(); i != e; ++i) - OS << " " << SC[i]->getName(); + OS << " " << SC[i]->getNameInitAsString(); } OS << "\n"; @@ -1954,18 +1979,6 @@ DagInit *Record::getValueAsDag(StringRef FieldName) const { "' does not have a dag initializer!"; } -std::string Record::getValueAsCode(StringRef FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; - - if (CodeInit *CI = dynamic_cast<CodeInit*>(R->getValue())) - return CI->getValue(); - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a code initializer!"; -} - void MultiClass::dump() const { errs() << "Record:\n"; @@ -2017,3 +2030,39 @@ RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const { return Defs; } +/// QualifyName - Return an Init with a qualifier prefix referring +/// to CurRec's name. +Init *llvm::QualifyName(Record &CurRec, MultiClass *CurMultiClass, + Init *Name, const std::string &Scoper) { + RecTy *Type = dynamic_cast<TypedInit *>(Name)->getType(); + + BinOpInit *NewName = + BinOpInit::get(BinOpInit::STRCONCAT, + BinOpInit::get(BinOpInit::STRCONCAT, + CurRec.getNameInit(), + StringInit::get(Scoper), + Type)->Fold(&CurRec, CurMultiClass), + Name, + Type); + + if (CurMultiClass && Scoper != "::") { + NewName = + BinOpInit::get(BinOpInit::STRCONCAT, + BinOpInit::get(BinOpInit::STRCONCAT, + CurMultiClass->Rec.getNameInit(), + StringInit::get("::"), + Type)->Fold(&CurRec, CurMultiClass), + NewName->Fold(&CurRec, CurMultiClass), + Type); + } + + return NewName->Fold(&CurRec, CurMultiClass); +} + +/// QualifyName - Return an Init with a qualifier prefix referring +/// to CurRec's name. +Init *llvm::QualifyName(Record &CurRec, MultiClass *CurMultiClass, + const std::string &Name, + const std::string &Scoper) { + return QualifyName(CurRec, CurMultiClass, StringInit::get(Name), Scoper); +} diff --git a/contrib/llvm/lib/TableGen/TGLexer.cpp b/contrib/llvm/lib/TableGen/TGLexer.cpp index 8c1b429..ff322e7 100644 --- a/contrib/llvm/lib/TableGen/TGLexer.cpp +++ b/contrib/llvm/lib/TableGen/TGLexer.cpp @@ -15,7 +15,6 @@ #include "llvm/TableGen/Error.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Config/config.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include <cctype> @@ -23,6 +22,9 @@ #include <cstdlib> #include <cstring> #include <cerrno> + +#include "llvm/Config/config.h" // for strtoull()/strtoll() define + using namespace llvm; TGLexer::TGLexer(SourceMgr &SM) : SrcMgr(SM) { @@ -80,6 +82,10 @@ int TGLexer::getNextChar() { } } +int TGLexer::peekNextChar(int Index) { + return *(CurPtr + Index); +} + tgtok::TokKind TGLexer::LexToken() { TokStart = CurPtr; // This always consumes at least one character. @@ -87,10 +93,10 @@ tgtok::TokKind TGLexer::LexToken() { switch (CurChar) { default: - // Handle letters: [a-zA-Z_#] - if (isalpha(CurChar) || CurChar == '_' || CurChar == '#') + // Handle letters: [a-zA-Z_] + if (isalpha(CurChar) || CurChar == '_') return LexIdentifier(); - + // Unknown character, emit an error. return ReturnError(TokStart, "Unexpected character"); case EOF: return tgtok::Eof; @@ -107,6 +113,7 @@ tgtok::TokKind TGLexer::LexToken() { case ')': return tgtok::r_paren; case '=': return tgtok::equal; case '?': return tgtok::question; + case '#': return tgtok::paste; case 0: case ' ': @@ -128,8 +135,44 @@ tgtok::TokKind TGLexer::LexToken() { return LexToken(); case '-': case '+': case '0': case '1': case '2': case '3': case '4': case '5': case '6': - case '7': case '8': case '9': + case '7': case '8': case '9': { + int NextChar = 0; + if (isdigit(CurChar)) { + // Allow identifiers to start with a number if it is followed by + // an identifier. This can happen with paste operations like + // foo#8i. + int i = 0; + do { + NextChar = peekNextChar(i++); + } while (isdigit(NextChar)); + + if (NextChar == 'x' || NextChar == 'b') { + // If this is [0-9]b[01] or [0-9]x[0-9A-fa-f] this is most + // likely a number. + int NextNextChar = peekNextChar(i); + switch (NextNextChar) { + default: + break; + case '0': case '1': + if (NextChar == 'b') + return LexNumber(); + // Fallthrough + case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + if (NextChar == 'x') + return LexNumber(); + break; + } + } + } + + if (isalpha(NextChar) || NextChar == '_') + return LexIdentifier(); + return LexNumber(); + } case '"': return LexString(); case '$': return LexVarName(); case '[': return LexBracket(); @@ -210,8 +253,7 @@ tgtok::TokKind TGLexer::LexIdentifier() { const char *IdentStart = TokStart; // Match the rest of the identifier regex: [0-9a-zA-Z_#]* - while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_' || - *CurPtr == '#') + while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_') ++CurPtr; // Check to see if this identifier is a keyword. @@ -232,6 +274,7 @@ tgtok::TokKind TGLexer::LexIdentifier() { .Case("dag", tgtok::Dag) .Case("class", tgtok::Class) .Case("def", tgtok::Def) + .Case("foreach", tgtok::Foreach) .Case("defm", tgtok::Defm) .Case("multiclass", tgtok::MultiClass) .Case("field", tgtok::Field) diff --git a/contrib/llvm/lib/TableGen/TGLexer.h b/contrib/llvm/lib/TableGen/TGLexer.h index 84d328b..8a850b5 100644 --- a/contrib/llvm/lib/TableGen/TGLexer.h +++ b/contrib/llvm/lib/TableGen/TGLexer.h @@ -39,9 +39,10 @@ namespace tgtok { colon, semi, // : ; comma, period, // , . equal, question, // = ? - + paste, // # + // Keywords. - Bit, Bits, Class, Code, Dag, Def, Defm, Field, In, Int, Let, List, + Bit, Bits, Class, Code, Dag, Def, Foreach, Defm, Field, In, Int, Let, List, MultiClass, String, // !keywords. @@ -109,6 +110,7 @@ private: tgtok::TokKind ReturnError(const char *Loc, const Twine &Msg); int getNextChar(); + int peekNextChar(int Index); void SkipBCPLComment(); bool SkipCComment(); tgtok::TokKind LexIdentifier(); diff --git a/contrib/llvm/lib/TableGen/TGParser.cpp b/contrib/llvm/lib/TableGen/TGParser.cpp index e7f00ba..04c4fc1 100644 --- a/contrib/llvm/lib/TableGen/TGParser.cpp +++ b/contrib/llvm/lib/TableGen/TGParser.cpp @@ -64,7 +64,7 @@ bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) { if (CurRec == 0) CurRec = &CurMultiClass->Rec; - if (RecordVal *ERV = CurRec->getValue(RV.getName())) { + if (RecordVal *ERV = CurRec->getValue(RV.getNameInit())) { // 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 '" + @@ -79,7 +79,7 @@ bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) { /// SetValue - /// Return true on error, false on success. -bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName, +bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName, const std::vector<unsigned> &BitList, Init *V) { if (!V) return false; @@ -87,13 +87,14 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName, RecordVal *RV = CurRec->getValue(ValName); if (RV == 0) - return Error(Loc, "Value '" + ValName + "' unknown!"); + return Error(Loc, "Value '" + ValName->getAsUnquotedString() + + "' 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) + if (VI->getNameInit() == ValName) return false; // If we are assigning to a subset of the bits in the value... then we must be @@ -103,7 +104,8 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName, if (!BitList.empty()) { BitsInit *CurVal = dynamic_cast<BitsInit*>(RV->getValue()); if (CurVal == 0) - return Error(Loc, "Value '" + ValName + "' is not a bits type"); + return Error(Loc, "Value '" + ValName->getAsUnquotedString() + + "' 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())); @@ -123,7 +125,7 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName, unsigned Bit = BitList[i]; if (NewBits[Bit]) return Error(Loc, "Cannot set bit #" + utostr(Bit) + " of value '" + - ValName + "' more than once"); + ValName->getAsUnquotedString() + "' more than once"); NewBits[Bit] = BInit->getBit(i); } @@ -135,9 +137,10 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName, } if (RV->setValue(V)) - return Error(Loc, "Value '" + ValName + "' of type '" + - RV->getType()->getAsString() + - "' is incompatible with initializer '" + V->getAsString() +"'"); + return Error(Loc, "Value '" + ValName->getAsUnquotedString() + "' of type '" + + RV->getType()->getAsString() + + "' is incompatible with initializer '" + V->getAsString() + + "'"); return false; } @@ -151,7 +154,7 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { if (AddValue(CurRec, SubClass.RefLoc, Vals[i])) return true; - const std::vector<std::string> &TArgs = SC->getTemplateArgs(); + const std::vector<Init *> &TArgs = SC->getTemplateArgs(); // Ensure that an appropriate number of template arguments are specified. if (TArgs.size() < SubClass.TemplateArgs.size()) @@ -174,8 +177,8 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { } 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() + "'!"); + + utostr(i) + " (" + TArgs[i]->getAsUnquotedString() + + ") of subclass '" + SC->getNameInitAsString() + "'!"); } } @@ -230,7 +233,7 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC, CurMC->DefPrototypes.push_back(NewDef); } - const std::vector<std::string> &SMCTArgs = SMC->Rec.getTemplateArgs(); + const std::vector<Init *> &SMCTArgs = SMC->Rec.getTemplateArgs(); // Ensure that an appropriate number of template arguments are // specified. @@ -278,14 +281,121 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC, } 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() + "'!"); + + utostr(i) + " (" + SMCTArgs[i]->getAsUnquotedString() + + ") of subclass '" + SMC->Rec.getNameInitAsString() + "'!"); } } return false; } +/// ProcessForeachDefs - Given a record, apply all of the variable +/// values in all surrounding foreach loops, creating new records for +/// each combination of values. +bool TGParser::ProcessForeachDefs(Record *CurRec, MultiClass *CurMultiClass, + SMLoc Loc) { + // We want to instantiate a new copy of CurRec for each combination + // of nested loop iterator values. We don't want top instantiate + // any copies until we have values for each loop iterator. + IterSet IterVals; + for (LoopVector::iterator Loop = Loops.begin(), LoopEnd = Loops.end(); + Loop != LoopEnd; + ++Loop) { + // Process this loop. + if (ProcessForeachDefs(CurRec, CurMultiClass, Loc, + IterVals, *Loop, Loop+1)) { + Error(Loc, + "Could not process loops for def " + CurRec->getNameInitAsString()); + return true; + } + } + + return false; +} + +/// ProcessForeachDefs - Given a record, a loop and a loop iterator, +/// apply each of the variable values in this loop and then process +/// subloops. +bool TGParser::ProcessForeachDefs(Record *CurRec, MultiClass *CurMultiClass, + SMLoc Loc, IterSet &IterVals, + ForeachLoop &CurLoop, + LoopVector::iterator NextLoop) { + Init *IterVar = CurLoop.IterVar; + ListInit *List = dynamic_cast<ListInit *>(CurLoop.ListValue); + + if (List == 0) { + Error(Loc, "Loop list is not a list"); + return true; + } + + // Process each value. + for (int64_t i = 0; i < List->getSize(); ++i) { + Init *ItemVal = List->resolveListElementReference(*CurRec, 0, i); + IterVals.push_back(IterRecord(IterVar, ItemVal)); + + if (IterVals.size() == Loops.size()) { + // Ok, we have all of the iterator values for this point in the + // iteration space. Instantiate a new record to reflect this + // combination of values. + Record *IterRec = new Record(*CurRec); + + // Set the iterator values now. + for (IterSet::iterator i = IterVals.begin(), iend = IterVals.end(); + i != iend; + ++i) { + VarInit *IterVar = dynamic_cast<VarInit *>(i->IterVar); + if (IterVar == 0) { + Error(Loc, "foreach iterator is unresolved"); + return true; + } + + TypedInit *IVal = dynamic_cast<TypedInit *>(i->IterValue); + if (IVal == 0) { + Error(Loc, "foreach iterator value is untyped"); + return true; + } + + IterRec->addValue(RecordVal(IterVar->getName(), IVal->getType(), false)); + + if (SetValue(IterRec, Loc, IterVar->getName(), + std::vector<unsigned>(), IVal)) { + Error(Loc, "when instantiating this def"); + return true; + } + + // Resolve it next. + IterRec->resolveReferencesTo(IterRec->getValue(IterVar->getName())); + + // Remove it. + IterRec->removeValue(IterVar->getName()); + } + + if (Records.getDef(IterRec->getNameInitAsString())) { + Error(Loc, "def already exists: " + IterRec->getNameInitAsString()); + return true; + } + + Records.addDef(IterRec); + IterRec->resolveReferences(); + } + + if (NextLoop != Loops.end()) { + // Process nested loops. + if (ProcessForeachDefs(CurRec, CurMultiClass, Loc, IterVals, *NextLoop, + NextLoop+1)) { + Error(Loc, + "Could not process loops for def " + + CurRec->getNameInitAsString()); + return true; + } + } + + // We're done with this iterator. + IterVals.pop_back(); + } + return false; +} + //===----------------------------------------------------------------------===// // Parser Code //===----------------------------------------------------------------------===// @@ -293,7 +403,8 @@ 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 || K == tgtok::Foreach; } static std::string GetNewAnonymousName() { @@ -303,18 +414,39 @@ static std::string GetNewAnonymousName() { /// ParseObjectName - If an object name is specified, return it. Otherwise, /// return an anonymous name. -/// ObjectName ::= ID +/// ObjectName ::= Value [ '#' Value ]* /// ObjectName ::= /*empty*/ /// -std::string TGParser::ParseObjectName() { - if (Lex.getCode() != tgtok::Id) - return GetNewAnonymousName(); +Init *TGParser::ParseObjectName(MultiClass *CurMultiClass) { + switch (Lex.getCode()) { + case tgtok::colon: + case tgtok::semi: + case tgtok::l_brace: + // These are all of the tokens that can begin an object body. + // Some of these can also begin values but we disallow those cases + // because they are unlikely to be useful. + return StringInit::get(GetNewAnonymousName()); + default: + break; + } - std::string Ret = Lex.getCurStrVal(); - Lex.Lex(); - return Ret; -} + Record *CurRec = 0; + if (CurMultiClass) + CurRec = &CurMultiClass->Rec; + + RecTy *Type = 0; + if (CurRec) { + const TypedInit *CurRecName = + dynamic_cast<const TypedInit *>(CurRec->getNameInit()); + if (!CurRecName) { + TokError("Record name is not typed!"); + return 0; + } + Type = CurRecName->getType(); + } + return ParseValue(CurRec, Type, ParseNameMode); +} /// ParseClassID - Parse and resolve a reference to a class name. This returns /// null on error. @@ -570,11 +702,11 @@ bool TGParser::ParseOptionalBitList(std::vector<unsigned> &Ranges) { /// ParseType - Parse and return a tblgen type. This returns null on error. /// /// Type ::= STRING // string type +/// Type ::= CODE // code 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 /// @@ -582,9 +714,9 @@ 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::Code: 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); @@ -633,7 +765,7 @@ RecTy *TGParser::ParseType() { /// IDValue ::= ID [multiclass template argument] /// IDValue ::= ID [def name] /// -Init *TGParser::ParseIDValue(Record *CurRec) { +Init *TGParser::ParseIDValue(Record *CurRec, IDParseMode Mode) { assert(Lex.getCode() == tgtok::Id && "Expected ID in ParseIDValue"); std::string Name = Lex.getCurStrVal(); SMLoc Loc = Lex.getLoc(); @@ -644,14 +776,17 @@ Init *TGParser::ParseIDValue(Record *CurRec) { /// ParseIDValue - This is just like ParseIDValue above, but it assumes the ID /// has already been read. Init *TGParser::ParseIDValue(Record *CurRec, - const std::string &Name, SMLoc NameLoc) { + const std::string &Name, SMLoc NameLoc, + IDParseMode Mode) { if (CurRec) { if (const RecordVal *RV = CurRec->getValue(Name)) return VarInit::get(Name, RV->getType()); - std::string TemplateArgName = CurRec->getName()+":"+Name; + Init *TemplateArgName = QualifyName(*CurRec, CurMultiClass, Name, ":"); + if (CurMultiClass) - TemplateArgName = CurMultiClass->Rec.getName()+"::"+TemplateArgName; + TemplateArgName = QualifyName(CurMultiClass->Rec, CurMultiClass, Name, + "::"); if (CurRec->isTemplateArg(TemplateArgName)) { const RecordVal *RV = CurRec->getValue(TemplateArgName); @@ -661,7 +796,9 @@ Init *TGParser::ParseIDValue(Record *CurRec, } if (CurMultiClass) { - std::string MCName = CurMultiClass->Rec.getName()+"::"+Name; + Init *MCName = QualifyName(CurMultiClass->Rec, CurMultiClass, Name, + "::"); + if (CurMultiClass->Rec.isTemplateArg(MCName)) { const RecordVal *RV = CurMultiClass->Rec.getValue(MCName); assert(RV && "Template arg doesn't exist??"); @@ -669,11 +806,27 @@ Init *TGParser::ParseIDValue(Record *CurRec, } } + // If this is in a foreach loop, make sure it's not a loop iterator + for (LoopVector::iterator i = Loops.begin(), iend = Loops.end(); + i != iend; + ++i) { + VarInit *IterVar = dynamic_cast<VarInit *>(i->IterVar); + if (IterVar && IterVar->getName() == Name) + return IterVar; + } + + if (Mode == ParseNameMode) + return StringInit::get(Name); + if (Record *D = Records.getDef(Name)) return DefInit::get(D); - Error(NameLoc, "Variable not defined: '" + Name + "'"); - return 0; + if (Mode == ParseValueMode) { + Error(NameLoc, "Variable not defined: '" + Name + "'"); + return 0; + } + + return StringInit::get(Name); } /// ParseOperation - Parse an operator. This returns null on error. @@ -685,7 +838,6 @@ Init *TGParser::ParseOperation(Record *CurRec) { default: TokError("unknown operation"); return 0; - break; case tgtok::XHead: case tgtok::XTail: case tgtok::XEmpty: @@ -694,7 +846,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { RecTy *Type = 0; switch (Lex.getCode()) { - default: assert(0 && "Unhandled code!"); + default: llvm_unreachable("Unhandled code!"); case tgtok::XCast: Lex.Lex(); // eat the operation Code = UnOpInit::CAST; @@ -810,7 +962,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { RecTy *Type = 0; switch (OpTok) { - default: assert(0 && "Unhandled code!"); + default: llvm_unreachable("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; @@ -874,7 +1026,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { tgtok::TokKind LexCode = Lex.getCode(); Lex.Lex(); // eat the operation switch (LexCode) { - default: assert(0 && "Unhandled code!"); + default: llvm_unreachable("Unhandled code!"); case tgtok::XIf: Code = TernOpInit::IF; break; @@ -919,7 +1071,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { Lex.Lex(); // eat the ')' switch (LexCode) { - default: assert(0 && "Unhandled code!"); + default: llvm_unreachable("Unhandled code!"); case tgtok::XIf: { // FIXME: The `!if' operator doesn't handle non-TypedInit well at // all. This can be made much more robust. @@ -989,8 +1141,6 @@ Init *TGParser::ParseOperation(Record *CurRec) { CurMultiClass); } } - TokError("could not parse operation"); - return 0; } /// ParseOperatorType - Parse a type for an operator. This returns @@ -1041,10 +1191,16 @@ RecTy *TGParser::ParseOperatorType() { /// SimpleValue ::= SRLTOK '(' Value ',' Value ')' /// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')' /// -Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { +Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, + IDParseMode Mode) { Init *R = 0; switch (Lex.getCode()) { default: TokError("Unknown token when parsing a value"); break; + case tgtok::paste: + // This is a leading paste operation. This is deprecated but + // still exists in some .td files. Ignore it. + Lex.Lex(); // Skip '#'. + return ParseSimpleValue(CurRec, ItemType, Mode); case tgtok::IntVal: R = IntInit::get(Lex.getCurIntVal()); Lex.Lex(); break; case tgtok::StrVal: { std::string Val = Lex.getCurStrVal(); @@ -1060,7 +1216,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { break; } case tgtok::CodeFragment: - R = CodeInit::get(Lex.getCurStrVal()); + R = StringInit::get(Lex.getCurStrVal()); Lex.Lex(); break; case tgtok::question: @@ -1071,7 +1227,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { SMLoc NameLoc = Lex.getLoc(); std::string Name = Lex.getCurStrVal(); if (Lex.Lex() != tgtok::less) // consume the Id. - return ParseIDValue(CurRec, Name, NameLoc); // Value ::= IDValue + return ParseIDValue(CurRec, Name, NameLoc, Mode); // Value ::= IDValue // Value ::= ID '<' ValueListNE '>' if (Lex.Lex() == tgtok::greater) { @@ -1305,8 +1461,8 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { /// ValueSuffix ::= '[' BitList ']' /// ValueSuffix ::= '.' ID /// -Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType) { - Init *Result = ParseSimpleValue(CurRec, ItemType); +Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) { + Init *Result = ParseSimpleValue(CurRec, ItemType, Mode); if (Result == 0) return 0; // Parse the suffixes now if present. @@ -1314,6 +1470,10 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType) { switch (Lex.getCode()) { default: return Result; case tgtok::l_brace: { + if (Mode == ParseNameMode || Mode == ParseForeachMode) + // This is the beginning of the object body. + return Result; + SMLoc CurlyLoc = Lex.getLoc(); Lex.Lex(); // eat the '{' std::vector<unsigned> Ranges = ParseRangeList(); @@ -1368,6 +1528,56 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType) { Result = FieldInit::get(Result, Lex.getCurStrVal()); Lex.Lex(); // eat field name break; + + case tgtok::paste: + SMLoc PasteLoc = Lex.getLoc(); + + // Create a !strconcat() operation, first casting each operand to + // a string if necessary. + + TypedInit *LHS = dynamic_cast<TypedInit *>(Result); + if (!LHS) { + Error(PasteLoc, "LHS of paste is not typed!"); + return 0; + } + + if (LHS->getType() != StringRecTy::get()) { + LHS = UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get()); + } + + TypedInit *RHS = 0; + + Lex.Lex(); // Eat the '#'. + switch (Lex.getCode()) { + case tgtok::colon: + case tgtok::semi: + case tgtok::l_brace: + // These are all of the tokens that can begin an object body. + // Some of these can also begin values but we disallow those cases + // because they are unlikely to be useful. + + // Trailing paste, concat with an empty string. + RHS = StringInit::get(""); + break; + + default: + Init *RHSResult = ParseValue(CurRec, ItemType, ParseNameMode); + RHS = dynamic_cast<TypedInit *>(RHSResult); + if (!RHS) { + Error(PasteLoc, "RHS of paste is not typed!"); + return 0; + } + + if (RHS->getType() != StringRecTy::get()) { + RHS = UnOpInit::get(UnOpInit::CAST, RHS, StringRecTy::get()); + } + + break; + } + + Result = BinOpInit::get(BinOpInit::STRCONCAT, LHS, RHS, + StringRecTy::get())->Fold(CurRec, CurMultiClass); + break; } } } @@ -1417,7 +1627,11 @@ std::vector<Init*> TGParser::ParseValueList(Record *CurRec, Record *ArgsRec, RecTy *ItemType = EltTy; unsigned int ArgN = 0; if (ArgsRec != 0 && EltTy == 0) { - const std::vector<std::string> &TArgs = ArgsRec->getTemplateArgs(); + const std::vector<Init *> &TArgs = ArgsRec->getTemplateArgs(); + if (!TArgs.size()) { + TokError("template argument provided to non-template class"); + return std::vector<Init*>(); + } const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]); if (!RV) { errs() << "Cannot find template arg " << ArgN << " (" << TArgs[ArgN] @@ -1434,7 +1648,7 @@ std::vector<Init*> TGParser::ParseValueList(Record *CurRec, Record *ArgsRec, Lex.Lex(); // Eat the comma if (ArgsRec != 0 && EltTy == 0) { - const std::vector<std::string> &TArgs = ArgsRec->getTemplateArgs(); + const std::vector<Init *> &TArgs = ArgsRec->getTemplateArgs(); if (ArgN >= TArgs.size()) { TokError("too many template arguments"); return std::vector<Init*>(); @@ -1462,37 +1676,38 @@ std::vector<Init*> TGParser::ParseValueList(Record *CurRec, Record *ArgsRec, /// /// Declaration ::= FIELD? Type ID ('=' Value)? /// -std::string TGParser::ParseDeclaration(Record *CurRec, +Init *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 (Type == 0) return 0; if (Lex.getCode() != tgtok::Id) { TokError("Expected identifier in declaration"); - return ""; + return 0; } SMLoc IdLoc = Lex.getLoc(); - std::string DeclName = Lex.getCurStrVal(); + Init *DeclName = StringInit::get(Lex.getCurStrVal()); Lex.Lex(); if (ParsingTemplateArgs) { if (CurRec) { - DeclName = CurRec->getName() + ":" + DeclName; + DeclName = QualifyName(*CurRec, CurMultiClass, DeclName, ":"); } else { assert(CurMultiClass); } if (CurMultiClass) - DeclName = CurMultiClass->Rec.getName() + "::" + DeclName; + DeclName = QualifyName(CurMultiClass->Rec, CurMultiClass, DeclName, + "::"); } // Add the value. if (AddValue(CurRec, IdLoc, RecordVal(DeclName, Type, HasField))) - return ""; + return 0; // If a value is present, parse it. if (Lex.getCode() == tgtok::equal) { @@ -1501,12 +1716,56 @@ std::string TGParser::ParseDeclaration(Record *CurRec, Init *Val = ParseValue(CurRec, Type); if (Val == 0 || SetValue(CurRec, ValLoc, DeclName, std::vector<unsigned>(), Val)) - return ""; + return 0; } return DeclName; } +/// ParseForeachDeclaration - Read a foreach declaration, returning +/// the name of the declared object or a NULL Init on error. Return +/// the name of the parsed initializer list through ForeachListName. +/// +/// ForeachDeclaration ::= ID '=' Value +/// +Init *TGParser::ParseForeachDeclaration(Init *&ForeachListValue) { + if (Lex.getCode() != tgtok::Id) { + TokError("Expected identifier in foreach declaration"); + return 0; + } + + Init *DeclName = StringInit::get(Lex.getCurStrVal()); + Lex.Lex(); + + // If a value is present, parse it. + if (Lex.getCode() != tgtok::equal) { + TokError("Expected '=' in foreach declaration"); + return 0; + } + Lex.Lex(); // Eat the '=' + + // Expect a list initializer. + ForeachListValue = ParseValue(0, 0, ParseForeachMode); + + TypedInit *TypedList = dynamic_cast<TypedInit *>(ForeachListValue); + if (TypedList == 0) { + TokError("Value list is untyped"); + return 0; + } + + RecTy *ValueType = TypedList->getType(); + ListRecTy *ListType = dynamic_cast<ListRecTy *>(ValueType); + if (ListType == 0) { + TokError("Value list is not of list type"); + return 0; + } + + RecTy *IterType = ListType->getElementType(); + VarInit *IterVar = VarInit::get(DeclName, IterType); + + return IterVar; +} + /// 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, @@ -1521,8 +1780,8 @@ bool TGParser::ParseTemplateArgList(Record *CurRec) { Record *TheRecToAddTo = CurRec ? CurRec : &CurMultiClass->Rec; // Read the first declaration. - std::string TemplArg = ParseDeclaration(CurRec, true/*templateargs*/); - if (TemplArg.empty()) + Init *TemplArg = ParseDeclaration(CurRec, true/*templateargs*/); + if (TemplArg == 0) return true; TheRecToAddTo->addTemplateArg(TemplArg); @@ -1532,7 +1791,7 @@ bool TGParser::ParseTemplateArgList(Record *CurRec) { // Read the following declarations. TemplArg = ParseDeclaration(CurRec, true/*templateargs*/); - if (TemplArg.empty()) + if (TemplArg == 0) return true; TheRecToAddTo->addTemplateArg(TemplArg); } @@ -1550,7 +1809,7 @@ 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) == 0) return true; if (Lex.getCode() != tgtok::semi) @@ -1671,22 +1930,24 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { Lex.Lex(); // Eat the 'def' token. // Parse ObjectName and make a record for it. - Record *CurRec = new Record(ParseObjectName(), DefLoc, Records); + Record *CurRec = new Record(ParseObjectName(CurMultiClass), 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"); + if (Records.getDef(CurRec->getNameInitAsString())) { + Error(DefLoc, "def '" + CurRec->getNameInitAsString() + + "' 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() + + if (CurMultiClass->DefPrototypes[i]->getNameInit() + == CurRec->getNameInit()) { + Error(DefLoc, "def '" + CurRec->getNameInitAsString() + "' already defined in this multiclass!"); return true; } @@ -1707,7 +1968,7 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { if (CurMultiClass) { // Copy the template arguments for the multiclass into the def. - const std::vector<std::string> &TArgs = + const std::vector<Init *> &TArgs = CurMultiClass->Rec.getTemplateArgs(); for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { @@ -1717,6 +1978,63 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { } } + if (ProcessForeachDefs(CurRec, CurMultiClass, DefLoc)) { + Error(DefLoc, + "Could not process loops for def" + CurRec->getNameInitAsString()); + return true; + } + + return false; +} + +/// ParseForeach - Parse a for statement. Return the record corresponding +/// to it. This returns true on error. +/// +/// Foreach ::= FOREACH Declaration IN '{ ObjectList '}' +/// Foreach ::= FOREACH Declaration IN Object +/// +bool TGParser::ParseForeach(MultiClass *CurMultiClass) { + assert(Lex.getCode() == tgtok::Foreach && "Unknown tok"); + Lex.Lex(); // Eat the 'for' token. + + // Make a temporary object to record items associated with the for + // loop. + Init *ListValue = 0; + Init *IterName = ParseForeachDeclaration(ListValue); + if (IterName == 0) + return TokError("expected declaration in for"); + + if (Lex.getCode() != tgtok::In) + return TokError("Unknown tok"); + Lex.Lex(); // Eat the in + + // Create a loop object and remember it. + Loops.push_back(ForeachLoop(IterName, ListValue)); + + if (Lex.getCode() != tgtok::l_brace) { + // FOREACH Declaration IN Object + if (ParseObject(CurMultiClass)) + return true; + } + else { + SMLoc BraceLoc = Lex.getLoc(); + // Otherwise, this is a group foreach. + Lex.Lex(); // eat the '{'. + + // Parse the object list. + if (ParseObjectList(CurMultiClass)) + return true; + + if (Lex.getCode() != tgtok::r_brace) { + TokError("expected '}' at end of foreach command"); + return Error(BraceLoc, "to match this '{'"); + } + Lex.Lex(); // Eat the } + } + + // We've processed everything in this loop. + Loops.pop_back(); + return false; } @@ -1734,10 +2052,11 @@ bool TGParser::ParseClass() { Record *CurRec = Records.getClass(Lex.getCurStrVal()); if (CurRec) { // If the body was previously defined, this is an error. - if (!CurRec->getValues().empty() || + if (CurRec->getValues().size() > 1 || // Account for NAME. !CurRec->getSuperClasses().empty() || !CurRec->getTemplateArgs().empty()) - return TokError("Class '" + CurRec->getName() + "' already defined"); + return TokError("Class '" + CurRec->getNameInitAsString() + + "' already defined"); } else { // If this is the first reference to this class, create and add it. CurRec = new Record(Lex.getCurStrVal(), Lex.getLoc(), Records); @@ -1909,6 +2228,7 @@ bool TGParser::ParseMultiClass() { case tgtok::Let: case tgtok::Def: case tgtok::Defm: + case tgtok::Foreach: if (ParseObject(CurMultiClass)) return true; break; @@ -1924,23 +2244,31 @@ bool TGParser::ParseMultiClass() { Record *TGParser:: InstantiateMulticlassDef(MultiClass &MC, Record *DefProto, - const std::string &DefmPrefix, + Init *DefmPrefix, SMLoc DefmPrefixLoc) { + // We need to preserve DefProto so it can be reused for later + // instantiations, so create a new Record to inherit from it. + // 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; - } + + if (DefmPrefix == 0) + DefmPrefix = StringInit::get(GetNewAnonymousName()); + + Init *DefName = DefProto->getNameInit(); + + StringInit *DefNameString = dynamic_cast<StringInit *>(DefName); + + if (DefNameString != 0) { + // We have a fully expanded string so there are no operators to + // resolve. We should concatenate the given prefix and name. + DefName = + BinOpInit::get(BinOpInit::STRCONCAT, + UnOpInit::get(UnOpInit::CAST, DefmPrefix, + StringRecTy::get())->Fold(DefProto, &MC), + DefName, StringRecTy::get())->Fold(DefProto, &MC); } Record *CurRec = new Record(DefName, DefmPrefixLoc, Records); @@ -1950,6 +2278,41 @@ InstantiateMulticlassDef(MultiClass &MC, Ref.Rec = DefProto; AddSubClass(CurRec, Ref); + if (DefNameString == 0) { + // We must resolve references to NAME. + if (SetValue(CurRec, Ref.RefLoc, "NAME", std::vector<unsigned>(), + DefmPrefix)) { + Error(DefmPrefixLoc, "Could not resolve " + + CurRec->getNameInitAsString() + ":NAME to '" + + DefmPrefix->getAsUnquotedString() + "'"); + return 0; + } + + RecordVal *DefNameRV = CurRec->getValue("NAME"); + CurRec->resolveReferencesTo(DefNameRV); + } + + if (!CurMultiClass) { + // We do this after resolving NAME because before resolution, many + // multiclass defs will have the same name expression. If we are + // currently in a multiclass, it means this defm appears inside a + // multiclass and its name won't be fully resolvable until we see + // the top-level defm. Therefore, we don't add this to the + // RecordKeeper at this point. If we did we could get duplicate + // defs as more than one probably refers to NAME or some other + // common internal placeholder. + + // Ensure redefinition doesn't happen. + if (Records.getDef(CurRec->getNameInitAsString())) { + Error(DefmPrefixLoc, "def '" + CurRec->getNameInitAsString() + + "' already defined, instantiating defm with subdef '" + + DefProto->getNameInitAsString() + "'"); + return 0; + } + + Records.addDef(CurRec); + } + return CurRec; } @@ -1957,7 +2320,7 @@ bool TGParser::ResolveMulticlassDefArgs(MultiClass &MC, Record *CurRec, SMLoc DefmPrefixLoc, SMLoc SubClassLoc, - const std::vector<std::string> &TArgs, + const std::vector<Init *> &TArgs, std::vector<Init *> &TemplateVals, bool DeleteArgs) { // Loop over all of the template arguments, setting them to the specified @@ -1979,8 +2342,9 @@ bool TGParser::ResolveMulticlassDefArgs(MultiClass &MC, } 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() + "'"); + utostr(i) + " (" + TArgs[i]->getAsUnquotedString() + + ") of multiclassclass '" + MC.Rec.getNameInitAsString() + + "'"); } } return false; @@ -1997,25 +2361,20 @@ bool TGParser::ResolveMulticlassDef(MultiClass &MC, LetStack[i][j].Bits, LetStack[i][j].Value)) return Error(DefmPrefixLoc, "when instantiating this defm"); - // 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()) - return Error(DefmPrefixLoc, "defm '" + CurRec->getName() + + if (CurMultiClass->DefPrototypes[i]->getNameInit() + == CurRec->getNameInit()) + return Error(DefmPrefixLoc, "defm '" + CurRec->getNameInitAsString() + "' already defined in this multiclass!"); CurMultiClass->DefPrototypes.push_back(CurRec); // Copy the template arguments for the multiclass into the new def. - const std::vector<std::string> &TA = + const std::vector<Init *> &TA = CurMultiClass->Rec.getTemplateArgs(); for (unsigned i = 0, e = TA.size(); i != e; ++i) { @@ -2023,8 +2382,6 @@ bool TGParser::ResolveMulticlassDef(MultiClass &MC, assert(RV && "Template arg doesn't exist?"); CurRec->addValue(*RV); } - } else { - Records.addDef(CurRec); } return false; @@ -2037,10 +2394,10 @@ bool TGParser::ResolveMulticlassDef(MultiClass &MC, bool TGParser::ParseDefm(MultiClass *CurMultiClass) { assert(Lex.getCode() == tgtok::Defm && "Unexpected token!"); - std::string DefmPrefix; + Init *DefmPrefix = 0; + if (Lex.Lex() == tgtok::Id) { // eat the defm. - DefmPrefix = Lex.getCurStrVal(); - Lex.Lex(); // Eat the defm prefix. + DefmPrefix = ParseObjectName(CurMultiClass); } SMLoc DefmPrefixLoc = Lex.getLoc(); @@ -2070,7 +2427,7 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { 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(); + const std::vector<Init *> &TArgs = MC->Rec.getTemplateArgs(); if (TArgs.size() < TemplateVals.size()) return Error(SubClassLoc, "more template args specified than multiclass expects"); @@ -2080,6 +2437,8 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { Record *DefProto = MC->DefPrototypes[i]; Record *CurRec = InstantiateMulticlassDef(*MC, DefProto, DefmPrefix, DefmPrefixLoc); + if (!CurRec) + return true; if (ResolveMulticlassDefArgs(*MC, CurRec, DefmPrefixLoc, SubClassLoc, TArgs, TemplateVals, true/*Delete args*/)) @@ -2165,6 +2524,7 @@ bool TGParser::ParseObject(MultiClass *MC) { return TokError("Expected class, def, defm, multiclass or let definition"); case tgtok::Let: return ParseTopLevelLet(MC); case tgtok::Def: return ParseDef(MC); + case tgtok::Foreach: return ParseForeach(MC); case tgtok::Defm: return ParseDefm(MC); case tgtok::Class: return ParseClass(); case tgtok::MultiClass: return ParseMultiClass(); diff --git a/contrib/llvm/lib/TableGen/TGParser.h b/contrib/llvm/lib/TableGen/TGParser.h index db8a620..b8e7cb1 100644 --- a/contrib/llvm/lib/TableGen/TGParser.h +++ b/contrib/llvm/lib/TableGen/TGParser.h @@ -14,6 +14,7 @@ #ifndef TGPARSER_H #define TGPARSER_H +#include "llvm/TableGen/Record.h" #include "TGLexer.h" #include "llvm/TableGen/Error.h" #include "llvm/ADT/Twine.h" @@ -41,17 +42,44 @@ namespace llvm { } }; + /// ForeachLoop - Record the iteration state associated with a for loop. + /// This is used to instantiate items in the loop body. + struct ForeachLoop { + Init *IterVar; + Init *ListValue; + + ForeachLoop(Init *IVar, Init *LValue) : IterVar(IVar), ListValue(LValue) {} + }; + class TGParser { TGLexer Lex; std::vector<std::vector<LetRecord> > LetStack; std::map<std::string, MultiClass*> MultiClasses; + /// Loops - Keep track of any foreach loops we are within. + /// + typedef std::vector<ForeachLoop> LoopVector; + LoopVector Loops; + /// CurMultiClass - If we are parsing a 'multiclass' definition, this is the /// current value. MultiClass *CurMultiClass; // Record tracker RecordKeeper &Records; + + // A "named boolean" indicating how to parse identifiers. Usually + // identifiers map to some existing object but in special cases + // (e.g. parsing def names) no such object exists yet because we are + // in the middle of creating in. For those situations, allow the + // parser to ignore missing object errors. + enum IDParseMode { + ParseValueMode, // We are parsing a value we expect to look up. + ParseNameMode, // We are parsing a name of an object that does not yet + // exist. + ParseForeachMode // We are parsing a foreach init. + }; + public: TGParser(SourceMgr &SrcMgr, RecordKeeper &records) : Lex(SrcMgr), CurMultiClass(0), Records(records) {} @@ -70,14 +98,36 @@ public: const std::vector<std::string> &getDependencies() const { return Lex.getDependencies(); } + private: // Semantic analysis methods. bool AddValue(Record *TheRec, SMLoc Loc, const RecordVal &RV); - bool SetValue(Record *TheRec, SMLoc Loc, const std::string &ValName, + bool SetValue(Record *TheRec, SMLoc Loc, Init *ValName, const std::vector<unsigned> &BitList, Init *V); + bool SetValue(Record *TheRec, SMLoc Loc, const std::string &ValName, + const std::vector<unsigned> &BitList, Init *V) { + return SetValue(TheRec, Loc, StringInit::get(ValName), BitList, V); + } bool AddSubClass(Record *Rec, SubClassReference &SubClass); bool AddSubMultiClass(MultiClass *CurMC, SubMultiClassReference &SubMultiClass); + // IterRecord: Map an iterator name to a value. + struct IterRecord { + Init *IterVar; + Init *IterValue; + IterRecord(Init *Var, Init *Val) : IterVar(Var), IterValue(Val) {} + }; + + // IterSet: The set of all iterator values at some point in the + // iteration space. + typedef std::vector<IterRecord> IterSet; + + bool ProcessForeachDefs(Record *CurRec, MultiClass *CurMultiClass, + SMLoc Loc); + bool ProcessForeachDefs(Record *CurRec, MultiClass *CurMultiClass, + SMLoc Loc, IterSet &IterVals, ForeachLoop &CurLoop, + LoopVector::iterator NextLoop); + private: // Parser methods. bool ParseObjectList(MultiClass *MC = 0); bool ParseObject(MultiClass *MC); @@ -85,13 +135,13 @@ private: // Parser methods. bool ParseMultiClass(); Record *InstantiateMulticlassDef(MultiClass &MC, Record *DefProto, - const std::string &DefmPrefix, + Init *DefmPrefix, SMLoc DefmPrefixLoc); bool ResolveMulticlassDefArgs(MultiClass &MC, Record *DefProto, SMLoc DefmPrefixLoc, SMLoc SubClassLoc, - const std::vector<std::string> &TArgs, + const std::vector<Init *> &TArgs, std::vector<Init *> &TemplateVals, bool DeleteArgs); bool ResolveMulticlassDef(MultiClass &MC, @@ -100,6 +150,7 @@ private: // Parser methods. SMLoc DefmPrefixLoc); bool ParseDefm(MultiClass *CurMultiClass); bool ParseDef(MultiClass *CurMultiClass); + bool ParseForeach(MultiClass *CurMultiClass); bool ParseTopLevelLet(MultiClass *CurMultiClass); std::vector<LetRecord> ParseLetList(); @@ -108,15 +159,19 @@ private: // Parser methods. bool ParseBodyItem(Record *CurRec); bool ParseTemplateArgList(Record *CurRec); - std::string ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs); + Init *ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs); + Init *ParseForeachDeclaration(Init *&ForeachListValue); SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm); SubMultiClassReference ParseSubMultiClassReference(MultiClass *CurMC); - Init *ParseIDValue(Record *CurRec); - Init *ParseIDValue(Record *CurRec, const std::string &Name, SMLoc NameLoc); - Init *ParseSimpleValue(Record *CurRec, RecTy *ItemType = 0); - Init *ParseValue(Record *CurRec, RecTy *ItemType = 0); + Init *ParseIDValue(Record *CurRec, IDParseMode Mode = ParseValueMode); + Init *ParseIDValue(Record *CurRec, const std::string &Name, SMLoc NameLoc, + IDParseMode Mode = ParseValueMode); + Init *ParseSimpleValue(Record *CurRec, RecTy *ItemType = 0, + IDParseMode Mode = ParseValueMode); + Init *ParseValue(Record *CurRec, RecTy *ItemType = 0, + IDParseMode Mode = ParseValueMode); std::vector<Init*> ParseValueList(Record *CurRec, Record *ArgsRec = 0, RecTy *EltTy = 0); std::vector<std::pair<llvm::Init*, std::string> > ParseDagArgList(Record *); bool ParseOptionalRangeList(std::vector<unsigned> &Ranges); @@ -126,7 +181,7 @@ private: // Parser methods. RecTy *ParseType(); Init *ParseOperation(Record *CurRec); RecTy *ParseOperatorType(); - std::string ParseObjectName(); + Init *ParseObjectName(MultiClass *CurMultiClass); Record *ParseClassID(); MultiClass *ParseMultiClassID(); Record *ParseDefmID(); diff --git a/contrib/llvm/lib/TableGen/TableGenAction.cpp b/contrib/llvm/lib/TableGen/TableGenAction.cpp new file mode 100644 index 0000000..54e5083 --- /dev/null +++ b/contrib/llvm/lib/TableGen/TableGenAction.cpp @@ -0,0 +1,15 @@ +//===- TableGenAction.cpp - defines TableGenAction --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/TableGen/TableGenAction.h" + +using namespace llvm; + +void TableGenAction::anchor() { } + diff --git a/contrib/llvm/lib/TableGen/TableGenBackend.cpp b/contrib/llvm/lib/TableGen/TableGenBackend.cpp index 29588db..09bcc7a 100644 --- a/contrib/llvm/lib/TableGen/TableGenBackend.cpp +++ b/contrib/llvm/lib/TableGen/TableGenBackend.cpp @@ -15,7 +15,9 @@ #include "llvm/TableGen/Record.h" using namespace llvm; -void TableGenBackend::EmitSourceFileHeader(const std::string &Desc, +void TableGenBackend::anchor() { } + +void TableGenBackend::EmitSourceFileHeader(StringRef Desc, raw_ostream &OS) const { OS << "//===- TableGen'erated file -------------------------------------*-" " C++ -*-===//\n//\n// " << Desc << "\n//\n// Automatically generate" |