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