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    debugger.HandleCommand('type summary add -w llvm '
19                           '-F lldbDataFormatters.OptionalSummaryProvider '
20                           '-x "^llvm::Optional<.+>$"')
21
22# Pretty printer for llvm::SmallVector/llvm::SmallVectorImpl
23class SmallVectorSynthProvider:
24    def __init__(self, valobj, dict):
25        self.valobj = valobj;
26        self.update() # initialize this provider
27
28    def num_children(self):
29        return self.size.GetValueAsUnsigned(0)
30
31    def get_child_index(self, name):
32        try:
33            return int(name.lstrip('[').rstrip(']'))
34        except:
35            return -1;
36
37    def get_child_at_index(self, index):
38        # Do bounds checking.
39        if index < 0:
40            return None
41        if index >= self.num_children():
42            return None;
43
44        offset = index * self.type_size
45        return self.begin.CreateChildAtOffset('['+str(index)+']',
46                                              offset, self.data_type)
47
48    def update(self):
49        self.begin = self.valobj.GetChildMemberWithName('BeginX')
50        self.size = self.valobj.GetChildMemberWithName('Size')
51        the_type = self.valobj.GetType()
52        # If this is a reference type we have to dereference it to get to the
53        # template parameter.
54        if the_type.IsReferenceType():
55            the_type = the_type.GetDereferencedType()
56
57        self.data_type = the_type.GetTemplateArgumentType(0)
58        self.type_size = self.data_type.GetByteSize()
59        assert self.type_size != 0
60
61class ArrayRefSynthProvider:
62    """ Provider for llvm::ArrayRef """
63    def __init__(self, valobj, dict):
64        self.valobj = valobj;
65        self.update() # initialize this provider
66
67    def num_children(self):
68        return self.length
69
70    def get_child_index(self, name):
71        try:
72            return int(name.lstrip('[').rstrip(']'))
73        except:
74            return -1;
75
76    def get_child_at_index(self, index):
77        if index < 0 or index >= self.num_children():
78            return None;
79        offset = index * self.type_size
80        return self.data.CreateChildAtOffset('[' + str(index) + ']',
81                                             offset, self.data_type)
82
83    def update(self):
84        self.data = self.valobj.GetChildMemberWithName('Data')
85        length_obj = self.valobj.GetChildMemberWithName('Length')
86        self.length = length_obj.GetValueAsUnsigned(0)
87        self.data_type = self.data.GetType().GetPointeeType()
88        self.type_size = self.data_type.GetByteSize()
89        assert self.type_size != 0
90
91def OptionalSummaryProvider(valobj, internal_dict):
92    storage = valobj.GetChildMemberWithName('Storage')
93    if not storage:
94        storage = valobj
95
96    failure = 2
97    hasVal = storage.GetChildMemberWithName('hasVal').GetValueAsUnsigned(failure)
98    if hasVal == failure:
99        return '<could not read llvm::Optional>'
100
101    if hasVal == 0:
102        return 'None'
103
104    underlying_type = storage.GetType().GetTemplateArgumentType(0)
105    storage = storage.GetChildMemberWithName('storage')
106    return str(storage.Cast(underlying_type))
107