| """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", |
| "DenseIntOrFPElementsAttr", |
| "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) |