[llvm] [Tablegen] Add keyword `dump`. (PR #68793)
Francesco Petrogalli via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 12 03:28:02 PDT 2023
https://github.com/fpetrogalli updated https://github.com/llvm/llvm-project/pull/68793
>From 004967c45f8ee41528cf9fb22472ae1b247548b7 Mon Sep 17 00:00:00 2001
From: Francesco Petrogalli <francesco.petrogalli at apple.com>
Date: Wed, 11 Oct 2023 01:29:06 +0200
Subject: [PATCH 01/12] [Tablegen] Add keywork `dump`.
The keyword is intended for debugging purpose. It prints a message to
stderr.
This patch is based on code originally written by Adam Nemet, and on
the feedback received by the reviewers in
https://reviews.llvm.org/D157492.
---
llvm/docs/TableGen/ProgRef.rst | 27 ++++++++++---
llvm/include/llvm/TableGen/Error.h | 1 +
llvm/include/llvm/TableGen/Record.h | 16 ++++++++
llvm/lib/TableGen/Error.cpp | 7 ++++
llvm/lib/TableGen/Record.cpp | 10 +++++
llvm/lib/TableGen/TGLexer.cpp | 51 ++++++++++++------------
llvm/lib/TableGen/TGLexer.h | 1 +
llvm/lib/TableGen/TGParser.cpp | 61 +++++++++++++++++++++++++++--
llvm/lib/TableGen/TGParser.h | 4 ++
llvm/test/TableGen/dump.td | 46 ++++++++++++++++++++++
10 files changed, 191 insertions(+), 33 deletions(-)
create mode 100644 llvm/test/TableGen/dump.td
diff --git a/llvm/docs/TableGen/ProgRef.rst b/llvm/docs/TableGen/ProgRef.rst
index 45e25573b0e00f0..9f916eafd6053e8 100644
--- a/llvm/docs/TableGen/ProgRef.rst
+++ b/llvm/docs/TableGen/ProgRef.rst
@@ -202,10 +202,10 @@ TableGen has the following reserved keywords, which cannot be used as
identifiers::
assert bit bits class code
- dag def else false foreach
- defm defset defvar field if
- in include int let list
- multiclass string then true
+ dag def dump else false
+ foreach defm defset defvar field
+ if in include int let
+ list multiclass string then true
.. warning::
The ``field`` reserved word is deprecated, except when used with the
@@ -571,7 +571,7 @@ files.
TableGenFile: (`Statement` | `IncludeDirective`
:| `PreprocessorDirective`)*
Statement: `Assert` | `Class` | `Def` | `Defm` | `Defset` | `Defvar`
- :| `Foreach` | `If` | `Let` | `MultiClass`
+ :| `Dump` | `Foreach` | `If` | `Let` | `MultiClass`
The following sections describe each of these top-level statements.
@@ -1275,6 +1275,23 @@ be nested.
This loop defines records named ``R0``, ``R1``, ``R2``, and ``R3``, along
with ``F0``, ``F1``, ``F2``, and ``F3``.
+``dump`` --- print messages to stderr
+-------------------------------------
+
+A ``dump`` statement prints the input string to standard error
+output. It is intended for debugging purpose.
+
+.. productionlist::
+ Dump: "dump" `string` ";"
+
+For example, it can be used in combination with `!repl` to investigate
+the values passed to a multiclass:
+
+.. code-block:: text
+
+ multiclass MC<dag s> {
+ dump "s = " # !repl(s);
+ }
``if`` --- select statements based on a test
--------------------------------------------
diff --git a/llvm/include/llvm/TableGen/Error.h b/llvm/include/llvm/TableGen/Error.h
index 2e639224c9c0312..ce8dc6aa0397e10 100644
--- a/llvm/include/llvm/TableGen/Error.h
+++ b/llvm/include/llvm/TableGen/Error.h
@@ -43,6 +43,7 @@ void PrintError(const RecordVal *RecVal, const Twine &Msg);
[[noreturn]] void PrintFatalError(const RecordVal *RecVal, const Twine &Msg);
void CheckAssert(SMLoc Loc, Init *Condition, Init *Message);
+void CheckDump(SMLoc Loc, Init *Message);
extern SourceMgr SrcMgr;
extern unsigned ErrorsPrinted;
diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h
index 5d6877cfacdcf19..f220b713efcd8f0 100644
--- a/llvm/include/llvm/TableGen/Record.h
+++ b/llvm/include/llvm/TableGen/Record.h
@@ -1641,6 +1641,15 @@ class Record {
: Loc(Loc), Condition(Condition), Message(Message) {}
};
+ struct DumpInfo {
+ SMLoc Loc;
+ Init *Message;
+
+ // User-defined constructor to support std::make_unique(). It can be
+ // removed in C++20 when braced initialization is supported.
+ DumpInfo(SMLoc Loc, Init *Message) : Loc(Loc), Message(Message) {}
+ };
+
private:
Init *Name;
// Location where record was instantiated, followed by the location of
@@ -1652,6 +1661,7 @@ class Record {
SmallVector<Init *, 0> TemplateArgs;
SmallVector<RecordVal, 0> Values;
SmallVector<AssertionInfo, 0> Assertions;
+ SmallVector<DumpInfo, 0> Dumps;
// All superclasses in the inheritance forest in post-order (yes, it
// must be a forest; diamond-shaped inheritance is not allowed).
@@ -1742,6 +1752,7 @@ class Record {
ArrayRef<RecordVal> getValues() const { return Values; }
ArrayRef<AssertionInfo> getAssertions() const { return Assertions; }
+ ArrayRef<DumpInfo> getDumps() const { return Dumps; }
ArrayRef<std::pair<Record *, SMRange>> getSuperClasses() const {
return SuperClasses;
@@ -1802,11 +1813,16 @@ class Record {
Assertions.push_back(AssertionInfo(Loc, Condition, Message));
}
+ void addDump(SMLoc Loc, Init *Message) {
+ Dumps.push_back(DumpInfo(Loc, Message));
+ }
+
void appendAssertions(const Record *Rec) {
Assertions.append(Rec->Assertions);
}
void checkRecordAssertions();
+ void checkRecordDumps();
void checkUnusedTemplateArgs();
bool isSubClassOf(const Record *R) const {
diff --git a/llvm/lib/TableGen/Error.cpp b/llvm/lib/TableGen/Error.cpp
index ebe9129ebaeb59c..f3a43b87889ca5c 100644
--- a/llvm/lib/TableGen/Error.cpp
+++ b/llvm/lib/TableGen/Error.cpp
@@ -170,4 +170,11 @@ void CheckAssert(SMLoc Loc, Init *Condition, Init *Message) {
}
}
+void CheckDump(SMLoc Loc, Init *Message) {
+ if (auto *MessageInit = dyn_cast<StringInit>(Message))
+ PrintNote(MessageInit->getValue());
+ else
+ PrintNote("(dump message is not a string)");
+}
+
} // end namespace llvm
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index 24b48b453e63e55..b7d355ec406d3a7 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -3119,6 +3119,16 @@ void Record::checkRecordAssertions() {
}
}
+void Record::checkRecordDumps() {
+ RecordResolver R(*this);
+ R.setFinal(true);
+
+ for (const auto &Dump : getDumps()) {
+ Init *Message = Dump.Message->resolveReferences(R);
+ CheckDump(Dump.Loc, Message);
+ }
+}
+
// Report a warning if the record has unused template arguments.
void Record::checkUnusedTemplateArgs() {
for (const Init *TA : getTemplateArgs()) {
diff --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp
index d5140e91fce9e94..c811a67d930d481 100644
--- a/llvm/lib/TableGen/TGLexer.cpp
+++ b/llvm/lib/TableGen/TGLexer.cpp
@@ -346,31 +346,32 @@ tgtok::TokKind TGLexer::LexIdentifier() {
StringRef Str(IdentStart, CurPtr-IdentStart);
tgtok::TokKind Kind = StringSwitch<tgtok::TokKind>(Str)
- .Case("int", tgtok::Int)
- .Case("bit", tgtok::Bit)
- .Case("bits", tgtok::Bits)
- .Case("string", tgtok::String)
- .Case("list", tgtok::List)
- .Case("code", tgtok::Code)
- .Case("dag", tgtok::Dag)
- .Case("class", tgtok::Class)
- .Case("def", tgtok::Def)
- .Case("true", tgtok::TrueVal)
- .Case("false", tgtok::FalseVal)
- .Case("foreach", tgtok::Foreach)
- .Case("defm", tgtok::Defm)
- .Case("defset", tgtok::Defset)
- .Case("multiclass", tgtok::MultiClass)
- .Case("field", tgtok::Field)
- .Case("let", tgtok::Let)
- .Case("in", tgtok::In)
- .Case("defvar", tgtok::Defvar)
- .Case("include", tgtok::Include)
- .Case("if", tgtok::If)
- .Case("then", tgtok::Then)
- .Case("else", tgtok::ElseKW)
- .Case("assert", tgtok::Assert)
- .Default(tgtok::Id);
+ .Case("int", tgtok::Int)
+ .Case("bit", tgtok::Bit)
+ .Case("bits", tgtok::Bits)
+ .Case("string", tgtok::String)
+ .Case("list", tgtok::List)
+ .Case("code", tgtok::Code)
+ .Case("dag", tgtok::Dag)
+ .Case("class", tgtok::Class)
+ .Case("def", tgtok::Def)
+ .Case("true", tgtok::TrueVal)
+ .Case("false", tgtok::FalseVal)
+ .Case("foreach", tgtok::Foreach)
+ .Case("defm", tgtok::Defm)
+ .Case("defset", tgtok::Defset)
+ .Case("multiclass", tgtok::MultiClass)
+ .Case("field", tgtok::Field)
+ .Case("let", tgtok::Let)
+ .Case("in", tgtok::In)
+ .Case("defvar", tgtok::Defvar)
+ .Case("include", tgtok::Include)
+ .Case("if", tgtok::If)
+ .Case("then", tgtok::Then)
+ .Case("else", tgtok::ElseKW)
+ .Case("assert", tgtok::Assert)
+ .Case("dump", tgtok::Dump)
+ .Default(tgtok::Id);
// A couple of tokens require special processing.
switch (Kind) {
diff --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h
index 4429c91b7c9cf76..2e2aa59f344083d 100644
--- a/llvm/lib/TableGen/TGLexer.h
+++ b/llvm/lib/TableGen/TGLexer.h
@@ -98,6 +98,7 @@ enum TokKind {
Defm,
Defset,
Defvar,
+ Dump,
Foreach,
If,
Let,
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 2e61925f55651ea..1f117234f9eee31 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -376,7 +376,7 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC,
/// Add a record, foreach loop, or assertion to the current context.
bool TGParser::addEntry(RecordsEntry E) {
- assert((!!E.Rec + !!E.Loop + !!E.Assertion) == 1 &&
+ assert((!!E.Rec + !!E.Loop + !!E.Assertion + !!E.Dump) == 1 &&
"RecordsEntry has invalid number of items");
// If we are parsing a loop, add it to the loop's entries.
@@ -404,6 +404,11 @@ bool TGParser::addEntry(RecordsEntry E) {
return false;
}
+ if (E.Dump) {
+ CheckDump(E.Dump->Loc, E.Dump->Message);
+ return false;
+ }
+
// It must be a record, so finish it off.
return addDefOne(std::move(E.Rec));
}
@@ -498,6 +503,18 @@ bool TGParser::resolve(const std::vector<RecordsEntry> &Source,
else
CheckAssert(E.Assertion->Loc, Condition, Message);
+ } else if (E.Dump) {
+ MapResolver R;
+ for (const auto &S : Substs)
+ R.set(S.first, S.second);
+ Init *Message = E.Dump->Message->resolveReferences(R);
+
+ if (Dest)
+ Dest->push_back(
+ std::make_unique<Record::DumpInfo>(E.Dump->Loc, Message));
+ else
+ CheckDump(E.Dump->Loc, Message);
+
} else {
auto Rec = std::make_unique<Record>(*E.Rec);
if (Loc)
@@ -545,6 +562,9 @@ bool TGParser::addDefOne(std::unique_ptr<Record> Rec) {
// Check the assertions.
Rec->checkRecordAssertions();
+ // Run the dumps.
+ Rec->checkRecordDumps();
+
// If ObjectBody has template arguments, it's an error.
assert(Rec->getTemplateArgs().empty() && "How'd this get template args?");
@@ -3405,6 +3425,7 @@ bool TGParser::ParseTemplateArgList(Record *CurRec) {
/// BodyItem ::= Declaration ';'
/// BodyItem ::= LET ID OptionalBitList '=' Value ';'
/// BodyItem ::= Defvar
+/// BodyItem ::= Dump
/// BodyItem ::= Assert
///
bool TGParser::ParseBodyItem(Record *CurRec) {
@@ -3414,6 +3435,9 @@ bool TGParser::ParseBodyItem(Record *CurRec) {
if (Lex.getCode() == tgtok::Defvar)
return ParseDefvar(CurRec);
+ if (Lex.getCode() == tgtok::Dump)
+ return ParseDump(nullptr, CurRec);
+
if (Lex.getCode() != tgtok::Let) {
if (!ParseDeclaration(CurRec, false))
return true;
@@ -3510,6 +3534,10 @@ bool TGParser::ApplyLetStack(RecordsEntry &Entry) {
if (Entry.Assertion)
return false;
+ // Let bindings are not applied to dumps.
+ if (Entry.Dump)
+ return false;
+
for (auto &E : Entry.Loop->Entries) {
if (ApplyLetStack(E))
return true;
@@ -4090,13 +4118,14 @@ bool TGParser::ParseMultiClass() {
while (Lex.getCode() != tgtok::r_brace) {
switch (Lex.getCode()) {
default:
- return TokError("expected 'assert', 'def', 'defm', 'defvar', "
+ return TokError("expected 'assert', 'def', 'defm', 'defvar', 'dump', "
"'foreach', 'if', or 'let' in multiclass body");
case tgtok::Assert:
case tgtok::Def:
case tgtok::Defm:
case tgtok::Defvar:
+ case tgtok::Dump:
case tgtok::Foreach:
case tgtok::If:
case tgtok::Let:
@@ -4244,11 +4273,13 @@ bool TGParser::ParseObject(MultiClass *MC) {
switch (Lex.getCode()) {
default:
return TokError(
- "Expected assert, class, def, defm, defset, foreach, if, or let");
+ "Expected assert, class, def, defm, defset, dump, foreach, if, or let");
case tgtok::Assert: return ParseAssert(MC);
case tgtok::Def: return ParseDef(MC);
case tgtok::Defm: return ParseDefm(MC);
case tgtok::Defvar: return ParseDefvar();
+ case tgtok::Dump:
+ return ParseDump(MC);
case tgtok::Foreach: return ParseForeach(MC);
case tgtok::If: return ParseIf(MC);
case tgtok::Let: return ParseTopLevelLet(MC);
@@ -4359,3 +4390,27 @@ LLVM_DUMP_METHOD void MultiClass::dump() const {
E.dump();
}
#endif
+
+bool TGParser::ParseDump(MultiClass *CurMultiClass, Record *CurRec) {
+ assert(Lex.getCode() == tgtok::Dump && "Unknown tok");
+ Lex.Lex(); // eat the operation
+
+ Init *Message = ParseValue(CurRec);
+ if (!Message)
+ return true;
+
+ std::string Msg;
+ if (auto SI = dyn_cast<StringInit>(Message))
+ Msg = SI->getValue();
+
+ if (!consume(tgtok::semi))
+ return TokError("expected ';'");
+
+ SMLoc ConditionLoc = Lex.getLoc();
+ if (CurRec)
+ CurRec->addDump(ConditionLoc, Message);
+ else
+ addEntry(std::make_unique<Record::DumpInfo>(ConditionLoc, Message));
+
+ return false;
+}
diff --git a/llvm/lib/TableGen/TGParser.h b/llvm/lib/TableGen/TGParser.h
index d42cdad88a843da..c5365ff2709243f 100644
--- a/llvm/lib/TableGen/TGParser.h
+++ b/llvm/lib/TableGen/TGParser.h
@@ -41,6 +41,7 @@ struct RecordsEntry {
std::unique_ptr<Record> Rec;
std::unique_ptr<ForeachLoop> Loop;
std::unique_ptr<Record::AssertionInfo> Assertion;
+ std::unique_ptr<Record::DumpInfo> Dump;
void dump() const;
@@ -49,6 +50,8 @@ struct RecordsEntry {
RecordsEntry(std::unique_ptr<ForeachLoop> Loop) : Loop(std::move(Loop)) {}
RecordsEntry(std::unique_ptr<Record::AssertionInfo> Assertion)
: Assertion(std::move(Assertion)) {}
+ RecordsEntry(std::unique_ptr<Record::DumpInfo> Dump)
+ : Dump(std::move(Dump)) {}
};
/// ForeachLoop - Record the iteration state associated with a for loop.
@@ -262,6 +265,7 @@ class TGParser {
bool ParseDef(MultiClass *CurMultiClass);
bool ParseDefset();
bool ParseDefvar(Record *CurRec = nullptr);
+ bool ParseDump(MultiClass *CurMultiClass, Record *CurRec = nullptr);
bool ParseForeach(MultiClass *CurMultiClass);
bool ParseIf(MultiClass *CurMultiClass);
bool ParseIfBody(MultiClass *CurMultiClass, StringRef Kind);
diff --git a/llvm/test/TableGen/dump.td b/llvm/test/TableGen/dump.td
new file mode 100644
index 000000000000000..ea0870a9a993138
--- /dev/null
+++ b/llvm/test/TableGen/dump.td
@@ -0,0 +1,46 @@
+// RUN: llvm-tblgen %s -o - 2>&1 >/dev/null | FileCheck %s
+
+// CHECK-LABEL: Debug message
+dump "Debug message";
+
+// CHECK-LABEL: The Value of A is:
+// CHECK-NEXT: a { // A
+// CHECK-NEXT: string A = "some text";
+// CHECK-NEXT: dag X = (op op);
+// CHECK-NEXT: }
+def op;
+class A {
+ string A = "some text";
+ dag X =(op op);
+}
+def a : A;
+dump "The Value of A is: \n" # !repr(a);
+
+
+// CHECK-LABEL: b { // A
+// CHECK-NEXT: string A = "some text";
+// CHECK-NEXT: dag X = (op op);
+// CHECK-NEXT: }
+def b : A;
+dump !repr(b) ;
+
+// CHECK-LABEL: got a pair of values ["some other text" : 12], and an empty record:
+// CHECK-NEXT: X {
+// CHECK-NEXT: }
+defvar value_A = "some other text";
+defvar value_B = 12;
+def X;
+dump "got a pair of values [" # !repr(value_A) # " : " # !repr(value_B) # "], " # "and an empty record:\n" # !repr(X);
+
+multiclass MC<dag s> {
+ dump "s = " # !repr(s);
+ dump "args[0] = " # !repr(!getdagarg<A>(s,0));
+ def A;
+}
+// CHECK-LABEL: note: s = (op a)
+// CHECK-NEXT: args[0] = a { // A
+// CHECK-NEXT: string A = "some text";
+// CHECK-NEXT: dag X = (op op);
+// CHECK-NEXT: }
+defm X : MC<(op a)>;
+
>From 59813e6aab6e014cee999062dd58293d7937d55f Mon Sep 17 00:00:00 2001
From: Francesco Petrogalli <francesco.petrogalli at apple.com>
Date: Wed, 11 Oct 2023 13:21:34 +0200
Subject: [PATCH 02/12] Rename var. [NFC]
---
llvm/lib/TableGen/TGParser.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 1f117234f9eee31..ff3d45703aaec69 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -4406,11 +4406,11 @@ bool TGParser::ParseDump(MultiClass *CurMultiClass, Record *CurRec) {
if (!consume(tgtok::semi))
return TokError("expected ';'");
- SMLoc ConditionLoc = Lex.getLoc();
+ SMLoc Loc = Lex.getLoc();
if (CurRec)
- CurRec->addDump(ConditionLoc, Message);
+ CurRec->addDump(Loc, Message);
else
- addEntry(std::make_unique<Record::DumpInfo>(ConditionLoc, Message));
+ addEntry(std::make_unique<Record::DumpInfo>(Loc, Message));
return false;
}
>From 0fab2a6f7b3256ea71adcd4d9ca2cb9adc665e08 Mon Sep 17 00:00:00 2001
From: Francesco Petrogalli <francesco.petrogalli at apple.com>
Date: Thu, 12 Oct 2023 09:54:01 +0200
Subject: [PATCH 03/12] Update llvm/docs/TableGen/ProgRef.rst
---
llvm/docs/TableGen/ProgRef.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/docs/TableGen/ProgRef.rst b/llvm/docs/TableGen/ProgRef.rst
index 9f916eafd6053e8..cb1d72a65978edc 100644
--- a/llvm/docs/TableGen/ProgRef.rst
+++ b/llvm/docs/TableGen/ProgRef.rst
@@ -1284,7 +1284,7 @@ output. It is intended for debugging purpose.
.. productionlist::
Dump: "dump" `string` ";"
-For example, it can be used in combination with `!repl` to investigate
+For example, it can be used in combination with `!repr` to investigate
the values passed to a multiclass:
.. code-block:: text
>From 71e687d21c02658d1e47fc9f92c4bacce357b7be Mon Sep 17 00:00:00 2001
From: Francesco Petrogalli <francesco.petrogalli at apple.com>
Date: Thu, 12 Oct 2023 09:54:10 +0200
Subject: [PATCH 04/12] Update llvm/docs/TableGen/ProgRef.rst
---
llvm/docs/TableGen/ProgRef.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/docs/TableGen/ProgRef.rst b/llvm/docs/TableGen/ProgRef.rst
index cb1d72a65978edc..936036f557a072d 100644
--- a/llvm/docs/TableGen/ProgRef.rst
+++ b/llvm/docs/TableGen/ProgRef.rst
@@ -1290,7 +1290,7 @@ the values passed to a multiclass:
.. code-block:: text
multiclass MC<dag s> {
- dump "s = " # !repl(s);
+ dump "s = " # !repr(s);
}
``if`` --- select statements based on a test
>From 6cc1fa702f6d9ae023e26ed23051666c981a6471 Mon Sep 17 00:00:00 2001
From: Francesco Petrogalli <francesco.petrogalli at apple.com>
Date: Thu, 12 Oct 2023 09:54:59 +0200
Subject: [PATCH 05/12] Update llvm/lib/TableGen/Error.cpp
---
llvm/lib/TableGen/Error.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/TableGen/Error.cpp b/llvm/lib/TableGen/Error.cpp
index f3a43b87889ca5c..95aa316d675d4bf 100644
--- a/llvm/lib/TableGen/Error.cpp
+++ b/llvm/lib/TableGen/Error.cpp
@@ -174,7 +174,7 @@ void CheckDump(SMLoc Loc, Init *Message) {
if (auto *MessageInit = dyn_cast<StringInit>(Message))
PrintNote(MessageInit->getValue());
else
- PrintNote("(dump message is not a string)");
+ PrintNote("(dump message is not a string - use `!repr`)");
}
} // end namespace llvm
>From 3a1192bd6207d71e7b0189bf8ff69e81c1abc27a Mon Sep 17 00:00:00 2001
From: Francesco Petrogalli <francesco.petrogalli at apple.com>
Date: Thu, 12 Oct 2023 10:11:23 +0200
Subject: [PATCH 06/12] s/CheckDump/dumpMessage
---
llvm/include/llvm/TableGen/Error.h | 2 +-
llvm/lib/TableGen/Error.cpp | 3 ++-
llvm/lib/TableGen/Record.cpp | 2 +-
llvm/lib/TableGen/TGParser.cpp | 4 ++--
4 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/llvm/include/llvm/TableGen/Error.h b/llvm/include/llvm/TableGen/Error.h
index ce8dc6aa0397e10..04618995e0fe6d4 100644
--- a/llvm/include/llvm/TableGen/Error.h
+++ b/llvm/include/llvm/TableGen/Error.h
@@ -43,7 +43,7 @@ void PrintError(const RecordVal *RecVal, const Twine &Msg);
[[noreturn]] void PrintFatalError(const RecordVal *RecVal, const Twine &Msg);
void CheckAssert(SMLoc Loc, Init *Condition, Init *Message);
-void CheckDump(SMLoc Loc, Init *Message);
+void dumpMessage(SMLoc Loc, Init *Message);
extern SourceMgr SrcMgr;
extern unsigned ErrorsPrinted;
diff --git a/llvm/lib/TableGen/Error.cpp b/llvm/lib/TableGen/Error.cpp
index 95aa316d675d4bf..c61140fa03dbf29 100644
--- a/llvm/lib/TableGen/Error.cpp
+++ b/llvm/lib/TableGen/Error.cpp
@@ -170,7 +170,8 @@ void CheckAssert(SMLoc Loc, Init *Condition, Init *Message) {
}
}
-void CheckDump(SMLoc Loc, Init *Message) {
+// Dump a message to stderr.
+void dumpMessage(SMLoc Loc, Init *Message) {
if (auto *MessageInit = dyn_cast<StringInit>(Message))
PrintNote(MessageInit->getValue());
else
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index b7d355ec406d3a7..2bff70dbdbda2d0 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -3125,7 +3125,7 @@ void Record::checkRecordDumps() {
for (const auto &Dump : getDumps()) {
Init *Message = Dump.Message->resolveReferences(R);
- CheckDump(Dump.Loc, Message);
+ dumpMessage(Dump.Loc, Message);
}
}
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index ff3d45703aaec69..7ea7c4b0870be36 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -405,7 +405,7 @@ bool TGParser::addEntry(RecordsEntry E) {
}
if (E.Dump) {
- CheckDump(E.Dump->Loc, E.Dump->Message);
+ dumpMessage(E.Dump->Loc, E.Dump->Message);
return false;
}
@@ -513,7 +513,7 @@ bool TGParser::resolve(const std::vector<RecordsEntry> &Source,
Dest->push_back(
std::make_unique<Record::DumpInfo>(E.Dump->Loc, Message));
else
- CheckDump(E.Dump->Loc, Message);
+ dumpMessage(E.Dump->Loc, Message);
} else {
auto Rec = std::make_unique<Record>(*E.Rec);
>From d4223ea63fef03d3719006b02f89288be8aa47c7 Mon Sep 17 00:00:00 2001
From: Francesco Petrogalli <francesco.petrogalli at apple.com>
Date: Thu, 12 Oct 2023 10:29:39 +0200
Subject: [PATCH 07/12] Use the correct Loc.
---
llvm/lib/TableGen/Error.cpp | 2 +-
llvm/lib/TableGen/TGParser.cpp | 3 ++-
llvm/test/TableGen/dump.td | 35 +++++++++++++++++-----------------
3 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/llvm/lib/TableGen/Error.cpp b/llvm/lib/TableGen/Error.cpp
index c61140fa03dbf29..1d3431de08b7af8 100644
--- a/llvm/lib/TableGen/Error.cpp
+++ b/llvm/lib/TableGen/Error.cpp
@@ -173,7 +173,7 @@ void CheckAssert(SMLoc Loc, Init *Condition, Init *Message) {
// Dump a message to stderr.
void dumpMessage(SMLoc Loc, Init *Message) {
if (auto *MessageInit = dyn_cast<StringInit>(Message))
- PrintNote(MessageInit->getValue());
+ PrintNote(Loc, MessageInit->getValue());
else
PrintNote("(dump message is not a string - use `!repr`)");
}
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 7ea7c4b0870be36..6450097d03f38b3 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -4392,6 +4392,8 @@ LLVM_DUMP_METHOD void MultiClass::dump() const {
#endif
bool TGParser::ParseDump(MultiClass *CurMultiClass, Record *CurRec) {
+ // Location of the `dump` statement.
+ SMLoc Loc = Lex.getLoc();
assert(Lex.getCode() == tgtok::Dump && "Unknown tok");
Lex.Lex(); // eat the operation
@@ -4406,7 +4408,6 @@ bool TGParser::ParseDump(MultiClass *CurMultiClass, Record *CurRec) {
if (!consume(tgtok::semi))
return TokError("expected ';'");
- SMLoc Loc = Lex.getLoc();
if (CurRec)
CurRec->addDump(Loc, Message);
else
diff --git a/llvm/test/TableGen/dump.td b/llvm/test/TableGen/dump.td
index ea0870a9a993138..aeb79ece08048f0 100644
--- a/llvm/test/TableGen/dump.td
+++ b/llvm/test/TableGen/dump.td
@@ -1,46 +1,45 @@
-// RUN: llvm-tblgen %s -o - 2>&1 >/dev/null | FileCheck %s
+// RUN: llvm-tblgen %s -o - 2>&1 >/dev/null | FileCheck %s -DFILE=%s
-// CHECK-LABEL: Debug message
+// CHECK: [[FILE]]:[[@LINE+1]]:1: note: Debug message
dump "Debug message";
-// CHECK-LABEL: The Value of A is:
-// CHECK-NEXT: a { // A
-// CHECK-NEXT: string A = "some text";
-// CHECK-NEXT: dag X = (op op);
-// CHECK-NEXT: }
def op;
class A {
string A = "some text";
dag X =(op op);
}
def a : A;
+// CHECK: [[FILE]]:[[@LINE+5]]:1: note: The Value of A is:
+// CHECK-NEXT: a { // A
+// CHECK-NEXT: string A = "some text";
+// CHECK-NEXT: dag X = (op op);
+// CHECK-NEXT: }
dump "The Value of A is: \n" # !repr(a);
-
-// CHECK-LABEL: b { // A
+def b : A;
+// CHECK: [[FILE]]:[[@LINE+4]]:1: note: b { // A
// CHECK-NEXT: string A = "some text";
// CHECK-NEXT: dag X = (op op);
// CHECK-NEXT: }
-def b : A;
dump !repr(b) ;
-// CHECK-LABEL: got a pair of values ["some other text" : 12], and an empty record:
-// CHECK-NEXT: X {
-// CHECK-NEXT: }
defvar value_A = "some other text";
defvar value_B = 12;
def X;
+// CHECK: [[FILE]]:[[@LINE+3]]:1: note: got a pair of values ["some other text" : 12], and an empty record:
+// CHECK-NEXT: X {
+// CHECK-NEXT: }
dump "got a pair of values [" # !repr(value_A) # " : " # !repr(value_B) # "], " # "and an empty record:\n" # !repr(X);
multiclass MC<dag s> {
+// CHECK: [[FILE]]:[[@LINE+1]]:3: note: s = (op a)
dump "s = " # !repr(s);
- dump "args[0] = " # !repr(!getdagarg<A>(s,0));
- def A;
-}
-// CHECK-LABEL: note: s = (op a)
-// CHECK-NEXT: args[0] = a { // A
+// CHECK: [[FILE]]:[[@LINE+4]]:3: note: args[0] = a { // A
// CHECK-NEXT: string A = "some text";
// CHECK-NEXT: dag X = (op op);
// CHECK-NEXT: }
+ dump "args[0] = " # !repr(!getdagarg<A>(s,0));
+ def A;
+}
defm X : MC<(op a)>;
>From 97187e7f84faa22a652c70da15c1e2f82de61034 Mon Sep 17 00:00:00 2001
From: Francesco Petrogalli <francesco.petrogalli at apple.com>
Date: Thu, 12 Oct 2023 10:38:17 +0200
Subject: [PATCH 08/12] test for warning on not using a string.
---
llvm/lib/TableGen/Error.cpp | 2 +-
llvm/test/TableGen/dump-error.td | 10 ++++++++++
2 files changed, 11 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/TableGen/dump-error.td
diff --git a/llvm/lib/TableGen/Error.cpp b/llvm/lib/TableGen/Error.cpp
index 1d3431de08b7af8..72ae94ffd6159c8 100644
--- a/llvm/lib/TableGen/Error.cpp
+++ b/llvm/lib/TableGen/Error.cpp
@@ -175,7 +175,7 @@ void dumpMessage(SMLoc Loc, Init *Message) {
if (auto *MessageInit = dyn_cast<StringInit>(Message))
PrintNote(Loc, MessageInit->getValue());
else
- PrintNote("(dump message is not a string - use `!repr`)");
+ PrintNote(Loc, "dump message is not a string - use `!repr`");
}
} // end namespace llvm
diff --git a/llvm/test/TableGen/dump-error.td b/llvm/test/TableGen/dump-error.td
new file mode 100644
index 000000000000000..0c7f58cbb3b8f9e
--- /dev/null
+++ b/llvm/test/TableGen/dump-error.td
@@ -0,0 +1,10 @@
+// RUN: llvm-tblgen %s -o - 2>&1 >/dev/null | FileCheck %s -DFILE=%s
+
+def op;
+class A {
+ string A = "some text";
+ dag X =(op op);
+}
+def a : A;
+// CHECK: [[FILE]]:[[@LINE+1]]:1: note: dump message is not a string - use `!repr`
+dump a;
>From 9c923a50a0131a5114c94b80a5da975e53f6bd46 Mon Sep 17 00:00:00 2001
From: Francesco Petrogalli <francesco.petrogalli at apple.com>
Date: Thu, 12 Oct 2023 10:41:07 +0200
Subject: [PATCH 09/12] Print a warning instead of a note if the dump operand
is not a string.
---
llvm/lib/TableGen/Error.cpp | 2 +-
llvm/test/TableGen/{dump-error.td => dump-warning.td} | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
rename llvm/test/TableGen/{dump-error.td => dump-warning.td} (64%)
diff --git a/llvm/lib/TableGen/Error.cpp b/llvm/lib/TableGen/Error.cpp
index 72ae94ffd6159c8..146a896fa27e258 100644
--- a/llvm/lib/TableGen/Error.cpp
+++ b/llvm/lib/TableGen/Error.cpp
@@ -175,7 +175,7 @@ void dumpMessage(SMLoc Loc, Init *Message) {
if (auto *MessageInit = dyn_cast<StringInit>(Message))
PrintNote(Loc, MessageInit->getValue());
else
- PrintNote(Loc, "dump message is not a string - use `!repr`");
+ PrintWarning(Loc, "dump message is not a string - use `!repr`");
}
} // end namespace llvm
diff --git a/llvm/test/TableGen/dump-error.td b/llvm/test/TableGen/dump-warning.td
similarity index 64%
rename from llvm/test/TableGen/dump-error.td
rename to llvm/test/TableGen/dump-warning.td
index 0c7f58cbb3b8f9e..0bb1e2205a37e38 100644
--- a/llvm/test/TableGen/dump-error.td
+++ b/llvm/test/TableGen/dump-warning.td
@@ -6,5 +6,5 @@ class A {
dag X =(op op);
}
def a : A;
-// CHECK: [[FILE]]:[[@LINE+1]]:1: note: dump message is not a string - use `!repr`
+// CHECK: [[FILE]]:[[@LINE+1]]:1: warning: dump message is not a string - use `!repr`
dump a;
>From 346574f3311471d667c7223cc99f911bc7b4971d Mon Sep 17 00:00:00 2001
From: Francesco Petrogalli <francesco.petrogalli at apple.com>
Date: Thu, 12 Oct 2023 11:15:25 +0200
Subject: [PATCH 10/12] Test if/foreach/defvar [NFCI].
---
llvm/test/TableGen/dump.td | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/llvm/test/TableGen/dump.td b/llvm/test/TableGen/dump.td
index aeb79ece08048f0..d90c33c2c28d1ee 100644
--- a/llvm/test/TableGen/dump.td
+++ b/llvm/test/TableGen/dump.td
@@ -43,3 +43,16 @@ multiclass MC<dag s> {
}
defm X : MC<(op a)>;
+foreach i = [-1, 2] in {
+// CHECK: [[FILE]]:[[@LINE+4]]:3: note: i = -1 (negative)
+// CHECK: [[FILE]]:[[@LINE+8]]:5: note: i + 1 <= 0
+// CHECK: [[FILE]]:[[@LINE+2]]:3: note: i = 2 (positive)
+// CHECK: [[FILE]]:[[@LINE+4]]:5: note: i + 1 > 0 (i + 1 = 3)
+ dump "i = " # !repr(i) # !if(!ge(i,0), " (positive)", " (negative)");
+ defvar ip1 = !add(i, 1);
+ if !gt(ip1,0) then {
+ dump "i + 1 > 0 (i + 1 = " # !repr(ip1) # ")";
+ } else {
+ dump "i + 1 <= 0" ;
+ }
+}
>From 4d77fc836899b88a41e2dbd53ccafc48bf8f671f Mon Sep 17 00:00:00 2001
From: Francesco Petrogalli <francesco.petrogalli at apple.com>
Date: Thu, 12 Oct 2023 11:54:04 +0200
Subject: [PATCH 11/12] Check the use of dump in `class`, even through
inhertance.
---
llvm/include/llvm/TableGen/Record.h | 2 ++
llvm/lib/TableGen/Record.cpp | 11 +++++++++++
llvm/lib/TableGen/TGParser.cpp | 4 ++++
llvm/test/TableGen/dump.td | 15 +++++++++++++++
4 files changed, 32 insertions(+)
diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h
index f220b713efcd8f0..3976fd80e715124 100644
--- a/llvm/include/llvm/TableGen/Record.h
+++ b/llvm/include/llvm/TableGen/Record.h
@@ -1821,6 +1821,8 @@ class Record {
Assertions.append(Rec->Assertions);
}
+ void appendDumps(const Record *Rec) { Dumps.append(Rec->Dumps); }
+
void checkRecordAssertions();
void checkRecordDumps();
void checkUnusedTemplateArgs();
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index 2bff70dbdbda2d0..ebf0f2e848c40f8 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -2272,6 +2272,9 @@ DefInit *VarDefInit::instantiate() {
// Copy assertions from class to instance.
NewRec->appendAssertions(Class);
+ // Copy dumps from class to instance.
+ NewRec->appendDumps(Class);
+
// Substitute and resolve template arguments
ArrayRef<Init *> TArgs = Class->getTemplateArgs();
MapResolver R(NewRec);
@@ -2306,6 +2309,9 @@ DefInit *VarDefInit::instantiate() {
// Check the assertions.
NewRec->checkRecordAssertions();
+ // Check the assertions.
+ NewRec->checkRecordDumps();
+
Def = DefInit::get(NewRec);
}
@@ -2863,6 +2869,11 @@ void Record::resolveReferences(Resolver &R, const RecordVal *SkipVal) {
Value = Assertion.Message->resolveReferences(R);
Assertion.Message = Value;
}
+ // Resolve the dump expressions.
+ for (auto &Dump : Dumps) {
+ Init *Value = Dump.Message->resolveReferences(R);
+ Dump.Message = Value;
+ }
}
void Record::resolveReferences(Init *NewName) {
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 6450097d03f38b3..51181c9b9a43bb7 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -313,6 +313,9 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
// Copy the subclass record's assertions to the new record.
CurRec->appendAssertions(SC);
+ // Copy the subclass record's dumps to the new record.
+ CurRec->appendDumps(SC);
+
Init *Name;
if (CurRec->isClass())
Name = VarInit::get(QualifiedNameOfImplicitName(*CurRec),
@@ -4269,6 +4272,7 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
/// Object ::= Defset
/// Object ::= Defvar
/// Object ::= Assert
+/// Object ::= Dump
bool TGParser::ParseObject(MultiClass *MC) {
switch (Lex.getCode()) {
default:
diff --git a/llvm/test/TableGen/dump.td b/llvm/test/TableGen/dump.td
index d90c33c2c28d1ee..8b3a48db50dfd90 100644
--- a/llvm/test/TableGen/dump.td
+++ b/llvm/test/TableGen/dump.td
@@ -56,3 +56,18 @@ foreach i = [-1, 2] in {
dump "i + 1 <= 0" ;
}
}
+
+class Code<code val> {
+ dump "val = " # !repr(val);
+ code Val = val;
+ int number = 0;
+}
+// CHECK: [[FILE]]:[[@LINE-4]]:3: note: val = [{a = a +1;}]
+def IncrementA : Code<[{a = a +1;}]>;
+class InheritFromCode : Code<[{f(x);}]>{
+ let number = 33;
+ dump "number = " # !repr(number);
+}
+// CHECK: [[FILE]]:[[@LINE-10]]:3: note: val = [{f(x);}]
+// CHECK: [[FILE]]:[[@LINE-3]]:3: note: number = 33
+def ModeCode : InheritFromCode;
>From cd815dfa8456902ca3325c87df886f7b528c6384 Mon Sep 17 00:00:00 2001
From: Francesco Petrogalli <francesco.petrogalli at apple.com>
Date: Thu, 12 Oct 2023 12:24:08 +0200
Subject: [PATCH 12/12] Test dump on defset.
Added a comment to the place were we could make repr look recursively
into a list.
---
llvm/lib/TableGen/Record.cpp | 9 ++++++---
llvm/test/TableGen/dump.td | 13 +++++++++++++
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index ebf0f2e848c40f8..baecc40bc475b84 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -806,9 +806,12 @@ Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const {
OS << *Def->getDef();
OS.flush();
return StringInit::get(RK, S);
- }
- // Otherwise, print the value of the variable.
- else {
+ } else {
+ // Otherwise, print the value of the variable.
+ //
+ // NOTE: we could look recursively !repr the elements of a
+ // list, but that could produce a lot of output when printing
+ // a defset.
return StringInit::get(RK, LHS->getAsString());
}
}
diff --git a/llvm/test/TableGen/dump.td b/llvm/test/TableGen/dump.td
index 8b3a48db50dfd90..6b49cd0d9de0a5b 100644
--- a/llvm/test/TableGen/dump.td
+++ b/llvm/test/TableGen/dump.td
@@ -71,3 +71,16 @@ class InheritFromCode : Code<[{f(x);}]>{
// CHECK: [[FILE]]:[[@LINE-10]]:3: note: val = [{f(x);}]
// CHECK: [[FILE]]:[[@LINE-3]]:3: note: number = 33
def ModeCode : InheritFromCode;
+
+
+class BaseClassForSet;
+multiclass DefineSubSet {
+ def _One : BaseClassForSet;
+ def _Two : BaseClassForSet;
+}
+defset list<BaseClassForSet> TheSet = {
+defm Subset: DefineSubSet;
+def Three : BaseClassForSet;
+}
+// CHECK: [[FILE]]:[[@LINE+1]]:1: note: TheSet = [Subset_One, Subset_Two, Three]
+dump "TheSet = " # !repr(TheSet);
More information about the llvm-commits
mailing list