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