diff --git a/debuginfo-tests/llvm-prettyprinters/gdb/mlir-support.cpp b/debuginfo-tests/llvm-prettyprinters/gdb/mlir-support.cpp --- a/debuginfo-tests/llvm-prettyprinters/gdb/mlir-support.cpp +++ b/debuginfo-tests/llvm-prettyprinters/gdb/mlir-support.cpp @@ -1,8 +1,12 @@ #include "mlir/IR/Identifier.h" #include "mlir/IR/MLIRContext.h" +#include "mlir/IR/OperationSupport.h" mlir::MLIRContext Context; auto Identifier = mlir::Identifier::get("foo", &Context); +mlir::OperationName OperationName("FooOp", &Context); +mlir::Value Value({reinterpret_cast(0x8), + mlir::Value::Kind::TrailingOpResult}); int main() { return 0; } diff --git a/debuginfo-tests/llvm-prettyprinters/gdb/mlir-support.gdb b/debuginfo-tests/llvm-prettyprinters/gdb/mlir-support.gdb --- a/debuginfo-tests/llvm-prettyprinters/gdb/mlir-support.gdb +++ b/debuginfo-tests/llvm-prettyprinters/gdb/mlir-support.gdb @@ -6,3 +6,10 @@ # CHECK: "foo" p Identifier + +# CHECK: "FooOp" +p OperationName + +# CHECK: pointer = 0xa0, +# CHECK: value = mlir::Value::Kind::TrailingOpResult +p Value \ No newline at end of file diff --git a/mlir/utils/gdb-scripts/prettyprinters.py b/mlir/utils/gdb-scripts/prettyprinters.py --- a/mlir/utils/gdb-scripts/prettyprinters.py +++ b/mlir/utils/gdb-scripts/prettyprinters.py @@ -2,6 +2,7 @@ import gdb.printing + class IdentifierPrinter: """Prints an mlir::Identifier instance.""" @@ -9,14 +10,91 @@ self.entry = val['entry'] def to_string(self): - ptr = (self.entry + 1).cast(gdb.lookup_type('char').pointer()); + ptr = (self.entry + 1).cast(gdb.lookup_type('char').pointer()) return ptr.string(length=self.entry['keyLength']) def display_hint(self): return 'string' + +class StructPrinter: + """Prints bases of a struct and its fields. + + This mimics GDB's printing of instances without a custom printer. + """ + + 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 get_default_or_struct_printer(val): + """Returns gdb.default_visualizer(val) or StructPrinter(val). + + A printer factory which forwards to a single instance field may want to always + return a valid printer. Otherwise, GDB will print the instance as raw, + defeating the purpose of forwarding. This function returns a printer whether + a custom printer for 'val' has been registered or not. + """ + default_printer = gdb.default_visualizer(val) + if default_printer: + return default_printer + # No custom printer available for val, fall back to StructPrinter. + return StructPrinter(val) + + +def get_operation_name_printer(val): + """Returns printer for an mlir::OperationName instance.""" + rep_printer = gdb.default_visualizer(val['representation']) + if not rep_printer: + return None # If the PointerUnion couldn't be analyzed, print as raw value. + pointer = rep_printer.pointer + if pointer.type.code == gdb.TYPE_CODE_PTR and pointer: + pointer = pointer.dereference() + return get_default_or_struct_printer(pointer) + + +def get_first_member_printer(val): + """Returns printer for the first member of val.""" + for field in val.type.fields(): + if not field.is_base_class: + field = val[field.name] + if field.type.code == gdb.TYPE_CODE_PTR and field: + field = field.dereference() + return get_default_or_struct_printer(field) + return None + + +def get_first_base_printer(val): + """Returns printer for the first base class of val.""" + for field in val.type.fields(): + if field.is_base_class and field.type: + return get_default_or_struct_printer(val.cast(field.type)) + return None + + pp = gdb.printing.RegexpCollectionPrettyPrinter('MLIRSupport') pp.add_printer('mlir::Identifier', '^mlir::Identifier$', IdentifierPrinter) +pp.add_printer('mlir::OperationName', '^mlir::OperationName$', + get_operation_name_printer) + +# Printers forwarding to single relevant member. +for name in ['Location', 'Value']: + pp.add_printer('mlir::%s' % name, '^mlir::%s$' % name, + get_first_member_printer) + +# Printers forwarding to the single relevant base class. +for name in [ + 'BoolAttr', 'LocationAttr', 'ElementsAttr', 'BaseMemRefType', 'FloatType', + 'ShapedType', 'TensorType' +]: + pp.add_printer('mlir::%s' % name, '^mlir::%s$' % name, get_first_base_printer) gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)