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