[llvm] r327494 - TableGen: Type-check BinOps
Nicolai Haehnle via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 14 04:00:43 PDT 2018
Author: nha
Date: Wed Mar 14 04:00:43 2018
New Revision: 327494
URL: http://llvm.org/viewvc/llvm-project?rev=327494&view=rev
Log:
TableGen: Type-check BinOps
Additionally, allow more than two operands to !con, !add, !and, !or
in the same way as is already allowed for !listconcat and !strconcat.
Change-Id: I9659411f554201b90cd8ed7c7e004d381a66fa93
Differential revision: https://reviews.llvm.org/D44112
Added:
llvm/trunk/test/TableGen/arithmetic.td
Modified:
llvm/trunk/docs/TableGen/LangIntro.rst
llvm/trunk/lib/TableGen/TGParser.cpp
llvm/trunk/test/TableGen/Paste.td
llvm/trunk/test/TableGen/dag-functional.td
llvm/trunk/test/TableGen/listconcat.td
llvm/trunk/test/TableGen/math.td
Modified: llvm/trunk/docs/TableGen/LangIntro.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/TableGen/LangIntro.rst?rev=327494&r1=327493&r2=327494&view=diff
==============================================================================
--- llvm/trunk/docs/TableGen/LangIntro.rst (original)
+++ llvm/trunk/docs/TableGen/LangIntro.rst Wed Mar 14 04:00:43 2018
@@ -267,8 +267,12 @@ supported include:
on string, int and bit objects. Use !cast<string> to compare other types of
objects.
-``!shl(a,b)`` ``!srl(a,b)`` ``!sra(a,b)`` ``!add(a,b)`` ``!and(a,b)``
- The usual binary and arithmetic operators.
+``!shl(a,b)`` ``!srl(a,b)`` ``!sra(a,b)``
+ The usual shift operators. Operations are on 64-bit integers, the result
+ is undefined for shift counts outside [0, 63].
+
+``!add(a,b,...)`` ``!and(a,b,...)`` ``!or(a,b,...)``
+ The usual arithmetic and binary operators.
Note that all of the values have rules specifying how they convert to values
for different types. These rules allow you to assign a value like "``7``"
Modified: llvm/trunk/lib/TableGen/TGParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGParser.cpp?rev=327494&r1=327493&r2=327494&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGParser.cpp (original)
+++ llvm/trunk/lib/TableGen/TGParser.cpp Wed Mar 14 04:00:43 2018
@@ -981,28 +981,59 @@ Init *TGParser::ParseOperation(Record *C
Lex.Lex(); // eat the operation
BinOpInit::BinaryOp Code;
- RecTy *Type = nullptr;
-
switch (OpTok) {
default: llvm_unreachable("Unhandled code!");
- case tgtok::XConcat: Code = BinOpInit::CONCAT;Type = DagRecTy::get(); break;
- case tgtok::XADD: Code = BinOpInit::ADD; Type = IntRecTy::get(); break;
- case tgtok::XAND: Code = BinOpInit::AND; Type = IntRecTy::get(); break;
- case tgtok::XOR: Code = BinOpInit::OR; Type = IntRecTy::get(); break;
- case tgtok::XSRA: Code = BinOpInit::SRA; Type = IntRecTy::get(); break;
- case tgtok::XSRL: Code = BinOpInit::SRL; Type = IntRecTy::get(); break;
- case tgtok::XSHL: Code = BinOpInit::SHL; Type = IntRecTy::get(); break;
- case tgtok::XEq: Code = BinOpInit::EQ; Type = BitRecTy::get(); break;
+ case tgtok::XConcat: Code = BinOpInit::CONCAT; break;
+ case tgtok::XADD: Code = BinOpInit::ADD; break;
+ case tgtok::XAND: Code = BinOpInit::AND; break;
+ case tgtok::XOR: Code = BinOpInit::OR; break;
+ case tgtok::XSRA: Code = BinOpInit::SRA; break;
+ case tgtok::XSRL: Code = BinOpInit::SRL; break;
+ case tgtok::XSHL: Code = BinOpInit::SHL; break;
+ case tgtok::XEq: Code = BinOpInit::EQ; break;
+ case tgtok::XListConcat: Code = BinOpInit::LISTCONCAT; break;
+ case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break;
+ }
+
+ RecTy *Type = nullptr;
+ RecTy *ArgType = nullptr;
+ switch (OpTok) {
+ default:
+ llvm_unreachable("Unhandled code!");
+ case tgtok::XConcat:
+ Type = DagRecTy::get();
+ ArgType = DagRecTy::get();
+ break;
+ case tgtok::XAND:
+ case tgtok::XOR:
+ case tgtok::XSRA:
+ case tgtok::XSRL:
+ case tgtok::XSHL:
+ case tgtok::XADD:
+ Type = IntRecTy::get();
+ ArgType = IntRecTy::get();
+ break;
+ case tgtok::XEq:
+ Type = BitRecTy::get();
+ // ArgType for Eq is not known at this point
+ break;
case tgtok::XListConcat:
- Code = BinOpInit::LISTCONCAT;
// We don't know the list type until we parse the first argument
+ ArgType = ItemType;
break;
case tgtok::XStrConcat:
- Code = BinOpInit::STRCONCAT;
Type = StringRecTy::get();
+ ArgType = StringRecTy::get();
break;
}
+ if (Type && ItemType && !Type->typeIsConvertibleTo(ItemType)) {
+ Error(OpLoc, Twine("expected value of type '") +
+ ItemType->getAsString() + "', got '" +
+ Type->getAsString() + "'");
+ return nullptr;
+ }
+
if (Lex.getCode() != tgtok::l_paren) {
TokError("expected '(' after binary operator");
return nullptr;
@@ -1011,14 +1042,51 @@ Init *TGParser::ParseOperation(Record *C
SmallVector<Init*, 2> InitList;
- InitList.push_back(ParseValue(CurRec));
- if (!InitList.back()) return nullptr;
+ for (;;) {
+ SMLoc InitLoc = Lex.getLoc();
+ InitList.push_back(ParseValue(CurRec, ArgType));
+ if (!InitList.back()) return nullptr;
- while (Lex.getCode() == tgtok::comma) {
- Lex.Lex(); // eat the ','
+ // All BinOps require their arguments to be of compatible types.
+ TypedInit *TI = dyn_cast<TypedInit>(InitList.back());
+ if (!ArgType) {
+ ArgType = TI->getType();
+
+ switch (Code) {
+ case BinOpInit::LISTCONCAT:
+ if (!isa<ListRecTy>(ArgType)) {
+ Error(InitLoc, Twine("expected a list, got value of type '") +
+ ArgType->getAsString() + "'");
+ return nullptr;
+ }
+ break;
+ case BinOpInit::EQ:
+ if (!ArgType->typeIsConvertibleTo(IntRecTy::get()) &&
+ !ArgType->typeIsConvertibleTo(StringRecTy::get())) {
+ Error(InitLoc, Twine("expected int, bits, or string; got value of "
+ "type '") + ArgType->getAsString() + "'");
+ return nullptr;
+ }
+ break;
+ default: llvm_unreachable("other ops have fixed argument types");
+ }
+ } else {
+ RecTy *Resolved = resolveTypes(ArgType, TI->getType());
+ if (!Resolved) {
+ Error(InitLoc, Twine("expected value of type '") +
+ ArgType->getAsString() + "', got '" +
+ TI->getType()->getAsString() + "'");
+ return nullptr;
+ }
+ if (Code != BinOpInit::ADD && Code != BinOpInit::AND &&
+ Code != BinOpInit::OR && Code != BinOpInit::SRA &&
+ Code != BinOpInit::SRL && Code != BinOpInit::SHL)
+ ArgType = Resolved;
+ }
- InitList.push_back(ParseValue(CurRec));
- if (!InitList.back()) return nullptr;
+ if (Lex.getCode() != tgtok::comma)
+ break;
+ Lex.Lex(); // eat the ','
}
if (Lex.getCode() != tgtok::r_paren) {
@@ -1027,20 +1095,14 @@ Init *TGParser::ParseOperation(Record *C
}
Lex.Lex(); // eat the ')'
- // If we are doing !listconcat, we should know the type by now
- if (OpTok == tgtok::XListConcat) {
- if (TypedInit *Arg0 = dyn_cast<TypedInit>(InitList[0]))
- Type = Arg0->getType();
- else {
- InitList[0]->print(errs());
- Error(OpLoc, "expected a list");
- return nullptr;
- }
- }
+ if (Code == BinOpInit::LISTCONCAT)
+ Type = ArgType;
// We allow multiple operands to associative operators like !strconcat as
// shorthand for nesting them.
- if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT) {
+ if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT ||
+ Code == BinOpInit::CONCAT || Code == BinOpInit::ADD ||
+ Code == BinOpInit::AND || Code == BinOpInit::OR) {
while (InitList.size() > 2) {
Init *RHS = InitList.pop_back_val();
RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type))
@@ -1896,7 +1958,7 @@ Init *TGParser::ParseValue(Record *CurRe
break;
default:
- Init *RHSResult = ParseValue(CurRec, ItemType, ParseNameMode);
+ Init *RHSResult = ParseValue(CurRec, nullptr, ParseNameMode);
RHS = dyn_cast<TypedInit>(RHSResult);
if (!RHS) {
Error(PasteLoc, "RHS of paste is not typed!");
Modified: llvm/trunk/test/TableGen/Paste.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/Paste.td?rev=327494&r1=327493&r2=327494&view=diff
==============================================================================
--- llvm/trunk/test/TableGen/Paste.td (original)
+++ llvm/trunk/test/TableGen/Paste.td Wed Mar 14 04:00:43 2018
@@ -12,6 +12,16 @@ multiclass Test {
def Vy#NAME#PD : Instr<3>;
}
+class Arithmetic<int i> {
+ string name = "number"#!add(i, 1);
+}
+
+def A : Arithmetic<5>;
+
+// CHECK: def A {
+// CHECK: string name = "number6";
+// CHECK: }
+
defm ADD : Test;
defm SUB : Test;
Added: llvm/trunk/test/TableGen/arithmetic.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/arithmetic.td?rev=327494&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/arithmetic.td (added)
+++ llvm/trunk/test/TableGen/arithmetic.td Wed Mar 14 04:00:43 2018
@@ -0,0 +1,25 @@
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+
+// CHECK: --- Defs ---
+
+// CHECK: def A0 {
+// CHECK: bits<8> add = { 0, 1, 0, 0, 0, 0, 0, 0 };
+// CHECK: bits<8> and = { 0, 0, 0, 0, 0, 0, 0, 1 };
+// CHECK: bits<8> or = { 0, 0, 1, 1, 1, 1, 1, 1 };
+// CHECK: bits<8> srl = { 0, 0, 0, 1, 1, 1, 1, 1 };
+// CHECK: bits<8> sra = { 0, 0, 0, 1, 1, 1, 1, 1 };
+// CHECK: bits<8> shl = { 0, 1, 1, 1, 1, 1, 1, 0 };
+// CHECK: }
+
+class A<bits<8> a, bits<2> b> {
+ // Operands of different bits types are allowed.
+ bits<8> add = !add(a, b);
+ bits<8> and = !and(a, b);
+ bits<8> or = !or(a, b);
+ bits<8> srl = !srl(a, b);
+ bits<8> sra = !sra(a, b);
+ bits<8> shl = !shl(a, b);
+}
+
+def A0 : A<63, 1>;
Modified: llvm/trunk/test/TableGen/dag-functional.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/dag-functional.td?rev=327494&r1=327493&r2=327494&view=diff
==============================================================================
--- llvm/trunk/test/TableGen/dag-functional.td (original)
+++ llvm/trunk/test/TableGen/dag-functional.td Wed Mar 14 04:00:43 2018
@@ -36,6 +36,10 @@
// CHECK: dag ret2 = (ops 1, 2);
// CHECK: }
+// CHECK: def D {
+// CHECK: dag d1 = (ops 1, ?:$name1, 2, 3);
+// CHECK: }
+
def ops;
class Node<int val, string name> {
@@ -93,3 +97,7 @@ class C<list<int> nodes, list<string> na
}
def C0 : C<[1, 2], ["a", "b"]>;
+
+def D {
+ dag d1 = !con((ops 1), (ops $name1), (ops), (ops 2, 3));
+}
\ No newline at end of file
Modified: llvm/trunk/test/TableGen/listconcat.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/listconcat.td?rev=327494&r1=327493&r2=327494&view=diff
==============================================================================
--- llvm/trunk/test/TableGen/listconcat.td (original)
+++ llvm/trunk/test/TableGen/listconcat.td Wed Mar 14 04:00:43 2018
@@ -9,6 +9,14 @@
// CHECK: list<string> T2 = !listconcat(Y:S, !listconcat(["foo"], !listconcat(Y:S, ["bar", "baz"])));
// CHECK: }
+// CHECK: def A0 {
+// CHECK: list<int> lst = [4];
+// CHECK: }
+
+// CHECK: def A1 {
+// CHECK: list<int> lst = [];
+// CHECK: }
+
// CHECK: def DX {
// CHECK: list<int> x = [0, 1, 1, 2]
// CHECK: }
@@ -18,6 +26,14 @@
// CHECK: list<string> T2 = ["fu", "foo", "fu", "bar", "baz"];
// CHECK: }
+class A<bit x> {
+ // The empty lists type-check without issues.
+ list<int> lst = !listconcat([], !if(x, [], [4]));
+}
+
+def A0 : A<0>;
+def A1 : A<1>;
+
class X<list<int> a, list<int> b, list<int> c> {
list<int> x = !listconcat(!listconcat(a, b), !listconcat(b, c));
}
Modified: llvm/trunk/test/TableGen/math.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/math.td?rev=327494&r1=327493&r2=327494&view=diff
==============================================================================
--- llvm/trunk/test/TableGen/math.td (original)
+++ llvm/trunk/test/TableGen/math.td Wed Mar 14 04:00:43 2018
@@ -35,6 +35,13 @@ def v1025 : Int<!add(v1024.Value, 1)>;
// CHECK: def v1025
// CHECK: Value = 1025
+// CHECK: def v1a
+// CHECK: Value = 1
+
+// CHECK: def v2
+// CHECK: Value = 2
+def v2 : Int<2>;
+
def v2048 : Int<!add(v1024.Value, v1024.Value)>;
// CHECK: def v2048
// CHECK: Value = 2048
@@ -45,3 +52,13 @@ def v1 : Int<!and(v1025.Value, 1)>;
// CHECK: def v3072
// CHECK: Value = 3072
def v3072 : Int<!or(v1024.Value, v2048.Value)>;
+
+// CHECK: def v4
+// CHECK: Value = 4
+
+// CHECK: def v7
+// CHECK: Value = 7
+
+def v4 : Int<!add(v2.Value, 1, v1.Value)>;
+def v7 : Int<!or(v1.Value, v2.Value, v4.Value)>;
+def v1a : Int<!and(v7.Value, 5, v1.Value)>;
More information about the llvm-commits
mailing list