From ab8674f99f155285e2c8e8c95c1ede4be42ecfe2 Mon Sep 17 00:00:00 2001 From: Enrico Granata Date: Sat, 17 Mar 2012 02:02:03 +0000 Subject: [PATCH] Adding a new example of synthetic children provider llvm-svn: 152970 --- lldb/examples/synthetic/bitfield/example.py | 94 ++++++++++++++++++++ lldb/examples/synthetic/bitfield/program.cpp | 74 +++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 lldb/examples/synthetic/bitfield/example.py create mode 100644 lldb/examples/synthetic/bitfield/program.cpp diff --git a/lldb/examples/synthetic/bitfield/example.py b/lldb/examples/synthetic/bitfield/example.py new file mode 100644 index 000000000000..f32d40715661 --- /dev/null +++ b/lldb/examples/synthetic/bitfield/example.py @@ -0,0 +1,94 @@ +# Synthetic children provider example for class MaskedData +# to use me: +# command script import ./example.py --allow-reload +# type synthetic add MaskedData --python-class example.MaskedData_SyntheticChildrenProvider +class MaskedData_SyntheticChildrenProvider: + def __init__(self, valobj, dict): + self.valobj = valobj # remember the SBValue since you will not have another chance to get it :-) + + def num_children(self): + # you could perform calculations involving the SBValue and/or its children to determine this value + # here, we have an hardcoded value - but since you have stored the SBValue you could use it to + # help figure out the correct thing to return here. if you return a number N, you should be prepared to + # answer questions about N children + return 4 + + def get_child_index(self,name): + # given a name, return its index + # you can return None if you don't know the answer for a given name + if name == "value": + return 0 + # here, we are using a reserved C++ keyword as a child name - we could not do that in the source code + # but we are free to use the names we like best in the synthetic children provider class + # we are also not respecting the order of declaration in the C++ class itself - as long as + # we are consistent, we can do that freely + if name == "operator": + return 1 + if name == "mask": + return 2 + # this member does not exist in the original class - we will compute its value and show it to the user + # when returning synthetic children, there is no need to only stick to what already exists in memory + if name == "apply()": + return 3 + return None # no clue, just say none + + def get_child_at_index(self,index): + # precautionary measures + if index < 0: + return None + if index > self.num_children(): + return None + if self.valobj.IsValid() == False: + return None + if index == 0: + return self.valobj.GetChildMemberWithName("value") + if index == 1: + # fetch the value of the operator + op_chosen = self.valobj.GetChildMemberWithName("oper").GetValueAsUnsigned() + # if it is a known value, return a descriptive string for it + # we are not doing this in the most efficient possible way, but the code is very readable + # and easy to maintain - if you change the values on the C++ side, the same changes must be made here + if op_chosen == 0: + return self.valobj.CreateValueFromExpression("operator",'(const char*)"none"') + elif op_chosen == 1: + return self.valobj.CreateValueFromExpression("operator",'(const char*)"AND"') + elif op_chosen == 2: + return self.valobj.CreateValueFromExpression("operator",'(const char*)"OR"') + elif op_chosen == 3: + return self.valobj.CreateValueFromExpression("operator",'(const char*)"XOR"') + elif op_chosen == 4: + return self.valobj.CreateValueFromExpression("operator",'(const char*)"NAND"') + elif op_chosen == 5: + return self.valobj.CreateValueFromExpression("operator",'(const char*)"NOR"') + else: + return self.valobj.CreateValueFromExpression("operator",'(const char*)"unknown"') # something else + if index == 2: + return self.valobj.GetChildMemberWithName("mask") + if index == 3: + # for this, we must fetch all the other elements + # in an efficient implementation, we would be caching this data for efficiency + value = self.valobj.GetChildMemberWithName("value").GetValueAsUnsigned() + operator = self.valobj.GetChildMemberWithName("oper").GetValueAsUnsigned() + mask = self.valobj.GetChildMemberWithName("mask").GetValueAsUnsigned() + # compute the masked value according to the operator + if operator == 1: + value = value & mask + elif operator == 2: + value = value | mask + elif operator == 3: + value = value ^ mask + elif operator == 4: + value = ~(value & mask) + elif operator == 5: + value = ~(value | mask) + else: + pass + value &= 0xFFFFFFFF # make sure Python does not extend our values to 64-bits + # return it - again, not the most efficient possible way. we should actually be pushing the computed value + # into an SBData, and using the SBData to create an SBValue - this has the advantage of readability + return self.valobj.CreateValueFromExpression("apply()",'(uint32_t)(' + str(value) + ')') + + def update(self): + # we do not do anything special in update - but this would be the right place to lookup + # the data we use in get_child_at_index and cache it + pass diff --git a/lldb/examples/synthetic/bitfield/program.cpp b/lldb/examples/synthetic/bitfield/program.cpp new file mode 100644 index 000000000000..5276824a2fb4 --- /dev/null +++ b/lldb/examples/synthetic/bitfield/program.cpp @@ -0,0 +1,74 @@ +typedef unsigned int uint32_t; + +enum MaskingOperator +{ + eMaskingOperatorDefault = 0, + eMaskingOperatorAnd = 1, + eMaskingOperatorOr = 2, + eMaskingOperatorXor = 3, + eMaskingOperatorNand = 4, + eMaskingOperatorNor = 5 +}; + +class MaskedData +{ +private: + uint32_t value; + uint32_t mask; + MaskingOperator oper; +public: + MaskedData( uint32_t V = 0, + uint32_t M = 0, + MaskingOperator P = eMaskingOperatorDefault) : + value(V), + mask(M), + oper(P) + { + } + + uint32_t apply() + { + switch(oper) + { + case eMaskingOperatorAnd: + return value & mask; + case eMaskingOperatorOr: + return value | mask; + case eMaskingOperatorXor: + return value ^ mask; + case eMaskingOperatorNand: + return ~(value & mask); + case eMaskingOperatorNor: + return ~(value | mask); + case eMaskingOperatorDefault: // fall through + default: + return value; + } + } + + void setValue(uint32_t V) + { + value = V; + } + + void setMask (uint32_t M) + { + mask = M; + } + + void setOperator(MaskingOperator P) + { + oper = P; + } +}; + +int main() +{ + MaskedData data_1(0xFF0F,0xA01F,eMaskingOperatorAnd); + MaskedData data_2(data_1.apply(),0x1AFC,eMaskingOperatorXor); + MaskedData data_3(data_2.apply(),0xFFCF,eMaskingOperatorOr); + MaskedData data_4(data_3.apply(),0xAABC,eMaskingOperatorAnd); + MaskedData data_5(data_4.apply(),0xFFAC,eMaskingOperatorNor); + MaskedData data_6(data_5.apply(),0x0000BEEF,eMaskingOperatorAnd); + return data_6.apply(); // <-- what comes out of here? +} \ No newline at end of file