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