-
Notifications
You must be signed in to change notification settings - Fork 11k
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
[lldb] Support custom LLVM formatting for variables #81196
[lldb] Support custom LLVM formatting for variables #81196
Conversation
@llvm/pr-subscribers-lldb Author: Dave Lee (kastiglione) ChangesFull diff: https://github.com/llvm/llvm-project/pull/81196.diff 1 Files Affected:
diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp
index fa5eadc6ff4e9a..0e929203935304 100644
--- a/lldb/source/Core/FormatEntity.cpp
+++ b/lldb/source/Core/FormatEntity.cpp
@@ -883,8 +883,29 @@ static bool DumpValue(Stream &s, const SymbolContext *sc,
}
if (!is_array_range) {
- LLDB_LOGF(log,
- "[Debugger::FormatPrompt] dumping ordinary printable output");
+ if (!entry.printf_format.empty()) {
+ auto type_info = target->GetTypeInfo();
+ if (type_info & eTypeIsInteger) {
+ if (type_info & eTypeIsSigned) {
+ bool success = false;
+ auto integer = target->GetValueAsSigned(0, &success);
+ if (success) {
+ LLDB_LOGF(log, "dumping using printf format");
+ s.Printf(entry.printf_format.c_str(), integer);
+ return true;
+ }
+ } else {
+ bool success = false;
+ auto integer = target->GetValueAsUnsigned(0, &success);
+ if (success) {
+ LLDB_LOGF(log, "dumping using printf format");
+ s.Printf(entry.printf_format.c_str(), integer);
+ return true;
+ }
+ }
+ }
+ }
+ LLDB_LOGF(log, "dumping ordinary printable output");
return target->DumpPrintableRepresentation(s, val_obj_display,
custom_format);
} else {
|
Note that the implementation here is a draft for illustration. I am first interested in high level agreement that allowing custom printf formatting of variables is good. |
The way the current FormatEntity strings work, the first
The "kind of formatter" is "%" which seems like a reasonable name for "printf format string following". To be entirely strict, if the data following the "kind" is the format string, this should be:
but that's kind of silly. I think it's fine to say the format kind If you didn't like the two percents, you could do this by having This seems fine to me. |
Should this be documented in |
@adrian-prantl good call, done. |
@jimingham I've updated the PR to a non-draft form if you want to check out the implementation. |
lldb/source/Core/FormatEntity.cpp
Outdated
static bool DumpValueWithPrintf(Stream &s, llvm::StringRef format, | ||
ValueObject &target) { | ||
auto type_info = target.GetTypeInfo(); | ||
if (type_info & eTypeIsInteger) { |
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.
Is there a reason not to do the same thing for eTypeIsFloat?
I've updated this PR to use llvm formatting instead of printf. For the following reasons:
Getting the size wrong could be any of undefined behavior, buggy, crashy, insecure. |
@jimingham now that I've switched to llvm format, I'll loop back and follow up on your comments. |
static bool DumpValueWithLLVMFormat(Stream &s, llvm::StringRef options, | ||
ValueObject &target) { | ||
std::string formatted; | ||
std::string llvm_format = ("{0:" + options + "}").str(); |
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.
Is there any way we can make this string static, by switching over the supported options?
Or let me ask another way — what happens if options contained "}{1}" is this well-defined in llvm::formatv because it knows the template arguments and thus will not lead to corruption and crashes?
If the answer is yes, then this is okay.
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.
by switching over the supported options?
There are many supported options, and they vary from type to type (int has different options than say strings). See FormatProviders.h for the builtins.
It would be possible to exhaustively iterate all the options llvm includes, but I'm not sure it would be worth it. Switching over them seems fragile to changes made to the source of truth in llvm.
I will check/test what llvm does for invalid options.
lldb/test/API/functionalities/data-formatter/custom-printf-summary/TestCustomPrintfSummary.py
Outdated
Show resolved
Hide resolved
✅ With the latest revision this PR passed the Python code formatter. |
lldb/test/API/functionalities/data-formatter/custom-printf-summary/TestCustomPrintfSummary.py
Outdated
Show resolved
Hide resolved
This diff broke buildbot: https://lab.llvm.org/buildbot/#/builders/68/builds/73367 |
This reverts commit 7a8d15e.
Adds support for applying LLVM formatting to variables.
The reason for this is to support cases such as the following.
Let's say you have two separate bytes that you want to print as a combined hex value. Consider the following summary string:
The output of this will be:
0x120x34
. That is, a0x
prefix is unconditionally applied to each byte. This is unlike printf formatting where you must include the0x
yourself.Currently, there's no way to do this with summary strings, instead you'll need a summary provider in python or c++.
This change introduces formatting support using LLVM's formatter system. This allows users to achieve the desired custom formatting using:
Here, each variable is suffixed with
:x-
. This is passed to the LLVM formatter as{0:x-}
. For integer values,x
declares the output as hex, and-
declares that no0x
prefix is to be used. Further, one could write:Where the added
2
results in these bytes being written with a minimum of 2 digits.An alternative considered was to add a new format specifier that would print hex values without the
0x
prefix. The reason that approach was not taken is because in addition to forcing a0x
prefix, hex values are also forced to use leading zeros. This approach lets the user have full control over formatting.