[llvm] [TableGen] Support automatic type deduction (PR #109434)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 20 10:35:41 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-tablegen
Author: Rahul Joshi (jurahul)
<details>
<summary>Changes</summary>
Support 'auto' type when declaring class or def fields. Make 'auto' a TableGen keyword and allow using it as a type when declaring class or def fields. When auto is used, the field must have an initializer from which its type can be infered.
---
Full diff: https://github.com/llvm/llvm-project/pull/109434.diff
5 Files Affected:
- (modified) llvm/lib/TableGen/TGLexer.cpp (+1)
- (modified) llvm/lib/TableGen/TGLexer.h (+1)
- (modified) llvm/lib/TableGen/TGParser.cpp (+47-11)
- (modified) llvm/lib/TableGen/TGParser.h (+2-1)
- (added) llvm/test/TableGen/auto.td (+44)
``````````diff
diff --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp
index 62a884e01a5306..9f23f33ca6dbab 100644
--- a/llvm/lib/TableGen/TGLexer.cpp
+++ b/llvm/lib/TableGen/TGLexer.cpp
@@ -383,6 +383,7 @@ tgtok::TokKind TGLexer::LexIdentifier() {
StringRef Str(IdentStart, CurPtr-IdentStart);
tgtok::TokKind Kind = StringSwitch<tgtok::TokKind>(Str)
+ .Case("auto", tgtok::Auto)
.Case("int", tgtok::Int)
.Case("bit", tgtok::Bit)
.Case("bits", tgtok::Bits)
diff --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h
index 9adc03ccc72b85..f6d8f0c606da75 100644
--- a/llvm/lib/TableGen/TGLexer.h
+++ b/llvm/lib/TableGen/TGLexer.h
@@ -75,6 +75,7 @@ enum TokKind {
// Reserved keywords. ('ElseKW' is named to distinguish it from the
// existing 'Else' that means the preprocessor #else.)
+ Auto,
Bit,
Bits,
Code,
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 1a60c2a567a297..262bf2656e86ed 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -3240,13 +3240,19 @@ bool TGParser::ParseTemplateArgValueList(
///
/// Declaration ::= FIELD? Type ID ('=' Value)?
///
-Init *TGParser::ParseDeclaration(Record *CurRec,
- bool ParsingTemplateArgs) {
+Init *TGParser::ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs,
+ bool AllowAuto = false) {
// Read the field prefix if present.
bool HasField = consume(tgtok::Field);
- RecTy *Type = ParseType();
- if (!Type) return nullptr;
+ RecTy *Type;
+ if (AllowAuto && consume(tgtok::Auto)) {
+ Type = nullptr;
+ } else {
+ Type = ParseType();
+ if (!Type)
+ return nullptr;
+ }
if (Lex.getCode() != tgtok::Id) {
TokError("Expected identifier in declaration");
@@ -3268,6 +3274,30 @@ Init *TGParser::ParseDeclaration(Record *CurRec,
Init *DeclName = StringInit::get(Records, Str);
Lex.Lex();
+ bool HasValue = consume(tgtok::equal);
+
+ // When 'auto' is used, parse the value and infer the type based on the
+ // value's type.
+ SMLoc ValLoc;
+ Init *Val = nullptr;
+ if (!Type) {
+ if (!HasValue) {
+ // auto used without a value.
+ TokError("auto requires assigning a value");
+ return nullptr;
+ }
+ ValLoc = Lex.getLoc();
+ Val = ParseValue(CurRec, Type);
+
+ // Infer type from the value.
+ if (TypedInit *TI = dyn_cast_or_null<TypedInit>(Val)) {
+ Type = TI->getType();
+ } else {
+ Error(ValLoc, "unable to infer type");
+ return nullptr;
+ }
+ }
+
bool BadField;
if (!ParsingTemplateArgs) { // def, possibly in a multiclass
BadField = AddValue(CurRec, IdLoc,
@@ -3289,10 +3319,14 @@ Init *TGParser::ParseDeclaration(Record *CurRec,
if (BadField)
return nullptr;
- // If a value is present, parse it and set new field's value.
- if (consume(tgtok::equal)) {
- SMLoc ValLoc = Lex.getLoc();
- Init *Val = ParseValue(CurRec, Type);
+ // For the non-auto case, if a value is present, parse it.
+ if (!Val && HasValue) {
+ ValLoc = Lex.getLoc();
+ Val = ParseValue(CurRec, Type);
+ }
+
+ // Set the new field's value.
+ if (HasValue) {
if (!Val ||
SetValue(CurRec, ValLoc, DeclName, {}, Val,
/*AllowSelfAssignment=*/false, /*OverrideDefLoc=*/false)) {
@@ -3401,7 +3435,7 @@ bool TGParser::ParseTemplateArgList(Record *CurRec) {
Record *TheRecToAddTo = CurRec ? CurRec : &CurMultiClass->Rec;
// Read the first declaration.
- Init *TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
+ Init *TemplArg = ParseDeclaration(CurRec, /*ParsingTemplateArgs=*/true);
if (!TemplArg)
return true;
@@ -3410,7 +3444,7 @@ bool TGParser::ParseTemplateArgList(Record *CurRec) {
while (consume(tgtok::comma)) {
// Read the following declarations.
SMLoc Loc = Lex.getLoc();
- TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
+ TemplArg = ParseDeclaration(CurRec, /*ParsingTemplateArgs=*/true);
if (!TemplArg)
return true;
@@ -3445,7 +3479,9 @@ bool TGParser::ParseBodyItem(Record *CurRec) {
return ParseDump(nullptr, CurRec);
if (Lex.getCode() != tgtok::Let) {
- if (!ParseDeclaration(CurRec, false))
+ // Allow 'auto' when parsing declarations in the body of a def or class.
+ if (!ParseDeclaration(CurRec, /*ParsingTemplateArgs=*/false,
+ /*AllowAuto=*/true))
return true;
if (!consume(tgtok::semi))
diff --git a/llvm/lib/TableGen/TGParser.h b/llvm/lib/TableGen/TGParser.h
index b08e250870901a..7101cd43b53d56 100644
--- a/llvm/lib/TableGen/TGParser.h
+++ b/llvm/lib/TableGen/TGParser.h
@@ -280,7 +280,8 @@ class TGParser {
bool ParseBodyItem(Record *CurRec);
bool ParseTemplateArgList(Record *CurRec);
- Init *ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs);
+ Init *ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs,
+ bool AllowAuto);
VarInit *ParseForeachDeclaration(Init *&ForeachListValue);
SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm);
diff --git a/llvm/test/TableGen/auto.td b/llvm/test/TableGen/auto.td
new file mode 100644
index 00000000000000..b05af8d5c16a7d
--- /dev/null
+++ b/llvm/test/TableGen/auto.td
@@ -0,0 +1,44 @@
+// RUN: llvm-tblgen %s | FileCheck %s --check-prefix=CHECK-PASS
+// RUN: not llvm-tblgen -DBAD0 %s 2>&1 | FileCheck %s --check-prefix=CHECK-BAD0 -DFILE=%s
+// RUN: not llvm-tblgen -DBAD1 %s 2>&1 | FileCheck %s --check-prefix=CHECK-BAD1 -DFILE=%s
+
+// CHECK-PASS: int Arg = A:P;
+class A<int P> {
+ auto Arg = P;
+}
+
+def MyOp;
+
+// CHECK-PASS-LABEL: class B
+// CHECK-PASS: int A = 10;
+// CHECK-PASS: string B = "x";
+// CHECK-PASS: list<int> C = [10, 10];
+// CHECK-PASS{LITERAL}: list<list<int>> D = [[10, 10], [11, 11]];
+// CHECK-PASS: list<A> F = [anonymous_0, anonymous_1];
+// CHECK-PASS: bits<4> G = { 0, 1, 0, 1 };
+// CHECK-PASS: code H = [{ printf(); }];
+// CHECK-PASS: bits<1> I = { 0 };
+// CHECK-PASS: dag K = (MyOp 10, 100);
+// CHECK-PASS: int L = 10;
+class B {
+ auto A = 10;
+ auto B = "x";
+ auto C = [10,10];
+ auto D = [[10,10],[11,11]];
+#ifdef BAD0
+ // CHECK-BAD0: [[FILE]]:[[@LINE+1]]:12: error: unable to infer type
+ auto E = [];
+#endif
+ auto F = [A<10>, A<11>];
+ auto G = {0,1,0,1};
+ auto H = [{ printf(); }];
+ // FIXME: This becomes `bits` and not `bit`.
+ auto I = 0b0;
+#ifdef BAD1
+ // CHECK-BAD1: [[FILE]]:[[@LINE+1]]:12: error: unable to infer type
+ auto J = ?;
+#endif
+ auto K = (MyOp 10, 100);
+ auto L = A<10>.Arg;
+}
+
``````````
</details>
https://github.com/llvm/llvm-project/pull/109434
More information about the llvm-commits
mailing list