-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Add DumpId() methods to Check::Context, Parse::Tree, Lex::TokenizedBuffer #4620
Conversation
856f2e7
to
9bb864a
Compare
…ffer These methods are useful for calling in a debugger, and will dump verbose information from an id value. Currently this is done in a pretty simple manner. The Lex and Parse methods are each replicated onto the Check::Context class manually (and same for Lex onto Parse::Tree). The DumpId methods are implemented in this PR for: - Lex::TokenIndex - Parse::NodeId - SemIR::LocId
Thanks for all the feedback on discord #toolchain. After determining what is possible this is a slimmer version that uses explicit forwarding from Check->Parse/Lex and Parse->Lex for dumping as suggested by @jonmeow . I have used the name DumpId as suggested by @geoffromer. I did not use a template, as the interactive debugger experience seems to be degraded (having to type angle brackets and types) even if we can resolve the linking issues created. |
Regarding my comment about being hesitant about adding (to be sure, I think we agreed the |
toolchain/check/dump_id.cpp
Outdated
auto DumpIdMethods<Context>::Newline() const -> void { | ||
llvm::errs() << "\n"; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the function for this instead of doing the write directly? Maybe the function should have some comments if it's needed?
Also, maybe this should be WriteNewline
? We typically name functions describing the action being taken, and it actually was unclear to me what Newline
would do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to avoid putting streaming includes into the header file, since operator<< is bad for compile times. Is this something we think about here? I took a quick look around and saw that the streaming includes had been generally avoided in headers elsewhere so far.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure which include you're looking for, but "common/ostream.h" seems to be relatively common in headers. (it's not something we avoid, it's actually more by design for correctness)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok noted, thanks, I will not try to avoid specific includes in header files then. I moved to using this header everywhere.
I wanted to reduce the number of steps you have to go through to dump things. Having to find and remember to construct a dumper type felt worse than having the methods on Context directly. But having a bunch of overloads right in context.h won't be great, so this felt like the right compromise to me. The use of CRTP specifically is to avoid state (passing a pointer up to the base class) and to avoid a Context parameter on the methods. |
To be sure, I'm suggesting a construction wouldn't be needed, it's just writing
Maintaining shortness, what if we had |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be sure, I'm suggesting a construction wouldn't be needed, it's just writing
context.dumper().Dump
instead ofcontext.Dump
That's more verbose than I'd like, considering that this function is intended to be called by typing out the call expression live.
Maintaining shortness, what if we had
Carbon::Dump(Context&, ..)
Carbon::Dump(TokenizedBuffer&, ...)
etc? i.e.,Dump(context
instead ofcontext.Dump
That seems like it could work, assuming I can call it from a debugger without the Carbon::
prefix. (I'm not sure if the change from DumpId
to Dump
was part of your point, but I think we should reserve Dump
for functions that print the value itself, rather than printing the thing the value refers to).
toolchain/check/dump_id.h
Outdated
// This class is inherited by `Check::Context`, which provides itself as the | ||
// template parameter. The methods are provided here instead of on `Context` | ||
// directly to avoid cluttering the `Context` class with overloads for every | ||
// dumpable id type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is a good tradeoff. The clutter of making these methods of Context
seems minimal compared to the complexity associated with the CRTP mixin (especially given how many methods Context
already has).
toolchain/lex/dump_id.cpp
Outdated
|
||
#include "toolchain/lex/dump_id.h" | ||
|
||
#include "llvm/Support/raw_ostream.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, to the point about common/ostream.h -- please include it instead of llvm/Support/raw_ostream.h. As noted in common/ostream.h, I'm trying to avoid having people include raw_ostream.h directly, in order to get more consistent behavior.
Hm, I tried this, with free functions in the Carbon namespace. namespace Carbon {
LLVM_DUMP_METHOD auto DumpId(const Check::Context& context, SemIR::LocId loc_id)
-> void;
} // namespace Carbon But gdb is not finding them at all,
|
I think --gc-sections is going to just remove free functions on us. Either I can move them to just be methods in the respective types though. |
Huh, interesting - could you post a commit/hash/personal PR/whatnot I could use to reproduce/try this? A small non-carbon example I tried did seem to find a Dump function in another translation unit via qualified name lookup, so I'm not sure what's different in your case/wouldn't mind poking around to figur eit out. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me, but I'm leaving it open because I'm not sure Jon's concerns have been addressed.
(nevermind - sounds like @jonmeow & @zygoloid figured it out - the Dump functions maybe weren't getting linked into the resultin grogram - Jon's working on some improvements I think (not to steal his thunder, just didn't want @danakj working on a repro, etc for me when it wasn't needed anymore)) |
I think maybe there's an alwayslink missing, see #4669 for an approach that I've manually tested and appears to work. (* I should do another pass, I just split things out to separate cc_library's, but I think alwayslink is what's important [ed: did another pass, verified]) One note from discussion yesterday, @zygoloid had mentioned being dubious of overloads working, but @dwblaikie expects they should. So we're going to try overloads, counter to earlier discussion. We'd also discussed whether |
Moving to #4669 |
- Provide `Check::Dump(context, arg)` and similar. - gdb and lldb should do contextual lookup, and `call Dump(*this, Lex::TokenIndex::Invalid)` has been tested with gdb. - Since this is only for debug, keeps the functions fully separated from code. - Uses alwayslink to ensure objects are correctly linked, even though there are no calls. - `-Wno-missing-prototypes` is needed when we don't have forward declarations. - Code is not linked in opt builds, using `#ifndef NDEBUG`. - This probably could be doing something in BUILD files with a `select()`, but the `#ifndef` seemed easier. This is based on #4620, but uses free functions instead of member functions. Co-authored-by: Dana Jansens <danakj@orodu.net> --------- Co-authored-by: danakj <danakj@orodu.net>
- Provide `Check::Dump(context, arg)` and similar. - gdb and lldb should do contextual lookup, and `call Dump(*this, Lex::TokenIndex::Invalid)` has been tested with gdb. - Since this is only for debug, keeps the functions fully separated from code. - Uses alwayslink to ensure objects are correctly linked, even though there are no calls. - `-Wno-missing-prototypes` is needed when we don't have forward declarations. - Code is not linked in opt builds, using `#ifndef NDEBUG`. - This probably could be doing something in BUILD files with a `select()`, but the `#ifndef` seemed easier. This is based on carbon-language#4620, but uses free functions instead of member functions. Co-authored-by: Dana Jansens <danakj@orodu.net> --------- Co-authored-by: danakj <danakj@orodu.net>
No description provided.