11from __future__ import annotations
2- from typing import Dict
2+ from typing import List
3+
34
45import lldb
56
67from lldb_providers import *
7- from rust_types import RustType , classify_struct , classify_union
8+ from rust_types import (
9+ ENUM_DISR_FIELD_NAME ,
10+ ENUM_LLDB_ENCODED_VARIANTS ,
11+ RustType ,
12+ classify_union ,
13+ is_tuple_fields ,
14+ )
15+
16+ ####################################################################################################
17+ # This file contains lookup functions that associate rust types with their synthetic/summary
18+ # providers.
19+ #
20+ # LLDB caches the results of the the commands in `lldb_commands`, but that caching is "shallow". It
21+ # purely associates the type with the function given, whether it is a regular function or a class
22+ # constructor. If the function makes decisions about what type of SyntheticProvider to return, that
23+ # processing is done **each time a value of that type is encountered**.
24+ #
25+ # To reiterate, inspecting a `vec![T; 100_000]` will call `T`'s lookup function/constructor 100,000
26+ # times. This can lead to significant delays in value visualization if the lookup logic is complex.
27+ #
28+ # As such, lookup functions should be kept as minimal as possible. LLDB technically expects a
29+ # SyntheticProvider class constructor. If you can provide just a class constructor, that should be
30+ # preferred. If extra processing must be done, try to keep it as minimal and as targeted as possible
31+ # (see: `classify_hashmap()` vs `classify_hashset()`).
32+ ####################################################################################################
833
934
1035# BACKCOMPAT: rust 1.35
1136def is_hashbrown_hashmap (hash_map : lldb .SBValue ) -> bool :
1237 return len (hash_map .type .fields ) == 1
1338
1439
15- def classify_rust_type (type : lldb .SBType ) -> RustType :
16- if type .IsPointerType ():
17- type = type .GetPointeeType ()
18-
19- type_class = type .GetTypeClass ()
20- if type_class == lldb .eTypeClassStruct :
21- return classify_struct (type .name , type .fields )
22- if type_class == lldb .eTypeClassUnion :
23- return classify_union (type .fields )
40+ def classify_hashmap (valobj : lldb .SBValue , _dict : LLDBOpaque ) -> object :
41+ if is_hashbrown_hashmap (valobj ):
42+ return StdHashMapSyntheticProvider (valobj , _dict )
43+ else :
44+ return StdOldHashMapSyntheticProvider (valobj , _dict )
2445
25- return RustType .Other
2646
47+ def classify_hashset (valobj : lldb .SBValue , _dict : LLDBOpaque ) -> object :
48+ hash_map = valobj .GetChildAtIndex (0 )
49+ if is_hashbrown_hashmap (hash_map ):
50+ return StdHashMapSyntheticProvider (valobj , _dict , show_values = False )
51+ else :
52+ return StdOldHashMapSyntheticProvider (hash_map , _dict , show_values = False )
2753
28- def summary_lookup (valobj : lldb .SBValue , _dict : LLDBOpaque ) -> str :
29- """Returns the summary provider for the given value"""
30- rust_type = classify_rust_type (valobj .GetType ())
3154
32- if rust_type == RustType .StdString :
33- return StdStringSummaryProvider (valobj , _dict )
34- if rust_type == RustType .StdOsString :
35- return StdOsStringSummaryProvider (valobj , _dict )
36- if rust_type == RustType .StdStr :
37- return StdStrSummaryProvider (valobj , _dict )
55+ def arc_synthetic (valobj : lldb .SBValue , _dict : LLDBOpaque ) -> object :
56+ return StdRcSyntheticProvider (valobj , _dict , is_atomic = True )
3857
39- if rust_type == RustType .StdVec :
40- return SizeSummaryProvider (valobj , _dict )
41- if rust_type == RustType .StdVecDeque :
42- return SizeSummaryProvider (valobj , _dict )
43- if rust_type == RustType .StdSlice :
44- return SizeSummaryProvider (valobj , _dict )
4558
46- if rust_type == RustType .StdHashMap :
47- return SizeSummaryProvider (valobj , _dict )
48- if rust_type == RustType .StdHashSet :
49- return SizeSummaryProvider (valobj , _dict )
59+ def classify_rust_type (type : lldb .SBType , is_msvc : bool ) -> RustType :
60+ if type .IsPointerType ():
61+ return RustType .Indirection
5062
51- if rust_type == RustType .StdRc :
52- return StdRcSummaryProvider (valobj , _dict )
53- if rust_type == RustType .StdArc :
54- return StdRcSummaryProvider (valobj , _dict )
63+ # there is a bit of code duplication here because we don't want to check all of the standard
64+ # library regexes since LLDB handles that for us
65+ type_class = type .GetTypeClass ()
66+ if type_class == lldb .eTypeClassStruct :
67+ fields : List [lldb .SBTypeMember ] = type .fields
68+ if len (fields ) == 0 :
69+ return RustType .Empty
5570
56- if rust_type == RustType . StdRef :
57- return StdRefSummaryProvider ( valobj , _dict )
58- if rust_type == RustType . StdRefMut :
59- return StdRefSummaryProvider ( valobj , _dict )
60- if rust_type == RustType . StdRefCell :
61- return StdRefSummaryProvider ( valobj , _dict )
71+ # <<variant>> is emitted by GDB while LLDB(18.1+) emits "$variants$"
72+ if (
73+ fields [ 0 ]. name == ENUM_DISR_FIELD_NAME
74+ or fields [ 0 ]. name == ENUM_LLDB_ENCODED_VARIANTS
75+ ) :
76+ return RustType . Enum
6277
63- if rust_type == RustType . StdNonZeroNumber :
64- return StdNonZeroNumberSummaryProvider ( valobj , _dict )
78+ if is_tuple_fields ( fields ) :
79+ return RustType . Tuple
6580
66- if rust_type == RustType .StdPathBuf :
67- return StdPathBufSummaryProvider (valobj , _dict )
68- if rust_type == RustType .StdPath :
69- return StdPathSummaryProvider (valobj , _dict )
81+ return RustType .Struct
82+ if type_class == lldb .eTypeClassUnion :
83+ # If we're debugging msvc, sum-type enums should have been caught by the regex in lldb
84+ # commands since they all start with "enum2$<"
85+ if is_msvc :
86+ return RustType .Union
87+ return classify_union (type .fields )
7088
71- return ""
89+ return RustType . Other
7290
7391
7492def synthetic_lookup (valobj : lldb .SBValue , _dict : LLDBOpaque ) -> object :
7593 """Returns the synthetic provider for the given value"""
76- rust_type = classify_rust_type (valobj .GetType ())
94+ is_msvc = valobj .GetTarget ().GetTriple ().endswith ("msvc" )
95+ rust_type = classify_rust_type (valobj .GetType (), is_msvc )
7796
78- if rust_type == RustType .Struct :
97+ if rust_type == RustType .Struct or rust_type == RustType . Union :
7998 return StructSyntheticProvider (valobj , _dict )
8099 if rust_type == RustType .StructVariant :
81100 return StructSyntheticProvider (valobj , _dict , is_variant = True )
@@ -92,37 +111,7 @@ def synthetic_lookup(valobj: lldb.SBValue, _dict: LLDBOpaque) -> object:
92111 return synthetic_lookup (valobj .GetChildAtIndex (0 ), _dict )
93112 if rust_type == RustType .Enum :
94113 return ClangEncodedEnumProvider (valobj , _dict )
95- if rust_type == RustType .StdVec :
96- return StdVecSyntheticProvider (valobj , _dict )
97- if rust_type == RustType .StdVecDeque :
98- return StdVecDequeSyntheticProvider (valobj , _dict )
99- if rust_type == RustType .StdSlice or rust_type == RustType .StdStr :
100- return StdSliceSyntheticProvider (valobj , _dict )
101-
102- if rust_type == RustType .StdHashMap :
103- if is_hashbrown_hashmap (valobj ):
104- return StdHashMapSyntheticProvider (valobj , _dict )
105- else :
106- return StdOldHashMapSyntheticProvider (valobj , _dict )
107- if rust_type == RustType .StdHashSet :
108- hash_map = valobj .GetChildAtIndex (0 )
109- if is_hashbrown_hashmap (hash_map ):
110- return StdHashMapSyntheticProvider (valobj , _dict , show_values = False )
111- else :
112- return StdOldHashMapSyntheticProvider (hash_map , _dict , show_values = False )
113-
114- if rust_type == RustType .StdRc :
115- return StdRcSyntheticProvider (valobj , _dict )
116- if rust_type == RustType .StdArc :
117- return StdRcSyntheticProvider (valobj , _dict , is_atomic = True )
118-
119- if rust_type == RustType .StdCell :
120- return StdCellSyntheticProvider (valobj , _dict )
121- if rust_type == RustType .StdRef :
122- return StdRefSyntheticProvider (valobj , _dict )
123- if rust_type == RustType .StdRefMut :
124- return StdRefSyntheticProvider (valobj , _dict )
125- if rust_type == RustType .StdRefCell :
126- return StdRefSyntheticProvider (valobj , _dict , is_cell = True )
114+ if rust_type == RustType .Indirection :
115+ return IndirectionSyntheticProvider (valobj , _dict )
127116
128117 return DefaultSyntheticProvider (valobj , _dict )
0 commit comments