xref: /openbsd-src/gnu/llvm/lldb/examples/synthetic/unordered_multi.py (revision 061da546b983eb767bad15e67af1174fb0bcf31c)
1*061da546Spatrickimport lldb
2*061da546Spatrick
3*061da546Spatrick_map_capping_size = 255
4*061da546Spatrick
5*061da546Spatrick
6*061da546Spatrickclass libcxx_hash_table_SynthProvider:
7*061da546Spatrick
8*061da546Spatrick    def __init__(self, valobj, dict):
9*061da546Spatrick        self.valobj = valobj
10*061da546Spatrick        self.num_elements = None
11*061da546Spatrick        self.next_element = None
12*061da546Spatrick        self.bucket_count = None
13*061da546Spatrick
14*061da546Spatrick    def update(self):
15*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
16*061da546Spatrick        self.num_elements = None
17*061da546Spatrick        self.next_element = None
18*061da546Spatrick        self.bucket_count = None
19*061da546Spatrick        try:
20*061da546Spatrick            # unordered_map is made up of a hash_map, which has 4 pieces in it:
21*061da546Spatrick            #   bucket list :
22*061da546Spatrick            #      array of buckets
23*061da546Spatrick            #   p1 (pair):
24*061da546Spatrick            #      first - pointer to first loaded element
25*061da546Spatrick            #   p2 (pair):
26*061da546Spatrick            #      first - number of elements
27*061da546Spatrick            #      second - hash function
28*061da546Spatrick            #   p3 (pair):
29*061da546Spatrick            #      first - max_load_factor
30*061da546Spatrick            #      second - equality operator function
31*061da546Spatrick            #
32*061da546Spatrick            # For display, we actually don't need to go inside the buckets, since 'p1' has a way to iterate over all
33*061da546Spatrick            # the elements directly.
34*061da546Spatrick            #
35*061da546Spatrick            # We will calculate other values about the map because they will be useful for the summary.
36*061da546Spatrick            #
37*061da546Spatrick            table = self.valobj.GetChildMemberWithName('__table_')
38*061da546Spatrick
39*061da546Spatrick            bl_ptr = table.GetChildMemberWithName(
40*061da546Spatrick                '__bucket_list_').GetChildMemberWithName('__ptr_')
41*061da546Spatrick            self.bucket_array_ptr = bl_ptr.GetChildMemberWithName(
42*061da546Spatrick                '__first_').GetValueAsUnsigned(0)
43*061da546Spatrick            self.bucket_count = bl_ptr.GetChildMemberWithName('__second_').GetChildMemberWithName(
44*061da546Spatrick                '__data_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
45*061da546Spatrick            logger >> "Bucket count = %r" % self.bucket_count
46*061da546Spatrick
47*061da546Spatrick            self.begin_ptr = table.GetChildMemberWithName('__p1_').GetChildMemberWithName(
48*061da546Spatrick                '__first_').GetChildMemberWithName('__next_')
49*061da546Spatrick
50*061da546Spatrick            self.num_elements = table.GetChildMemberWithName(
51*061da546Spatrick                '__p2_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
52*061da546Spatrick            self.max_load_factor = table.GetChildMemberWithName(
53*061da546Spatrick                '__p3_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
54*061da546Spatrick            logger >> "Num elements = %r" % self.num_elements
55*061da546Spatrick
56*061da546Spatrick            # save the pointers as we get them
57*061da546Spatrick            #   -- don't access this first element if num_element==0!
58*061da546Spatrick            self.elements_cache = []
59*061da546Spatrick            if self.num_elements:
60*061da546Spatrick                self.next_element = self.begin_ptr
61*061da546Spatrick            else:
62*061da546Spatrick                self.next_element = None
63*061da546Spatrick        except Exception as e:
64*061da546Spatrick            logger >> "Caught exception: %r" % e
65*061da546Spatrick            pass
66*061da546Spatrick
67*061da546Spatrick    def num_children(self):
68*061da546Spatrick        global _map_capping_size
69*061da546Spatrick        num_elements = self.num_elements
70*061da546Spatrick        if num_elements is not None:
71*061da546Spatrick            if num_elements > _map_capping_size:
72*061da546Spatrick                num_elements = _map_capping_size
73*061da546Spatrick        return num_elements
74*061da546Spatrick
75*061da546Spatrick    def has_children(self):
76*061da546Spatrick        return True
77*061da546Spatrick
78*061da546Spatrick    def get_child_index(self, name):
79*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
80*061da546Spatrick        try:
81*061da546Spatrick            return int(name.lstrip('[').rstrip(']'))
82*061da546Spatrick        except:
83*061da546Spatrick            return -1
84*061da546Spatrick
85*061da546Spatrick    def get_child_at_index(self, index):
86*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
87*061da546Spatrick        logger >> "Retrieving child " + str(index)
88*061da546Spatrick        if index < 0:
89*061da546Spatrick            return None
90*061da546Spatrick        if index >= self.num_children():
91*061da546Spatrick            return None
92*061da546Spatrick
93*061da546Spatrick        # extend
94*061da546Spatrick        logger >> " : cache size starts with %d elements" % len(
95*061da546Spatrick            self.elements_cache)
96*061da546Spatrick        while index >= len(self.elements_cache):
97*061da546Spatrick            # if we hit the end before we get the index, give up:
98*061da546Spatrick            if not self.next_element:
99*061da546Spatrick                logger >> " : hit end of list"
100*061da546Spatrick                return None
101*061da546Spatrick
102*061da546Spatrick            node = self.next_element.Dereference()
103*061da546Spatrick
104*061da546Spatrick            value = node.GetChildMemberWithName('__value_')
105*061da546Spatrick            hash_value = node.GetChildMemberWithName(
106*061da546Spatrick                '__hash_').GetValueAsUnsigned()
107*061da546Spatrick            self.elements_cache.append((value, hash_value))
108*061da546Spatrick
109*061da546Spatrick            self.next_element = node.GetChildMemberWithName('__next_')
110*061da546Spatrick            if not self.next_element.GetValueAsUnsigned(0):
111*061da546Spatrick                self.next_element = None
112*061da546Spatrick
113*061da546Spatrick        # hit the index! so we have the value
114*061da546Spatrick        logger >> " : cache size ends with %d elements" % len(
115*061da546Spatrick            self.elements_cache)
116*061da546Spatrick        value, hash_value = self.elements_cache[index]
117*061da546Spatrick        return self.valobj.CreateValueFromData(
118*061da546Spatrick            '[%d] <hash %d>' %
119*061da546Spatrick            (index, hash_value), value.GetData(), value.GetType())
120*061da546Spatrick
121*061da546Spatrick
122*061da546Spatrickdef __lldb_init_module(debugger, dict):
123*061da546Spatrick    debugger.HandleCommand(
124*061da546Spatrick        'type synthetic add -l unordered_multi.libcxx_hash_table_SynthProvider -x "^(std::__1::)unordered_(multi)?(map|set)<.+> >$" -w libcxx')
125