//===- TGParser.cpp - Parser for TableGen Files ---------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Implement the Parser for TableGen. // //===----------------------------------------------------------------------===// #include "TGParser.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> #include <cstdint> #include <limits> usingnamespacellvm; //===----------------------------------------------------------------------===// // Support Code for the Semantic Actions. //===----------------------------------------------------------------------===// namespace llvm { struct SubClassReference { … }; struct SubMultiClassReference { … }; #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void SubMultiClassReference::dump() const { errs() << "Multiclass:\n"; MC->dump(); errs() << "Template args:\n"; for (Init *TA : TemplateArgs) TA->dump(); } #endif } // end namespace llvm static bool checkBitsConcrete(Record &R, const RecordVal &RV) { … } static void checkConcrete(Record &R) { … } /// Return an Init with a qualifier prefix referring /// to CurRec's name. static Init *QualifyName(Record &CurRec, Init *Name) { … } static Init *QualifyName(MultiClass *MC, Init *Name) { … } /// Return the qualified version of the implicit 'NAME' template argument. static Init *QualifiedNameOfImplicitName(Record &Rec) { … } static Init *QualifiedNameOfImplicitName(MultiClass *MC) { … } Init *TGVarScope::getVar(RecordKeeper &Records, MultiClass *ParsingMultiClass, StringInit *Name, SMRange NameLoc, bool TrackReferenceLocs) const { … } 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, Init *ValName, ArrayRef<unsigned> BitList, Init *V, bool AllowSelfAssignment, bool OverrideDefLoc) { … } /// AddSubClass - Add SubClass as a subclass to CurRec, resolving its template /// args as SubClass's template arguments. bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { … } bool TGParser::AddSubClass(RecordsEntry &Entry, SubClassReference &SubClass) { … } /// AddSubMultiClass - Add SubMultiClass as a subclass to /// CurMC, resolving its template args as SubMultiClass's /// template arguments. bool TGParser::AddSubMultiClass(MultiClass *CurMC, SubMultiClassReference &SubMultiClass) { … } /// Add a record, foreach loop, or assertion to the current context. bool TGParser::addEntry(RecordsEntry E) { … } /// Resolve the entries in \p Loop, going over inner loops recursively /// and making the given subsitutions of (name, value) pairs. /// /// The resulting records are stored in \p Dest if non-null. Otherwise, they /// are added to the global record keeper. bool TGParser::resolve(const ForeachLoop &Loop, SubstStack &Substs, bool Final, std::vector<RecordsEntry> *Dest, SMLoc *Loc) { … } /// Resolve the entries in \p Source, going over loops recursively and /// making the given substitutions of (name, value) pairs. /// /// The resulting records are stored in \p Dest if non-null. Otherwise, they /// are added to the global record keeper. bool TGParser::resolve(const std::vector<RecordsEntry> &Source, SubstStack &Substs, bool Final, std::vector<RecordsEntry> *Dest, SMLoc *Loc) { … } /// Resolve the record fully and add it to the record keeper. bool TGParser::addDefOne(std::unique_ptr<Record> Rec) { … } bool TGParser::resolveArguments(Record *Rec, ArrayRef<ArgumentInit *> ArgValues, SMLoc Loc, ArgValueHandler ArgValueHandler) { … } /// Resolve the arguments of class and set them to MapResolver. /// Returns true if failed. bool TGParser::resolveArgumentsOfClass(MapResolver &R, Record *Rec, ArrayRef<ArgumentInit *> ArgValues, SMLoc Loc) { … } /// Resolve the arguments of multiclass and store them into SubstStack. /// Returns true if failed. bool TGParser::resolveArgumentsOfMultiClass(SubstStack &Substs, MultiClass *MC, ArrayRef<ArgumentInit *> ArgValues, Init *DefmName, SMLoc Loc) { … } //===----------------------------------------------------------------------===// // Parser Code //===----------------------------------------------------------------------===// bool TGParser::consume(tgtok::TokKind K) { … } /// ParseObjectName - If a valid object name is specified, return it. If no /// name is specified, return the unset initializer. Return nullptr on parse /// error. /// ObjectName ::= Value [ '#' Value ]* /// ObjectName ::= /*empty*/ /// Init *TGParser::ParseObjectName(MultiClass *CurMultiClass) { … } /// ParseClassID - Parse and resolve a reference to a class name. This returns /// null on error. /// /// ClassID ::= ID /// Record *TGParser::ParseClassID() { … } /// ParseMultiClassID - Parse and resolve a reference to a multiclass name. /// This returns null on error. /// /// MultiClassID ::= ID /// MultiClass *TGParser::ParseMultiClassID() { … } /// ParseSubClassReference - Parse a reference to a subclass or a /// multiclass. This returns a SubClassRefTy with a null Record* on error. /// /// SubClassRef ::= ClassID /// SubClassRef ::= ClassID '<' ArgValueList '>' /// SubClassReference TGParser:: ParseSubClassReference(Record *CurRec, bool isDefm) { … } /// ParseSubMultiClassReference - Parse a reference to a subclass or to a /// templated submulticlass. This returns a SubMultiClassRefTy with a null /// Record* on error. /// /// SubMultiClassRef ::= MultiClassID /// SubMultiClassRef ::= MultiClassID '<' ArgValueList '>' /// SubMultiClassReference TGParser:: ParseSubMultiClassReference(MultiClass *CurMC) { … } /// ParseSliceElement - Parse subscript or range /// /// SliceElement ::= Value<list<int>> /// SliceElement ::= Value<int> /// SliceElement ::= Value<int> '...' Value<int> /// SliceElement ::= Value<int> '-' Value<int> (deprecated) /// SliceElement ::= Value<int> INTVAL(Negative; deprecated) /// /// SliceElement is either IntRecTy, ListRecTy, or nullptr /// TypedInit *TGParser::ParseSliceElement(Record *CurRec) { … } /// ParseSliceElements - Parse subscripts in square brackets. /// /// SliceElements ::= ( SliceElement ',' )* SliceElement ','? /// /// SliceElement is either IntRecTy, ListRecTy, or nullptr /// /// Returns ListRecTy by defaut. /// Returns IntRecTy if; /// - Single=true /// - SliceElements is Value<int> w/o trailing comma /// TypedInit *TGParser::ParseSliceElements(Record *CurRec, bool Single) { … } /// ParseRangePiece - Parse a bit/value range. /// RangePiece ::= INTVAL /// RangePiece ::= INTVAL '...' INTVAL /// RangePiece ::= INTVAL '-' INTVAL /// RangePiece ::= INTVAL INTVAL // The last two forms are deprecated. bool TGParser::ParseRangePiece(SmallVectorImpl<unsigned> &Ranges, TypedInit *FirstItem) { … } /// ParseRangeList - Parse a list of scalars and ranges into scalar values. /// /// RangeList ::= RangePiece (',' RangePiece)* /// void TGParser::ParseRangeList(SmallVectorImpl<unsigned> &Result) { … } /// ParseOptionalRangeList - Parse either a range list in <>'s or nothing. /// OptionalRangeList ::= '<' RangeList '>' /// OptionalRangeList ::= /*empty*/ bool TGParser::ParseOptionalRangeList(SmallVectorImpl<unsigned> &Ranges) { … } /// ParseOptionalBitList - Parse either a bit list in {}'s or nothing. /// OptionalBitList ::= '{' RangeList '}' /// OptionalBitList ::= /*empty*/ bool TGParser::ParseOptionalBitList(SmallVectorImpl<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 ::= DAG // dag type /// Type ::= ClassID // Record Type /// const RecTy *TGParser::ParseType() { … } /// ParseIDValue Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMRange NameLoc, IDParseMode Mode) { … } /// ParseOperation - Parse an operator. This returns null on error. /// /// Operation ::= XOperator ['<' Type '>'] '(' Args ')' /// Init *TGParser::ParseOperation(Record *CurRec, const RecTy *ItemType) { … } /// ParseOperatorType - Parse a type for an operator. This returns /// null on error. /// /// OperatorType ::= '<' Type '>' /// const RecTy *TGParser::ParseOperatorType() { … } /// Parse the !substr operation. Return null on error. /// /// Substr ::= !substr(string, start-int [, length-int]) => string Init *TGParser::ParseOperationSubstr(Record *CurRec, const RecTy *ItemType) { … } /// Parse the !find operation. Return null on error. /// /// Substr ::= !find(string, string [, start-int]) => int Init *TGParser::ParseOperationFind(Record *CurRec, const RecTy *ItemType) { … } /// Parse the !foreach and !filter operations. Return null on error. /// /// ForEach ::= !foreach(ID, list-or-dag, expr) => list<expr type> /// Filter ::= !foreach(ID, list, predicate) ==> list<list type> Init *TGParser::ParseOperationForEachFilter(Record *CurRec, const RecTy *ItemType) { … } Init *TGParser::ParseOperationCond(Record *CurRec, const RecTy *ItemType) { … } /// ParseSimpleValue - Parse a tblgen value. This returns null on error. /// /// SimpleValue ::= IDValue /// SimpleValue ::= INTVAL /// SimpleValue ::= STRVAL+ /// SimpleValue ::= CODEFRAGMENT /// SimpleValue ::= '?' /// SimpleValue ::= '{' ValueList '}' /// SimpleValue ::= ID '<' ValueListNE '>' /// SimpleValue ::= '[' ValueList ']' /// SimpleValue ::= '(' IDValue DagArgList ')' /// SimpleValue ::= CONCATTOK '(' Value ',' Value ')' /// SimpleValue ::= ADDTOK '(' Value ',' Value ')' /// SimpleValue ::= DIVTOK '(' Value ',' Value ')' /// SimpleValue ::= SUBTOK '(' Value ',' Value ')' /// SimpleValue ::= SHLTOK '(' Value ',' Value ')' /// SimpleValue ::= SRATOK '(' Value ',' Value ')' /// SimpleValue ::= SRLTOK '(' Value ',' Value ')' /// SimpleValue ::= LISTCONCATTOK '(' Value ',' Value ')' /// SimpleValue ::= LISTSPLATTOK '(' Value ',' Value ')' /// SimpleValue ::= LISTREMOVETOK '(' Value ',' Value ')' /// SimpleValue ::= RANGE '(' Value ')' /// SimpleValue ::= RANGE '(' Value ',' Value ')' /// SimpleValue ::= RANGE '(' Value ',' Value ',' Value ')' /// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')' /// SimpleValue ::= COND '(' [Value ':' Value,]+ ')' /// Init *TGParser::ParseSimpleValue(Record *CurRec, const RecTy *ItemType, IDParseMode Mode) { … } /// ParseValue - Parse a TableGen value. This returns null on error. /// /// Value ::= SimpleValue ValueSuffix* /// ValueSuffix ::= '{' BitList '}' /// ValueSuffix ::= '[' SliceElements ']' /// ValueSuffix ::= '.' ID /// Init *TGParser::ParseValue(Record *CurRec, const RecTy *ItemType, IDParseMode Mode) { … } /// ParseDagArgList - Parse the argument list for a dag literal expression. /// /// DagArg ::= Value (':' VARNAME)? /// DagArg ::= VARNAME /// DagArgList ::= DagArg /// DagArgList ::= DagArgList ',' DagArg void TGParser::ParseDagArgList( SmallVectorImpl<std::pair<llvm::Init*, StringInit*>> &Result, Record *CurRec) { … } /// ParseValueList - Parse a comma separated list of values, returning them /// in a vector. Note that this always expects to be able to parse at least one /// value. It returns an empty list if this is not possible. /// /// ValueList ::= Value (',' Value) /// void TGParser::ParseValueList(SmallVectorImpl<Init *> &Result, Record *CurRec, const RecTy *ItemType) { … } // ParseTemplateArgValueList - Parse a template argument list with the syntax // shown, filling in the Result vector. The open angle has been consumed. // An empty argument list is allowed. Return false if okay, true if an // error was detected. // // ArgValueList ::= '<' PostionalArgValueList [','] NamedArgValueList '>' // PostionalArgValueList ::= [Value {',' Value}*] // NamedArgValueList ::= [NameValue '=' Value {',' NameValue '=' Value}*] bool TGParser::ParseTemplateArgValueList( SmallVectorImpl<ArgumentInit *> &Result, Record *CurRec, Record *ArgsRec) { … } /// ParseDeclaration - Read a declaration, returning the name of field ID, or an /// empty string on error. This can happen in a number of different contexts, /// including within a def or in the template args for a class (in which case /// CurRec will be non-null) and within the template args for a multiclass (in /// which case CurRec will be null, but CurMultiClass will be set). This can /// also happen within a def that is within a multiclass, which will set both /// CurRec and CurMultiClass. /// /// Declaration ::= FIELD? Type ID ('=' Value)? /// Init *TGParser::ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs) { … } /// 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 '=' '{' RangeList '}' /// ForeachDeclaration ::= ID '=' RangePiece /// ForeachDeclaration ::= ID '=' Value /// VarInit *TGParser::ParseForeachDeclaration(Init *&ForeachListValue) { … } /// 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 class. If null, these are the template args for a /// multiclass. /// /// TemplateArgList ::= '<' Declaration (',' Declaration)* '>' /// bool TGParser::ParseTemplateArgList(Record *CurRec) { … } /// ParseBodyItem - Parse a single item within the body of a def or class. /// /// BodyItem ::= Declaration ';' /// BodyItem ::= LET ID OptionalBitList '=' Value ';' /// BodyItem ::= Defvar /// BodyItem ::= Dump /// BodyItem ::= Assert /// bool TGParser::ParseBodyItem(Record *CurRec) { … } /// ParseBody - Read the body of a class or def. Return true on error, false on /// success. /// /// Body ::= ';' /// Body ::= '{' BodyList '}' /// BodyList BodyItem* /// bool TGParser::ParseBody(Record *CurRec) { … } /// Apply the current let bindings to \a CurRec. /// \returns true on error, false otherwise. bool TGParser::ApplyLetStack(Record *CurRec) { … } /// Apply the current let bindings to the RecordsEntry. bool TGParser::ApplyLetStack(RecordsEntry &Entry) { … } /// ParseObjectBody - Parse the body of a def or class. This consists of an /// optional ClassList followed by a Body. CurRec is the current def or class /// that is being parsed. /// /// ObjectBody ::= BaseClassList Body /// BaseClassList ::= /*empty*/ /// BaseClassList ::= ':' BaseClassListNE /// BaseClassListNE ::= SubClassRef (',' SubClassRef)* /// bool TGParser::ParseObjectBody(Record *CurRec) { … } /// ParseDef - Parse and return a top level or multiclass record definition. /// Return false if okay, true if error. /// /// DefInst ::= DEF ObjectName ObjectBody /// bool TGParser::ParseDef(MultiClass *CurMultiClass) { … } /// ParseDefset - Parse a defset statement. /// /// Defset ::= DEFSET Type Id '=' '{' ObjectList '}' /// bool TGParser::ParseDefset() { … } /// ParseDeftype - Parse a defvar statement. /// /// Deftype ::= DEFTYPE Id '=' Type ';' /// bool TGParser::ParseDeftype() { … } /// ParseDefvar - Parse a defvar statement. /// /// Defvar ::= DEFVAR Id '=' Value ';' /// bool TGParser::ParseDefvar(Record *CurRec) { … } /// 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) { … } /// ParseIf - Parse an if statement. /// /// If ::= IF Value THEN IfBody /// If ::= IF Value THEN IfBody ELSE IfBody /// bool TGParser::ParseIf(MultiClass *CurMultiClass) { … } /// ParseIfBody - Parse the then-clause or else-clause of an if statement. /// /// IfBody ::= Object /// IfBody ::= '{' ObjectList '}' /// bool TGParser::ParseIfBody(MultiClass *CurMultiClass, StringRef Kind) { … } /// ParseAssert - Parse an assert statement. /// /// Assert ::= ASSERT condition , message ; bool TGParser::ParseAssert(MultiClass *CurMultiClass, Record *CurRec) { … } /// ParseClass - Parse a tblgen class definition. /// /// ClassInst ::= CLASS ID TemplateArgList? ObjectBody /// bool TGParser::ParseClass() { … } /// ParseLetList - Parse a non-empty list of assignment expressions into a list /// of LetRecords. /// /// LetList ::= LetItem (',' LetItem)* /// LetItem ::= ID OptionalRangeList '=' Value /// void TGParser::ParseLetList(SmallVectorImpl<LetRecord> &Result) { … } /// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of /// different related productions. This works inside multiclasses too. /// /// Object ::= LET LetList IN '{' ObjectList '}' /// Object ::= LET LetList IN Object /// bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) { … } /// ParseMultiClass - Parse a multiclass definition. /// /// MultiClassInst ::= MULTICLASS ID TemplateArgList? /// ':' BaseMultiClassList '{' MultiClassObject+ '}' /// MultiClassObject ::= Assert /// MultiClassObject ::= DefInst /// MultiClassObject ::= DefMInst /// MultiClassObject ::= Defvar /// MultiClassObject ::= Foreach /// MultiClassObject ::= If /// MultiClassObject ::= LETCommand '{' ObjectList '}' /// MultiClassObject ::= LETCommand Object /// bool TGParser::ParseMultiClass() { … } /// ParseDefm - Parse the instantiation of a multiclass. /// /// DefMInst ::= DEFM ID ':' DefmSubClassRef ';' /// bool TGParser::ParseDefm(MultiClass *CurMultiClass) { … } /// ParseObject /// Object ::= ClassInst /// Object ::= DefInst /// Object ::= MultiClassInst /// Object ::= DefMInst /// Object ::= LETCommand '{' ObjectList '}' /// Object ::= LETCommand Object /// Object ::= Defset /// Object ::= Deftype /// Object ::= Defvar /// Object ::= Assert /// Object ::= Dump bool TGParser::ParseObject(MultiClass *MC) { … } /// ParseObjectList /// ObjectList :== Object* bool TGParser::ParseObjectList(MultiClass *MC) { … } bool TGParser::ParseFile() { … } // Check the types of the template argument values for a class // inheritance, multiclass invocation, or anonymous class invocation. // If necessary, replace an argument with a cast to the required type. // The argument count has already been checked. bool TGParser::CheckTemplateArgValues( SmallVectorImpl<llvm::ArgumentInit *> &Values, SMLoc Loc, Record *ArgsRec) { … } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void RecordsEntry::dump() const { if (Loop) Loop->dump(); if (Rec) Rec->dump(); } LLVM_DUMP_METHOD void ForeachLoop::dump() const { errs() << "foreach " << IterVar->getAsString() << " = " << ListValue->getAsString() << " in {\n"; for (const auto &E : Entries) E.dump(); errs() << "}\n"; } LLVM_DUMP_METHOD void MultiClass::dump() const { errs() << "Record:\n"; Rec.dump(); errs() << "Defs:\n"; for (const auto &E : Entries) E.dump(); } #endif bool TGParser::ParseDump(MultiClass *CurMultiClass, Record *CurRec) { … }