aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/TableGen')
-rw-r--r--contrib/llvm/lib/TableGen/Error.cpp7
-rw-r--r--contrib/llvm/lib/TableGen/JSONBackend.cpp7
-rw-r--r--contrib/llvm/lib/TableGen/Main.cpp7
-rw-r--r--contrib/llvm/lib/TableGen/Record.cpp204
-rw-r--r--contrib/llvm/lib/TableGen/SetTheory.cpp7
-rw-r--r--contrib/llvm/lib/TableGen/StringMatcher.cpp7
-rw-r--r--contrib/llvm/lib/TableGen/TGLexer.cpp28
-rw-r--r--contrib/llvm/lib/TableGen/TGLexer.h15
-rw-r--r--contrib/llvm/lib/TableGen/TGParser.cpp280
-rw-r--r--contrib/llvm/lib/TableGen/TGParser.h11
-rw-r--r--contrib/llvm/lib/TableGen/TableGenBackend.cpp7
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
//
//===----------------------------------------------------------------------===//
//