1"""
2LLDB Formatters for LLVM data types.
3
4Load into LLDB with 'command script import /path/to/lldbDataFormatters.py'
5"""
6
7def __lldb_init_module(debugger, internal_dict):
8    debugger.HandleCommand('type category define -e llvm -l c++')
9    debugger.HandleCommand('type synthetic add -w llvm '
10                           '-l lldbDataFormatters.SmallVectorSynthProvider '
11                           '-x "^llvm::SmallVectorImpl<.+>$"')
12    debugger.HandleCommand('type synthetic add -w llvm '
13                           '-l lldbDataFormatters.SmallVectorSynthProvider '
14                           '-x "^llvm::SmallVector<.+,.+>$"')
15    debugger.HandleCommand('type synthetic add -w llvm '
16                           '-l lldbDataFormatters.ArrayRefSynthProvider '
17                           '-x "^llvm::ArrayRef<.+>$"')
18
19# Pretty printer for llvm::SmallVector/llvm::SmallVectorImpl
20class SmallVectorSynthProvider:
21    def __init__(self, valobj, dict):
22        self.valobj = valobj;
23        self.update() # initialize this provider
24
25    def num_children(self):
26        begin = self.begin.GetValueAsUnsigned(0)
27        end = self.end.GetValueAsUnsigned(0)
28        return (end - begin)/self.type_size
29
30    def get_child_index(self, name):
31        try:
32            return int(name.lstrip('[').rstrip(']'))
33        except:
34            return -1;
35
36    def get_child_at_index(self, index):
37        # Do bounds checking.
38        if index < 0:
39            return None
40        if index >= self.num_children():
41            return None;
42
43        offset = index * self.type_size
44        return self.begin.CreateChildAtOffset('['+str(index)+']',
45                                              offset, self.data_type)
46
47    def update(self):
48        self.begin = self.valobj.GetChildMemberWithName('BeginX')
49        self.end = self.valobj.GetChildMemberWithName('EndX')
50        the_type = self.valobj.GetType()
51        # If this is a reference type we have to dereference it to get to the
52        # template parameter.
53        if the_type.IsReferenceType():
54            the_type = the_type.GetDereferencedType()
55
56        self.data_type = the_type.GetTemplateArgumentType(0)
57        self.type_size = self.data_type.GetByteSize()
58        assert self.type_size != 0
59
60class ArrayRefSynthProvider:
61    """ Provider for llvm::ArrayRef """
62    def __init__(self, valobj, dict):
63        self.valobj = valobj;
64        self.update() # initialize this provider
65
66    def num_children(self):
67        return self.length
68
69    def get_child_index(self, name):
70        try:
71            return int(name.lstrip('[').rstrip(']'))
72        except:
73            return -1;
74
75    def get_child_at_index(self, index):
76        if index < 0 or index >= self.num_children():
77            return None;
78        offset = index * self.type_size
79        return self.data.CreateChildAtOffset('[' + str(index) + ']',
80                                             offset, self.data_type)
81
82    def update(self):
83        self.data = self.valobj.GetChildMemberWithName('Data')
84        length_obj = self.valobj.GetChildMemberWithName('Length')
85        self.length = length_obj.GetValueAsUnsigned(0)
86        self.data_type = self.data.GetType().GetPointeeType()
87        self.type_size = self.data_type.GetByteSize()
88        assert self.type_size != 0
89