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