| """GDB pretty printers for MLIR types.""" | |
| import gdb.printing | |
| 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] | |
| def to_string(self): | |
| return "mlir::Storage" | |
| 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] | |
| def to_string(self): | |
| return "mlir::TupleTypeStorage of %u elements" % self.val["numElements"] | |
| 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] | |
| def to_string(self): | |
| return "mlir::FusedLocationStorage of %u locs" % self.val["numLocs"] | |
| class StorageTypeMap: | |
| """Maps a TypeID to the corresponding concrete type. | |
| 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 TypeIdPrinter: | |
| 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 TypeIdPrinter("mlir::TypeID::get<%s>()" % concrete_type) | |
| def get_attr_or_type_printer(val, get_type_id): | |
| """Returns a printer for mlir::Attribute or mlir::Type.""" | |
| class AttrOrTypePrinter: | |
| def __init__(self, type_id, impl): | |
| self.type_id = type_id | |
| self.impl = impl | |
| def children(self): | |
| yield "typeID", self.type_id | |
| yield "impl", self.impl | |
| def to_string(self): | |
| return "cast<%s>" % self.impl.type | |
| if not val["impl"]: | |
| return None | |
| impl = val["impl"].dereference() | |
| type_id = get_type_id(impl) | |
| concrete_type = storage_type_map[type_id] | |
| if not concrete_type: | |
| return None | |
| # 3rd template argument of StorageUserBase is the storage type. | |
| storage_type = concrete_type.fields()[0].type.template_argument(2) | |
| if not storage_type: | |
| return None | |
| return AttrOrTypePrinter(type_id, impl.cast(storage_type)) | |
| class ImplPrinter: | |
| """Printer for an instance with a single 'impl' member pointer.""" | |
| def __init__(self, val): | |
| self.val = val | |
| self.impl = val["impl"] | |
| def children(self): | |
| if self.impl: | |
| yield "impl", self.impl.dereference() | |
| def to_string(self): | |
| return self.val.type.name | |
| # 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", | |
| "DenseTypedElementsAttr", | |
| "SparseElementsAttr", | |
| # mlir/IR/BuiltinTypes.h | |
| "ComplexType", | |
| "IndexType", | |
| "IntegerType", | |
| "Float16Type", | |
| "FloatTF32Type", | |
| "Float32Type", | |
| "Float64Type", | |
| "Float80Type", | |
| "Float128Type", | |
| "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. | |
| storage_type_map.register_type("void") # Register default. | |
| pp = gdb.printing.RegexpCollectionPrettyPrinter("MLIRSupport") | |
| pp.add_printer("mlir::OperationName", "^mlir::OperationName$", ImplPrinter) | |
| pp.add_printer("mlir::Value", "^mlir::Value$", ImplPrinter) | |
| # Printers for types deriving from AttributeStorage or TypeStorage. | |
| pp.add_printer( | |
| "mlir::detail::FusedLocationStorage", | |
| "^mlir::detail::FusedLocationStorage", | |
| FusedLocationStoragePrinter, | |
| ) | |
| pp.add_printer( | |
| "mlir::detail::TupleTypeStorage", | |
| "^mlir::detail::TupleTypeStorage$", | |
| TupleTypeStoragePrinter, | |
| ) | |
| 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), | |
| ) | |
| # 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) |