diff options
Diffstat (limited to 'llvm/lib/TableGen/TGParser.h')
-rw-r--r-- | llvm/lib/TableGen/TGParser.h | 74 |
1 files changed, 69 insertions, 5 deletions
diff --git a/llvm/lib/TableGen/TGParser.h b/llvm/lib/TableGen/TGParser.h index af2b639f8d59..c66c79771298 100644 --- a/llvm/lib/TableGen/TGParser.h +++ b/llvm/lib/TableGen/TGParser.h @@ -56,6 +56,10 @@ namespace llvm { /// ForeachLoop - Record the iteration state associated with a for loop. /// This is used to instantiate items in the loop body. + /// + /// IterVar is allowed to be null, in which case no iteration variable is + /// defined in the loop at all. (This happens when a ForeachLoop is + /// constructed by desugaring an if statement.) struct ForeachLoop { SMLoc Loc; VarInit *IterVar; @@ -70,10 +74,50 @@ namespace llvm { struct DefsetRecord { SMLoc Loc; - RecTy *EltTy; + RecTy *EltTy = nullptr; SmallVector<Init *, 16> Elements; }; +class TGLocalVarScope { + // A scope to hold local variable definitions from defvar. + std::map<std::string, Init *, std::less<>> vars; + std::unique_ptr<TGLocalVarScope> parent; + +public: + TGLocalVarScope() = default; + TGLocalVarScope(std::unique_ptr<TGLocalVarScope> parent) + : parent(std::move(parent)) {} + + std::unique_ptr<TGLocalVarScope> extractParent() { + // This is expected to be called just before we are destructed, so + // it doesn't much matter what state we leave 'parent' in. + return std::move(parent); + } + + Init *getVar(StringRef Name) const { + auto It = vars.find(Name); + if (It != vars.end()) + return It->second; + if (parent) + return parent->getVar(Name); + return nullptr; + } + + bool varAlreadyDefined(StringRef Name) const { + // When we check whether a variable is already defined, for the purpose of + // reporting an error on redefinition, we don't look up to the parent + // scope, because it's all right to shadow an outer definition with an + // inner one. + return vars.find(Name) != vars.end(); + } + + void addVar(StringRef Name, Init *I) { + bool Ins = vars.insert(std::make_pair(Name, I)).second; + (void)Ins; + assert(Ins && "Local variable already exists"); + } +}; + struct MultiClass { Record Rec; // Placeholder for template args and Name. std::vector<RecordsEntry> Entries; @@ -99,6 +143,10 @@ class TGParser { /// current value. MultiClass *CurMultiClass; + /// CurLocalScope - Innermost of the current nested scopes for 'defvar' local + /// variables. + std::unique_ptr<TGLocalVarScope> CurLocalScope; + // Record tracker RecordKeeper &Records; @@ -114,9 +162,9 @@ class TGParser { }; public: - TGParser(SourceMgr &SrcMgr, ArrayRef<std::string> Macros, + TGParser(SourceMgr &SM, ArrayRef<std::string> Macros, RecordKeeper &records) - : Lex(SrcMgr, Macros), CurMultiClass(nullptr), Records(records) {} + : Lex(SM, Macros), CurMultiClass(nullptr), Records(records) {} /// ParseFile - Main entrypoint for parsing a tblgen file. These parser /// routines return true on error, or false on success. @@ -129,11 +177,24 @@ public: bool TokError(const Twine &Msg) const { return Error(Lex.getLoc(), Msg); } - const TGLexer::DependenciesMapTy &getDependencies() const { + const TGLexer::DependenciesSetTy &getDependencies() const { return Lex.getDependencies(); } -private: // Semantic analysis methods. + TGLocalVarScope *PushLocalScope() { + CurLocalScope = std::make_unique<TGLocalVarScope>(std::move(CurLocalScope)); + // Returns a pointer to the new scope, so that the caller can pass it back + // to PopLocalScope which will check by assertion that the pushes and pops + // match up properly. + return CurLocalScope.get(); + } + void PopLocalScope(TGLocalVarScope *ExpectedStackTop) { + assert(ExpectedStackTop == CurLocalScope.get() && + "Mismatched pushes and pops of local variable scopes"); + CurLocalScope = CurLocalScope->extractParent(); + } + +private: // Semantic analysis methods. bool AddValue(Record *TheRec, SMLoc Loc, const RecordVal &RV); bool SetValue(Record *TheRec, SMLoc Loc, Init *ValName, ArrayRef<unsigned> BitList, Init *V, @@ -161,7 +222,10 @@ private: // Parser methods. bool ParseDefm(MultiClass *CurMultiClass); bool ParseDef(MultiClass *CurMultiClass); bool ParseDefset(); + bool ParseDefvar(); bool ParseForeach(MultiClass *CurMultiClass); + bool ParseIf(MultiClass *CurMultiClass); + bool ParseIfBody(MultiClass *CurMultiClass, StringRef Kind); bool ParseTopLevelLet(MultiClass *CurMultiClass); void ParseLetList(SmallVectorImpl<LetRecord> &Result); |