diff options
| author | Sam Estep <sam@samestep.com> | 2025-07-23 10:00:24 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-23 14:00:24 +0000 |
| commit | 876b21f21cb9bfdff1479364f60f2ce6b15ea0b3 (patch) | |
| tree | 52ecc56939b737dfbcf82bc802642588d2995334 /source | |
| parent | ed8add13e917eb50a0ab4b021b57191271313a58 (diff) | |
Add LLDB data formatters for Slang IR (#7828)
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang_lldb.py | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/source/slang/slang_lldb.py b/source/slang/slang_lldb.py new file mode 100644 index 000000000..c1213e830 --- /dev/null +++ b/source/slang/slang_lldb.py @@ -0,0 +1,179 @@ +""" +This python script provides LLDB formatters for Slang IR types. +To use it, add the following line to your ~/.lldbinit file: +command script import /path/to/source/slang/slang_lldb.py +""" + +import json + +import lldb + + +class Children: + indices: dict[str, int] + values: list[lldb.SBValue] + + def __init__(self): + self.indices = {} + self.values = [] + + def append(self, value: lldb.SBValue) -> None: + self.indices[value.name] = len(self.values) + self.values.append(value) + + def __len__(self) -> int: + return len(self.values) + + def get_index(self, name: str) -> int: + return self.indices[name] + + def get_at_index(self, idx: int) -> lldb.SBValue: + return self.values[idx] + + +def IRUse_summary(valobj: lldb.SBValue, dict) -> str: + val = valobj.GetNonSyntheticValue() + return val.GetChildMemberWithName("usedValue").deref.summary + + +class IRInstListBase_synthetic(lldb.SBSyntheticValueProvider): + def __init__(self, valobj: lldb.SBValue, dict): + self.valobj = valobj + + def num_children(self): + return len(self.children) + + def get_child_index(self, name): + return self.children.get_index(name) + + def get_child_at_index(self, idx): + return self.children.get_at_index(idx) + + def update(self): + self.children = Children() + pointer = self.valobj.GetChildMemberWithName("first") + i = 0 + while pointer.unsigned != 0: + child = pointer.deref + self.children.append(child.Clone(f"[{i}]")) + pointer = child.GetNonSyntheticValue().GetChildMemberWithName("next") + i += 1 + + def has_children(self): + return True + + +class IRInst_synthetic(lldb.SBSyntheticValueProvider): + def __init__(self, valobj: lldb.SBValue, dict): + self.valobj = valobj + + def num_children(self): + return len(self.children) + + def get_child_index(self, name): + return self.children.get_index(name) + + def get_child_at_index(self, idx): + return self.children.get_at_index(idx) + + def update(self): + self.children = Children() + target = self.valobj.target + ty = self.valobj.type + op = self.valobj.GetChildMemberWithName("m_op") + + # literal values + value: list[tuple[str, lldb.SBValue]] = [] + match op.value: + case "kIROp_StringLit": + string_lit_t = target.FindFirstType("Slang::IRStringLit") + string_lit = self.valobj.Cast(string_lit_t) + val = string_lit.GetChildMemberWithName("value") + value = [("[value]", val.GetChildMemberWithName("stringVal"))] + case "kIROp_IntLit": + int_lit_t = target.FindFirstType("Slang::IRIntLit") + int_lit = self.valobj.Cast(int_lit_t) + val = int_lit.GetChildMemberWithName("value") + value = [("[value]", val.GetChildMemberWithName("intVal"))] + + # operands + operands: list[tuple[str, lldb.SBValue]] = [] + 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): + name = f"[operand{index}]" + operand = self.valobj.CreateChildAtOffset( + name, offset + index * ir_use_size, ir_use_t + ) + operands.append((name, operand)) + + for name, child in [ + ("[op]", op), + ("[UID]", self.valobj.GetChildMemberWithName("_debugUID")), + ( + "[type]", + self.valobj.GetChildMemberWithName("typeUse").GetChildMemberWithName( + "usedValue" + ), + ), + # TODO: [exportName] + # TODO: [importName] + # TODO: [name] + *value, + *operands, + ( + "[decorations/children]", + self.valobj.GetChildMemberWithName("m_decorationsAndChildren"), + ), + ("[parent]", self.valobj.GetChildMemberWithName("parent")), + # TODO: Traverse the linked list to show all uses next to + # each other, rather than pointing to the first one. + ("[uses]", self.valobj.GetChildMemberWithName("firstUse")), + ]: + self.children.append(child.Clone(name)) + + def has_children(self): + return True + + +def IRInst_summary(valobj: lldb.SBValue, dict) -> str: + val = valobj.GetNonSyntheticValue() + op = val.GetChildMemberWithName("m_op") + return f"{{{op.value} {val.address_of.value}}}" + + +def stringval_summary(valobj: lldb.SBValue) -> str: + val = valobj.GetNonSyntheticValue() + num_chars = val.GetChildMemberWithName("numChars").unsigned + chars = val.GetChildMemberWithName("chars").GetPointeeData(0, num_chars).uint8 + return json.dumps("".join(chr(chars[i]) for i in range(num_chars))) + + +def StringValue_summary(valobj: lldb.SBValue, dict) -> str: + return stringval_summary(valobj) + + +def StringSliceValue_summary(valobj: lldb.SBValue, dict) -> str: + return stringval_summary(valobj) + + +def __lldb_init_module(debugger: lldb.SBDebugger, internal_dict): + commands = [ + # Slang::IRUse + "type summary add Slang::IRUse -F slang_lldb.IRUse_summary -w slang", + # Slang::IRInstListBase + "type synthetic add Slang::IRInstListBase -l slang_lldb.IRInstListBase_synthetic -w slang", + # Slang::IRInst + "type synthetic add Slang::IRInst -l slang_lldb.IRInst_synthetic -w slang", + "type summary add --expand Slang::IRInst -F slang_lldb.IRInst_summary -w slang", + # Slang::IRConstant::StringValue + "type summary add Slang::IRConstant::StringValue -F slang_lldb.StringValue_summary -w slang", + # Slang::IRConstant::StringSliceValue + "type summary add Slang::IRConstant::StringSliceValue -F slang_lldb.StringSliceValue_summary -w slang", + # Enable slang category + "type category enable slang", + ] + + for c in commands: + debugger.HandleCommand(c) |
