brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.5 KiB · 09b7d53 Raw
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