diff options
Diffstat (limited to 'contrib/llvm/lib/TableGen')
-rw-r--r-- | contrib/llvm/lib/TableGen/Error.cpp | 7 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/JSONBackend.cpp | 7 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/Main.cpp | 7 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/Record.cpp | 204 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/SetTheory.cpp | 7 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/StringMatcher.cpp | 7 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/TGLexer.cpp | 28 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/TGLexer.h | 15 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/TGParser.cpp | 280 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/TGParser.h | 11 | ||||
-rw-r--r-- | contrib/llvm/lib/TableGen/TableGenBackend.cpp | 7 |
11 files changed, 471 insertions, 109 deletions
diff --git a/contrib/llvm/lib/TableGen/Error.cpp b/contrib/llvm/lib/TableGen/Error.cpp index e6171c71efc0..7523b32ca0e5 100644 --- a/contrib/llvm/lib/TableGen/Error.cpp +++ b/contrib/llvm/lib/TableGen/Error.cpp @@ -1,9 +1,8 @@ //===- Error.cpp - tblgen error handling helper routines --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/contrib/llvm/lib/TableGen/JSONBackend.cpp b/contrib/llvm/lib/TableGen/JSONBackend.cpp index 36cb2208a294..196644cda667 100644 --- a/contrib/llvm/lib/TableGen/JSONBackend.cpp +++ b/contrib/llvm/lib/TableGen/JSONBackend.cpp @@ -1,9 +1,8 @@ //===- JSONBackend.cpp - Generate a JSON dump of all records. -*- C++ -*-=====// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/contrib/llvm/lib/TableGen/Main.cpp b/contrib/llvm/lib/TableGen/Main.cpp index 02698416609f..bcd39584e450 100644 --- a/contrib/llvm/lib/TableGen/Main.cpp +++ b/contrib/llvm/lib/TableGen/Main.cpp @@ -1,9 +1,8 @@ //===- Main.cpp - Top-Level TableGen implementation -----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/contrib/llvm/lib/TableGen/Record.cpp b/contrib/llvm/lib/TableGen/Record.cpp index cf1685a2e8c2..27d1bdc7f4c3 100644 --- a/contrib/llvm/lib/TableGen/Record.cpp +++ b/contrib/llvm/lib/TableGen/Record.cpp @@ -1,9 +1,8 @@ //===- Record.cpp - Record implementation ---------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -16,9 +15,11 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" @@ -31,14 +32,20 @@ #include <cassert> #include <cstdint> #include <memory> +#include <map> #include <string> #include <utility> #include <vector> using namespace llvm; +#define DEBUG_TYPE "tblgen-records" + static BumpPtrAllocator Allocator; +STATISTIC(CodeInitsConstructed, + "The total number of unique CodeInits constructed"); + //===----------------------------------------------------------------------===// // Type implementations //===----------------------------------------------------------------------===// @@ -451,7 +458,7 @@ Init *BitsInit::resolveReferences(Resolver &R) const { } IntInit *IntInit::get(int64_t V) { - static DenseMap<int64_t, IntInit*> ThePool; + static std::map<int64_t, IntInit*> ThePool; IntInit *&I = ThePool[V]; if (!I) I = new(Allocator) IntInit(V); @@ -507,13 +514,20 @@ IntInit::convertInitializerBitRange(ArrayRef<unsigned> Bits) const { return BitsInit::get(NewBits); } -CodeInit *CodeInit::get(StringRef V) { - static StringMap<CodeInit*, BumpPtrAllocator &> ThePool(Allocator); +CodeInit *CodeInit::get(StringRef V, const SMLoc &Loc) { + static StringSet<BumpPtrAllocator &> ThePool(Allocator); - auto &Entry = *ThePool.insert(std::make_pair(V, nullptr)).first; - if (!Entry.second) - Entry.second = new(Allocator) CodeInit(Entry.getKey()); - return Entry.second; + CodeInitsConstructed++; + + // Unlike StringMap, StringSet doesn't accept empty keys. + if (V.empty()) + return new (Allocator) CodeInit("", Loc); + + // Location tracking prevents us from de-duping CodeInits as we're never + // called with the same string and same location twice. However, we can at + // least de-dupe the strings for a modest saving. + auto &Entry = *ThePool.insert(V).first; + return new(Allocator) CodeInit(Entry.getKey(), Loc); } StringInit *StringInit::get(StringRef V) { @@ -529,7 +543,7 @@ Init *StringInit::convertInitializerTo(RecTy *Ty) const { if (isa<StringRecTy>(Ty)) return const_cast<StringInit *>(this); if (isa<CodeRecTy>(Ty)) - return CodeInit::get(getValue()); + return CodeInit::get(getValue(), SMLoc()); return nullptr; } @@ -843,6 +857,28 @@ Init *BinOpInit::getStrConcat(Init *I0, Init *I1) { return BinOpInit::get(BinOpInit::STRCONCAT, I0, I1, StringRecTy::get()); } +static ListInit *ConcatListInits(const ListInit *LHS, + const ListInit *RHS) { + SmallVector<Init *, 8> Args; + Args.insert(Args.end(), LHS->begin(), LHS->end()); + Args.insert(Args.end(), RHS->begin(), RHS->end()); + return ListInit::get(Args, LHS->getElementType()); +} + +Init *BinOpInit::getListConcat(TypedInit *LHS, Init *RHS) { + assert(isa<ListRecTy>(LHS->getType()) && "First arg must be a list"); + + // Shortcut for the common case of concatenating two lists. + if (const ListInit *LHSList = dyn_cast<ListInit>(LHS)) + if (const ListInit *RHSList = dyn_cast<ListInit>(RHS)) + return ConcatListInits(LHSList, RHSList); + return BinOpInit::get(BinOpInit::LISTCONCAT, LHS, RHS, LHS->getType()); +} + +Init *BinOpInit::getListSplat(TypedInit *LHS, Init *RHS) { + return BinOpInit::get(BinOpInit::LISTSPLAT, LHS, RHS, LHS->getType()); +} + Init *BinOpInit::Fold(Record *CurRec) const { switch (getOpcode()) { case CONCAT: { @@ -883,6 +919,15 @@ Init *BinOpInit::Fold(Record *CurRec) const { } break; } + case LISTSPLAT: { + TypedInit *Value = dyn_cast<TypedInit>(LHS); + IntInit *Size = dyn_cast<IntInit>(RHS); + if (Value && Size) { + SmallVector<Init *, 8> Args(Size->getValue(), Value); + return ListInit::get(Args, Value->getType()); + } + break; + } case STRCONCAT: { StringInit *LHSs = dyn_cast<StringInit>(LHS); StringInit *RHSs = dyn_cast<StringInit>(RHS); @@ -931,6 +976,7 @@ Init *BinOpInit::Fold(Record *CurRec) const { break; } case ADD: + case MUL: case AND: case OR: case SHL: @@ -946,6 +992,7 @@ Init *BinOpInit::Fold(Record *CurRec) const { switch (getOpcode()) { default: llvm_unreachable("Bad opcode!"); case ADD: Result = LHSv + RHSv; break; + case MUL: Result = LHSv * RHSv; break; case AND: Result = LHSv & RHSv; break; case OR: Result = LHSv | RHSv; break; case SHL: Result = LHSv << RHSv; break; @@ -975,6 +1022,7 @@ std::string BinOpInit::getAsString() const { switch (getOpcode()) { case CONCAT: Result = "!con"; break; case ADD: Result = "!add"; break; + case MUL: Result = "!mul"; break; case AND: Result = "!and"; break; case OR: Result = "!or"; break; case SHL: Result = "!shl"; break; @@ -987,6 +1035,7 @@ std::string BinOpInit::getAsString() const { case GE: Result = "!ge"; break; case GT: Result = "!gt"; break; case LISTCONCAT: Result = "!listconcat"; break; + case LISTSPLAT: Result = "!listsplat"; break; case STRCONCAT: Result = "!strconcat"; break; } return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")"; @@ -1694,6 +1743,137 @@ Init *FieldInit::Fold(Record *CurRec) const { return const_cast<FieldInit *>(this); } +static void ProfileCondOpInit(FoldingSetNodeID &ID, + ArrayRef<Init *> CondRange, + ArrayRef<Init *> ValRange, + const RecTy *ValType) { + assert(CondRange.size() == ValRange.size() && + "Number of conditions and values must match!"); + ID.AddPointer(ValType); + ArrayRef<Init *>::iterator Case = CondRange.begin(); + ArrayRef<Init *>::iterator Val = ValRange.begin(); + + while (Case != CondRange.end()) { + ID.AddPointer(*Case++); + ID.AddPointer(*Val++); + } +} + +void CondOpInit::Profile(FoldingSetNodeID &ID) const { + ProfileCondOpInit(ID, + makeArrayRef(getTrailingObjects<Init *>(), NumConds), + makeArrayRef(getTrailingObjects<Init *>() + NumConds, NumConds), + ValType); +} + +CondOpInit * +CondOpInit::get(ArrayRef<Init *> CondRange, + ArrayRef<Init *> ValRange, RecTy *Ty) { + assert(CondRange.size() == ValRange.size() && + "Number of conditions and values must match!"); + + static FoldingSet<CondOpInit> ThePool; + FoldingSetNodeID ID; + ProfileCondOpInit(ID, CondRange, ValRange, Ty); + + void *IP = nullptr; + if (CondOpInit *I = ThePool.FindNodeOrInsertPos(ID, IP)) + return I; + + void *Mem = Allocator.Allocate(totalSizeToAlloc<Init *>(2*CondRange.size()), + alignof(BitsInit)); + CondOpInit *I = new(Mem) CondOpInit(CondRange.size(), Ty); + + std::uninitialized_copy(CondRange.begin(), CondRange.end(), + I->getTrailingObjects<Init *>()); + std::uninitialized_copy(ValRange.begin(), ValRange.end(), + I->getTrailingObjects<Init *>()+CondRange.size()); + ThePool.InsertNode(I, IP); + return I; +} + +Init *CondOpInit::resolveReferences(Resolver &R) const { + SmallVector<Init*, 4> NewConds; + bool Changed = false; + for (const Init *Case : getConds()) { + Init *NewCase = Case->resolveReferences(R); + NewConds.push_back(NewCase); + Changed |= NewCase != Case; + } + + SmallVector<Init*, 4> NewVals; + for (const Init *Val : getVals()) { + Init *NewVal = Val->resolveReferences(R); + NewVals.push_back(NewVal); + Changed |= NewVal != Val; + } + + if (Changed) + return (CondOpInit::get(NewConds, NewVals, + getValType()))->Fold(R.getCurrentRecord()); + + return const_cast<CondOpInit *>(this); +} + +Init *CondOpInit::Fold(Record *CurRec) const { + for ( unsigned i = 0; i < NumConds; ++i) { + Init *Cond = getCond(i); + Init *Val = getVal(i); + + if (IntInit *CondI = dyn_cast_or_null<IntInit>( + Cond->convertInitializerTo(IntRecTy::get()))) { + if (CondI->getValue()) + return Val->convertInitializerTo(getValType()); + } else + return const_cast<CondOpInit *>(this); + } + + PrintFatalError(CurRec->getLoc(), + CurRec->getName() + + " does not have any true condition in:" + + this->getAsString()); + return nullptr; +} + +bool CondOpInit::isConcrete() const { + for (const Init *Case : getConds()) + if (!Case->isConcrete()) + return false; + + for (const Init *Val : getVals()) + if (!Val->isConcrete()) + return false; + + return true; +} + +bool CondOpInit::isComplete() const { + for (const Init *Case : getConds()) + if (!Case->isComplete()) + return false; + + for (const Init *Val : getVals()) + if (!Val->isConcrete()) + return false; + + return true; +} + +std::string CondOpInit::getAsString() const { + std::string Result = "!cond("; + for (unsigned i = 0; i < getNumConds(); i++) { + Result += getCond(i)->getAsString() + ": "; + Result += getVal(i)->getAsString(); + if (i != getNumConds()-1) + Result += ", "; + } + return Result + ")"; +} + +Init *CondOpInit::getBit(unsigned Bit) const { + return VarBitInit::get(const_cast<CondOpInit *>(this), Bit); +} + static void ProfileDagInit(FoldingSetNodeID &ID, Init *V, StringInit *VN, ArrayRef<Init *> ArgRange, ArrayRef<StringInit *> NameRange) { diff --git a/contrib/llvm/lib/TableGen/SetTheory.cpp b/contrib/llvm/lib/TableGen/SetTheory.cpp index 733e0aeef623..a870e41d58f8 100644 --- a/contrib/llvm/lib/TableGen/SetTheory.cpp +++ b/contrib/llvm/lib/TableGen/SetTheory.cpp @@ -1,9 +1,8 @@ //===- SetTheory.cpp - Generate ordered sets from DAG expressions ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/contrib/llvm/lib/TableGen/StringMatcher.cpp b/contrib/llvm/lib/TableGen/StringMatcher.cpp index 2c4d1f33997d..2fca068893f3 100644 --- a/contrib/llvm/lib/TableGen/StringMatcher.cpp +++ b/contrib/llvm/lib/TableGen/StringMatcher.cpp @@ -1,9 +1,8 @@ //===- StringMatcher.cpp - Generate a matcher for input strings -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/contrib/llvm/lib/TableGen/TGLexer.cpp b/contrib/llvm/lib/TableGen/TGLexer.cpp index 16aeee561075..d28c62b3133d 100644 --- a/contrib/llvm/lib/TableGen/TGLexer.cpp +++ b/contrib/llvm/lib/TableGen/TGLexer.cpp @@ -1,9 +1,8 @@ //===- TGLexer.cpp - Lexer for TableGen -----------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -37,6 +36,7 @@ struct { const char *Word; } PreprocessorDirs[] = { { tgtok::Ifdef, "ifdef" }, + { tgtok::Ifndef, "ifndef" }, { tgtok::Else, "else" }, { tgtok::Endif, "endif" }, { tgtok::Define, "define" } @@ -545,6 +545,7 @@ tgtok::TokKind TGLexer::LexExclaim() { .Case("ge", tgtok::XGe) .Case("gt", tgtok::XGt) .Case("if", tgtok::XIf) + .Case("cond", tgtok::XCond) .Case("isa", tgtok::XIsA) .Case("head", tgtok::XHead) .Case("tail", tgtok::XTail) @@ -552,6 +553,7 @@ tgtok::TokKind TGLexer::LexExclaim() { .Case("con", tgtok::XConcat) .Case("dag", tgtok::XDag) .Case("add", tgtok::XADD) + .Case("mul", tgtok::XMUL) .Case("and", tgtok::XAND) .Case("or", tgtok::XOR) .Case("shl", tgtok::XSHL) @@ -563,6 +565,7 @@ tgtok::TokKind TGLexer::LexExclaim() { .Case("foldl", tgtok::XFoldl) .Case("foreach", tgtok::XForEach) .Case("listconcat", tgtok::XListConcat) + .Case("listsplat", tgtok::XListSplat) .Case("strconcat", tgtok::XStrConcat) .Default(tgtok::Error); @@ -674,21 +677,28 @@ tgtok::TokKind TGLexer::lexPreprocessor( PrintFatalError("lexPreprocessor() called for unknown " "preprocessor directive"); - if (Kind == tgtok::Ifdef) { + if (Kind == tgtok::Ifdef || Kind == tgtok::Ifndef) { StringRef MacroName = prepLexMacroName(); + StringRef IfTokName = Kind == tgtok::Ifdef ? "#ifdef" : "#ifndef"; if (MacroName.empty()) - return ReturnError(TokStart, "Expected macro name after #ifdef"); + return ReturnError(TokStart, "Expected macro name after " + IfTokName); bool MacroIsDefined = DefinedMacros.count(MacroName) != 0; + // Canonicalize ifndef to ifdef equivalent + if (Kind == tgtok::Ifndef) { + MacroIsDefined = !MacroIsDefined; + Kind = tgtok::Ifdef; + } + // Regardless of whether we are processing tokens or not, // we put the #ifdef control on stack. PrepIncludeStack.back()->push_back( {Kind, MacroIsDefined, SMLoc::getFromPointer(TokStart)}); if (!prepSkipDirectiveEnd()) - return ReturnError(CurPtr, - "Only comments are supported after #ifdef NAME"); + return ReturnError(CurPtr, "Only comments are supported after " + + IfTokName + " NAME"); // If we were not processing tokens before this #ifdef, // then just return back to the lines skipping code. @@ -712,7 +722,7 @@ tgtok::TokKind TGLexer::lexPreprocessor( // Check if this #else is correct before calling prepSkipDirectiveEnd(), // which will move CurPtr away from the beginning of #else. if (PrepIncludeStack.back()->empty()) - return ReturnError(TokStart, "#else without #ifdef"); + return ReturnError(TokStart, "#else without #ifdef or #ifndef"); PreprocessorControlDesc IfdefEntry = PrepIncludeStack.back()->back(); diff --git a/contrib/llvm/lib/TableGen/TGLexer.h b/contrib/llvm/lib/TableGen/TGLexer.h index e9980b36b97b..3085ab2c0478 100644 --- a/contrib/llvm/lib/TableGen/TGLexer.h +++ b/contrib/llvm/lib/TableGen/TGLexer.h @@ -1,9 +1,8 @@ //===- TGLexer.h - Lexer for TableGen Files ---------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -50,9 +49,9 @@ namespace tgtok { MultiClass, String, Defset, // !keywords. - XConcat, XADD, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XStrConcat, XCast, - XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XEq, XIsA, XDag, - XNe, XLe, XLt, XGe, XGt, + XConcat, XADD, XMUL, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XListSplat, + XStrConcat, XCast, XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, + XIf, XCond, XEq, XIsA, XDag, XNe, XLe, XLt, XGe, XGt, // Integer value. IntVal, @@ -66,7 +65,7 @@ namespace tgtok { // Preprocessing tokens for internal usage by the lexer. // They are never returned as a result of Lex(). - Ifdef, Else, Endif, Define + Ifdef, Ifndef, Else, Endif, Define }; } diff --git a/contrib/llvm/lib/TableGen/TGParser.cpp b/contrib/llvm/lib/TableGen/TGParser.cpp index 1d1f3603c83c..a9ace152d59e 100644 --- a/contrib/llvm/lib/TableGen/TGParser.cpp +++ b/contrib/llvm/lib/TableGen/TGParser.cpp @@ -1,9 +1,8 @@ //===- TGParser.cpp - Parser for TableGen Files ---------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -537,8 +536,14 @@ Record *TGParser::ParseClassID() { } Record *Result = Records.getClass(Lex.getCurStrVal()); - if (!Result) - TokError("Couldn't find class '" + Lex.getCurStrVal() + "'"); + if (!Result) { + std::string Msg("Couldn't find class '" + Lex.getCurStrVal() + "'"); + if (MultiClasses[Lex.getCurStrVal()].get()) + TokError(Msg + ". Use 'defm' if you meant to use multiclass '" + + Lex.getCurStrVal() + "'"); + else + TokError(Msg); + } Lex.Lex(); return Result; @@ -661,35 +666,47 @@ ParseSubMultiClassReference(MultiClass *CurMC) { /// RangePiece ::= INTVAL /// RangePiece ::= INTVAL '-' INTVAL /// RangePiece ::= INTVAL INTVAL -bool TGParser::ParseRangePiece(SmallVectorImpl<unsigned> &Ranges) { - if (Lex.getCode() != tgtok::IntVal) { - TokError("expected integer or bitrange"); - return true; - } - int64_t Start = Lex.getCurIntVal(); +bool TGParser::ParseRangePiece(SmallVectorImpl<unsigned> &Ranges, + TypedInit *FirstItem) { + Init *CurVal = FirstItem; + if (!CurVal) + CurVal = ParseValue(nullptr); + + IntInit *II = dyn_cast_or_null<IntInit>(CurVal); + if (!II) + return TokError("expected integer or bitrange"); + + int64_t Start = II->getValue(); int64_t End; if (Start < 0) return TokError("invalid range, cannot be negative"); - switch (Lex.Lex()) { // eat first character. + switch (Lex.getCode()) { default: Ranges.push_back(Start); return false; - case tgtok::minus: - if (Lex.Lex() != tgtok::IntVal) { + case tgtok::minus: { + Lex.Lex(); // eat + + Init *I_End = ParseValue(nullptr); + IntInit *II_End = dyn_cast_or_null<IntInit>(I_End); + if (!II_End) { TokError("expected integer value as end of range"); return true; } - End = Lex.getCurIntVal(); + + End = II_End->getValue(); break; - case tgtok::IntVal: + } + case tgtok::IntVal: { End = -Lex.getCurIntVal(); + Lex.Lex(); break; } + } if (End < 0) return TokError("invalid range, cannot be negative"); - Lex.Lex(); // Add to the range. if (Start < End) @@ -1024,6 +1041,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { case tgtok::XConcat: case tgtok::XADD: + case tgtok::XMUL: case tgtok::XAND: case tgtok::XOR: case tgtok::XSRA: @@ -1036,6 +1054,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { case tgtok::XGe: case tgtok::XGt: case tgtok::XListConcat: + case tgtok::XListSplat: case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')' tgtok::TokKind OpTok = Lex.getCode(); SMLoc OpLoc = Lex.getLoc(); @@ -1046,6 +1065,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { default: llvm_unreachable("Unhandled code!"); case tgtok::XConcat: Code = BinOpInit::CONCAT; break; case tgtok::XADD: Code = BinOpInit::ADD; break; + case tgtok::XMUL: Code = BinOpInit::MUL; break; case tgtok::XAND: Code = BinOpInit::AND; break; case tgtok::XOR: Code = BinOpInit::OR; break; case tgtok::XSRA: Code = BinOpInit::SRA; break; @@ -1058,6 +1078,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { case tgtok::XGe: Code = BinOpInit::GE; break; case tgtok::XGt: Code = BinOpInit::GT; break; case tgtok::XListConcat: Code = BinOpInit::LISTCONCAT; break; + case tgtok::XListSplat: Code = BinOpInit::LISTSPLAT; break; case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break; } @@ -1076,6 +1097,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { case tgtok::XSRL: case tgtok::XSHL: case tgtok::XADD: + case tgtok::XMUL: Type = IntRecTy::get(); ArgType = IntRecTy::get(); break; @@ -1095,6 +1117,9 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { // We don't know the list type until we parse the first argument ArgType = ItemType; break; + case tgtok::XListSplat: + // Can't do any typechecking until we parse the first argument. + break; case tgtok::XStrConcat: Type = StringRecTy::get(); ArgType = StringRecTy::get(); @@ -1134,6 +1159,33 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { return nullptr; } break; + case BinOpInit::LISTSPLAT: + if (ItemType && InitList.size() == 1) { + if (!isa<ListRecTy>(ItemType)) { + Error(OpLoc, + Twine("expected output type to be a list, got type '") + + ItemType->getAsString() + "'"); + return nullptr; + } + if (!ArgType->getListTy()->typeIsConvertibleTo(ItemType)) { + Error(OpLoc, Twine("expected first arg type to be '") + + ArgType->getAsString() + + "', got value of type '" + + cast<ListRecTy>(ItemType) + ->getElementType() + ->getAsString() + + "'"); + return nullptr; + } + } + if (InitList.size() == 2 && !isa<IntRecTy>(ArgType)) { + Error(InitLoc, Twine("expected second parameter to be an int, got " + "value of type '") + + ArgType->getAsString() + "'"); + return nullptr; + } + ArgType = nullptr; // Broken invariant: types not identical. + break; case BinOpInit::EQ: case BinOpInit::NE: if (!ArgType->typeIsConvertibleTo(IntRecTy::get()) && @@ -1155,7 +1207,8 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { } if (Code != BinOpInit::ADD && Code != BinOpInit::AND && Code != BinOpInit::OR && Code != BinOpInit::SRA && - Code != BinOpInit::SRL && Code != BinOpInit::SHL) + Code != BinOpInit::SRL && Code != BinOpInit::SHL && + Code != BinOpInit::MUL) ArgType = Resolved; } @@ -1170,14 +1223,19 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { } Lex.Lex(); // eat the ')' + // listconcat returns a list with type of the argument. if (Code == BinOpInit::LISTCONCAT) Type = ArgType; + // listsplat returns a list of type of the *first* argument. + if (Code == BinOpInit::LISTSPLAT) + Type = cast<TypedInit>(InitList.front())->getType()->getListTy(); // We allow multiple operands to associative operators like !strconcat as // shorthand for nesting them. if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT || Code == BinOpInit::CONCAT || Code == BinOpInit::ADD || - Code == BinOpInit::AND || Code == BinOpInit::OR) { + Code == BinOpInit::AND || Code == BinOpInit::OR || + Code == BinOpInit::MUL) { while (InitList.size() > 2) { Init *RHS = InitList.pop_back_val(); RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type))->Fold(CurRec); @@ -1445,6 +1503,9 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec); } + case tgtok::XCond: + return ParseOperationCond(CurRec, ItemType); + case tgtok::XFoldl: { // Value ::= !foldl '(' Id ',' Id ',' Value ',' Value ',' Value ')' Lex.Lex(); // eat the operation @@ -1603,6 +1664,91 @@ RecTy *TGParser::ParseOperatorType() { return Type; } +Init *TGParser::ParseOperationCond(Record *CurRec, RecTy *ItemType) { + Lex.Lex(); // eat the operation 'cond' + + if (Lex.getCode() != tgtok::l_paren) { + TokError("expected '(' after !cond operator"); + return nullptr; + } + Lex.Lex(); // eat the '(' + + // Parse through '[Case: Val,]+' + SmallVector<Init *, 4> Case; + SmallVector<Init *, 4> Val; + while (true) { + if (Lex.getCode() == tgtok::r_paren) { + Lex.Lex(); // eat the ')' + break; + } + + Init *V = ParseValue(CurRec); + if (!V) + return nullptr; + Case.push_back(V); + + if (Lex.getCode() != tgtok::colon) { + TokError("expected ':' following a condition in !cond operator"); + return nullptr; + } + Lex.Lex(); // eat the ':' + + V = ParseValue(CurRec, ItemType); + if (!V) + return nullptr; + Val.push_back(V); + + if (Lex.getCode() == tgtok::r_paren) { + Lex.Lex(); // eat the ')' + break; + } + + if (Lex.getCode() != tgtok::comma) { + TokError("expected ',' or ')' following a value in !cond operator"); + return nullptr; + } + Lex.Lex(); // eat the ',' + } + + if (Case.size() < 1) { + TokError("there should be at least 1 'condition : value' in the !cond operator"); + return nullptr; + } + + // resolve type + RecTy *Type = nullptr; + for (Init *V : Val) { + RecTy *VTy = nullptr; + if (TypedInit *Vt = dyn_cast<TypedInit>(V)) + VTy = Vt->getType(); + if (BitsInit *Vbits = dyn_cast<BitsInit>(V)) + VTy = BitsRecTy::get(Vbits->getNumBits()); + if (isa<BitInit>(V)) + VTy = BitRecTy::get(); + + if (Type == nullptr) { + if (!isa<UnsetInit>(V)) + Type = VTy; + } else { + if (!isa<UnsetInit>(V)) { + RecTy *RType = resolveTypes(Type, VTy); + if (!RType) { + TokError(Twine("inconsistent types '") + Type->getAsString() + + "' and '" + VTy->getAsString() + "' for !cond"); + return nullptr; + } + Type = RType; + } + } + } + + if (!Type) { + TokError("could not determine type for !cond from its arguments"); + return nullptr; + } + return CondOpInit::get(Case, Val, Type)->Fold(CurRec); +} + /// ParseSimpleValue - Parse a tblgen value. This returns null on error. /// /// SimpleValue ::= IDValue @@ -1620,7 +1766,9 @@ RecTy *TGParser::ParseOperatorType() { /// SimpleValue ::= SRATOK '(' Value ',' Value ')' /// SimpleValue ::= SRLTOK '(' Value ',' Value ')' /// SimpleValue ::= LISTCONCATTOK '(' Value ',' Value ')' +/// SimpleValue ::= LISTSPLATTOK '(' Value ',' Value ')' /// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')' +/// SimpleValue ::= COND '(' [Value ':' Value,]+ ')' /// Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) { @@ -1656,7 +1804,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, break; } case tgtok::CodeFragment: - R = CodeInit::get(Lex.getCurStrVal()); + R = CodeInit::get(Lex.getCurStrVal(), Lex.getLoc()); Lex.Lex(); break; case tgtok::question: @@ -1919,6 +2067,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, case tgtok::XConcat: case tgtok::XDag: case tgtok::XADD: + case tgtok::XMUL: case tgtok::XAND: case tgtok::XOR: case tgtok::XSRA: @@ -1931,8 +2080,10 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, case tgtok::XGe: case tgtok::XGt: case tgtok::XListConcat: + case tgtok::XListSplat: case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')' case tgtok::XIf: + case tgtok::XCond: case tgtok::XFoldl: case tgtok::XForEach: case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')' @@ -2024,25 +2175,41 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) { case tgtok::paste: SMLoc PasteLoc = Lex.getLoc(); - - // Create a !strconcat() operation, first casting each operand to - // a string if necessary. - TypedInit *LHS = dyn_cast<TypedInit>(Result); if (!LHS) { Error(PasteLoc, "LHS of paste is not typed!"); return nullptr; } + // Check if it's a 'listA # listB' + if (isa<ListRecTy>(LHS->getType())) { + Lex.Lex(); // Eat the '#'. + + switch (Lex.getCode()) { + case tgtok::colon: + case tgtok::semi: + case tgtok::l_brace: + Result = LHS; // trailing paste, ignore. + break; + default: + Init *RHSResult = ParseValue(CurRec, ItemType, ParseNameMode); + Result = BinOpInit::getListConcat(LHS, RHSResult); + } + break; + } + + // Create a !strconcat() operation, first casting each operand to + // a string if necessary. if (LHS->getType() != StringRecTy::get()) { - LHS = dyn_cast<TypedInit>( + auto CastLHS = dyn_cast<TypedInit>( UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get()) ->Fold(CurRec)); - if (!LHS) { - Error(PasteLoc, Twine("can't cast '") + LHS->getAsString() + - "' to string"); + if (!CastLHS) { + Error(PasteLoc, + Twine("can't cast '") + LHS->getAsString() + "' to string"); return nullptr; } + LHS = CastLHS; } TypedInit *RHS = nullptr; @@ -2069,14 +2236,15 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) { } if (RHS->getType() != StringRecTy::get()) { - RHS = dyn_cast<TypedInit>( + auto CastRHS = dyn_cast<TypedInit>( UnOpInit::get(UnOpInit::CAST, RHS, StringRecTy::get()) ->Fold(CurRec)); - if (!RHS) { - Error(PasteLoc, Twine("can't cast '") + RHS->getAsString() + - "' to string"); + if (!CastRHS) { + Error(PasteLoc, + Twine("can't cast '") + RHS->getAsString() + "' to string"); return nullptr; } + RHS = CastRHS; } break; @@ -2167,6 +2335,10 @@ void TGParser::ParseValueList(SmallVectorImpl<Init*> &Result, Record *CurRec, while (Lex.getCode() == tgtok::comma) { Lex.Lex(); // Eat the comma + // ignore trailing comma for lists + if (Lex.getCode() == tgtok::r_square) + return; + if (ArgsRec && !EltTy) { ArrayRef<Init *> TArgs = ArgsRec->getTemplateArgs(); if (ArgN >= TArgs.size()) { @@ -2279,12 +2451,6 @@ VarInit *TGParser::ParseForeachDeclaration(Init *&ForeachListValue) { SmallVector<unsigned, 16> Ranges; switch (Lex.getCode()) { - case tgtok::IntVal: { // RangePiece. - if (ParseRangePiece(Ranges)) - return nullptr; - break; - } - case tgtok::l_brace: { // '{' RangeList '}' Lex.Lex(); // eat the '{' ParseRangeList(Ranges); @@ -2299,23 +2465,35 @@ VarInit *TGParser::ParseForeachDeclaration(Init *&ForeachListValue) { default: { SMLoc ValueLoc = Lex.getLoc(); Init *I = ParseValue(nullptr); - TypedInit *TI = dyn_cast<TypedInit>(I); - if (!TI || !isa<ListRecTy>(TI->getType())) { - std::string Type; - if (TI) - Type = (Twine("' of type '") + TI->getType()->getAsString()).str(); - Error(ValueLoc, "expected a list, got '" + I->getAsString() + Type + "'"); - if (CurMultiClass) - PrintNote({}, "references to multiclass template arguments cannot be " - "resolved at this time"); + if (!I) return nullptr; + + TypedInit *TI = dyn_cast<TypedInit>(I); + if (TI && isa<ListRecTy>(TI->getType())) { + ForeachListValue = I; + IterType = cast<ListRecTy>(TI->getType())->getElementType(); + break; } - ForeachListValue = I; - IterType = cast<ListRecTy>(TI->getType())->getElementType(); - break; + + if (TI) { + if (ParseRangePiece(Ranges, TI)) + return nullptr; + break; + } + + std::string Type; + if (TI) + Type = (Twine("' of type '") + TI->getType()->getAsString()).str(); + Error(ValueLoc, "expected a list, got '" + I->getAsString() + Type + "'"); + if (CurMultiClass) { + PrintNote({}, "references to multiclass template arguments cannot be " + "resolved at this time"); + } + return nullptr; } } + if (!Ranges.empty()) { assert(!IterType && "Type already initialized?"); IterType = IntRecTy::get(); diff --git a/contrib/llvm/lib/TableGen/TGParser.h b/contrib/llvm/lib/TableGen/TGParser.h index e3849043513b..af2b639f8d59 100644 --- a/contrib/llvm/lib/TableGen/TGParser.h +++ b/contrib/llvm/lib/TableGen/TGParser.h @@ -1,9 +1,8 @@ //===- TGParser.h - Parser for TableGen Files -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -191,9 +190,11 @@ private: // Parser methods. bool ParseOptionalRangeList(SmallVectorImpl<unsigned> &Ranges); bool ParseOptionalBitList(SmallVectorImpl<unsigned> &Ranges); void ParseRangeList(SmallVectorImpl<unsigned> &Result); - bool ParseRangePiece(SmallVectorImpl<unsigned> &Ranges); + bool ParseRangePiece(SmallVectorImpl<unsigned> &Ranges, + TypedInit *FirstItem = nullptr); RecTy *ParseType(); Init *ParseOperation(Record *CurRec, RecTy *ItemType); + Init *ParseOperationCond(Record *CurRec, RecTy *ItemType); RecTy *ParseOperatorType(); Init *ParseObjectName(MultiClass *CurMultiClass); Record *ParseClassID(); diff --git a/contrib/llvm/lib/TableGen/TableGenBackend.cpp b/contrib/llvm/lib/TableGen/TableGenBackend.cpp index 77ed8414b15f..e11b28e8cff9 100644 --- a/contrib/llvm/lib/TableGen/TableGenBackend.cpp +++ b/contrib/llvm/lib/TableGen/TableGenBackend.cpp @@ -1,9 +1,8 @@ //===- TableGenBackend.cpp - Utilities for TableGen Backends ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // |