1*fffe8c66SAdrian Prantl""" 2*fffe8c66SAdrian PrantlThis is the llvm::Optional data formatter from llvm/utils/lldbDataFormatters.py 3*fffe8c66SAdrian Prantlwith the implementation replaced by bytecode. 4*fffe8c66SAdrian Prantl""" 5*fffe8c66SAdrian Prantl 6*fffe8c66SAdrian Prantlfrom __future__ import annotations 7*fffe8c66SAdrian Prantlfrom formatter_bytecode import * 8*fffe8c66SAdrian Prantlimport lldb 9*fffe8c66SAdrian Prantl 10*fffe8c66SAdrian Prantl 11*fffe8c66SAdrian Prantldef __lldb_init_module(debugger, internal_dict): 12*fffe8c66SAdrian Prantl debugger.HandleCommand( 13*fffe8c66SAdrian Prantl "type synthetic add -w llvm " 14*fffe8c66SAdrian Prantl f"-l {__name__}.MyOptionalSynthProvider " 15*fffe8c66SAdrian Prantl '-x "^MyOptional<.+>$"' 16*fffe8c66SAdrian Prantl ) 17*fffe8c66SAdrian Prantl debugger.HandleCommand( 18*fffe8c66SAdrian Prantl "type summary add -w llvm " 19*fffe8c66SAdrian Prantl f"-e -F {__name__}.MyOptionalSummaryProvider " 20*fffe8c66SAdrian Prantl '-x "^MyOptional<.+>$"' 21*fffe8c66SAdrian Prantl ) 22*fffe8c66SAdrian Prantl 23*fffe8c66SAdrian Prantl 24*fffe8c66SAdrian Prantldef stringify(bytecode: bytearray) -> str: 25*fffe8c66SAdrian Prantl s = "" 26*fffe8c66SAdrian Prantl in_hex = False 27*fffe8c66SAdrian Prantl for b in bytecode: 28*fffe8c66SAdrian Prantl if (b < 32 or b > 127 or chr(b) in ['"', "`", "'"]) or ( 29*fffe8c66SAdrian Prantl in_hex 30*fffe8c66SAdrian Prantl and chr(b).lower() 31*fffe8c66SAdrian Prantl in [ 32*fffe8c66SAdrian Prantl "a", 33*fffe8c66SAdrian Prantl "b", 34*fffe8c66SAdrian Prantl "c", 35*fffe8c66SAdrian Prantl "d", 36*fffe8c66SAdrian Prantl "e", 37*fffe8c66SAdrian Prantl "f", 38*fffe8c66SAdrian Prantl "0", 39*fffe8c66SAdrian Prantl "1", 40*fffe8c66SAdrian Prantl "2", 41*fffe8c66SAdrian Prantl "3", 42*fffe8c66SAdrian Prantl "4", 43*fffe8c66SAdrian Prantl "5", 44*fffe8c66SAdrian Prantl "6", 45*fffe8c66SAdrian Prantl "7", 46*fffe8c66SAdrian Prantl "8", 47*fffe8c66SAdrian Prantl "9", 48*fffe8c66SAdrian Prantl ] 49*fffe8c66SAdrian Prantl ): 50*fffe8c66SAdrian Prantl s += r"\x" + hex(b)[2:] 51*fffe8c66SAdrian Prantl in_hex = True 52*fffe8c66SAdrian Prantl else: 53*fffe8c66SAdrian Prantl s += chr(b) 54*fffe8c66SAdrian Prantl in_hex = False 55*fffe8c66SAdrian Prantl return s 56*fffe8c66SAdrian Prantl 57*fffe8c66SAdrian Prantl 58*fffe8c66SAdrian Prantldef evaluate(assembler: str, data: list): 59*fffe8c66SAdrian Prantl bytecode = compile(assembler) 60*fffe8c66SAdrian Prantl trace = True 61*fffe8c66SAdrian Prantl if trace: 62*fffe8c66SAdrian Prantl print( 63*fffe8c66SAdrian Prantl "Compiled to {0} bytes of bytecode:\n{1}".format( 64*fffe8c66SAdrian Prantl len(bytecode), stringify(bytecode) 65*fffe8c66SAdrian Prantl ) 66*fffe8c66SAdrian Prantl ) 67*fffe8c66SAdrian Prantl result = interpret(bytecode, [], data, False) # trace) 68*fffe8c66SAdrian Prantl if trace: 69*fffe8c66SAdrian Prantl print("--> {0}".format(result)) 70*fffe8c66SAdrian Prantl return result 71*fffe8c66SAdrian Prantl 72*fffe8c66SAdrian Prantl 73*fffe8c66SAdrian Prantl# def GetOptionalValue(valobj): 74*fffe8c66SAdrian Prantl# storage = valobj.GetChildMemberWithName("Storage") 75*fffe8c66SAdrian Prantl# if not storage: 76*fffe8c66SAdrian Prantl# storage = valobj 77*fffe8c66SAdrian Prantl# 78*fffe8c66SAdrian Prantl# failure = 2 79*fffe8c66SAdrian Prantl# hasVal = storage.GetChildMemberWithName("hasVal").GetValueAsUnsigned(failure) 80*fffe8c66SAdrian Prantl# if hasVal == failure: 81*fffe8c66SAdrian Prantl# return "<could not read MyOptional>" 82*fffe8c66SAdrian Prantl# 83*fffe8c66SAdrian Prantl# if hasVal == 0: 84*fffe8c66SAdrian Prantl# return None 85*fffe8c66SAdrian Prantl# 86*fffe8c66SAdrian Prantl# underlying_type = storage.GetType().GetTemplateArgumentType(0) 87*fffe8c66SAdrian Prantl# storage = storage.GetChildMemberWithName("value") 88*fffe8c66SAdrian Prantl# return storage.Cast(underlying_type) 89*fffe8c66SAdrian Prantl 90*fffe8c66SAdrian Prantl 91*fffe8c66SAdrian Prantldef MyOptionalSummaryProvider(valobj, internal_dict): 92*fffe8c66SAdrian Prantl # val = GetOptionalValue(valobj) 93*fffe8c66SAdrian Prantl # if val is None: 94*fffe8c66SAdrian Prantl # return "None" 95*fffe8c66SAdrian Prantl # if val.summary: 96*fffe8c66SAdrian Prantl # return val.summary 97*fffe8c66SAdrian Prantl # return val.GetValue() 98*fffe8c66SAdrian Prantl summary = "" 99*fffe8c66SAdrian Prantl summary += ' dup "Storage" @get_child_with_name call' # valobj storage 100*fffe8c66SAdrian Prantl summary += " dup is_null ~ { swap } if drop" # storage 101*fffe8c66SAdrian Prantl summary += ' dup "hasVal" @get_child_with_name call' # storage obj(hasVal) 102*fffe8c66SAdrian Prantl summary += ' dup is_null { drop "<could not read MyOptional>" } {' 103*fffe8c66SAdrian Prantl summary += " @get_value_as_unsigned call" # storage int(hasVal) 104*fffe8c66SAdrian Prantl summary += ' 0u = { "None" } {' 105*fffe8c66SAdrian Prantl summary += " dup @get_type call" 106*fffe8c66SAdrian Prantl summary += " 0u @get_template_argument_type call" # storage type 107*fffe8c66SAdrian Prantl summary += " swap" # type storage 108*fffe8c66SAdrian Prantl summary += ' "value" @get_child_with_name call' # type value 109*fffe8c66SAdrian Prantl summary += " swap @cast call" # type(value) 110*fffe8c66SAdrian Prantl summary += ' dup is_null { "None" } {' 111*fffe8c66SAdrian Prantl summary += ( 112*fffe8c66SAdrian Prantl " dup @summary call dup @strlen call { @get_value call } { drop } ifelse" 113*fffe8c66SAdrian Prantl ) 114*fffe8c66SAdrian Prantl summary += " } ifelse" 115*fffe8c66SAdrian Prantl summary += " } ifelse" 116*fffe8c66SAdrian Prantl summary += " } ifelse" 117*fffe8c66SAdrian Prantl return evaluate(summary, [valobj]) 118*fffe8c66SAdrian Prantl 119*fffe8c66SAdrian Prantl 120*fffe8c66SAdrian Prantlclass MyOptionalSynthProvider: 121*fffe8c66SAdrian Prantl """Provides deref support to llvm::Optional<T>""" 122*fffe8c66SAdrian Prantl 123*fffe8c66SAdrian Prantl def __init__(self, valobj, internal_dict): 124*fffe8c66SAdrian Prantl self.valobj = valobj 125*fffe8c66SAdrian Prantl 126*fffe8c66SAdrian Prantl def num_children(self): 127*fffe8c66SAdrian Prantl # return self.valobj.num_children 128*fffe8c66SAdrian Prantl num_children = " @get_num_children call" 129*fffe8c66SAdrian Prantl return evaluate(num_children, [self.valobj]) 130*fffe8c66SAdrian Prantl 131*fffe8c66SAdrian Prantl def get_child_index(self, name): 132*fffe8c66SAdrian Prantl # if name == "$$dereference$$": 133*fffe8c66SAdrian Prantl # return self.valobj.num_children 134*fffe8c66SAdrian Prantl # return self.valobj.GetIndexOfChildWithName(name) 135*fffe8c66SAdrian Prantl get_child_index = ' dup "$$dereference$$" =' 136*fffe8c66SAdrian Prantl get_child_index += " { drop @get_num_children call } {" # obj name 137*fffe8c66SAdrian Prantl get_child_index += " @get_child_index call" # index 138*fffe8c66SAdrian Prantl get_child_index += " } ifelse" 139*fffe8c66SAdrian Prantl return evaluate(get_child_index, [self.valobj, name]) 140*fffe8c66SAdrian Prantl 141*fffe8c66SAdrian Prantl def get_child_at_index(self, index): 142*fffe8c66SAdrian Prantl # if index < self.valobj.num_children: 143*fffe8c66SAdrian Prantl # return self.valobj.GetChildAtIndex(index) 144*fffe8c66SAdrian Prantl # return GetOptionalValue(self.valobj) or lldb.SBValue() 145*fffe8c66SAdrian Prantl get_child_at_index = " over over swap" # obj index index obj 146*fffe8c66SAdrian Prantl get_child_at_index += " @get_num_children call" # obj index index n 147*fffe8c66SAdrian Prantl get_child_at_index += " < { @get_child_at_index call } {" # obj index 148*fffe8c66SAdrian Prantl 149*fffe8c66SAdrian Prantl get_opt_val = ' dup "Storage" @get_child_with_name call' # valobj storage 150*fffe8c66SAdrian Prantl get_opt_val += " dup { swap } if drop" # storage 151*fffe8c66SAdrian Prantl get_opt_val += ' dup "hasVal" @get_child_with_name call' # storage 152*fffe8c66SAdrian Prantl get_opt_val += " @get_value_as_unsigned call" # storage int(hasVal) 153*fffe8c66SAdrian Prantl get_opt_val += ' dup 2 = { drop "<could not read MyOptional>" } {' 154*fffe8c66SAdrian Prantl get_opt_val += ' 0 = { "None" } {' 155*fffe8c66SAdrian Prantl get_opt_val += ( 156*fffe8c66SAdrian Prantl " dup @get_type call 0 @get_template_argument_type call" # storage type 157*fffe8c66SAdrian Prantl ) 158*fffe8c66SAdrian Prantl get_opt_val += " swap" # type storage 159*fffe8c66SAdrian Prantl get_opt_val += ' "value" @get_child_with_name call' # type value 160*fffe8c66SAdrian Prantl get_opt_val += " swap @cast call" # type(value) 161*fffe8c66SAdrian Prantl get_opt_val += " } ifelse" 162*fffe8c66SAdrian Prantl get_opt_val += " } ifelse" 163*fffe8c66SAdrian Prantl 164*fffe8c66SAdrian Prantl get_child_at_index += get_opt_val 165*fffe8c66SAdrian Prantl get_child_at_index += " } ifelse" 166*fffe8c66SAdrian Prantl 167*fffe8c66SAdrian Prantl return evaluate(get_child_at_index, [self.valobj, index]) 168