1 //===- TGParser.h - Parser for TableGen Files -------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This class represents the Parser for tablegen files.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_LIB_TABLEGEN_TGPARSER_H
14 #define LLVM_LIB_TABLEGEN_TGPARSER_H
15 
16 #include "TGLexer.h"
17 #include "llvm/TableGen/Error.h"
18 #include "llvm/TableGen/Record.h"
19 #include <map>
20 
21 namespace llvm {
22 class SourceMgr;
23 class Twine;
24 struct ForeachLoop;
25 struct MultiClass;
26 struct SubClassReference;
27 struct SubMultiClassReference;
28 
29 struct LetRecord {
30   StringInit *Name;
31   std::vector<unsigned> Bits;
32   Init *Value;
33   SMLoc Loc;
LetRecordLetRecord34   LetRecord(StringInit *N, ArrayRef<unsigned> B, Init *V, SMLoc L)
35       : Name(N), Bits(B), Value(V), Loc(L) {}
36 };
37 
38 /// RecordsEntry - Holds exactly one of a Record, ForeachLoop, or
39 /// AssertionInfo.
40 struct RecordsEntry {
41   std::unique_ptr<Record> Rec;
42   std::unique_ptr<ForeachLoop> Loop;
43   std::unique_ptr<Record::AssertionInfo> Assertion;
44   std::unique_ptr<Record::DumpInfo> Dump;
45 
46   void dump() const;
47 
48   RecordsEntry() = default;
RecordsEntryRecordsEntry49   RecordsEntry(std::unique_ptr<Record> Rec) : Rec(std::move(Rec)) {}
RecordsEntryRecordsEntry50   RecordsEntry(std::unique_ptr<ForeachLoop> Loop) : Loop(std::move(Loop)) {}
RecordsEntryRecordsEntry51   RecordsEntry(std::unique_ptr<Record::AssertionInfo> Assertion)
52       : Assertion(std::move(Assertion)) {}
RecordsEntryRecordsEntry53   RecordsEntry(std::unique_ptr<Record::DumpInfo> Dump)
54       : Dump(std::move(Dump)) {}
55 };
56 
57 /// ForeachLoop - Record the iteration state associated with a for loop.
58 /// This is used to instantiate items in the loop body.
59 ///
60 /// IterVar is allowed to be null, in which case no iteration variable is
61 /// defined in the loop at all. (This happens when a ForeachLoop is
62 /// constructed by desugaring an if statement.)
63 struct ForeachLoop {
64   SMLoc Loc;
65   VarInit *IterVar;
66   Init *ListValue;
67   std::vector<RecordsEntry> Entries;
68 
69   void dump() const;
70 
ForeachLoopForeachLoop71   ForeachLoop(SMLoc Loc, VarInit *IVar, Init *LValue)
72       : Loc(Loc), IterVar(IVar), ListValue(LValue) {}
73 };
74 
75 struct DefsetRecord {
76   SMLoc Loc;
77   RecTy *EltTy = nullptr;
78   SmallVector<Init *, 16> Elements;
79 };
80 
81 struct MultiClass {
82   Record Rec; // Placeholder for template args and Name.
83   std::vector<RecordsEntry> Entries;
84 
85   void dump() const;
86 
MultiClassMultiClass87   MultiClass(StringRef Name, SMLoc Loc, RecordKeeper &Records)
88       : Rec(Name, Loc, Records, Record::RK_MultiClass) {}
89 };
90 
91 class TGVarScope {
92 public:
93   enum ScopeKind { SK_Local, SK_Record, SK_ForeachLoop, SK_MultiClass };
94 
95 private:
96   ScopeKind Kind;
97   std::unique_ptr<TGVarScope> Parent;
98   // A scope to hold variable definitions from defvar.
99   std::map<std::string, Init *, std::less<>> Vars;
100   Record *CurRec = nullptr;
101   ForeachLoop *CurLoop = nullptr;
102   MultiClass *CurMultiClass = nullptr;
103 
104 public:
TGVarScope(std::unique_ptr<TGVarScope> Parent)105   TGVarScope(std::unique_ptr<TGVarScope> Parent)
106       : Kind(SK_Local), Parent(std::move(Parent)) {}
TGVarScope(std::unique_ptr<TGVarScope> Parent,Record * Rec)107   TGVarScope(std::unique_ptr<TGVarScope> Parent, Record *Rec)
108       : Kind(SK_Record), Parent(std::move(Parent)), CurRec(Rec) {}
TGVarScope(std::unique_ptr<TGVarScope> Parent,ForeachLoop * Loop)109   TGVarScope(std::unique_ptr<TGVarScope> Parent, ForeachLoop *Loop)
110       : Kind(SK_ForeachLoop), Parent(std::move(Parent)), CurLoop(Loop) {}
TGVarScope(std::unique_ptr<TGVarScope> Parent,MultiClass * Multiclass)111   TGVarScope(std::unique_ptr<TGVarScope> Parent, MultiClass *Multiclass)
112       : Kind(SK_MultiClass), Parent(std::move(Parent)),
113         CurMultiClass(Multiclass) {}
114 
extractParent()115   std::unique_ptr<TGVarScope> extractParent() {
116     // This is expected to be called just before we are destructed, so
117     // it doesn't much matter what state we leave 'parent' in.
118     return std::move(Parent);
119   }
120 
121   Init *getVar(RecordKeeper &Records, MultiClass *ParsingMultiClass,
122                StringInit *Name, SMRange NameLoc,
123                bool TrackReferenceLocs) const;
124 
varAlreadyDefined(StringRef Name)125   bool varAlreadyDefined(StringRef Name) const {
126     // When we check whether a variable is already defined, for the purpose of
127     // reporting an error on redefinition, we don't look up to the parent
128     // scope, because it's all right to shadow an outer definition with an
129     // inner one.
130     return Vars.find(Name) != Vars.end();
131   }
132 
addVar(StringRef Name,Init * I)133   void addVar(StringRef Name, Init *I) {
134     bool Ins = Vars.insert(std::make_pair(std::string(Name), I)).second;
135     (void)Ins;
136     assert(Ins && "Local variable already exists");
137   }
138 
isOutermost()139   bool isOutermost() const { return Parent == nullptr; }
140 };
141 
142 class TGParser {
143   TGLexer Lex;
144   std::vector<SmallVector<LetRecord, 4>> LetStack;
145   std::map<std::string, std::unique_ptr<MultiClass>> MultiClasses;
146 
147   /// Loops - Keep track of any foreach loops we are within.
148   ///
149   std::vector<std::unique_ptr<ForeachLoop>> Loops;
150 
151   SmallVector<DefsetRecord *, 2> Defsets;
152 
153   /// CurMultiClass - If we are parsing a 'multiclass' definition, this is the
154   /// current value.
155   MultiClass *CurMultiClass;
156 
157   /// CurScope - Innermost of the current nested scopes for 'defvar' variables.
158   std::unique_ptr<TGVarScope> CurScope;
159 
160   // Record tracker
161   RecordKeeper &Records;
162 
163   // A "named boolean" indicating how to parse identifiers.  Usually
164   // identifiers map to some existing object but in special cases
165   // (e.g. parsing def names) no such object exists yet because we are
166   // in the middle of creating in.  For those situations, allow the
167   // parser to ignore missing object errors.
168   enum IDParseMode {
169     ParseValueMode,   // We are parsing a value we expect to look up.
170     ParseNameMode,    // We are parsing a name of an object that does not yet
171                       // exist.
172   };
173 
174   bool NoWarnOnUnusedTemplateArgs = false;
175   bool TrackReferenceLocs = false;
176 
177 public:
178   TGParser(SourceMgr &SM, ArrayRef<std::string> Macros, RecordKeeper &records,
179            const bool NoWarnOnUnusedTemplateArgs = false,
180            const bool TrackReferenceLocs = false)
Lex(SM,Macros)181       : Lex(SM, Macros), CurMultiClass(nullptr), Records(records),
182         NoWarnOnUnusedTemplateArgs(NoWarnOnUnusedTemplateArgs),
183         TrackReferenceLocs(TrackReferenceLocs) {}
184 
185   /// ParseFile - Main entrypoint for parsing a tblgen file.  These parser
186   /// routines return true on error, or false on success.
187   bool ParseFile();
188 
Error(SMLoc L,const Twine & Msg)189   bool Error(SMLoc L, const Twine &Msg) const {
190     PrintError(L, Msg);
191     return true;
192   }
TokError(const Twine & Msg)193   bool TokError(const Twine &Msg) const {
194     return Error(Lex.getLoc(), Msg);
195   }
getDependencies()196   const TGLexer::DependenciesSetTy &getDependencies() const {
197     return Lex.getDependencies();
198   }
199 
PushScope()200   TGVarScope *PushScope() {
201     CurScope = std::make_unique<TGVarScope>(std::move(CurScope));
202     // Returns a pointer to the new scope, so that the caller can pass it back
203     // to PopScope which will check by assertion that the pushes and pops
204     // match up properly.
205     return CurScope.get();
206   }
PushScope(Record * Rec)207   TGVarScope *PushScope(Record *Rec) {
208     CurScope = std::make_unique<TGVarScope>(std::move(CurScope), Rec);
209     return CurScope.get();
210   }
PushScope(ForeachLoop * Loop)211   TGVarScope *PushScope(ForeachLoop *Loop) {
212     CurScope = std::make_unique<TGVarScope>(std::move(CurScope), Loop);
213     return CurScope.get();
214   }
PushScope(MultiClass * Multiclass)215   TGVarScope *PushScope(MultiClass *Multiclass) {
216     CurScope = std::make_unique<TGVarScope>(std::move(CurScope), Multiclass);
217     return CurScope.get();
218   }
PopScope(TGVarScope * ExpectedStackTop)219   void PopScope(TGVarScope *ExpectedStackTop) {
220     assert(ExpectedStackTop == CurScope.get() &&
221            "Mismatched pushes and pops of local variable scopes");
222     CurScope = CurScope->extractParent();
223   }
224 
225 private: // Semantic analysis methods.
226   bool AddValue(Record *TheRec, SMLoc Loc, const RecordVal &RV);
227   /// Set the value of a RecordVal within the given record. If `OverrideDefLoc`
228   /// is set, the provided location overrides any existing location of the
229   /// RecordVal.
230   bool SetValue(Record *TheRec, SMLoc Loc, Init *ValName,
231                 ArrayRef<unsigned> BitList, Init *V,
232                 bool AllowSelfAssignment = false, bool OverrideDefLoc = true);
233   bool AddSubClass(Record *Rec, SubClassReference &SubClass);
234   bool AddSubClass(RecordsEntry &Entry, SubClassReference &SubClass);
235   bool AddSubMultiClass(MultiClass *CurMC,
236                         SubMultiClassReference &SubMultiClass);
237 
238   using SubstStack = SmallVector<std::pair<Init *, Init *>, 8>;
239 
240   bool addEntry(RecordsEntry E);
241   bool resolve(const ForeachLoop &Loop, SubstStack &Stack, bool Final,
242                std::vector<RecordsEntry> *Dest, SMLoc *Loc = nullptr);
243   bool resolve(const std::vector<RecordsEntry> &Source, SubstStack &Substs,
244                bool Final, std::vector<RecordsEntry> *Dest,
245                SMLoc *Loc = nullptr);
246   bool addDefOne(std::unique_ptr<Record> Rec);
247 
248   using ArgValueHandler = std::function<void(Init *, Init *)>;
249   bool resolveArguments(
250       Record *Rec, ArrayRef<ArgumentInit *> ArgValues, SMLoc Loc,
251       ArgValueHandler ArgValueHandler = [](Init *, Init *) {});
252   bool resolveArgumentsOfClass(MapResolver &R, Record *Rec,
253                                ArrayRef<ArgumentInit *> ArgValues, SMLoc Loc);
254   bool resolveArgumentsOfMultiClass(SubstStack &Substs, MultiClass *MC,
255                                     ArrayRef<ArgumentInit *> ArgValues,
256                                     Init *DefmName, SMLoc Loc);
257 
258 private:  // Parser methods.
259   bool consume(tgtok::TokKind K);
260   bool ParseObjectList(MultiClass *MC = nullptr);
261   bool ParseObject(MultiClass *MC);
262   bool ParseClass();
263   bool ParseMultiClass();
264   bool ParseDefm(MultiClass *CurMultiClass);
265   bool ParseDef(MultiClass *CurMultiClass);
266   bool ParseDefset();
267   bool ParseDefvar(Record *CurRec = nullptr);
268   bool ParseDump(MultiClass *CurMultiClass, Record *CurRec = nullptr);
269   bool ParseForeach(MultiClass *CurMultiClass);
270   bool ParseIf(MultiClass *CurMultiClass);
271   bool ParseIfBody(MultiClass *CurMultiClass, StringRef Kind);
272   bool ParseAssert(MultiClass *CurMultiClass, Record *CurRec = nullptr);
273   bool ParseTopLevelLet(MultiClass *CurMultiClass);
274   void ParseLetList(SmallVectorImpl<LetRecord> &Result);
275 
276   bool ParseObjectBody(Record *CurRec);
277   bool ParseBody(Record *CurRec);
278   bool ParseBodyItem(Record *CurRec);
279 
280   bool ParseTemplateArgList(Record *CurRec);
281   Init *ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs);
282   VarInit *ParseForeachDeclaration(Init *&ForeachListValue);
283 
284   SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm);
285   SubMultiClassReference ParseSubMultiClassReference(MultiClass *CurMC);
286 
287   Init *ParseIDValue(Record *CurRec, StringInit *Name, SMRange NameLoc,
288                      IDParseMode Mode = ParseValueMode);
289   Init *ParseSimpleValue(Record *CurRec, RecTy *ItemType = nullptr,
290                          IDParseMode Mode = ParseValueMode);
291   Init *ParseValue(Record *CurRec, RecTy *ItemType = nullptr,
292                    IDParseMode Mode = ParseValueMode);
293   void ParseValueList(SmallVectorImpl<llvm::Init*> &Result,
294                       Record *CurRec, RecTy *ItemType = nullptr);
295   bool ParseTemplateArgValueList(SmallVectorImpl<llvm::ArgumentInit *> &Result,
296                                  Record *CurRec, Record *ArgsRec);
297   void ParseDagArgList(
298       SmallVectorImpl<std::pair<llvm::Init*, StringInit*>> &Result,
299       Record *CurRec);
300   bool ParseOptionalRangeList(SmallVectorImpl<unsigned> &Ranges);
301   bool ParseOptionalBitList(SmallVectorImpl<unsigned> &Ranges);
302   TypedInit *ParseSliceElement(Record *CurRec);
303   TypedInit *ParseSliceElements(Record *CurRec, bool Single = false);
304   void ParseRangeList(SmallVectorImpl<unsigned> &Result);
305   bool ParseRangePiece(SmallVectorImpl<unsigned> &Ranges,
306                        TypedInit *FirstItem = nullptr);
307   RecTy *ParseType();
308   Init *ParseOperation(Record *CurRec, RecTy *ItemType);
309   Init *ParseOperationSubstr(Record *CurRec, RecTy *ItemType);
310   Init *ParseOperationFind(Record *CurRec, RecTy *ItemType);
311   Init *ParseOperationForEachFilter(Record *CurRec, RecTy *ItemType);
312   Init *ParseOperationCond(Record *CurRec, RecTy *ItemType);
313   RecTy *ParseOperatorType();
314   Init *ParseObjectName(MultiClass *CurMultiClass);
315   Record *ParseClassID();
316   MultiClass *ParseMultiClassID();
317   bool ApplyLetStack(Record *CurRec);
318   bool ApplyLetStack(RecordsEntry &Entry);
319   bool CheckTemplateArgValues(SmallVectorImpl<llvm::ArgumentInit *> &Values,
320                               SMLoc Loc, Record *ArgsRec);
321 };
322 
323 } // end namespace llvm
324 
325 #endif
326