168 lines · python
1"""2This is the llvm::Optional data formatter from llvm/utils/lldbDataFormatters.py3with the implementation replaced by bytecode.4"""5 6from __future__ import annotations7from formatter_bytecode import *8import lldb9 10 11def __lldb_init_module(debugger, internal_dict):12 debugger.HandleCommand(13 "type synthetic add -w llvm "14 f"-l {__name__}.MyOptionalSynthProvider "15 '-x "^MyOptional<.+>$"'16 )17 debugger.HandleCommand(18 "type summary add -w llvm "19 f"-e -F {__name__}.MyOptionalSummaryProvider "20 '-x "^MyOptional<.+>$"'21 )22 23 24def stringify(bytecode: bytearray) -> str:25 s = ""26 in_hex = False27 for b in bytecode:28 if (b < 32 or b > 127 or chr(b) in ['"', "`", "'"]) or (29 in_hex30 and chr(b).lower()31 in [32 "a",33 "b",34 "c",35 "d",36 "e",37 "f",38 "0",39 "1",40 "2",41 "3",42 "4",43 "5",44 "6",45 "7",46 "8",47 "9",48 ]49 ):50 s += r"\x" + hex(b)[2:]51 in_hex = True52 else:53 s += chr(b)54 in_hex = False55 return s56 57 58def evaluate(assembler: str, data: list):59 bytecode = compile(assembler)60 trace = True61 if trace:62 print(63 "Compiled to {0} bytes of bytecode:\n{1}".format(64 len(bytecode), stringify(bytecode)65 )66 )67 result = interpret(bytecode, [], data, False) # trace)68 if trace:69 print("--> {0}".format(result))70 return result71 72 73# def GetOptionalValue(valobj):74# storage = valobj.GetChildMemberWithName("Storage")75# if not storage:76# storage = valobj77#78# failure = 279# hasVal = storage.GetChildMemberWithName("hasVal").GetValueAsUnsigned(failure)80# if hasVal == failure:81# return "<could not read MyOptional>"82#83# if hasVal == 0:84# return None85#86# underlying_type = storage.GetType().GetTemplateArgumentType(0)87# storage = storage.GetChildMemberWithName("value")88# return storage.Cast(underlying_type)89 90 91def MyOptionalSummaryProvider(valobj, internal_dict):92 # val = GetOptionalValue(valobj)93 # if val is None:94 # return "None"95 # if val.summary:96 # return val.summary97 # return val.GetValue()98 summary = ""99 summary += ' dup "Storage" @get_child_with_name call' # valobj storage100 summary += " dup is_null ~ { swap } if drop" # storage101 summary += ' dup "hasVal" @get_child_with_name call' # storage obj(hasVal)102 summary += ' dup is_null { drop "<could not read MyOptional>" } {'103 summary += " @get_value_as_unsigned call" # storage int(hasVal)104 summary += ' 0u = { "None" } {'105 summary += " dup @get_type call"106 summary += " 0u @get_template_argument_type call" # storage type107 summary += " swap" # type storage108 summary += ' "value" @get_child_with_name call' # type value109 summary += " swap @cast call" # type(value)110 summary += ' dup is_null { "None" } {'111 summary += (112 " dup @summary call dup @strlen call { @get_value call } { drop } ifelse"113 )114 summary += " } ifelse"115 summary += " } ifelse"116 summary += " } ifelse"117 return evaluate(summary, [valobj])118 119 120class MyOptionalSynthProvider:121 """Provides deref support to llvm::Optional<T>"""122 123 def __init__(self, valobj, internal_dict):124 self.valobj = valobj125 126 def num_children(self):127 # return self.valobj.num_children128 num_children = " @get_num_children call"129 return evaluate(num_children, [self.valobj])130 131 def get_child_index(self, name):132 # if name == "$$dereference$$":133 # return self.valobj.num_children134 # return self.valobj.GetIndexOfChildWithName(name)135 get_child_index = ' dup "$$dereference$$" ='136 get_child_index += " { drop @get_num_children call } {" # obj name137 get_child_index += " @get_child_index call" # index138 get_child_index += " } ifelse"139 return evaluate(get_child_index, [self.valobj, name])140 141 def get_child_at_index(self, index):142 # if index < self.valobj.num_children:143 # return self.valobj.GetChildAtIndex(index)144 # return GetOptionalValue(self.valobj) or lldb.SBValue()145 get_child_at_index = " over over swap" # obj index index obj146 get_child_at_index += " @get_num_children call" # obj index index n147 get_child_at_index += " < { @get_child_at_index call } {" # obj index148 149 get_opt_val = ' dup "Storage" @get_child_with_name call' # valobj storage150 get_opt_val += " dup { swap } if drop" # storage151 get_opt_val += ' dup "hasVal" @get_child_with_name call' # storage152 get_opt_val += " @get_value_as_unsigned call" # storage int(hasVal)153 get_opt_val += ' dup 2 = { drop "<could not read MyOptional>" } {'154 get_opt_val += ' 0 = { "None" } {'155 get_opt_val += (156 " dup @get_type call 0 @get_template_argument_type call" # storage type157 )158 get_opt_val += " swap" # type storage159 get_opt_val += ' "value" @get_child_with_name call' # type value160 get_opt_val += " swap @cast call" # type(value)161 get_opt_val += " } ifelse"162 get_opt_val += " } ifelse"163 164 get_child_at_index += get_opt_val165 get_child_at_index += " } ifelse"166 167 return evaluate(get_child_at_index, [self.valobj, index])168