diff options
| -rw-r--r-- | source/slang/slang_lldb.py | 32 | ||||
| -rw-r--r-- | typings/lldb.pyi | 4 |
2 files changed, 33 insertions, 3 deletions
diff --git a/source/slang/slang_lldb.py b/source/slang/slang_lldb.py index d4cb3b6f6..a5d2500af 100644 --- a/source/slang/slang_lldb.py +++ b/source/slang/slang_lldb.py @@ -57,6 +57,15 @@ class IRInstListBase_synthetic(lldb.SBSyntheticValueProvider): self.children.append(child.Clone(f"[{i}]")) pointer = child.GetNonSyntheticValue().GetChildMemberWithName("next") i += 1 + if i >= 5000: + # The debugger can call this function on uninitialized + # values, so we need to ensure that we stop iterating at + # some point. Ideally we'd provide a synthetic child + # called something like `[more]` to see another batch of + # many children in the case where there really is just a + # very large list, but this is good enough because one + # can always manually follow `next` pointers. + break def has_children(self): return True @@ -77,12 +86,26 @@ class IRInst_synthetic(lldb.SBSyntheticValueProvider): def update(self): self.children = Children() + + if self.valobj.type.IsPointerType(): + if self.valobj.unsigned != 0: + valobj = self.valobj.deref + for i in range(valobj.GetNumChildren()): + self.children.append(valobj.GetChildAtIndex(i)) + return + target = self.valobj.target ty = self.valobj.type op = self.valobj.GetChildMemberWithName("m_op") # literal values value: list[tuple[str, lldb.SBValue]] = [] + # Using `Cast` here seems to work just fine in the LLDB CLI with + # `v`, as well as in CodeLLDB, but for some reason it does not + # work correctly with `p`, causing the `[value]` child to be + # missing in that case. It is possible to fix that by using + # `EvaluateExpression` instead, but that significantly degrades + # performance, so we choose not to do it here. match op.value: case "kIROp_StringLit": string_lit_t = target.FindFirstType("Slang::IRStringLit") @@ -100,7 +123,12 @@ class IRInst_synthetic(lldb.SBSyntheticValueProvider): offset = ty.GetByteSize() ir_use_t = target.FindFirstType("Slang::IRUse") ir_use_size = ir_use_t.GetByteSize() - for index in range(self.valobj.GetChildMemberWithName("operandCount").unsigned): + operand_count = self.valobj.GetChildMemberWithName("operandCount").unsigned + # We must ensure that we don't loop for an unbounded amount of + # time, so we cap the number of operands displayed here. Ideally + # we'd provide a way to view more in the case of instructions + # with more than this many operands, though. + for index in range(min(operand_count, 10)): name = f"[operand{index}]" operand = self.valobj.CreateChildAtOffset( name, offset + index * ir_use_size, ir_use_t @@ -137,6 +165,8 @@ class IRInst_synthetic(lldb.SBSyntheticValueProvider): def IRInst_summary(valobj: lldb.SBValue, dict) -> str: + if valobj.type.IsPointerType(): + return "nullptr" if valobj.unsigned == 0 else valobj.deref.summary val = valobj.GetNonSyntheticValue() op = val.GetChildMemberWithName("m_op") return f"{{{op.value} {val.address_of.value}}}" diff --git a/typings/lldb.pyi b/typings/lldb.pyi index 646bb46b2..658f8add2 100644 --- a/typings/lldb.pyi +++ b/typings/lldb.pyi @@ -333,7 +333,7 @@ class SBType: def IsValid(self): ... def GetByteSize(self) -> int: ... def GetByteAlign(self): ... - def IsPointerType(self): ... + def IsPointerType(self) -> bool: ... def IsReferenceType(self): ... def IsFunctionType(self): ... def IsPolymorphicClass(self): ... @@ -470,7 +470,7 @@ class SBValue: def CreateValueFromExpression(self, *args): ... def CreateValueFromAddress(self, name, address, type): ... def CreateValueFromData(self, name, data, type): ... - def GetChildAtIndex(self, *args): ... + def GetChildAtIndex(self, idx: int) -> SBValue: ... def GetIndexOfChildWithName(self, name): ... def GetChildMemberWithName(self, name: str) -> SBValue: ... def GetValueForExpressionPath(self, expr_path): ... |
