2016-11-17 05:15:24 +08:00
|
|
|
//===-- FormatManager.cpp ----------------------------------------*- C++-*-===//
|
2011-06-24 01:59:56 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2011-06-24 01:59:56 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-01-29 07:47:25 +08:00
|
|
|
#include "lldb/DataFormatters/FormatManager.h"
|
2011-06-24 01:59:56 +08:00
|
|
|
|
2015-10-20 12:50:09 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
|
2011-06-24 01:59:56 +08:00
|
|
|
|
2011-07-15 10:26:42 +08:00
|
|
|
#include "lldb/Core/Debugger.h"
|
2015-09-02 09:21:31 +08:00
|
|
|
#include "lldb/DataFormatters/FormattersHelpers.h"
|
2015-09-02 02:22:39 +08:00
|
|
|
#include "lldb/DataFormatters/LanguageCategory.h"
|
2013-01-29 07:47:25 +08:00
|
|
|
#include "lldb/Target/ExecutionContext.h"
|
2015-09-05 05:01:18 +08:00
|
|
|
#include "lldb/Target/Language.h"
|
2017-03-04 04:56:28 +08:00
|
|
|
#include "lldb/Utility/Log.h"
|
2015-09-02 02:22:39 +08:00
|
|
|
|
2011-06-24 01:59:56 +08:00
|
|
|
using namespace lldb;
|
|
|
|
using namespace lldb_private;
|
2015-09-02 09:21:31 +08:00
|
|
|
using namespace lldb_private::formatters;
|
2011-06-24 05:22:24 +08:00
|
|
|
|
|
|
|
struct FormatInfo {
|
|
|
|
Format format;
|
|
|
|
const char format_char; // One or more format characters that can be used for
|
|
|
|
// this format.
|
|
|
|
const char *format_name; // Long format name that can be used to specify the
|
|
|
|
// current format
|
|
|
|
};
|
|
|
|
|
2019-08-22 10:56:00 +08:00
|
|
|
static constexpr FormatInfo g_format_infos[] = {
|
2011-06-24 05:22:24 +08:00
|
|
|
{eFormatDefault, '\0', "default"},
|
|
|
|
{eFormatBoolean, 'B', "boolean"},
|
|
|
|
{eFormatBinary, 'b', "binary"},
|
|
|
|
{eFormatBytes, 'y', "bytes"},
|
|
|
|
{eFormatBytesWithASCII, 'Y', "bytes with ASCII"},
|
|
|
|
{eFormatChar, 'c', "character"},
|
|
|
|
{eFormatCharPrintable, 'C', "printable character"},
|
|
|
|
{eFormatComplexFloat, 'F', "complex float"},
|
|
|
|
{eFormatCString, 's', "c-string"},
|
Added support for the new ".apple_objc" accelerator tables. These tables are
in the same hashed format as the ".apple_names", but they map objective C
class names to all of the methods and class functions. We need to do this
because in the DWARF the methods for Objective C are never contained in the
class definition, they are scattered about at the translation unit level and
they don't even have attributes that say the are contained within the class
itself.
Added 3 new formats which can be used to display data:
eFormatAddressInfo
eFormatHexFloat
eFormatInstruction
eFormatAddressInfo describes an address such as function+offset and file+line,
or symbol + offset, or constant data (c string, 2, 4, 8, or 16 byte constants).
The format character for this is "A", the long format is "address".
eFormatHexFloat will print out the hex float format that compilers tend to use.
The format character for this is "X", the long format is "hex float".
eFormatInstruction will print out disassembly with bytes and it will use the
current target's architecture. The format character for this is "i" (which
used to be being used for the integer format, but the integer format also has
"d", so we gave the "i" format to disassembly), the long format is
"instruction".
Mate the lldb::FormatterChoiceCriterion enumeration private as it should have
been from the start. It is very specialized and doesn't belong in the public
API.
llvm-svn: 143114
2011-10-28 01:55:14 +08:00
|
|
|
{eFormatDecimal, 'd', "decimal"},
|
2011-06-24 05:22:24 +08:00
|
|
|
{eFormatEnum, 'E', "enumeration"},
|
|
|
|
{eFormatHex, 'x', "hex"},
|
2012-08-10 03:33:34 +08:00
|
|
|
{eFormatHexUppercase, 'X', "uppercase hex"},
|
2011-06-24 05:22:24 +08:00
|
|
|
{eFormatFloat, 'f', "float"},
|
|
|
|
{eFormatOctal, 'o', "octal"},
|
|
|
|
{eFormatOSType, 'O', "OSType"},
|
|
|
|
{eFormatUnicode16, 'U', "unicode16"},
|
|
|
|
{eFormatUnicode32, '\0', "unicode32"},
|
|
|
|
{eFormatUnsigned, 'u', "unsigned decimal"},
|
|
|
|
{eFormatPointer, 'p', "pointer"},
|
|
|
|
{eFormatVectorOfChar, '\0', "char[]"},
|
|
|
|
{eFormatVectorOfSInt8, '\0', "int8_t[]"},
|
|
|
|
{eFormatVectorOfUInt8, '\0', "uint8_t[]"},
|
|
|
|
{eFormatVectorOfSInt16, '\0', "int16_t[]"},
|
|
|
|
{eFormatVectorOfUInt16, '\0', "uint16_t[]"},
|
2011-07-06 23:56:06 +08:00
|
|
|
{eFormatVectorOfSInt32, '\0', "int32_t[]"},
|
|
|
|
{eFormatVectorOfUInt32, '\0', "uint32_t[]"},
|
|
|
|
{eFormatVectorOfSInt64, '\0', "int64_t[]"},
|
|
|
|
{eFormatVectorOfUInt64, '\0', "uint64_t[]"},
|
2015-10-16 16:28:47 +08:00
|
|
|
{eFormatVectorOfFloat16, '\0', "float16[]"},
|
2011-06-24 05:22:24 +08:00
|
|
|
{eFormatVectorOfFloat32, '\0', "float32[]"},
|
|
|
|
{eFormatVectorOfFloat64, '\0', "float64[]"},
|
|
|
|
{eFormatVectorOfUInt128, '\0', "uint128_t[]"},
|
|
|
|
{eFormatComplexInteger, 'I', "complex integer"},
|
Added support for the new ".apple_objc" accelerator tables. These tables are
in the same hashed format as the ".apple_names", but they map objective C
class names to all of the methods and class functions. We need to do this
because in the DWARF the methods for Objective C are never contained in the
class definition, they are scattered about at the translation unit level and
they don't even have attributes that say the are contained within the class
itself.
Added 3 new formats which can be used to display data:
eFormatAddressInfo
eFormatHexFloat
eFormatInstruction
eFormatAddressInfo describes an address such as function+offset and file+line,
or symbol + offset, or constant data (c string, 2, 4, 8, or 16 byte constants).
The format character for this is "A", the long format is "address".
eFormatHexFloat will print out the hex float format that compilers tend to use.
The format character for this is "X", the long format is "hex float".
eFormatInstruction will print out disassembly with bytes and it will use the
current target's architecture. The format character for this is "i" (which
used to be being used for the integer format, but the integer format also has
"d", so we gave the "i" format to disassembly), the long format is
"instruction".
Mate the lldb::FormatterChoiceCriterion enumeration private as it should have
been from the start. It is very specialized and doesn't belong in the public
API.
llvm-svn: 143114
2011-10-28 01:55:14 +08:00
|
|
|
{eFormatCharArray, 'a', "character array"},
|
|
|
|
{eFormatAddressInfo, 'A', "address"},
|
2012-08-10 03:33:34 +08:00
|
|
|
{eFormatHexFloat, '\0', "hex float"},
|
2012-08-09 01:35:10 +08:00
|
|
|
{eFormatInstruction, 'i', "instruction"},
|
2019-08-22 11:12:25 +08:00
|
|
|
{eFormatVoid, 'v', "void"},
|
|
|
|
{eFormatUnicode8, 'u', "unicode8"},
|
|
|
|
};
|
2011-06-24 05:22:24 +08:00
|
|
|
|
2019-08-22 10:56:00 +08:00
|
|
|
static_assert((sizeof(g_format_infos) / sizeof(g_format_infos[0])) ==
|
|
|
|
kNumFormats,
|
|
|
|
"All formats must have a corresponding info entry.");
|
|
|
|
|
2014-06-27 13:17:41 +08:00
|
|
|
static uint32_t g_num_format_infos = llvm::array_lengthof(g_format_infos);
|
2011-06-24 05:22:24 +08:00
|
|
|
|
|
|
|
static bool GetFormatFromFormatChar(char format_char, Format &format) {
|
|
|
|
for (uint32_t i = 0; i < g_num_format_infos; ++i) {
|
|
|
|
if (g_format_infos[i].format_char == format_char) {
|
|
|
|
format = g_format_infos[i].format;
|
|
|
|
return true;
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2011-06-24 05:22:24 +08:00
|
|
|
format = eFormatInvalid;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool GetFormatFromFormatName(const char *format_name,
|
|
|
|
bool partial_match_ok, Format &format) {
|
|
|
|
uint32_t i;
|
|
|
|
for (i = 0; i < g_num_format_infos; ++i) {
|
|
|
|
if (strcasecmp(g_format_infos[i].format_name, format_name) == 0) {
|
|
|
|
format = g_format_infos[i].format;
|
|
|
|
return true;
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2011-06-24 05:22:24 +08:00
|
|
|
if (partial_match_ok) {
|
|
|
|
for (i = 0; i < g_num_format_infos; ++i) {
|
|
|
|
if (strcasestr(g_format_infos[i].format_name, format_name) ==
|
|
|
|
g_format_infos[i].format_name) {
|
|
|
|
format = g_format_infos[i].format;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2011-06-24 05:22:24 +08:00
|
|
|
format = eFormatInvalid;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-12-15 10:20:48 +08:00
|
|
|
void FormatManager::Changed() {
|
|
|
|
++m_last_revision;
|
|
|
|
m_format_cache.Clear();
|
2016-05-18 09:59:10 +08:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
|
2015-12-15 10:20:48 +08:00
|
|
|
for (auto &iter : m_language_categories_map) {
|
|
|
|
if (iter.second)
|
|
|
|
iter.second->GetFormatCache().Clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-24 05:22:24 +08:00
|
|
|
bool FormatManager::GetFormatFromCString(const char *format_cstr,
|
|
|
|
bool partial_match_ok,
|
|
|
|
lldb::Format &format) {
|
|
|
|
bool success = false;
|
|
|
|
if (format_cstr && format_cstr[0]) {
|
|
|
|
if (format_cstr[1] == '\0') {
|
|
|
|
success = GetFormatFromFormatChar(format_cstr[0], format);
|
|
|
|
if (success)
|
|
|
|
return true;
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2011-06-24 05:22:24 +08:00
|
|
|
success = GetFormatFromFormatName(format_cstr, partial_match_ok, format);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2011-06-24 05:22:24 +08:00
|
|
|
if (!success)
|
|
|
|
format = eFormatInvalid;
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
char FormatManager::GetFormatAsFormatChar(lldb::Format format) {
|
|
|
|
for (uint32_t i = 0; i < g_num_format_infos; ++i) {
|
|
|
|
if (g_format_infos[i].format == format)
|
|
|
|
return g_format_infos[i].format_char;
|
|
|
|
}
|
|
|
|
return '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *FormatManager::GetFormatAsCString(Format format) {
|
|
|
|
if (format >= eFormatDefault && format < kNumFormats)
|
|
|
|
return g_format_infos[format].format_name;
|
[lldb] NFC modernize codebase with modernize-use-nullptr
Summary:
NFC = [[ https://llvm.org/docs/Lexicon.html#nfc | Non functional change ]]
This commit is the result of modernizing the LLDB codebase by using
`nullptr` instread of `0` or `NULL`. See
https://clang.llvm.org/extra/clang-tidy/checks/modernize-use-nullptr.html
for more information.
This is the command I ran and I to fix and format the code base:
```
run-clang-tidy.py \
-header-filter='.*' \
-checks='-*,modernize-use-nullptr' \
-fix ~/dev/llvm-project/lldb/.* \
-format \
-style LLVM \
-p ~/llvm-builds/debug-ninja-gcc
```
NOTE: There were also changes to `llvm/utils/unittest` but I did not
include them because I felt that maybe this library shall be updated in
isolation somehow.
NOTE: I know this is a rather large commit but it is a nobrainer in most
parts.
Reviewers: martong, espindola, shafik, #lldb, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: arsenm, jvesely, nhaehnle, hiraditya, JDevlieghere, teemperor, rnkovacs, emaste, kubamracek, nemanjai, ki.stfu, javed.absar, arichardson, kbarton, jrtc27, MaskRay, atanasyan, dexonsmith, arphaman, jfb, jsji, jdoerfert, lldb-commits, llvm-commits
Tags: #lldb, #llvm
Differential Revision: https://reviews.llvm.org/D61847
llvm-svn: 361484
2019-05-23 19:14:47 +08:00
|
|
|
return nullptr;
|
2011-06-24 05:22:24 +08:00
|
|
|
}
|
2011-07-02 08:25:22 +08:00
|
|
|
|
2015-09-05 05:01:18 +08:00
|
|
|
void FormatManager::EnableAllCategories() {
|
|
|
|
m_categories_map.EnableAllCategories();
|
2016-05-18 09:59:10 +08:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
|
2015-09-05 05:01:18 +08:00
|
|
|
for (auto &iter : m_language_categories_map) {
|
|
|
|
if (iter.second)
|
|
|
|
iter.second->Enable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FormatManager::DisableAllCategories() {
|
|
|
|
m_categories_map.DisableAllCategories();
|
2016-05-18 09:59:10 +08:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
|
2015-09-05 05:01:18 +08:00
|
|
|
for (auto &iter : m_language_categories_map) {
|
|
|
|
if (iter.second)
|
|
|
|
iter.second->Disable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
void FormatManager::GetPossibleMatches(
|
2015-09-18 02:43:40 +08:00
|
|
|
ValueObject &valobj, CompilerType compiler_type, uint32_t reason,
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
lldb::DynamicValueType use_dynamic, FormattersMatchVector &entries,
|
|
|
|
bool did_strip_ptr, bool did_strip_ref, bool did_strip_typedef,
|
|
|
|
bool root_level) {
|
2015-09-23 09:39:46 +08:00
|
|
|
compiler_type = compiler_type.GetTypeForFormatters();
|
2015-09-18 02:43:40 +08:00
|
|
|
ConstString type_name(compiler_type.GetConstTypeName());
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
if (valobj.GetBitfieldBitSize() > 0) {
|
|
|
|
StreamString sstring;
|
|
|
|
sstring.Printf("%s:%d", type_name.AsCString(), valobj.GetBitfieldBitSize());
|
2016-11-17 05:15:24 +08:00
|
|
|
ConstString bitfieldname(sstring.GetString());
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
entries.push_back(
|
|
|
|
{bitfieldname, 0, did_strip_ptr, did_strip_ref, did_strip_typedef});
|
|
|
|
reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField;
|
|
|
|
}
|
Introduce the concept of a "display name" for types
Rationale:
Pretty simply, the idea is that sometimes type names are way too long and contain way too many details for the average developer to care about. For instance, a plain ol' vector of int might be shown as
std::__1::vector<int, std::__1::allocator<....
rather than the much simpler std::vector<int> form, which is what most developers would actually type in their code
Proposed solution:
Introduce a notion of "display name" and a corresponding API GetDisplayTypeName() to return such a crafted for visual representation type name
Obviously, the display name and the fully qualified (or "true") name are not necessarily the same - that's the whole point
LLDB could choose to pick the "display name" as its one true notion of a type name, and if somebody really needs the fully qualified version of it, let them deal with the problem
Or, LLDB could rename what it currently calls the "type name" to be the "display name", and add new APIs for the fully qualified name, making the display name the default choice
The choice that I am making here is that the type name will keep meaning the same, and people who want a type name suited for display will explicitly ask for one
It is the less risky/disruptive choice - and it should eventually make it fairly obvious when someone is asking for the wrong type
Caveats:
- for now, GetDisplayTypeName() == GetTypeName(), there is no logic to produce customized display type names yet.
- while the fully-qualified type name is still the main key to the kingdom of data formatters, if we start showing custom names to people, those should match formatters
llvm-svn: 209072
2014-05-18 03:14:17 +08:00
|
|
|
|
2019-08-06 08:42:11 +08:00
|
|
|
if (!compiler_type.IsMeaninglessWithoutDynamicResolution()) {
|
|
|
|
entries.push_back(
|
|
|
|
{type_name, reason, did_strip_ptr, did_strip_ref, did_strip_typedef});
|
2015-10-20 08:13:19 +08:00
|
|
|
|
2019-08-06 08:42:11 +08:00
|
|
|
ConstString display_type_name(compiler_type.GetDisplayTypeName());
|
|
|
|
if (display_type_name != type_name)
|
|
|
|
entries.push_back({display_type_name, reason, did_strip_ptr,
|
|
|
|
did_strip_ref, did_strip_typedef});
|
|
|
|
}
|
Introduce the concept of a "display name" for types
Rationale:
Pretty simply, the idea is that sometimes type names are way too long and contain way too many details for the average developer to care about. For instance, a plain ol' vector of int might be shown as
std::__1::vector<int, std::__1::allocator<....
rather than the much simpler std::vector<int> form, which is what most developers would actually type in their code
Proposed solution:
Introduce a notion of "display name" and a corresponding API GetDisplayTypeName() to return such a crafted for visual representation type name
Obviously, the display name and the fully qualified (or "true") name are not necessarily the same - that's the whole point
LLDB could choose to pick the "display name" as its one true notion of a type name, and if somebody really needs the fully qualified version of it, let them deal with the problem
Or, LLDB could rename what it currently calls the "type name" to be the "display name", and add new APIs for the fully qualified name, making the display name the default choice
The choice that I am making here is that the type name will keep meaning the same, and people who want a type name suited for display will explicitly ask for one
It is the less risky/disruptive choice - and it should eventually make it fairly obvious when someone is asking for the wrong type
Caveats:
- for now, GetDisplayTypeName() == GetTypeName(), there is no logic to produce customized display type names yet.
- while the fully-qualified type name is still the main key to the kingdom of data formatters, if we start showing custom names to people, those should match formatters
llvm-svn: 209072
2014-05-18 03:14:17 +08:00
|
|
|
|
2015-09-18 02:43:40 +08:00
|
|
|
for (bool is_rvalue_ref = true, j = true;
|
|
|
|
j && compiler_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false) {
|
|
|
|
CompilerType non_ref_type = compiler_type.GetNonReferenceType();
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
GetPossibleMatches(
|
|
|
|
valobj, non_ref_type,
|
|
|
|
reason |
|
2014-04-10 08:14:07 +08:00
|
|
|
lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
|
|
|
|
use_dynamic, entries, did_strip_ptr, true, did_strip_typedef);
|
2015-09-18 02:43:40 +08:00
|
|
|
if (non_ref_type.IsTypedefType()) {
|
|
|
|
CompilerType deffed_referenced_type = non_ref_type.GetTypedefedType();
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
deffed_referenced_type =
|
2014-04-10 08:14:07 +08:00
|
|
|
is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType()
|
2015-08-12 06:53:00 +08:00
|
|
|
: deffed_referenced_type.GetLValueReferenceType();
|
2014-04-10 08:14:07 +08:00
|
|
|
GetPossibleMatches(
|
|
|
|
valobj, deffed_referenced_type,
|
|
|
|
reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
|
|
|
|
use_dynamic, entries, did_strip_ptr, did_strip_ref,
|
|
|
|
true); // this is not exactly the usual meaning of stripping typedefs
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2015-09-09 09:10:46 +08:00
|
|
|
if (compiler_type.IsPointerType()) {
|
|
|
|
CompilerType non_ptr_type = compiler_type.GetPointeeType();
|
|
|
|
GetPossibleMatches(
|
|
|
|
valobj, non_ptr_type,
|
2016-09-07 04:57:50 +08:00
|
|
|
reason |
|
2015-09-09 09:10:46 +08:00
|
|
|
lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
|
|
|
|
use_dynamic, entries, true, did_strip_ref, did_strip_typedef);
|
|
|
|
if (non_ptr_type.IsTypedefType()) {
|
|
|
|
CompilerType deffed_pointed_type =
|
|
|
|
non_ptr_type.GetTypedefedType().GetPointerType();
|
|
|
|
GetPossibleMatches(
|
|
|
|
valobj, deffed_pointed_type,
|
|
|
|
reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
|
|
|
|
use_dynamic, entries, did_strip_ptr, did_strip_ref,
|
|
|
|
true); // this is not exactly the usual meaning of stripping typedefs
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2015-09-18 02:43:40 +08:00
|
|
|
for (lldb::LanguageType language_type : GetCandidateLanguages(valobj)) {
|
|
|
|
if (Language *language = Language::FindPlugin(language_type)) {
|
|
|
|
for (ConstString candidate :
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
language->GetPossibleFormattersMatches(valobj, use_dynamic)) {
|
2015-09-09 09:10:46 +08:00
|
|
|
entries.push_back(
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
{candidate,
|
|
|
|
reason | lldb_private::eFormatterChoiceCriterionLanguagePlugin,
|
|
|
|
did_strip_ptr, did_strip_ref, did_strip_typedef});
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
// try to strip typedef chains
|
2015-09-18 02:43:40 +08:00
|
|
|
if (compiler_type.IsTypedefType()) {
|
|
|
|
CompilerType deffed_type = compiler_type.GetTypedefedType();
|
|
|
|
GetPossibleMatches(
|
|
|
|
valobj, deffed_type,
|
|
|
|
reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
|
|
|
|
use_dynamic, entries, did_strip_ptr, did_strip_ref, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2015-09-18 02:43:40 +08:00
|
|
|
if (root_level) {
|
2016-09-07 04:57:50 +08:00
|
|
|
do {
|
2015-09-18 02:43:40 +08:00
|
|
|
if (!compiler_type.IsValid())
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
break;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-09-18 02:43:40 +08:00
|
|
|
CompilerType unqual_compiler_ast_type =
|
|
|
|
compiler_type.GetFullyUnqualifiedType();
|
|
|
|
if (!unqual_compiler_ast_type.IsValid())
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
2015-09-18 02:43:40 +08:00
|
|
|
if (unqual_compiler_ast_type.GetOpaqueQualType() !=
|
2015-09-23 10:04:34 +08:00
|
|
|
compiler_type.GetOpaqueQualType())
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
GetPossibleMatches(valobj, unqual_compiler_ast_type, reason,
|
|
|
|
use_dynamic, entries, did_strip_ptr, did_strip_ref,
|
|
|
|
did_strip_typedef);
|
|
|
|
} while (false);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
// if all else fails, go to static type
|
|
|
|
if (valobj.IsDynamic()) {
|
|
|
|
lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue());
|
|
|
|
if (static_value_sp)
|
|
|
|
GetPossibleMatches(
|
2015-08-25 07:46:31 +08:00
|
|
|
*static_value_sp.get(), static_value_sp->GetCompilerType(),
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
reason | lldb_private::eFormatterChoiceCriterionWentToStaticValue,
|
|
|
|
use_dynamic, entries, did_strip_ptr, did_strip_ref,
|
|
|
|
did_strip_typedef, true);
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
<rdar://problem/15530080>
Rework data formatters matching algorithm
What happens now is that, for each category, the FormatNavigator generates all possible matches, and checks them one by one
Since the possible matches do not actually depend on the category (whether a match is accepted or not does, but that check can be shifted at a more convenient time),
it is actually feasible to generate every possible match upfront and then let individual categories just scan through those
This commit changes things by introducing a notion of formatters match candidate, and shifting responsibility for generating all of them given a (ValueObject,DynamicValueType) pair
from the FormatNavigator back to the FormatManager
A list of these candidates is then passed down to each category for matching
Candidates also need to remember whether they were generated by stripping pointers, references, typedefs, since this is something that individual formatters can choose to reject
This check, however, is conveniently only done once a "textual" match has been found, so that the list of candidates is truly category-independent
While the performance benefit is small (mostly, due to caching), this is much cleaner from a design perspective
llvm-svn: 195395
2013-11-22 08:02:13 +08:00
|
|
|
}
|
|
|
|
|
2013-10-09 03:03:22 +08:00
|
|
|
lldb::TypeFormatImplSP
|
|
|
|
FormatManager::GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp) {
|
|
|
|
if (!type_sp)
|
|
|
|
return lldb::TypeFormatImplSP();
|
|
|
|
lldb::TypeFormatImplSP format_chosen_sp;
|
|
|
|
uint32_t num_categories = m_categories_map.GetCount();
|
|
|
|
lldb::TypeCategoryImplSP category_sp;
|
|
|
|
uint32_t prio_category = UINT32_MAX;
|
|
|
|
for (uint32_t category_id = 0; category_id < num_categories; category_id++) {
|
|
|
|
category_sp = GetCategoryAtIndex(category_id);
|
2018-12-15 08:15:33 +08:00
|
|
|
if (!category_sp->IsEnabled())
|
2013-10-09 03:03:22 +08:00
|
|
|
continue;
|
|
|
|
lldb::TypeFormatImplSP format_current_sp =
|
|
|
|
category_sp->GetFormatForType(type_sp);
|
|
|
|
if (format_current_sp &&
|
[lldb] NFC modernize codebase with modernize-use-nullptr
Summary:
NFC = [[ https://llvm.org/docs/Lexicon.html#nfc | Non functional change ]]
This commit is the result of modernizing the LLDB codebase by using
`nullptr` instread of `0` or `NULL`. See
https://clang.llvm.org/extra/clang-tidy/checks/modernize-use-nullptr.html
for more information.
This is the command I ran and I to fix and format the code base:
```
run-clang-tidy.py \
-header-filter='.*' \
-checks='-*,modernize-use-nullptr' \
-fix ~/dev/llvm-project/lldb/.* \
-format \
-style LLVM \
-p ~/llvm-builds/debug-ninja-gcc
```
NOTE: There were also changes to `llvm/utils/unittest` but I did not
include them because I felt that maybe this library shall be updated in
isolation somehow.
NOTE: I know this is a rather large commit but it is a nobrainer in most
parts.
Reviewers: martong, espindola, shafik, #lldb, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: arsenm, jvesely, nhaehnle, hiraditya, JDevlieghere, teemperor, rnkovacs, emaste, kubamracek, nemanjai, ki.stfu, javed.absar, arichardson, kbarton, jrtc27, MaskRay, atanasyan, dexonsmith, arphaman, jfb, jsji, jdoerfert, lldb-commits, llvm-commits
Tags: #lldb, #llvm
Differential Revision: https://reviews.llvm.org/D61847
llvm-svn: 361484
2019-05-23 19:14:47 +08:00
|
|
|
(format_chosen_sp.get() == nullptr ||
|
2013-10-09 03:03:22 +08:00
|
|
|
(prio_category > category_sp->GetEnabledPosition()))) {
|
|
|
|
prio_category = category_sp->GetEnabledPosition();
|
|
|
|
format_chosen_sp = format_current_sp;
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2013-10-09 03:03:22 +08:00
|
|
|
return format_chosen_sp;
|
|
|
|
}
|
|
|
|
|
2012-05-09 05:49:57 +08:00
|
|
|
lldb::TypeSummaryImplSP
|
|
|
|
FormatManager::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp) {
|
|
|
|
if (!type_sp)
|
|
|
|
return lldb::TypeSummaryImplSP();
|
|
|
|
lldb::TypeSummaryImplSP summary_chosen_sp;
|
|
|
|
uint32_t num_categories = m_categories_map.GetCount();
|
|
|
|
lldb::TypeCategoryImplSP category_sp;
|
|
|
|
uint32_t prio_category = UINT32_MAX;
|
|
|
|
for (uint32_t category_id = 0; category_id < num_categories; category_id++) {
|
|
|
|
category_sp = GetCategoryAtIndex(category_id);
|
2018-12-15 08:15:33 +08:00
|
|
|
if (!category_sp->IsEnabled())
|
2012-05-09 05:49:57 +08:00
|
|
|
continue;
|
|
|
|
lldb::TypeSummaryImplSP summary_current_sp =
|
|
|
|
category_sp->GetSummaryForType(type_sp);
|
|
|
|
if (summary_current_sp &&
|
[lldb] NFC modernize codebase with modernize-use-nullptr
Summary:
NFC = [[ https://llvm.org/docs/Lexicon.html#nfc | Non functional change ]]
This commit is the result of modernizing the LLDB codebase by using
`nullptr` instread of `0` or `NULL`. See
https://clang.llvm.org/extra/clang-tidy/checks/modernize-use-nullptr.html
for more information.
This is the command I ran and I to fix and format the code base:
```
run-clang-tidy.py \
-header-filter='.*' \
-checks='-*,modernize-use-nullptr' \
-fix ~/dev/llvm-project/lldb/.* \
-format \
-style LLVM \
-p ~/llvm-builds/debug-ninja-gcc
```
NOTE: There were also changes to `llvm/utils/unittest` but I did not
include them because I felt that maybe this library shall be updated in
isolation somehow.
NOTE: I know this is a rather large commit but it is a nobrainer in most
parts.
Reviewers: martong, espindola, shafik, #lldb, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: arsenm, jvesely, nhaehnle, hiraditya, JDevlieghere, teemperor, rnkovacs, emaste, kubamracek, nemanjai, ki.stfu, javed.absar, arichardson, kbarton, jrtc27, MaskRay, atanasyan, dexonsmith, arphaman, jfb, jsji, jdoerfert, lldb-commits, llvm-commits
Tags: #lldb, #llvm
Differential Revision: https://reviews.llvm.org/D61847
llvm-svn: 361484
2019-05-23 19:14:47 +08:00
|
|
|
(summary_chosen_sp.get() == nullptr ||
|
2012-05-09 05:49:57 +08:00
|
|
|
(prio_category > category_sp->GetEnabledPosition()))) {
|
|
|
|
prio_category = category_sp->GetEnabledPosition();
|
|
|
|
summary_chosen_sp = summary_current_sp;
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2012-05-09 05:49:57 +08:00
|
|
|
return summary_chosen_sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
lldb::TypeFilterImplSP
|
|
|
|
FormatManager::GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp) {
|
|
|
|
if (!type_sp)
|
|
|
|
return lldb::TypeFilterImplSP();
|
|
|
|
lldb::TypeFilterImplSP filter_chosen_sp;
|
|
|
|
uint32_t num_categories = m_categories_map.GetCount();
|
|
|
|
lldb::TypeCategoryImplSP category_sp;
|
|
|
|
uint32_t prio_category = UINT32_MAX;
|
|
|
|
for (uint32_t category_id = 0; category_id < num_categories; category_id++) {
|
|
|
|
category_sp = GetCategoryAtIndex(category_id);
|
2018-12-15 08:15:33 +08:00
|
|
|
if (!category_sp->IsEnabled())
|
2012-05-09 05:49:57 +08:00
|
|
|
continue;
|
|
|
|
lldb::TypeFilterImplSP filter_current_sp(
|
|
|
|
(TypeFilterImpl *)category_sp->GetFilterForType(type_sp).get());
|
|
|
|
if (filter_current_sp &&
|
[lldb] NFC modernize codebase with modernize-use-nullptr
Summary:
NFC = [[ https://llvm.org/docs/Lexicon.html#nfc | Non functional change ]]
This commit is the result of modernizing the LLDB codebase by using
`nullptr` instread of `0` or `NULL`. See
https://clang.llvm.org/extra/clang-tidy/checks/modernize-use-nullptr.html
for more information.
This is the command I ran and I to fix and format the code base:
```
run-clang-tidy.py \
-header-filter='.*' \
-checks='-*,modernize-use-nullptr' \
-fix ~/dev/llvm-project/lldb/.* \
-format \
-style LLVM \
-p ~/llvm-builds/debug-ninja-gcc
```
NOTE: There were also changes to `llvm/utils/unittest` but I did not
include them because I felt that maybe this library shall be updated in
isolation somehow.
NOTE: I know this is a rather large commit but it is a nobrainer in most
parts.
Reviewers: martong, espindola, shafik, #lldb, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: arsenm, jvesely, nhaehnle, hiraditya, JDevlieghere, teemperor, rnkovacs, emaste, kubamracek, nemanjai, ki.stfu, javed.absar, arichardson, kbarton, jrtc27, MaskRay, atanasyan, dexonsmith, arphaman, jfb, jsji, jdoerfert, lldb-commits, llvm-commits
Tags: #lldb, #llvm
Differential Revision: https://reviews.llvm.org/D61847
llvm-svn: 361484
2019-05-23 19:14:47 +08:00
|
|
|
(filter_chosen_sp.get() == nullptr ||
|
2012-05-09 05:49:57 +08:00
|
|
|
(prio_category > category_sp->GetEnabledPosition()))) {
|
|
|
|
prio_category = category_sp->GetEnabledPosition();
|
|
|
|
filter_chosen_sp = filter_current_sp;
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2012-05-09 05:49:57 +08:00
|
|
|
return filter_chosen_sp;
|
|
|
|
}
|
|
|
|
|
2013-01-29 07:47:25 +08:00
|
|
|
lldb::ScriptedSyntheticChildrenSP
|
2012-05-09 05:49:57 +08:00
|
|
|
FormatManager::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) {
|
|
|
|
if (!type_sp)
|
2013-01-29 07:47:25 +08:00
|
|
|
return lldb::ScriptedSyntheticChildrenSP();
|
|
|
|
lldb::ScriptedSyntheticChildrenSP synth_chosen_sp;
|
2012-05-09 05:49:57 +08:00
|
|
|
uint32_t num_categories = m_categories_map.GetCount();
|
|
|
|
lldb::TypeCategoryImplSP category_sp;
|
|
|
|
uint32_t prio_category = UINT32_MAX;
|
|
|
|
for (uint32_t category_id = 0; category_id < num_categories; category_id++) {
|
|
|
|
category_sp = GetCategoryAtIndex(category_id);
|
2018-12-15 08:15:33 +08:00
|
|
|
if (!category_sp->IsEnabled())
|
2012-05-09 05:49:57 +08:00
|
|
|
continue;
|
2013-01-29 07:47:25 +08:00
|
|
|
lldb::ScriptedSyntheticChildrenSP synth_current_sp(
|
|
|
|
(ScriptedSyntheticChildren *)category_sp->GetSyntheticForType(type_sp)
|
|
|
|
.get());
|
2012-05-09 05:49:57 +08:00
|
|
|
if (synth_current_sp &&
|
[lldb] NFC modernize codebase with modernize-use-nullptr
Summary:
NFC = [[ https://llvm.org/docs/Lexicon.html#nfc | Non functional change ]]
This commit is the result of modernizing the LLDB codebase by using
`nullptr` instread of `0` or `NULL`. See
https://clang.llvm.org/extra/clang-tidy/checks/modernize-use-nullptr.html
for more information.
This is the command I ran and I to fix and format the code base:
```
run-clang-tidy.py \
-header-filter='.*' \
-checks='-*,modernize-use-nullptr' \
-fix ~/dev/llvm-project/lldb/.* \
-format \
-style LLVM \
-p ~/llvm-builds/debug-ninja-gcc
```
NOTE: There were also changes to `llvm/utils/unittest` but I did not
include them because I felt that maybe this library shall be updated in
isolation somehow.
NOTE: I know this is a rather large commit but it is a nobrainer in most
parts.
Reviewers: martong, espindola, shafik, #lldb, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: arsenm, jvesely, nhaehnle, hiraditya, JDevlieghere, teemperor, rnkovacs, emaste, kubamracek, nemanjai, ki.stfu, javed.absar, arichardson, kbarton, jrtc27, MaskRay, atanasyan, dexonsmith, arphaman, jfb, jsji, jdoerfert, lldb-commits, llvm-commits
Tags: #lldb, #llvm
Differential Revision: https://reviews.llvm.org/D61847
llvm-svn: 361484
2019-05-23 19:14:47 +08:00
|
|
|
(synth_chosen_sp.get() == nullptr ||
|
2012-05-09 05:49:57 +08:00
|
|
|
(prio_category > category_sp->GetEnabledPosition()))) {
|
|
|
|
prio_category = category_sp->GetEnabledPosition();
|
|
|
|
synth_chosen_sp = synth_current_sp;
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2012-05-09 05:49:57 +08:00
|
|
|
return synth_chosen_sp;
|
|
|
|
}
|
|
|
|
|
2014-09-06 04:45:07 +08:00
|
|
|
lldb::TypeValidatorImplSP
|
|
|
|
FormatManager::GetValidatorForType(lldb::TypeNameSpecifierImplSP type_sp) {
|
|
|
|
if (!type_sp)
|
|
|
|
return lldb::TypeValidatorImplSP();
|
|
|
|
lldb::TypeValidatorImplSP validator_chosen_sp;
|
|
|
|
uint32_t num_categories = m_categories_map.GetCount();
|
|
|
|
lldb::TypeCategoryImplSP category_sp;
|
|
|
|
uint32_t prio_category = UINT32_MAX;
|
|
|
|
for (uint32_t category_id = 0; category_id < num_categories; category_id++) {
|
|
|
|
category_sp = GetCategoryAtIndex(category_id);
|
2018-12-15 08:15:33 +08:00
|
|
|
if (!category_sp->IsEnabled())
|
2014-09-06 04:45:07 +08:00
|
|
|
continue;
|
|
|
|
lldb::TypeValidatorImplSP validator_current_sp(
|
|
|
|
category_sp->GetValidatorForType(type_sp).get());
|
|
|
|
if (validator_current_sp &&
|
[lldb] NFC modernize codebase with modernize-use-nullptr
Summary:
NFC = [[ https://llvm.org/docs/Lexicon.html#nfc | Non functional change ]]
This commit is the result of modernizing the LLDB codebase by using
`nullptr` instread of `0` or `NULL`. See
https://clang.llvm.org/extra/clang-tidy/checks/modernize-use-nullptr.html
for more information.
This is the command I ran and I to fix and format the code base:
```
run-clang-tidy.py \
-header-filter='.*' \
-checks='-*,modernize-use-nullptr' \
-fix ~/dev/llvm-project/lldb/.* \
-format \
-style LLVM \
-p ~/llvm-builds/debug-ninja-gcc
```
NOTE: There were also changes to `llvm/utils/unittest` but I did not
include them because I felt that maybe this library shall be updated in
isolation somehow.
NOTE: I know this is a rather large commit but it is a nobrainer in most
parts.
Reviewers: martong, espindola, shafik, #lldb, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: arsenm, jvesely, nhaehnle, hiraditya, JDevlieghere, teemperor, rnkovacs, emaste, kubamracek, nemanjai, ki.stfu, javed.absar, arichardson, kbarton, jrtc27, MaskRay, atanasyan, dexonsmith, arphaman, jfb, jsji, jdoerfert, lldb-commits, llvm-commits
Tags: #lldb, #llvm
Differential Revision: https://reviews.llvm.org/D61847
llvm-svn: 361484
2019-05-23 19:14:47 +08:00
|
|
|
(validator_chosen_sp.get() == nullptr ||
|
2014-09-06 04:45:07 +08:00
|
|
|
(prio_category > category_sp->GetEnabledPosition()))) {
|
|
|
|
prio_category = category_sp->GetEnabledPosition();
|
|
|
|
validator_chosen_sp = validator_current_sp;
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-09-06 04:45:07 +08:00
|
|
|
return validator_chosen_sp;
|
|
|
|
}
|
|
|
|
|
2015-11-14 13:44:23 +08:00
|
|
|
void FormatManager::ForEachCategory(TypeCategoryMap::ForEachCallback callback) {
|
|
|
|
m_categories_map.ForEach(callback);
|
2016-05-18 09:59:10 +08:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
|
2015-11-14 13:44:23 +08:00
|
|
|
for (const auto &entry : m_language_categories_map) {
|
|
|
|
if (auto category_sp = entry.second->GetCategory()) {
|
|
|
|
if (!callback(category_sp))
|
|
|
|
break;
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2015-11-14 13:44:23 +08:00
|
|
|
}
|
|
|
|
|
2012-02-15 10:34:21 +08:00
|
|
|
lldb::TypeCategoryImplSP
|
2019-03-07 05:22:25 +08:00
|
|
|
FormatManager::GetCategory(ConstString category_name, bool can_create) {
|
2011-08-23 08:32:52 +08:00
|
|
|
if (!category_name)
|
Redesign of the interaction between Python and frozen objects:
- introduced two new classes ValueObjectConstResultChild and ValueObjectConstResultImpl: the first one is a ValueObjectChild obtained from
a ValueObjectConstResult, the second is a common implementation backend for VOCR and VOCRCh of method calls meant to read through pointers stored
in frozen objects ; now such reads transparently move from host to target as required
- as a consequence of the above, removed code that made target-memory copies of expression results in several places throughout LLDB, and also
removed code that enabled to recognize an expression result VO as such
- introduced a new GetPointeeData() method in ValueObject that lets you read a given amount of objects of type T from a VO
representing a T* or T[], and doing dereferences transparently
in private layer it returns a DataExtractor ; in public layer it returns an instance of a newly created lldb::SBData
- as GetPointeeData() does the right thing for both frozen and non-frozen ValueObject's, reimplemented ReadPointedString() to use it
en lieu of doing the raw read itself
- introduced a new GetData() method in ValueObject that lets you get a copy of the data that backs the ValueObject (for pointers,
this returns the address without any previous dereferencing steps ; for arrays it actually reads the whole chunk of memory)
in public layer this returns an SBData, just like GetPointeeData()
- introduced a new CreateValueFromData() method in SBValue that lets you create a new SBValue from a chunk of data wrapped in an SBData
the limitation to remember for this kind of SBValue is that they have no address: extracting the address-of for these objects (with any
of GetAddress(), GetLoadAddress() and AddressOf()) will return invalid values
- added several tests to check that "p"-ing objects (STL classes, char* and char[]) will do the right thing
Solved a bug where global pointers to global variables were not dereferenced correctly for display
New target setting "max-string-summary-length" gives the maximum number of characters to show in a string when summarizing it, instead of the hardcoded 128
Solved a bug where the summary for char[] and char* would not be shown if the ValueObject's were dumped via the "p" command
Removed m_pointers_point_to_load_addrs from ValueObject. Introduced a new m_address_type_of_children, which each ValueObject can set to tell the address type
of any pointers and/or references it creates. In the current codebase, this is load address most of the time (the only notable exception being file
addresses that generate file address children UNLESS we have a live process)
Updated help text for summary-string
Fixed an issue in STL formatters where std::stlcontainer::iterator would match the container's synthetic children providers
Edited the syntax and help for some commands to have proper argument types
llvm-svn: 139160
2011-09-07 03:20:51 +08:00
|
|
|
return GetCategory(m_default_category_name);
|
2012-02-15 10:34:21 +08:00
|
|
|
lldb::TypeCategoryImplSP category;
|
2011-08-23 08:32:52 +08:00
|
|
|
if (m_categories_map.Get(category_name, category))
|
|
|
|
return category;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2011-08-23 08:32:52 +08:00
|
|
|
if (!can_create)
|
2012-02-15 10:34:21 +08:00
|
|
|
return lldb::TypeCategoryImplSP();
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2012-02-15 10:34:21 +08:00
|
|
|
m_categories_map.Add(
|
|
|
|
category_name,
|
|
|
|
lldb::TypeCategoryImplSP(new TypeCategoryImpl(this, category_name)));
|
Redesign of the interaction between Python and frozen objects:
- introduced two new classes ValueObjectConstResultChild and ValueObjectConstResultImpl: the first one is a ValueObjectChild obtained from
a ValueObjectConstResult, the second is a common implementation backend for VOCR and VOCRCh of method calls meant to read through pointers stored
in frozen objects ; now such reads transparently move from host to target as required
- as a consequence of the above, removed code that made target-memory copies of expression results in several places throughout LLDB, and also
removed code that enabled to recognize an expression result VO as such
- introduced a new GetPointeeData() method in ValueObject that lets you read a given amount of objects of type T from a VO
representing a T* or T[], and doing dereferences transparently
in private layer it returns a DataExtractor ; in public layer it returns an instance of a newly created lldb::SBData
- as GetPointeeData() does the right thing for both frozen and non-frozen ValueObject's, reimplemented ReadPointedString() to use it
en lieu of doing the raw read itself
- introduced a new GetData() method in ValueObject that lets you get a copy of the data that backs the ValueObject (for pointers,
this returns the address without any previous dereferencing steps ; for arrays it actually reads the whole chunk of memory)
in public layer this returns an SBData, just like GetPointeeData()
- introduced a new CreateValueFromData() method in SBValue that lets you create a new SBValue from a chunk of data wrapped in an SBData
the limitation to remember for this kind of SBValue is that they have no address: extracting the address-of for these objects (with any
of GetAddress(), GetLoadAddress() and AddressOf()) will return invalid values
- added several tests to check that "p"-ing objects (STL classes, char* and char[]) will do the right thing
Solved a bug where global pointers to global variables were not dereferenced correctly for display
New target setting "max-string-summary-length" gives the maximum number of characters to show in a string when summarizing it, instead of the hardcoded 128
Solved a bug where the summary for char[] and char* would not be shown if the ValueObject's were dumped via the "p" command
Removed m_pointers_point_to_load_addrs from ValueObject. Introduced a new m_address_type_of_children, which each ValueObject can set to tell the address type
of any pointers and/or references it creates. In the current codebase, this is load address most of the time (the only notable exception being file
addresses that generate file address children UNLESS we have a live process)
Updated help text for summary-string
Fixed an issue in STL formatters where std::stlcontainer::iterator would match the container's synthetic children providers
Edited the syntax and help for some commands to have proper argument types
llvm-svn: 139160
2011-09-07 03:20:51 +08:00
|
|
|
return GetCategory(category_name);
|
2011-08-23 08:32:52 +08:00
|
|
|
}
|
|
|
|
|
2011-07-13 06:56:10 +08:00
|
|
|
lldb::Format FormatManager::GetSingleItemFormat(lldb::Format vector_format) {
|
|
|
|
switch (vector_format) {
|
|
|
|
case eFormatVectorOfChar:
|
|
|
|
return eFormatCharArray;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2011-07-13 06:56:10 +08:00
|
|
|
case eFormatVectorOfSInt8:
|
|
|
|
case eFormatVectorOfSInt16:
|
|
|
|
case eFormatVectorOfSInt32:
|
|
|
|
case eFormatVectorOfSInt64:
|
|
|
|
return eFormatDecimal;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2011-07-13 06:56:10 +08:00
|
|
|
case eFormatVectorOfUInt8:
|
|
|
|
case eFormatVectorOfUInt16:
|
|
|
|
case eFormatVectorOfUInt32:
|
|
|
|
case eFormatVectorOfUInt64:
|
|
|
|
case eFormatVectorOfUInt128:
|
|
|
|
return eFormatHex;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-10-16 16:28:47 +08:00
|
|
|
case eFormatVectorOfFloat16:
|
2011-07-13 06:56:10 +08:00
|
|
|
case eFormatVectorOfFloat32:
|
|
|
|
case eFormatVectorOfFloat64:
|
|
|
|
return eFormatFloat;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2011-07-13 06:56:10 +08:00
|
|
|
default:
|
|
|
|
return lldb::eFormatInvalid;
|
|
|
|
}
|
2011-08-10 10:10:13 +08:00
|
|
|
}
|
2011-08-18 06:13:59 +08:00
|
|
|
|
2013-10-05 07:14:13 +08:00
|
|
|
bool FormatManager::ShouldPrintAsOneLiner(ValueObject &valobj) {
|
2013-10-26 07:09:40 +08:00
|
|
|
// if settings say no oneline whatsoever
|
2013-11-01 05:01:07 +08:00
|
|
|
if (valobj.GetTargetSP().get() &&
|
2018-12-15 08:15:33 +08:00
|
|
|
!valobj.GetTargetSP()->GetDebugger().GetAutoOneLineSummaries())
|
2013-10-26 07:09:40 +08:00
|
|
|
return false; // then don't oneline
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-09-12 07:00:27 +08:00
|
|
|
// if this object has a summary, then ask the summary
|
2013-10-05 07:14:13 +08:00
|
|
|
if (valobj.GetSummaryFormat().get() != nullptr)
|
2014-09-12 07:00:27 +08:00
|
|
|
return valobj.GetSummaryFormat()->IsOneLiner();
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2013-10-05 07:14:13 +08:00
|
|
|
// no children, no party
|
|
|
|
if (valobj.GetNumChildren() == 0)
|
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2018-05-01 00:49:04 +08:00
|
|
|
// ask the type if it has any opinion about this eLazyBoolCalculate == no
|
|
|
|
// opinion; other values should be self explanatory
|
2013-10-05 07:14:13 +08:00
|
|
|
CompilerType compiler_type(valobj.GetCompilerType());
|
|
|
|
if (compiler_type.IsValid()) {
|
2015-11-10 05:28:55 +08:00
|
|
|
switch (compiler_type.ShouldPrintAsOneLiner(&valobj)) {
|
2015-09-23 10:04:34 +08:00
|
|
|
case eLazyBoolNo:
|
2013-10-05 07:14:13 +08:00
|
|
|
return false;
|
2015-09-23 10:04:34 +08:00
|
|
|
case eLazyBoolYes:
|
|
|
|
return true;
|
|
|
|
case eLazyBoolCalculate:
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-05 07:14:13 +08:00
|
|
|
size_t total_children_name_len = 0;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2013-10-05 07:14:13 +08:00
|
|
|
for (size_t idx = 0; idx < valobj.GetNumChildren(); idx++) {
|
2014-10-10 02:47:36 +08:00
|
|
|
bool is_synth_val = false;
|
2013-10-05 07:14:13 +08:00
|
|
|
ValueObjectSP child_sp(valobj.GetChildAtIndex(idx, true));
|
|
|
|
// something is wrong here - bail out
|
|
|
|
if (!child_sp)
|
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-11-10 05:28:55 +08:00
|
|
|
// also ask the child's type if it has any opinion
|
|
|
|
CompilerType child_compiler_type(child_sp->GetCompilerType());
|
|
|
|
if (child_compiler_type.IsValid()) {
|
|
|
|
switch (child_compiler_type.ShouldPrintAsOneLiner(child_sp.get())) {
|
2015-09-23 10:04:34 +08:00
|
|
|
case eLazyBoolYes:
|
2015-11-10 05:28:55 +08:00
|
|
|
// an opinion of yes is only binding for the child, so keep going
|
2015-09-23 10:04:34 +08:00
|
|
|
case eLazyBoolCalculate:
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
2015-09-23 10:04:34 +08:00
|
|
|
case eLazyBoolNo:
|
2015-11-10 05:28:55 +08:00
|
|
|
// but if the child says no, then it's a veto on the whole thing
|
2013-10-05 07:14:13 +08:00
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-05 07:14:13 +08:00
|
|
|
// if we decided to define synthetic children for a type, we probably care
|
2018-05-01 00:49:04 +08:00
|
|
|
// enough to show them, but avoid nesting children in children
|
2013-10-05 07:14:13 +08:00
|
|
|
if (child_sp->GetSyntheticChildren().get() != nullptr) {
|
2014-10-10 02:47:36 +08:00
|
|
|
ValueObjectSP synth_sp(child_sp->GetSyntheticValue());
|
|
|
|
// wait.. wat? just get out of here..
|
|
|
|
if (!synth_sp)
|
2013-10-05 07:14:13 +08:00
|
|
|
return false;
|
2014-10-10 02:47:36 +08:00
|
|
|
// but if we only have them to provide a value, keep going
|
2018-12-15 08:15:33 +08:00
|
|
|
if (!synth_sp->MightHaveChildren() &&
|
2014-10-10 02:47:36 +08:00
|
|
|
synth_sp->DoesProvideSyntheticValue())
|
|
|
|
is_synth_val = true;
|
2016-09-07 04:57:50 +08:00
|
|
|
else
|
2013-10-05 07:14:13 +08:00
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2013-10-05 07:14:13 +08:00
|
|
|
total_children_name_len += child_sp->GetName().GetLength();
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2013-10-05 07:14:13 +08:00
|
|
|
// 50 itself is a "randomly" chosen number - the idea is that
|
|
|
|
// overly long structs should not get this treatment
|
|
|
|
// FIXME: maybe make this a user-tweakable setting?
|
|
|
|
if (total_children_name_len > 50)
|
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2013-10-05 07:14:13 +08:00
|
|
|
// if a summary is there..
|
|
|
|
if (child_sp->GetSummaryFormat()) {
|
|
|
|
// and it wants children, then bail out
|
2014-04-24 07:16:25 +08:00
|
|
|
if (child_sp->GetSummaryFormat()->DoesPrintChildren(child_sp.get()))
|
2013-10-05 07:14:13 +08:00
|
|
|
return false;
|
2015-09-23 10:04:34 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-11-10 05:28:55 +08:00
|
|
|
// if this child has children..
|
|
|
|
if (child_sp->GetNumChildren()) {
|
|
|
|
// ...and no summary...
|
2013-10-05 07:14:13 +08:00
|
|
|
// (if it had a summary and the summary wanted children, we would have
|
|
|
|
// bailed out anyway
|
2014-10-10 02:47:36 +08:00
|
|
|
// so this only makes us bail out if this has no summary and we would
|
|
|
|
// then print children)
|
2013-10-05 07:14:13 +08:00
|
|
|
if (!child_sp->GetSummaryFormat() && !is_synth_val) // but again only do
|
|
|
|
// that if not a
|
2013-10-23 09:34:31 +08:00
|
|
|
// synthetic valued
|
|
|
|
// child
|
|
|
|
return false; // then bail out
|
2013-10-05 07:14:13 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2013-10-05 07:14:13 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-03-07 05:22:25 +08:00
|
|
|
ConstString FormatManager::GetValidTypeName(ConstString type) {
|
2011-08-19 09:14:49 +08:00
|
|
|
return ::GetValidTypeName_Impl(type);
|
|
|
|
}
|
|
|
|
|
2015-09-02 02:22:39 +08:00
|
|
|
ConstString FormatManager::GetTypeForCache(ValueObject &valobj,
|
|
|
|
lldb::DynamicValueType use_dynamic) {
|
2015-10-20 08:13:19 +08:00
|
|
|
ValueObjectSP valobj_sp = valobj.GetQualifiedRepresentationIfAvailable(
|
|
|
|
use_dynamic, valobj.IsSynthetic());
|
2019-08-06 08:42:11 +08:00
|
|
|
if (valobj_sp && valobj_sp->GetCompilerType().IsValid()) {
|
|
|
|
if (!valobj_sp->GetCompilerType().IsMeaninglessWithoutDynamicResolution())
|
|
|
|
return valobj_sp->GetQualifiedTypeName();
|
|
|
|
}
|
2013-01-29 07:47:25 +08:00
|
|
|
return ConstString();
|
|
|
|
}
|
|
|
|
|
2015-09-09 09:10:46 +08:00
|
|
|
std::vector<lldb::LanguageType>
|
|
|
|
FormatManager::GetCandidateLanguages(ValueObject &valobj) {
|
2015-09-02 02:22:39 +08:00
|
|
|
lldb::LanguageType lang_type = valobj.GetObjectRuntimeLanguage();
|
2015-09-10 06:30:24 +08:00
|
|
|
return GetCandidateLanguages(lang_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<lldb::LanguageType>
|
|
|
|
FormatManager::GetCandidateLanguages(lldb::LanguageType lang_type) {
|
2015-09-02 02:22:39 +08:00
|
|
|
switch (lang_type) {
|
2015-09-05 05:01:18 +08:00
|
|
|
case lldb::eLanguageTypeC:
|
|
|
|
case lldb::eLanguageTypeC89:
|
|
|
|
case lldb::eLanguageTypeC99:
|
|
|
|
case lldb::eLanguageTypeC11:
|
|
|
|
case lldb::eLanguageTypeC_plus_plus:
|
|
|
|
case lldb::eLanguageTypeC_plus_plus_03:
|
|
|
|
case lldb::eLanguageTypeC_plus_plus_11:
|
|
|
|
case lldb::eLanguageTypeC_plus_plus_14:
|
2015-09-15 06:18:32 +08:00
|
|
|
return {lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeObjC};
|
2015-09-02 02:22:39 +08:00
|
|
|
default:
|
|
|
|
return {lang_type};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LanguageCategory *
|
|
|
|
FormatManager::GetCategoryForLanguage(lldb::LanguageType lang_type) {
|
2016-05-18 09:59:10 +08:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
|
2015-09-02 02:22:39 +08:00
|
|
|
auto iter = m_language_categories_map.find(lang_type),
|
|
|
|
end = m_language_categories_map.end();
|
|
|
|
if (iter != end)
|
|
|
|
return iter->second.get();
|
|
|
|
LanguageCategory *lang_category = new LanguageCategory(lang_type);
|
|
|
|
m_language_categories_map[lang_type] =
|
|
|
|
LanguageCategory::UniquePointer(lang_category);
|
|
|
|
return lang_category;
|
|
|
|
}
|
|
|
|
|
2014-08-20 02:47:58 +08:00
|
|
|
lldb::TypeFormatImplSP
|
2015-10-06 09:02:47 +08:00
|
|
|
FormatManager::GetHardcodedFormat(FormattersMatchData &match_data) {
|
2015-09-17 02:28:11 +08:00
|
|
|
TypeFormatImplSP retval_sp;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-10-06 09:02:47 +08:00
|
|
|
for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
|
2015-09-17 02:28:11 +08:00
|
|
|
if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
|
2015-10-06 09:02:47 +08:00
|
|
|
if (lang_category->GetHardcoded(*this, match_data, retval_sp))
|
2015-09-17 02:28:11 +08:00
|
|
|
break;
|
2014-08-20 02:47:58 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2015-09-17 02:28:11 +08:00
|
|
|
|
|
|
|
return retval_sp;
|
2013-10-31 07:46:27 +08:00
|
|
|
}
|
|
|
|
|
2013-10-09 03:03:22 +08:00
|
|
|
lldb::TypeFormatImplSP
|
|
|
|
FormatManager::GetFormat(ValueObject &valobj,
|
|
|
|
lldb::DynamicValueType use_dynamic) {
|
2015-10-06 09:02:47 +08:00
|
|
|
FormattersMatchData match_data(valobj, use_dynamic);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2013-10-09 03:03:22 +08:00
|
|
|
TypeFormatImplSP retval;
|
2015-10-07 01:55:14 +08:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
|
2015-10-06 09:02:47 +08:00
|
|
|
if (match_data.GetTypeForCache()) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
"\n\n[FormatManager::GetFormat] Looking into cache for type %s",
|
|
|
|
match_data.GetTypeForCache().AsCString("<invalid>"));
|
2013-10-18 06:27:19 +08:00
|
|
|
if (m_format_cache.GetFormat(match_data.GetTypeForCache(), retval)) {
|
|
|
|
if (log) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(
|
|
|
|
log, "[FormatManager::GetFormat] Cache search success. Returning.");
|
2017-02-13 19:03:17 +08:00
|
|
|
LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
|
|
|
|
m_format_cache.GetCacheHits(),
|
|
|
|
m_format_cache.GetCacheMisses());
|
2015-09-02 02:22:39 +08:00
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(
|
|
|
|
log,
|
|
|
|
"[FormatManager::GetFormat] Cache search failed. Going normal route");
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2015-10-06 09:02:47 +08:00
|
|
|
retval = m_categories_map.GetFormat(match_data);
|
2013-10-31 07:46:27 +08:00
|
|
|
if (!retval) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
"[FormatManager::GetFormat] Search failed. Giving language a "
|
|
|
|
"chance.");
|
2015-10-06 09:02:47 +08:00
|
|
|
for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
|
|
|
|
if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
|
|
|
|
if (lang_category->Get(match_data, retval))
|
|
|
|
break;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2013-10-31 07:46:27 +08:00
|
|
|
}
|
2015-10-06 09:02:47 +08:00
|
|
|
if (retval) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(
|
|
|
|
log,
|
|
|
|
"[FormatManager::GetFormat] Language search success. Returning.");
|
2015-10-06 09:02:47 +08:00
|
|
|
return retval;
|
2013-10-18 06:27:19 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2015-09-02 02:22:39 +08:00
|
|
|
if (!retval) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "[FormatManager::GetFormat] Search failed. Giving hardcoded "
|
|
|
|
"a chance.");
|
2015-10-06 09:02:47 +08:00
|
|
|
retval = GetHardcodedFormat(match_data);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2015-10-06 09:02:47 +08:00
|
|
|
if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "[FormatManager::GetFormat] Caching %p for type %s",
|
|
|
|
static_cast<void *>(retval.get()),
|
|
|
|
match_data.GetTypeForCache().AsCString("<invalid>"));
|
2015-10-06 09:02:47 +08:00
|
|
|
m_format_cache.SetFormat(match_data.GetTypeForCache(), retval);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2017-02-13 19:03:17 +08:00
|
|
|
LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
|
|
|
|
m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
|
2013-10-09 03:03:22 +08:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2014-08-20 02:47:58 +08:00
|
|
|
lldb::TypeSummaryImplSP
|
2015-10-06 09:02:47 +08:00
|
|
|
FormatManager::GetHardcodedSummaryFormat(FormattersMatchData &match_data) {
|
2015-09-17 02:28:11 +08:00
|
|
|
TypeSummaryImplSP retval_sp;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-10-06 09:02:47 +08:00
|
|
|
for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
|
2015-09-17 02:28:11 +08:00
|
|
|
if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
|
2015-10-06 09:02:47 +08:00
|
|
|
if (lang_category->GetHardcoded(*this, match_data, retval_sp))
|
2015-09-17 02:28:11 +08:00
|
|
|
break;
|
2014-08-20 02:47:58 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2015-09-17 02:28:11 +08:00
|
|
|
return retval_sp;
|
2013-10-31 07:46:27 +08:00
|
|
|
}
|
|
|
|
|
2013-01-29 07:47:25 +08:00
|
|
|
lldb::TypeSummaryImplSP
|
|
|
|
FormatManager::GetSummaryFormat(ValueObject &valobj,
|
|
|
|
lldb::DynamicValueType use_dynamic) {
|
2015-10-06 09:02:47 +08:00
|
|
|
FormattersMatchData match_data(valobj, use_dynamic);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2013-01-29 07:47:25 +08:00
|
|
|
TypeSummaryImplSP retval;
|
2015-10-07 01:55:14 +08:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
|
2015-10-06 09:02:47 +08:00
|
|
|
if (match_data.GetTypeForCache()) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
"\n\n[FormatManager::GetSummaryFormat] Looking into cache "
|
|
|
|
"for type %s",
|
|
|
|
match_data.GetTypeForCache().AsCString("<invalid>"));
|
2013-08-08 03:05:15 +08:00
|
|
|
if (m_format_cache.GetSummary(match_data.GetTypeForCache(), retval)) {
|
2013-01-29 07:47:25 +08:00
|
|
|
if (log) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
"[FormatManager::GetSummaryFormat] Cache search success. "
|
|
|
|
"Returning.");
|
2017-02-13 19:03:17 +08:00
|
|
|
LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
|
|
|
|
m_format_cache.GetCacheHits(),
|
|
|
|
m_format_cache.GetCacheMisses());
|
2015-09-02 02:22:39 +08:00
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "[FormatManager::GetSummaryFormat] Cache search failed. "
|
|
|
|
"Going normal route");
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2015-10-06 09:02:47 +08:00
|
|
|
retval = m_categories_map.GetSummaryFormat(match_data);
|
2013-10-31 07:46:27 +08:00
|
|
|
if (!retval) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "[FormatManager::GetSummaryFormat] Search failed. Giving "
|
|
|
|
"language a chance.");
|
2015-10-06 09:02:47 +08:00
|
|
|
for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
|
|
|
|
if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
|
|
|
|
if (lang_category->Get(match_data, retval))
|
|
|
|
break;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2013-10-31 07:46:27 +08:00
|
|
|
}
|
2015-10-06 09:02:47 +08:00
|
|
|
if (retval) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "[FormatManager::GetSummaryFormat] Language search "
|
|
|
|
"success. Returning.");
|
2015-10-06 09:02:47 +08:00
|
|
|
return retval;
|
2013-01-29 07:47:25 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2015-09-02 02:22:39 +08:00
|
|
|
if (!retval) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "[FormatManager::GetSummaryFormat] Search failed. Giving "
|
|
|
|
"hardcoded a chance.");
|
2015-10-06 09:02:47 +08:00
|
|
|
retval = GetHardcodedSummaryFormat(match_data);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2013-06-26 09:03:38 +08:00
|
|
|
if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "[FormatManager::GetSummaryFormat] Caching %p for type %s",
|
|
|
|
static_cast<void *>(retval.get()),
|
|
|
|
match_data.GetTypeForCache().AsCString("<invalid>"));
|
2013-08-08 03:05:15 +08:00
|
|
|
m_format_cache.SetSummary(match_data.GetTypeForCache(), retval);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2017-02-13 19:03:17 +08:00
|
|
|
LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
|
|
|
|
m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
|
2013-01-29 07:47:25 +08:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2014-08-20 02:47:58 +08:00
|
|
|
lldb::SyntheticChildrenSP
|
2015-10-06 09:02:47 +08:00
|
|
|
FormatManager::GetHardcodedSyntheticChildren(FormattersMatchData &match_data) {
|
2015-09-17 02:28:11 +08:00
|
|
|
SyntheticChildrenSP retval_sp;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-10-06 09:02:47 +08:00
|
|
|
for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
|
2015-09-17 02:28:11 +08:00
|
|
|
if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
|
2015-10-06 09:02:47 +08:00
|
|
|
if (lang_category->GetHardcoded(*this, match_data, retval_sp))
|
2015-09-17 02:28:11 +08:00
|
|
|
break;
|
2014-08-20 02:47:58 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2015-09-17 02:28:11 +08:00
|
|
|
return retval_sp;
|
2013-10-31 07:46:27 +08:00
|
|
|
}
|
|
|
|
|
2013-01-29 07:47:25 +08:00
|
|
|
lldb::SyntheticChildrenSP
|
|
|
|
FormatManager::GetSyntheticChildren(ValueObject &valobj,
|
2013-06-26 09:03:38 +08:00
|
|
|
lldb::DynamicValueType use_dynamic) {
|
2015-10-06 09:02:47 +08:00
|
|
|
FormattersMatchData match_data(valobj, use_dynamic);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2013-01-29 07:47:25 +08:00
|
|
|
SyntheticChildrenSP retval;
|
2015-10-07 01:55:14 +08:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
|
2015-10-06 09:02:47 +08:00
|
|
|
if (match_data.GetTypeForCache()) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
"\n\n[FormatManager::GetSyntheticChildren] Looking into "
|
|
|
|
"cache for type %s",
|
|
|
|
match_data.GetTypeForCache().AsCString("<invalid>"));
|
2013-08-08 03:05:15 +08:00
|
|
|
if (m_format_cache.GetSynthetic(match_data.GetTypeForCache(), retval)) {
|
2013-01-29 07:47:25 +08:00
|
|
|
if (log) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "[FormatManager::GetSyntheticChildren] Cache search "
|
|
|
|
"success. Returning.");
|
2017-02-13 19:03:17 +08:00
|
|
|
LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
|
|
|
|
m_format_cache.GetCacheHits(),
|
|
|
|
m_format_cache.GetCacheMisses());
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2015-09-02 02:22:39 +08:00
|
|
|
return retval;
|
|
|
|
}
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "[FormatManager::GetSyntheticChildren] Cache search failed. "
|
|
|
|
"Going normal route");
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2015-10-06 09:02:47 +08:00
|
|
|
retval = m_categories_map.GetSyntheticChildren(match_data);
|
2013-10-31 07:46:27 +08:00
|
|
|
if (!retval) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
"[FormatManager::GetSyntheticChildren] Search failed. Giving "
|
|
|
|
"language a chance.");
|
2015-10-06 09:02:47 +08:00
|
|
|
for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
|
|
|
|
if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
|
|
|
|
if (lang_category->Get(match_data, retval))
|
|
|
|
break;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2013-10-31 07:46:27 +08:00
|
|
|
}
|
2015-10-06 09:02:47 +08:00
|
|
|
if (retval) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "[FormatManager::GetSyntheticChildren] Language search "
|
|
|
|
"success. Returning.");
|
2015-10-06 09:02:47 +08:00
|
|
|
return retval;
|
2013-01-29 07:47:25 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2015-09-02 02:22:39 +08:00
|
|
|
if (!retval) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
"[FormatManager::GetSyntheticChildren] Search failed. Giving "
|
|
|
|
"hardcoded a chance.");
|
2015-10-06 09:02:47 +08:00
|
|
|
retval = GetHardcodedSyntheticChildren(match_data);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2013-06-26 09:03:38 +08:00
|
|
|
if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
"[FormatManager::GetSyntheticChildren] Caching %p for type %s",
|
|
|
|
static_cast<void *>(retval.get()),
|
|
|
|
match_data.GetTypeForCache().AsCString("<invalid>"));
|
2013-08-08 03:05:15 +08:00
|
|
|
m_format_cache.SetSynthetic(match_data.GetTypeForCache(), retval);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2017-02-13 19:03:17 +08:00
|
|
|
LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
|
|
|
|
m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
|
2013-01-29 07:47:25 +08:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2014-09-06 04:45:07 +08:00
|
|
|
lldb::TypeValidatorImplSP
|
|
|
|
FormatManager::GetValidator(ValueObject &valobj,
|
|
|
|
lldb::DynamicValueType use_dynamic) {
|
2015-10-06 09:02:47 +08:00
|
|
|
FormattersMatchData match_data(valobj, use_dynamic);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-09-06 04:45:07 +08:00
|
|
|
TypeValidatorImplSP retval;
|
2015-10-07 01:55:14 +08:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
|
2015-10-06 09:02:47 +08:00
|
|
|
if (match_data.GetTypeForCache()) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(
|
|
|
|
log, "\n\n[FormatManager::GetValidator] Looking into cache for type %s",
|
|
|
|
match_data.GetTypeForCache().AsCString("<invalid>"));
|
2014-09-06 04:45:07 +08:00
|
|
|
if (m_format_cache.GetValidator(match_data.GetTypeForCache(), retval)) {
|
|
|
|
if (log) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(
|
|
|
|
log,
|
2014-09-06 04:45:07 +08:00
|
|
|
"[FormatManager::GetValidator] Cache search success. Returning.");
|
2017-02-13 19:03:17 +08:00
|
|
|
LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
|
|
|
|
m_format_cache.GetCacheHits(),
|
|
|
|
m_format_cache.GetCacheMisses());
|
2015-09-02 02:22:39 +08:00
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "[FormatManager::GetValidator] Cache search failed. Going "
|
|
|
|
"normal route");
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2015-10-06 09:02:47 +08:00
|
|
|
retval = m_categories_map.GetValidator(match_data);
|
2014-09-06 04:45:07 +08:00
|
|
|
if (!retval) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "[FormatManager::GetValidator] Search failed. Giving "
|
|
|
|
"language a chance.");
|
2015-10-06 09:02:47 +08:00
|
|
|
for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
|
|
|
|
if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
|
|
|
|
if (lang_category->Get(match_data, retval))
|
|
|
|
break;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-09-06 04:45:07 +08:00
|
|
|
}
|
2015-10-06 09:02:47 +08:00
|
|
|
if (retval) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "[FormatManager::GetValidator] Language search success. "
|
|
|
|
"Returning.");
|
2015-10-06 09:02:47 +08:00
|
|
|
return retval;
|
2014-09-06 04:45:07 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2015-09-02 02:22:39 +08:00
|
|
|
if (!retval) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "[FormatManager::GetValidator] Search failed. Giving "
|
|
|
|
"hardcoded a chance.");
|
2015-10-06 09:02:47 +08:00
|
|
|
retval = GetHardcodedValidator(match_data);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2015-10-06 09:02:47 +08:00
|
|
|
if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "[FormatManager::GetValidator] Caching %p for type %s",
|
|
|
|
static_cast<void *>(retval.get()),
|
|
|
|
match_data.GetTypeForCache().AsCString("<invalid>"));
|
2015-10-06 09:02:47 +08:00
|
|
|
m_format_cache.SetValidator(match_data.GetTypeForCache(), retval);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2017-02-13 19:03:17 +08:00
|
|
|
LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
|
|
|
|
m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
|
2014-09-06 04:45:07 +08:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
lldb::TypeValidatorImplSP
|
2015-10-06 09:02:47 +08:00
|
|
|
FormatManager::GetHardcodedValidator(FormattersMatchData &match_data) {
|
2015-09-17 02:28:11 +08:00
|
|
|
TypeValidatorImplSP retval_sp;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-10-06 09:02:47 +08:00
|
|
|
for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
|
2015-09-17 02:28:11 +08:00
|
|
|
if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
|
2015-10-06 09:02:47 +08:00
|
|
|
if (lang_category->GetHardcoded(*this, match_data, retval_sp))
|
2015-09-17 02:28:11 +08:00
|
|
|
break;
|
2014-09-06 04:45:07 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2015-09-17 02:28:11 +08:00
|
|
|
return retval_sp;
|
2014-09-06 04:45:07 +08:00
|
|
|
}
|
|
|
|
|
2016-05-18 09:59:10 +08:00
|
|
|
FormatManager::FormatManager()
|
|
|
|
: m_last_revision(0), m_format_cache(), m_language_categories_mutex(),
|
|
|
|
m_language_categories_map(), m_named_summaries_map(this),
|
|
|
|
m_categories_map(this), m_default_category_name(ConstString("default")),
|
|
|
|
m_system_category_name(ConstString("system")),
|
|
|
|
m_vectortypes_category_name(ConstString("VectorTypes")) {
|
2012-02-17 11:18:30 +08:00
|
|
|
LoadSystemFormatters();
|
2015-09-15 06:18:32 +08:00
|
|
|
LoadVectorFormatters();
|
2016-05-18 09:59:10 +08:00
|
|
|
|
|
|
|
EnableCategory(m_vectortypes_category_name, TypeCategoryMap::Last,
|
|
|
|
lldb::eLanguageTypeObjC_plus_plus);
|
|
|
|
EnableCategory(m_system_category_name, TypeCategoryMap::Last,
|
|
|
|
lldb::eLanguageTypeObjC_plus_plus);
|
2012-02-17 11:18:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void FormatManager::LoadSystemFormatters() {
|
2013-01-11 06:08:35 +08:00
|
|
|
TypeSummaryImpl::Flags string_flags;
|
2013-02-22 08:37:31 +08:00
|
|
|
string_flags.SetCascades(true)
|
2013-01-11 06:08:35 +08:00
|
|
|
.SetSkipPointers(true)
|
|
|
|
.SetSkipReferences(false)
|
|
|
|
.SetDontShowChildren(true)
|
|
|
|
.SetDontShowValue(false)
|
|
|
|
.SetShowMembersOneLiner(false)
|
|
|
|
.SetHideItemNames(false);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-06-16 07:01:47 +08:00
|
|
|
TypeSummaryImpl::Flags string_array_flags;
|
2015-07-28 10:13:03 +08:00
|
|
|
string_array_flags.SetCascades(true)
|
2015-06-16 07:01:47 +08:00
|
|
|
.SetSkipPointers(true)
|
|
|
|
.SetSkipReferences(false)
|
|
|
|
.SetDontShowChildren(true)
|
|
|
|
.SetDontShowValue(true)
|
|
|
|
.SetShowMembersOneLiner(false)
|
|
|
|
.SetHideItemNames(false);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2013-01-11 06:08:35 +08:00
|
|
|
lldb::TypeSummaryImplSP string_format(
|
|
|
|
new StringSummaryFormat(string_flags, "${var%s}"));
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-06-16 07:01:47 +08:00
|
|
|
lldb::TypeSummaryImplSP string_array_format(
|
|
|
|
new StringSummaryFormat(string_array_flags, "${var%s}"));
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2019-09-04 17:47:18 +08:00
|
|
|
RegularExpression any_size_char_arr(llvm::StringRef("char \\[[0-9]+\\]"));
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2012-02-17 11:18:30 +08:00
|
|
|
TypeCategoryImpl::SharedPointer sys_category_sp =
|
|
|
|
GetCategory(m_system_category_name);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2013-12-20 17:38:13 +08:00
|
|
|
sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("char *"),
|
|
|
|
string_format);
|
|
|
|
sys_category_sp->GetTypeSummariesContainer()->Add(
|
|
|
|
ConstString("unsigned char *"), string_format);
|
2019-09-04 17:47:18 +08:00
|
|
|
sys_category_sp->GetRegexTypeSummariesContainer()->Add(
|
|
|
|
std::move(any_size_char_arr), string_array_format);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2012-07-14 02:54:40 +08:00
|
|
|
lldb::TypeSummaryImplSP ostype_summary(
|
|
|
|
new StringSummaryFormat(TypeSummaryImpl::Flags()
|
|
|
|
.SetCascades(false)
|
|
|
|
.SetSkipPointers(true)
|
|
|
|
.SetSkipReferences(true)
|
|
|
|
.SetDontShowChildren(true)
|
|
|
|
.SetDontShowValue(false)
|
|
|
|
.SetShowMembersOneLiner(false)
|
|
|
|
.SetHideItemNames(false),
|
|
|
|
"${var%O}"));
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2013-12-20 17:38:13 +08:00
|
|
|
sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("OSType"),
|
|
|
|
ostype_summary);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2013-10-09 04:59:02 +08:00
|
|
|
TypeFormatImpl::Flags fourchar_flags;
|
|
|
|
fourchar_flags.SetCascades(true).SetSkipPointers(true).SetSkipReferences(
|
|
|
|
true);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2013-10-09 04:59:02 +08:00
|
|
|
AddFormat(sys_category_sp, lldb::eFormatOSType, ConstString("FourCharCode"),
|
|
|
|
fourchar_flags);
|
2012-02-24 07:10:03 +08:00
|
|
|
}
|
2012-09-14 02:27:09 +08:00
|
|
|
|
2015-09-15 06:18:32 +08:00
|
|
|
void FormatManager::LoadVectorFormatters() {
|
2012-02-17 11:18:30 +08:00
|
|
|
TypeCategoryImpl::SharedPointer vectors_category_sp =
|
|
|
|
GetCategory(m_vectortypes_category_name);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2012-02-17 11:18:30 +08:00
|
|
|
TypeSummaryImpl::Flags vector_flags;
|
|
|
|
vector_flags.SetCascades(true)
|
|
|
|
.SetSkipPointers(true)
|
|
|
|
.SetSkipReferences(false)
|
|
|
|
.SetDontShowChildren(true)
|
|
|
|
.SetDontShowValue(false)
|
|
|
|
.SetShowMembersOneLiner(true)
|
|
|
|
.SetHideItemNames(true);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2012-12-11 07:30:25 +08:00
|
|
|
AddStringSummary(vectors_category_sp, "${var.uint128}",
|
|
|
|
ConstString("builtin_type_vec128"), vector_flags);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2012-12-11 07:30:25 +08:00
|
|
|
AddStringSummary(vectors_category_sp, "", ConstString("float [4]"),
|
|
|
|
vector_flags);
|
|
|
|
AddStringSummary(vectors_category_sp, "", ConstString("int32_t [4]"),
|
|
|
|
vector_flags);
|
|
|
|
AddStringSummary(vectors_category_sp, "", ConstString("int16_t [8]"),
|
|
|
|
vector_flags);
|
|
|
|
AddStringSummary(vectors_category_sp, "", ConstString("vDouble"),
|
|
|
|
vector_flags);
|
|
|
|
AddStringSummary(vectors_category_sp, "", ConstString("vFloat"),
|
2015-09-15 06:18:32 +08:00
|
|
|
vector_flags);
|
2012-12-11 07:30:25 +08:00
|
|
|
AddStringSummary(vectors_category_sp, "", ConstString("vSInt8"),
|
|
|
|
vector_flags);
|
|
|
|
AddStringSummary(vectors_category_sp, "", ConstString("vSInt16"),
|
|
|
|
vector_flags);
|
|
|
|
AddStringSummary(vectors_category_sp, "", ConstString("vSInt32"),
|
|
|
|
vector_flags);
|
|
|
|
AddStringSummary(vectors_category_sp, "", ConstString("vUInt16"),
|
|
|
|
vector_flags);
|
|
|
|
AddStringSummary(vectors_category_sp, "", ConstString("vUInt8"),
|
|
|
|
vector_flags);
|
|
|
|
AddStringSummary(vectors_category_sp, "", ConstString("vUInt16"),
|
2015-09-15 06:18:32 +08:00
|
|
|
vector_flags);
|
2012-12-11 07:30:25 +08:00
|
|
|
AddStringSummary(vectors_category_sp, "", ConstString("vUInt32"),
|
|
|
|
vector_flags);
|
|
|
|
AddStringSummary(vectors_category_sp, "", ConstString("vBool32"),
|
|
|
|
vector_flags);
|
2011-10-12 08:53:29 +08:00
|
|
|
}
|