aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/TableGen/TGParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/TableGen/TGParser.cpp')
-rw-r--r--contrib/llvm/lib/TableGen/TGParser.cpp280
1 files changed, 229 insertions, 51 deletions
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();