xref: /llvm-project/mlir/utils/lldb-scripts/mlirDataFormatters.py (revision 3f9cabae0029bcbe88835aaa4c417ce41e584fb1)
1"""
2LLDB Formatters for MLIR data types.
3
4Load into LLDB with 'command script import /path/to/mlirDataFormatters.py'
5"""
6
7import re
8import lldb
9
10
11def get_expression_path(val: lldb.SBValue):
12    """Compute the expression path for the given value."""
13
14    stream = lldb.SBStream()
15    if not val.GetExpressionPath(stream):
16        return None
17    return stream.GetData()
18
19
20def build_ptr_str_from_addr(addrValue: lldb.SBValue, type: lldb.SBType):
21    """Build a string that computes a pointer using the given address value and type."""
22
23    if type.is_reference:
24        type = type.GetDereferencedType()
25    if not type.is_pointer:
26        type = type.GetPointerType()
27    return f"(({type}){addrValue.GetData().GetUnsignedInt64(lldb.SBError(), 0)})"
28
29
30# ===----------------------------------------------------------------------=== #
31# Attributes and Types
32# ===----------------------------------------------------------------------=== #
33
34# This variable defines various mnemonic strings for use by the builtin
35# dialect attributes and types, which often have special formatting within
36# the parser/printer.
37builtin_attr_type_mnemonics = {
38    "mlir::AffineMapAttr": '"affine_map<...>"',
39    "mlir::ArrayAttr": '"[...]"',
40    "mlir::DenseArray": '"array<...>"',
41    "mlir::DenseResourceElementsAttr": '"dense_resource<...>"',
42    "mlir::DictionaryAttr": '"{...}"',
43    "mlir::IntegerAttr": '"float"',
44    "mlir::IntegerAttr": '"integer"',
45    "mlir::IntegerSetAttr": '"affine_set<...>"',
46    "mlir::SparseElementsAttr": '"sparse<...>"',
47    "mlir::StringAttr": '""...""',
48    "mlir::StridedLayout": '"strided_layout"',
49    "mlir::UnitAttr": '"unit"',
50    "mlir::CallSiteLoc": '"loc(callsite(...))"',
51    "mlir::FusedLoc": '"loc(fused<...>[...])"',
52    "mlir::UnknownLoc": '"loc(unknown)"',
53    "mlir::Float4E2M1FNType": '"f4E2M1FN"',
54    "mlir::Float6E2M3FNType": '"f6E2M3FN"',
55    "mlir::Float6E3M2FNType": '"f6E3M2FN"',
56    "mlir::Float8E5M2Type": '"f8E5M2"',
57    "mlir::Float8E4M3Type": '"f8E4M3"',
58    "mlir::Float8E4M3FNType": '"f8E4M3FN"',
59    "mlir::Float8E5M2FNUZType": '"f8E5M2FNUZ"',
60    "mlir::Float8E4M3FNUZType": '"f8E4M3FNUZ"',
61    "mlir::Float8E4M3B11FNUZType": '"f8E4M3B11FNUZ"',
62    "mlir::Float8E3M4Type": '"f8E3M4"',
63    "mlir::Float8E8M0FNUType": '"f8E8M0FNU"',
64    "mlir::BFloat16Type": '"bf16"',
65    "mlir::Float16Type": '"f16"',
66    "mlir::FloatTF32Type": '"tf32"',
67    "mlir::Float32Type": '"f32"',
68    "mlir::Float64Type": '"f64"',
69    "mlir::Float80Type": '"f80"',
70    "mlir::Float128Type": '"f128"',
71    "mlir::FunctionType": '"(...) -> (...)"',
72    "mlir::IndexType": '"index"',
73    "mlir::IntegerType": '"iN"',
74    "mlir::NoneType": '"none"',
75    "mlir::TupleType": '"tuple<...>"',
76    "mlir::MemRefType": '"memref<...>"',
77    "mlir::UnrankedMemRef": '"memref<...>"',
78    "mlir::UnrankedTensorType": '"tensor<...>"',
79    "mlir::RankedTensorType": '"tensor<...>"',
80    "mlir::VectorType": '"vector<...>"',
81}
82
83
84class ComputedTypeIDMap:
85    """Compute a map of type ids to derived attributes, types, and locations.
86
87    This is necessary for determining the C++ type when holding a base class,
88    where we really only have access to dynamic information.
89    """
90
91    def __init__(self, target: lldb.SBTarget, internal_dict: dict):
92        self.resolved_typeids = {}
93
94        # Find all of the `id` variables, which are the name of TypeID variables
95        # defined within the TypeIDResolver.
96        type_ids = target.FindGlobalVariables("id", lldb.UINT32_MAX)
97        for type_id in type_ids:
98            # Strip out any matches that didn't come from a TypeID resolver. This
99            # also lets us extract the derived type name.
100            name = type_id.GetName()
101            match = re.search("^mlir::detail::TypeIDResolver<(.*), void>::id$", name)
102            if not match:
103                continue
104            type_name = match.group(1)
105
106            # Filter out types that we don't care about.
107            if not type_name.endswith(("Attr", "Loc", "Type")):
108                continue
109
110            # Find the LLDB type for the derived type.
111            type = None
112            for typeIt in target.FindTypes(type_name):
113                if not typeIt or not typeIt.IsValid():
114                    continue
115                type = typeIt
116                break
117            if not type or not type.IsValid():
118                continue
119
120            # Map the raw address of the type id variable to the LLDB type.
121            self.resolved_typeids[type_id.AddressOf().GetValueAsUnsigned()] = type
122
123    # Resolve the type for the given TypeID address.
124    def resolve_type(self, typeIdAddr: lldb.SBValue):
125        try:
126            return self.resolved_typeids[typeIdAddr.GetValueAsUnsigned()]
127        except KeyError:
128            return None
129
130
131def is_derived_attribute_or_type(sbtype: lldb.SBType, internal_dict):
132    """Return if the given type is a derived attribute or type."""
133
134    # We only expect an AttrBase/TypeBase base class.
135    if sbtype.num_bases != 1:
136        return False
137    base_name = sbtype.GetDirectBaseClassAtIndex(0).GetName()
138    return base_name.startswith(("mlir::Attribute::AttrBase", "mlir::Type::TypeBase"))
139
140
141def get_typeid_map(target: lldb.SBTarget, internal_dict: dict):
142    """Get or construct a TypeID map for the given target."""
143
144    if "typeIdMap" not in internal_dict:
145        internal_dict["typeIdMap"] = ComputedTypeIDMap(target, internal_dict)
146    return internal_dict["typeIdMap"]
147
148
149def is_attribute_or_type(sbtype: lldb.SBType, internal_dict):
150    """Return if the given type is an attribute or type."""
151
152    num_bases = sbtype.GetNumberOfDirectBaseClasses()
153    typeName = sbtype.GetName()
154
155    # We bottom out at Attribute/Type/Location.
156    if num_bases == 0:
157        return typeName in ["mlir::Attribute", "mlir::Type", "mlir::Location"]
158
159    # Check the easy cases of AttrBase/TypeBase.
160    if typeName.startswith(("mlir::Attribute::AttrBase", "mlir::Type::TypeBase")):
161        return True
162
163    # Otherwise, recurse into the base class.
164    return is_attribute_or_type(
165        sbtype.GetDirectBaseClassAtIndex(0).GetType(), internal_dict
166    )
167
168
169def resolve_attr_type_from_value(
170    valobj: lldb.SBValue, abstractVal: lldb.SBValue, internal_dict
171):
172    """Resolve the derived C++ type of an Attribute/Type value."""
173
174    # Derived attribute/types already have the desired type.
175    if is_derived_attribute_or_type(valobj.GetType(), internal_dict):
176        return valobj.GetType()
177
178    # Otherwise, we need to resolve the ImplTy from the TypeID. This is
179    # done dynamically, because we don't use C++ RTTI of any kind.
180    typeIdMap = get_typeid_map(valobj.GetTarget(), internal_dict)
181    return typeIdMap.resolve_type(
182        abstractVal.GetChildMemberWithName("typeID").GetChildMemberWithName("storage")
183    )
184
185
186class AttrTypeSynthProvider:
187    """Define an LLDB synthetic children provider for Attributes and Types."""
188
189    def __init__(self, valobj: lldb.SBValue, internal_dict):
190        self.valobj = valobj
191
192        # Grab the impl variable, which if this is a Location needs to be
193        # resolved through the LocationAttr impl variable.
194        impl: lldb.SBValue = self.valobj.GetChildMemberWithName("impl")
195        if self.valobj.GetTypeName() == "mlir::Location":
196            impl = impl.GetChildMemberWithName("impl")
197        self.abstractVal = impl.GetChildMemberWithName("abstractType")
198        if not self.abstractVal.IsValid():
199            self.abstractVal = impl.GetChildMemberWithName("abstractAttribute")
200
201        self.type = resolve_attr_type_from_value(
202            valobj, self.abstractVal, internal_dict
203        )
204        if not self.type:
205            self.impl_type = None
206            return
207
208        # Grab the ImplTy from the resolved type. This is the 3rd template
209        # argument of the base class.
210        self.impl_type = (
211            self.type.GetDirectBaseClassAtIndex(0).GetType().GetTemplateArgumentType(2)
212        )
213        self.impl_pointer_ty = self.impl_type.GetPointerType()
214        self.num_fields = self.impl_type.GetNumberOfFields()
215
216        # Optionally add a mnemonic field.
217        type_name = self.type.GetName()
218        if type_name in builtin_attr_type_mnemonics:
219            self.mnemonic = builtin_attr_type_mnemonics[type_name]
220        elif type_name.startswith("mlir::Dense"):
221            self.mnemonic = "dense<...>"
222        else:
223            self.mnemonic = self.valobj.CreateValueFromExpression(
224                "mnemonic", f"(llvm::StringRef){type_name}::getMnemonic()"
225            )
226            if not self.mnemonic.summary:
227                self.mnemonic = None
228        if self.mnemonic:
229            self.num_fields += 1
230
231    def num_children(self):
232        if not self.impl_type:
233            return 0
234        return self.num_fields
235
236    def get_child_index(self, name):
237        if not self.impl_type:
238            return None
239        if self.mnemonic and name == "[mnemonic]":
240            return self.impl_type.GetNumberOfFields()
241        for i in range(self.impl_type.GetNumberOfFields()):
242            if self.impl_type.GetFieldAtIndex(i).GetName() == name:
243                return i
244        return None
245
246    def get_child_at_index(self, index):
247        if not self.impl_type or index >= self.num_fields:
248            return None
249
250        impl: lldb.SBValue = self.valobj.GetChildMemberWithName("impl")
251        impl_ptr: lldb.SBValue = self.valobj.CreateValueFromData(
252            build_ptr_str_from_addr(impl, self.impl_pointer_ty),
253            impl.GetData(),
254            self.impl_pointer_ty,
255        )
256
257        # Check for the mnemonic field.
258        if index == self.impl_type.GetNumberOfFields():
259            return self.valobj.CreateValueFromExpression(
260                "[mnemonic]", self.get_mnemonic_string(impl_ptr)
261            )
262
263        # Otherwise, we expect the index to be a field.
264        field: lldb.SBTypeMember = self.impl_type.GetFieldAtIndex(index)
265
266        # Build the field access by resolving through the impl variable.
267        return impl_ptr.GetChildMemberWithName(field.GetName())
268
269    def get_mnemonic_string(self, impl_ptr: lldb.SBValue):
270        if isinstance(self.mnemonic, str):
271            return self.mnemonic
272
273        # If we don't already have the mnemonic in string form, compute
274        # it from the dialect name and the mnemonic.
275        dialect_name = self.abstractVal.GetChildMemberWithName(
276            "dialect"
277        ).GetChildMemberWithName("name")
278        self.mnemonic = f'{dialect_name.summary}"."{self.mnemonic.summary}'
279        return self.mnemonic
280
281
282def AttrTypeSummaryProvider(valobj: lldb.SBValue, internal_dict):
283    """Define an LLDB summary provider for Attributes and Types."""
284
285    # Check for a value field.
286    value = valobj.GetChildMemberWithName("value")
287    if value and value.summary:
288        return value.summary
289
290    # Otherwise, try the mnemoic.
291    mnemonic: lldb.SBValue = valobj.GetChildMemberWithName("[mnemonic]")
292    if not mnemonic.summary:
293        return ""
294    mnemonicStr = mnemonic.summary.strip('"')
295
296    # Handle a few extremely common builtin attributes/types.
297    ## IntegerType
298    if mnemonicStr == "iN":
299        signedness = valobj.GetChildMemberWithName("signedness").GetValueAsUnsigned()
300        prefix = "i"
301        if signedness == 1:
302            prefix = "si"
303        elif signedness == 2:
304            prefix = "ui"
305        return f"{prefix}{valobj.GetChildMemberWithName('width').GetValueAsUnsigned()}"
306    ## IntegerAttr
307    if mnemonicStr == "integer":
308        value = valobj.GetChildMemberWithName("value")
309        bitwidth = value.GetChildMemberWithName("BitWidth").GetValueAsUnsigned()
310        if bitwidth <= 64:
311            intVal = (
312                value.GetChildMemberWithName("U")
313                .GetChildMemberWithName("VAL")
314                .GetValueAsUnsigned()
315            )
316
317            if bitwidth == 1:
318                return "true" if intVal else "false"
319            return f"{intVal} : i{bitwidth}"
320
321    return mnemonicStr
322
323
324# ===----------------------------------------------------------------------=== #
325# mlir::Block
326# ===----------------------------------------------------------------------=== #
327
328
329class BlockSynthProvider:
330    """Define an LLDB synthetic children provider for Blocks."""
331
332    def __init__(self, valobj, internal_dict):
333        self.valobj = valobj
334
335    def num_children(self):
336        return 3
337
338    def get_child_index(self, name):
339        if name == "parent":
340            return 0
341        if name == "operations":
342            return 1
343        if name == "arguments":
344            return 2
345        return None
346
347    def get_child_at_index(self, index):
348        if index >= 3:
349            return None
350        if index == 1:
351            return self.valobj.GetChildMemberWithName("operations")
352        if index == 2:
353            return self.valobj.GetChildMemberWithName("arguments")
354
355        expr_path = build_ptr_str_from_addr(self.valobj, self.valobj.GetType())
356        return self.valobj.CreateValueFromExpression(
357            "parent", f"{expr_path}->getParent()"
358        )
359
360
361# ===----------------------------------------------------------------------=== #
362# mlir::Operation
363# ===----------------------------------------------------------------------=== #
364
365
366def is_op(sbtype: lldb.SBType, internal_dict):
367    """Return if the given type is an operation."""
368
369    # Bottom out at OpState/Op.
370    typeName = sbtype.GetName()
371    if sbtype.GetNumberOfDirectBaseClasses() == 0:
372        return typeName == "mlir::OpState"
373    if typeName == "mlir::Operation" or typeName.startswith("mlir::Op<"):
374        return True
375
376    # Otherwise, recurse into the base class.
377    return is_op(sbtype.GetDirectBaseClassAtIndex(0).GetType(), internal_dict)
378
379
380class OperationSynthProvider:
381    """Define an LLDB synthetic children provider for Operations."""
382
383    def __init__(self, valobj, internal_dict):
384        self.valobj = valobj
385        self.fields = []
386        self.update()
387
388    def num_children(self):
389        return len(self.fields)
390
391    def get_child_index(self, name):
392        try:
393            return self.fields.index(name)
394        except ValueError:
395            return None
396
397    def get_child_at_index(self, index):
398        if index >= len(self.fields):
399            return None
400        name = self.fields[index]
401        if name == "name":
402            return self.opobj.GetChildMemberWithName("name")
403        if name == "parent":
404            return self.opobj.GetChildMemberWithName("block").Clone("parent")
405        if name == "location":
406            return self.opobj.GetChildMemberWithName("location")
407        if name == "attributes":
408            return self.opobj.GetChildMemberWithName("attrs")
409
410        expr_path = build_ptr_str_from_addr(self.opobj, self.opobj.GetType())
411        if name == "operands":
412            return self.opobj.CreateValueFromExpression(
413                "operands", f"{expr_path}->debug_getOperands()"
414            )
415        if name == "results":
416            return self.opobj.CreateValueFromExpression(
417                "results", f"{expr_path}->debug_getResults()"
418            )
419        if name == "successors":
420            return self.opobj.CreateValueFromExpression(
421                "successors", f"{expr_path}->debug_getSuccessors()"
422            )
423        if name == "regions":
424            return self.opobj.CreateValueFromExpression(
425                "regions", f"{expr_path}->debug_getRegions()"
426            )
427        return None
428
429    def update(self):
430        # If this is a derived operation, we need to resolve through the
431        # state field.
432        self.opobj = self.valobj
433        if "mlir::Operation" not in self.valobj.GetTypeName():
434            self.opobj = self.valobj.GetChildMemberWithName("state")
435
436        self.fields = ["parent", "name", "location", "attributes"]
437        if (
438            self.opobj.GetChildMemberWithName("hasOperandStorage").GetValueAsUnsigned(0)
439            != 0
440        ):
441            self.fields.append("operands")
442        if self.opobj.GetChildMemberWithName("numResults").GetValueAsUnsigned(0) != 0:
443            self.fields.append("results")
444        if self.opobj.GetChildMemberWithName("numSuccs").GetValueAsUnsigned(0) != 0:
445            self.fields.append("successors")
446        if self.opobj.GetChildMemberWithName("numRegions").GetValueAsUnsigned(0) != 0:
447            self.fields.append("regions")
448
449
450def OperationSummaryProvider(valobj: lldb.SBValue, internal_dict):
451    """Define an LLDB summary provider for Operations."""
452
453    name = valobj.GetChildMemberWithName("name")
454    if name and name.summary:
455        return name.summary
456    return ""
457
458
459# ===----------------------------------------------------------------------=== #
460# Ranges
461# ===----------------------------------------------------------------------=== #
462
463
464class DirectRangeSynthProvider:
465    """Define an LLDB synthetic children provider for direct ranges, i.e. those
466    with a base pointer that points to the type of element we want to display.
467    """
468
469    def __init__(self, valobj, internal_dict):
470        self.valobj = valobj
471        self.update()
472
473    def num_children(self):
474        return self.length
475
476    def get_child_index(self, name):
477        try:
478            return int(name.lstrip("[").rstrip("]"))
479        except:
480            return None
481
482    def get_child_at_index(self, index):
483        if index >= self.num_children():
484            return None
485        offset = index * self.type_size
486        return self.data.CreateChildAtOffset(f"[{index}]", offset, self.data_type)
487
488    def update(self):
489        length_obj = self.valobj.GetChildMemberWithName("count")
490        self.length = length_obj.GetValueAsUnsigned(0)
491
492        self.data = self.valobj.GetChildMemberWithName("base")
493        self.data_type = self.data.GetType().GetPointeeType()
494        self.type_size = self.data_type.GetByteSize()
495        assert self.type_size != 0
496
497
498class InDirectRangeSynthProvider:
499    """Define an LLDB synthetic children provider for ranges
500    that transform the underlying base pointer, e.g. to convert
501    it to a different type depending on various characteristics
502    (e.g. mlir::ValueRange).
503    """
504
505    def __init__(self, valobj, internal_dict):
506        self.valobj = valobj
507        self.update()
508
509    def num_children(self):
510        return self.length
511
512    def get_child_index(self, name):
513        try:
514            return int(name.lstrip("[").rstrip("]"))
515        except:
516            return None
517
518    def get_child_at_index(self, index):
519        if index >= self.num_children():
520            return None
521        expr_path = get_expression_path(self.valobj)
522        return self.valobj.CreateValueFromExpression(
523            f"[{index}]", f"{expr_path}[{index}]"
524        )
525
526    def update(self):
527        length_obj = self.valobj.GetChildMemberWithName("count")
528        self.length = length_obj.GetValueAsUnsigned(0)
529
530
531class IPListRangeSynthProvider:
532    """Define an LLDB synthetic children provider for an IPList."""
533
534    def __init__(self, valobj, internal_dict):
535        self.valobj = valobj
536        self.update()
537
538    def num_children(self):
539        sentinel = self.valobj.GetChildMemberWithName("Sentinel")
540        sentinel_addr = sentinel.AddressOf().GetValueAsUnsigned(0)
541
542        # Iterate the next pointers looking for the sentinel.
543        count = 0
544        current = sentinel.GetChildMemberWithName("Next")
545        while current.GetValueAsUnsigned(0) != sentinel_addr:
546            current = current.GetChildMemberWithName("Next")
547            count += 1
548
549        return count
550
551    def get_child_index(self, name):
552        try:
553            return int(name.lstrip("[").rstrip("]"))
554        except:
555            return None
556
557    def get_child_at_index(self, index):
558        if index >= self.num_children():
559            return None
560
561        # Start from the sentinel and grab the next pointer.
562        value: lldb.SBValue = self.valobj.GetChildMemberWithName("Sentinel")
563        it = 0
564        while it <= index:
565            value = value.GetChildMemberWithName("Next")
566            it += 1
567
568        return value.CreateValueFromExpression(
569            f"[{index}]",
570            f"(({self.value_type})({value.GetTypeName()}){value.GetValueAsUnsigned()})",
571        )
572
573    def update(self):
574        self.value_type = (
575            self.valobj.GetType().GetTemplateArgumentType(0).GetPointerType()
576        )
577
578
579# ===----------------------------------------------------------------------=== #
580# mlir::Value
581# ===----------------------------------------------------------------------=== #
582
583
584class ValueSynthProvider:
585    """Define an LLDB synthetic children provider for Values."""
586
587    def __init__(self, valobj, internal_dict):
588        self.valobj = valobj
589        self.update()
590
591    def num_children(self):
592        # 7: BlockArgument:
593        #  index, type, owner, firstUse, location
594        if self.kind == 7:
595            return 5
596
597        # 0-6: OpResult:
598        #  index, type, owner, firstUse
599        return 4
600
601    def get_child_index(self, name):
602        if name == "index":
603            return 0
604        if name == "type":
605            return 1
606        if name == "owner":
607            return 2
608        if name == "firstUse":
609            return 3
610        if name == "location":
611            return 4
612        return None
613
614    def get_child_at_index(self, index):
615        if index >= self.num_children():
616            return None
617
618        # Check if the current value is already an Impl struct.
619        if self.valobj.GetTypeName().endswith("Impl"):
620            impl_ptr_str = build_ptr_str_from_addr(
621                self.valobj.AddressOf(), self.valobj.GetType().GetPointerType()
622            )
623        else:
624            impl = self.valobj.GetChildMemberWithName("impl")
625            impl_ptr_str = build_ptr_str_from_addr(impl, impl.GetType())
626
627        # Cast to the derived Impl type.
628        if self.kind == 7:
629            derived_impl_str = f"((mlir::detail::BlockArgumentImpl *){impl_ptr_str})"
630        elif self.kind == 6:
631            derived_impl_str = f"((mlir::detail::OutOfLineOpResult *){impl_ptr_str})"
632        else:
633            derived_impl_str = f"((mlir::detail::InlineOpResult *){impl_ptr_str})"
634
635        # Handle the shared fields when possible.
636        if index == 1:
637            return self.valobj.CreateValueFromExpression(
638                "type", f"{derived_impl_str}->debug_getType()"
639            )
640        if index == 3:
641            return self.valobj.CreateValueFromExpression(
642                "firstUse", f"{derived_impl_str}->firstUse"
643            )
644
645        # Handle Block argument children.
646        if self.kind == 7:
647            impl = self.valobj.CreateValueFromExpression("impl", derived_impl_str)
648            if index == 0:
649                return impl.GetChildMemberWithName("index")
650            if index == 2:
651                return impl.GetChildMemberWithName("owner")
652            if index == 4:
653                return impl.GetChildMemberWithName("loc")
654
655        # Handle OpResult children.
656        if index == 0:
657            # Handle the out of line case.
658            if self.kind == 6:
659                return self.valobj.CreateValueFromExpression(
660                    "index", f"{derived_impl_str}->outOfLineIndex + 6"
661                )
662            return self.valobj.CreateValueFromExpression("index", f"{self.kind}")
663        if index == 2:
664            return self.valobj.CreateValueFromExpression(
665                "owner", f"{derived_impl_str}->getOwner()"
666            )
667        return None
668
669    def update(self):
670        # Check if the current value is already an Impl struct.
671        if self.valobj.GetTypeName().endswith("Impl"):
672            impl_ptr_str = build_ptr_str_from_addr(
673                self.valobj, self.valobj.GetType().GetPointerType()
674            )
675        else:
676            impl = self.valobj.GetChildMemberWithName("impl")
677            impl_ptr_str = build_ptr_str_from_addr(impl, impl.GetType())
678
679        # Compute the kind of value we are dealing with.
680        self.kind = self.valobj.CreateValueFromExpression(
681            "kind", f"{impl_ptr_str}->debug_getKind()"
682        ).GetValueAsUnsigned()
683
684
685def ValueSummaryProvider(valobj: lldb.SBValue, internal_dict):
686    """Define an LLDB summary provider for Values."""
687
688    index = valobj.GetChildMemberWithName("index").GetValueAsUnsigned()
689    # Check if this is a block argument or not (block arguments have locations).
690    if valobj.GetChildMemberWithName("location").IsValid():
691        summary = f"Block Argument {index}"
692    else:
693        owner_name = (
694            valobj.GetChildMemberWithName("owner")
695            .GetChildMemberWithName("name")
696            .summary
697        )
698        summary = f"{owner_name} Result {index}"
699
700    # Grab the type to help form the summary.
701    type = valobj.GetChildMemberWithName("type")
702    if type.summary:
703        summary += f": {type.summary}"
704
705    return summary
706
707
708# ===----------------------------------------------------------------------=== #
709# Initialization
710# ===----------------------------------------------------------------------=== #
711
712
713def __lldb_init_module(debugger: lldb.SBDebugger, internal_dict):
714    cat: lldb.SBTypeCategory = debugger.CreateCategory("mlir")
715    cat.SetEnabled(True)
716
717    # Attributes and Types
718    cat.AddTypeSummary(
719        lldb.SBTypeNameSpecifier(
720            "mlirDataFormatters.is_attribute_or_type", lldb.eFormatterMatchCallback
721        ),
722        lldb.SBTypeSummary.CreateWithFunctionName(
723            "mlirDataFormatters.AttrTypeSummaryProvider"
724        ),
725    )
726    cat.AddTypeSynthetic(
727        lldb.SBTypeNameSpecifier(
728            "mlirDataFormatters.is_attribute_or_type", lldb.eFormatterMatchCallback
729        ),
730        lldb.SBTypeSynthetic.CreateWithClassName(
731            "mlirDataFormatters.AttrTypeSynthProvider"
732        ),
733    )
734
735    # Operation
736    cat.AddTypeSynthetic(
737        lldb.SBTypeNameSpecifier("mlir::Block", lldb.eFormatterMatchExact),
738        lldb.SBTypeSynthetic.CreateWithClassName(
739            "mlirDataFormatters.BlockSynthProvider"
740        ),
741    )
742
743    # NamedAttribute
744    cat.AddTypeSummary(
745        lldb.SBTypeNameSpecifier("mlir::NamedAttribute", lldb.eFormatterMatchExact),
746        lldb.SBTypeSummary.CreateWithSummaryString("${var.name%S} = ${var.value%S}"),
747    )
748
749    # OperationName
750    cat.AddTypeSummary(
751        lldb.SBTypeNameSpecifier("mlir::OperationName", lldb.eFormatterMatchExact),
752        lldb.SBTypeSummary.CreateWithSummaryString("${var.impl->name%S}"),
753    )
754
755    # Operation
756    cat.AddTypeSummary(
757        lldb.SBTypeNameSpecifier(
758            "mlirDataFormatters.is_op", lldb.eFormatterMatchCallback
759        ),
760        lldb.SBTypeSummary.CreateWithFunctionName(
761            "mlirDataFormatters.OperationSummaryProvider"
762        ),
763    )
764    cat.AddTypeSynthetic(
765        lldb.SBTypeNameSpecifier(
766            "mlirDataFormatters.is_op", lldb.eFormatterMatchCallback
767        ),
768        lldb.SBTypeSynthetic.CreateWithClassName(
769            "mlirDataFormatters.OperationSynthProvider"
770        ),
771    )
772
773    # Ranges
774    def add_direct_range_summary_and_synth(name):
775        cat.AddTypeSummary(
776            lldb.SBTypeNameSpecifier(name, lldb.eFormatterMatchExact),
777            lldb.SBTypeSummary.CreateWithSummaryString("size=${svar%#}"),
778        )
779        cat.AddTypeSynthetic(
780            lldb.SBTypeNameSpecifier(name, lldb.eFormatterMatchExact),
781            lldb.SBTypeSynthetic.CreateWithClassName(
782                "mlirDataFormatters.DirectRangeSynthProvider"
783            ),
784        )
785
786    def add_indirect_range_summary_and_synth(name):
787        cat.AddTypeSummary(
788            lldb.SBTypeNameSpecifier(name, lldb.eFormatterMatchExact),
789            lldb.SBTypeSummary.CreateWithSummaryString("size=${svar%#}"),
790        )
791        cat.AddTypeSynthetic(
792            lldb.SBTypeNameSpecifier(name, lldb.eFormatterMatchExact),
793            lldb.SBTypeSynthetic.CreateWithClassName(
794                "mlirDataFormatters.InDirectRangeSynthProvider"
795            ),
796        )
797
798    def add_iplist_range_summary_and_synth(name):
799        cat.AddTypeSummary(
800            lldb.SBTypeNameSpecifier(name, lldb.eFormatterMatchExact),
801            lldb.SBTypeSummary.CreateWithSummaryString("size=${svar%#}"),
802        )
803        cat.AddTypeSynthetic(
804            lldb.SBTypeNameSpecifier(name, lldb.eFormatterMatchExact),
805            lldb.SBTypeSynthetic.CreateWithClassName(
806                "mlirDataFormatters.IPListRangeSynthProvider"
807            ),
808        )
809
810    add_direct_range_summary_and_synth("mlir::Operation::operand_range")
811    add_direct_range_summary_and_synth("mlir::OperandRange")
812    add_direct_range_summary_and_synth("mlir::Operation::result_range")
813    add_direct_range_summary_and_synth("mlir::ResultRange")
814    add_direct_range_summary_and_synth("mlir::SuccessorRange")
815    add_indirect_range_summary_and_synth("mlir::ValueRange")
816    add_indirect_range_summary_and_synth("mlir::TypeRange")
817    add_iplist_range_summary_and_synth("mlir::Block::OpListType")
818    add_iplist_range_summary_and_synth("mlir::Region::BlockListType")
819
820    # Values
821    def add_value_summary_and_synth(name):
822        cat.AddTypeSummary(
823            lldb.SBTypeNameSpecifier(name, lldb.eFormatterMatchExact),
824            lldb.SBTypeSummary.CreateWithFunctionName(
825                "mlirDataFormatters.ValueSummaryProvider"
826            ),
827        )
828        cat.AddTypeSynthetic(
829            lldb.SBTypeNameSpecifier(name, lldb.eFormatterMatchExact),
830            lldb.SBTypeSynthetic.CreateWithClassName(
831                "mlirDataFormatters.ValueSynthProvider"
832            ),
833        )
834
835    add_value_summary_and_synth("mlir::BlockArgument")
836    add_value_summary_and_synth("mlir::Value")
837    add_value_summary_and_synth("mlir::OpResult")
838    add_value_summary_and_synth("mlir::detail::OpResultImpl")
839