Skip to content

[Tablegen] Add keyword dump. #68793

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
004967c
[Tablegen] Add keywork `dump`.
fpetrogalli Oct 10, 2023
59813e6
Rename var. [NFC]
fpetrogalli Oct 11, 2023
0fab2a6
Update llvm/docs/TableGen/ProgRef.rst
fpetrogalli Oct 12, 2023
71e687d
Update llvm/docs/TableGen/ProgRef.rst
fpetrogalli Oct 12, 2023
6cc1fa7
Update llvm/lib/TableGen/Error.cpp
fpetrogalli Oct 12, 2023
3a1192b
s/CheckDump/dumpMessage
fpetrogalli Oct 12, 2023
d4223ea
Use the correct Loc.
fpetrogalli Oct 12, 2023
97187e7
test for warning on not using a string.
fpetrogalli Oct 12, 2023
9c923a5
Print a warning instead of a note if the dump operand is not a string.
fpetrogalli Oct 12, 2023
346574f
Test if/foreach/defvar [NFCI].
fpetrogalli Oct 12, 2023
4d77fc8
Check the use of dump in `class`, even through inhertance.
fpetrogalli Oct 12, 2023
cd815df
Test dump on defset.
fpetrogalli Oct 12, 2023
977666e
s/checkRecordDumps/emitRecordDumps/ [NFC]
fpetrogalli Oct 12, 2023
529758f
Update coment in llvm/lib/TableGen/Record.cpp [NFC]
fpetrogalli Oct 13, 2023
3fd5df2
Apply clang-format to latest commit. [NFC]
fpetrogalli Oct 13, 2023
7164ec4
Allow dumping of def and defvar directly.
fpetrogalli Oct 13, 2023
45f067b
Remove unused variable. [NFC]
fpetrogalli Oct 13, 2023
2562922
Enforce dumpMessage to require a StringInit to print.
fpetrogalli Oct 13, 2023
36a00b8
[docs] Explain when the messages are instantiated. [NFC]
fpetrogalli Oct 13, 2023
5ffabf3
Add test case with multiple nested `defm`. [NFC]
fpetrogalli Oct 13, 2023
f270615
Fix code formmatting [NFC]
fpetrogalli Oct 13, 2023
3c1f83d
Update docs after review feedback in https://github.com/llvm/llvm-pro…
fpetrogalli Oct 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 28 additions & 5 deletions llvm/docs/TableGen/ProgRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -1275,6 +1275,29 @@ 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.

* At top level, the message is printed immediately.

* Within a record/class/multiclass, `dump` gets evaluated at each
instantiation point of the containing record.

.. productionlist::
Dump: "dump" `string` ";"

For example, it can be used in combination with `!repr` to investigate
the values passed to a multiclass:

.. code-block:: text

multiclass MC<dag s> {
dump "s = " # !repr(s);
}


``if`` --- select statements based on a test
--------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/TableGen/Error.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 dumpMessage(SMLoc Loc, Init *Message);

extern SourceMgr SrcMgr;
extern unsigned ErrorsPrinted;
Expand Down
18 changes: 18 additions & 0 deletions llvm/include/llvm/TableGen/Record.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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).
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1802,11 +1813,18 @@ 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 appendDumps(const Record *Rec) { Dumps.append(Rec->Dumps); }

void checkRecordAssertions();
void emitRecordDumps();
void checkUnusedTemplateArgs();

bool isSubClassOf(const Record *R) const {
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/TableGen/Error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,11 @@ void CheckAssert(SMLoc Loc, Init *Condition, Init *Message) {
}
}

// Dump a message to stderr.
void dumpMessage(SMLoc Loc, Init *Message) {
auto *MessageInit = dyn_cast<StringInit>(Message);
assert(MessageInit && "no debug message to print");
PrintNote(Loc, MessageInit->getValue());
}

} // end namespace llvm
30 changes: 27 additions & 3 deletions llvm/lib/TableGen/Record.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 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());
}
}
Expand Down Expand Up @@ -2272,6 +2275,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);
Expand Down Expand Up @@ -2306,6 +2312,9 @@ DefInit *VarDefInit::instantiate() {
// Check the assertions.
NewRec->checkRecordAssertions();

// Check the assertions.
NewRec->emitRecordDumps();

Def = DefInit::get(NewRec);
}

Expand Down Expand Up @@ -2863,6 +2872,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) {
Expand Down Expand Up @@ -3119,6 +3133,16 @@ void Record::checkRecordAssertions() {
}
}

void Record::emitRecordDumps() {
RecordResolver R(*this);
R.setFinal(true);

for (const auto &Dump : getDumps()) {
Init *Message = Dump.Message->resolveReferences(R);
dumpMessage(Dump.Loc, Message);
}
}

// Report a warning if the record has unused template arguments.
void Record::checkUnusedTemplateArgs() {
for (const Init *TA : getTemplateArgs()) {
Expand Down
51 changes: 26 additions & 25 deletions llvm/lib/TableGen/TGLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/TableGen/TGLexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ enum TokKind {
Defm,
Defset,
Defvar,
Dump,
Foreach,
If,
Let,
Expand Down
Loading