"""GDB pretty printers for MLIR types.""" import gdb.printing class IdentifierPrinter: """Prints an mlir::Identifier instance.""" def __init__(self, val): self.entry = val['entry'] def to_string(self): ptr = (self.entry + 1).cast(gdb.lookup_type('char').pointer()) return ptr.string(length=self.entry['keyLength']) def display_hint(self): return 'string' class StoragePrinter: """Prints bases of a struct and its fields.""" def __init__(self, val): self.val = val def children(self): for field in self.val.type.fields(): if field.is_base_class: yield ('<%s>' % field.name, self.val.cast(field.type)) else: yield (field.name, self.val[field.name]) class TupleTypeStoragePrinter(StoragePrinter): def children(self): for child in StoragePrinter.children(self): yield child pointer_type = gdb.lookup_type('mlir::Type').pointer() elements = (self.val.address + 1).cast(pointer_type) for i in range(self.val['numElements']): yield 'elements[%u]' % i, elements[i] class RankedTypeStoragePrinter(StoragePrinter): def children(self): for child in StoragePrinter.children(self): yield child for i in range(self.val['shapeSize']): yield 'shapeElements[%u]' % i, self.val['shapeElements'][i] class MemRefTypeStoragePrinter(RankedTypeStoragePrinter): def children(self): for child in RankedTypeStoragePrinter.children(self): yield child for i in range(self.val['numAffineMaps']): yield 'affineMapsList[%u]' % i, self.val['affineMapsList'][i] class FusedLocationStoragePrinter(StoragePrinter): def children(self): for child in StoragePrinter.children(self): yield child pointer_type = gdb.lookup_type('mlir::Location').pointer() elements = (self.val.address + 1).cast(pointer_type) for i in range(self.val['numLocs']): yield 'locs[%u]' % i, elements[i] class StorageUserBasePrinter: """Printer for an mlir::detail::StorageUserBase instance.""" def __init__(self, val): self.val = val def children(self): storage_type = self.val.type.template_argument(2) yield 'impl', self.val['impl'].dereference().cast(storage_type) class StorageTypeMap: """Maps a TypeID to the corresponding type derived from StorageUserBase. Types need to be registered by name before the first lookup. """ def __init__(self): self.map = None self.type_names = [] def register_type(self, type_name): assert not self.map, 'register_type called after __getitem__' self.type_names += [type_name] def _init_map(self): """Lazy initialization of self.map.""" if self.map: return self.map = {} for type_name in self.type_names: concrete_type = gdb.lookup_type(type_name) try: storage = gdb.parse_and_eval( "&'mlir::detail::TypeIDExported::get<%s>()::instance'" % type_name) except gdb.error: # Skip when TypeID instance cannot be found in current context. continue if concrete_type and storage: self.map[int(storage)] = concrete_type def __getitem__(self, type_id): self._init_map() return self.map.get(int(type_id['storage'])) storage_type_map = StorageTypeMap() def get_type_id_printer(val): """Returns a printer of the name of a mlir::TypeID.""" class StringPrinter: def __init__(self, string): self.string = string def to_string(self): return self.string concrete_type = storage_type_map[val] if not concrete_type: return None return StringPrinter('"%s"' % concrete_type.name) def get_attr_or_type_printer(val, get_type_id): """Returns a printer for mlir::Attribute or mlir::Type.""" class UpcastPrinter: def __init__(self, val, type): self.val = val.cast(type) def children(self): yield 'cast<%s>' % self.val.type.name, self.val if not val['impl']: return None type_id = get_type_id(val['impl'].dereference()) concrete_type = storage_type_map[type_id] if not concrete_type: return None return UpcastPrinter(val, concrete_type) pp = gdb.printing.RegexpCollectionPrettyPrinter('MLIRSupport') pp.add_printer('mlir::Identifier', '^mlir::Identifier$', IdentifierPrinter) # Printers for types deriving from AttributeStorage or TypeStorage. pp.add_printer('mlir::detail::FusedLocationStorage', '^mlir::detail::FusedLocationStorage', FusedLocationStoragePrinter) pp.add_printer('mlir::detail::VectorTypeStorage', '^mlir::detail::VectorTypeStorage', RankedTypeStoragePrinter) pp.add_printer('mlir::detail::RankedTensorTypeStorage', '^mlir::detail::RankedTensorTypeStorage', RankedTypeStoragePrinter) pp.add_printer('mlir::detail::MemRefTypeStorage', '^mlir::detail::MemRefTypeStorage$', MemRefTypeStoragePrinter) pp.add_printer('mlir::detail::TupleTypeStorage', '^mlir::detail::TupleTypeStorage$', TupleTypeStoragePrinter) # Printers for Attribute::AttrBase or Type::TypeBase typedefs. pp.add_printer('mlir::detail::StorageUserBase', '^mlir::detail::StorageUserBase<.*>$', StorageUserBasePrinter) # Printers of types deriving from Attribute::AttrBase or Type::TypeBase. for name in [ # mlir/IR/Attributes.h 'ArrayAttr', 'DictionaryAttr', 'FloatAttr', 'IntegerAttr', 'IntegerSetAttr', 'OpaqueAttr', 'StringAttr', 'SymbolRefAttr', 'TypeAttr', 'UnitAttr', 'DenseStringElementsAttr', 'DenseIntOrFPElementsAttr', 'OpaqueElementsAttr', 'SparseElementsAttr', # mlir/IR/BuiltinTypes.h 'ComplexType', 'IndexType', 'IntegerType', 'Float16Type', 'Float32Type', 'Float64Type', 'NoneType', 'VectorType', 'RankedTensorType', 'UnrankedTensorType', 'MemRefType', 'UnrankedMemRefType', 'TupleType', # mlir/IR/Location.h 'CallSiteLoc', 'FileLineColLoc', 'FusedLoc', 'NameLoc', 'OpaqueLoc', 'UnknownLoc' ]: storage_type_map.register_type('mlir::%s' % name) # Register for upcasting. pp.add_printer('mlir::TypeID', '^mlir::TypeID$', get_type_id_printer) def add_attr_or_type_printers(name): """Adds printers for mlir::Attribute or mlir::Type and their Storage type.""" get_type_id = lambda val: val['abstract%s' % name]['typeID'] pp.add_printer('mlir::%s' % name, '^mlir::%s$' % name, lambda val: get_attr_or_type_printer(val, get_type_id)) pp.add_printer('mlir::%sStorage' % name, '^mlir::%sStorage$' % name, lambda val: get_type_id_printer(get_type_id(val))) # Upcasting printers of mlir::Attribute and mlir::Type. for name in ['Attribute', 'Type']: add_attr_or_type_printers(name) gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)