xref: /llvm-project/lldb/examples/synthetic/bitfield/example.py (revision fd35a92300a00edaf56ae94176317390677569a4)
1# Synthetic children provider example for class MaskedData
2# to use me:
3# command script import ./example.py --allow-reload
4# type synthetic add MaskedData --python-class
5# example.MaskedData_SyntheticChildrenProvider
6
7
8class MaskedData_SyntheticChildrenProvider:
9    def __init__(self, valobj, dict):
10        # remember the SBValue since you will not have another chance to get it
11        # :-)
12        self.valobj = valobj
13
14    def num_children(self):
15        # you could perform calculations involving the SBValue and/or its children to determine this value
16        # here, we have an hardcoded value - but since you have stored the SBValue you could use it to
17        # help figure out the correct thing to return here. if you return a number N, you should be prepared to
18        # answer questions about N children
19        return 4
20
21    def has_children(self):
22        # we simply say True here because we know we have 4 children
23        # in general, you want to make this calculation as simple as possible
24        # and return True if in doubt (you can always return num_children == 0
25        # later)
26        return True
27
28    def get_child_index(self, name):
29        # given a name, return its index
30        # you can return None if you don't know the answer for a given name
31        if name == "value":
32            return 0
33        # here, we are using a reserved C++ keyword as a child name - we could not do that in the source code
34        # but we are free to use the names we like best in the synthetic children provider class
35        # we are also not respecting the order of declaration in the C++ class itself - as long as
36        # we are consistent, we can do that freely
37        if name == "operator":
38            return 1
39        if name == "mask":
40            return 2
41        # this member does not exist in the original class - we will compute its value and show it to the user
42        # when returning synthetic children, there is no need to only stick to
43        # what already exists in memory
44        if name == "apply()":
45            return 3
46        return None  # no clue, just say none
47
48    def get_child_at_index(self, index):
49        # precautionary measures
50        if index < 0:
51            return None
52        if index > self.num_children():
53            return None
54        if not self.valobj.IsValid():
55            return None
56        if index == 0:
57            return self.valobj.GetChildMemberWithName("value")
58        if index == 1:
59            # fetch the value of the operator
60            op_chosen = self.valobj.GetChildMemberWithName("oper").GetValueAsUnsigned()
61            # if it is a known value, return a descriptive string for it
62            # we are not doing this in the most efficient possible way, but the code is very readable
63            # and easy to maintain - if you change the values on the C++ side,
64            # the same changes must be made here
65            if op_chosen == 0:
66                return self.valobj.CreateValueFromExpression(
67                    "operator", '(const char*)"none"'
68                )
69            elif op_chosen == 1:
70                return self.valobj.CreateValueFromExpression(
71                    "operator", '(const char*)"AND"'
72                )
73            elif op_chosen == 2:
74                return self.valobj.CreateValueFromExpression(
75                    "operator", '(const char*)"OR"'
76                )
77            elif op_chosen == 3:
78                return self.valobj.CreateValueFromExpression(
79                    "operator", '(const char*)"XOR"'
80                )
81            elif op_chosen == 4:
82                return self.valobj.CreateValueFromExpression(
83                    "operator", '(const char*)"NAND"'
84                )
85            elif op_chosen == 5:
86                return self.valobj.CreateValueFromExpression(
87                    "operator", '(const char*)"NOR"'
88                )
89            else:
90                return self.valobj.CreateValueFromExpression(
91                    "operator", '(const char*)"unknown"'
92                )  # something else
93        if index == 2:
94            return self.valobj.GetChildMemberWithName("mask")
95        if index == 3:
96            # for this, we must fetch all the other elements
97            # in an efficient implementation, we would be caching this data for
98            # efficiency
99            value = self.valobj.GetChildMemberWithName("value").GetValueAsUnsigned()
100            operator = self.valobj.GetChildMemberWithName("oper").GetValueAsUnsigned()
101            mask = self.valobj.GetChildMemberWithName("mask").GetValueAsUnsigned()
102            # compute the masked value according to the operator
103            if operator == 1:
104                value = value & mask
105            elif operator == 2:
106                value = value | mask
107            elif operator == 3:
108                value = value ^ mask
109            elif operator == 4:
110                value = ~(value & mask)
111            elif operator == 5:
112                value = ~(value | mask)
113            else:
114                pass
115            value &= (
116                0xFFFFFFFF  # make sure Python does not extend our values to 64-bits
117            )
118            # return it - again, not the most efficient possible way. we should actually be pushing the computed value
119            # into an SBData, and using the SBData to create an SBValue - this
120            # has the advantage of readability
121            return self.valobj.CreateValueFromExpression(
122                "apply()", "(uint32_t)(" + str(value) + ")"
123            )
124
125    def update(self):
126        # we do not do anything special in update - but this would be the right place to lookup
127        # the data we use in get_child_at_index and cache it
128        pass
129